Skip to content

Commit 28e5691

Browse files
committed
net: Move {l,t,d}stats allocation to core and convert veth & vrf
JIRA: https://issues.redhat.com/browse/RHEL-57740 Conflicts: - include/linux/netdevice.h: context conflict due to backported commit c353c7b ("net-device: move lstats in net_device_read_txrx") - drivers/net/veth.c: modified due to backported commit 0bef512 ("net: add netdev_lockdep_set_classes() to virtual drivers") - net/core/dev.c: context conflict due to missing commit 1202cdd ("Remove DECnet support from kernel") commit 34d21de Author: Daniel Borkmann <daniel@iogearbox.net> Date: Tue Nov 14 01:42:14 2023 +0100 net: Move {l,t,d}stats allocation to core and convert veth & vrf 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 <kuba@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Cc: David Ahern <dsahern@kernel.org> Link: https://lore.kernel.org/r/20231114004220.6495-3-daniel@iogearbox.net Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
1 parent 5d16900 commit 28e5691

File tree

4 files changed

+71
-30
lines changed

4 files changed

+71
-30
lines changed

drivers/net/veth.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,26 +1430,13 @@ static void veth_free_queues(struct net_device *dev)
14301430

14311431
static int veth_dev_init(struct net_device *dev)
14321432
{
1433-
int err;
1434-
1435-
dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
1436-
if (!dev->lstats)
1437-
return -ENOMEM;
1438-
14391433
netdev_lockdep_set_classes(dev);
1440-
err = veth_alloc_queues(dev);
1441-
if (err) {
1442-
free_percpu(dev->lstats);
1443-
return err;
1444-
}
1445-
1446-
return 0;
1434+
return veth_alloc_queues(dev);
14471435
}
14481436

14491437
static void veth_dev_free(struct net_device *dev)
14501438
{
14511439
veth_free_queues(dev);
1452-
free_percpu(dev->lstats);
14531440
}
14541441

14551442
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1738,6 +1725,7 @@ static void veth_setup(struct net_device *dev)
17381725
NETIF_F_HW_VLAN_STAG_RX);
17391726
dev->needs_free_netdev = true;
17401727
dev->priv_destructor = veth_dev_free;
1728+
dev->pcpu_stat_type = NETDEV_PCPU_STAT_LSTATS;
17411729
dev->max_mtu = ETH_MAX_MTU;
17421730

17431731
dev->hw_features = VETH_FEATURES;

drivers/net/vrf.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,22 +1166,15 @@ static void vrf_dev_uninit(struct net_device *dev)
11661166

11671167
vrf_rtable_release(dev, vrf);
11681168
vrf_rt6_release(dev, vrf);
1169-
1170-
free_percpu(dev->dstats);
1171-
dev->dstats = NULL;
11721169
}
11731170

11741171
static int vrf_dev_init(struct net_device *dev)
11751172
{
11761173
struct net_vrf *vrf = netdev_priv(dev);
11771174

1178-
dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
1179-
if (!dev->dstats)
1180-
goto out_nomem;
1181-
11821175
/* create the default dst which points back to us */
11831176
if (vrf_rtable_create(dev) != 0)
1184-
goto out_stats;
1177+
goto out_nomem;
11851178

11861179
if (vrf_rt6_create(dev) != 0)
11871180
goto out_rth;
@@ -1195,9 +1188,6 @@ static int vrf_dev_init(struct net_device *dev)
11951188

11961189
out_rth:
11971190
vrf_rtable_release(dev, vrf);
1198-
out_stats:
1199-
free_percpu(dev->dstats);
1200-
dev->dstats = NULL;
12011191
out_nomem:
12021192
return -ENOMEM;
12031193
}
@@ -1696,6 +1686,8 @@ static void vrf_setup(struct net_device *dev)
16961686
dev->min_mtu = IPV6_MIN_MTU;
16971687
dev->max_mtu = IP6_MAX_MTU;
16981688
dev->mtu = dev->max_mtu;
1689+
1690+
dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
16991691
}
17001692

17011693
static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],

include/linux/netdevice.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,13 @@ enum netdev_ml_priv_type {
17691769
ML_PRIV_CAN,
17701770
};
17711771

