Skip to content

Commit 877c81f

Browse files
borkmanngregkh
authored andcommitted
net: Move {l,t,d}stats allocation to core and convert veth & vrf
[ Upstream commit 34d21de99cea9cb17967874313e5b0262527833c ] Move {l,t,d}stats allocation to the core and let netdevs pick the stats type they need. That way the driver doesn't have to bother with error handling (allocation failure checking, making sure free happens in the right spot, etc) - all happening in the core. Co-developed-by: Jakub Kicinski <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Nikolay Aleksandrov <[email protected]> Cc: David Ahern <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]> Stable-dep-of: 024ee930cb3c ("bpf: Fix dev's rx stats for bpf_redirect_peer traffic") [ Note: Simplified vrf bits to reduce patch given unrelated to the fix ] Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 988e55a commit 877c81f

File tree

4 files changed

+85
-38
lines changed

4 files changed

+85
-38
lines changed

drivers/net/veth.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,25 +1381,12 @@ static void veth_free_queues(struct net_device *dev)
13811381

13821382
static int veth_dev_init(struct net_device *dev)
13831383
{
1384-
int err;
1385-
1386-
dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
1387-
if (!dev->lstats)
1388-
return -ENOMEM;
1389-
1390-
err = veth_alloc_queues(dev);
1391-
if (err) {
1392-
free_percpu(dev->lstats);
1393-
return err;
1394-
}
1395-
1396-
return 0;
1384+
return veth_alloc_queues(dev);
13971385
}
13981386

13991387
static void veth_dev_free(struct net_device *dev)
14001388
{
14011389
veth_free_queues(dev);
1402-
free_percpu(dev->lstats);
14031390
}
14041391

14051392
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1625,6 +1612,7 @@ static void veth_setup(struct net_device *dev)
16251612
NETIF_F_HW_VLAN_STAG_RX);
16261613
dev->needs_free_netdev = true;
16271614
dev->priv_destructor = veth_dev_free;
1615+
dev->pcpu_stat_type = NETDEV_PCPU_STAT_LSTATS;
16281616
dev->max_mtu = ETH_MAX_MTU;
16291617

16301618
dev->hw_features = VETH_FEATURES;

drivers/net/vrf.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,12 @@ struct net_vrf {
121121
int ifindex;
122122
};
123123

124-
struct pcpu_dstats {
125-
u64 tx_pkts;
126-
u64 tx_bytes;
127-
u64 tx_drps;
128-
u64 rx_pkts;
129-
u64 rx_bytes;
130-
u64 rx_drps;
131-
struct u64_stats_sync syncp;
132-
};
133-
134124
static void vrf_rx_stats(struct net_device *dev, int len)
135125
{
136126
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
137127

138128
u64_stats_update_begin(&dstats->syncp);
139-
dstats->rx_pkts++;
129+
dstats->rx_packets++;
140130
dstats->rx_bytes += len;
141131
u64_stats_update_end(&dstats->syncp);
142132
}
@@ -161,10 +151,10 @@ static void vrf_get_stats64(struct net_device *dev,
161151
do {
162152
start = u64_stats_fetch_begin_irq(&dstats->syncp);
163153
tbytes = dstats->tx_bytes;
164-
tpkts = dstats->tx_pkts;
165-
tdrops = dstats->tx_drps;
154+
tpkts = dstats->tx_packets;
155+
tdrops = dstats->tx_drops;
166156
rbytes = dstats->rx_bytes;
167-
rpkts = dstats->rx_pkts;
157+
rpkts = dstats->rx_packets;
168158
} while (u64_stats_fetch_retry_irq(&dstats->syncp, start));
169159
stats->tx_bytes += tbytes;
170160
stats->tx_packets += tpkts;
@@ -421,7 +411,7 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
421411
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
422412
vrf_rx_stats(dev, len);
423413
else
424-
this_cpu_inc(dev->dstats->rx_drps);
414+
this_cpu_inc(dev->dstats->rx_drops);
425415

426416
return NETDEV_TX_OK;
427417
}
@@ -616,11 +606,11 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
616606
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
617607

618608
u64_stats_update_begin(&dstats->syncp);
619-
dstats->tx_pkts++;
609+
dstats->tx_packets++;
620610
dstats->tx_bytes += len;
621611
u64_stats_update_end(&dstats->syncp);
622612
} else {
623-
this_cpu_inc(dev->dstats->tx_drps);
613+
this_cpu_inc(dev->dstats->tx_drops);
624614
}
625615

626616
return ret;

include/linux/netdevice.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,13 @@ enum netdev_ml_priv_type {
17471747
ML_PRIV_CAN,
17481748
};
17491749

