ffbb588724d8fc79bae9fd7ff8182b9eb649808f
[sfrench/cifs-2.6.git] / tools / lib / bpf / xsk.c
1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2
3 /*
4  * AF_XDP user-space access library.
5  *
6  * Copyright(c) 2018 - 2019 Intel Corporation.
7  *
8  * Author(s): Magnus Karlsson <magnus.karlsson@intel.com>
9  */
10
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <arpa/inet.h>
16 #include <asm/barrier.h>
17 #include <linux/compiler.h>
18 #include <linux/ethtool.h>
19 #include <linux/filter.h>
20 #include <linux/if_ether.h>
21 #include <linux/if_packet.h>
22 #include <linux/if_xdp.h>
23 #include <linux/kernel.h>
24 #include <linux/list.h>
25 #include <linux/sockios.h>
26 #include <net/if.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <sys/socket.h>
30 #include <sys/types.h>
31
32 #include "bpf.h"
33 #include "libbpf.h"
34 #include "libbpf_internal.h"
35 #include "xsk.h"
36
37 #ifndef SOL_XDP
38  #define SOL_XDP 283
39 #endif
40
41 #ifndef AF_XDP
42  #define AF_XDP 44
43 #endif
44
45 #ifndef PF_XDP
46  #define PF_XDP AF_XDP
47 #endif
48
49 enum xsk_prog {
50         XSK_PROG_FALLBACK,
51         XSK_PROG_REDIRECT_FLAGS,
52 };
53
54 struct xsk_umem {
55         struct xsk_ring_prod *fill_save;
56         struct xsk_ring_cons *comp_save;
57         char *umem_area;
58         struct xsk_umem_config config;
59         int fd;
60         int refcount;
61         struct list_head ctx_list;
62 };
63
64 struct xsk_ctx {
65         struct xsk_ring_prod *fill;
66         struct xsk_ring_cons *comp;
67         __u32 queue_id;
68         struct xsk_umem *umem;
69         int refcount;
70         int ifindex;
71         struct list_head list;
72         int prog_fd;
73         int xsks_map_fd;
74         char ifname[IFNAMSIZ];
75 };
76
77 struct xsk_socket {
78         struct xsk_ring_cons *rx;
79         struct xsk_ring_prod *tx;
80         __u64 outstanding_tx;
81         struct xsk_ctx *ctx;
82         struct xsk_socket_config config;
83         int fd;
84 };
85
86 struct xsk_nl_info {
87         bool xdp_prog_attached;
88         int ifindex;
89         int fd;
90 };
91
92 /* Up until and including Linux 5.3 */
93 struct xdp_ring_offset_v1 {
94         __u64 producer;
95         __u64 consumer;
96         __u64 desc;
97 };
98
99 /* Up until and including Linux 5.3 */
100 struct xdp_mmap_offsets_v1 {
101         struct xdp_ring_offset_v1 rx;
102         struct xdp_ring_offset_v1 tx;
103         struct xdp_ring_offset_v1 fr;
104         struct xdp_ring_offset_v1 cr;
105 };
106
107 int xsk_umem__fd(const struct xsk_umem *umem)
108 {
109         return umem ? umem->fd : -EINVAL;
110 }
111
112 int xsk_socket__fd(const struct xsk_socket *xsk)
113 {
114         return xsk ? xsk->fd : -EINVAL;
115 }
116
117 static bool xsk_page_aligned(void *buffer)
118 {
119         unsigned long addr = (unsigned long)buffer;
120
121         return !(addr & (getpagesize() - 1));
122 }
123
124 static void xsk_set_umem_config(struct xsk_umem_config *cfg,
125                                 const struct xsk_umem_config *usr_cfg)
126 {
127         if (!usr_cfg) {
128                 cfg->fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
129                 cfg->comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
130                 cfg->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
131                 cfg->frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM;
132                 cfg->flags = XSK_UMEM__DEFAULT_FLAGS;
133                 return;
134         }
135
136         cfg->fill_size = usr_cfg->fill_size;
137         cfg->comp_size = usr_cfg->comp_size;
138         cfg->frame_size = usr_cfg->frame_size;
139         cfg->frame_headroom = usr_cfg->frame_headroom;
140         cfg->flags = usr_cfg->flags;
141 }
142
143 static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
144                                      const struct xsk_socket_config *usr_cfg)
145 {
146         if (!usr_cfg) {
147                 cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
148                 cfg->tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
149                 cfg->libbpf_flags = 0;
150                 cfg->xdp_flags = 0;
151                 cfg->bind_flags = 0;
152                 return 0;
153         }
154
155         if (usr_cfg->libbpf_flags & ~XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)
156                 return -EINVAL;
157
158         cfg->rx_size = usr_cfg->rx_size;
159         cfg->tx_size = usr_cfg->tx_size;
160         cfg->libbpf_flags = usr_cfg->libbpf_flags;
161         cfg->xdp_flags = usr_cfg->xdp_flags;
162         cfg->bind_flags = usr_cfg->bind_flags;
163
164         return 0;
165 }
166
167 static void xsk_mmap_offsets_v1(struct xdp_mmap_offsets *off)
168 {
169         struct xdp_mmap_offsets_v1 off_v1;
170
171         /* getsockopt on a kernel <= 5.3 has no flags fields.
172          * Copy over the offsets to the correct places in the >=5.4 format
173          * and put the flags where they would have been on that kernel.
174          */
175         memcpy(&off_v1, off, sizeof(off_v1));
176
177         off->rx.producer = off_v1.rx.producer;
178         off->rx.consumer = off_v1.rx.consumer;
179         off->rx.desc = off_v1.rx.desc;
180         off->rx.flags = off_v1.rx.consumer + sizeof(__u32);
181
182         off->tx.producer = off_v1.tx.producer;
183         off->tx.consumer = off_v1.tx.consumer;
184         off->tx.desc = off_v1.tx.desc;
185         off->tx.flags = off_v1.tx.consumer + sizeof(__u32);
186
187         off->fr.producer = off_v1.fr.producer;
188         off->fr.consumer = off_v1.fr.consumer;
189         off->fr.desc = off_v1.fr.desc;
190         off->fr.flags = off_v1.fr.consumer + sizeof(__u32);
191
192         off->cr.producer = off_v1.cr.producer;
193         off->cr.consumer = off_v1.cr.consumer;
194         off->cr.desc = off_v1.cr.desc;
195         off->cr.flags = off_v1.cr.consumer + sizeof(__u32);
196 }
197
198 static int xsk_get_mmap_offsets(int fd, struct xdp_mmap_offsets *off)
199 {
200         socklen_t optlen;
201         int err;
202
203         optlen = sizeof(*off);
204         err = getsockopt(fd, SOL_XDP, XDP_MMAP_OFFSETS, off, &optlen);
205         if (err)
206                 return err;
207
208         if (optlen == sizeof(*off))
209                 return 0;
210
211         if (optlen == sizeof(struct xdp_mmap_offsets_v1)) {
212                 xsk_mmap_offsets_v1(off);
213                 return 0;
214         }
215
216         return -EINVAL;
217 }
218
219 static int xsk_create_umem_rings(struct xsk_umem *umem, int fd,
220                                  struct xsk_ring_prod *fill,
221                                  struct xsk_ring_cons *comp)
222 {
223         struct xdp_mmap_offsets off;
224         void *map;
225         int err;
226
227         err = setsockopt(fd, SOL_XDP, XDP_UMEM_FILL_RING,
228                          &umem->config.fill_size,
229                          sizeof(umem->config.fill_size));
230         if (err)
231                 return -errno;
232
233         err = setsockopt(fd, SOL_XDP, XDP_UMEM_COMPLETION_RING,
234                          &umem->config.comp_size,
235                          sizeof(umem->config.comp_size));
236         if (err)
237                 return -errno;
238
239         err = xsk_get_mmap_offsets(fd, &off);
240         if (err)
241                 return -errno;
242
243         map = mmap(NULL, off.fr.desc + umem->config.fill_size * sizeof(__u64),
244                    PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd,
245                    XDP_UMEM_PGOFF_FILL_RING);
246         if (map == MAP_FAILED)
247                 return -errno;
248
249         fill->mask = umem->config.fill_size - 1;
250         fill->size = umem->config.fill_size;
251         fill->producer = map + off.fr.producer;
252         fill->consumer = map + off.fr.consumer;
253         fill->flags = map + off.fr.flags;
254         fill->ring = map + off.fr.desc;
255         fill->cached_cons = umem->config.fill_size;
256
257         map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64),
258                    PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd,
259                    XDP_UMEM_PGOFF_COMPLETION_RING);
260         if (map == MAP_FAILED) {
261                 err = -errno;
262                 goto out_mmap;
263         }
264
265         comp->mask = umem->config.comp_size - 1;
266         comp->size = umem->config.comp_size;
267         comp->producer = map + off.cr.producer;
268         comp->consumer = map + off.cr.consumer;
269         comp->flags = map + off.cr.flags;
270         comp->ring = map + off.cr.desc;
271
272         return 0;
273
274 out_mmap:
275         munmap(map, off.fr.desc + umem->config.fill_size * sizeof(__u64));
276         return err;
277 }
278
279 int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
280                             __u64 size, struct xsk_ring_prod *fill,
281                             struct xsk_ring_cons *comp,
282                             const struct xsk_umem_config *usr_config)
283 {
284         struct xdp_umem_reg mr;
285         struct xsk_umem *umem;
286         int err;
287
288         if (!umem_area || !umem_ptr || !fill || !comp)
289                 return -EFAULT;
290         if (!size && !xsk_page_aligned(umem_area))
291                 return -EINVAL;
292
293         umem = calloc(1, sizeof(*umem));
294         if (!umem)
295                 return -ENOMEM;
296
297         umem->fd = socket(AF_XDP, SOCK_RAW, 0);
298         if (umem->fd < 0) {
299                 err = -errno;
300                 goto out_umem_alloc;
301         }
302
303         umem->umem_area = umem_area;
304         INIT_LIST_HEAD(&umem->ctx_list);
305         xsk_set_umem_config(&umem->config, usr_config);
306
307         memset(&mr, 0, sizeof(mr));
308         mr.addr = (uintptr_t)umem_area;
309         mr.len = size;
310         mr.chunk_size = umem->config.frame_size;
311         mr.headroom = umem->config.frame_headroom;
312         mr.flags = umem->config.flags;
313
314         err = setsockopt(umem->fd, SOL_XDP, XDP_UMEM_REG, &mr, sizeof(mr));
315         if (err) {
316                 err = -errno;
317                 goto out_socket;
318         }
319
320         err = xsk_create_umem_rings(umem, umem->fd, fill, comp);
321         if (err)
322                 goto out_socket;
323
324         umem->fill_save = fill;
325         umem->comp_save = comp;
326         *umem_ptr = umem;
327         return 0;
328
329 out_socket:
330         close(umem->fd);
331 out_umem_alloc:
332         free(umem);
333         return err;
334 }
335
336 struct xsk_umem_config_v1 {
337         __u32 fill_size;
338         __u32 comp_size;
339         __u32 frame_size;
340         __u32 frame_headroom;
341 };
342
343 int xsk_umem__create_v0_0_2(struct xsk_umem **umem_ptr, void *umem_area,
344                             __u64 size, struct xsk_ring_prod *fill,
345                             struct xsk_ring_cons *comp,
346                             const struct xsk_umem_config *usr_config)
347 {
348         struct xsk_umem_config config;
349
350         memcpy(&config, usr_config, sizeof(struct xsk_umem_config_v1));
351         config.flags = 0;
352
353         return xsk_umem__create_v0_0_4(umem_ptr, umem_area, size, fill, comp,
354                                         &config);
355 }
356 COMPAT_VERSION(xsk_umem__create_v0_0_2, xsk_umem__create, LIBBPF_0.0.2)
357 DEFAULT_VERSION(xsk_umem__create_v0_0_4, xsk_umem__create, LIBBPF_0.0.4)
358
359 static enum xsk_prog get_xsk_prog(void)
360 {
361         enum xsk_prog detected = XSK_PROG_FALLBACK;
362         struct bpf_load_program_attr prog_attr;
363         struct bpf_create_map_attr map_attr;
364         __u32 size_out, retval, duration;
365         char data_in = 0, data_out;
366         struct bpf_insn insns[] = {
367                 BPF_LD_MAP_FD(BPF_REG_1, 0),
368                 BPF_MOV64_IMM(BPF_REG_2, 0),
369                 BPF_MOV64_IMM(BPF_REG_3, XDP_PASS),
370                 BPF_EMIT_CALL(BPF_FUNC_redirect_map),
371                 BPF_EXIT_INSN(),
372         };
373         int prog_fd, map_fd, ret;
374
375         memset(&map_attr, 0, sizeof(map_attr));
376         map_attr.map_type = BPF_MAP_TYPE_XSKMAP;
377         map_attr.key_size = sizeof(int);
378         map_attr.value_size = sizeof(int);
379         map_attr.max_entries = 1;
380
381         map_fd = bpf_create_map_xattr(&map_attr);
382         if (map_fd < 0)
383                 return detected;
384
385         insns[0].imm = map_fd;
386
387         memset(&prog_attr, 0, sizeof(prog_attr));
388         prog_attr.prog_type = BPF_PROG_TYPE_XDP;
389         prog_attr.insns = insns;
390         prog_attr.insns_cnt = ARRAY_SIZE(insns);
391         prog_attr.license = "GPL";
392
393         prog_fd = bpf_load_program_xattr(&prog_attr, NULL, 0);
394         if (prog_fd < 0) {
395                 close(map_fd);
396                 return detected;
397         }
398
399         ret = bpf_prog_test_run(prog_fd, 0, &data_in, 1, &data_out, &size_out, &retval, &duration);
400         if (!ret && retval == XDP_PASS)
401                 detected = XSK_PROG_REDIRECT_FLAGS;
402         close(prog_fd);
403         close(map_fd);
404         return detected;
405 }
406
407 static int xsk_load_xdp_prog(struct xsk_socket *xsk)
408 {
409         static const int log_buf_size = 16 * 1024;
410         struct xsk_ctx *ctx = xsk->ctx;
411         char log_buf[log_buf_size];
412         int err, prog_fd;
413
414         /* This is the fallback C-program:
415          * SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx)
416          * {
417          *     int ret, index = ctx->rx_queue_index;
418          *
419          *     // A set entry here means that the correspnding queue_id
420          *     // has an active AF_XDP socket bound to it.
421          *     ret = bpf_redirect_map(&xsks_map, index, XDP_PASS);
422          *     if (ret > 0)
423          *         return ret;
424          *
425          *     // Fallback for pre-5.3 kernels, not supporting default
426          *     // action in the flags parameter.
427          *     if (bpf_map_lookup_elem(&xsks_map, &index))
428          *         return bpf_redirect_map(&xsks_map, index, 0);
429          *     return XDP_PASS;
430          * }
431          */
432         struct bpf_insn prog[] = {
433                 /* r2 = *(u32 *)(r1 + 16) */
434                 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 16),
435                 /* *(u32 *)(r10 - 4) = r2 */
436                 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -4),
437                 /* r1 = xskmap[] */
438                 BPF_LD_MAP_FD(BPF_REG_1, ctx->xsks_map_fd),
439                 /* r3 = XDP_PASS */
440                 BPF_MOV64_IMM(BPF_REG_3, 2),
441                 /* call bpf_redirect_map */
442                 BPF_EMIT_CALL(BPF_FUNC_redirect_map),
443                 /* if w0 != 0 goto pc+13 */
444                 BPF_JMP32_IMM(BPF_JSGT, BPF_REG_0, 0, 13),
445                 /* r2 = r10 */
446                 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
447                 /* r2 += -4 */
448                 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
449                 /* r1 = xskmap[] */
450                 BPF_LD_MAP_FD(BPF_REG_1, ctx->xsks_map_fd),
451                 /* call bpf_map_lookup_elem */
452                 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
453                 /* r1 = r0 */
454                 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
455                 /* r0 = XDP_PASS */
456                 BPF_MOV64_IMM(BPF_REG_0, 2),
457                 /* if r1 == 0 goto pc+5 */
458                 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 5),
459                 /* r2 = *(u32 *)(r10 - 4) */
460                 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_10, -4),
461                 /* r1 = xskmap[] */
462                 BPF_LD_MAP_FD(BPF_REG_1, ctx->xsks_map_fd),
463                 /* r3 = 0 */
464                 BPF_MOV64_IMM(BPF_REG_3, 0),
465                 /* call bpf_redirect_map */
466                 BPF_EMIT_CALL(BPF_FUNC_redirect_map),
467                 /* The jumps are to this instruction */
468                 BPF_EXIT_INSN(),
469         };
470
471         /* This is the post-5.3 kernel C-program:
472          * SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx)
473          * {
474          *     return bpf_redirect_map(&xsks_map, ctx->rx_queue_index, XDP_PASS);
475          * }
476          */
477         struct bpf_insn prog_redirect_flags[] = {
478                 /* r2 = *(u32 *)(r1 + 16) */
479                 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 16),
480                 /* r1 = xskmap[] */
481                 BPF_LD_MAP_FD(BPF_REG_1, ctx->xsks_map_fd),
482                 /* r3 = XDP_PASS */
483                 BPF_MOV64_IMM(BPF_REG_3, 2),
484                 /* call bpf_redirect_map */
485                 BPF_EMIT_CALL(BPF_FUNC_redirect_map),
486                 BPF_EXIT_INSN(),
487         };
488         size_t insns_cnt[] = {sizeof(prog) / sizeof(struct bpf_insn),
489                               sizeof(prog_redirect_flags) / sizeof(struct bpf_insn),
490         };
491         struct bpf_insn *progs[] = {prog, prog_redirect_flags};
492         enum xsk_prog option = get_xsk_prog();
493
494         prog_fd = bpf_load_program(BPF_PROG_TYPE_XDP, progs[option], insns_cnt[option],
495                                    "LGPL-2.1 or BSD-2-Clause", 0, log_buf,
496                                    log_buf_size);
497         if (prog_fd < 0) {
498                 pr_warn("BPF log buffer:\n%s", log_buf);
499                 return prog_fd;
500         }
501
502         err = bpf_set_link_xdp_fd(xsk->ctx->ifindex, prog_fd,
503                                   xsk->config.xdp_flags);
504         if (err) {
505                 close(prog_fd);
506                 return err;
507         }
508
509         ctx->prog_fd = prog_fd;
510         return 0;
511 }
512
513 static int xsk_get_max_queues(struct xsk_socket *xsk)
514 {
515         struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS };
516         struct xsk_ctx *ctx = xsk->ctx;
517         struct ifreq ifr = {};
518         int fd, err, ret;
519
520         fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
521         if (fd < 0)
522                 return -errno;
523
524         ifr.ifr_data = (void *)&channels;
525         memcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ - 1);
526         ifr.ifr_name[IFNAMSIZ - 1] = '\0';
527         err = ioctl(fd, SIOCETHTOOL, &ifr);
528         if (err && errno != EOPNOTSUPP) {
529                 ret = -errno;
530                 goto out;
531         }
532
533         if (err) {
534                 /* If the device says it has no channels, then all traffic
535                  * is sent to a single stream, so max queues = 1.
536                  */
537                 ret = 1;
538         } else {
539                 /* Take the max of rx, tx, combined. Drivers return
540                  * the number of channels in different ways.
541                  */
542                 ret = max(channels.max_rx, channels.max_tx);
543                 ret = max(ret, (int)channels.max_combined);
544         }
545
546 out:
547         close(fd);
548         return ret;
549 }
550
551 static int xsk_create_bpf_maps(struct xsk_socket *xsk)
552 {
553         struct xsk_ctx *ctx = xsk->ctx;
554         int max_queues;
555         int fd;
556
557         max_queues = xsk_get_max_queues(xsk);
558         if (max_queues < 0)
559                 return max_queues;
560
561         fd = bpf_create_map_name(BPF_MAP_TYPE_XSKMAP, "xsks_map",
562                                  sizeof(int), sizeof(int), max_queues, 0);
563         if (fd < 0)
564                 return fd;
565
566         ctx->xsks_map_fd = fd;
567
568         return 0;
569 }
570
571 static void xsk_delete_bpf_maps(struct xsk_socket *xsk)
572 {
573         struct xsk_ctx *ctx = xsk->ctx;
574
575         bpf_map_delete_elem(ctx->xsks_map_fd, &ctx->queue_id);
576         close(ctx->xsks_map_fd);
577 }
578
579 static int xsk_lookup_bpf_maps(struct xsk_socket *xsk)
580 {
581         __u32 i, *map_ids, num_maps, prog_len = sizeof(struct bpf_prog_info);
582         __u32 map_len = sizeof(struct bpf_map_info);
583         struct bpf_prog_info prog_info = {};
584         struct xsk_ctx *ctx = xsk->ctx;
585         struct bpf_map_info map_info;
586         int fd, err;
587
588         err = bpf_obj_get_info_by_fd(ctx->prog_fd, &prog_info, &prog_len);
589         if (err)
590                 return err;
591
592         num_maps = prog_info.nr_map_ids;
593
594         map_ids = calloc(prog_info.nr_map_ids, sizeof(*map_ids));
595         if (!map_ids)
596                 return -ENOMEM;
597
598         memset(&prog_info, 0, prog_len);
599         prog_info.nr_map_ids = num_maps;
600         prog_info.map_ids = (__u64)(unsigned long)map_ids;
601
602         err = bpf_obj_get_info_by_fd(ctx->prog_fd, &prog_info, &prog_len);
603         if (err)
604                 goto out_map_ids;
605
606         ctx->xsks_map_fd = -1;
607
608         for (i = 0; i < prog_info.nr_map_ids; i++) {
609                 fd = bpf_map_get_fd_by_id(map_ids[i]);
610                 if (fd < 0)
611                         continue;
612
613                 err = bpf_obj_get_info_by_fd(fd, &map_info, &map_len);
614                 if (err) {
615                         close(fd);
616                         continue;
617                 }
618
619                 if (!strcmp(map_info.name, "xsks_map")) {
620                         ctx->xsks_map_fd = fd;
621                         continue;
622                 }
623
624                 close(fd);
625         }
626
627         err = 0;
628         if (ctx->xsks_map_fd == -1)
629                 err = -ENOENT;
630
631 out_map_ids:
632         free(map_ids);
633         return err;
634 }
635
636 static int xsk_set_bpf_maps(struct xsk_socket *xsk)
637 {
638         struct xsk_ctx *ctx = xsk->ctx;
639
640         return bpf_map_update_elem(ctx->xsks_map_fd, &ctx->queue_id,
641                                    &xsk->fd, 0);
642 }
643
644 static int xsk_create_xsk_struct(int ifindex, struct xsk_socket *xsk)
645 {
646         char ifname[IFNAMSIZ];
647         struct xsk_ctx *ctx;
648         char *interface;
649
650         ctx = calloc(1, sizeof(*ctx));
651         if (!ctx)
652                 return -ENOMEM;
653
654         interface = if_indextoname(ifindex, &ifname[0]);
655         if (!interface) {
656                 free(ctx);
657                 return -errno;
658         }
659
660         ctx->ifindex = ifindex;
661         memcpy(ctx->ifname, ifname, IFNAMSIZ -1);
662         ctx->ifname[IFNAMSIZ - 1] = 0;
663
664         xsk->ctx = ctx;
665
666         return 0;
667 }
668
669 static int __xsk_setup_xdp_prog(struct xsk_socket *_xdp,
670                                 int *xsks_map_fd)
671 {
672         struct xsk_socket *xsk = _xdp;
673         struct xsk_ctx *ctx = xsk->ctx;
674         __u32 prog_id = 0;
675         int err;
676
677         err = bpf_get_link_xdp_id(ctx->ifindex, &prog_id,
678                                   xsk->config.xdp_flags);
679         if (err)
680                 return err;
681
682         if (!prog_id) {
683                 err = xsk_create_bpf_maps(xsk);
684                 if (err)
685                         return err;
686
687                 err = xsk_load_xdp_prog(xsk);
688                 if (err) {
689                         goto err_load_xdp_prog;
690                 }
691         } else {
692                 ctx->prog_fd = bpf_prog_get_fd_by_id(prog_id);
693                 if (ctx->prog_fd < 0)
694                         return -errno;
695                 err = xsk_lookup_bpf_maps(xsk);
696                 if (err) {
697                         close(ctx->prog_fd);
698                         return err;
699                 }
700         }
701
702         if (xsk->rx) {
703                 err = xsk_set_bpf_maps(xsk);
704                 if (err) {
705                         if (!prog_id) {
706                                 goto err_set_bpf_maps;
707                         } else {
708                                 close(ctx->prog_fd);
709                                 return err;
710                         }
711                 }
712         }
713         if (xsks_map_fd)
714                 *xsks_map_fd = ctx->xsks_map_fd;
715
716         return 0;
717
718 err_set_bpf_maps:
719         close(ctx->prog_fd);
720         bpf_set_link_xdp_fd(ctx->ifindex, -1, 0);
721 err_load_xdp_prog:
722         xsk_delete_bpf_maps(xsk);
723
724         return err;
725 }
726
727 static struct xsk_ctx *xsk_get_ctx(struct xsk_umem *umem, int ifindex,
728                                    __u32 queue_id)
729 {
730         struct xsk_ctx *ctx;
731
732         if (list_empty(&umem->ctx_list))
733                 return NULL;
734
735         list_for_each_entry(ctx, &umem->ctx_list, list) {
736                 if (ctx->ifindex == ifindex && ctx->queue_id == queue_id) {
737                         ctx->refcount++;
738                         return ctx;
739                 }
740         }
741
742         return NULL;
743 }
744
745 static void xsk_put_ctx(struct xsk_ctx *ctx)
746 {
747         struct xsk_umem *umem = ctx->umem;
748         struct xdp_mmap_offsets off;
749         int err;
750
751         if (--ctx->refcount == 0) {
752                 err = xsk_get_mmap_offsets(umem->fd, &off);
753                 if (!err) {
754                         munmap(ctx->fill->ring - off.fr.desc,
755                                off.fr.desc + umem->config.fill_size *
756                                sizeof(__u64));
757                         munmap(ctx->comp->ring - off.cr.desc,
758                                off.cr.desc + umem->config.comp_size *
759                                sizeof(__u64));
760                 }
761
762                 list_del(&ctx->list);
763                 free(ctx);
764         }
765 }
766
767 static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk,
768                                       struct xsk_umem *umem, int ifindex,
769                                       const char *ifname, __u32 queue_id,
770                                       struct xsk_ring_prod *fill,
771                                       struct xsk_ring_cons *comp)
772 {
773         struct xsk_ctx *ctx;
774         int err;
775
776         ctx = calloc(1, sizeof(*ctx));
777         if (!ctx)
778                 return NULL;
779
780         if (!umem->fill_save) {
781                 err = xsk_create_umem_rings(umem, xsk->fd, fill, comp);
782                 if (err) {
783                         free(ctx);
784                         return NULL;
785                 }
786         } else if (umem->fill_save != fill || umem->comp_save != comp) {
787                 /* Copy over rings to new structs. */
788                 memcpy(fill, umem->fill_save, sizeof(*fill));
789                 memcpy(comp, umem->comp_save, sizeof(*comp));
790         }
791
792         ctx->ifindex = ifindex;
793         ctx->refcount = 1;
794         ctx->umem = umem;
795         ctx->queue_id = queue_id;
796         memcpy(ctx->ifname, ifname, IFNAMSIZ - 1);
797         ctx->ifname[IFNAMSIZ - 1] = '\0';
798
799         umem->fill_save = NULL;
800         umem->comp_save = NULL;
801         ctx->fill = fill;
802         ctx->comp = comp;
803         list_add(&ctx->list, &umem->ctx_list);
804         return ctx;
805 }
806
807 static void xsk_destroy_xsk_struct(struct xsk_socket *xsk)
808 {
809         free(xsk->ctx);
810         free(xsk);
811 }
812
813 int xsk_socket__update_xskmap(struct xsk_socket *xsk, int fd)
814 {
815         xsk->ctx->xsks_map_fd = fd;
816         return xsk_set_bpf_maps(xsk);
817 }
818
819 int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd)
820 {
821         struct xsk_socket *xsk;
822         int res;
823
824         xsk = calloc(1, sizeof(*xsk));
825         if (!xsk)
826                 return -ENOMEM;
827
828         res = xsk_create_xsk_struct(ifindex, xsk);
829         if (res) {
830                 free(xsk);
831                 return -EINVAL;
832         }
833
834         res = __xsk_setup_xdp_prog(xsk, xsks_map_fd);
835
836         xsk_destroy_xsk_struct(xsk);
837
838         return res;
839 }
840
841 int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
842                               const char *ifname,
843                               __u32 queue_id, struct xsk_umem *umem,
844                               struct xsk_ring_cons *rx,
845                               struct xsk_ring_prod *tx,
846                               struct xsk_ring_prod *fill,
847                               struct xsk_ring_cons *comp,
848                               const struct xsk_socket_config *usr_config)
849 {
850         void *rx_map = NULL, *tx_map = NULL;
851         struct sockaddr_xdp sxdp = {};
852         struct xdp_mmap_offsets off;
853         struct xsk_socket *xsk;
854         struct xsk_ctx *ctx;
855         int err, ifindex;
856
857         if (!umem || !xsk_ptr || !(rx || tx))
858                 return -EFAULT;
859
860         xsk = calloc(1, sizeof(*xsk));
861         if (!xsk)
862                 return -ENOMEM;
863
864         err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
865         if (err)
866                 goto out_xsk_alloc;
867
868         xsk->outstanding_tx = 0;
869         ifindex = if_nametoindex(ifname);
870         if (!ifindex) {
871                 err = -errno;
872                 goto out_xsk_alloc;
873         }
874
875         if (umem->refcount++ > 0) {
876                 xsk->fd = socket(AF_XDP, SOCK_RAW, 0);
877                 if (xsk->fd < 0) {
878                         err = -errno;
879                         goto out_xsk_alloc;
880                 }
881         } else {
882                 xsk->fd = umem->fd;
883         }
884
885         ctx = xsk_get_ctx(umem, ifindex, queue_id);
886         if (!ctx) {
887                 if (!fill || !comp) {
888                         err = -EFAULT;
889                         goto out_socket;
890                 }
891
892                 ctx = xsk_create_ctx(xsk, umem, ifindex, ifname, queue_id,
893                                      fill, comp);
894                 if (!ctx) {
895                         err = -ENOMEM;
896                         goto out_socket;
897                 }
898         }
899         xsk->ctx = ctx;
900
901         if (rx) {
902                 err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,
903                                  &xsk->config.rx_size,
904                                  sizeof(xsk->config.rx_size));
905                 if (err) {
906                         err = -errno;
907                         goto out_put_ctx;
908                 }
909         }
910         if (tx) {
911                 err = setsockopt(xsk->fd, SOL_XDP, XDP_TX_RING,
912                                  &xsk->config.tx_size,
913                                  sizeof(xsk->config.tx_size));
914                 if (err) {
915                         err = -errno;
916                         goto out_put_ctx;
917                 }
918         }
919
920         err = xsk_get_mmap_offsets(xsk->fd, &off);
921         if (err) {
922                 err = -errno;
923                 goto out_put_ctx;
924         }
925
926         if (rx) {
927                 rx_map = mmap(NULL, off.rx.desc +
928                               xsk->config.rx_size * sizeof(struct xdp_desc),
929                               PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
930                               xsk->fd, XDP_PGOFF_RX_RING);
931                 if (rx_map == MAP_FAILED) {
932                         err = -errno;
933                         goto out_put_ctx;
934                 }
935
936                 rx->mask = xsk->config.rx_size - 1;
937                 rx->size = xsk->config.rx_size;
938                 rx->producer = rx_map + off.rx.producer;
939                 rx->consumer = rx_map + off.rx.consumer;
940                 rx->flags = rx_map + off.rx.flags;
941                 rx->ring = rx_map + off.rx.desc;
942                 rx->cached_prod = *rx->producer;
943                 rx->cached_cons = *rx->consumer;
944         }
945         xsk->rx = rx;
946
947         if (tx) {
948                 tx_map = mmap(NULL, off.tx.desc +
949                               xsk->config.tx_size * sizeof(struct xdp_desc),
950                               PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
951                               xsk->fd, XDP_PGOFF_TX_RING);
952                 if (tx_map == MAP_FAILED) {
953                         err = -errno;
954                         goto out_mmap_rx;
955                 }
956
957                 tx->mask = xsk->config.tx_size - 1;
958                 tx->size = xsk->config.tx_size;
959                 tx->producer = tx_map + off.tx.producer;
960                 tx->consumer = tx_map + off.tx.consumer;
961                 tx->flags = tx_map + off.tx.flags;
962                 tx->ring = tx_map + off.tx.desc;
963                 tx->cached_prod = *tx->producer;
964                 /* cached_cons is r->size bigger than the real consumer pointer
965                  * See xsk_prod_nb_free
966                  */
967                 tx->cached_cons = *tx->consumer + xsk->config.tx_size;
968         }
969         xsk->tx = tx;
970
971         sxdp.sxdp_family = PF_XDP;
972         sxdp.sxdp_ifindex = ctx->ifindex;
973         sxdp.sxdp_queue_id = ctx->queue_id;
974         if (umem->refcount > 1) {
975                 sxdp.sxdp_flags |= XDP_SHARED_UMEM;
976                 sxdp.sxdp_shared_umem_fd = umem->fd;
977         } else {
978                 sxdp.sxdp_flags = xsk->config.bind_flags;
979         }
980
981         err = bind(xsk->fd, (struct sockaddr *)&sxdp, sizeof(sxdp));
982         if (err) {
983                 err = -errno;
984                 goto out_mmap_tx;
985         }
986
987         ctx->prog_fd = -1;
988
989         if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
990                 err = __xsk_setup_xdp_prog(xsk, NULL);
991                 if (err)
992                         goto out_mmap_tx;
993         }
994
995         *xsk_ptr = xsk;
996         return 0;
997
998 out_mmap_tx:
999         if (tx)
1000                 munmap(tx_map, off.tx.desc +
1001                        xsk->config.tx_size * sizeof(struct xdp_desc));
1002 out_mmap_rx:
1003         if (rx)
1004                 munmap(rx_map, off.rx.desc +
1005                        xsk->config.rx_size * sizeof(struct xdp_desc));
1006 out_put_ctx:
1007         xsk_put_ctx(ctx);
1008 out_socket:
1009         if (--umem->refcount)
1010                 close(xsk->fd);
1011 out_xsk_alloc:
1012         free(xsk);
1013         return err;
1014 }
1015
1016 int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
1017                        __u32 queue_id, struct xsk_umem *umem,
1018                        struct xsk_ring_cons *rx, struct xsk_ring_prod *tx,
1019                        const struct xsk_socket_config *usr_config)
1020 {
1021         return xsk_socket__create_shared(xsk_ptr, ifname, queue_id, umem,
1022                                          rx, tx, umem->fill_save,
1023                                          umem->comp_save, usr_config);
1024 }
1025
1026 int xsk_umem__delete(struct xsk_umem *umem)
1027 {
1028         if (!umem)
1029                 return 0;
1030
1031         if (umem->refcount)
1032                 return -EBUSY;
1033
1034         close(umem->fd);
1035         free(umem);
1036
1037         return 0;
1038 }
1039
1040 void xsk_socket__delete(struct xsk_socket *xsk)
1041 {
1042         size_t desc_sz = sizeof(struct xdp_desc);
1043         struct xdp_mmap_offsets off;
1044         struct xsk_umem *umem;
1045         struct xsk_ctx *ctx;
1046         int err;
1047
1048         if (!xsk)
1049                 return;
1050
1051         ctx = xsk->ctx;
1052         umem = ctx->umem;
1053         if (ctx->prog_fd != -1) {
1054                 xsk_delete_bpf_maps(xsk);
1055                 close(ctx->prog_fd);
1056         }
1057
1058         err = xsk_get_mmap_offsets(xsk->fd, &off);
1059         if (!err) {
1060                 if (xsk->rx) {
1061                         munmap(xsk->rx->ring - off.rx.desc,
1062                                off.rx.desc + xsk->config.rx_size * desc_sz);
1063                 }
1064                 if (xsk->tx) {
1065                         munmap(xsk->tx->ring - off.tx.desc,
1066                                off.tx.desc + xsk->config.tx_size * desc_sz);
1067                 }
1068         }
1069
1070         xsk_put_ctx(ctx);
1071
1072         umem->refcount--;
1073         /* Do not close an fd that also has an associated umem connected
1074          * to it.
1075          */
1076         if (xsk->fd != umem->fd)
1077                 close(xsk->fd);
1078         free(xsk);
1079 }