]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
gve: Correct ethtool rx_dropped calculation
authorMax Yuan <maxyuan@google.com>
Mon, 2 Feb 2026 19:39:25 +0000 (19:39 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 4 Feb 2026 03:28:05 +0000 (19:28 -0800)
The gve driver's "rx_dropped" statistic, exposed via `ethtool -S`,
incorrectly includes `rx_buf_alloc_fail` counts. These failures
represent an inability to allocate receive buffers, not true packet
drops where a received packet is discarded. This misrepresentation can
lead to inaccurate diagnostics.

This patch rectifies the ethtool "rx_dropped" calculation. It removes
`rx_buf_alloc_fail` from the total and adds `xdp_tx_errors` and
`xdp_redirect_errors`, which represent legitimate packet drops within
the XDP path.

Cc: stable@vger.kernel.org
Fixes: 433e274b8f7b ("gve: Add stats for gve.")
Signed-off-by: Max Yuan <maxyuan@google.com>
Reviewed-by: Jordan Rhee <jordanrhee@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Matt Olson <maolson@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260202193925.3106272-3-hramamurthy@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/google/gve/gve_ethtool.c

index 137dd7285bdad2ce0d5ca8d8be1d41cf84a4533e..66ddc4413f8dffd3ccf8bf4e38a77b2ca248ce69 100644 (file)
@@ -152,10 +152,11 @@ gve_get_ethtool_stats(struct net_device *netdev,
        u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes,
                tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail,
                tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt,
-               tmp_tx_pkts, tmp_tx_bytes;
+               tmp_tx_pkts, tmp_tx_bytes,
+               tmp_xdp_tx_errors, tmp_xdp_redirect_errors;
        u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt,
                rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes,
-               tx_dropped;
+               tx_dropped, xdp_tx_errors, xdp_redirect_errors;
        int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx;
        int stats_idx, stats_region_len, nic_stats_len;
        struct stats *report_stats;
@@ -199,6 +200,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
        for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0,
             rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0,
             rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0,
+            xdp_tx_errors = 0, xdp_redirect_errors = 0,
             ring = 0;
             ring < priv->rx_cfg.num_queues; ring++) {
                if (priv->rx) {
@@ -216,6 +218,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
                                        rx->rx_desc_err_dropped_pkt;
                                tmp_rx_hsplit_unsplit_pkt =
                                        rx->rx_hsplit_unsplit_pkt;
+                               tmp_xdp_tx_errors = rx->xdp_tx_errors;
+                               tmp_xdp_redirect_errors =
+                                       rx->xdp_redirect_errors;
                        } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
                                                       start));
                        rx_pkts += tmp_rx_pkts;
@@ -225,6 +230,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
                        rx_buf_alloc_fail += tmp_rx_buf_alloc_fail;
                        rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt;
                        rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt;
+                       xdp_tx_errors += tmp_xdp_tx_errors;
+                       xdp_redirect_errors += tmp_xdp_redirect_errors;
                }
        }
        for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0;
@@ -250,8 +257,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
        data[i++] = rx_bytes;
        data[i++] = tx_bytes;
        /* total rx dropped packets */
-       data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail +
-                   rx_desc_err_dropped_pkt;
+       data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt +
+                   xdp_tx_errors + xdp_redirect_errors;
        data[i++] = tx_dropped;
        data[i++] = priv->tx_timeo_cnt;
        data[i++] = rx_skb_alloc_fail;
@@ -330,6 +337,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
                                tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
                                tmp_rx_desc_err_dropped_pkt =
                                        rx->rx_desc_err_dropped_pkt;
+                               tmp_xdp_tx_errors = rx->xdp_tx_errors;
+                               tmp_xdp_redirect_errors =
+                                       rx->xdp_redirect_errors;
                        } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
                                                       start));
                        data[i++] = tmp_rx_bytes;
@@ -340,8 +350,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
                        data[i++] = rx->rx_frag_alloc_cnt;
                        /* rx dropped packets */
                        data[i++] = tmp_rx_skb_alloc_fail +
-                               tmp_rx_buf_alloc_fail +
-                               tmp_rx_desc_err_dropped_pkt;
+                                   tmp_rx_desc_err_dropped_pkt +
+                                   tmp_xdp_tx_errors +
+                                   tmp_xdp_redirect_errors;
                        data[i++] = rx->rx_copybreak_pkt;
                        data[i++] = rx->rx_copied_pkt;
                        /* stats from NIC */