Skip to content

Commit 279fe48

Browse files
committed
Merge branch 'gve-stats-reporting-fixes'
Max Yuan says: ==================== gve: Stats reporting fixes This series addresses two issues related to statistics in the gve driver. The first patch fixes a memory corruption issue that occurs when resizing the stats region during queue count changes. By allocating the maximum possible size upfront and aligning offset calculations with the NIC, we ensure stability and accuracy across reconfigurations. The second patch fixes the 'rx_dropped' counter by removing allocation failures and incorporating XDP transmit and redirect errors to provide a more accurate representation of dropped packets. ==================== Link: https://patch.msgid.link/20260202193925.3106272-1-hramamurthy@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 6788d44 + c7db85d commit 279fe48

File tree

2 files changed

+53
-28
lines changed

2 files changed

+53
-28
lines changed

drivers/net/ethernet/google/gve/gve_ethtool.c

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,13 @@ gve_get_ethtool_stats(struct net_device *netdev,
152152
u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes,
153153
tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail,
154154
tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt,
155-
tmp_tx_pkts, tmp_tx_bytes;
155+
tmp_tx_pkts, tmp_tx_bytes,
156+
tmp_xdp_tx_errors, tmp_xdp_redirect_errors;
156157
u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt,
157158
rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes,
158-
tx_dropped;
159-
int stats_idx, base_stats_idx, max_stats_idx;
159+
tx_dropped, xdp_tx_errors, xdp_redirect_errors;
160+
int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx;
161+
int stats_idx, stats_region_len, nic_stats_len;
160162
struct stats *report_stats;
161163
int *rx_qid_to_stats_idx;
162164
int *tx_qid_to_stats_idx;
@@ -198,6 +200,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
198200
for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0,
199201
rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0,
200202
rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0,
203+
xdp_tx_errors = 0, xdp_redirect_errors = 0,
201204
ring = 0;
202205
ring < priv->rx_cfg.num_queues; ring++) {
203206
if (priv->rx) {
@@ -215,6 +218,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
215218
rx->rx_desc_err_dropped_pkt;
216219
tmp_rx_hsplit_unsplit_pkt =
217220
rx->rx_hsplit_unsplit_pkt;
221+
tmp_xdp_tx_errors = rx->xdp_tx_errors;
222+
tmp_xdp_redirect_errors =
223+
rx->xdp_redirect_errors;
218224
} while (u64_stats_fetch_retry(&priv->rx[ring].statss,
219225
start));
220226
rx_pkts += tmp_rx_pkts;
@@ -224,6 +230,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
224230
rx_buf_alloc_fail += tmp_rx_buf_alloc_fail;
225231
rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt;
226232
rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt;
233+
xdp_tx_errors += tmp_xdp_tx_errors;
234+
xdp_redirect_errors += tmp_xdp_redirect_errors;
227235
}
228236
}
229237
for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0;
@@ -249,8 +257,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
249257
data[i++] = rx_bytes;
250258
data[i++] = tx_bytes;
251259
/* total rx dropped packets */
252-
data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail +
253-
rx_desc_err_dropped_pkt;
260+
data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt +
261+
xdp_tx_errors + xdp_redirect_errors;
254262
data[i++] = tx_dropped;
255263
data[i++] = priv->tx_timeo_cnt;
256264
data[i++] = rx_skb_alloc_fail;
@@ -265,20 +273,38 @@ gve_get_ethtool_stats(struct net_device *netdev,
265273
data[i++] = priv->stats_report_trigger_cnt;
266274
i = GVE_MAIN_STATS_LEN;
267275

268-
/* For rx cross-reporting stats, start from nic rx stats in report */
269-
base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues +
270-
GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues;
271-
/* The boundary between driver stats and NIC stats shifts if there are
272-
* stopped queues.
273-
*/
274-
base_stats_idx += NIC_RX_STATS_REPORT_NUM * num_stopped_rxqs +
275-
NIC_TX_STATS_REPORT_NUM * num_stopped_txqs;
276-
max_stats_idx = NIC_RX_STATS_REPORT_NUM *
277-
(priv->rx_cfg.num_queues - num_stopped_rxqs) +
278-
base_stats_idx;
276+
rx_base_stats_idx = 0;
277+
max_rx_stats_idx = 0;
278+
max_tx_stats_idx = 0;
279+
stats_region_len = priv->stats_report_len -
280+
sizeof(struct gve_stats_report);
281+
nic_stats_len = (NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues +
282+
NIC_TX_STATS_REPORT_NUM * num_tx_queues) * sizeof(struct stats);
283+
if (unlikely((stats_region_len -
284+
nic_stats_len) % sizeof(struct stats))) {
285+
net_err_ratelimited("Starting index of NIC stats should be multiple of stats size");
286+
} else {
287+
/* For rx cross-reporting stats,
288+
* start from nic rx stats in report
289+
*/
290+
rx_base_stats_idx = (stats_region_len - nic_stats_len) /
291+
sizeof(struct stats);
292+
/* The boundary between driver stats and NIC stats
293+
* shifts if there are stopped queues
294+
*/
295+
rx_base_stats_idx += NIC_RX_STATS_REPORT_NUM *
296+
num_stopped_rxqs + NIC_TX_STATS_REPORT_NUM *
297+
num_stopped_txqs;
298+
max_rx_stats_idx = NIC_RX_STATS_REPORT_NUM *
299+
(priv->rx_cfg.num_queues - num_stopped_rxqs) +
300+
rx_base_stats_idx;
301+
max_tx_stats_idx = NIC_TX_STATS_REPORT_NUM *
302+
(num_tx_queues - num_stopped_txqs) +
303+
max_rx_stats_idx;
304+
}
279305
/* Preprocess the stats report for rx, map queue id to start index */
280306
skip_nic_stats = false;
281-
for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
307+
for (stats_idx = rx_base_stats_idx; stats_idx < max_rx_stats_idx;
282308
stats_idx += NIC_RX_STATS_REPORT_NUM) {
283309
u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
284310
u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
@@ -311,6 +337,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
311337
tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
312338
tmp_rx_desc_err_dropped_pkt =
313339
rx->rx_desc_err_dropped_pkt;
340+
tmp_xdp_tx_errors = rx->xdp_tx_errors;
341+
tmp_xdp_redirect_errors =
342+
rx->xdp_redirect_errors;
314343
} while (u64_stats_fetch_retry(&priv->rx[ring].statss,
315344
start));
316345
data[i++] = tmp_rx_bytes;
@@ -321,8 +350,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
321350
data[i++] = rx->rx_frag_alloc_cnt;
322351
/* rx dropped packets */
323352
data[i++] = tmp_rx_skb_alloc_fail +
324-
tmp_rx_buf_alloc_fail +
325-
tmp_rx_desc_err_dropped_pkt;
353+
tmp_rx_desc_err_dropped_pkt +
354+
tmp_xdp_tx_errors +
355+
tmp_xdp_redirect_errors;
326356
data[i++] = rx->rx_copybreak_pkt;
327357
data[i++] = rx->rx_copied_pkt;
328358
/* stats from NIC */
@@ -354,14 +384,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
354384
i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
355385
}
356386

