realtek: implement get_stats64

By default, the network interface stats are based on software counters,
which only consider traffic from and to the CPU. Implementing the
get_stats64 method allows to report the full hardware counters instead.

Signed-off-by: Jan Hoffmann <jan@3e8.eu>
Link: https://github.com/openwrt/openwrt/pull/18415
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Jan Hoffmann
2025-04-25 20:18:52 +02:00
committed by Hauke Mehrtens
parent e27e695978
commit fa63a5365e
2 changed files with 63 additions and 0 deletions

View File

@@ -79,6 +79,7 @@ const struct rtldsa_mib_desc rtldsa_838x_mib = {
.if_out_ucast_pkts = MIB_ITEM(MIB_REG_STD, 0xdc, 1),
.if_out_mcast_pkts = MIB_ITEM(MIB_REG_STD, 0xd8, 1),
.if_out_bcast_pkts = MIB_ITEM(MIB_REG_STD, 0xd4, 1),
.if_out_discards = MIB_ITEM(MIB_REG_STD, 0xd0, 1),
.single_collisions = MIB_ITEM(MIB_REG_STD, 0xcc, 1),
.multiple_collisions = MIB_ITEM(MIB_REG_STD, 0xc8, 1),
.deferred_transmissions = MIB_ITEM(MIB_REG_STD, 0xc4, 1),
@@ -121,6 +122,9 @@ const struct rtldsa_mib_desc rtldsa_838x_mib = {
{ 1519, 10000 }
},
.drop_events = MIB_ITEM(MIB_REG_STD, 0xa8, 1),
.collisions = MIB_ITEM(MIB_REG_STD, 0x7c, 1),
.rx_pause_frames = MIB_ITEM(MIB_REG_STD, 0xb0, 1),
.tx_pause_frames = MIB_ITEM(MIB_REG_STD, 0xac, 1),
@@ -159,6 +163,7 @@ const struct rtldsa_mib_desc rtldsa_839x_mib = {
.if_out_ucast_pkts = MIB_ITEM(MIB_REG_STD, 0xe0, 1),
.if_out_mcast_pkts = MIB_ITEM(MIB_REG_STD, 0xdc, 1),
.if_out_bcast_pkts = MIB_ITEM(MIB_REG_STD, 0xd8, 1),
.if_out_discards = MIB_ITEM(MIB_REG_STD, 0xd4, 1),
.single_collisions = MIB_ITEM(MIB_REG_STD, 0xcc, 1),
.multiple_collisions = MIB_ITEM(MIB_REG_STD, 0xc8, 1),
.deferred_transmissions = MIB_ITEM(MIB_REG_STD, 0xc4, 1),
@@ -201,6 +206,9 @@ const struct rtldsa_mib_desc rtldsa_839x_mib = {
{ 1519, 12288 }
},
.drop_events = MIB_ITEM(MIB_REG_STD, 0xa8, 1),
.collisions = MIB_ITEM(MIB_REG_STD, 0x7c, 1),
.rx_pause_frames = MIB_ITEM(MIB_REG_STD, 0xb0, 1),
.tx_pause_frames = MIB_ITEM(MIB_REG_STD, 0xac, 1),
@@ -249,6 +257,7 @@ const struct rtldsa_mib_desc rtldsa_930x_mib = {
.if_out_ucast_pkts = MIB_ITEM(MIB_REG_STD, 0xd0, 2),
.if_out_mcast_pkts = MIB_ITEM(MIB_REG_STD, 0xc8, 2),
.if_out_bcast_pkts = MIB_ITEM(MIB_REG_STD, 0xc0, 2),
.if_out_discards = MIB_ITEM(MIB_REG_STD, 0xbc, 1),
.single_collisions = MIB_ITEM(MIB_REG_STD, 0xb4, 1),
.multiple_collisions = MIB_ITEM(MIB_REG_STD, 0xb0, 1),
.deferred_transmissions = MIB_ITEM(MIB_REG_STD, 0xac, 1),
@@ -294,6 +303,9 @@ const struct rtldsa_mib_desc rtldsa_930x_mib = {
{ 12289, 65535 }
},
.drop_events = MIB_ITEM(MIB_REG_STD, 0x90, 1),
.collisions = MIB_ITEM(MIB_REG_STD, 0x5c, 1),
.rx_pause_frames = MIB_ITEM(MIB_REG_STD, 0x98, 1),
.tx_pause_frames = MIB_ITEM(MIB_REG_STD, 0x94, 1),
@@ -1279,6 +1291,51 @@ static void rtldsa_get_rmon_stats(struct dsa_switch *ds, int port,
*ranges = mib_desc->rmon_ranges;
}
static void rtldsa_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *s)
{
struct rtl838x_switch_priv *priv = ds->priv;
const struct rtldsa_mib_desc *mib_desc;
uint64_t val;
if (port < 0 || port >= priv->cpu_port)
return;
mib_desc = rtldsa_get_mib_desc(priv);
if (!mib_desc) {
dev_get_tstats64(dsa_to_port(ds, port)->user, s);
return;
}
rtldsa_read_mib_item(priv, port, &mib_desc->if_in_ucast_pkts, &s->rx_packets);
if (rtldsa_read_mib_item(priv, port, &mib_desc->if_in_mcast_pkts, &s->multicast))
s->rx_packets += s->multicast;
if (rtldsa_read_mib_item(priv, port, &mib_desc->if_in_bcast_pkts, &val))
s->rx_packets += val;
rtldsa_read_mib_item(priv, port, &mib_desc->if_out_ucast_pkts, &s->tx_packets);
if (rtldsa_read_mib_item(priv, port, &mib_desc->if_out_mcast_pkts, &val))
s->tx_packets += val;
if (rtldsa_read_mib_item(priv, port, &mib_desc->if_out_bcast_pkts, &val))
s->tx_packets += val;
/* Ideally, we should subtract the FCS for each packet here */
rtldsa_read_mib_item(priv, port, &mib_desc->if_in_octets, &s->rx_bytes);
rtldsa_read_mib_item(priv, port, &mib_desc->if_out_octets, &s->tx_bytes);
rtldsa_read_mib_item(priv, port, &mib_desc->collisions, &s->collisions);
rtldsa_read_mib_item(priv, port, &mib_desc->drop_events, &s->rx_dropped);
rtldsa_read_mib_item(priv, port, &mib_desc->if_out_discards, &s->tx_dropped);
rtldsa_read_mib_item(priv, port, &mib_desc->crc_align_errors, &s->rx_crc_errors);
s->rx_errors = s->rx_crc_errors;
rtldsa_read_mib_item(priv, port, &mib_desc->excessive_collisions, &s->tx_aborted_errors);
rtldsa_read_mib_item(priv, port, &mib_desc->late_collisions, &s->tx_window_errors);
s->tx_errors = s->tx_aborted_errors + s->tx_window_errors;
}
static void rtldsa_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats)
{
@@ -2501,6 +2558,7 @@ const struct dsa_switch_ops rtl83xx_switch_ops = {
.get_eth_mac_stats = rtldsa_get_eth_mac_stats,
.get_eth_ctrl_stats = rtldsa_get_eth_ctrl_stats,
.get_rmon_stats = rtldsa_get_rmon_stats,
.get_stats64 = rtldsa_get_stats64,
.get_pause_stats = rtldsa_get_pause_stats,
.port_enable = rtl83xx_port_enable,
@@ -2563,6 +2621,7 @@ const struct dsa_switch_ops rtl930x_switch_ops = {
.get_eth_mac_stats = rtldsa_get_eth_mac_stats,
.get_eth_ctrl_stats = rtldsa_get_eth_ctrl_stats,
.get_rmon_stats = rtldsa_get_rmon_stats,
.get_stats64 = rtldsa_get_stats64,
.get_pause_stats = rtldsa_get_pause_stats,
.port_enable = rtl83xx_port_enable,

View File

@@ -51,6 +51,7 @@ struct rtldsa_mib_desc {
struct rtldsa_mib_item if_out_ucast_pkts;
struct rtldsa_mib_item if_out_mcast_pkts;
struct rtldsa_mib_item if_out_bcast_pkts;
struct rtldsa_mib_item if_out_discards;
struct rtldsa_mib_item single_collisions;
struct rtldsa_mib_item multiple_collisions;
struct rtldsa_mib_item deferred_transmissions;
@@ -69,6 +70,9 @@ struct rtldsa_mib_desc {
struct rtldsa_mib_item rx_pkts[ETHTOOL_RMON_HIST_MAX];
struct ethtool_rmon_hist_range rmon_ranges[ETHTOOL_RMON_HIST_MAX];
struct rtldsa_mib_item drop_events;
struct rtldsa_mib_item collisions;
struct rtldsa_mib_item rx_pause_frames;
struct rtldsa_mib_item tx_pause_frames;