net/af_xdp: fix zero copy Tx queue drain

Message ID 421e4003bb7f556588ae95f0ed32ce282906a000.1629737818.git.baruch@tkos.co.il (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series net/af_xdp: fix zero copy Tx queue drain |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-aarch64-compile-testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-aarch64-unit-testing fail Testing issues

Commit Message

Baruch Siach Aug. 23, 2021, 4:56 p.m. UTC
  Call xsk_ring_prod__submit() before kick_tx() so that the kernel
consumer sees the updated state of Tx ring. Otherwise, Tx packets are
stuck in the ring until the next call to af_xdp_tx_zc().

Fixes: d8a210774e1d ("net/af_xdp: support unaligned umem chunks")
Cc: stable@dpdk.org

Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
 drivers/net/af_xdp/rte_eth_af_xdp.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
  

Comments

Loftus, Ciara Aug. 25, 2021, 9:32 a.m. UTC | #1
> 
> Call xsk_ring_prod__submit() before kick_tx() so that the kernel
> consumer sees the updated state of Tx ring. Otherwise, Tx packets are
> stuck in the ring until the next call to af_xdp_tx_zc().
> 
> Fixes: d8a210774e1d ("net/af_xdp: support unaligned umem chunks")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> ---
>  drivers/net/af_xdp/rte_eth_af_xdp.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c
> b/drivers/net/af_xdp/rte_eth_af_xdp.c
> index 74ffa4511284..81998d86b4aa 100644
> --- a/drivers/net/af_xdp/rte_eth_af_xdp.c
> +++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
> @@ -502,10 +502,11 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf
> **bufs, uint16_t nb_pkts)
> 
>  		if (mbuf->pool == umem->mb_pool) {
>  			if (!xsk_ring_prod__reserve(&txq->tx, 1, &idx_tx)) {
> +				xsk_ring_prod__submit(&txq->tx, count);

We cannot submit 'count' to the tx ring both here and at 'out'. We could end up submitting too many.

>  				kick_tx(txq, cq);

The purpose of this kick is not necessarily to transmit new descriptors but to drain the completion queue. No space in the completion queue may be what is preventing the kernel from transmitting existing tx buffers and then in userspace causing the the xsk_ring_prod__reserve to fail.
We are not trying to transmit new descriptors here.

>  				if (!xsk_ring_prod__reserve(&txq->tx, 1,
>  							    &idx_tx))
> -					goto out;
> +					goto out_skip_tx;
>  			}
>  			desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
>  			desc->len = mbuf->pkt_len;
> @@ -527,7 +528,6 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> 
>  			if (!xsk_ring_prod__reserve(&txq->tx, 1, &idx_tx)) {
>  				rte_pktmbuf_free(local_mbuf);
> -				kick_tx(txq, cq);
>  				goto out;
>  			}
> 
> @@ -551,11 +551,11 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf
> **bufs, uint16_t nb_pkts)
>  		tx_bytes += mbuf->pkt_len;
>  	}
> 
> -	kick_tx(txq, cq);
> -
>  out:
>  	xsk_ring_prod__submit(&txq->tx, count);
> +	kick_tx(txq, cq);

I think this change is valid. We should kick here after the submit.
Thanks for the patch. Could you please spin a v2 if you agree with the above?

Thanks,
Ciara

> 
> +out_skip_tx:
>  	txq->stats.tx_pkts += count;
>  	txq->stats.tx_bytes += tx_bytes;
>  	txq->stats.tx_dropped += nb_pkts - count;
> --
> 2.32.0
  

Patch

diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 74ffa4511284..81998d86b4aa 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -502,10 +502,11 @@  af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 
 		if (mbuf->pool == umem->mb_pool) {
 			if (!xsk_ring_prod__reserve(&txq->tx, 1, &idx_tx)) {
+				xsk_ring_prod__submit(&txq->tx, count);
 				kick_tx(txq, cq);
 				if (!xsk_ring_prod__reserve(&txq->tx, 1,
 							    &idx_tx))
-					goto out;
+					goto out_skip_tx;
 			}
 			desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
 			desc->len = mbuf->pkt_len;
@@ -527,7 +528,6 @@  af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 
 			if (!xsk_ring_prod__reserve(&txq->tx, 1, &idx_tx)) {
 				rte_pktmbuf_free(local_mbuf);
-				kick_tx(txq, cq);
 				goto out;
 			}
 
@@ -551,11 +551,11 @@  af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		tx_bytes += mbuf->pkt_len;
 	}
 
-	kick_tx(txq, cq);
-
 out:
 	xsk_ring_prod__submit(&txq->tx, count);
+	kick_tx(txq, cq);
 
+out_skip_tx:
 	txq->stats.tx_pkts += count;
 	txq->stats.tx_bytes += tx_bytes;
 	txq->stats.tx_dropped += nb_pkts - count;