xsk: introduce XSK_USE_SG bind flag for xsk socket
authorTirthendu Sarkar <tirthendu.sarkar@intel.com>
Wed, 19 Jul 2023 13:23:59 +0000 (15:23 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 19 Jul 2023 16:56:48 +0000 (09:56 -0700)
As of now xsk core drops any xdp_buff with data size greater than the
xsk frame_size as set by the af_xdp application. With multi-buffer
support introduced in the next patch xsk core can now split those
buffers into multiple descriptors provided the af_xdp application can
handle them. Such capability of the application needs to be independent
of the xdp_prog's frag support capability since there are cases where
even a single xdp_buffer may need to be split into multiple descriptors
owing to a smaller xsk frame size.

For e.g., with NIC rx_buffer size set to 4kB, a 3kB packet will
constitute of a single buffer and so will be sent as such to AF_XDP layer
irrespective of 'xdp.frags' capability of the XDP program. Now if the xsk
frame size is set to 2kB by the AF_XDP application, then the packet will
need to be split into 2 descriptors if AF_XDP application can handle
multi-buffer, else it needs to be dropped.

Applications can now advertise their frag handling capability to xsk core
so that xsk core can decide if it should drop or split xdp_buffs that
exceed xsk frame size. This is done using a new 'XSK_USE_SG' bind flag
for the xdp socket.

Signed-off-by: Tirthendu Sarkar <tirthendu.sarkar@intel.com>
Link: https://lore.kernel.org/r/20230719132421.584801-3-maciej.fijalkowski@intel.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/net/xdp_sock.h
include/uapi/linux/if_xdp.h
net/xdp/xsk.c

index e96a1151ec759f35ca280beb24fecfe1e660a9e1..36b0411a0d1b39d2fd09fd3d2631a6d234c0785f 100644 (file)
@@ -52,6 +52,7 @@ struct xdp_sock {
        struct xsk_buff_pool *pool;
        u16 queue_id;
        bool zc;
+       bool sg;
        enum {
                XSK_READY = 0,
                XSK_BOUND,
index 434f313dc26c72ad00991cf6f7f737f651cf9bc1..8d48863472b922c290ecb36f935b4a35dde41563 100644 (file)
  * application.
  */
 #define XDP_USE_NEED_WAKEUP (1 << 3)
+/* By setting this option, userspace application indicates that it can
+ * handle multiple descriptors per packet thus enabling AF_XDP to split
+ * multi-buffer XDP frames into multiple Rx descriptors. Without this set
+ * such frames will be dropped.
+ */
+#define XDP_USE_SG     (1 << 4)
 
 /* Flags for xsk_umem_config flags */
 #define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
index 914a80cd55d34a02a3a182013048127eee97c2aa..7b709e4e7ec46a78e847119369008515c3173a70 100644 (file)
@@ -897,7 +897,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 
        flags = sxdp->sxdp_flags;
        if (flags & ~(XDP_SHARED_UMEM | XDP_COPY | XDP_ZEROCOPY |
-                     XDP_USE_NEED_WAKEUP))
+                     XDP_USE_NEED_WAKEUP | XDP_USE_SG))
                return -EINVAL;
 
        bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
@@ -929,7 +929,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
                struct socket *sock;
 
                if ((flags & XDP_COPY) || (flags & XDP_ZEROCOPY) ||
-                   (flags & XDP_USE_NEED_WAKEUP)) {
+                   (flags & XDP_USE_NEED_WAKEUP) || (flags & XDP_USE_SG)) {
                        /* Cannot specify flags for shared sockets. */
                        err = -EINVAL;
                        goto out_unlock;
@@ -1028,6 +1028,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 
        xs->dev = dev;
        xs->zc = xs->umem->zc;
+       xs->sg = !!(flags & XDP_USE_SG);
        xs->queue_id = qid;
        xp_add_xsk(xs->pool, xs);