summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Karlsson <magnus.karlsson@intel.com>2019-11-07 18:47:36 +0100
committerAlexei Starovoitov <ast@kernel.org>2019-11-10 19:30:45 -0800
commitcbf07409d0c2afad7bb54be039490bffad8bc737 (patch)
tree133661eb096da2d2853d5900f0aacb9850879ad4
parent472aeb386eda3b73bbd38a2ec8c928708f77d7ee (diff)
downloadlinux-cbf07409d0c2afad7bb54be039490bffad8bc737.tar.bz2
libbpf: Support XDP_SHARED_UMEM with external XDP program
Add support in libbpf to create multiple sockets that share a single umem. Note that an external XDP program need to be supplied that routes the incoming traffic to the desired sockets. So you need to supply the libbpf_flag XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD and load your own XDP program. Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: William Tu <u9012063@gmail.com> Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com> Link: https://lore.kernel.org/bpf/1573148860-30254-2-git-send-email-magnus.karlsson@intel.com
-rw-r--r--tools/lib/bpf/xsk.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
index 86c1b61017f6..8ebd810931ab 100644
--- a/tools/lib/bpf/xsk.c
+++ b/tools/lib/bpf/xsk.c
@@ -586,15 +586,21 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
if (!umem || !xsk_ptr || !rx || !tx)
return -EFAULT;
- if (umem->refcount) {
- pr_warn("Error: shared umems not supported by libbpf.\n");
- return -EBUSY;
- }
-
xsk = calloc(1, sizeof(*xsk));
if (!xsk)
return -ENOMEM;
+ err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
+ if (err)
+ goto out_xsk_alloc;
+
+ if (umem->refcount &&
+ !(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
+ pr_warn("Error: shared umems not supported by libbpf supplied XDP program.\n");
+ err = -EBUSY;
+ goto out_xsk_alloc;
+ }
+
if (umem->refcount++ > 0) {
xsk->fd = socket(AF_XDP, SOCK_RAW, 0);
if (xsk->fd < 0) {
@@ -616,10 +622,6 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
memcpy(xsk->ifname, ifname, IFNAMSIZ - 1);
xsk->ifname[IFNAMSIZ - 1] = '\0';
- err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
- if (err)
- goto out_socket;
-
if (rx) {
err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,
&xsk->config.rx_size,
@@ -687,7 +689,12 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
sxdp.sxdp_family = PF_XDP;
sxdp.sxdp_ifindex = xsk->ifindex;
sxdp.sxdp_queue_id = xsk->queue_id;
- sxdp.sxdp_flags = xsk->config.bind_flags;
+ if (umem->refcount > 1) {
+ sxdp.sxdp_flags = XDP_SHARED_UMEM;
+ sxdp.sxdp_shared_umem_fd = umem->fd;
+ } else {
+ sxdp.sxdp_flags = xsk->config.bind_flags;
+ }
err = bind(xsk->fd, (struct sockaddr *)&sxdp, sizeof(sxdp));
if (err) {