357-
/* For tx cross-reporting stats, start from nic tx stats in report */
358-
base_stats_idx = max_stats_idx;
359-
max_stats_idx = NIC_TX_STATS_REPORT_NUM *
360-
(num_tx_queues - num_stopped_txqs) +
361-
max_stats_idx;
362-
/* Preprocess the stats report for tx, map queue id to start index */
363387
skip_nic_stats = false;
364-
for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
388+
/* NIC TX stats start right after NIC RX stats */
389+
for (stats_idx = max_rx_stats_idx; stats_idx < max_tx_stats_idx;
365390
stats_idx += NIC_TX_STATS_REPORT_NUM) {
366391
u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
367392
u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);

drivers/net/ethernet/google/gve/gve_main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,9 @@ static int gve_alloc_stats_report(struct gve_priv *priv)
283283
int tx_stats_num, rx_stats_num;
284284

285285
tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) *
286-
gve_num_tx_queues(priv);
286+
priv->tx_cfg.max_queues;
287287
rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
288-
priv->rx_cfg.num_queues;
288+
priv->rx_cfg.max_queues;
289289
priv->stats_report_len = struct_size(priv->stats_report, stats,
290290
size_add(tx_stats_num, rx_stats_num));
291291
priv->stats_report =

0 commit comments

Comments
 (0)