1 /* Copyright (c) 2017 Facebook
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
17 #include <linux/types.h>
18 typedef __u16 __sum16;
19 #include <arpa/inet.h>
20 #include <linux/if_ether.h>
21 #include <linux/if_packet.h>
23 #include <linux/ipv6.h>
24 #include <linux/tcp.h>
25 #include <linux/filter.h>
26 #include <linux/perf_event.h>
27 #include <linux/unistd.h>
29 #include <sys/ioctl.h>
31 #include <sys/types.h>
35 #include <linux/bpf.h>
36 #include <linux/err.h>
38 #include <bpf/libbpf.h>
40 #include "test_iptunnel_common.h"
42 #include "bpf_endian.h"
43 #include "bpf_rlimit.h"
44 #include "trace_helpers.h"
45 #include "flow_dissector_load.h"
47 static int error_cnt, pass_cnt;
48 static bool jit_enabled;
50 #define MAGIC_BYTES 123
52 /* ipv4 test vector */
58 .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
60 .iph.protocol = IPPROTO_TCP,
61 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
66 /* ipv6 test vector */
72 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
73 .iph.nexthdr = IPPROTO_TCP,
74 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
79 #define _CHECK(condition, tag, duration, format...) ({ \
80 int __ret = !!(condition); \
83 printf("%s:FAIL:%s ", __func__, tag); \
87 printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\
92 #define CHECK(condition, tag, format...) \
93 _CHECK(condition, tag, duration, format)
94 #define CHECK_ATTR(condition, tag, format...) \
95 _CHECK(condition, tag, tattr.duration, format)
97 static int bpf_find_map(const char *test, struct bpf_object *obj,
102 map = bpf_object__find_map_by_name(obj, name);
104 printf("%s:FAIL:map '%s' not found\n", test, name);
108 return bpf_map__fd(map);
111 static void test_pkt_access(void)
113 const char *file = "./test_pkt_access.o";
114 struct bpf_object *obj;
115 __u32 duration, retval;
118 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
124 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
125 NULL, NULL, &retval, &duration);
126 CHECK(err || retval, "ipv4",
127 "err %d errno %d retval %d duration %d\n",
128 err, errno, retval, duration);
130 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v6, sizeof(pkt_v6),
131 NULL, NULL, &retval, &duration);
132 CHECK(err || retval, "ipv6",
133 "err %d errno %d retval %d duration %d\n",
134 err, errno, retval, duration);
135 bpf_object__close(obj);
138 static void test_prog_run_xattr(void)
140 const char *file = "./test_pkt_access.o";
141 struct bpf_object *obj;
144 struct bpf_prog_test_run_attr tattr = {
147 .data_size_in = sizeof(pkt_v4),
152 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj,
154 if (CHECK_ATTR(err, "load", "err %d errno %d\n", err, errno))
157 memset(buf, 0, sizeof(buf));
159 err = bpf_prog_test_run_xattr(&tattr);
160 CHECK_ATTR(err != -1 || errno != ENOSPC || tattr.retval, "run",
161 "err %d errno %d retval %d\n", err, errno, tattr.retval);
163 CHECK_ATTR(tattr.data_size_out != sizeof(pkt_v4), "data_size_out",
164 "incorrect output size, want %lu have %u\n",
165 sizeof(pkt_v4), tattr.data_size_out);
167 CHECK_ATTR(buf[5] != 0, "overflow",
168 "BPF_PROG_TEST_RUN ignored size hint\n");
170 tattr.data_out = NULL;
171 tattr.data_size_out = 0;
174 err = bpf_prog_test_run_xattr(&tattr);
175 CHECK_ATTR(err || errno || tattr.retval, "run_no_output",
176 "err %d errno %d retval %d\n", err, errno, tattr.retval);
178 tattr.data_size_out = 1;
179 err = bpf_prog_test_run_xattr(&tattr);
180 CHECK_ATTR(err != -EINVAL, "run_wrong_size_out", "err %d\n", err);
182 bpf_object__close(obj);
185 static void test_xdp(void)
187 struct vip key4 = {.protocol = 6, .family = AF_INET};
188 struct vip key6 = {.protocol = 6, .family = AF_INET6};
189 struct iptnl_info value4 = {.family = AF_INET};
190 struct iptnl_info value6 = {.family = AF_INET6};
191 const char *file = "./test_xdp.o";
192 struct bpf_object *obj;
194 struct ipv6hdr *iph6 = (void *)buf + sizeof(struct ethhdr);
195 struct iphdr *iph = (void *)buf + sizeof(struct ethhdr);
196 __u32 duration, retval, size;
197 int err, prog_fd, map_fd;
199 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
205 map_fd = bpf_find_map(__func__, obj, "vip2tnl");
208 bpf_map_update_elem(map_fd, &key4, &value4, 0);
209 bpf_map_update_elem(map_fd, &key6, &value6, 0);
211 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
212 buf, &size, &retval, &duration);
214 CHECK(err || retval != XDP_TX || size != 74 ||
215 iph->protocol != IPPROTO_IPIP, "ipv4",
216 "err %d errno %d retval %d size %d\n",
217 err, errno, retval, size);
219 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
220 buf, &size, &retval, &duration);
221 CHECK(err || retval != XDP_TX || size != 114 ||
222 iph6->nexthdr != IPPROTO_IPV6, "ipv6",
223 "err %d errno %d retval %d size %d\n",
224 err, errno, retval, size);
226 bpf_object__close(obj);
229 static void test_xdp_adjust_tail(void)
231 const char *file = "./test_adjust_tail.o";
232 struct bpf_object *obj;
234 __u32 duration, retval, size;
237 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
243 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
244 buf, &size, &retval, &duration);
246 CHECK(err || retval != XDP_DROP,
247 "ipv4", "err %d errno %d retval %d size %d\n",
248 err, errno, retval, size);
250 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
251 buf, &size, &retval, &duration);
252 CHECK(err || retval != XDP_TX || size != 54,
253 "ipv6", "err %d errno %d retval %d size %d\n",
254 err, errno, retval, size);
255 bpf_object__close(obj);
260 #define MAGIC_VAL 0x1234
261 #define NUM_ITER 100000
264 static void test_l4lb(const char *file)
266 unsigned int nr_cpus = bpf_num_possible_cpus();
267 struct vip key = {.protocol = 6};
271 } value = {.vip_num = VIP_NUM};
272 __u32 stats_key = VIP_NUM;
277 struct real_definition {
283 } real_def = {.dst = MAGIC_VAL};
284 __u32 ch_key = 11, real_num = 3;
285 __u32 duration, retval, size;
286 int err, i, prog_fd, map_fd;
287 __u64 bytes = 0, pkts = 0;
288 struct bpf_object *obj;
290 u32 *magic = (u32 *)buf;
292 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
298 map_fd = bpf_find_map(__func__, obj, "vip_map");
301 bpf_map_update_elem(map_fd, &key, &value, 0);
303 map_fd = bpf_find_map(__func__, obj, "ch_rings");
306 bpf_map_update_elem(map_fd, &ch_key, &real_num, 0);
308 map_fd = bpf_find_map(__func__, obj, "reals");
311 bpf_map_update_elem(map_fd, &real_num, &real_def, 0);
313 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
314 buf, &size, &retval, &duration);
315 CHECK(err || retval != 7/*TC_ACT_REDIRECT*/ || size != 54 ||
316 *magic != MAGIC_VAL, "ipv4",
317 "err %d errno %d retval %d size %d magic %x\n",
318 err, errno, retval, size, *magic);
320 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
321 buf, &size, &retval, &duration);
322 CHECK(err || retval != 7/*TC_ACT_REDIRECT*/ || size != 74 ||
323 *magic != MAGIC_VAL, "ipv6",
324 "err %d errno %d retval %d size %d magic %x\n",
325 err, errno, retval, size, *magic);
327 map_fd = bpf_find_map(__func__, obj, "stats");
330 bpf_map_lookup_elem(map_fd, &stats_key, stats);
331 for (i = 0; i < nr_cpus; i++) {
332 bytes += stats[i].bytes;
333 pkts += stats[i].pkts;
335 if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
337 printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
340 bpf_object__close(obj);
343 static void test_l4lb_all(void)
345 const char *file1 = "./test_l4lb.o";
346 const char *file2 = "./test_l4lb_noinline.o";
352 static void test_xdp_noinline(void)
354 const char *file = "./test_xdp_noinline.o";
355 unsigned int nr_cpus = bpf_num_possible_cpus();
356 struct vip key = {.protocol = 6};
360 } value = {.vip_num = VIP_NUM};
361 __u32 stats_key = VIP_NUM;
366 struct real_definition {
372 } real_def = {.dst = MAGIC_VAL};
373 __u32 ch_key = 11, real_num = 3;
374 __u32 duration, retval, size;
375 int err, i, prog_fd, map_fd;
376 __u64 bytes = 0, pkts = 0;
377 struct bpf_object *obj;
379 u32 *magic = (u32 *)buf;
381 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
387 map_fd = bpf_find_map(__func__, obj, "vip_map");
390 bpf_map_update_elem(map_fd, &key, &value, 0);
392 map_fd = bpf_find_map(__func__, obj, "ch_rings");
395 bpf_map_update_elem(map_fd, &ch_key, &real_num, 0);
397 map_fd = bpf_find_map(__func__, obj, "reals");
400 bpf_map_update_elem(map_fd, &real_num, &real_def, 0);
402 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
403 buf, &size, &retval, &duration);
404 CHECK(err || retval != 1 || size != 54 ||
405 *magic != MAGIC_VAL, "ipv4",
406 "err %d errno %d retval %d size %d magic %x\n",
407 err, errno, retval, size, *magic);
409 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
410 buf, &size, &retval, &duration);
411 CHECK(err || retval != 1 || size != 74 ||
412 *magic != MAGIC_VAL, "ipv6",
413 "err %d errno %d retval %d size %d magic %x\n",
414 err, errno, retval, size, *magic);
416 map_fd = bpf_find_map(__func__, obj, "stats");
419 bpf_map_lookup_elem(map_fd, &stats_key, stats);
420 for (i = 0; i < nr_cpus; i++) {
421 bytes += stats[i].bytes;
422 pkts += stats[i].pkts;
424 if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
426 printf("test_xdp_noinline:FAIL:stats %lld %lld\n", bytes, pkts);
429 bpf_object__close(obj);
432 static void test_tcp_estats(void)
434 const char *file = "./test_tcp_estats.o";
436 struct bpf_object *obj;
439 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
440 CHECK(err, "", "err %d errno %d\n", err, errno);
446 bpf_object__close(obj);
449 static inline __u64 ptr_to_u64(const void *ptr)
451 return (__u64) (unsigned long) ptr;
454 static bool is_jit_enabled(void)
456 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
457 bool enabled = false;
460 sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
461 if (sysctl_fd != -1) {
464 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
465 enabled = (tmpc != '0');
472 static void test_bpf_obj_id(void)
474 const __u64 array_magic_value = 0xfaceb00c;
475 const __u32 array_key = 0;
476 const int nr_iters = 2;
477 const char *file = "./test_obj_id.o";
478 const char *expected_prog_name = "test_obj_id";
479 const char *expected_map_name = "test_map_id";
480 const __u64 nsec_per_sec = 1000000000;
482 struct bpf_object *objs[nr_iters];
483 int prog_fds[nr_iters], map_fds[nr_iters];
484 /* +1 to test for the info_len returned by kernel */
485 struct bpf_prog_info prog_infos[nr_iters + 1];
486 struct bpf_map_info map_infos[nr_iters + 1];
487 /* Each prog only uses one map. +1 to test nr_map_ids
488 * returned by kernel.
490 __u32 map_ids[nr_iters + 1];
491 char jited_insns[128], xlated_insns[128], zeros[128];
492 __u32 i, next_id, info_len, nr_id_found, duration = 0;
493 struct timespec real_time_ts, boot_time_ts;
496 uid_t my_uid = getuid();
497 time_t now, load_time;
499 err = bpf_prog_get_fd_by_id(0);
500 CHECK(err >= 0 || errno != ENOENT,
501 "get-fd-by-notexist-prog-id", "err %d errno %d\n", err, errno);
503 err = bpf_map_get_fd_by_id(0);
504 CHECK(err >= 0 || errno != ENOENT,
505 "get-fd-by-notexist-map-id", "err %d errno %d\n", err, errno);
507 for (i = 0; i < nr_iters; i++)
510 /* Check bpf_obj_get_info_by_fd() */
511 bzero(zeros, sizeof(zeros));
512 for (i = 0; i < nr_iters; i++) {
514 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
515 &objs[i], &prog_fds[i]);
516 /* test_obj_id.o is a dumb prog. It should never fail
523 /* Insert a magic value to the map */
524 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
525 assert(map_fds[i] >= 0);
526 err = bpf_map_update_elem(map_fds[i], &array_key,
527 &array_magic_value, 0);
530 /* Check getting map info */
531 info_len = sizeof(struct bpf_map_info) * 2;
532 bzero(&map_infos[i], info_len);
533 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i],
536 map_infos[i].type != BPF_MAP_TYPE_ARRAY ||
537 map_infos[i].key_size != sizeof(__u32) ||
538 map_infos[i].value_size != sizeof(__u64) ||
539 map_infos[i].max_entries != 1 ||
540 map_infos[i].map_flags != 0 ||
541 info_len != sizeof(struct bpf_map_info) ||
542 strcmp((char *)map_infos[i].name, expected_map_name),
544 "err %d errno %d type %d(%d) info_len %u(%Zu) key_size %u value_size %u max_entries %u map_flags %X name %s(%s)\n",
546 map_infos[i].type, BPF_MAP_TYPE_ARRAY,
547 info_len, sizeof(struct bpf_map_info),
548 map_infos[i].key_size,
549 map_infos[i].value_size,
550 map_infos[i].max_entries,
551 map_infos[i].map_flags,
552 map_infos[i].name, expected_map_name))
555 /* Check getting prog info */
556 info_len = sizeof(struct bpf_prog_info) * 2;
557 bzero(&prog_infos[i], info_len);
558 bzero(jited_insns, sizeof(jited_insns));
559 bzero(xlated_insns, sizeof(xlated_insns));
560 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
561 prog_infos[i].jited_prog_len = sizeof(jited_insns);
562 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
563 prog_infos[i].xlated_prog_len = sizeof(xlated_insns);
564 prog_infos[i].map_ids = ptr_to_u64(map_ids + i);
565 prog_infos[i].nr_map_ids = 2;
566 err = clock_gettime(CLOCK_REALTIME, &real_time_ts);
568 err = clock_gettime(CLOCK_BOOTTIME, &boot_time_ts);
570 err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i],
572 load_time = (real_time_ts.tv_sec - boot_time_ts.tv_sec)
573 + (prog_infos[i].load_time / nsec_per_sec);
575 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
576 info_len != sizeof(struct bpf_prog_info) ||
577 (jit_enabled && !prog_infos[i].jited_prog_len) ||
579 !memcmp(jited_insns, zeros, sizeof(zeros))) ||
580 !prog_infos[i].xlated_prog_len ||
581 !memcmp(xlated_insns, zeros, sizeof(zeros)) ||
582 load_time < now - 60 || load_time > now + 60 ||
583 prog_infos[i].created_by_uid != my_uid ||
584 prog_infos[i].nr_map_ids != 1 ||
585 *(int *)(long)prog_infos[i].map_ids != map_infos[i].id ||
586 strcmp((char *)prog_infos[i].name, expected_prog_name),
588 "err %d errno %d i %d type %d(%d) info_len %u(%Zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n",
590 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
591 info_len, sizeof(struct bpf_prog_info),
593 prog_infos[i].jited_prog_len,
594 prog_infos[i].xlated_prog_len,
595 !!memcmp(jited_insns, zeros, sizeof(zeros)),
596 !!memcmp(xlated_insns, zeros, sizeof(zeros)),
598 prog_infos[i].created_by_uid, my_uid,
599 prog_infos[i].nr_map_ids, 1,
600 *(int *)(long)prog_infos[i].map_ids, map_infos[i].id,
601 prog_infos[i].name, expected_prog_name))
605 /* Check bpf_prog_get_next_id() */
608 while (!bpf_prog_get_next_id(next_id, &next_id)) {
609 struct bpf_prog_info prog_info = {};
613 info_len = sizeof(prog_info);
615 prog_fd = bpf_prog_get_fd_by_id(next_id);
616 if (prog_fd < 0 && errno == ENOENT)
617 /* The bpf_prog is in the dead row */
619 if (CHECK(prog_fd < 0, "get-prog-fd(next_id)",
620 "prog_fd %d next_id %d errno %d\n",
621 prog_fd, next_id, errno))
624 for (i = 0; i < nr_iters; i++)
625 if (prog_infos[i].id == next_id)
634 * prog_info.nr_map_ids = 1
635 * prog_info.map_ids = NULL
637 prog_info.nr_map_ids = 1;
638 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
639 if (CHECK(!err || errno != EFAULT,
640 "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)",
643 bzero(&prog_info, sizeof(prog_info));
644 info_len = sizeof(prog_info);
646 saved_map_id = *(int *)((long)prog_infos[i].map_ids);
647 prog_info.map_ids = prog_infos[i].map_ids;
648 prog_info.nr_map_ids = 2;
649 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
650 prog_infos[i].jited_prog_insns = 0;
651 prog_infos[i].xlated_prog_insns = 0;
652 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
653 memcmp(&prog_info, &prog_infos[i], info_len) ||
654 *(int *)(long)prog_info.map_ids != saved_map_id,
655 "get-prog-info(next_id->fd)",
656 "err %d errno %d info_len %u(%Zu) memcmp %d map_id %u(%u)\n",
657 err, errno, info_len, sizeof(struct bpf_prog_info),
658 memcmp(&prog_info, &prog_infos[i], info_len),
659 *(int *)(long)prog_info.map_ids, saved_map_id);
662 CHECK(nr_id_found != nr_iters,
663 "check total prog id found by get_next_id",
664 "nr_id_found %u(%u)\n",
665 nr_id_found, nr_iters);
667 /* Check bpf_map_get_next_id() */
670 while (!bpf_map_get_next_id(next_id, &next_id)) {
671 struct bpf_map_info map_info = {};
674 info_len = sizeof(map_info);
676 map_fd = bpf_map_get_fd_by_id(next_id);
677 if (map_fd < 0 && errno == ENOENT)
678 /* The bpf_map is in the dead row */
680 if (CHECK(map_fd < 0, "get-map-fd(next_id)",
681 "map_fd %d next_id %u errno %d\n",
682 map_fd, next_id, errno))
685 for (i = 0; i < nr_iters; i++)
686 if (map_infos[i].id == next_id)
694 err = bpf_map_lookup_elem(map_fd, &array_key, &array_value);
697 err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
698 CHECK(err || info_len != sizeof(struct bpf_map_info) ||
699 memcmp(&map_info, &map_infos[i], info_len) ||
700 array_value != array_magic_value,
701 "check get-map-info(next_id->fd)",
702 "err %d errno %d info_len %u(%Zu) memcmp %d array_value %llu(%llu)\n",
703 err, errno, info_len, sizeof(struct bpf_map_info),
704 memcmp(&map_info, &map_infos[i], info_len),
705 array_value, array_magic_value);
709 CHECK(nr_id_found != nr_iters,
710 "check total map id found by get_next_id",
711 "nr_id_found %u(%u)\n",
712 nr_id_found, nr_iters);
715 for (i = 0; i < nr_iters; i++)
716 bpf_object__close(objs[i]);
719 static void test_pkt_md_access(void)
721 const char *file = "./test_pkt_md_access.o";
722 struct bpf_object *obj;
723 __u32 duration, retval;
726 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
732 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
733 NULL, NULL, &retval, &duration);
734 CHECK(err || retval, "",
735 "err %d errno %d retval %d duration %d\n",
736 err, errno, retval, duration);
738 bpf_object__close(obj);
741 static void test_obj_name(void)
749 { "_123456789ABCDE", 1, 0 },
750 { "_123456789ABCDEF", 0, EINVAL },
751 { "_123456789ABCD\n", 0, EINVAL },
753 struct bpf_insn prog[] = {
754 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
760 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
761 size_t name_len = strlen(tests[i].name) + 1;
766 /* test different attr.prog_name during BPF_PROG_LOAD */
767 ncopy = name_len < sizeof(attr.prog_name) ?
768 name_len : sizeof(attr.prog_name);
769 bzero(&attr, sizeof(attr));
770 attr.prog_type = BPF_PROG_TYPE_SCHED_CLS;
772 attr.insns = ptr_to_u64(prog);
773 attr.license = ptr_to_u64("");
774 memcpy(attr.prog_name, tests[i].name, ncopy);
776 fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
777 CHECK((tests[i].success && fd < 0) ||
778 (!tests[i].success && fd != -1) ||
779 (!tests[i].success && errno != tests[i].expected_errno),
780 "check-bpf-prog-name",
781 "fd %d(%d) errno %d(%d)\n",
782 fd, tests[i].success, errno, tests[i].expected_errno);
787 /* test different attr.map_name during BPF_MAP_CREATE */
788 ncopy = name_len < sizeof(attr.map_name) ?
789 name_len : sizeof(attr.map_name);
790 bzero(&attr, sizeof(attr));
791 attr.map_type = BPF_MAP_TYPE_ARRAY;
794 attr.max_entries = 1;
796 memcpy(attr.map_name, tests[i].name, ncopy);
797 fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
798 CHECK((tests[i].success && fd < 0) ||
799 (!tests[i].success && fd != -1) ||
800 (!tests[i].success && errno != tests[i].expected_errno),
801 "check-bpf-map-name",
802 "fd %d(%d) errno %d(%d)\n",
803 fd, tests[i].success, errno, tests[i].expected_errno);
810 static void test_tp_attach_query(void)
812 const int num_progs = 3;
813 int i, j, bytes, efd, err, prog_fd[num_progs], pmu_fd[num_progs];
814 __u32 duration = 0, info_len, saved_prog_ids[num_progs];
815 const char *file = "./test_tracepoint.o";
816 struct perf_event_query_bpf *query;
817 struct perf_event_attr attr = {};
818 struct bpf_object *obj[num_progs];
819 struct bpf_prog_info prog_info;
822 snprintf(buf, sizeof(buf),
823 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
824 efd = open(buf, O_RDONLY, 0);
825 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
827 bytes = read(efd, buf, sizeof(buf));
829 if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
830 "read", "bytes %d errno %d\n", bytes, errno))
833 attr.config = strtol(buf, NULL, 0);
834 attr.type = PERF_TYPE_TRACEPOINT;
835 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
836 attr.sample_period = 1;
837 attr.wakeup_events = 1;
839 query = malloc(sizeof(*query) + sizeof(__u32) * num_progs);
840 for (i = 0; i < num_progs; i++) {
841 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj[i],
843 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
846 bzero(&prog_info, sizeof(prog_info));
847 prog_info.jited_prog_len = 0;
848 prog_info.xlated_prog_len = 0;
849 prog_info.nr_map_ids = 0;
850 info_len = sizeof(prog_info);
851 err = bpf_obj_get_info_by_fd(prog_fd[i], &prog_info, &info_len);
852 if (CHECK(err, "bpf_obj_get_info_by_fd", "err %d errno %d\n",
855 saved_prog_ids[i] = prog_info.id;
857 pmu_fd[i] = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
858 0 /* cpu 0 */, -1 /* group id */,
860 if (CHECK(pmu_fd[i] < 0, "perf_event_open", "err %d errno %d\n",
863 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
864 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
869 /* check NULL prog array query */
870 query->ids_len = num_progs;
871 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
872 if (CHECK(err || query->prog_cnt != 0,
873 "perf_event_ioc_query_bpf",
874 "err %d errno %d query->prog_cnt %u\n",
875 err, errno, query->prog_cnt))
879 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[i]);
880 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
885 /* try to get # of programs only */
887 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
888 if (CHECK(err || query->prog_cnt != 2,
889 "perf_event_ioc_query_bpf",
890 "err %d errno %d query->prog_cnt %u\n",
891 err, errno, query->prog_cnt))
894 /* try a few negative tests */
895 /* invalid query pointer */
896 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF,
897 (struct perf_event_query_bpf *)0x1);
898 if (CHECK(!err || errno != EFAULT,
899 "perf_event_ioc_query_bpf",
900 "err %d errno %d\n", err, errno))
903 /* no enough space */
905 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
906 if (CHECK(!err || errno != ENOSPC || query->prog_cnt != 2,
907 "perf_event_ioc_query_bpf",
908 "err %d errno %d query->prog_cnt %u\n",
909 err, errno, query->prog_cnt))
913 query->ids_len = num_progs;
914 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
915 if (CHECK(err || query->prog_cnt != (i + 1),
916 "perf_event_ioc_query_bpf",
917 "err %d errno %d query->prog_cnt %u\n",
918 err, errno, query->prog_cnt))
920 for (j = 0; j < i + 1; j++)
921 if (CHECK(saved_prog_ids[j] != query->ids[j],
922 "perf_event_ioc_query_bpf",
923 "#%d saved_prog_id %x query prog_id %x\n",
924 j, saved_prog_ids[j], query->ids[j]))
929 for (; i >= 0; i--) {
931 ioctl(pmu_fd[i], PERF_EVENT_IOC_DISABLE);
935 bpf_object__close(obj[i]);
940 static int compare_map_keys(int map1_fd, int map2_fd)
943 char val_buf[PERF_MAX_STACK_DEPTH *
944 sizeof(struct bpf_stack_build_id)];
947 err = bpf_map_get_next_key(map1_fd, NULL, &key);
950 err = bpf_map_lookup_elem(map2_fd, &key, val_buf);
954 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) {
955 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf);
967 static int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len)
969 __u32 key, next_key, *cur_key_p, *next_key_p;
970 char *val_buf1, *val_buf2;
973 val_buf1 = malloc(stack_trace_len);
974 val_buf2 = malloc(stack_trace_len);
977 while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) {
978 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1);
981 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2);
984 for (i = 0; i < stack_trace_len; i++) {
985 if (val_buf1[i] != val_buf2[i]) {
992 next_key_p = &next_key;
1003 static void test_stacktrace_map()
1005 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
1006 const char *file = "./test_stacktrace_map.o";
1007 int bytes, efd, err, pmu_fd, prog_fd, stack_trace_len;
1008 struct perf_event_attr attr = {};
1009 __u32 key, val, duration = 0;
1010 struct bpf_object *obj;
1013 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1014 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1017 /* Get the ID for the sched/sched_switch tracepoint */
1018 snprintf(buf, sizeof(buf),
1019 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
1020 efd = open(buf, O_RDONLY, 0);
1021 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1024 bytes = read(efd, buf, sizeof(buf));
1026 if (bytes <= 0 || bytes >= sizeof(buf))
1029 /* Open the perf event and attach bpf progrram */
1030 attr.config = strtol(buf, NULL, 0);
1031 attr.type = PERF_TYPE_TRACEPOINT;
1032 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
1033 attr.sample_period = 1;
1034 attr.wakeup_events = 1;
1035 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1036 0 /* cpu 0 */, -1 /* group id */,
1038 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n",
1042 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1046 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1051 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1052 if (control_map_fd < 0)
1055 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1056 if (stackid_hmap_fd < 0)
1059 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1060 if (stackmap_fd < 0)
1063 stack_amap_fd = bpf_find_map(__func__, obj, "stack_amap");
1064 if (stack_amap_fd < 0)
1067 /* give some time for bpf program run */
1070 /* disable stack trace collection */
1073 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1075 /* for every element in stackid_hmap, we can find a corresponding one
1076 * in stackmap, and vise versa.
1078 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1079 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1080 "err %d errno %d\n", err, errno))
1081 goto disable_pmu_noerr;
1083 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1084 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1085 "err %d errno %d\n", err, errno))
1086 goto disable_pmu_noerr;
1088 stack_trace_len = PERF_MAX_STACK_DEPTH * sizeof(__u64);
1089 err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len);
1090 if (CHECK(err, "compare_stack_ips stackmap vs. stack_amap",
1091 "err %d errno %d\n", err, errno))
1092 goto disable_pmu_noerr;
1094 goto disable_pmu_noerr;
1098 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1101 bpf_object__close(obj);
1104 static void test_stacktrace_map_raw_tp()
1106 int control_map_fd, stackid_hmap_fd, stackmap_fd;
1107 const char *file = "./test_stacktrace_map.o";
1108 int efd, err, prog_fd;
1109 __u32 key, val, duration = 0;
1110 struct bpf_object *obj;
1112 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
1113 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1116 efd = bpf_raw_tracepoint_open("sched_switch", prog_fd);
1117 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
1121 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1122 if (control_map_fd < 0)
1125 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1126 if (stackid_hmap_fd < 0)
1129 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1130 if (stackmap_fd < 0)
1133 /* give some time for bpf program run */
1136 /* disable stack trace collection */
1139 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1141 /* for every element in stackid_hmap, we can find a corresponding one
1142 * in stackmap, and vise versa.
1144 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1145 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1146 "err %d errno %d\n", err, errno))
1149 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1150 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1151 "err %d errno %d\n", err, errno))
1154 goto close_prog_noerr;
1158 bpf_object__close(obj);
1161 static int extract_build_id(char *build_id, size_t size)
1167 fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r");
1171 if (getline(&line, &len, fp) == -1)
1177 memcpy(build_id, line, len);
1178 build_id[len] = '\0';
1185 static void test_stacktrace_build_id(void)
1187 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
1188 const char *file = "./test_stacktrace_build_id.o";
1189 int bytes, efd, err, pmu_fd, prog_fd, stack_trace_len;
1190 struct perf_event_attr attr = {};
1191 __u32 key, previous_key, val, duration = 0;
1192 struct bpf_object *obj;
1195 struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
1196 int build_id_matches = 0;
1200 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1201 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1204 /* Get the ID for the sched/sched_switch tracepoint */
1205 snprintf(buf, sizeof(buf),
1206 "/sys/kernel/debug/tracing/events/random/urandom_read/id");
1207 efd = open(buf, O_RDONLY, 0);
1208 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1211 bytes = read(efd, buf, sizeof(buf));
1213 if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
1214 "read", "bytes %d errno %d\n", bytes, errno))
1217 /* Open the perf event and attach bpf progrram */
1218 attr.config = strtol(buf, NULL, 0);
1219 attr.type = PERF_TYPE_TRACEPOINT;
1220 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
1221 attr.sample_period = 1;
1222 attr.wakeup_events = 1;
1223 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1224 0 /* cpu 0 */, -1 /* group id */,
1226 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n",
1230 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1231 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
1235 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1236 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
1241 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1242 if (CHECK(control_map_fd < 0, "bpf_find_map control_map",
1243 "err %d errno %d\n", err, errno))
1246 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1247 if (CHECK(stackid_hmap_fd < 0, "bpf_find_map stackid_hmap",
1248 "err %d errno %d\n", err, errno))
1251 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1252 if (CHECK(stackmap_fd < 0, "bpf_find_map stackmap", "err %d errno %d\n",
1256 stack_amap_fd = bpf_find_map(__func__, obj, "stack_amap");
1257 if (CHECK(stack_amap_fd < 0, "bpf_find_map stack_amap",
1258 "err %d errno %d\n", err, errno))
1261 assert(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null")
1263 assert(system("./urandom_read") == 0);
1264 /* disable stack trace collection */
1267 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1269 /* for every element in stackid_hmap, we can find a corresponding one
1270 * in stackmap, and vise versa.
1272 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1273 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1274 "err %d errno %d\n", err, errno))
1277 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1278 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1279 "err %d errno %d\n", err, errno))
1282 err = extract_build_id(buf, 256);
1284 if (CHECK(err, "get build_id with readelf",
1285 "err %d errno %d\n", err, errno))
1288 err = bpf_map_get_next_key(stackmap_fd, NULL, &key);
1289 if (CHECK(err, "get_next_key from stackmap",
1290 "err %d, errno %d\n", err, errno))
1296 err = bpf_map_lookup_elem(stackmap_fd, &key, id_offs);
1297 if (CHECK(err, "lookup_elem from stackmap",
1298 "err %d, errno %d\n", err, errno))
1300 for (i = 0; i < PERF_MAX_STACK_DEPTH; ++i)
1301 if (id_offs[i].status == BPF_STACK_BUILD_ID_VALID &&
1302 id_offs[i].offset != 0) {
1303 for (j = 0; j < 20; ++j)
1304 sprintf(build_id + 2 * j, "%02x",
1305 id_offs[i].build_id[j] & 0xff);
1306 if (strstr(buf, build_id) != NULL)
1307 build_id_matches = 1;
1310 } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
1312 /* stack_map_get_build_id_offset() is racy and sometimes can return
1313 * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
1314 * try it one more time.
1316 if (build_id_matches < 1 && retry--) {
1317 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1319 bpf_object__close(obj);
1320 printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
1325 if (CHECK(build_id_matches < 1, "build id match",
1326 "Didn't find expected build ID from the map\n"))
1329 stack_trace_len = PERF_MAX_STACK_DEPTH
1330 * sizeof(struct bpf_stack_build_id);
1331 err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len);
1332 CHECK(err, "compare_stack_ips stackmap vs. stack_amap",
1333 "err %d errno %d\n", err, errno);
1336 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1342 bpf_object__close(obj);
1348 static void test_stacktrace_build_id_nmi(void)
1350 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
1351 const char *file = "./test_stacktrace_build_id.o";
1352 int err, pmu_fd, prog_fd;
1353 struct perf_event_attr attr = {
1354 .sample_freq = 5000,
1356 .type = PERF_TYPE_HARDWARE,
1357 .config = PERF_COUNT_HW_CPU_CYCLES,
1359 __u32 key, previous_key, val, duration = 0;
1360 struct bpf_object *obj;
1363 struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
1364 int build_id_matches = 0;
1368 err = bpf_prog_load(file, BPF_PROG_TYPE_PERF_EVENT, &obj, &prog_fd);
1369 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1372 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1373 0 /* cpu 0 */, -1 /* group id */,
1375 if (CHECK(pmu_fd < 0, "perf_event_open",
1376 "err %d errno %d. Does the test host support PERF_COUNT_HW_CPU_CYCLES?\n",
1380 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1381 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
1385 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1386 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
1391 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1392 if (CHECK(control_map_fd < 0, "bpf_find_map control_map",
1393 "err %d errno %d\n", err, errno))
1396 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1397 if (CHECK(stackid_hmap_fd < 0, "bpf_find_map stackid_hmap",
1398 "err %d errno %d\n", err, errno))
1401 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1402 if (CHECK(stackmap_fd < 0, "bpf_find_map stackmap", "err %d errno %d\n",
1406 stack_amap_fd = bpf_find_map(__func__, obj, "stack_amap");
1407 if (CHECK(stack_amap_fd < 0, "bpf_find_map stack_amap",
1408 "err %d errno %d\n", err, errno))
1411 assert(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null")
1413 assert(system("taskset 0x1 ./urandom_read 100000") == 0);
1414 /* disable stack trace collection */
1417 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1419 /* for every element in stackid_hmap, we can find a corresponding one
1420 * in stackmap, and vise versa.
1422 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1423 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1424 "err %d errno %d\n", err, errno))
1427 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1428 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1429 "err %d errno %d\n", err, errno))
1432 err = extract_build_id(buf, 256);
1434 if (CHECK(err, "get build_id with readelf",
1435 "err %d errno %d\n", err, errno))
1438 err = bpf_map_get_next_key(stackmap_fd, NULL, &key);
1439 if (CHECK(err, "get_next_key from stackmap",
1440 "err %d, errno %d\n", err, errno))
1446 err = bpf_map_lookup_elem(stackmap_fd, &key, id_offs);
1447 if (CHECK(err, "lookup_elem from stackmap",
1448 "err %d, errno %d\n", err, errno))
1450 for (i = 0; i < PERF_MAX_STACK_DEPTH; ++i)
1451 if (id_offs[i].status == BPF_STACK_BUILD_ID_VALID &&
1452 id_offs[i].offset != 0) {
1453 for (j = 0; j < 20; ++j)
1454 sprintf(build_id + 2 * j, "%02x",
1455 id_offs[i].build_id[j] & 0xff);
1456 if (strstr(buf, build_id) != NULL)
1457 build_id_matches = 1;
1460 } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
1462 /* stack_map_get_build_id_offset() is racy and sometimes can return
1463 * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
1464 * try it one more time.
1466 if (build_id_matches < 1 && retry--) {
1467 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1469 bpf_object__close(obj);
1470 printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
1475 if (CHECK(build_id_matches < 1, "build id match",
1476 "Didn't find expected build ID from the map\n"))
1480 * We intentionally skip compare_stack_ips(). This is because we
1481 * only support one in_nmi() ips-to-build_id translation per cpu
1482 * at any time, thus stack_amap here will always fallback to
1483 * BPF_STACK_BUILD_ID_IP;
1487 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1493 bpf_object__close(obj);
1496 #define MAX_CNT_RAWTP 10ull
1497 #define MAX_STACK_RAWTP 100
1498 struct get_stack_trace_t {
1500 int kern_stack_size;
1501 int user_stack_size;
1502 int user_stack_buildid_size;
1503 __u64 kern_stack[MAX_STACK_RAWTP];
1504 __u64 user_stack[MAX_STACK_RAWTP];
1505 struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP];
1508 static int get_stack_print_output(void *data, int size)
1510 bool good_kern_stack = false, good_user_stack = false;
1511 const char *nonjit_func = "___bpf_prog_run";
1512 struct get_stack_trace_t *e = data;
1519 if (size < sizeof(struct get_stack_trace_t)) {
1520 __u64 *raw_data = data;
1523 num_stack = size / sizeof(__u64);
1524 /* If jit is enabled, we do not have a good way to
1525 * verify the sanity of the kernel stack. So we
1526 * just assume it is good if the stack is not empty.
1527 * This could be improved in the future.
1530 found = num_stack > 0;
1532 for (i = 0; i < num_stack; i++) {
1533 ks = ksym_search(raw_data[i]);
1534 if (strcmp(ks->name, nonjit_func) == 0) {
1541 good_kern_stack = true;
1542 good_user_stack = true;
1545 num_stack = e->kern_stack_size / sizeof(__u64);
1547 good_kern_stack = num_stack > 0;
1549 for (i = 0; i < num_stack; i++) {
1550 ks = ksym_search(e->kern_stack[i]);
1551 if (strcmp(ks->name, nonjit_func) == 0) {
1552 good_kern_stack = true;
1557 if (e->user_stack_size > 0 && e->user_stack_buildid_size > 0)
1558 good_user_stack = true;
1560 if (!good_kern_stack || !good_user_stack)
1561 return LIBBPF_PERF_EVENT_ERROR;
1563 if (cnt == MAX_CNT_RAWTP)
1564 return LIBBPF_PERF_EVENT_DONE;
1566 return LIBBPF_PERF_EVENT_CONT;
1569 static void test_get_stack_raw_tp(void)
1571 const char *file = "./test_get_stack_rawtp.o";
1572 int i, efd, err, prog_fd, pmu_fd, perfmap_fd;
1573 struct perf_event_attr attr = {};
1574 struct timespec tv = {0, 10};
1575 __u32 key = 0, duration = 0;
1576 struct bpf_object *obj;
1578 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
1579 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1582 efd = bpf_raw_tracepoint_open("sys_enter", prog_fd);
1583 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
1586 perfmap_fd = bpf_find_map(__func__, obj, "perfmap");
1587 if (CHECK(perfmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
1591 err = load_kallsyms();
1592 if (CHECK(err < 0, "load_kallsyms", "err %d errno %d\n", err, errno))
1595 attr.sample_type = PERF_SAMPLE_RAW;
1596 attr.type = PERF_TYPE_SOFTWARE;
1597 attr.config = PERF_COUNT_SW_BPF_OUTPUT;
1598 pmu_fd = syscall(__NR_perf_event_open, &attr, getpid()/*pid*/, -1/*cpu*/,
1600 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd,
1604 err = bpf_map_update_elem(perfmap_fd, &key, &pmu_fd, BPF_ANY);
1605 if (CHECK(err < 0, "bpf_map_update_elem", "err %d errno %d\n", err,
1609 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1610 if (CHECK(err < 0, "ioctl PERF_EVENT_IOC_ENABLE", "err %d errno %d\n",
1614 err = perf_event_mmap(pmu_fd);
1615 if (CHECK(err < 0, "perf_event_mmap", "err %d errno %d\n", err, errno))
1618 /* trigger some syscall action */
1619 for (i = 0; i < MAX_CNT_RAWTP; i++)
1620 nanosleep(&tv, NULL);
1622 err = perf_event_poller(pmu_fd, get_stack_print_output);
1623 if (CHECK(err < 0, "perf_event_poller", "err %d errno %d\n", err, errno))
1626 goto close_prog_noerr;
1630 bpf_object__close(obj);
1633 static void test_task_fd_query_rawtp(void)
1635 const char *file = "./test_get_stack_rawtp.o";
1636 __u64 probe_offset, probe_addr;
1637 __u32 len, prog_id, fd_type;
1638 struct bpf_object *obj;
1639 int efd, err, prog_fd;
1643 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
1644 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1647 efd = bpf_raw_tracepoint_open("sys_enter", prog_fd);
1648 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
1651 /* query (getpid(), efd) */
1653 err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id,
1654 &fd_type, &probe_offset, &probe_addr);
1655 if (CHECK(err < 0, "bpf_task_fd_query", "err %d errno %d\n", err,
1659 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1660 strcmp(buf, "sys_enter") == 0;
1661 if (CHECK(!err, "check_results", "fd_type %d tp_name %s\n",
1667 err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id,
1668 &fd_type, &probe_offset, &probe_addr);
1669 if (CHECK(err < 0, "bpf_task_fd_query (len = 0)", "err %d errno %d\n",
1672 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1673 len == strlen("sys_enter");
1674 if (CHECK(!err, "check_results", "fd_type %d len %u\n", fd_type, len))
1677 /* test empty buffer */
1679 err = bpf_task_fd_query(getpid(), efd, 0, 0, &len, &prog_id,
1680 &fd_type, &probe_offset, &probe_addr);
1681 if (CHECK(err < 0, "bpf_task_fd_query (buf = 0)", "err %d errno %d\n",
1684 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1685 len == strlen("sys_enter");
1686 if (CHECK(!err, "check_results", "fd_type %d len %u\n", fd_type, len))
1689 /* test smaller buffer */
1691 err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id,
1692 &fd_type, &probe_offset, &probe_addr);
1693 if (CHECK(err >= 0 || errno != ENOSPC, "bpf_task_fd_query (len = 3)",
1694 "err %d errno %d\n", err, errno))
1696 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1697 len == strlen("sys_enter") &&
1698 strcmp(buf, "sy") == 0;
1699 if (CHECK(!err, "check_results", "fd_type %d len %u\n", fd_type, len))
1702 goto close_prog_noerr;
1706 bpf_object__close(obj);
1709 static void test_task_fd_query_tp_core(const char *probe_name,
1710 const char *tp_name)
1712 const char *file = "./test_tracepoint.o";
1713 int err, bytes, efd, prog_fd, pmu_fd;
1714 struct perf_event_attr attr = {};
1715 __u64 probe_offset, probe_addr;
1716 __u32 len, prog_id, fd_type;
1717 struct bpf_object *obj;
1721 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1722 if (CHECK(err, "bpf_prog_load", "err %d errno %d\n", err, errno))
1725 snprintf(buf, sizeof(buf),
1726 "/sys/kernel/debug/tracing/events/%s/id", probe_name);
1727 efd = open(buf, O_RDONLY, 0);
1728 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1730 bytes = read(efd, buf, sizeof(buf));
1732 if (CHECK(bytes <= 0 || bytes >= sizeof(buf), "read",
1733 "bytes %d errno %d\n", bytes, errno))
1736 attr.config = strtol(buf, NULL, 0);
1737 attr.type = PERF_TYPE_TRACEPOINT;
1738 attr.sample_type = PERF_SAMPLE_RAW;
1739 attr.sample_period = 1;
1740 attr.wakeup_events = 1;
1741 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1742 0 /* cpu 0 */, -1 /* group id */,
1744 if (CHECK(err, "perf_event_open", "err %d errno %d\n", err, errno))
1747 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1748 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", err,
1752 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1753 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", err,
1757 /* query (getpid(), pmu_fd) */
1759 err = bpf_task_fd_query(getpid(), pmu_fd, 0, buf, &len, &prog_id,
1760 &fd_type, &probe_offset, &probe_addr);
1761 if (CHECK(err < 0, "bpf_task_fd_query", "err %d errno %d\n", err,
1765 err = (fd_type == BPF_FD_TYPE_TRACEPOINT) && !strcmp(buf, tp_name);
1766 if (CHECK(!err, "check_results", "fd_type %d tp_name %s\n",
1771 goto close_prog_noerr;
1778 bpf_object__close(obj);
1781 static void test_task_fd_query_tp(void)
1783 test_task_fd_query_tp_core("sched/sched_switch",
1785 test_task_fd_query_tp_core("syscalls/sys_enter_read",
1789 static int libbpf_debug_print(enum libbpf_print_level level,
1790 const char *format, va_list args)
1792 if (level == LIBBPF_DEBUG)
1795 return vfprintf(stderr, format, args);
1798 static void test_reference_tracking()
1800 const char *file = "./test_sk_lookup_kern.o";
1801 struct bpf_object *obj;
1802 struct bpf_program *prog;
1806 obj = bpf_object__open(file);
1812 bpf_object__for_each_program(prog, obj) {
1815 /* Ignore .text sections */
1816 title = bpf_program__title(prog, false);
1817 if (strstr(title, ".text") != NULL)
1820 bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
1822 /* Expect verifier failure if test name has 'fail' */
1823 if (strstr(title, "fail") != NULL) {
1824 libbpf_set_print(NULL);
1825 err = !bpf_program__load(prog, "GPL", 0);
1826 libbpf_set_print(libbpf_debug_print);
1828 err = bpf_program__load(prog, "GPL", 0);
1830 CHECK(err, title, "\n");
1832 bpf_object__close(obj);
1840 static void test_queue_stack_map(int type)
1842 const int MAP_SIZE = 32;
1843 __u32 vals[MAP_SIZE], duration, retval, size, val;
1844 int i, err, prog_fd, map_in_fd, map_out_fd;
1845 char file[32], buf[128];
1846 struct bpf_object *obj;
1847 struct iphdr *iph = (void *)buf + sizeof(struct ethhdr);
1849 /* Fill test values to be used */
1850 for (i = 0; i < MAP_SIZE; i++)
1854 strncpy(file, "./test_queue_map.o", sizeof(file));
1855 else if (type == STACK)
1856 strncpy(file, "./test_stack_map.o", sizeof(file));
1860 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
1866 map_in_fd = bpf_find_map(__func__, obj, "map_in");
1870 map_out_fd = bpf_find_map(__func__, obj, "map_out");
1874 /* Push 32 elements to the input map */
1875 for (i = 0; i < MAP_SIZE; i++) {
1876 err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0);
1883 /* The eBPF program pushes iph.saddr in the output map,
1884 * pops the input map and saves this value in iph.daddr
1886 for (i = 0; i < MAP_SIZE; i++) {
1887 if (type == QUEUE) {
1889 pkt_v4.iph.saddr = vals[i] * 5;
1890 } else if (type == STACK) {
1891 val = vals[MAP_SIZE - 1 - i];
1892 pkt_v4.iph.saddr = vals[MAP_SIZE - 1 - i] * 5;
1895 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
1896 buf, &size, &retval, &duration);
1897 if (err || retval || size != sizeof(pkt_v4) ||
1902 CHECK(err || retval || size != sizeof(pkt_v4) || iph->daddr != val,
1904 "err %d errno %d retval %d size %d iph->daddr %u\n",
1905 err, errno, retval, size, iph->daddr);
1907 /* Queue is empty, program should return TC_ACT_SHOT */
1908 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
1909 buf, &size, &retval, &duration);
1910 CHECK(err || retval != 2 /* TC_ACT_SHOT */|| size != sizeof(pkt_v4),
1911 "check-queue-stack-map-empty",
1912 "err %d errno %d retval %d size %d\n",
1913 err, errno, retval, size);
1915 /* Check that the program pushed elements correctly */
1916 for (i = 0; i < MAP_SIZE; i++) {
1917 err = bpf_map_lookup_and_delete_elem(map_out_fd, NULL, &val);
1918 if (err || val != vals[i] * 5)
1922 CHECK(i != MAP_SIZE && (err || val != vals[i] * 5),
1923 "bpf_map_push_elem", "err %d value %u\n", err, val);
1926 pkt_v4.iph.saddr = 0;
1927 bpf_object__close(obj);
1930 #define CHECK_FLOW_KEYS(desc, got, expected) \
1931 CHECK(memcmp(&got, &expected, sizeof(got)) != 0, \
1935 "addr_proto=0x%x/0x%x " \
1937 "is_first_frag=%u/%u " \
1939 "n_proto=0x%x/0x%x " \
1942 got.nhoff, expected.nhoff, \
1943 got.thoff, expected.thoff, \
1944 got.addr_proto, expected.addr_proto, \
1945 got.is_frag, expected.is_frag, \
1946 got.is_first_frag, expected.is_first_frag, \
1947 got.is_encap, expected.is_encap, \
1948 got.n_proto, expected.n_proto, \
1949 got.sport, expected.sport, \
1950 got.dport, expected.dport)
1952 static struct bpf_flow_keys pkt_v4_flow_keys = {
1954 .thoff = sizeof(struct iphdr),
1955 .addr_proto = ETH_P_IP,
1956 .ip_proto = IPPROTO_TCP,
1957 .n_proto = __bpf_constant_htons(ETH_P_IP),
1960 static struct bpf_flow_keys pkt_v6_flow_keys = {
1962 .thoff = sizeof(struct ipv6hdr),
1963 .addr_proto = ETH_P_IPV6,
1964 .ip_proto = IPPROTO_TCP,
1965 .n_proto = __bpf_constant_htons(ETH_P_IPV6),
1968 static void test_flow_dissector(void)
1970 struct bpf_flow_keys flow_keys;
1971 struct bpf_object *obj;
1972 __u32 duration, retval;
1976 err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
1977 "jmp_table", &prog_fd);
1983 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
1984 &flow_keys, &size, &retval, &duration);
1985 CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv4",
1986 "err %d errno %d retval %d duration %d size %u/%lu\n",
1987 err, errno, retval, duration, size, sizeof(flow_keys));
1988 CHECK_FLOW_KEYS("ipv4_flow_keys", flow_keys, pkt_v4_flow_keys);
1990 err = bpf_prog_test_run(prog_fd, 10, &pkt_v6, sizeof(pkt_v6),
1991 &flow_keys, &size, &retval, &duration);
1992 CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv6",
1993 "err %d errno %d retval %d duration %d size %u/%lu\n",
1994 err, errno, retval, duration, size, sizeof(flow_keys));
1995 CHECK_FLOW_KEYS("ipv6_flow_keys", flow_keys, pkt_v6_flow_keys);
1997 bpf_object__close(obj);
2000 static void *test_spin_lock(void *arg)
2002 __u32 duration, retval;
2003 int err, prog_fd = *(u32 *) arg;
2005 err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4),
2006 NULL, NULL, &retval, &duration);
2007 CHECK(err || retval, "",
2008 "err %d errno %d retval %d duration %d\n",
2009 err, errno, retval, duration);
2013 static void test_spinlock(void)
2015 const char *file = "./test_spin_lock.o";
2016 pthread_t thread_id[4];
2017 struct bpf_object *obj;
2022 err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
2024 printf("test_spin_lock:bpf_prog_load errno %d\n", errno);
2027 for (i = 0; i < 4; i++)
2028 assert(pthread_create(&thread_id[i], NULL,
2029 &test_spin_lock, &prog_fd) == 0);
2030 for (i = 0; i < 4; i++)
2031 assert(pthread_join(thread_id[i], &ret) == 0 &&
2032 ret == (void *)&prog_fd);
2033 goto close_prog_noerr;
2037 bpf_object__close(obj);
2040 static void *parallel_map_access(void *arg)
2042 int err, map_fd = *(u32 *) arg;
2043 int vars[17], i, j, rnd, key = 0;
2045 for (i = 0; i < 10000; i++) {
2046 err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK);
2048 printf("lookup failed\n");
2053 printf("lookup #%d var[0]=%d\n", i, vars[0]);
2058 for (j = 2; j < 17; j++) {
2061 printf("lookup #%d var[1]=%d var[%d]=%d\n",
2062 i, rnd, j, vars[j]);
2071 static void test_map_lock(void)
2073 const char *file = "./test_map_lock.o";
2074 int prog_fd, map_fd[2], vars[17] = {};
2075 pthread_t thread_id[6];
2076 struct bpf_object *obj;
2077 int err = 0, key = 0, i;
2080 err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
2082 printf("test_map_lock:bpf_prog_load errno %d\n", errno);
2085 map_fd[0] = bpf_find_map(__func__, obj, "hash_map");
2088 map_fd[1] = bpf_find_map(__func__, obj, "array_map");
2092 bpf_map_update_elem(map_fd[0], &key, vars, BPF_F_LOCK);
2094 for (i = 0; i < 4; i++)
2095 assert(pthread_create(&thread_id[i], NULL,
2096 &test_spin_lock, &prog_fd) == 0);
2097 for (i = 4; i < 6; i++)
2098 assert(pthread_create(&thread_id[i], NULL,
2099 ¶llel_map_access, &map_fd[i - 4]) == 0);
2100 for (i = 0; i < 4; i++)
2101 assert(pthread_join(thread_id[i], &ret) == 0 &&
2102 ret == (void *)&prog_fd);
2103 for (i = 4; i < 6; i++)
2104 assert(pthread_join(thread_id[i], &ret) == 0 &&
2105 ret == (void *)&map_fd[i - 4]);
2106 goto close_prog_noerr;
2110 bpf_object__close(obj);
2113 static void sigalrm_handler(int s) {}
2114 static struct sigaction sigalrm_action = {
2115 .sa_handler = sigalrm_handler,
2118 static void test_signal_pending(enum bpf_prog_type prog_type)
2120 struct bpf_insn prog[4096];
2121 struct itimerval timeo = {
2122 .it_value.tv_usec = 100000, /* 100ms */
2124 __u32 duration, retval;
2129 for (i = 0; i < ARRAY_SIZE(prog); i++)
2130 prog[i] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0);
2131 prog[ARRAY_SIZE(prog) - 1] = BPF_EXIT_INSN();
2133 prog_fd = bpf_load_program(prog_type, prog, ARRAY_SIZE(prog),
2135 CHECK(prog_fd < 0, "test-run", "errno %d\n", errno);
2137 err = sigaction(SIGALRM, &sigalrm_action, NULL);
2138 CHECK(err, "test-run-signal-sigaction", "errno %d\n", errno);
2140 err = setitimer(ITIMER_REAL, &timeo, NULL);
2141 CHECK(err, "test-run-signal-timer", "errno %d\n", errno);
2143 err = bpf_prog_test_run(prog_fd, 0xffffffff, &pkt_v4, sizeof(pkt_v4),
2144 NULL, NULL, &retval, &duration);
2145 CHECK(duration > 500000000, /* 500ms */
2146 "test-run-signal-duration",
2147 "duration %dns > 500ms\n",
2150 signal(SIGALRM, SIG_DFL);
2157 jit_enabled = is_jit_enabled();
2160 test_prog_run_xattr();
2162 test_xdp_adjust_tail();
2164 test_xdp_noinline();
2167 test_pkt_md_access();
2169 test_tp_attach_query();
2170 test_stacktrace_map();
2171 test_stacktrace_build_id();
2172 test_stacktrace_build_id_nmi();
2173 test_stacktrace_map_raw_tp();
2174 test_get_stack_raw_tp();
2175 test_task_fd_query_rawtp();
2176 test_task_fd_query_tp();
2177 test_reference_tracking();
2178 test_queue_stack_map(QUEUE);
2179 test_queue_stack_map(STACK);
2180 test_flow_dissector();
2183 test_signal_pending(BPF_PROG_TYPE_SOCKET_FILTER);
2184 test_signal_pending(BPF_PROG_TYPE_FLOW_DISSECTOR);
2186 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
2187 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;