Note that MTU of AF_XDP PMD is limited due to XDP lacks support for
fragmentation.
+AF_XDP PMD enables need_wakeup flag by default if it is supported. This
+need_wakeup feature is used to support executing application and driver on the
+same core efficiently. This feature not only has a large positive performance
+impact for the one core case, but also does not degrade 2 core performance and
+actually improves it for Tx heavy workloads.
+
Options
-------
User can install libbpf via `make install_lib` && `make install_headers` in
<kernel src tree>/tools/lib/bpf;
* A Kernel bound interface to attach to;
+* For need_wakeup feature, it requires kernel version later than v5.3-rc1;
Set up an af_xdp interface
-----------------------------
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <poll.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/socket.h>
struct rx_stats stats;
struct pkt_tx_queue *pair;
+ struct pollfd fds[1];
int xsk_queue_idx;
};
return 0;
rcvd = xsk_ring_cons__peek(rx, nb_pkts, &idx_rx);
- if (rcvd == 0)
+ if (rcvd == 0) {
+#if defined(XDP_USE_NEED_WAKEUP)
+ if (xsk_ring_prod__needs_wakeup(fq))
+ (void)poll(rxq->fds, 1, 1000);
+#endif
+
goto out;
+ }
if (xsk_prod_nb_free(fq, free_thresh) >= free_thresh)
(void)reserve_fill_queue(umem, ETH_AF_XDP_RX_BATCH_SIZE);
{
struct xsk_umem_info *umem = txq->pair->umem;
- while (send(xsk_socket__fd(txq->pair->xsk), NULL,
- 0, MSG_DONTWAIT) < 0) {
- /* some thing unexpected */
- if (errno != EBUSY && errno != EAGAIN && errno != EINTR)
- break;
-
- /* pull from completion queue to leave more space */
- if (errno == EAGAIN)
- pull_umem_cq(umem, ETH_AF_XDP_TX_BATCH_SIZE);
- }
+#if defined(XDP_USE_NEED_WAKEUP)
+ if (xsk_ring_prod__needs_wakeup(&txq->tx))
+#endif
+ while (send(xsk_socket__fd(txq->pair->xsk), NULL,
+ 0, MSG_DONTWAIT) < 0) {
+ /* some thing unexpected */
+ if (errno != EBUSY && errno != EAGAIN && errno != EINTR)
+ break;
+
+ /* pull from completion queue to leave more space */
+ if (errno == EAGAIN)
+ pull_umem_cq(umem, ETH_AF_XDP_TX_BATCH_SIZE);
+ }
pull_umem_cq(umem, ETH_AF_XDP_TX_BATCH_SIZE);
}
cfg.libbpf_flags = 0;
cfg.xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
cfg.bind_flags = 0;
+
+#if defined(XDP_USE_NEED_WAKEUP)
+ cfg.bind_flags |= XDP_USE_NEED_WAKEUP;
+#endif
+
ret = xsk_socket__create(&rxq->xsk, internals->if_name,
rxq->xsk_queue_idx, rxq->umem->umem, &rxq->rx,
&txq->tx, &cfg);
goto err;
}
+ rxq->fds[0].fd = xsk_socket__fd(rxq->xsk);
+ rxq->fds[0].events = POLLIN;
+
rxq->umem->pmd_zc = internals->pmd_zc;
dev->data->rx_queues[rx_queue_id] = rxq;