1772+
enum netdev_stat_type {
1773+
NETDEV_PCPU_STAT_NONE,
1774+
NETDEV_PCPU_STAT_LSTATS, /* struct pcpu_lstats */
1775+
NETDEV_PCPU_STAT_TSTATS, /* struct pcpu_sw_netstats */
1776+
NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */
1777+
};
1778+
17721779
/**
17731780
* struct net_device - The DEVICE structure.
17741781
*
@@ -1964,10 +1971,14 @@ enum netdev_ml_priv_type {
19641971
*
19651972
* @ml_priv: Mid-layer private
19661973
* @ml_priv_type: Mid-layer private type
1967-
* @lstats: Loopback statistics
1968-
* @tstats: Tunnel statistics
1969-
* @dstats: Dummy statistics
1970-
* @vstats: Virtual ethernet statistics
1974+
*
1975+
* @pcpu_stat_type: Type of device statistics which the core should
1976+
* allocate/free: none, lstats, tstats, dstats. none
1977+
* means the driver is handling statistics allocation/
1978+
* freeing internally.
1979+
* @lstats: Loopback statistics: packets, bytes
1980+
* @tstats: Tunnel statistics: RX/TX packets, RX/TX bytes
1981+
* @dstats: Dummy statistics: RX/TX/drop packets, RX/TX bytes
19711982
*
19721983
* @garp_port: GARP
19731984
* @mrp_port: MRP
@@ -2355,6 +2366,8 @@ struct net_device {
23552366
void *ml_priv;
23562367
enum netdev_ml_priv_type ml_priv_type;
23572368

2369+
enum netdev_stat_type pcpu_stat_type:8;
2370+
23582371
#if IS_ENABLED(CONFIG_GARP)
23592372
struct garp_port __rcu *garp_port;
23602373
#endif

net/core/dev.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9962,6 +9962,46 @@ void netif_tx_stop_all_queues(struct net_device *dev)
99629962
}
99639963
EXPORT_SYMBOL(netif_tx_stop_all_queues);
99649964

9965+
static int netdev_do_alloc_pcpu_stats(struct net_device *dev)
9966+
{
9967+
void __percpu *v;
9968+
9969+
switch (dev->pcpu_stat_type) {
9970+
case NETDEV_PCPU_STAT_NONE:
9971+
return 0;
9972+
case NETDEV_PCPU_STAT_LSTATS:
9973+
v = dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
9974+
break;
9975+
case NETDEV_PCPU_STAT_TSTATS:
9976+
v = dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
9977+
break;
9978+
case NETDEV_PCPU_STAT_DSTATS:
9979+
v = dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
9980+
break;
9981+
default:
9982+
return -EINVAL;
9983+
}
9984+
9985+
return v ? 0 : -ENOMEM;
9986+
}
9987+
9988+
static void netdev_do_free_pcpu_stats(struct net_device *dev)
9989+
{
9990+
switch (dev->pcpu_stat_type) {
9991+
case NETDEV_PCPU_STAT_NONE:
9992+
return;
9993+
case NETDEV_PCPU_STAT_LSTATS:
9994+
free_percpu(dev->lstats);
9995+
break;
9996+
case NETDEV_PCPU_STAT_TSTATS:
9997+
free_percpu(dev->tstats);
9998+
break;
9999+
case NETDEV_PCPU_STAT_DSTATS:
10000+
free_percpu(dev->dstats);
10001+
break;
10002+
}
10003+
}
10004+
996510005
/**
996610006
* register_netdevice - register a network device
996710007
* @dev: device to register
@@ -10030,9 +10070,13 @@ int register_netdevice(struct net_device *dev)
1003010070
goto err_uninit;
1003110071
}
1003210072

10073+
ret = netdev_do_alloc_pcpu_stats(dev);
10074+
if (ret)
10075+
goto err_uninit;
10076+
1003310077
ret = dev_index_reserve(net, dev->ifindex);
1003410078
if (ret < 0)
10035-
goto err_uninit;
10079+
goto err_free_pcpu;
1003610080
dev->ifindex = ret;
1003710081

1003810082
/* Transfer changeable features to wanted_features and enable
@@ -10138,6 +10182,8 @@ int register_netdevice(struct net_device *dev)
1013810182
call_netdevice_notifiers(NETDEV_PRE_UNINIT, dev);
1013910183
err_ifindex_release:
1014010184
dev_index_release(net, dev->ifindex);
10185+
err_free_pcpu:
10186+
netdev_do_free_pcpu_stats(dev);
1014110187
err_uninit:
1014210188
if (dev->netdev_ops->ndo_uninit)
1014310189
dev->netdev_ops->ndo_uninit(dev);
@@ -10392,6 +10438,8 @@ void netdev_run_todo(void)
1039210438
#if IS_ENABLED(CONFIG_DECNET)
1039310439
WARN_ON(dev->dn_ptr);
1039410440
#endif
10441+
10442+
netdev_do_free_pcpu_stats(dev);
1039510443
if (dev->priv_destructor)
1039610444
dev->priv_destructor(dev);
1039710445
if (dev->needs_free_netdev)

0 commit comments

Comments
 (0)