[ Sasha's backport helper bot ] Hi, The upstream commit SHA1 provided is correct: 34d21de99cea9cb17967874313e5b0262527833c Status in newer kernel trees: 6.12.y | Present (exact SHA1) 6.6.y | Present (different SHA1: 6ae7b3fc7ae8) 6.1.y | Not found Note: The patch differs from the upstream commit: --- 1: 34d21de99cea9 ! 1: 927b0635b3b95 net: Move {l,t,d}stats allocation to core and convert veth & vrf @@ Metadata ## Commit message ## net: Move {l,t,d}stats allocation to core and convert veth & vrf + [ Upstream commit 34d21de99cea9cb17967874313e5b0262527833c ] + [ Note: Simplified vrf bits to reduce patch given unrelated to the fix ] + 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 @@ Commit message Cc: David Ahern <dsahern@xxxxxxxxxx> Link: https://lore.kernel.org/r/20231114004220.6495-3-daniel@xxxxxxxxxxxxx Signed-off-by: Martin KaFai Lau <martin.lau@xxxxxxxxxx> + Stable-dep-of: 024ee930cb3c ("bpf: Fix dev's rx stats for bpf_redirect_peer traffic") + Signed-off-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx> ## drivers/net/veth.c ## @@ drivers/net/veth.c: static void veth_free_queues(struct net_device *dev) @@ drivers/net/veth.c: static void veth_setup(struct net_device *dev) dev->hw_features = VETH_FEATURES; ## drivers/net/vrf.c ## -@@ drivers/net/vrf.c: static void vrf_dev_uninit(struct net_device *dev) +@@ drivers/net/vrf.c: struct net_vrf { + int ifindex; + }; - vrf_rtable_release(dev, vrf); - vrf_rt6_release(dev, vrf); +-struct pcpu_dstats { +- u64 tx_pkts; +- u64 tx_bytes; +- u64 tx_drps; +- u64 rx_pkts; +- u64 rx_bytes; +- u64 rx_drps; +- struct u64_stats_sync syncp; +-}; - -- free_percpu(dev->dstats); -- dev->dstats = NULL; - } - - static int vrf_dev_init(struct net_device *dev) + static void vrf_rx_stats(struct net_device *dev, int len) { - struct net_vrf *vrf = netdev_priv(dev); + struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats); -- dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats); -- if (!dev->dstats) -- goto out_nomem; -- - /* create the default dst which points back to us */ - if (vrf_rtable_create(dev) != 0) -- goto out_stats; -+ goto out_nomem; - - if (vrf_rt6_create(dev) != 0) - goto out_rth; -@@ drivers/net/vrf.c: static int vrf_dev_init(struct net_device *dev) - - out_rth: - vrf_rtable_release(dev, vrf); --out_stats: -- free_percpu(dev->dstats); -- dev->dstats = NULL; - out_nomem: - return -ENOMEM; + u64_stats_update_begin(&dstats->syncp); +- dstats->rx_pkts++; ++ dstats->rx_packets++; + dstats->rx_bytes += len; + u64_stats_update_end(&dstats->syncp); } -@@ drivers/net/vrf.c: static void vrf_setup(struct net_device *dev) - dev->min_mtu = IPV6_MIN_MTU; - dev->max_mtu = IP6_MAX_MTU; - dev->mtu = dev->max_mtu; -+ -+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS; +@@ drivers/net/vrf.c: static void vrf_get_stats64(struct net_device *dev, + do { + start = u64_stats_fetch_begin_irq(&dstats->syncp); + tbytes = dstats->tx_bytes; +- tpkts = dstats->tx_pkts; +- tdrops = dstats->tx_drps; ++ tpkts = dstats->tx_packets; ++ tdrops = dstats->tx_drops; + rbytes = dstats->rx_bytes; +- rpkts = dstats->rx_pkts; ++ rpkts = dstats->rx_packets; + } while (u64_stats_fetch_retry_irq(&dstats->syncp, start)); + stats->tx_bytes += tbytes; + stats->tx_packets += tpkts; +@@ drivers/net/vrf.c: static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev, + if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) + vrf_rx_stats(dev, len); + else +- this_cpu_inc(dev->dstats->rx_drps); ++ this_cpu_inc(dev->dstats->rx_drops); + + return NETDEV_TX_OK; } +@@ drivers/net/vrf.c: static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) + struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats); - static int vrf_validate(struct nlattr *tb[], struct nlattr *data[], + u64_stats_update_begin(&dstats->syncp); +- dstats->tx_pkts++; ++ dstats->tx_packets++; + dstats->tx_bytes += len; + u64_stats_update_end(&dstats->syncp); + } else { +- this_cpu_inc(dev->dstats->tx_drps); ++ this_cpu_inc(dev->dstats->tx_drops); + } + + return ret; ## include/linux/netdevice.h ## @@ include/linux/netdevice.h: enum netdev_ml_priv_type { @@ include/linux/netdevice.h: struct net_device { union { struct pcpu_lstats __percpu *lstats; struct pcpu_sw_netstats __percpu *tstats; +@@ include/linux/netdevice.h: struct pcpu_sw_netstats { + struct u64_stats_sync syncp; + } __aligned(4 * sizeof(u64)); + ++struct pcpu_dstats { ++ u64 rx_packets; ++ u64 rx_bytes; ++ u64 rx_drops; ++ u64 tx_packets; ++ u64 tx_bytes; ++ u64 tx_drops; ++ struct u64_stats_sync syncp; ++} __aligned(8 * sizeof(u64)); ++ + struct pcpu_lstats { + u64_stats_t packets; + u64_stats_t bytes; ## net/core/dev.c ## @@ net/core/dev.c: void netif_tx_stop_all_queues(struct net_device *dev) @@ net/core/dev.c: int register_netdevice(struct net_device *dev) + if (ret) + goto err_uninit; + - ret = dev_index_reserve(net, dev->ifindex); - if (ret < 0) + ret = -EBUSY; + if (!dev->ifindex) + dev->ifindex = dev_new_index(net); + else if (__dev_get_by_index(net, dev->ifindex)) - goto err_uninit; + goto err_free_pcpu; - dev->ifindex = ret; /* Transfer changeable features to wanted_features and enable + * software offloads (GSO and GRO). +@@ net/core/dev.c: int register_netdevice(struct net_device *dev) + ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); + ret = notifier_to_errno(ret); + if (ret) +- goto err_uninit; ++ goto err_free_pcpu; + + ret = netdev_register_kobject(dev); + write_lock(&dev_base_lock); + dev->reg_state = ret ? NETREG_UNREGISTERED : NETREG_REGISTERED; + write_unlock(&dev_base_lock); + if (ret) +- goto err_uninit; ++ goto err_free_pcpu; + + __netdev_update_features(dev); + @@ net/core/dev.c: int register_netdevice(struct net_device *dev) - call_netdevice_notifiers(NETDEV_PRE_UNINIT, dev); - err_ifindex_release: - dev_index_release(net, dev->ifindex); + out: + return ret; + +err_free_pcpu: + netdev_do_free_pcpu_stats(dev); err_uninit: --- Results of testing on various branches: | Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-6.1.y | Success | Success |