Skip to content

Commit bfc6507

Browse files
committed
Merge branch 'net-core-unify-dstats-with-tstats-and-lstats-implement-generic-dstats-collection'
Jeremy Kerr says: ==================== net: core: Unify dstats with tstats and lstats, implement generic dstats collection The struct pcpu_dstats ("dstats") has a few variations from the other two stats types (struct pcpu_sw_netstats and struct pcpu_lstats), and doesn't have generic helpers for collecting the per-cpu stats into a struct rtnl_link_stats64. This change unifies dstats with the other types, adds a collection implementation to the core, and updates the single driver (vrf) to use this generic implementation. Of course, questions/comments/etc are most welcome! v3: https://lore.kernel.org/r/[email protected] v2: v1: https://lore.kernel.org/r/[email protected] ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 45403b1 + 2202576 commit bfc6507

File tree

3 files changed

+73
-45
lines changed

3 files changed

+73
-45
lines changed

drivers/net/vrf.c

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ static void vrf_rx_stats(struct net_device *dev, int len)
126126
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
127127

128128
u64_stats_update_begin(&dstats->syncp);
129-
dstats->rx_packets++;
130-
dstats->rx_bytes += len;
129+
u64_stats_inc(&dstats->rx_packets);
130+
u64_stats_add(&dstats->rx_bytes, len);
131131
u64_stats_update_end(&dstats->syncp);
132132
}
133133

@@ -137,33 +137,6 @@ static void vrf_tx_error(struct net_device *vrf_dev, struct sk_buff *skb)
137137
kfree_skb(skb);
138138
}
139139

140-
static void vrf_get_stats64(struct net_device *dev,
141-
struct rtnl_link_stats64 *stats)
142-
{
143-
int i;
144-
145-
for_each_possible_cpu(i) {
146-
const struct pcpu_dstats *dstats;
147-
u64 tbytes, tpkts, tdrops, rbytes, rpkts;
148-
unsigned int start;
149-
150-
dstats = per_cpu_ptr(dev->dstats, i);
151-
do {
152-
start = u64_stats_fetch_begin(&dstats->syncp);
153-
tbytes = dstats->tx_bytes;
154-
tpkts = dstats->tx_packets;
155-
tdrops = dstats->tx_drops;
156-
rbytes = dstats->rx_bytes;
157-
rpkts = dstats->rx_packets;
158-
} while (u64_stats_fetch_retry(&dstats->syncp, start));
159-
stats->tx_bytes += tbytes;
160-
stats->tx_packets += tpkts;
161-
stats->tx_dropped += tdrops;
162-
stats->rx_bytes += rbytes;
163-
stats->rx_packets += rpkts;
164-
}
165-
}
166-
167140
static struct vrf_map *netns_vrf_map(struct net *net)
168141
{
169142
struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
@@ -408,10 +381,15 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
408381

409382
skb->protocol = eth_type_trans(skb, dev);
410383

411-
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
384+
if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {
412385
vrf_rx_stats(dev, len);
413-
else
414-
this_cpu_inc(dev->dstats->rx_drops);
386+
} else {
387+
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
388+
389+
u64_stats_update_begin(&dstats->syncp);
390+
u64_stats_inc(&dstats->rx_drops);
391+
u64_stats_update_end(&dstats->syncp);
392+
}
415393

416394
return NETDEV_TX_OK;
417395
}
@@ -599,19 +577,20 @@ static netdev_tx_t is_ip_tx_frame(struct sk_buff *skb, struct net_device *dev)
599577

600578
static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
601579
{
580+
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
581+
602582
int len = skb->len;
603583
netdev_tx_t ret = is_ip_tx_frame(skb, dev);
604584

585+
u64_stats_update_begin(&dstats->syncp);
605586
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
606-
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
607587

608-
u64_stats_update_begin(&dstats->syncp);
609-
dstats->tx_packets++;
610-
dstats->tx_bytes += len;
611-
u64_stats_update_end(&dstats->syncp);
588+
u64_stats_inc(&dstats->tx_packets);
589+
u64_stats_add(&dstats->tx_bytes, len);
612590
} else {
613-
this_cpu_inc(dev->dstats->tx_drops);
591+
u64_stats_inc(&dstats->tx_drops);
614592
}
593+
u64_stats_update_end(&dstats->syncp);
615594

