libbpf: add support for need_wakeup flag in AF_XDP part
authorMagnus Karlsson <magnus.karlsson@intel.com>
Wed, 14 Aug 2019 07:27:20 +0000 (09:27 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Sat, 17 Aug 2019 21:07:32 +0000 (23:07 +0200)
This commit adds support for the new need_wakeup flag in AF_XDP. The
xsk_socket__create function is updated to handle this and a new
function is introduced called xsk_ring_prod__needs_wakeup(). This
function can be used by the application to check if Rx and/or Tx
processing needs to be explicitly woken up.

Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
tools/include/uapi/linux/if_xdp.h
tools/lib/bpf/xsk.c
tools/lib/bpf/xsk.h

index faaa5ca2a11767a3cfd967661f21645799b95f9c..62b80d57b72a58eacecb46fe7b441ca6976e59f2 100644 (file)
 #define XDP_SHARED_UMEM        (1 << 0)
 #define XDP_COPY       (1 << 1) /* Force copy-mode */
 #define XDP_ZEROCOPY   (1 << 2) /* Force zero-copy mode */
+/* If this option is set, the driver might go sleep and in that case
+ * the XDP_RING_NEED_WAKEUP flag in the fill and/or Tx rings will be
+ * set. If it is set, the application need to explicitly wake up the
+ * driver with a poll() (Rx and Tx) or sendto() (Tx only). If you are
+ * running the driver and the application on the same core, you should
+ * use this option so that the kernel will yield to the user space
+ * application.
+ */
+#define XDP_USE_NEED_WAKEUP (1 << 3)
 
 struct sockaddr_xdp {
        __u16 sxdp_family;
@@ -25,10 +34,14 @@ struct sockaddr_xdp {
        __u32 sxdp_shared_umem_fd;
 };
 
+/* XDP_RING flags */
+#define XDP_RING_NEED_WAKEUP (1 << 0)
+
 struct xdp_ring_offset {
        __u64 producer;
        __u64 consumer;
        __u64 desc;
+       __u64 flags;
 };
 
 struct xdp_mmap_offsets {
index 680e63066cf39c7f3bd06cdf645b05065060728e..17e8d79c11a87d665c9ed627417339c8da168766 100644 (file)
@@ -224,6 +224,7 @@ int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size,
        fill->size = umem->config.fill_size;
        fill->producer = map + off.fr.producer;
        fill->consumer = map + off.fr.consumer;
+       fill->flags = map + off.fr.flags;
        fill->ring = map + off.fr.desc;
        fill->cached_cons = umem->config.fill_size;
 
@@ -241,6 +242,7 @@ int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size,
        comp->size = umem->config.comp_size;
        comp->producer = map + off.cr.producer;
        comp->consumer = map + off.cr.consumer;
+       comp->flags = map + off.cr.flags;
        comp->ring = map + off.cr.desc;
 
        *umem_ptr = umem;
@@ -564,6 +566,7 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
                rx->size = xsk->config.rx_size;
                rx->producer = rx_map + off.rx.producer;
                rx->consumer = rx_map + off.rx.consumer;
+               rx->flags = rx_map + off.rx.flags;
                rx->ring = rx_map + off.rx.desc;
        }
        xsk->rx = rx;
@@ -583,6 +586,7 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
                tx->size = xsk->config.tx_size;
                tx->producer = tx_map + off.tx.producer;
                tx->consumer = tx_map + off.tx.consumer;
+               tx->flags = tx_map + off.tx.flags;
                tx->ring = tx_map + off.tx.desc;
                tx->cached_cons = xsk->config.tx_size;
        }
index 833a6e60d065fc3128e052eccc693d454aba1a04..aa1d6122b7dba61ac9b1a1f4dec90544006f8569 100644 (file)
@@ -32,6 +32,7 @@ struct name { \
        __u32 *producer; \
        __u32 *consumer; \
        void *ring; \
+       __u32 *flags; \
 }
 
 DEFINE_XSK_RING(xsk_ring_prod);
@@ -76,6 +77,11 @@ xsk_ring_cons__rx_desc(const struct xsk_ring_cons *rx, __u32 idx)
        return &descs[idx & rx->mask];
 }
 
+static inline int xsk_ring_prod__needs_wakeup(const struct xsk_ring_prod *r)
+{
+       return *r->flags & XDP_RING_NEED_WAKEUP;
+}
+
 static inline __u32 xsk_prod_nb_free(struct xsk_ring_prod *r, __u32 nb)
 {
        __u32 free_entries = r->cached_cons - r->cached_prod;