i40e: report correct statistics when XDP is enabled
authorBjörn Töpel <bjorn.topel@intel.com>
Fri, 24 Aug 2018 11:21:59 +0000 (13:21 +0200)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 30 Aug 2018 20:53:04 +0000 (13:53 -0700)
When XDP is enabled, the driver will report incorrect
statistics. Received frames will reported as transmitted frames.

This commits fixes the i40e implementation of ndo_get_stats64 (struct
net_device_ops), so that iproute2 will report correct statistics
(e.g. when running "ip -stats link show dev eth0") even when XDP is
enabled.

Reported-by: Jesper Dangaard Brouer <brouer@redhat.com>
Fixes: 74608d17fe29 ("i40e: add support for XDP_TX action")
Signed-off-by: Björn Töpel <bjorn.topel@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e_main.c

index 62f2b5bce6bb78ab2130d4a1f3ccf6547721af07..6cb4076e8fba4b96e858c75156a0692bea552e71 100644 (file)
@@ -420,9 +420,9 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
                                  struct rtnl_link_stats64 *stats)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_ring *tx_ring, *rx_ring;
        struct i40e_vsi *vsi = np->vsi;
        struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
+       struct i40e_ring *ring;
        int i;
 
        if (test_bit(__I40E_VSI_DOWN, vsi->state))
@@ -436,24 +436,26 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
                u64 bytes, packets;
                unsigned int start;
 
-               tx_ring = READ_ONCE(vsi->tx_rings[i]);
-               if (!tx_ring)
+               ring = READ_ONCE(vsi->tx_rings[i]);
+               if (!ring)
                        continue;
-               i40e_get_netdev_stats_struct_tx(tx_ring, stats);
+               i40e_get_netdev_stats_struct_tx(ring, stats);
 
-               rx_ring = &tx_ring[1];
+               if (i40e_enabled_xdp_vsi(vsi)) {
+                       ring++;
+                       i40e_get_netdev_stats_struct_tx(ring, stats);
+               }
 
+               ring++;
                do {
-                       start = u64_stats_fetch_begin_irq(&rx_ring->syncp);
-                       packets = rx_ring->stats.packets;
-                       bytes   = rx_ring->stats.bytes;
-               } while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start));
+                       start   = u64_stats_fetch_begin_irq(&ring->syncp);
+                       packets = ring->stats.packets;
+                       bytes   = ring->stats.bytes;
+               } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
 
                stats->rx_packets += packets;
                stats->rx_bytes   += bytes;
 
-               if (i40e_enabled_xdp_vsi(vsi))
-                       i40e_get_netdev_stats_struct_tx(&rx_ring[1], stats);
        }
        rcu_read_unlock();