From f40bdbb80d59be824ee9cc9273785f9548a3fe77 Mon Sep 17 00:00:00 2001 From: Benoît Ganne Date: Thu, 2 Dec 2021 16:06:12 +0100 Subject: af_xdp: make sure all packets are transmitted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AF_XDP socket will only tx enqueued packets up to a max batch size so we need to retry until everything has been sent. Type: fix Change-Id: Ia487ab63d3e85a478471cd1d679c5fb471804ba3 Signed-off-by: Benoît Ganne --- src/plugins/af_xdp/input.c | 4 +--- src/plugins/af_xdp/output.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/plugins/af_xdp/input.c b/src/plugins/af_xdp/input.c index 4f3ac5725a4..08b503b1641 100644 --- a/src/plugins/af_xdp/input.c +++ b/src/plugins/af_xdp/input.c @@ -15,7 +15,6 @@ *------------------------------------------------------------------ */ -#include #include #include #include @@ -89,8 +88,7 @@ af_xdp_device_input_refill_db (vlib_main_t * vm, if (clib_spinlock_trylock_if_init (&rxq->syscall_lock)) { - struct pollfd fd = { .fd = rxq->xsk_fd, .events = POLLIN | POLLOUT }; - int ret = poll (&fd, 1, 0); + int ret = recvmsg (rxq->xsk_fd, 0, MSG_DONTWAIT); clib_spinlock_unlock_if_init (&rxq->syscall_lock); if (PREDICT_FALSE (ret < 0)) { diff --git a/src/plugins/af_xdp/output.c b/src/plugins/af_xdp/output.c index d1500a63cbb..8136d918a75 100644 --- a/src/plugins/af_xdp/output.c +++ b/src/plugins/af_xdp/output.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -101,11 +100,19 @@ af_xdp_device_output_tx_db (vlib_main_t * vm, if (xsk_ring_prod__needs_wakeup (&txq->tx)) { - struct pollfd fd = { .fd = txq->xsk_fd, .events = POLLIN | POLLOUT }; - int ret = poll (&fd, 1, 0); + const struct msghdr msg = {}; + int ret; + /* On tx, xsk socket will only tx up to TX_BATCH_SIZE, as defined in + * kernel net/xdp/xsk.c. Unfortunately we do not know how much this is, + * our only option is to retry until everything is sent... */ + do + { + ret = sendmsg (txq->xsk_fd, &msg, MSG_DONTWAIT); + } + while (ret < 0 && EAGAIN == errno); if (PREDICT_FALSE (ret < 0)) { - /* something bad is happening */ + /* not EAGAIN: something bad is happening */ vlib_error_count (vm, node->node_index, AF_XDP_TX_ERROR_SYSCALL_FAILURES, 1); af_xdp_device_error (ad, "tx poll() failed"); -- cgit 1.2.3-korg