]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
net: harmonize tstats and dstats
authorPaolo Abeni <pabeni@redhat.com>
Sat, 1 Feb 2025 18:02:51 +0000 (19:02 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 4 Feb 2025 02:39:59 +0000 (18:39 -0800)
After the blamed commits below, some UDP tunnel use dstats for
accounting. On the xmit path, all the UDP-base tunnels ends up
using iptunnel_xmit_stats() for stats accounting, and the latter
assumes the relevant (tunnel) network device uses tstats.

The end result is some 'funny' stat report for the mentioned UDP
tunnel, e.g. when no packet is actually dropped and a bunch of
packets are transmitted:

gnv2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue \
state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether ee:7d:09:87:90:ea brd ff:ff:ff:ff:ff:ff
    RX:  bytes packets errors dropped  missed   mcast
         14916      23      0      15       0       0
    TX:  bytes packets errors dropped carrier collsns
             0    1566      0       0       0       0

Address the issue ensuring the same binary layout for the overlapping
fields of dstats and tstats. While this solution is a bit hackish, is
smaller and with no performance pitfall compared to other alternatives
i.e. supporting both dstat and tstat in iptunnel_xmit_stats() or
reverting the blamed commit.

With time we should possibly move all the IP-based tunnel (and virtual
devices) to dstats.

Fixes: c77200c07491 ("bareudp: Handle stats using NETDEV_PCPU_STAT_DSTATS.")
Fixes: 6fa6de302246 ("geneve: Handle stats using NETDEV_PCPU_STAT_DSTATS.")
Fixes: be226352e8dc ("vxlan: Handle stats using NETDEV_PCPU_STAT_DSTATS.")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Guillaume Nault <gnault@redhat.com>
Link: https://patch.msgid.link/2e1c444cf0f63ae472baff29862c4c869be17031.1738432804.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/linux/netdevice.h
net/core/dev.c

index 2a59034a5fa2fb53300657968c2053ab354bb746..03bb584c62cf8a920b12c673dcc438eb1cc41499 100644 (file)
@@ -2904,9 +2904,9 @@ struct pcpu_sw_netstats {
 struct pcpu_dstats {
        u64_stats_t             rx_packets;
        u64_stats_t             rx_bytes;
-       u64_stats_t             rx_drops;
        u64_stats_t             tx_packets;
        u64_stats_t             tx_bytes;
+       u64_stats_t             rx_drops;
        u64_stats_t             tx_drops;
        struct u64_stats_sync   syncp;
 } __aligned(8 * sizeof(u64));
index c0021cbd28fc11e4c4eb6184d98a2505fa674871..b91658e8aedb41de57c0b6531183c454ed770b2b 100644 (file)
@@ -11286,6 +11286,20 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
        const struct net_device_ops *ops = dev->netdev_ops;
        const struct net_device_core_stats __percpu *p;
 
+       /*
+        * IPv{4,6} and udp tunnels share common stat helpers and use
+        * different stat type (NETDEV_PCPU_STAT_TSTATS vs
+        * NETDEV_PCPU_STAT_DSTATS). Ensure the accounting is consistent.
+        */
+       BUILD_BUG_ON(offsetof(struct pcpu_sw_netstats, rx_bytes) !=
+                    offsetof(struct pcpu_dstats, rx_bytes));
+       BUILD_BUG_ON(offsetof(struct pcpu_sw_netstats, rx_packets) !=
+                    offsetof(struct pcpu_dstats, rx_packets));
+       BUILD_BUG_ON(offsetof(struct pcpu_sw_netstats, tx_bytes) !=
+                    offsetof(struct pcpu_dstats, tx_bytes));
+       BUILD_BUG_ON(offsetof(struct pcpu_sw_netstats, tx_packets) !=
+                    offsetof(struct pcpu_dstats, tx_packets));
+
        if (ops->ndo_get_stats64) {
                memset(storage, 0, sizeof(*storage));
                ops->ndo_get_stats64(dev, storage);