1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
3 #include <test_progs.h>
4 #include "bpf_iter_ipv6_route.skel.h"
5 #include "bpf_iter_netlink.skel.h"
6 #include "bpf_iter_bpf_map.skel.h"
7 #include "bpf_iter_task.skel.h"
8 #include "bpf_iter_task_stack.skel.h"
9 #include "bpf_iter_task_file.skel.h"
10 #include "bpf_iter_task_vma.skel.h"
11 #include "bpf_iter_task_btf.skel.h"
12 #include "bpf_iter_tcp4.skel.h"
13 #include "bpf_iter_tcp6.skel.h"
14 #include "bpf_iter_udp4.skel.h"
15 #include "bpf_iter_udp6.skel.h"
16 #include "bpf_iter_unix.skel.h"
17 #include "bpf_iter_test_kern1.skel.h"
18 #include "bpf_iter_test_kern2.skel.h"
19 #include "bpf_iter_test_kern3.skel.h"
20 #include "bpf_iter_test_kern4.skel.h"
21 #include "bpf_iter_bpf_hash_map.skel.h"
22 #include "bpf_iter_bpf_percpu_hash_map.skel.h"
23 #include "bpf_iter_bpf_array_map.skel.h"
24 #include "bpf_iter_bpf_percpu_array_map.skel.h"
25 #include "bpf_iter_bpf_sk_storage_helpers.skel.h"
26 #include "bpf_iter_bpf_sk_storage_map.skel.h"
27 #include "bpf_iter_test_kern5.skel.h"
28 #include "bpf_iter_test_kern6.skel.h"
29 #include "bpf_iter_bpf_link.skel.h"
30 #include "bpf_iter_ksym.skel.h"
34 static void test_btf_id_or_null(void)
36 struct bpf_iter_test_kern3 *skel;
38 skel = bpf_iter_test_kern3__open_and_load();
39 if (!ASSERT_ERR_PTR(skel, "bpf_iter_test_kern3__open_and_load")) {
40 bpf_iter_test_kern3__destroy(skel);
45 static void do_dummy_read(struct bpf_program *prog)
47 struct bpf_link *link;
51 link = bpf_program__attach_iter(prog, NULL);
52 if (!ASSERT_OK_PTR(link, "attach_iter"))
55 iter_fd = bpf_iter_create(bpf_link__fd(link));
56 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
59 /* not check contents, but ensure read() ends without error */
60 while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
62 CHECK(len < 0, "read", "read failed: %s\n", strerror(errno));
67 bpf_link__destroy(link);
70 static int read_fd_into_buffer(int fd, char *buf, int size)
76 len = read(fd, buf, bufleft);
83 return len < 0 ? len : size - bufleft;
86 static void test_ipv6_route(void)
88 struct bpf_iter_ipv6_route *skel;
90 skel = bpf_iter_ipv6_route__open_and_load();
91 if (!ASSERT_OK_PTR(skel, "bpf_iter_ipv6_route__open_and_load"))
94 do_dummy_read(skel->progs.dump_ipv6_route);
96 bpf_iter_ipv6_route__destroy(skel);
99 static void test_netlink(void)
101 struct bpf_iter_netlink *skel;
103 skel = bpf_iter_netlink__open_and_load();
104 if (!ASSERT_OK_PTR(skel, "bpf_iter_netlink__open_and_load"))
107 do_dummy_read(skel->progs.dump_netlink);
109 bpf_iter_netlink__destroy(skel);
112 static void test_bpf_map(void)
114 struct bpf_iter_bpf_map *skel;
116 skel = bpf_iter_bpf_map__open_and_load();
117 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_map__open_and_load"))
120 do_dummy_read(skel->progs.dump_bpf_map);
122 bpf_iter_bpf_map__destroy(skel);
125 static void test_task(void)
127 struct bpf_iter_task *skel;
129 skel = bpf_iter_task__open_and_load();
130 if (!ASSERT_OK_PTR(skel, "bpf_iter_task__open_and_load"))
133 do_dummy_read(skel->progs.dump_task);
135 bpf_iter_task__destroy(skel);
138 static void test_task_sleepable(void)
140 struct bpf_iter_task *skel;
142 skel = bpf_iter_task__open_and_load();
143 if (!ASSERT_OK_PTR(skel, "bpf_iter_task__open_and_load"))
146 do_dummy_read(skel->progs.dump_task_sleepable);
148 ASSERT_GT(skel->bss->num_expected_failure_copy_from_user_task, 0,
149 "num_expected_failure_copy_from_user_task");
150 ASSERT_GT(skel->bss->num_success_copy_from_user_task, 0,
151 "num_success_copy_from_user_task");
153 bpf_iter_task__destroy(skel);
156 static void test_task_stack(void)
158 struct bpf_iter_task_stack *skel;
160 skel = bpf_iter_task_stack__open_and_load();
161 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_stack__open_and_load"))
164 do_dummy_read(skel->progs.dump_task_stack);
165 do_dummy_read(skel->progs.get_task_user_stacks);
167 bpf_iter_task_stack__destroy(skel);
170 static void *do_nothing(void *arg)
175 static void test_task_file(void)
177 struct bpf_iter_task_file *skel;
181 skel = bpf_iter_task_file__open_and_load();
182 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_file__open_and_load"))
185 skel->bss->tgid = getpid();
187 if (!ASSERT_OK(pthread_create(&thread_id, NULL, &do_nothing, NULL),
191 do_dummy_read(skel->progs.dump_task_file);
193 if (!ASSERT_FALSE(pthread_join(thread_id, &ret) || ret != NULL,
197 ASSERT_EQ(skel->bss->count, 0, "check_count");
200 bpf_iter_task_file__destroy(skel);
203 #define TASKBUFSZ 32768
205 static char taskbuf[TASKBUFSZ];
207 static int do_btf_read(struct bpf_iter_task_btf *skel)
209 struct bpf_program *prog = skel->progs.dump_task_struct;
210 struct bpf_iter_task_btf__bss *bss = skel->bss;
211 int iter_fd = -1, err;
212 struct bpf_link *link;
216 link = bpf_program__attach_iter(prog, NULL);
217 if (!ASSERT_OK_PTR(link, "attach_iter"))
220 iter_fd = bpf_iter_create(bpf_link__fd(link));
221 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
224 err = read_fd_into_buffer(iter_fd, buf, TASKBUFSZ);
226 printf("%s:SKIP:no __builtin_btf_type_id\n", __func__);
232 if (CHECK(err < 0, "read", "read failed: %s\n", strerror(errno)))
235 ASSERT_HAS_SUBSTR(taskbuf, "(struct task_struct)",
236 "check for btf representation of task_struct in iter data");
240 bpf_link__destroy(link);
244 static void test_task_btf(void)
246 struct bpf_iter_task_btf__bss *bss;
247 struct bpf_iter_task_btf *skel;
250 skel = bpf_iter_task_btf__open_and_load();
251 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_btf__open_and_load"))
256 ret = do_btf_read(skel);
260 if (!ASSERT_NEQ(bss->tasks, 0, "no task iteration, did BPF program run?"))
263 ASSERT_EQ(bss->seq_err, 0, "check for unexpected err");
266 bpf_iter_task_btf__destroy(skel);
269 static void test_tcp4(void)
271 struct bpf_iter_tcp4 *skel;
273 skel = bpf_iter_tcp4__open_and_load();
274 if (!ASSERT_OK_PTR(skel, "bpf_iter_tcp4__open_and_load"))
277 do_dummy_read(skel->progs.dump_tcp4);
279 bpf_iter_tcp4__destroy(skel);
282 static void test_tcp6(void)
284 struct bpf_iter_tcp6 *skel;
286 skel = bpf_iter_tcp6__open_and_load();
287 if (!ASSERT_OK_PTR(skel, "bpf_iter_tcp6__open_and_load"))
290 do_dummy_read(skel->progs.dump_tcp6);
292 bpf_iter_tcp6__destroy(skel);
295 static void test_udp4(void)
297 struct bpf_iter_udp4 *skel;
299 skel = bpf_iter_udp4__open_and_load();
300 if (!ASSERT_OK_PTR(skel, "bpf_iter_udp4__open_and_load"))
303 do_dummy_read(skel->progs.dump_udp4);
305 bpf_iter_udp4__destroy(skel);
308 static void test_udp6(void)
310 struct bpf_iter_udp6 *skel;
312 skel = bpf_iter_udp6__open_and_load();
313 if (!ASSERT_OK_PTR(skel, "bpf_iter_udp6__open_and_load"))
316 do_dummy_read(skel->progs.dump_udp6);
318 bpf_iter_udp6__destroy(skel);
321 static void test_unix(void)
323 struct bpf_iter_unix *skel;
325 skel = bpf_iter_unix__open_and_load();
326 if (!ASSERT_OK_PTR(skel, "bpf_iter_unix__open_and_load"))
329 do_dummy_read(skel->progs.dump_unix);
331 bpf_iter_unix__destroy(skel);
334 /* The expected string is less than 16 bytes */
335 static int do_read_with_fd(int iter_fd, const char *expected,
338 int len, read_buf_len, start;
341 read_buf_len = read_one_char ? 1 : 16;
343 while ((len = read(iter_fd, buf + start, read_buf_len)) > 0) {
345 if (CHECK(start >= 16, "read", "read len %d\n", len))
347 read_buf_len = read_one_char ? 1 : 16 - start;
349 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
352 if (!ASSERT_STREQ(buf, expected, "read"))
358 static void test_anon_iter(bool read_one_char)
360 struct bpf_iter_test_kern1 *skel;
361 struct bpf_link *link;
364 skel = bpf_iter_test_kern1__open_and_load();
365 if (!ASSERT_OK_PTR(skel, "bpf_iter_test_kern1__open_and_load"))
368 err = bpf_iter_test_kern1__attach(skel);
369 if (!ASSERT_OK(err, "bpf_iter_test_kern1__attach")) {
373 link = skel->links.dump_task;
374 iter_fd = bpf_iter_create(bpf_link__fd(link));
375 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
378 do_read_with_fd(iter_fd, "abcd", read_one_char);
382 bpf_iter_test_kern1__destroy(skel);
385 static int do_read(const char *path, const char *expected)
389 iter_fd = open(path, O_RDONLY);
390 if (CHECK(iter_fd < 0, "open", "open %s failed: %s\n",
391 path, strerror(errno)))
394 err = do_read_with_fd(iter_fd, expected, false);
399 static void test_file_iter(void)
401 const char *path = "/sys/fs/bpf/bpf_iter_test1";
402 struct bpf_iter_test_kern1 *skel1;
403 struct bpf_iter_test_kern2 *skel2;
404 struct bpf_link *link;
407 skel1 = bpf_iter_test_kern1__open_and_load();
408 if (!ASSERT_OK_PTR(skel1, "bpf_iter_test_kern1__open_and_load"))
411 link = bpf_program__attach_iter(skel1->progs.dump_task, NULL);
412 if (!ASSERT_OK_PTR(link, "attach_iter"))
415 /* unlink this path if it exists. */
418 err = bpf_link__pin(link, path);
419 if (CHECK(err, "pin_iter", "pin_iter to %s failed: %d\n", path, err))
422 err = do_read(path, "abcd");
426 /* file based iterator seems working fine. Let us a link update
427 * of the underlying link and `cat` the iterator again, its content
430 skel2 = bpf_iter_test_kern2__open_and_load();
431 if (!ASSERT_OK_PTR(skel2, "bpf_iter_test_kern2__open_and_load"))
434 err = bpf_link__update_program(link, skel2->progs.dump_task);
435 if (!ASSERT_OK(err, "update_prog"))
438 do_read(path, "ABCD");
441 bpf_iter_test_kern2__destroy(skel2);
445 bpf_link__destroy(link);
447 bpf_iter_test_kern1__destroy(skel1);
450 static void test_overflow(bool test_e2big_overflow, bool ret1)
452 __u32 map_info_len, total_read_len, expected_read_len;
453 int err, iter_fd, map1_fd, map2_fd, len;
454 struct bpf_map_info map_info = {};
455 struct bpf_iter_test_kern4 *skel;
456 struct bpf_link *link;
460 skel = bpf_iter_test_kern4__open();
461 if (!ASSERT_OK_PTR(skel, "bpf_iter_test_kern4__open"))
464 /* create two maps: bpf program will only do bpf_seq_write
465 * for these two maps. The goal is one map output almost
466 * fills seq_file buffer and then the other will trigger
467 * overflow and needs restart.
469 map1_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 8, 1, NULL);
470 if (CHECK(map1_fd < 0, "bpf_map_create",
471 "map_creation failed: %s\n", strerror(errno)))
473 map2_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 8, 1, NULL);
474 if (CHECK(map2_fd < 0, "bpf_map_create",
475 "map_creation failed: %s\n", strerror(errno)))
478 /* bpf_seq_printf kernel buffer is 8 pages, so one map
479 * bpf_seq_write will mostly fill it, and the other map
480 * will partially fill and then trigger overflow and need
481 * bpf_seq_read restart.
483 iter_size = sysconf(_SC_PAGE_SIZE) << 3;
485 if (test_e2big_overflow) {
486 skel->rodata->print_len = (iter_size + 8) / 8;
487 expected_read_len = 2 * (iter_size + 8);
489 skel->rodata->print_len = (iter_size - 8) / 8;
490 expected_read_len = 2 * (iter_size - 8);
492 skel->rodata->print_len = 1;
493 expected_read_len = 2 * 8;
495 skel->rodata->ret1 = ret1;
497 if (!ASSERT_OK(bpf_iter_test_kern4__load(skel),
498 "bpf_iter_test_kern4__load"))
501 /* setup filtering map_id in bpf program */
502 map_info_len = sizeof(map_info);
503 err = bpf_obj_get_info_by_fd(map1_fd, &map_info, &map_info_len);
504 if (CHECK(err, "get_map_info", "get map info failed: %s\n",
507 skel->bss->map1_id = map_info.id;
509 err = bpf_obj_get_info_by_fd(map2_fd, &map_info, &map_info_len);
510 if (CHECK(err, "get_map_info", "get map info failed: %s\n",
513 skel->bss->map2_id = map_info.id;
515 link = bpf_program__attach_iter(skel->progs.dump_bpf_map, NULL);
516 if (!ASSERT_OK_PTR(link, "attach_iter"))
519 iter_fd = bpf_iter_create(bpf_link__fd(link));
520 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
523 buf = malloc(expected_read_len);
529 if (test_e2big_overflow) {
530 while ((len = read(iter_fd, buf, expected_read_len)) > 0)
531 total_read_len += len;
533 CHECK(len != -1 || errno != E2BIG, "read",
534 "expected ret -1, errno E2BIG, but get ret %d, error %s\n",
535 len, strerror(errno));
538 while ((len = read(iter_fd, buf, expected_read_len)) > 0)
539 total_read_len += len;
541 if (CHECK(len < 0, "read", "read failed: %s\n",
546 len = read(iter_fd, buf, expected_read_len);
548 total_read_len += len;
549 } while (len > 0 || len == -EAGAIN);
551 if (CHECK(len < 0, "read", "read failed: %s\n",
556 if (!ASSERT_EQ(total_read_len, expected_read_len, "read"))
559 if (!ASSERT_EQ(skel->bss->map1_accessed, 1, "map1_accessed"))
562 if (!ASSERT_EQ(skel->bss->map2_accessed, 2, "map2_accessed"))
565 ASSERT_EQ(skel->bss->map2_seqnum1, skel->bss->map2_seqnum2, "map2_seqnum");
572 bpf_link__destroy(link);
578 bpf_iter_test_kern4__destroy(skel);
581 static void test_bpf_hash_map(void)
583 __u32 expected_key_a = 0, expected_key_b = 0;
584 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
585 struct bpf_iter_bpf_hash_map *skel;
586 int err, i, len, map_fd, iter_fd;
587 union bpf_iter_link_info linfo;
588 __u64 val, expected_val = 0;
589 struct bpf_link *link;
597 skel = bpf_iter_bpf_hash_map__open();
598 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_hash_map__open"))
601 skel->bss->in_test_mode = true;
603 err = bpf_iter_bpf_hash_map__load(skel);
604 if (!ASSERT_OK(err, "bpf_iter_bpf_hash_map__load"))
607 /* iterator with hashmap2 and hashmap3 should fail */
608 memset(&linfo, 0, sizeof(linfo));
609 linfo.map.map_fd = bpf_map__fd(skel->maps.hashmap2);
610 opts.link_info = &linfo;
611 opts.link_info_len = sizeof(linfo);
612 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts);
613 if (!ASSERT_ERR_PTR(link, "attach_iter"))
616 linfo.map.map_fd = bpf_map__fd(skel->maps.hashmap3);
617 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts);
618 if (!ASSERT_ERR_PTR(link, "attach_iter"))
621 /* hashmap1 should be good, update map values here */
622 map_fd = bpf_map__fd(skel->maps.hashmap1);
623 for (i = 0; i < bpf_map__max_entries(skel->maps.hashmap1); i++) {
628 expected_key_a += key.a;
629 expected_key_b += key.b;
632 err = bpf_map_update_elem(map_fd, &key, &val, BPF_ANY);
633 if (!ASSERT_OK(err, "map_update"))
637 linfo.map.map_fd = map_fd;
638 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts);
639 if (!ASSERT_OK_PTR(link, "attach_iter"))
642 iter_fd = bpf_iter_create(bpf_link__fd(link));
643 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
647 while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
649 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
653 if (!ASSERT_EQ(skel->bss->key_sum_a, expected_key_a, "key_sum_a"))
655 if (!ASSERT_EQ(skel->bss->key_sum_b, expected_key_b, "key_sum_b"))
657 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum"))
663 bpf_link__destroy(link);
665 bpf_iter_bpf_hash_map__destroy(skel);
668 static void test_bpf_percpu_hash_map(void)
670 __u32 expected_key_a = 0, expected_key_b = 0;
671 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
672 struct bpf_iter_bpf_percpu_hash_map *skel;
673 int err, i, j, len, map_fd, iter_fd;
674 union bpf_iter_link_info linfo;
675 __u32 expected_val = 0;
676 struct bpf_link *link;
685 skel = bpf_iter_bpf_percpu_hash_map__open();
686 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_hash_map__open"))
689 skel->rodata->num_cpus = bpf_num_possible_cpus();
690 val = malloc(8 * bpf_num_possible_cpus());
692 err = bpf_iter_bpf_percpu_hash_map__load(skel);
693 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_hash_map__load"))
696 /* update map values here */
697 map_fd = bpf_map__fd(skel->maps.hashmap1);
698 for (i = 0; i < bpf_map__max_entries(skel->maps.hashmap1); i++) {
702 expected_key_a += key.a;
703 expected_key_b += key.b;
705 for (j = 0; j < bpf_num_possible_cpus(); j++) {
706 *(__u32 *)(val + j * 8) = i + j;
707 expected_val += i + j;
710 err = bpf_map_update_elem(map_fd, &key, val, BPF_ANY);
711 if (!ASSERT_OK(err, "map_update"))
715 memset(&linfo, 0, sizeof(linfo));
716 linfo.map.map_fd = map_fd;
717 opts.link_info = &linfo;
718 opts.link_info_len = sizeof(linfo);
719 link = bpf_program__attach_iter(skel->progs.dump_bpf_percpu_hash_map, &opts);
720 if (!ASSERT_OK_PTR(link, "attach_iter"))
723 iter_fd = bpf_iter_create(bpf_link__fd(link));
724 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
728 while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
730 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
734 if (!ASSERT_EQ(skel->bss->key_sum_a, expected_key_a, "key_sum_a"))
736 if (!ASSERT_EQ(skel->bss->key_sum_b, expected_key_b, "key_sum_b"))
738 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum"))
744 bpf_link__destroy(link);
746 bpf_iter_bpf_percpu_hash_map__destroy(skel);
750 static void test_bpf_array_map(void)
752 __u64 val, expected_val = 0, res_first_val, first_val = 0;
753 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
754 __u32 expected_key = 0, res_first_key;
755 struct bpf_iter_bpf_array_map *skel;
756 union bpf_iter_link_info linfo;
757 int err, i, map_fd, iter_fd;
758 struct bpf_link *link;
762 skel = bpf_iter_bpf_array_map__open_and_load();
763 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_array_map__open_and_load"))
766 map_fd = bpf_map__fd(skel->maps.arraymap1);
767 for (i = 0; i < bpf_map__max_entries(skel->maps.arraymap1); i++) {
775 err = bpf_map_update_elem(map_fd, &i, &val, BPF_ANY);
776 if (!ASSERT_OK(err, "map_update"))
780 memset(&linfo, 0, sizeof(linfo));
781 linfo.map.map_fd = map_fd;
782 opts.link_info = &linfo;
783 opts.link_info_len = sizeof(linfo);
784 link = bpf_program__attach_iter(skel->progs.dump_bpf_array_map, &opts);
785 if (!ASSERT_OK_PTR(link, "attach_iter"))
788 iter_fd = bpf_iter_create(bpf_link__fd(link));
789 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
794 while ((len = read(iter_fd, buf + start, sizeof(buf) - start)) > 0)
796 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
800 res_first_key = *(__u32 *)buf;
801 res_first_val = *(__u64 *)(buf + sizeof(__u32));
802 if (CHECK(res_first_key != 0 || res_first_val != first_val,
804 "seq_write failure: first key %u vs expected 0, "
805 " first value %llu vs expected %llu\n",
806 res_first_key, res_first_val, first_val))
809 if (!ASSERT_EQ(skel->bss->key_sum, expected_key, "key_sum"))
811 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum"))
814 for (i = 0; i < bpf_map__max_entries(skel->maps.arraymap1); i++) {
815 err = bpf_map_lookup_elem(map_fd, &i, &val);
816 if (!ASSERT_OK(err, "map_lookup"))
818 if (!ASSERT_EQ(i, val, "invalid_val"))
825 bpf_link__destroy(link);
827 bpf_iter_bpf_array_map__destroy(skel);
830 static void test_bpf_percpu_array_map(void)
832 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
833 struct bpf_iter_bpf_percpu_array_map *skel;
834 __u32 expected_key = 0, expected_val = 0;
835 union bpf_iter_link_info linfo;
836 int err, i, j, map_fd, iter_fd;
837 struct bpf_link *link;
842 skel = bpf_iter_bpf_percpu_array_map__open();
843 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_array_map__open"))
846 skel->rodata->num_cpus = bpf_num_possible_cpus();
847 val = malloc(8 * bpf_num_possible_cpus());
849 err = bpf_iter_bpf_percpu_array_map__load(skel);
850 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_array_map__load"))
853 /* update map values here */
854 map_fd = bpf_map__fd(skel->maps.arraymap1);
855 for (i = 0; i < bpf_map__max_entries(skel->maps.arraymap1); i++) {
858 for (j = 0; j < bpf_num_possible_cpus(); j++) {
859 *(__u32 *)(val + j * 8) = i + j;
860 expected_val += i + j;
863 err = bpf_map_update_elem(map_fd, &i, val, BPF_ANY);
864 if (!ASSERT_OK(err, "map_update"))
868 memset(&linfo, 0, sizeof(linfo));
869 linfo.map.map_fd = map_fd;
870 opts.link_info = &linfo;
871 opts.link_info_len = sizeof(linfo);
872 link = bpf_program__attach_iter(skel->progs.dump_bpf_percpu_array_map, &opts);
873 if (!ASSERT_OK_PTR(link, "attach_iter"))
876 iter_fd = bpf_iter_create(bpf_link__fd(link));
877 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
881 while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
883 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
887 if (!ASSERT_EQ(skel->bss->key_sum, expected_key, "key_sum"))
889 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum"))
895 bpf_link__destroy(link);
897 bpf_iter_bpf_percpu_array_map__destroy(skel);
901 /* An iterator program deletes all local storage in a map. */
902 static void test_bpf_sk_storage_delete(void)
904 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
905 struct bpf_iter_bpf_sk_storage_helpers *skel;
906 union bpf_iter_link_info linfo;
907 int err, len, map_fd, iter_fd;
908 struct bpf_link *link;
913 skel = bpf_iter_bpf_sk_storage_helpers__open_and_load();
914 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load"))
917 map_fd = bpf_map__fd(skel->maps.sk_stg_map);
919 sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
920 if (!ASSERT_GE(sock_fd, 0, "socket"))
922 err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
923 if (!ASSERT_OK(err, "map_update"))
926 memset(&linfo, 0, sizeof(linfo));
927 linfo.map.map_fd = map_fd;
928 opts.link_info = &linfo;
929 opts.link_info_len = sizeof(linfo);
930 link = bpf_program__attach_iter(skel->progs.delete_bpf_sk_storage_map,
932 if (!ASSERT_OK_PTR(link, "attach_iter"))
935 iter_fd = bpf_iter_create(bpf_link__fd(link));
936 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
940 while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
942 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
946 err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
947 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem",
948 "map value wasn't deleted (err=%d, errno=%d)\n", err, errno))
954 bpf_link__destroy(link);
958 bpf_iter_bpf_sk_storage_helpers__destroy(skel);
961 /* This creates a socket and its local storage. It then runs a task_iter BPF
962 * program that replaces the existing socket local storage with the tgid of the
963 * only task owning a file descriptor to this socket, this process, prog_tests.
964 * It then runs a tcp socket iterator that negates the value in the existing
965 * socket local storage, the test verifies that the resulting value is -pid.
967 static void test_bpf_sk_storage_get(void)
969 struct bpf_iter_bpf_sk_storage_helpers *skel;
970 int err, map_fd, val = -1;
973 skel = bpf_iter_bpf_sk_storage_helpers__open_and_load();
974 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load"))
977 sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
978 if (!ASSERT_GE(sock_fd, 0, "socket"))
981 err = listen(sock_fd, 1);
982 if (!ASSERT_OK(err, "listen"))
985 map_fd = bpf_map__fd(skel->maps.sk_stg_map);
987 err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST);
988 if (!ASSERT_OK(err, "bpf_map_update_elem"))
991 do_dummy_read(skel->progs.fill_socket_owner);
993 err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
994 if (CHECK(err || val != getpid(), "bpf_map_lookup_elem",
995 "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
999 do_dummy_read(skel->progs.negate_socket_local_storage);
1001 err = bpf_map_lookup_elem(map_fd, &sock_fd, &val);
1002 CHECK(err || val != -getpid(), "bpf_map_lookup_elem",
1003 "map value wasn't set correctly (expected %d, got %d, err=%d)\n",
1004 -getpid(), val, err);
1009 bpf_iter_bpf_sk_storage_helpers__destroy(skel);
1012 static void test_bpf_sk_storage_map(void)
1014 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
1015 int err, i, len, map_fd, iter_fd, num_sockets;
1016 struct bpf_iter_bpf_sk_storage_map *skel;
1017 union bpf_iter_link_info linfo;
1018 int sock_fd[3] = {-1, -1, -1};
1019 __u32 val, expected_val = 0;
1020 struct bpf_link *link;
1023 skel = bpf_iter_bpf_sk_storage_map__open_and_load();
1024 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_map__open_and_load"))
1027 map_fd = bpf_map__fd(skel->maps.sk_stg_map);
1028 num_sockets = ARRAY_SIZE(sock_fd);
1029 for (i = 0; i < num_sockets; i++) {
1030 sock_fd[i] = socket(AF_INET6, SOCK_STREAM, 0);
1031 if (!ASSERT_GE(sock_fd[i], 0, "socket"))
1035 expected_val += val;
1037 err = bpf_map_update_elem(map_fd, &sock_fd[i], &val,
1039 if (!ASSERT_OK(err, "map_update"))
1043 memset(&linfo, 0, sizeof(linfo));
1044 linfo.map.map_fd = map_fd;
1045 opts.link_info = &linfo;
1046 opts.link_info_len = sizeof(linfo);
1047 link = bpf_program__attach_iter(skel->progs.dump_bpf_sk_storage_map, &opts);
1048 if (!ASSERT_OK_PTR(link, "attach_iter"))
1051 iter_fd = bpf_iter_create(bpf_link__fd(link));
1052 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
1056 while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
1058 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
1062 if (!ASSERT_EQ(skel->bss->ipv6_sk_count, num_sockets, "ipv6_sk_count"))
1065 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum"))
1071 bpf_link__destroy(link);
1073 for (i = 0; i < num_sockets; i++) {
1074 if (sock_fd[i] >= 0)
1077 bpf_iter_bpf_sk_storage_map__destroy(skel);
1080 static void test_rdonly_buf_out_of_bound(void)
1082 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
1083 struct bpf_iter_test_kern5 *skel;
1084 union bpf_iter_link_info linfo;
1085 struct bpf_link *link;
1087 skel = bpf_iter_test_kern5__open_and_load();
1088 if (!ASSERT_OK_PTR(skel, "bpf_iter_test_kern5__open_and_load"))
1091 memset(&linfo, 0, sizeof(linfo));
1092 linfo.map.map_fd = bpf_map__fd(skel->maps.hashmap1);
1093 opts.link_info = &linfo;
1094 opts.link_info_len = sizeof(linfo);
1095 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts);
1096 if (!ASSERT_ERR_PTR(link, "attach_iter"))
1097 bpf_link__destroy(link);
1099 bpf_iter_test_kern5__destroy(skel);
1102 static void test_buf_neg_offset(void)
1104 struct bpf_iter_test_kern6 *skel;
1106 skel = bpf_iter_test_kern6__open_and_load();
1107 if (!ASSERT_ERR_PTR(skel, "bpf_iter_test_kern6__open_and_load"))
1108 bpf_iter_test_kern6__destroy(skel);
1111 static void test_link_iter(void)
1113 struct bpf_iter_bpf_link *skel;
1115 skel = bpf_iter_bpf_link__open_and_load();
1116 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_link__open_and_load"))
1119 do_dummy_read(skel->progs.dump_bpf_link);
1121 bpf_iter_bpf_link__destroy(skel);
1124 static void test_ksym_iter(void)
1126 struct bpf_iter_ksym *skel;
1128 skel = bpf_iter_ksym__open_and_load();
1129 if (!ASSERT_OK_PTR(skel, "bpf_iter_ksym__open_and_load"))
1132 do_dummy_read(skel->progs.dump_ksym);
1134 bpf_iter_ksym__destroy(skel);
1137 #define CMP_BUFFER_SIZE 1024
1138 static char task_vma_output[CMP_BUFFER_SIZE];
1139 static char proc_maps_output[CMP_BUFFER_SIZE];
1141 /* remove \0 and \t from str, and only keep the first line */
1142 static void str_strip_first_line(char *str)
1144 char *dst = str, *src = str;
1147 if (*src == ' ' || *src == '\t')
1150 *(dst++) = *(src++);
1152 } while (*src != '\0' && *src != '\n');
1157 static void test_task_vma(void)
1159 int err, iter_fd = -1, proc_maps_fd = -1;
1160 struct bpf_iter_task_vma *skel;
1161 int len, read_size = 4;
1164 skel = bpf_iter_task_vma__open();
1165 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_vma__open"))
1168 skel->bss->pid = getpid();
1170 err = bpf_iter_task_vma__load(skel);
1171 if (!ASSERT_OK(err, "bpf_iter_task_vma__load"))
1174 skel->links.proc_maps = bpf_program__attach_iter(
1175 skel->progs.proc_maps, NULL);
1177 if (!ASSERT_OK_PTR(skel->links.proc_maps, "bpf_program__attach_iter")) {
1178 skel->links.proc_maps = NULL;
1182 iter_fd = bpf_iter_create(bpf_link__fd(skel->links.proc_maps));
1183 if (!ASSERT_GE(iter_fd, 0, "create_iter"))
1186 /* Read CMP_BUFFER_SIZE (1kB) from bpf_iter. Read in small chunks
1187 * to trigger seq_file corner cases.
1190 while (len < CMP_BUFFER_SIZE) {
1191 err = read_fd_into_buffer(iter_fd, task_vma_output + len,
1192 MIN(read_size, CMP_BUFFER_SIZE - len));
1195 if (!ASSERT_GE(err, 0, "read_iter_fd"))
1200 /* read CMP_BUFFER_SIZE (1kB) from /proc/pid/maps */
1201 snprintf(maps_path, 64, "/proc/%u/maps", skel->bss->pid);
1202 proc_maps_fd = open(maps_path, O_RDONLY);
1203 if (!ASSERT_GE(proc_maps_fd, 0, "open_proc_maps"))
1205 err = read_fd_into_buffer(proc_maps_fd, proc_maps_output, CMP_BUFFER_SIZE);
1206 if (!ASSERT_GE(err, 0, "read_prog_maps_fd"))
1209 /* strip and compare the first line of the two files */
1210 str_strip_first_line(task_vma_output);
1211 str_strip_first_line(proc_maps_output);
1213 ASSERT_STREQ(task_vma_output, proc_maps_output, "compare_output");
1215 close(proc_maps_fd);
1217 bpf_iter_task_vma__destroy(skel);
1220 void test_bpf_iter(void)
1222 if (test__start_subtest("btf_id_or_null"))
1223 test_btf_id_or_null();
1224 if (test__start_subtest("ipv6_route"))
1226 if (test__start_subtest("netlink"))
1228 if (test__start_subtest("bpf_map"))
1230 if (test__start_subtest("task"))
1232 if (test__start_subtest("task_sleepable"))
1233 test_task_sleepable();
1234 if (test__start_subtest("task_stack"))
1236 if (test__start_subtest("task_file"))
1238 if (test__start_subtest("task_vma"))
1240 if (test__start_subtest("task_btf"))
1242 if (test__start_subtest("tcp4"))
1244 if (test__start_subtest("tcp6"))
1246 if (test__start_subtest("udp4"))
1248 if (test__start_subtest("udp6"))
1250 if (test__start_subtest("unix"))
1252 if (test__start_subtest("anon"))
1253 test_anon_iter(false);
1254 if (test__start_subtest("anon-read-one-char"))
1255 test_anon_iter(true);
1256 if (test__start_subtest("file"))
1258 if (test__start_subtest("overflow"))
1259 test_overflow(false, false);
1260 if (test__start_subtest("overflow-e2big"))
1261 test_overflow(true, false);
1262 if (test__start_subtest("prog-ret-1"))
1263 test_overflow(false, true);
1264 if (test__start_subtest("bpf_hash_map"))
1265 test_bpf_hash_map();
1266 if (test__start_subtest("bpf_percpu_hash_map"))
1267 test_bpf_percpu_hash_map();
1268 if (test__start_subtest("bpf_array_map"))
1269 test_bpf_array_map();
1270 if (test__start_subtest("bpf_percpu_array_map"))
1271 test_bpf_percpu_array_map();
1272 if (test__start_subtest("bpf_sk_storage_map"))
1273 test_bpf_sk_storage_map();
1274 if (test__start_subtest("bpf_sk_storage_delete"))
1275 test_bpf_sk_storage_delete();
1276 if (test__start_subtest("bpf_sk_storage_get"))
1277 test_bpf_sk_storage_get();
1278 if (test__start_subtest("rdonly-buf-out-of-bound"))
1279 test_rdonly_buf_out_of_bound();
1280 if (test__start_subtest("buf-neg-offset"))
1281 test_buf_neg_offset();
1282 if (test__start_subtest("link-iter"))
1284 if (test__start_subtest("ksym"))