1750+
enum netdev_stat_type {
1751+
NETDEV_PCPU_STAT_NONE,
1752+
NETDEV_PCPU_STAT_LSTATS, /* struct pcpu_lstats */
1753+
NETDEV_PCPU_STAT_TSTATS, /* struct pcpu_sw_netstats */
1754+
NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */
1755+
};
1756+
17501757
/**
17511758
* struct net_device - The DEVICE structure.
17521759
*
@@ -1941,10 +1948,14 @@ enum netdev_ml_priv_type {
19411948
*
19421949
* @ml_priv: Mid-layer private
19431950
* @ml_priv_type: Mid-layer private type
1944-
* @lstats: Loopback statistics
1945-
* @tstats: Tunnel statistics
1946-
* @dstats: Dummy statistics
1947-
* @vstats: Virtual ethernet statistics
1951+
*
1952+
* @pcpu_stat_type: Type of device statistics which the core should
1953+
* allocate/free: none, lstats, tstats, dstats. none
1954+
* means the driver is handling statistics allocation/
1955+
* freeing internally.
1956+
* @lstats: Loopback statistics: packets, bytes
1957+
* @tstats: Tunnel statistics: RX/TX packets, RX/TX bytes
1958+
* @dstats: Dummy statistics: RX/TX/drop packets, RX/TX bytes
19481959
*
19491960
* @garp_port: GARP
19501961
* @mrp_port: MRP
@@ -2287,6 +2298,7 @@ struct net_device {
22872298
void *ml_priv;
22882299
enum netdev_ml_priv_type ml_priv_type;
22892300

2301+
enum netdev_stat_type pcpu_stat_type:8;
22902302
union {
22912303
struct pcpu_lstats __percpu *lstats;
22922304
struct pcpu_sw_netstats __percpu *tstats;
@@ -2670,6 +2682,16 @@ struct pcpu_sw_netstats {
26702682
struct u64_stats_sync syncp;
26712683
} __aligned(4 * sizeof(u64));
26722684

2685+
struct pcpu_dstats {
2686+
u64 rx_packets;
2687+
u64 rx_bytes;
2688+
u64 rx_drops;
2689+
u64 tx_packets;
2690+
u64 tx_bytes;
2691+
u64 tx_drops;
2692+
struct u64_stats_sync syncp;
2693+
} __aligned(8 * sizeof(u64));
2694+
26732695
struct pcpu_lstats {
26742696
u64_stats_t packets;
26752697
u64_stats_t bytes;

net/core/dev.c

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9991,6 +9991,46 @@ void netif_tx_stop_all_queues(struct net_device *dev)
99919991
}
99929992
EXPORT_SYMBOL(netif_tx_stop_all_queues);
99939993

9994+
static int netdev_do_alloc_pcpu_stats(struct net_device *dev)
9995+
{
9996+
void __percpu *v;
9997+
9998+
switch (dev->pcpu_stat_type) {
9999+
case NETDEV_PCPU_STAT_NONE:
10000+
return 0;
10001+
case NETDEV_PCPU_STAT_LSTATS:
10002+
v = dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
10003+
break;
10004+
case NETDEV_PCPU_STAT_TSTATS:
10005+
v = dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
10006+
break;
10007+
case NETDEV_PCPU_STAT_DSTATS:
10008+
v = dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
10009+
break;
10010+
default:
10011+
return -EINVAL;
10012+
}
10013+
10014+
return v ? 0 : -ENOMEM;
10015+
}
10016+
10017+
static void netdev_do_free_pcpu_stats(struct net_device *dev)
10018+
{
10019+
switch (dev->pcpu_stat_type) {
10020+
case NETDEV_PCPU_STAT_NONE:
10021+
return;
10022+
case NETDEV_PCPU_STAT_LSTATS:
10023+
free_percpu(dev->lstats);
10024+
break;
10025+
case NETDEV_PCPU_STAT_TSTATS:
10026+
free_percpu(dev->tstats);
10027+
break;
10028+
case NETDEV_PCPU_STAT_DSTATS:
10029+
free_percpu(dev->dstats);
10030+
break;
10031+
}
10032+
}
10033+
999410034
/**
999510035
* register_netdevice() - register a network device
999610036
* @dev: device to register
@@ -10051,11 +10091,15 @@ int register_netdevice(struct net_device *dev)
1005110091
goto err_uninit;
1005210092
}
1005310093

10094+
ret = netdev_do_alloc_pcpu_stats(dev);
10095+
if (ret)
10096+
goto err_uninit;
10097+
1005410098
ret = -EBUSY;
1005510099
if (!dev->ifindex)
1005610100
dev->ifindex = dev_new_index(net);
1005710101
else if (__dev_get_by_index(net, dev->ifindex))
10058-
goto err_uninit;
10102+
goto err_free_pcpu;
1005910103

1006010104
/* Transfer changeable features to wanted_features and enable
1006110105
* software offloads (GSO and GRO).
@@ -10102,14 +10146,14 @@ int register_netdevice(struct net_device *dev)
1010210146
ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
1010310147
ret = notifier_to_errno(ret);
1010410148
if (ret)
10105-
goto err_uninit;
10149+
goto err_free_pcpu;
1010610150

1010710151
ret = netdev_register_kobject(dev);
1010810152
write_lock(&dev_base_lock);
1010910153
dev->reg_state = ret ? NETREG_UNREGISTERED : NETREG_REGISTERED;
1011010154
write_unlock(&dev_base_lock);
1011110155
if (ret)
10112-
goto err_uninit;
10156+
goto err_free_pcpu;
1011310157

1011410158
__netdev_update_features(dev);
1011510159

@@ -10156,6 +10200,8 @@ int register_netdevice(struct net_device *dev)
1015610200
out:
1015710201
return ret;
1015810202

10203+
err_free_pcpu:
10204+
netdev_do_free_pcpu_stats(dev);
1015910205
err_uninit:
1016010206
if (dev->netdev_ops->ndo_uninit)
1016110207
dev->netdev_ops->ndo_uninit(dev);
@@ -10409,6 +10455,7 @@ void netdev_run_todo(void)
1040910455
WARN_ON(rcu_access_pointer(dev->ip_ptr));
1041010456
WARN_ON(rcu_access_pointer(dev->ip6_ptr));
1041110457

10458+
netdev_do_free_pcpu_stats(dev);
1041210459
if (dev->priv_destructor)
1041310460
dev->priv_destructor(dev);
1041410461
if (dev->needs_free_netdev)

0 commit comments

Comments
 (0)