@@ -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 );
0 commit comments