af_xdp: make sure all packets are transmitted 68/34668/3
authorBenoît Ganne <bganne@cisco.com>
Thu, 2 Dec 2021 15:06:12 +0000 (16:06 +0100)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Thu, 8 Jun 2023 11:53:21 +0000 (11:53 +0000)
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 <bganne@cisco.com>
src/plugins/af_xdp/input.c
src/plugins/af_xdp/output.c

index 4f3ac57..08b503b 100644 (file)
@@ -15,7 +15,6 @@
  *------------------------------------------------------------------
  */
 
-#include <poll.h>
 #include <vlib/vlib.h>
 #include <vlib/unix/unix.h>
 #include <vlib/pci/pci.h>
@@ -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))
        {
index d1500a6..8136d91 100644 (file)
@@ -1,4 +1,3 @@
-#include <poll.h>
 #include <string.h>
 #include <vlib/vlib.h>
 #include <vlib/unix/unix.h>
@@ -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");