4.19-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Björn Töpel <[email protected]>

commit cdec2141c24ef177d929765c5a6f95549c266fb3 upstream.

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 <[email protected]>
Fixes: 74608d17fe29 ("i40e: add support for XDP_TX action")
Signed-off-by: Björn Töpel <[email protected]>
Tested-by: Andrew Bowers <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
Cc: Emeric Brun <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 drivers/net/ethernet/intel/i40e/i40e_main.c |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -424,9 +424,9 @@ static void i40e_get_netdev_stats_struct
                                  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))
@@ -440,24 +440,26 @@ static void i40e_get_netdev_stats_struct
                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();
 


Reply via email to