Skip to content

Commit 1507091

Browse files
netoptimizerdavem330
authored andcommitted
mvneta: add XDP ethtool errors stats for TX to driver
Adding ethtool stats for when XDP transmitted packets overrun the TX queue. This is recorded separately for XDP_TX and ndo_xdp_xmit. This is an important aid for troubleshooting XDP based setups. It is currently a known weakness and property of XDP that there isn't any push-back or congestion feedback when transmitting frames via XDP. It's easy to realise when redirecting from a higher speed link into a slower speed link, or simply two ingress links into a single egress. The situation can also happen when Ethernet flow control is active. For testing the patch and provoking the situation to occur on my Espressobin board, I configured the TX-queue to be smaller (434) than RX-queue (512) and overload network with large MTU size frames (as a larger frame takes longer to transmit). Hopefully the upcoming XDP TX hook can be extended to provide insight into these TX queue overflows, to allow programmable adaptation strategies. Signed-off-by: Jesper Dangaard Brouer <[email protected]> Acked-by: Lorenzo Bianconi <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0b56a29 commit 1507091

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

drivers/net/ethernet/marvell/mvneta.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,10 @@ enum {
344344
ETHTOOL_XDP_REDIRECT,
345345
ETHTOOL_XDP_PASS,
346346
ETHTOOL_XDP_DROP,
347-
ETHTOOL_XDP_XMIT,
348347
ETHTOOL_XDP_TX,
348+
ETHTOOL_XDP_TX_ERR,
349+
ETHTOOL_XDP_XMIT,
350+
ETHTOOL_XDP_XMIT_ERR,
349351
ETHTOOL_MAX_STATS,
350352
};
351353

@@ -404,7 +406,9 @@ static const struct mvneta_statistic mvneta_statistics[] = {
404406
{ ETHTOOL_XDP_PASS, T_SW, "rx_xdp_pass", },
405407
{ ETHTOOL_XDP_DROP, T_SW, "rx_xdp_drop", },
406408
{ ETHTOOL_XDP_TX, T_SW, "rx_xdp_tx", },
409+
{ ETHTOOL_XDP_TX_ERR, T_SW, "rx_xdp_tx_errors", },
407410
{ ETHTOOL_XDP_XMIT, T_SW, "tx_xdp_xmit", },
411+
{ ETHTOOL_XDP_XMIT_ERR, T_SW, "tx_xdp_xmit_errors", },
408412
};
409413

410414
struct mvneta_stats {
@@ -417,7 +421,9 @@ struct mvneta_stats {
417421
u64 xdp_pass;
418422
u64 xdp_drop;
419423
u64 xdp_xmit;
424+
u64 xdp_xmit_err;
420425
u64 xdp_tx;
426+
u64 xdp_tx_err;
421427
};
422428

423429
struct mvneta_ethtool_stats {
@@ -2059,6 +2065,7 @@ mvneta_xdp_submit_frame(struct mvneta_port *pp, struct mvneta_tx_queue *txq,
20592065
static int
20602066
mvneta_xdp_xmit_back(struct mvneta_port *pp, struct xdp_buff *xdp)
20612067
{
2068+
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
20622069
struct mvneta_tx_queue *txq;
20632070
struct netdev_queue *nq;
20642071
struct xdp_frame *xdpf;
@@ -2076,15 +2083,17 @@ mvneta_xdp_xmit_back(struct mvneta_port *pp, struct xdp_buff *xdp)
20762083
__netif_tx_lock(nq, cpu);
20772084
ret = mvneta_xdp_submit_frame(pp, txq, xdpf, false);
20782085
if (ret == MVNETA_XDP_TX) {
2079-
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
2080-
20812086
u64_stats_update_begin(&stats->syncp);
20822087
stats->es.ps.tx_bytes += xdpf->len;
20832088
stats->es.ps.tx_packets++;
20842089
stats->es.ps.xdp_tx++;
20852090
u64_stats_update_end(&stats->syncp);
20862091

20872092
mvneta_txq_pend_desc_add(pp, txq, 0);
2093+
} else {
2094+
u64_stats_update_begin(&stats->syncp);
2095+
stats->es.ps.xdp_tx_err++;
2096+
u64_stats_update_end(&stats->syncp);
20882097
}
20892098
__netif_tx_unlock(nq);
20902099

@@ -2128,6 +2137,7 @@ mvneta_xdp_xmit(struct net_device *dev, int num_frame,
21282137
stats->es.ps.tx_bytes += nxmit_byte;
21292138
stats->es.ps.tx_packets += nxmit;
21302139
stats->es.ps.xdp_xmit += nxmit;
2140+
stats->es.ps.xdp_xmit_err += num_frame - nxmit;
21312141
u64_stats_update_end(&stats->syncp);
21322142

21332143
return nxmit;
@@ -2152,7 +2162,7 @@ mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
21522162
int err;
21532163

21542164
err = xdp_do_redirect(pp->dev, xdp, prog);
2155-
if (err) {
2165+
if (unlikely(err)) {
21562166
ret = MVNETA_XDP_DROPPED;
21572167
page_pool_put_page(rxq->page_pool,
21582168
virt_to_head_page(xdp->data), len,
@@ -4518,6 +4528,8 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp,
45184528
u64 skb_alloc_error;
45194529
u64 refill_error;
45204530
u64 xdp_redirect;
4531+
u64 xdp_xmit_err;
4532+
u64 xdp_tx_err;
45214533
u64 xdp_pass;
45224534
u64 xdp_drop;
45234535
u64 xdp_xmit;
@@ -4532,7 +4544,9 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp,
45324544
xdp_pass = stats->es.ps.xdp_pass;
45334545
xdp_drop = stats->es.ps.xdp_drop;
45344546
xdp_xmit = stats->es.ps.xdp_xmit;
4547+
xdp_xmit_err = stats->es.ps.xdp_xmit_err;
45354548
xdp_tx = stats->es.ps.xdp_tx;
4549+
xdp_tx_err = stats->es.ps.xdp_tx_err;
45364550
} while (u64_stats_fetch_retry_irq(&stats->syncp, start));
45374551

45384552
es->skb_alloc_error += skb_alloc_error;
@@ -4541,7 +4555,9 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp,
45414555
es->ps.xdp_pass += xdp_pass;
45424556
es->ps.xdp_drop += xdp_drop;
45434557
es->ps.xdp_xmit += xdp_xmit;
4558+
es->ps.xdp_xmit_err += xdp_xmit_err;
45444559
es->ps.xdp_tx += xdp_tx;
4560+
es->ps.xdp_tx_err += xdp_tx_err;
45454561
}
45464562
}
45474563

@@ -4594,9 +4610,15 @@ static void mvneta_ethtool_update_stats(struct mvneta_port *pp)
45944610
case ETHTOOL_XDP_TX:
45954611
pp->ethtool_stats[i] = stats.ps.xdp_tx;
45964612
break;
4613+
case ETHTOOL_XDP_TX_ERR:
4614+
pp->ethtool_stats[i] = stats.ps.xdp_tx_err;
4615+
break;
45974616
case ETHTOOL_XDP_XMIT:
45984617
pp->ethtool_stats[i] = stats.ps.xdp_xmit;
45994618
break;
4619+
case ETHTOOL_XDP_XMIT_ERR:
4620+
pp->ethtool_stats[i] = stats.ps.xdp_xmit_err;
4621+
break;
46004622
}
46014623
break;
46024624
}

0 commit comments

Comments
 (0)