Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libxdp: Use opts to create XDP socket #454

Merged
merged 1 commit into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion headers/xdp/xsk.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ struct xsk_umem_config {
* 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.
* Except for the fields mentioned above, no field can be set.
*/
struct xsk_umem_opts {
size_t sz;
Expand Down Expand Up @@ -249,6 +249,40 @@ struct xsk_socket_config {
__u16 bind_flags;
};

/*
* The following fields should not be NULL at the same time:
*
* @rx, @tx
* At least one traffic direction should be assigned for an xsk.
*
* The following fields are optional:
*
* @fill, @comp, @rx_size, @tx_size, @libxdp_flags, @xdp_flags,
* @bind_flags
* If a socket with exclusive ownership of a umem is going to be
* created, keep @fill and @comp unset. If the umem is to be shared
* with other sockets, set @fill and @comp to the corresponding
* fields of the umem.
* If the remaining fields are unset, they will be set to
* default value (see `xsk_set_xdp_socket_config()`).
*
* Except for the fields mentioned above, no field can be set.
*/
struct xsk_socket_opts {
size_t sz;
struct xsk_ring_cons *rx;
struct xsk_ring_prod *tx;
struct xsk_ring_prod *fill;
struct xsk_ring_cons *comp;
__u32 rx_size;
__u32 tx_size;
__u32 libxdp_flags;
__u32 xdp_flags;
__u16 bind_flags;
size_t :0;
};
#define xsk_socket_opts__last_field bind_flags

/* Set config to NULL to get the default configuration. */
int xsk_umem__create(struct xsk_umem **umem,
void *umem_area, __u64 size,
Expand Down Expand Up @@ -280,6 +314,11 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
struct xsk_ring_prod *fill,
struct xsk_ring_cons *comp,
const struct xsk_socket_config *config);
/* Newer version to create xsk by opts, recommended to use. */
struct xsk_socket *xsk_socket__create_opts(const char *ifname,
__u32 queue_id,
struct xsk_umem *umem,
struct xsk_socket_opts *opts);

/* Returns 0 for success and -EBUSY if the umem is still in use. */
int xsk_umem__delete(struct xsk_umem *umem);
Expand Down
1 change: 1 addition & 0 deletions lib/libxdp/libxdp.map
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@ LIBXDP_1.4.0 {

LIBXDP_1.5.0 {
xsk_umem__create_opts;
xsk_socket__create_opts;
} LIBXDP_1.4.0;
106 changes: 74 additions & 32 deletions lib/libxdp/xsk.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,25 +162,19 @@ static void xsk_set_umem_config(struct xsk_umem_config *cfg,
}

static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
const struct xsk_socket_config *usr_cfg)
const struct xsk_socket_opts *opts)
{
if (!usr_cfg) {
cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
cfg->tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
cfg->libbpf_flags = 0;
cfg->xdp_flags = 0;
cfg->bind_flags = 0;
return 0;
}
__u32 libxdp_flags;

if (usr_cfg->libbpf_flags & ~XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)
libxdp_flags = OPTS_GET(opts, libxdp_flags, 0);
if (libxdp_flags & ~XSK_LIBXDP_FLAGS__INHIBIT_PROG_LOAD)
return -EINVAL;

cfg->rx_size = usr_cfg->rx_size;
cfg->tx_size = usr_cfg->tx_size;
cfg->libbpf_flags = usr_cfg->libbpf_flags;
cfg->xdp_flags = usr_cfg->xdp_flags;
cfg->bind_flags = usr_cfg->bind_flags;
cfg->rx_size = OPTS_GET(opts, rx_size, 0) ?: XSK_RING_CONS__DEFAULT_NUM_DESCS;
cfg->tx_size = OPTS_GET(opts, tx_size, 0) ?: XSK_RING_PROD__DEFAULT_NUM_DESCS;
cfg->libxdp_flags = libxdp_flags;
cfg->xdp_flags = OPTS_GET(opts, xdp_flags, 0);
cfg->bind_flags = OPTS_GET(opts, bind_flags, 0);

return 0;
}
Expand Down Expand Up @@ -1052,34 +1046,47 @@ int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd)
return res;
}

int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
const char *ifname,
__u32 queue_id, struct xsk_umem *umem,
struct xsk_ring_cons *rx,
struct xsk_ring_prod *tx,
struct xsk_ring_prod *fill,
struct xsk_ring_cons *comp,
const struct xsk_socket_config *usr_config)
struct xsk_socket *xsk_socket__create_opts(const char *ifname,
__u32 queue_id,
struct xsk_umem *umem,
struct xsk_socket_opts *opts)
{
bool rx_setup_done = false, tx_setup_done = false;
void *rx_map = NULL, *tx_map = NULL;
struct sockaddr_xdp sxdp = {};
struct xdp_mmap_offsets off;
struct xsk_ring_prod *fill;
struct xsk_ring_cons *comp;
struct xsk_ring_cons *rx;
struct xsk_ring_prod *tx;
struct xsk_socket *xsk;
struct xsk_ctx *ctx;
int err, ifindex;
__u64 netns_cookie;
socklen_t optlen;
bool unmap;

if (!umem || !xsk_ptr || !(rx || tx))
return -EFAULT;
if (!OPTS_VALID(opts, xsk_socket_opts)) {
err = -EINVAL;
goto err;
}
rx = OPTS_GET(opts, rx, NULL);
tx = OPTS_GET(opts, tx, NULL);
fill = OPTS_GET(opts, fill, umem->fill_save);
comp = OPTS_GET(opts, comp, umem->comp_save);

if (!umem || !(rx || tx)) {
err = -EFAULT;
goto err;
}

xsk = calloc(1, sizeof(*xsk));
if (!xsk)
return -ENOMEM;
if (!xsk) {
err = -ENOMEM;
goto err;
}

err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
err = xsk_set_xdp_socket_config(&xsk->config, opts);
if (err)
goto out_xsk_alloc;

Expand Down Expand Up @@ -1218,16 +1225,15 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
goto out_mmap_tx;
}

if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
if (!(xsk->config.libxdp_flags & XSK_LIBXDP_FLAGS__INHIBIT_PROG_LOAD)) {
err = __xsk_setup_xdp_prog(xsk, NULL);
if (err)
goto out_mmap_tx;
}

*xsk_ptr = xsk;
umem->fill_save = NULL;
umem->comp_save = NULL;
return 0;
return xsk;

out_mmap_tx:
if (tx)
Expand All @@ -1245,7 +1251,43 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
close(xsk->fd);
out_xsk_alloc:
free(xsk);
return err;
err:
return libxdp_err_ptr(err, true);
}

int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
const char *ifname,
__u32 queue_id, struct xsk_umem *umem,
struct xsk_ring_cons *rx,
struct xsk_ring_prod *tx,
struct xsk_ring_prod *fill,
struct xsk_ring_cons *comp,
const struct xsk_socket_config *usr_config)
{
struct xsk_socket *xsk;

if (!xsk_ptr)
return -EFAULT;

DECLARE_LIBXDP_OPTS(xsk_socket_opts, opts,
.rx = rx,
.tx = tx,
.fill = fill,
.comp = comp,
);
if (usr_config) {
opts.rx_size = usr_config->rx_size;
opts.tx_size= usr_config->tx_size;
opts.libxdp_flags = usr_config->libxdp_flags;
opts.xdp_flags = usr_config->xdp_flags;
opts.bind_flags = usr_config->bind_flags;
}
xsk = xsk_socket__create_opts(ifname, queue_id, umem, &opts);
if (!xsk)
return errno;

*xsk_ptr = xsk;
return 0;
}

int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
Expand Down