net: core: Implement dstats-type stats collections
We currently have dev_get_tstats64() for collecting per-cpu stats of type pcpu_sw_netstats ("tstats"). However, tstats doesn't allow for accounting tx/rx drops. We do have a stats variant that does have stats for dropped packets: struct pcpu_dstats, but there are no core helpers for using those stats. The VRF driver uses dstats, by providing its own collation/fetch functions to do so. This change adds a common implementation for dstats-type collection, used when pcpu_stat_type == NETDEV_PCPU_STAT_DSTAT. This is based on the VRF driver's existing stats collator (plus the unused tx_drops stat from there). We will switch the VRF driver to use this in the next change. Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au> Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://lore.kernel.org/r/20240607-dstats-v3-2-cc781fe116f7@codeconstruct.com.au Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
fa59dc2f6f
commit
94b601bc4f
@ -10703,6 +10703,54 @@ void netdev_run_todo(void)
|
||||
wake_up(&netdev_unregistering_wq);
|
||||
}
|
||||
|
||||
/* Collate per-cpu network dstats statistics
|
||||
*
|
||||
* Read per-cpu network statistics from dev->dstats and populate the related
|
||||
* fields in @s.
|
||||
*/
|
||||
static void dev_fetch_dstats(struct rtnl_link_stats64 *s,
|
||||
const struct pcpu_dstats __percpu *dstats)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
u64 rx_packets, rx_bytes, rx_drops;
|
||||
u64 tx_packets, tx_bytes, tx_drops;
|
||||
const struct pcpu_dstats *stats;
|
||||
unsigned int start;
|
||||
|
||||
stats = per_cpu_ptr(dstats, cpu);
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&stats->syncp);
|
||||
rx_packets = u64_stats_read(&stats->rx_packets);
|
||||
rx_bytes = u64_stats_read(&stats->rx_bytes);
|
||||
rx_drops = u64_stats_read(&stats->rx_drops);
|
||||
tx_packets = u64_stats_read(&stats->tx_packets);
|
||||
tx_bytes = u64_stats_read(&stats->tx_bytes);
|
||||
tx_drops = u64_stats_read(&stats->tx_drops);
|
||||
} while (u64_stats_fetch_retry(&stats->syncp, start));
|
||||
|
||||
s->rx_packets += rx_packets;
|
||||
s->rx_bytes += rx_bytes;
|
||||
s->rx_dropped += rx_drops;
|
||||
s->tx_packets += tx_packets;
|
||||
s->tx_bytes += tx_bytes;
|
||||
s->tx_dropped += tx_drops;
|
||||
}
|
||||
}
|
||||
|
||||
/* ndo_get_stats64 implementation for dtstats-based accounting.
|
||||
*
|
||||
* Populate @s from dev->stats and dev->dstats. This is used internally by the
|
||||
* core for NETDEV_PCPU_STAT_DSTAT-type stats collection.
|
||||
*/
|
||||
static void dev_get_dstats64(const struct net_device *dev,
|
||||
struct rtnl_link_stats64 *s)
|
||||
{
|
||||
netdev_stats_to_stats64(s, &dev->stats);
|
||||
dev_fetch_dstats(s, dev->dstats);
|
||||
}
|
||||
|
||||
/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has
|
||||
* all the same fields in the same order as net_device_stats, with only
|
||||
* the type differing, but rtnl_link_stats64 may have additional fields
|
||||
@ -10779,6 +10827,8 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
|
||||
netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev));
|
||||
} else if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS) {
|
||||
dev_get_tstats64(dev, storage);
|
||||
} else if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) {
|
||||
dev_get_dstats64(dev, storage);
|
||||
} else {
|
||||
netdev_stats_to_stats64(storage, &dev->stats);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user