diff options
author | Heiner Kallweit <hkallweit1@gmail.com> | 2020-10-12 10:01:27 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-10-13 17:33:48 -0700 |
commit | 44fa32f008ab7092842095a7a474c48303a2f186 (patch) | |
tree | 2da344027227688188027dc5516bdc7b2510e2f8 /net/core | |
parent | 3618ad2a7c0e78e4258386394d5d5f92a3dbccf8 (diff) | |
download | linux-44fa32f008ab7092842095a7a474c48303a2f186.tar.gz linux-44fa32f008ab7092842095a7a474c48303a2f186.tar.bz2 linux-44fa32f008ab7092842095a7a474c48303a2f186.zip |
net: add function dev_fetch_sw_netstats for fetching pcpu_sw_netstats
In several places the same code is used to populate rtnl_link_stats64
fields with data from pcpu_sw_netstats. Therefore factor out this code
to a new function dev_fetch_sw_netstats().
v2:
- constify argument netstats
- don't ignore netstats being NULL or an ERRPTR
- switch to EXPORT_SYMBOL_GPL
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Link: https://lore.kernel.org/r/6d16a338-52f5-df69-0020-6bc771a7d498@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 22babf5bcc88..751e5264fd49 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10328,6 +10328,40 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, } EXPORT_SYMBOL(dev_get_stats); +/** + * dev_fetch_sw_netstats - get per-cpu network device statistics + * @s: place to store stats + * @netstats: per-cpu network stats to read from + * + * Read per-cpu network statistics and populate the related fields in @s. + */ +void dev_fetch_sw_netstats(struct rtnl_link_stats64 *s, + const struct pcpu_sw_netstats __percpu *netstats) +{ + int cpu; + + for_each_possible_cpu(cpu) { + const struct pcpu_sw_netstats *stats; + struct pcpu_sw_netstats tmp; + unsigned int start; + + stats = per_cpu_ptr(netstats, cpu); + do { + start = u64_stats_fetch_begin_irq(&stats->syncp); + tmp.rx_packets = stats->rx_packets; + tmp.rx_bytes = stats->rx_bytes; + tmp.tx_packets = stats->tx_packets; + tmp.tx_bytes = stats->tx_bytes; + } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); + + s->rx_packets += tmp.rx_packets; + s->rx_bytes += tmp.rx_bytes; + s->tx_packets += tmp.tx_packets; + s->tx_bytes += tmp.tx_bytes; + } +} +EXPORT_SYMBOL_GPL(dev_fetch_sw_netstats); + struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) { struct netdev_queue *queue = dev_ingress_queue(dev); |