From 44b5e00692dbce7b2a5eab5d56c237c967b8f03f Mon Sep 17 00:00:00 2001 From: Muyang Tian Date: Tue, 22 Oct 2024 19:18:45 +0800 Subject: [PATCH] libxdp: Add tx_metadata_len/xsk_umem__create_opts() to support AF_XDP Tx metadata Add tx_metadata_len to support AF_XDP Tx metadata. Also, add xsk_umem__create_opts() to provide a new way to create umem, like xdp_program__create(). Another 2 functions to create umem(xsk_umem__create() and xsk_umem__create_with_fd()) calls xsk_umem__create_opts() internally, while outside callers do not know this change. Signed-off-by: Muyang Tian --- headers/linux/if_xdp.h | 1 + headers/xdp/xsk.h | 32 ++++++++++++ lib/libxdp/libxdp.map | 4 ++ lib/libxdp/xsk.c | 113 ++++++++++++++++++++++++++++------------- 4 files changed, 115 insertions(+), 35 deletions(-) diff --git a/headers/linux/if_xdp.h b/headers/linux/if_xdp.h index a78a809..c6569e9 100644 --- a/headers/linux/if_xdp.h +++ b/headers/linux/if_xdp.h @@ -70,6 +70,7 @@ struct xdp_umem_reg { __u32 chunk_size; __u32 headroom; __u32 flags; + __u32 tx_metadata_len; }; struct xdp_statistics { diff --git a/headers/xdp/xsk.h b/headers/xdp/xsk.h index 0b4fdca..55aab26 100644 --- a/headers/xdp/xsk.h +++ b/headers/xdp/xsk.h @@ -194,6 +194,7 @@ int xsk_socket__fd(const struct xsk_socket *xsk); #define XSK_UMEM__DEFAULT_FRAME_SIZE (1 << XSK_UMEM__DEFAULT_FRAME_SHIFT) #define XSK_UMEM__DEFAULT_FRAME_HEADROOM 0 #define XSK_UMEM__DEFAULT_FLAGS 0 +#define XSK_UMEM__DEFAULT_TX_METADATA_LEN 0 struct xsk_umem_config { __u32 fill_size; @@ -203,6 +204,31 @@ struct xsk_umem_config { __u32 flags; }; +/* The following fields are optional: + * + * @fd, @size, @fill_size, @comp_size, @frame_size, @frame_headroom, + * @flags, @tx_metadata_len + * If @fd is unset, a new sockfd will be created. + * If @size is unset, @umem_area must be page-aligned. + * If the remaining fields are unset, they will be set to + * default value (see `xsk_set_umem_config()`). + * + * Except for the fields mentioned above, none field can be set. + */ +struct xsk_umem_opts { + size_t sz; + int fd; + __u64 size; + __u32 fill_size; + __u32 comp_size; + __u32 frame_size; + __u32 frame_headroom; + __u32 flags; + __u32 tx_metadata_len; + size_t :0; +}; +#define xsk_umem_opts__last_field tx_metadata_len + int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd); int xsk_socket__update_xskmap(struct xsk_socket *xsk, int xsks_map_fd); @@ -234,6 +260,12 @@ int xsk_umem__create_with_fd(struct xsk_umem **umem, struct xsk_ring_prod *fill, struct xsk_ring_cons *comp, const struct xsk_umem_config *config); +/* Newer version to create umem by opts, recommended to use. */ +struct xsk_umem *xsk_umem__create_opts(void *umem_area, + struct xsk_ring_prod *fill, + struct xsk_ring_cons *comp, + struct xsk_umem_opts *opts); + int xsk_socket__create(struct xsk_socket **xsk, const char *ifname, __u32 queue_id, struct xsk_umem *umem, diff --git a/lib/libxdp/libxdp.map b/lib/libxdp/libxdp.map index 51f78b4..61f686e 100644 --- a/lib/libxdp/libxdp.map +++ b/lib/libxdp/libxdp.map @@ -80,3 +80,7 @@ LIBXDP_1.3.0 { LIBXDP_1.4.0 { xsk_umem__create_with_fd; } LIBXDP_1.3.0; + +LIBXDP_1.5.0 { + xsk_umem__create_opts; +} LIBXDP_1.4.0; diff --git a/lib/libxdp/xsk.c b/lib/libxdp/xsk.c index b3527fb..958a2b0 100644 --- a/lib/libxdp/xsk.c +++ b/lib/libxdp/xsk.c @@ -152,22 +152,13 @@ static bool xsk_page_aligned(void *buffer) } static void xsk_set_umem_config(struct xsk_umem_config *cfg, - const struct xsk_umem_config *usr_cfg) + const struct xsk_umem_opts *opts) { - if (!usr_cfg) { - cfg->fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; - cfg->comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; - cfg->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE; - cfg->frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM; - cfg->flags = XSK_UMEM__DEFAULT_FLAGS; - return; - } - - cfg->fill_size = usr_cfg->fill_size; - cfg->comp_size = usr_cfg->comp_size; - cfg->frame_size = usr_cfg->frame_size; - cfg->frame_headroom = usr_cfg->frame_headroom; - cfg->flags = usr_cfg->flags; + cfg->fill_size = OPTS_GET(opts, fill_size, XSK_RING_PROD__DEFAULT_NUM_DESCS); + cfg->comp_size = OPTS_GET(opts, comp_size, XSK_RING_CONS__DEFAULT_NUM_DESCS); + cfg->frame_size = OPTS_GET(opts, frame_size, XSK_UMEM__DEFAULT_FRAME_SIZE); + cfg->frame_headroom = OPTS_GET(opts, frame_headroom, XSK_UMEM__DEFAULT_FRAME_HEADROOM); + cfg->flags = OPTS_GET(opts, flags, XSK_UMEM__DEFAULT_FLAGS); } static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg, @@ -306,24 +297,38 @@ out_mmap: return err; } -int xsk_umem__create_with_fd(struct xsk_umem **umem_ptr, int fd, - void *umem_area, __u64 size, - struct xsk_ring_prod *fill, - struct xsk_ring_cons *comp, - const struct xsk_umem_config *usr_config) -{ +struct xsk_umem *xsk_umem__create_opts(void *umem_area, + struct xsk_ring_prod *fill, + struct xsk_ring_cons *comp, + struct xsk_umem_opts *opts) { struct xdp_umem_reg mr; struct xsk_umem *umem; - int err; + size_t mr_size; + int err, fd; + __u64 size; + + if (!umem_area || !fill || !comp) { + err = -EFAULT; + goto err; + } - if (!umem_area || !umem_ptr || !fill || !comp) - return -EFAULT; - if (!size && !xsk_page_aligned(umem_area)) - return -EINVAL; + if (!OPTS_VALID(opts, xsk_umem_opts)) { + err = -EINVAL; + goto err; + } + fd = OPTS_GET(opts, fd, -1); + size = OPTS_GET(opts, size, 0); + + if (!size && !xsk_page_aligned(umem_area)) { + err = -EINVAL; + goto err; + } umem = calloc(1, sizeof(*umem)); - if (!umem) - return -ENOMEM; + if (!umem) { + err = -ENOMEM; + goto err; + } umem->fd = fd < 0 ? socket(AF_XDP, SOCK_RAW, 0) : fd; if (umem->fd < 0) { @@ -333,7 +338,7 @@ int xsk_umem__create_with_fd(struct xsk_umem **umem_ptr, int fd, umem->umem_area = umem_area; INIT_LIST_HEAD(&umem->ctx_list); - xsk_set_umem_config(&umem->config, usr_config); + xsk_set_umem_config(&umem->config, opts); memset(&mr, 0, sizeof(mr)); mr.addr = (uintptr_t)umem_area; @@ -341,8 +346,13 @@ int xsk_umem__create_with_fd(struct xsk_umem **umem_ptr, int fd, mr.chunk_size = umem->config.frame_size; mr.headroom = umem->config.frame_headroom; mr.flags = umem->config.flags; - - err = setsockopt(umem->fd, SOL_XDP, XDP_UMEM_REG, &mr, sizeof(mr)); + mr.tx_metadata_len = OPTS_GET(opts, tx_metadata_len, XSK_UMEM__DEFAULT_TX_METADATA_LEN); + + mr_size = sizeof(mr); + /* Older kernels don't support tx_metadata_len, skip if we are not setting a value */ + if(!mr.tx_metadata_len) + mr_size = offsetof(struct xdp_umem_reg, tx_metadata_len); + err = setsockopt(umem->fd, SOL_XDP, XDP_UMEM_REG, &mr, mr_size); if (err) { err = -errno; goto out_socket; @@ -354,14 +364,47 @@ int xsk_umem__create_with_fd(struct xsk_umem **umem_ptr, int fd, umem->fill_save = fill; umem->comp_save = comp; - *umem_ptr = umem; - return 0; - + return umem; out_socket: close(umem->fd); out_umem_alloc: free(umem); - return err; +err: + return libxdp_err_ptr(err, true); +} + +int xsk_umem__create_with_fd(struct xsk_umem **umem_ptr, int fd, + void *umem_area, __u64 size, + struct xsk_ring_prod *fill, + struct xsk_ring_cons *comp, + const struct xsk_umem_config *usr_config) +{ + struct xsk_umem *umem; + + if(!umem_ptr) + return -EFAULT; + + DECLARE_LIBXDP_OPTS(xsk_umem_opts, opts, + .fd = fd, + .size = size, + .fill_size = usr_config ? usr_config->fill_size + : XSK_RING_PROD__DEFAULT_NUM_DESCS, + .comp_size = usr_config ? usr_config->comp_size + : XSK_RING_CONS__DEFAULT_NUM_DESCS, + .frame_size = usr_config ? usr_config->frame_size + : XSK_UMEM__DEFAULT_FRAME_SIZE, + .frame_headroom = usr_config ? usr_config->frame_headroom + : XSK_UMEM__DEFAULT_FRAME_HEADROOM, + .flags = usr_config ? usr_config->flags + : XSK_UMEM__DEFAULT_FLAGS, + ); + + umem = xsk_umem__create_opts(umem_area, fill, comp, &opts); + if(!umem) + return errno; + + *umem_ptr = umem; + return 0; } int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, -- 2.41.0