616595
return ret;
617596
}
@@ -1195,7 +1174,6 @@ static const struct net_device_ops vrf_netdev_ops = {
11951174
.ndo_uninit = vrf_dev_uninit,
11961175
.ndo_start_xmit = vrf_xmit,
11971176
.ndo_set_mac_address = eth_mac_addr,
1198-
.ndo_get_stats64 = vrf_get_stats64,
11991177
.ndo_add_slave = vrf_add_slave,
12001178
.ndo_del_slave = vrf_del_slave,
12011179
};

include/linux/netdevice.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,12 +2731,12 @@ struct pcpu_sw_netstats {
27312731
} __aligned(4 * sizeof(u64));
27322732

27332733
struct pcpu_dstats {
2734-
u64 rx_packets;
2735-
u64 rx_bytes;
2736-
u64 rx_drops;
2737-
u64 tx_packets;
2738-
u64 tx_bytes;
2739-
u64 tx_drops;
2734+
u64_stats_t rx_packets;
2735+
u64_stats_t rx_bytes;
2736+
u64_stats_t rx_drops;
2737+
u64_stats_t tx_packets;
2738+
u64_stats_t tx_bytes;
2739+
u64_stats_t tx_drops;
27402740
struct u64_stats_sync syncp;
27412741
} __aligned(8 * sizeof(u64));
27422742

net/core/dev.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10703,6 +10703,54 @@ void netdev_run_todo(void)
1070310703
wake_up(&netdev_unregistering_wq);
1070410704
}
1070510705

10706+
/* Collate per-cpu network dstats statistics
10707+
*
10708+
* Read per-cpu network statistics from dev->dstats and populate the related
10709+
* fields in @s.
10710+
*/
10711+
static void dev_fetch_dstats(struct rtnl_link_stats64 *s,
10712+
const struct pcpu_dstats __percpu *dstats)
10713+
{
10714+
int cpu;
10715+
10716+
for_each_possible_cpu(cpu) {
10717+
u64 rx_packets, rx_bytes, rx_drops;
10718+
u64 tx_packets, tx_bytes, tx_drops;
10719+
const struct pcpu_dstats *stats;
10720+
unsigned int start;
10721+
10722+
stats = per_cpu_ptr(dstats, cpu);
10723+
do {
10724+
start = u64_stats_fetch_begin(&stats->syncp);
10725+
rx_packets = u64_stats_read(&stats->rx_packets);
10726+
rx_bytes = u64_stats_read(&stats->rx_bytes);
10727+
rx_drops = u64_stats_read(&stats->rx_drops);
10728+
tx_packets = u64_stats_read(&stats->tx_packets);
10729+
tx_bytes = u64_stats_read(&stats->tx_bytes);
10730+
tx_drops = u64_stats_read(&stats->tx_drops);
10731+
} while (u64_stats_fetch_retry(&stats->syncp, start));
10732+
10733+
s->rx_packets += rx_packets;
10734+
s->rx_bytes += rx_bytes;
10735+
s->rx_dropped += rx_drops;
10736+
s->tx_packets += tx_packets;
10737+
s->tx_bytes += tx_bytes;
10738+
s->tx_dropped += tx_drops;
10739+
}
10740+
}
10741+
10742+
/* ndo_get_stats64 implementation for dtstats-based accounting.
10743+
*
10744+
* Populate @s from dev->stats and dev->dstats. This is used internally by the
10745+
* core for NETDEV_PCPU_STAT_DSTAT-type stats collection.
10746+
*/
10747+
static void dev_get_dstats64(const struct net_device *dev,
10748+
struct rtnl_link_stats64 *s)
10749+
{
10750+
netdev_stats_to_stats64(s, &dev->stats);
10751+
dev_fetch_dstats(s, dev->dstats);
10752+
}
10753+
1070610754
/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has
1070710755
* all the same fields in the same order as net_device_stats, with only
1070810756
* 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,
1077910827
netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev));
1078010828
} else if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS) {
1078110829
dev_get_tstats64(dev, storage);
10830+
} else if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) {
10831+
dev_get_dstats64(dev, storage);
1078210832
} else {
1078310833
netdev_stats_to_stats64(storage, &dev->stats);
1078410834
}

0 commit comments

Comments
 (0)