Skip to content

Commit

Permalink
libxdp: Add tx_metadata_len/xsk_umem__create_opts() to support AF_XDP…
Browse files Browse the repository at this point in the history
… 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 <[email protected]>
  • Loading branch information
tacslon committed Nov 7, 2024
1 parent cc7a112 commit 0e7192b
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 35 deletions.
1 change: 1 addition & 0 deletions headers/linux/if_xdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct xdp_umem_reg {
__u32 chunk_size;
__u32 headroom;
__u32 flags;
__u32 tx_metadata_len;
};

struct xdp_statistics {
Expand Down
32 changes: 32 additions & 0 deletions headers/xdp/xsk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions lib/libxdp/libxdp.map
Original file line number Diff line number Diff line change
Expand Up @@ -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;
113 changes: 78 additions & 35 deletions lib/libxdp/xsk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -306,24 +297,38 @@ static int xsk_create_umem_rings(struct xsk_umem *umem, int fd,
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) {
Expand All @@ -333,16 +338,21 @@ 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;
mr.len = size;
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;
Expand All @@ -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,
Expand Down

0 comments on commit 0e7192b

Please sign in to comment.