Skip to content

Commit 2f523dc

Browse files
DavMiladavem330
authored andcommitted
gve: NIC stats for report-stats and for ethtool
This adds per queue NIC stats to ethtool stats and to report-stats. These stats are always exposed to guest whether or not the report-stats flag is turned on. Signed-off-by: David Awogbemila <awogbemila@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 24aeb56 commit 2f523dc

File tree

4 files changed

+94
-3
lines changed

4 files changed

+94
-3
lines changed

drivers/net/ethernet/google/gve/gve.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
/* Interval to schedule a stats report update, 20000ms. */
3535
#define GVE_STATS_REPORT_TIMER_PERIOD 20000
3636

37+
/* Numbers of NIC tx/rx stats in stats report. */
38+
#define NIC_TX_STATS_REPORT_NUM 0
39+
#define NIC_RX_STATS_REPORT_NUM 4
40+
3741
/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
3842
struct gve_rx_desc_queue {
3943
struct gve_rx_desc *desc_ring; /* the descriptor ring */

drivers/net/ethernet/google/gve/gve_adminq.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ enum gve_stat_names {
205205
TX_LAST_COMPLETION_PROCESSED = 5,
206206
RX_NEXT_EXPECTED_SEQUENCE = 6,
207207
RX_BUFFERS_POSTED = 7,
208+
// stats from NIC
209+
RX_QUEUE_DROP_CNT = 65,
210+
RX_NO_BUFFERS_POSTED = 66,
211+
RX_DROPS_PACKET_OVER_MRU = 67,
212+
RX_DROPS_INVALID_CHECKSUM = 68,
208213
};
209214

210215
union gve_adminq_command {

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

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ static const char gve_gstrings_main_stats[][ETH_GSTRING_LEN] = {
4343
static const char gve_gstrings_rx_stats[][ETH_GSTRING_LEN] = {
4444
"rx_posted_desc[%u]", "rx_completed_desc[%u]", "rx_bytes[%u]",
4545
"rx_dropped_pkt[%u]", "rx_copybreak_pkt[%u]", "rx_copied_pkt[%u]",
46+
"rx_queue_drop_cnt[%u]", "rx_no_buffers_posted[%u]",
47+
"rx_drops_packet_over_mru[%u]", "rx_drops_invalid_checksum[%u]",
4648
};
4749

4850
static const char gve_gstrings_tx_stats[][ETH_GSTRING_LEN] = {
@@ -138,14 +140,30 @@ gve_get_ethtool_stats(struct net_device *netdev,
138140
tmp_rx_desc_err_dropped_pkt, tmp_tx_pkts, tmp_tx_bytes;
139141
u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_pkts,
140142
rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes;
143+
int stats_idx, base_stats_idx, max_stats_idx;
144+
struct stats *report_stats;
145+
int *rx_qid_to_stats_idx;
146+
int *tx_qid_to_stats_idx;
141147
struct gve_priv *priv;
148+
bool skip_nic_stats;
142149
unsigned int start;
143150
int ring;
144-
int i;
151+
int i, j;
145152

146153
ASSERT_RTNL();
147154

148155
priv = netdev_priv(netdev);
156+
report_stats = priv->stats_report->stats;
157+
rx_qid_to_stats_idx = kmalloc_array(priv->rx_cfg.num_queues,
158+
sizeof(int), GFP_KERNEL);
159+
if (!rx_qid_to_stats_idx)
160+
return;
161+
tx_qid_to_stats_idx = kmalloc_array(priv->tx_cfg.num_queues,
162+
sizeof(int), GFP_KERNEL);
163+
if (!tx_qid_to_stats_idx) {
164+
kfree(rx_qid_to_stats_idx);
165+
return;
166+
}
149167
for (rx_pkts = 0, rx_bytes = 0, rx_skb_alloc_fail = 0,
150168
rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, ring = 0;
151169
ring < priv->rx_cfg.num_queues; ring++) {
@@ -208,6 +226,25 @@ gve_get_ethtool_stats(struct net_device *netdev,
208226
data[i++] = priv->stats_report_trigger_cnt;
209227
i = GVE_MAIN_STATS_LEN;
210228

229+
/* For rx cross-reporting stats, start from nic rx stats in report */
230+
base_stats_idx = GVE_TX_STATS_REPORT_NUM * priv->tx_cfg.num_queues +
231+
GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues;
232+
max_stats_idx = NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues +
233+
base_stats_idx;
234+
/* Preprocess the stats report for rx, map queue id to start index */
235+
skip_nic_stats = false;
236+
for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
237+
stats_idx += NIC_RX_STATS_REPORT_NUM) {
238+
u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
239+
u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
240+
241+
if (stat_name == 0) {
242+
/* no stats written by NIC yet */
243+
skip_nic_stats = true;
244+
break;
245+
}
246+
rx_qid_to_stats_idx[queue_id] = stats_idx;
247+
}
211248
/* walk RX rings */
212249
if (priv->rx) {
213250
for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
@@ -232,10 +269,41 @@ gve_get_ethtool_stats(struct net_device *netdev,
232269
tmp_rx_desc_err_dropped_pkt;
233270
data[i++] = rx->rx_copybreak_pkt;
234271
data[i++] = rx->rx_copied_pkt;
272+
/* stats from NIC */
273+
if (skip_nic_stats) {
274+
/* skip NIC rx stats */
275+
i += NIC_RX_STATS_REPORT_NUM;
276+
continue;
277+
}
278+
for (j = 0; j < NIC_RX_STATS_REPORT_NUM; j++) {
279+
u64 value =
280+
be64_to_cpu(report_stats[rx_qid_to_stats_idx[ring] + j].value);
281+
282+
data[i++] = value;
283+
}
235284
}
236285
} else {
237286
i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
238287
}
288+
289+
/* For tx cross-reporting stats, start from nic tx stats in report */
290+
base_stats_idx = max_stats_idx;
291+
max_stats_idx = NIC_TX_STATS_REPORT_NUM * priv->tx_cfg.num_queues +
292+
max_stats_idx;
293+
/* Preprocess the stats report for tx, map queue id to start index */
294+
skip_nic_stats = false;
295+
for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
296+
stats_idx += NIC_TX_STATS_REPORT_NUM) {
297+
u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
298+
u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
299+
300+
if (stat_name == 0) {
301+
/* no stats written by NIC yet */
302+
skip_nic_stats = true;
303+
break;
304+
}
305+
tx_qid_to_stats_idx[queue_id] = stats_idx;
306+
}
239307
/* walk TX rings */
240308
if (priv->tx) {
241309
for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
@@ -254,10 +322,24 @@ gve_get_ethtool_stats(struct net_device *netdev,
254322
data[i++] = tx->stop_queue;
255323
data[i++] = be32_to_cpu(gve_tx_load_event_counter(priv,
256324
tx));
325+
/* stats from NIC */
326+
if (skip_nic_stats) {
327+
/* skip NIC tx stats */
328+
i += NIC_TX_STATS_REPORT_NUM;
329+
continue;
330+
}
331+
for (j = 0; j < NIC_TX_STATS_REPORT_NUM; j++) {
332+
u64 value =
333+
be64_to_cpu(report_stats[tx_qid_to_stats_idx[ring] + j].value);
334+
data[i++] = value;
335+
}
257336
}
258337
} else {
259338
i += priv->tx_cfg.num_queues * NUM_GVE_TX_CNTS;
260339
}
340+
341+
kfree(rx_qid_to_stats_idx);
342+
kfree(tx_qid_to_stats_idx);
261343
/* AQ Stats */
262344
data[i++] = priv->adminq_prod_cnt;
263345
data[i++] = priv->adminq_cmd_fail;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ static int gve_alloc_stats_report(struct gve_priv *priv)
112112
{
113113
int tx_stats_num, rx_stats_num;
114114

115-
tx_stats_num = (GVE_TX_STATS_REPORT_NUM) *
115+
tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) *
116116
priv->tx_cfg.num_queues;
117-
rx_stats_num = (GVE_RX_STATS_REPORT_NUM) *
117+
rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
118118
priv->rx_cfg.num_queues;
119119
priv->stats_report_len = sizeof(struct gve_stats_report) +
120120
(tx_stats_num + rx_stats_num) *

0 commit comments

Comments
 (0)