hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/tools/lib/bpf/bpf.c
....@@ -1,4 +1,4 @@
1
-// SPDX-License-Identifier: LGPL-2.1
1
+// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
22
33 /*
44 * common eBPF ELF operations.
....@@ -22,21 +22,15 @@
2222 */
2323
2424 #include <stdlib.h>
25
+#include <string.h>
2526 #include <memory.h>
2627 #include <unistd.h>
2728 #include <asm/unistd.h>
29
+#include <errno.h>
2830 #include <linux/bpf.h>
2931 #include "bpf.h"
3032 #include "libbpf.h"
31
-#include "nlattr.h"
32
-#include <linux/rtnetlink.h>
33
-#include <linux/if_link.h>
34
-#include <sys/socket.h>
35
-#include <errno.h>
36
-
37
-#ifndef SOL_NETLINK
38
-#define SOL_NETLINK 270
39
-#endif
33
+#include "libbpf_internal.h"
4034
4135 /*
4236 * When building perf, unistd.h is overridden. __NR_bpf is
....@@ -58,10 +52,6 @@
5852 # else
5953 # error __NR_bpf not defined. libbpf does not support your arch.
6054 # endif
61
-#endif
62
-
63
-#ifndef min
64
-#define min(x, y) ((x) < (y) ? (x) : (y))
6555 #endif
6656
6757 static inline __u64 ptr_to_u64(const void *ptr)
....@@ -88,9 +78,7 @@
8878
8979 int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
9080 {
91
- __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0;
9281 union bpf_attr attr;
93
- int ret;
9482
9583 memset(&attr, '\0', sizeof(attr));
9684
....@@ -99,24 +87,21 @@
9987 attr.value_size = create_attr->value_size;
10088 attr.max_entries = create_attr->max_entries;
10189 attr.map_flags = create_attr->map_flags;
102
- memcpy(attr.map_name, create_attr->name,
103
- min(name_len, BPF_OBJ_NAME_LEN - 1));
90
+ if (create_attr->name)
91
+ memcpy(attr.map_name, create_attr->name,
92
+ min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1));
10493 attr.numa_node = create_attr->numa_node;
10594 attr.btf_fd = create_attr->btf_fd;
10695 attr.btf_key_type_id = create_attr->btf_key_type_id;
10796 attr.btf_value_type_id = create_attr->btf_value_type_id;
10897 attr.map_ifindex = create_attr->map_ifindex;
109
- attr.inner_map_fd = create_attr->inner_map_fd;
98
+ if (attr.map_type == BPF_MAP_TYPE_STRUCT_OPS)
99
+ attr.btf_vmlinux_value_type_id =
100
+ create_attr->btf_vmlinux_value_type_id;
101
+ else
102
+ attr.inner_map_fd = create_attr->inner_map_fd;
110103
111
- ret = sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
112
- if (ret < 0 && errno == EINVAL && create_attr->name) {
113
- /* Retry the same syscall, but without the name.
114
- * Pre v4.14 kernels don't support map names.
115
- */
116
- memset(attr.map_name, 0, sizeof(attr.map_name));
117
- return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
118
- }
119
- return ret;
104
+ return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
120105 }
121106
122107 int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
....@@ -173,7 +158,6 @@
173158 int key_size, int inner_map_fd, int max_entries,
174159 __u32 map_flags, int node)
175160 {
176
- __u32 name_len = name ? strlen(name) : 0;
177161 union bpf_attr attr;
178162
179163 memset(&attr, '\0', sizeof(attr));
....@@ -184,7 +168,9 @@
184168 attr.inner_map_fd = inner_map_fd;
185169 attr.max_entries = max_entries;
186170 attr.map_flags = map_flags;
187
- memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
171
+ if (name)
172
+ memcpy(attr.map_name, name,
173
+ min(strlen(name), BPF_OBJ_NAME_LEN - 1));
188174
189175 if (node >= 0) {
190176 attr.map_flags |= BPF_F_NUMA_NODE;
....@@ -203,42 +189,141 @@
203189 -1);
204190 }
205191
192
+static void *
193
+alloc_zero_tailing_info(const void *orecord, __u32 cnt,
194
+ __u32 actual_rec_size, __u32 expected_rec_size)
195
+{
196
+ __u64 info_len = (__u64)actual_rec_size * cnt;
197
+ void *info, *nrecord;
198
+ int i;
199
+
200
+ info = malloc(info_len);
201
+ if (!info)
202
+ return NULL;
203
+
204
+ /* zero out bytes kernel does not understand */
205
+ nrecord = info;
206
+ for (i = 0; i < cnt; i++) {
207
+ memcpy(nrecord, orecord, expected_rec_size);
208
+ memset(nrecord + expected_rec_size, 0,
209
+ actual_rec_size - expected_rec_size);
210
+ orecord += actual_rec_size;
211
+ nrecord += actual_rec_size;
212
+ }
213
+
214
+ return info;
215
+}
216
+
206217 int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
207218 char *log_buf, size_t log_buf_sz)
208219 {
220
+ void *finfo = NULL, *linfo = NULL;
209221 union bpf_attr attr;
210
- __u32 name_len;
222
+ __u32 log_level;
211223 int fd;
212224
213
- if (!load_attr)
225
+ if (!load_attr || !log_buf != !log_buf_sz)
214226 return -EINVAL;
215227
216
- name_len = load_attr->name ? strlen(load_attr->name) : 0;
228
+ log_level = load_attr->log_level;
229
+ if (log_level > (4 | 2 | 1) || (log_level && !log_buf))
230
+ return -EINVAL;
217231
218
- bzero(&attr, sizeof(attr));
232
+ memset(&attr, 0, sizeof(attr));
219233 attr.prog_type = load_attr->prog_type;
220234 attr.expected_attach_type = load_attr->expected_attach_type;
235
+ if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
236
+ attr.prog_type == BPF_PROG_TYPE_LSM) {
237
+ attr.attach_btf_id = load_attr->attach_btf_id;
238
+ } else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
239
+ attr.prog_type == BPF_PROG_TYPE_EXT) {
240
+ attr.attach_btf_id = load_attr->attach_btf_id;
241
+ attr.attach_prog_fd = load_attr->attach_prog_fd;
242
+ } else {
243
+ attr.prog_ifindex = load_attr->prog_ifindex;
244
+ attr.kern_version = load_attr->kern_version;
245
+ }
221246 attr.insn_cnt = (__u32)load_attr->insns_cnt;
222247 attr.insns = ptr_to_u64(load_attr->insns);
223248 attr.license = ptr_to_u64(load_attr->license);
224
- attr.log_buf = ptr_to_u64(NULL);
225
- attr.log_size = 0;
226
- attr.log_level = 0;
227
- attr.kern_version = load_attr->kern_version;
228
- attr.prog_ifindex = load_attr->prog_ifindex;
229
- memcpy(attr.prog_name, load_attr->name,
230
- min(name_len, BPF_OBJ_NAME_LEN - 1));
249
+
250
+ attr.log_level = log_level;
251
+ if (log_level) {
252
+ attr.log_buf = ptr_to_u64(log_buf);
253
+ attr.log_size = log_buf_sz;
254
+ } else {
255
+ attr.log_buf = ptr_to_u64(NULL);
256
+ attr.log_size = 0;
257
+ }
258
+
259
+ attr.prog_btf_fd = load_attr->prog_btf_fd;
260
+ attr.func_info_rec_size = load_attr->func_info_rec_size;
261
+ attr.func_info_cnt = load_attr->func_info_cnt;
262
+ attr.func_info = ptr_to_u64(load_attr->func_info);
263
+ attr.line_info_rec_size = load_attr->line_info_rec_size;
264
+ attr.line_info_cnt = load_attr->line_info_cnt;
265
+ attr.line_info = ptr_to_u64(load_attr->line_info);
266
+ if (load_attr->name)
267
+ memcpy(attr.prog_name, load_attr->name,
268
+ min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
269
+ attr.prog_flags = load_attr->prog_flags;
231270
232271 fd = sys_bpf_prog_load(&attr, sizeof(attr));
233
- if (fd >= 0 || !log_buf || !log_buf_sz)
272
+ if (fd >= 0)
234273 return fd;
274
+
275
+ /* After bpf_prog_load, the kernel may modify certain attributes
276
+ * to give user space a hint how to deal with loading failure.
277
+ * Check to see whether we can make some changes and load again.
278
+ */
279
+ while (errno == E2BIG && (!finfo || !linfo)) {
280
+ if (!finfo && attr.func_info_cnt &&
281
+ attr.func_info_rec_size < load_attr->func_info_rec_size) {
282
+ /* try with corrected func info records */
283
+ finfo = alloc_zero_tailing_info(load_attr->func_info,
284
+ load_attr->func_info_cnt,
285
+ load_attr->func_info_rec_size,
286
+ attr.func_info_rec_size);
287
+ if (!finfo)
288
+ goto done;
289
+
290
+ attr.func_info = ptr_to_u64(finfo);
291
+ attr.func_info_rec_size = load_attr->func_info_rec_size;
292
+ } else if (!linfo && attr.line_info_cnt &&
293
+ attr.line_info_rec_size <
294
+ load_attr->line_info_rec_size) {
295
+ linfo = alloc_zero_tailing_info(load_attr->line_info,
296
+ load_attr->line_info_cnt,
297
+ load_attr->line_info_rec_size,
298
+ attr.line_info_rec_size);
299
+ if (!linfo)
300
+ goto done;
301
+
302
+ attr.line_info = ptr_to_u64(linfo);
303
+ attr.line_info_rec_size = load_attr->line_info_rec_size;
304
+ } else {
305
+ break;
306
+ }
307
+
308
+ fd = sys_bpf_prog_load(&attr, sizeof(attr));
309
+
310
+ if (fd >= 0)
311
+ goto done;
312
+ }
313
+
314
+ if (log_level || !log_buf)
315
+ goto done;
235316
236317 /* Try again with log */
237318 attr.log_buf = ptr_to_u64(log_buf);
238319 attr.log_size = log_buf_sz;
239320 attr.log_level = 1;
240321 log_buf[0] = 0;
241
- return sys_bpf_prog_load(&attr, sizeof(attr));
322
+ fd = sys_bpf_prog_load(&attr, sizeof(attr));
323
+done:
324
+ free(finfo);
325
+ free(linfo);
326
+ return fd;
242327 }
243328
244329 int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
....@@ -267,7 +352,7 @@
267352 {
268353 union bpf_attr attr;
269354
270
- bzero(&attr, sizeof(attr));
355
+ memset(&attr, 0, sizeof(attr));
271356 attr.prog_type = type;
272357 attr.insn_cnt = (__u32)insns_cnt;
273358 attr.insns = ptr_to_u64(insns);
....@@ -287,7 +372,7 @@
287372 {
288373 union bpf_attr attr;
289374
290
- bzero(&attr, sizeof(attr));
375
+ memset(&attr, 0, sizeof(attr));
291376 attr.map_fd = fd;
292377 attr.key = ptr_to_u64(key);
293378 attr.value = ptr_to_u64(value);
....@@ -300,7 +385,7 @@
300385 {
301386 union bpf_attr attr;
302387
303
- bzero(&attr, sizeof(attr));
388
+ memset(&attr, 0, sizeof(attr));
304389 attr.map_fd = fd;
305390 attr.key = ptr_to_u64(key);
306391 attr.value = ptr_to_u64(value);
....@@ -308,11 +393,36 @@
308393 return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
309394 }
310395
396
+int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
397
+{
398
+ union bpf_attr attr;
399
+
400
+ memset(&attr, 0, sizeof(attr));
401
+ attr.map_fd = fd;
402
+ attr.key = ptr_to_u64(key);
403
+ attr.value = ptr_to_u64(value);
404
+ attr.flags = flags;
405
+
406
+ return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
407
+}
408
+
409
+int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
410
+{
411
+ union bpf_attr attr;
412
+
413
+ memset(&attr, 0, sizeof(attr));
414
+ attr.map_fd = fd;
415
+ attr.key = ptr_to_u64(key);
416
+ attr.value = ptr_to_u64(value);
417
+
418
+ return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
419
+}
420
+
311421 int bpf_map_delete_elem(int fd, const void *key)
312422 {
313423 union bpf_attr attr;
314424
315
- bzero(&attr, sizeof(attr));
425
+ memset(&attr, 0, sizeof(attr));
316426 attr.map_fd = fd;
317427 attr.key = ptr_to_u64(key);
318428
....@@ -323,7 +433,7 @@
323433 {
324434 union bpf_attr attr;
325435
326
- bzero(&attr, sizeof(attr));
436
+ memset(&attr, 0, sizeof(attr));
327437 attr.map_fd = fd;
328438 attr.key = ptr_to_u64(key);
329439 attr.next_key = ptr_to_u64(next_key);
....@@ -331,11 +441,79 @@
331441 return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
332442 }
333443
444
+int bpf_map_freeze(int fd)
445
+{
446
+ union bpf_attr attr;
447
+
448
+ memset(&attr, 0, sizeof(attr));
449
+ attr.map_fd = fd;
450
+
451
+ return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
452
+}
453
+
454
+static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
455
+ void *out_batch, void *keys, void *values,
456
+ __u32 *count,
457
+ const struct bpf_map_batch_opts *opts)
458
+{
459
+ union bpf_attr attr;
460
+ int ret;
461
+
462
+ if (!OPTS_VALID(opts, bpf_map_batch_opts))
463
+ return -EINVAL;
464
+
465
+ memset(&attr, 0, sizeof(attr));
466
+ attr.batch.map_fd = fd;
467
+ attr.batch.in_batch = ptr_to_u64(in_batch);
468
+ attr.batch.out_batch = ptr_to_u64(out_batch);
469
+ attr.batch.keys = ptr_to_u64(keys);
470
+ attr.batch.values = ptr_to_u64(values);
471
+ attr.batch.count = *count;
472
+ attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0);
473
+ attr.batch.flags = OPTS_GET(opts, flags, 0);
474
+
475
+ ret = sys_bpf(cmd, &attr, sizeof(attr));
476
+ *count = attr.batch.count;
477
+
478
+ return ret;
479
+}
480
+
481
+int bpf_map_delete_batch(int fd, void *keys, __u32 *count,
482
+ const struct bpf_map_batch_opts *opts)
483
+{
484
+ return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
485
+ NULL, keys, NULL, count, opts);
486
+}
487
+
488
+int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
489
+ void *values, __u32 *count,
490
+ const struct bpf_map_batch_opts *opts)
491
+{
492
+ return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
493
+ out_batch, keys, values, count, opts);
494
+}
495
+
496
+int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
497
+ void *keys, void *values, __u32 *count,
498
+ const struct bpf_map_batch_opts *opts)
499
+{
500
+ return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
501
+ fd, in_batch, out_batch, keys, values,
502
+ count, opts);
503
+}
504
+
505
+int bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count,
506
+ const struct bpf_map_batch_opts *opts)
507
+{
508
+ return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
509
+ keys, values, count, opts);
510
+}
511
+
334512 int bpf_obj_pin(int fd, const char *pathname)
335513 {
336514 union bpf_attr attr;
337515
338
- bzero(&attr, sizeof(attr));
516
+ memset(&attr, 0, sizeof(attr));
339517 attr.pathname = ptr_to_u64((void *)pathname);
340518 attr.bpf_fd = fd;
341519
....@@ -346,7 +524,7 @@
346524 {
347525 union bpf_attr attr;
348526
349
- bzero(&attr, sizeof(attr));
527
+ memset(&attr, 0, sizeof(attr));
350528 attr.pathname = ptr_to_u64((void *)pathname);
351529
352530 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
....@@ -355,13 +533,28 @@
355533 int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
356534 unsigned int flags)
357535 {
536
+ DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
537
+ .flags = flags,
538
+ );
539
+
540
+ return bpf_prog_attach_xattr(prog_fd, target_fd, type, &opts);
541
+}
542
+
543
+int bpf_prog_attach_xattr(int prog_fd, int target_fd,
544
+ enum bpf_attach_type type,
545
+ const struct bpf_prog_attach_opts *opts)
546
+{
358547 union bpf_attr attr;
359548
360
- bzero(&attr, sizeof(attr));
549
+ if (!OPTS_VALID(opts, bpf_prog_attach_opts))
550
+ return -EINVAL;
551
+
552
+ memset(&attr, 0, sizeof(attr));
361553 attr.target_fd = target_fd;
362554 attr.attach_bpf_fd = prog_fd;
363555 attr.attach_type = type;
364
- attr.attach_flags = flags;
556
+ attr.attach_flags = OPTS_GET(opts, flags, 0);
557
+ attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0);
365558
366559 return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
367560 }
....@@ -370,7 +563,7 @@
370563 {
371564 union bpf_attr attr;
372565
373
- bzero(&attr, sizeof(attr));
566
+ memset(&attr, 0, sizeof(attr));
374567 attr.target_fd = target_fd;
375568 attr.attach_type = type;
376569
....@@ -381,12 +574,82 @@
381574 {
382575 union bpf_attr attr;
383576
384
- bzero(&attr, sizeof(attr));
577
+ memset(&attr, 0, sizeof(attr));
385578 attr.target_fd = target_fd;
386579 attr.attach_bpf_fd = prog_fd;
387580 attr.attach_type = type;
388581
389582 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
583
+}
584
+
585
+int bpf_link_create(int prog_fd, int target_fd,
586
+ enum bpf_attach_type attach_type,
587
+ const struct bpf_link_create_opts *opts)
588
+{
589
+ __u32 target_btf_id, iter_info_len;
590
+ union bpf_attr attr;
591
+
592
+ if (!OPTS_VALID(opts, bpf_link_create_opts))
593
+ return -EINVAL;
594
+
595
+ iter_info_len = OPTS_GET(opts, iter_info_len, 0);
596
+ target_btf_id = OPTS_GET(opts, target_btf_id, 0);
597
+
598
+ if (iter_info_len && target_btf_id)
599
+ return -EINVAL;
600
+
601
+ memset(&attr, 0, sizeof(attr));
602
+ attr.link_create.prog_fd = prog_fd;
603
+ attr.link_create.target_fd = target_fd;
604
+ attr.link_create.attach_type = attach_type;
605
+ attr.link_create.flags = OPTS_GET(opts, flags, 0);
606
+
607
+ if (iter_info_len) {
608
+ attr.link_create.iter_info =
609
+ ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0));
610
+ attr.link_create.iter_info_len = iter_info_len;
611
+ } else if (target_btf_id) {
612
+ attr.link_create.target_btf_id = target_btf_id;
613
+ }
614
+
615
+ return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr));
616
+}
617
+
618
+int bpf_link_detach(int link_fd)
619
+{
620
+ union bpf_attr attr;
621
+
622
+ memset(&attr, 0, sizeof(attr));
623
+ attr.link_detach.link_fd = link_fd;
624
+
625
+ return sys_bpf(BPF_LINK_DETACH, &attr, sizeof(attr));
626
+}
627
+
628
+int bpf_link_update(int link_fd, int new_prog_fd,
629
+ const struct bpf_link_update_opts *opts)
630
+{
631
+ union bpf_attr attr;
632
+
633
+ if (!OPTS_VALID(opts, bpf_link_update_opts))
634
+ return -EINVAL;
635
+
636
+ memset(&attr, 0, sizeof(attr));
637
+ attr.link_update.link_fd = link_fd;
638
+ attr.link_update.new_prog_fd = new_prog_fd;
639
+ attr.link_update.flags = OPTS_GET(opts, flags, 0);
640
+ attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
641
+
642
+ return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
643
+}
644
+
645
+int bpf_iter_create(int link_fd)
646
+{
647
+ union bpf_attr attr;
648
+
649
+ memset(&attr, 0, sizeof(attr));
650
+ attr.iter_create.link_fd = link_fd;
651
+
652
+ return sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr));
390653 }
391654
392655 int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
....@@ -395,7 +658,7 @@
395658 union bpf_attr attr;
396659 int ret;
397660
398
- bzero(&attr, sizeof(attr));
661
+ memset(&attr, 0, sizeof(attr));
399662 attr.query.target_fd = target_fd;
400663 attr.query.attach_type = type;
401664 attr.query.query_flags = query_flags;
....@@ -416,7 +679,7 @@
416679 union bpf_attr attr;
417680 int ret;
418681
419
- bzero(&attr, sizeof(attr));
682
+ memset(&attr, 0, sizeof(attr));
420683 attr.test.prog_fd = prog_fd;
421684 attr.test.data_in = ptr_to_u64(data);
422685 attr.test.data_out = ptr_to_u64(data_out);
....@@ -433,41 +696,105 @@
433696 return ret;
434697 }
435698
436
-int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
699
+int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr)
700
+{
701
+ union bpf_attr attr;
702
+ int ret;
703
+
704
+ if (!test_attr->data_out && test_attr->data_size_out > 0)
705
+ return -EINVAL;
706
+
707
+ memset(&attr, 0, sizeof(attr));
708
+ attr.test.prog_fd = test_attr->prog_fd;
709
+ attr.test.data_in = ptr_to_u64(test_attr->data_in);
710
+ attr.test.data_out = ptr_to_u64(test_attr->data_out);
711
+ attr.test.data_size_in = test_attr->data_size_in;
712
+ attr.test.data_size_out = test_attr->data_size_out;
713
+ attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in);
714
+ attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out);
715
+ attr.test.ctx_size_in = test_attr->ctx_size_in;
716
+ attr.test.ctx_size_out = test_attr->ctx_size_out;
717
+ attr.test.repeat = test_attr->repeat;
718
+
719
+ ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
720
+ test_attr->data_size_out = attr.test.data_size_out;
721
+ test_attr->ctx_size_out = attr.test.ctx_size_out;
722
+ test_attr->retval = attr.test.retval;
723
+ test_attr->duration = attr.test.duration;
724
+ return ret;
725
+}
726
+
727
+int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
728
+{
729
+ union bpf_attr attr;
730
+ int ret;
731
+
732
+ if (!OPTS_VALID(opts, bpf_test_run_opts))
733
+ return -EINVAL;
734
+
735
+ memset(&attr, 0, sizeof(attr));
736
+ attr.test.prog_fd = prog_fd;
737
+ attr.test.cpu = OPTS_GET(opts, cpu, 0);
738
+ attr.test.flags = OPTS_GET(opts, flags, 0);
739
+ attr.test.repeat = OPTS_GET(opts, repeat, 0);
740
+ attr.test.duration = OPTS_GET(opts, duration, 0);
741
+ attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0);
742
+ attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0);
743
+ attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
744
+ attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
745
+ attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
746
+ attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
747
+ attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
748
+ attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
749
+
750
+ ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
751
+ OPTS_SET(opts, data_size_out, attr.test.data_size_out);
752
+ OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
753
+ OPTS_SET(opts, duration, attr.test.duration);
754
+ OPTS_SET(opts, retval, attr.test.retval);
755
+ return ret;
756
+}
757
+
758
+static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
437759 {
438760 union bpf_attr attr;
439761 int err;
440762
441
- bzero(&attr, sizeof(attr));
763
+ memset(&attr, 0, sizeof(attr));
442764 attr.start_id = start_id;
443765
444
- err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr));
766
+ err = sys_bpf(cmd, &attr, sizeof(attr));
445767 if (!err)
446768 *next_id = attr.next_id;
447769
448770 return err;
449771 }
450772
773
+int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
774
+{
775
+ return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID);
776
+}
777
+
451778 int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
452779 {
453
- union bpf_attr attr;
454
- int err;
780
+ return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID);
781
+}
455782
456
- bzero(&attr, sizeof(attr));
457
- attr.start_id = start_id;
783
+int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id)
784
+{
785
+ return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID);
786
+}
458787
459
- err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr));
460
- if (!err)
461
- *next_id = attr.next_id;
462
-
463
- return err;
788
+int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
789
+{
790
+ return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
464791 }
465792
466793 int bpf_prog_get_fd_by_id(__u32 id)
467794 {
468795 union bpf_attr attr;
469796
470
- bzero(&attr, sizeof(attr));
797
+ memset(&attr, 0, sizeof(attr));
471798 attr.prog_id = id;
472799
473800 return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
....@@ -477,7 +804,7 @@
477804 {
478805 union bpf_attr attr;
479806
480
- bzero(&attr, sizeof(attr));
807
+ memset(&attr, 0, sizeof(attr));
481808 attr.map_id = id;
482809
483810 return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
....@@ -487,19 +814,29 @@
487814 {
488815 union bpf_attr attr;
489816
490
- bzero(&attr, sizeof(attr));
817
+ memset(&attr, 0, sizeof(attr));
491818 attr.btf_id = id;
492819
493820 return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr));
494821 }
495822
496
-int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
823
+int bpf_link_get_fd_by_id(__u32 id)
824
+{
825
+ union bpf_attr attr;
826
+
827
+ memset(&attr, 0, sizeof(attr));
828
+ attr.link_id = id;
829
+
830
+ return sys_bpf(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr));
831
+}
832
+
833
+int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
497834 {
498835 union bpf_attr attr;
499836 int err;
500837
501
- bzero(&attr, sizeof(attr));
502
- attr.info.bpf_fd = prog_fd;
838
+ memset(&attr, 0, sizeof(attr));
839
+ attr.info.bpf_fd = bpf_fd;
503840 attr.info.info_len = *info_len;
504841 attr.info.info = ptr_to_u64(info);
505842
....@@ -514,135 +851,14 @@
514851 {
515852 union bpf_attr attr;
516853
517
- bzero(&attr, sizeof(attr));
854
+ memset(&attr, 0, sizeof(attr));
518855 attr.raw_tracepoint.name = ptr_to_u64(name);
519856 attr.raw_tracepoint.prog_fd = prog_fd;
520857
521858 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
522859 }
523860
524
-int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
525
-{
526
- struct sockaddr_nl sa;
527
- int sock, seq = 0, len, ret = -1;
528
- char buf[4096];
529
- struct nlattr *nla, *nla_xdp;
530
- struct {
531
- struct nlmsghdr nh;
532
- struct ifinfomsg ifinfo;
533
- char attrbuf[64];
534
- } req;
535
- struct nlmsghdr *nh;
536
- struct nlmsgerr *err;
537
- socklen_t addrlen;
538
- int one = 1;
539
-
540
- memset(&sa, 0, sizeof(sa));
541
- sa.nl_family = AF_NETLINK;
542
-
543
- sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
544
- if (sock < 0) {
545
- return -errno;
546
- }
547
-
548
- if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
549
- &one, sizeof(one)) < 0) {
550
- fprintf(stderr, "Netlink error reporting not supported\n");
551
- }
552
-
553
- if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
554
- ret = -errno;
555
- goto cleanup;
556
- }
557
-
558
- addrlen = sizeof(sa);
559
- if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
560
- ret = -errno;
561
- goto cleanup;
562
- }
563
-
564
- if (addrlen != sizeof(sa)) {
565
- ret = -LIBBPF_ERRNO__INTERNAL;
566
- goto cleanup;
567
- }
568
-
569
- memset(&req, 0, sizeof(req));
570
- req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
571
- req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
572
- req.nh.nlmsg_type = RTM_SETLINK;
573
- req.nh.nlmsg_pid = 0;
574
- req.nh.nlmsg_seq = ++seq;
575
- req.ifinfo.ifi_family = AF_UNSPEC;
576
- req.ifinfo.ifi_index = ifindex;
577
-
578
- /* started nested attribute for XDP */
579
- nla = (struct nlattr *)(((char *)&req)
580
- + NLMSG_ALIGN(req.nh.nlmsg_len));
581
- nla->nla_type = NLA_F_NESTED | IFLA_XDP;
582
- nla->nla_len = NLA_HDRLEN;
583
-
584
- /* add XDP fd */
585
- nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
586
- nla_xdp->nla_type = IFLA_XDP_FD;
587
- nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
588
- memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
589
- nla->nla_len += nla_xdp->nla_len;
590
-
591
- /* if user passed in any flags, add those too */
592
- if (flags) {
593
- nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
594
- nla_xdp->nla_type = IFLA_XDP_FLAGS;
595
- nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
596
- memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
597
- nla->nla_len += nla_xdp->nla_len;
598
- }
599
-
600
- req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
601
-
602
- if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
603
- ret = -errno;
604
- goto cleanup;
605
- }
606
-
607
- len = recv(sock, buf, sizeof(buf), 0);
608
- if (len < 0) {
609
- ret = -errno;
610
- goto cleanup;
611
- }
612
-
613
- for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
614
- nh = NLMSG_NEXT(nh, len)) {
615
- if (nh->nlmsg_pid != sa.nl_pid) {
616
- ret = -LIBBPF_ERRNO__WRNGPID;
617
- goto cleanup;
618
- }
619
- if (nh->nlmsg_seq != seq) {
620
- ret = -LIBBPF_ERRNO__INVSEQ;
621
- goto cleanup;
622
- }
623
- switch (nh->nlmsg_type) {
624
- case NLMSG_ERROR:
625
- err = (struct nlmsgerr *)NLMSG_DATA(nh);
626
- if (!err->error)
627
- continue;
628
- ret = err->error;
629
- nla_dump_errormsg(nh);
630
- goto cleanup;
631
- case NLMSG_DONE:
632
- break;
633
- default:
634
- break;
635
- }
636
- }
637
-
638
- ret = 0;
639
-
640
-cleanup:
641
- close(sock);
642
- return ret;
643
-}
644
-
645
-int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
861
+int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
646862 bool do_log)
647863 {
648864 union bpf_attr attr = {};
....@@ -689,3 +905,29 @@
689905
690906 return err;
691907 }
908
+
909
+int bpf_enable_stats(enum bpf_stats_type type)
910
+{
911
+ union bpf_attr attr;
912
+
913
+ memset(&attr, 0, sizeof(attr));
914
+ attr.enable_stats.type = type;
915
+
916
+ return sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr));
917
+}
918
+
919
+int bpf_prog_bind_map(int prog_fd, int map_fd,
920
+ const struct bpf_prog_bind_opts *opts)
921
+{
922
+ union bpf_attr attr;
923
+
924
+ if (!OPTS_VALID(opts, bpf_prog_bind_opts))
925
+ return -EINVAL;
926
+
927
+ memset(&attr, 0, sizeof(attr));
928
+ attr.prog_bind_map.prog_fd = prog_fd;
929
+ attr.prog_bind_map.map_fd = map_fd;
930
+ attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
931
+
932
+ return sys_bpf(BPF_PROG_BIND_MAP, &attr, sizeof(attr));
933
+}