The recvfrom() syscall is only supported by AF_XDP sockets since kernel 5.11. Only use it if busy polling is configured. We can assume a kernel >= 5.11 is in use if busy polling is configured so we can safely call recvfrom() in that case.
Fixes: 63e8989fe5a4 ("net/af_xdp: use recvfrom instead of poll syscall") Signed-off-by: Ciara Loftus <ciara.lof...@intel.com> --- drivers/net/af_xdp/compat.h | 28 ++++++++++++++++++++++------ drivers/net/af_xdp/rte_eth_af_xdp.c | 10 +++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/net/af_xdp/compat.h b/drivers/net/af_xdp/compat.h index 9de9454885..52fd447b69 100644 --- a/drivers/net/af_xdp/compat.h +++ b/drivers/net/af_xdp/compat.h @@ -4,6 +4,7 @@ #include <bpf/xsk.h> #include <linux/version.h> +#include <poll.h> #if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE && \ defined(RTE_LIBRTE_AF_XDP_PMD_SHARED_UMEM) @@ -41,10 +42,22 @@ create_shared_socket(struct xsk_socket **xsk_ptr __rte_unused, #endif #ifdef XDP_USE_NEED_WAKEUP -static int -rx_syscall_needed(struct xsk_ring_prod *q, uint32_t busy_budget) +static void +rx_syscall_handler(struct xsk_ring_prod *q, uint32_t busy_budget, + struct pollfd *fds, struct xsk_socket *xsk) { - return xsk_ring_prod__needs_wakeup(q) | busy_budget; + /* we can assume a kernel >= 5.11 is in use if busy polling is enabled + * and thus we can safely use the recvfrom() syscall which is only + * supported for AF_XDP sockets in kernels >= 5.11. + */ + if (busy_budget) { + (void)recvfrom(xsk_socket__fd(xsk), NULL, 0, + MSG_DONTWAIT, NULL, NULL); + return; + } + + if (xsk_ring_prod__needs_wakeup(q)) + (void)poll(fds, 1, 1000); } static int tx_syscall_needed(struct xsk_ring_prod *q) @@ -52,10 +65,13 @@ tx_syscall_needed(struct xsk_ring_prod *q) return xsk_ring_prod__needs_wakeup(q); } #else -static int -rx_syscall_needed(struct xsk_ring_prod *q __rte_unused, uint32_t busy_budget) +static void +rx_syscall_handler(struct xsk_ring_prod *q __rte_unused, uint32_t busy_budget, + struct pollfd *fds __rte_unused, struct xsk_socket *xsk) { - return busy_budget; + if (busy_budget) + (void)recvfrom(xsk_socket__fd(xsk), NULL, 0, + MSG_DONTWAIT, NULL, NULL); } static int tx_syscall_needed(struct xsk_ring_prod *q __rte_unused) diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c index 8c6cd224a8..0c91a40c4a 100644 --- a/drivers/net/af_xdp/rte_eth_af_xdp.c +++ b/drivers/net/af_xdp/rte_eth_af_xdp.c @@ -5,7 +5,6 @@ #include <errno.h> #include <stdlib.h> #include <string.h> -#include <poll.h> #include <netinet/in.h> #include <net/if.h> #include <sys/socket.h> @@ -273,10 +272,8 @@ af_xdp_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) nb_pkts = xsk_ring_cons__peek(rx, nb_pkts, &idx_rx); if (nb_pkts == 0) { - if (rx_syscall_needed(&rxq->fq, rxq->busy_budget)) - (void)recvfrom(xsk_socket__fd(rxq->xsk), NULL, 0, - MSG_DONTWAIT, NULL, NULL); - + rx_syscall_handler(&rxq->fq, rxq->busy_budget, &rxq->fds[0], + rxq->xsk); return 0; } @@ -346,8 +343,7 @@ af_xdp_rx_cp(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) if (nb_pkts == 0) { #if defined(XDP_USE_NEED_WAKEUP) if (xsk_ring_prod__needs_wakeup(fq)) - (void)recvfrom(xsk_socket__fd(rxq->xsk), NULL, 0, - MSG_DONTWAIT, NULL, NULL); + (void)poll(rxq->fds, 1, 1000); #endif return 0; } -- 2.25.1