From: Björn Töpel <bjorn.to...@intel.com>

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 <bro...@redhat.com>
Fixes: 74608d17fe29 ("i40e: add support for XDP_TX action")
Signed-off-by: Björn Töpel <bjorn.to...@intel.com>
Tested-by: Andrew Bowers <andrewx.bow...@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirs...@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 24 +++++++++++----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c 
b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 62f2b5bce6bb..6cb4076e8fba 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -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();
 
-- 
2.17.1

Reply via email to