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.
15 #include <linux/types.h>
16 typedef __u16 __sum16;
17 #include <arpa/inet.h>
18 #include <linux/if_ether.h>
19 #include <linux/if_packet.h>
21 #include <linux/ipv6.h>
22 #include <linux/tcp.h>
23 #include <linux/filter.h>
24 #include <linux/perf_event.h>
25 #include <linux/unistd.h>
27 #include <sys/ioctl.h>
29 #include <sys/types.h>
32 #include <linux/bpf.h>
33 #include <linux/err.h>
35 #include <bpf/libbpf.h>
37 #include "test_iptunnel_common.h"
39 #include "bpf_endian.h"
40 #include "bpf_rlimit.h"
41 #include "trace_helpers.h"
42 #include "flow_dissector_load.h"
44 static int error_cnt, pass_cnt;
45 static bool jit_enabled;
47 #define MAGIC_BYTES 123
49 /* ipv4 test vector */
55 .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
57 .iph.protocol = IPPROTO_TCP,
58 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
63 /* ipv6 test vector */
69 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
70 .iph.nexthdr = IPPROTO_TCP,
71 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
76 #define _CHECK(condition, tag, duration, format...) ({ \
77 int __ret = !!(condition); \
80 printf("%s:FAIL:%s ", __func__, tag); \
84 printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\
89 #define CHECK(condition, tag, format...) \
90 _CHECK(condition, tag, duration, format)
91 #define CHECK_ATTR(condition, tag, format...) \
92 _CHECK(condition, tag, tattr.duration, format)
94 static int bpf_find_map(const char *test, struct bpf_object *obj,
99 map = bpf_object__find_map_by_name(obj, name);
101 printf("%s:FAIL:map '%s' not found\n", test, name);
105 return bpf_map__fd(map);
108 static void test_pkt_access(void)
110 const char *file = "./test_pkt_access.o";
111 struct bpf_object *obj;
112 __u32 duration, retval;
115 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
121 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
122 NULL, NULL, &retval, &duration);
123 CHECK(err || retval, "ipv4",
124 "err %d errno %d retval %d duration %d\n",
125 err, errno, retval, duration);
127 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v6, sizeof(pkt_v6),
128 NULL, NULL, &retval, &duration);
129 CHECK(err || retval, "ipv6",
130 "err %d errno %d retval %d duration %d\n",
131 err, errno, retval, duration);
132 bpf_object__close(obj);
135 static void test_prog_run_xattr(void)
137 const char *file = "./test_pkt_access.o";
138 struct bpf_object *obj;
141 struct bpf_prog_test_run_attr tattr = {
144 .data_size_in = sizeof(pkt_v4),
149 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj,
151 if (CHECK_ATTR(err, "load", "err %d errno %d\n", err, errno))
154 memset(buf, 0, sizeof(buf));
156 err = bpf_prog_test_run_xattr(&tattr);
157 CHECK_ATTR(err != -1 || errno != ENOSPC || tattr.retval, "run",
158 "err %d errno %d retval %d\n", err, errno, tattr.retval);
160 CHECK_ATTR(tattr.data_size_out != sizeof(pkt_v4), "data_size_out",
161 "incorrect output size, want %lu have %u\n",
162 sizeof(pkt_v4), tattr.data_size_out);
164 CHECK_ATTR(buf[5] != 0, "overflow",
165 "BPF_PROG_TEST_RUN ignored size hint\n");
167 tattr.data_out = NULL;
168 tattr.data_size_out = 0;
171 err = bpf_prog_test_run_xattr(&tattr);
172 CHECK_ATTR(err || errno || tattr.retval, "run_no_output",
173 "err %d errno %d retval %d\n", err, errno, tattr.retval);
175 tattr.data_size_out = 1;
176 err = bpf_prog_test_run_xattr(&tattr);
177 CHECK_ATTR(err != -EINVAL, "run_wrong_size_out", "err %d\n", err);
179 bpf_object__close(obj);
182 static void test_xdp(void)
184 struct vip key4 = {.protocol = 6, .family = AF_INET};
185 struct vip key6 = {.protocol = 6, .family = AF_INET6};
186 struct iptnl_info value4 = {.family = AF_INET};
187 struct iptnl_info value6 = {.family = AF_INET6};
188 const char *file = "./test_xdp.o";
189 struct bpf_object *obj;
191 struct ipv6hdr *iph6 = (void *)buf + sizeof(struct ethhdr);
192 struct iphdr *iph = (void *)buf + sizeof(struct ethhdr);
193 __u32 duration, retval, size;
194 int err, prog_fd, map_fd;
196 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
202 map_fd = bpf_find_map(__func__, obj, "vip2tnl");
205 bpf_map_update_elem(map_fd, &key4, &value4, 0);
206 bpf_map_update_elem(map_fd, &key6, &value6, 0);
208 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
209 buf, &size, &retval, &duration);
211 CHECK(err || retval != XDP_TX || size != 74 ||
212 iph->protocol != IPPROTO_IPIP, "ipv4",
213 "err %d errno %d retval %d size %d\n",
214 err, errno, retval, size);
216 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
217 buf, &size, &retval, &duration);
218 CHECK(err || retval != XDP_TX || size != 114 ||
219 iph6->nexthdr != IPPROTO_IPV6, "ipv6",
220 "err %d errno %d retval %d size %d\n",
221 err, errno, retval, size);
223 bpf_object__close(obj);
226 static void test_xdp_adjust_tail(void)
228 const char *file = "./test_adjust_tail.o";
229 struct bpf_object *obj;
231 __u32 duration, retval, size;
234 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
240 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
241 buf, &size, &retval, &duration);
243 CHECK(err || retval != XDP_DROP,
244 "ipv4", "err %d errno %d retval %d size %d\n",
245 err, errno, retval, size);
247 err = bpf_prog_test_run(prog_fd, 1, &pkt_v6, sizeof(pkt_v6),
248 buf, &size, &retval, &duration);
249 CHECK(err || retval != XDP_TX || size != 54,
250 "ipv6", "err %d errno %d retval %d size %d\n",
251 err, errno, retval, size);
252 bpf_object__close(obj);
257 #define MAGIC_VAL 0x1234
258 #define NUM_ITER 100000
261 static void test_l4lb(const char *file)
263 unsigned int nr_cpus = bpf_num_possible_cpus();
264 struct vip key = {.protocol = 6};
268 } value = {.vip_num = VIP_NUM};
269 __u32 stats_key = VIP_NUM;
274 struct real_definition {
280 } real_def = {.dst = MAGIC_VAL};
281 __u32 ch_key = 11, real_num = 3;
282 __u32 duration, retval, size;
283 int err, i, prog_fd, map_fd;
284 __u64 bytes = 0, pkts = 0;
285 struct bpf_object *obj;
287 u32 *magic = (u32 *)buf;
289 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
295 map_fd = bpf_find_map(__func__, obj, "vip_map");
298 bpf_map_update_elem(map_fd, &key, &value, 0);
300 map_fd = bpf_find_map(__func__, obj, "ch_rings");
303 bpf_map_update_elem(map_fd, &ch_key, &real_num, 0);
305 map_fd = bpf_find_map(__func__, obj, "reals");
308 bpf_map_update_elem(map_fd, &real_num, &real_def, 0);
310 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
311 buf, &size, &retval, &duration);
312 CHECK(err || retval != 7/*TC_ACT_REDIRECT*/ || size != 54 ||
313 *magic != MAGIC_VAL, "ipv4",
314 "err %d errno %d retval %d size %d magic %x\n",
315 err, errno, retval, size, *magic);
317 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
318 buf, &size, &retval, &duration);
319 CHECK(err || retval != 7/*TC_ACT_REDIRECT*/ || size != 74 ||
320 *magic != MAGIC_VAL, "ipv6",
321 "err %d errno %d retval %d size %d magic %x\n",
322 err, errno, retval, size, *magic);
324 map_fd = bpf_find_map(__func__, obj, "stats");
327 bpf_map_lookup_elem(map_fd, &stats_key, stats);
328 for (i = 0; i < nr_cpus; i++) {
329 bytes += stats[i].bytes;
330 pkts += stats[i].pkts;
332 if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
334 printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
337 bpf_object__close(obj);
340 static void test_l4lb_all(void)
342 const char *file1 = "./test_l4lb.o";
343 const char *file2 = "./test_l4lb_noinline.o";
349 static void test_xdp_noinline(void)
351 const char *file = "./test_xdp_noinline.o";
352 unsigned int nr_cpus = bpf_num_possible_cpus();
353 struct vip key = {.protocol = 6};
357 } value = {.vip_num = VIP_NUM};
358 __u32 stats_key = VIP_NUM;
363 struct real_definition {
369 } real_def = {.dst = MAGIC_VAL};
370 __u32 ch_key = 11, real_num = 3;
371 __u32 duration, retval, size;
372 int err, i, prog_fd, map_fd;
373 __u64 bytes = 0, pkts = 0;
374 struct bpf_object *obj;
376 u32 *magic = (u32 *)buf;
378 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
384 map_fd = bpf_find_map(__func__, obj, "vip_map");
387 bpf_map_update_elem(map_fd, &key, &value, 0);
389 map_fd = bpf_find_map(__func__, obj, "ch_rings");
392 bpf_map_update_elem(map_fd, &ch_key, &real_num, 0);
394 map_fd = bpf_find_map(__func__, obj, "reals");
397 bpf_map_update_elem(map_fd, &real_num, &real_def, 0);
399 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v4, sizeof(pkt_v4),
400 buf, &size, &retval, &duration);
401 CHECK(err || retval != 1 || size != 54 ||
402 *magic != MAGIC_VAL, "ipv4",
403 "err %d errno %d retval %d size %d magic %x\n",
404 err, errno, retval, size, *magic);
406 err = bpf_prog_test_run(prog_fd, NUM_ITER, &pkt_v6, sizeof(pkt_v6),
407 buf, &size, &retval, &duration);
408 CHECK(err || retval != 1 || size != 74 ||
409 *magic != MAGIC_VAL, "ipv6",
410 "err %d errno %d retval %d size %d magic %x\n",
411 err, errno, retval, size, *magic);
413 map_fd = bpf_find_map(__func__, obj, "stats");
416 bpf_map_lookup_elem(map_fd, &stats_key, stats);
417 for (i = 0; i < nr_cpus; i++) {
418 bytes += stats[i].bytes;
419 pkts += stats[i].pkts;
421 if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
423 printf("test_xdp_noinline:FAIL:stats %lld %lld\n", bytes, pkts);
426 bpf_object__close(obj);
429 static void test_tcp_estats(void)
431 const char *file = "./test_tcp_estats.o";
433 struct bpf_object *obj;
436 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
437 CHECK(err, "", "err %d errno %d\n", err, errno);
443 bpf_object__close(obj);
446 static inline __u64 ptr_to_u64(const void *ptr)
448 return (__u64) (unsigned long) ptr;
451 static bool is_jit_enabled(void)
453 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
454 bool enabled = false;
457 sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
458 if (sysctl_fd != -1) {
461 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
462 enabled = (tmpc != '0');
469 static void test_bpf_obj_id(void)
471 const __u64 array_magic_value = 0xfaceb00c;
472 const __u32 array_key = 0;
473 const int nr_iters = 2;
474 const char *file = "./test_obj_id.o";
475 const char *expected_prog_name = "test_obj_id";
476 const char *expected_map_name = "test_map_id";
477 const __u64 nsec_per_sec = 1000000000;
479 struct bpf_object *objs[nr_iters];
480 int prog_fds[nr_iters], map_fds[nr_iters];
481 /* +1 to test for the info_len returned by kernel */
482 struct bpf_prog_info prog_infos[nr_iters + 1];
483 struct bpf_map_info map_infos[nr_iters + 1];
484 /* Each prog only uses one map. +1 to test nr_map_ids
485 * returned by kernel.
487 __u32 map_ids[nr_iters + 1];
488 char jited_insns[128], xlated_insns[128], zeros[128];
489 __u32 i, next_id, info_len, nr_id_found, duration = 0;
490 struct timespec real_time_ts, boot_time_ts;
493 uid_t my_uid = getuid();
494 time_t now, load_time;
496 err = bpf_prog_get_fd_by_id(0);
497 CHECK(err >= 0 || errno != ENOENT,
498 "get-fd-by-notexist-prog-id", "err %d errno %d\n", err, errno);
500 err = bpf_map_get_fd_by_id(0);
501 CHECK(err >= 0 || errno != ENOENT,
502 "get-fd-by-notexist-map-id", "err %d errno %d\n", err, errno);
504 for (i = 0; i < nr_iters; i++)
507 /* Check bpf_obj_get_info_by_fd() */
508 bzero(zeros, sizeof(zeros));
509 for (i = 0; i < nr_iters; i++) {
511 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
512 &objs[i], &prog_fds[i]);
513 /* test_obj_id.o is a dumb prog. It should never fail
520 /* Insert a magic value to the map */
521 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
522 assert(map_fds[i] >= 0);
523 err = bpf_map_update_elem(map_fds[i], &array_key,
524 &array_magic_value, 0);
527 /* Check getting map info */
528 info_len = sizeof(struct bpf_map_info) * 2;
529 bzero(&map_infos[i], info_len);
530 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i],
533 map_infos[i].type != BPF_MAP_TYPE_ARRAY ||
534 map_infos[i].key_size != sizeof(__u32) ||
535 map_infos[i].value_size != sizeof(__u64) ||
536 map_infos[i].max_entries != 1 ||
537 map_infos[i].map_flags != 0 ||
538 info_len != sizeof(struct bpf_map_info) ||
539 strcmp((char *)map_infos[i].name, expected_map_name),
541 "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",
543 map_infos[i].type, BPF_MAP_TYPE_ARRAY,
544 info_len, sizeof(struct bpf_map_info),
545 map_infos[i].key_size,
546 map_infos[i].value_size,
547 map_infos[i].max_entries,
548 map_infos[i].map_flags,
549 map_infos[i].name, expected_map_name))
552 /* Check getting prog info */
553 info_len = sizeof(struct bpf_prog_info) * 2;
554 bzero(&prog_infos[i], info_len);
555 bzero(jited_insns, sizeof(jited_insns));
556 bzero(xlated_insns, sizeof(xlated_insns));
557 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
558 prog_infos[i].jited_prog_len = sizeof(jited_insns);
559 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
560 prog_infos[i].xlated_prog_len = sizeof(xlated_insns);
561 prog_infos[i].map_ids = ptr_to_u64(map_ids + i);
562 prog_infos[i].nr_map_ids = 2;
563 err = clock_gettime(CLOCK_REALTIME, &real_time_ts);
565 err = clock_gettime(CLOCK_BOOTTIME, &boot_time_ts);
567 err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i],
569 load_time = (real_time_ts.tv_sec - boot_time_ts.tv_sec)
570 + (prog_infos[i].load_time / nsec_per_sec);
572 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
573 info_len != sizeof(struct bpf_prog_info) ||
574 (jit_enabled && !prog_infos[i].jited_prog_len) ||
576 !memcmp(jited_insns, zeros, sizeof(zeros))) ||
577 !prog_infos[i].xlated_prog_len ||
578 !memcmp(xlated_insns, zeros, sizeof(zeros)) ||
579 load_time < now - 60 || load_time > now + 60 ||
580 prog_infos[i].created_by_uid != my_uid ||
581 prog_infos[i].nr_map_ids != 1 ||
582 *(int *)(long)prog_infos[i].map_ids != map_infos[i].id ||
583 strcmp((char *)prog_infos[i].name, expected_prog_name),
585 "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",
587 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
588 info_len, sizeof(struct bpf_prog_info),
590 prog_infos[i].jited_prog_len,
591 prog_infos[i].xlated_prog_len,
592 !!memcmp(jited_insns, zeros, sizeof(zeros)),
593 !!memcmp(xlated_insns, zeros, sizeof(zeros)),
595 prog_infos[i].created_by_uid, my_uid,
596 prog_infos[i].nr_map_ids, 1,
597 *(int *)(long)prog_infos[i].map_ids, map_infos[i].id,
598 prog_infos[i].name, expected_prog_name))
602 /* Check bpf_prog_get_next_id() */
605 while (!bpf_prog_get_next_id(next_id, &next_id)) {
606 struct bpf_prog_info prog_info = {};
610 info_len = sizeof(prog_info);
612 prog_fd = bpf_prog_get_fd_by_id(next_id);
613 if (prog_fd < 0 && errno == ENOENT)
614 /* The bpf_prog is in the dead row */
616 if (CHECK(prog_fd < 0, "get-prog-fd(next_id)",
617 "prog_fd %d next_id %d errno %d\n",
618 prog_fd, next_id, errno))
621 for (i = 0; i < nr_iters; i++)
622 if (prog_infos[i].id == next_id)
631 * prog_info.nr_map_ids = 1
632 * prog_info.map_ids = NULL
634 prog_info.nr_map_ids = 1;
635 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
636 if (CHECK(!err || errno != EFAULT,
637 "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)",
640 bzero(&prog_info, sizeof(prog_info));
641 info_len = sizeof(prog_info);
643 saved_map_id = *(int *)((long)prog_infos[i].map_ids);
644 prog_info.map_ids = prog_infos[i].map_ids;
645 prog_info.nr_map_ids = 2;
646 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
647 prog_infos[i].jited_prog_insns = 0;
648 prog_infos[i].xlated_prog_insns = 0;
649 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
650 memcmp(&prog_info, &prog_infos[i], info_len) ||
651 *(int *)(long)prog_info.map_ids != saved_map_id,
652 "get-prog-info(next_id->fd)",
653 "err %d errno %d info_len %u(%Zu) memcmp %d map_id %u(%u)\n",
654 err, errno, info_len, sizeof(struct bpf_prog_info),
655 memcmp(&prog_info, &prog_infos[i], info_len),
656 *(int *)(long)prog_info.map_ids, saved_map_id);
659 CHECK(nr_id_found != nr_iters,
660 "check total prog id found by get_next_id",
661 "nr_id_found %u(%u)\n",
662 nr_id_found, nr_iters);
664 /* Check bpf_map_get_next_id() */
667 while (!bpf_map_get_next_id(next_id, &next_id)) {
668 struct bpf_map_info map_info = {};
671 info_len = sizeof(map_info);
673 map_fd = bpf_map_get_fd_by_id(next_id);
674 if (map_fd < 0 && errno == ENOENT)
675 /* The bpf_map is in the dead row */
677 if (CHECK(map_fd < 0, "get-map-fd(next_id)",
678 "map_fd %d next_id %u errno %d\n",
679 map_fd, next_id, errno))
682 for (i = 0; i < nr_iters; i++)
683 if (map_infos[i].id == next_id)
691 err = bpf_map_lookup_elem(map_fd, &array_key, &array_value);
694 err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
695 CHECK(err || info_len != sizeof(struct bpf_map_info) ||
696 memcmp(&map_info, &map_infos[i], info_len) ||
697 array_value != array_magic_value,
698 "check get-map-info(next_id->fd)",
699 "err %d errno %d info_len %u(%Zu) memcmp %d array_value %llu(%llu)\n",
700 err, errno, info_len, sizeof(struct bpf_map_info),
701 memcmp(&map_info, &map_infos[i], info_len),
702 array_value, array_magic_value);
706 CHECK(nr_id_found != nr_iters,
707 "check total map id found by get_next_id",
708 "nr_id_found %u(%u)\n",
709 nr_id_found, nr_iters);
712 for (i = 0; i < nr_iters; i++)
713 bpf_object__close(objs[i]);
716 static void test_pkt_md_access(void)
718 const char *file = "./test_pkt_md_access.o";
719 struct bpf_object *obj;
720 __u32 duration, retval;
723 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
729 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
730 NULL, NULL, &retval, &duration);
731 CHECK(err || retval, "",
732 "err %d errno %d retval %d duration %d\n",
733 err, errno, retval, duration);
735 bpf_object__close(obj);
738 static void test_obj_name(void)
746 { "_123456789ABCDE", 1, 0 },
747 { "_123456789ABCDEF", 0, EINVAL },
748 { "_123456789ABCD\n", 0, EINVAL },
750 struct bpf_insn prog[] = {
751 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
757 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
758 size_t name_len = strlen(tests[i].name) + 1;
763 /* test different attr.prog_name during BPF_PROG_LOAD */
764 ncopy = name_len < sizeof(attr.prog_name) ?
765 name_len : sizeof(attr.prog_name);
766 bzero(&attr, sizeof(attr));
767 attr.prog_type = BPF_PROG_TYPE_SCHED_CLS;
769 attr.insns = ptr_to_u64(prog);
770 attr.license = ptr_to_u64("");
771 memcpy(attr.prog_name, tests[i].name, ncopy);
773 fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
774 CHECK((tests[i].success && fd < 0) ||
775 (!tests[i].success && fd != -1) ||
776 (!tests[i].success && errno != tests[i].expected_errno),
777 "check-bpf-prog-name",
778 "fd %d(%d) errno %d(%d)\n",
779 fd, tests[i].success, errno, tests[i].expected_errno);
784 /* test different attr.map_name during BPF_MAP_CREATE */
785 ncopy = name_len < sizeof(attr.map_name) ?
786 name_len : sizeof(attr.map_name);
787 bzero(&attr, sizeof(attr));
788 attr.map_type = BPF_MAP_TYPE_ARRAY;
791 attr.max_entries = 1;
793 memcpy(attr.map_name, tests[i].name, ncopy);
794 fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
795 CHECK((tests[i].success && fd < 0) ||
796 (!tests[i].success && fd != -1) ||
797 (!tests[i].success && errno != tests[i].expected_errno),
798 "check-bpf-map-name",
799 "fd %d(%d) errno %d(%d)\n",
800 fd, tests[i].success, errno, tests[i].expected_errno);
807 static void test_tp_attach_query(void)
809 const int num_progs = 3;
810 int i, j, bytes, efd, err, prog_fd[num_progs], pmu_fd[num_progs];
811 __u32 duration = 0, info_len, saved_prog_ids[num_progs];
812 const char *file = "./test_tracepoint.o";
813 struct perf_event_query_bpf *query;
814 struct perf_event_attr attr = {};
815 struct bpf_object *obj[num_progs];
816 struct bpf_prog_info prog_info;
819 snprintf(buf, sizeof(buf),
820 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
821 efd = open(buf, O_RDONLY, 0);
822 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
824 bytes = read(efd, buf, sizeof(buf));
826 if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
827 "read", "bytes %d errno %d\n", bytes, errno))
830 attr.config = strtol(buf, NULL, 0);
831 attr.type = PERF_TYPE_TRACEPOINT;
832 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
833 attr.sample_period = 1;
834 attr.wakeup_events = 1;
836 query = malloc(sizeof(*query) + sizeof(__u32) * num_progs);
837 for (i = 0; i < num_progs; i++) {
838 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj[i],
840 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
843 bzero(&prog_info, sizeof(prog_info));
844 prog_info.jited_prog_len = 0;
845 prog_info.xlated_prog_len = 0;
846 prog_info.nr_map_ids = 0;
847 info_len = sizeof(prog_info);
848 err = bpf_obj_get_info_by_fd(prog_fd[i], &prog_info, &info_len);
849 if (CHECK(err, "bpf_obj_get_info_by_fd", "err %d errno %d\n",
852 saved_prog_ids[i] = prog_info.id;
854 pmu_fd[i] = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
855 0 /* cpu 0 */, -1 /* group id */,
857 if (CHECK(pmu_fd[i] < 0, "perf_event_open", "err %d errno %d\n",
860 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
861 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
866 /* check NULL prog array query */
867 query->ids_len = num_progs;
868 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
869 if (CHECK(err || query->prog_cnt != 0,
870 "perf_event_ioc_query_bpf",
871 "err %d errno %d query->prog_cnt %u\n",
872 err, errno, query->prog_cnt))
876 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[i]);
877 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
882 /* try to get # of programs only */
884 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
885 if (CHECK(err || query->prog_cnt != 2,
886 "perf_event_ioc_query_bpf",
887 "err %d errno %d query->prog_cnt %u\n",
888 err, errno, query->prog_cnt))
891 /* try a few negative tests */
892 /* invalid query pointer */
893 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF,
894 (struct perf_event_query_bpf *)0x1);
895 if (CHECK(!err || errno != EFAULT,
896 "perf_event_ioc_query_bpf",
897 "err %d errno %d\n", err, errno))
900 /* no enough space */
902 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
903 if (CHECK(!err || errno != ENOSPC || query->prog_cnt != 2,
904 "perf_event_ioc_query_bpf",
905 "err %d errno %d query->prog_cnt %u\n",
906 err, errno, query->prog_cnt))
910 query->ids_len = num_progs;
911 err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
912 if (CHECK(err || query->prog_cnt != (i + 1),
913 "perf_event_ioc_query_bpf",
914 "err %d errno %d query->prog_cnt %u\n",
915 err, errno, query->prog_cnt))
917 for (j = 0; j < i + 1; j++)
918 if (CHECK(saved_prog_ids[j] != query->ids[j],
919 "perf_event_ioc_query_bpf",
920 "#%d saved_prog_id %x query prog_id %x\n",
921 j, saved_prog_ids[j], query->ids[j]))
926 for (; i >= 0; i--) {
928 ioctl(pmu_fd[i], PERF_EVENT_IOC_DISABLE);
932 bpf_object__close(obj[i]);
937 static int compare_map_keys(int map1_fd, int map2_fd)
940 char val_buf[PERF_MAX_STACK_DEPTH *
941 sizeof(struct bpf_stack_build_id)];
944 err = bpf_map_get_next_key(map1_fd, NULL, &key);
947 err = bpf_map_lookup_elem(map2_fd, &key, val_buf);
951 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) {
952 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf);
964 static int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len)
966 __u32 key, next_key, *cur_key_p, *next_key_p;
967 char *val_buf1, *val_buf2;
970 val_buf1 = malloc(stack_trace_len);
971 val_buf2 = malloc(stack_trace_len);
974 while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) {
975 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1);
978 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2);
981 for (i = 0; i < stack_trace_len; i++) {
982 if (val_buf1[i] != val_buf2[i]) {
989 next_key_p = &next_key;
1000 static void test_stacktrace_map()
1002 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
1003 const char *file = "./test_stacktrace_map.o";
1004 int bytes, efd, err, pmu_fd, prog_fd, stack_trace_len;
1005 struct perf_event_attr attr = {};
1006 __u32 key, val, duration = 0;
1007 struct bpf_object *obj;
1010 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1011 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1014 /* Get the ID for the sched/sched_switch tracepoint */
1015 snprintf(buf, sizeof(buf),
1016 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
1017 efd = open(buf, O_RDONLY, 0);
1018 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1021 bytes = read(efd, buf, sizeof(buf));
1023 if (bytes <= 0 || bytes >= sizeof(buf))
1026 /* Open the perf event and attach bpf progrram */
1027 attr.config = strtol(buf, NULL, 0);
1028 attr.type = PERF_TYPE_TRACEPOINT;
1029 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
1030 attr.sample_period = 1;
1031 attr.wakeup_events = 1;
1032 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1033 0 /* cpu 0 */, -1 /* group id */,
1035 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n",
1039 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1043 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1048 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1049 if (control_map_fd < 0)
1052 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1053 if (stackid_hmap_fd < 0)
1056 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1057 if (stackmap_fd < 0)
1060 stack_amap_fd = bpf_find_map(__func__, obj, "stack_amap");
1061 if (stack_amap_fd < 0)
1064 /* give some time for bpf program run */
1067 /* disable stack trace collection */
1070 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1072 /* for every element in stackid_hmap, we can find a corresponding one
1073 * in stackmap, and vise versa.
1075 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1076 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1077 "err %d errno %d\n", err, errno))
1078 goto disable_pmu_noerr;
1080 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1081 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1082 "err %d errno %d\n", err, errno))
1083 goto disable_pmu_noerr;
1085 stack_trace_len = PERF_MAX_STACK_DEPTH * sizeof(__u64);
1086 err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len);
1087 if (CHECK(err, "compare_stack_ips stackmap vs. stack_amap",
1088 "err %d errno %d\n", err, errno))
1089 goto disable_pmu_noerr;
1091 goto disable_pmu_noerr;
1095 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1098 bpf_object__close(obj);
1101 static void test_stacktrace_map_raw_tp()
1103 int control_map_fd, stackid_hmap_fd, stackmap_fd;
1104 const char *file = "./test_stacktrace_map.o";
1105 int efd, err, prog_fd;
1106 __u32 key, val, duration = 0;
1107 struct bpf_object *obj;
1109 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
1110 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1113 efd = bpf_raw_tracepoint_open("sched_switch", prog_fd);
1114 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
1118 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1119 if (control_map_fd < 0)
1122 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1123 if (stackid_hmap_fd < 0)
1126 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1127 if (stackmap_fd < 0)
1130 /* give some time for bpf program run */
1133 /* disable stack trace collection */
1136 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1138 /* for every element in stackid_hmap, we can find a corresponding one
1139 * in stackmap, and vise versa.
1141 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1142 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1143 "err %d errno %d\n", err, errno))
1146 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1147 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1148 "err %d errno %d\n", err, errno))
1151 goto close_prog_noerr;
1155 bpf_object__close(obj);
1158 static int extract_build_id(char *build_id, size_t size)
1164 fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r");
1168 if (getline(&line, &len, fp) == -1)
1174 memcpy(build_id, line, len);
1175 build_id[len] = '\0';
1182 static void test_stacktrace_build_id(void)
1184 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
1185 const char *file = "./test_stacktrace_build_id.o";
1186 int bytes, efd, err, pmu_fd, prog_fd, stack_trace_len;
1187 struct perf_event_attr attr = {};
1188 __u32 key, previous_key, val, duration = 0;
1189 struct bpf_object *obj;
1192 struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
1193 int build_id_matches = 0;
1197 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1198 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1201 /* Get the ID for the sched/sched_switch tracepoint */
1202 snprintf(buf, sizeof(buf),
1203 "/sys/kernel/debug/tracing/events/random/urandom_read/id");
1204 efd = open(buf, O_RDONLY, 0);
1205 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1208 bytes = read(efd, buf, sizeof(buf));
1210 if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
1211 "read", "bytes %d errno %d\n", bytes, errno))
1214 /* Open the perf event and attach bpf progrram */
1215 attr.config = strtol(buf, NULL, 0);
1216 attr.type = PERF_TYPE_TRACEPOINT;
1217 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
1218 attr.sample_period = 1;
1219 attr.wakeup_events = 1;
1220 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1221 0 /* cpu 0 */, -1 /* group id */,
1223 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n",
1227 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1228 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
1232 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1233 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
1238 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1239 if (CHECK(control_map_fd < 0, "bpf_find_map control_map",
1240 "err %d errno %d\n", err, errno))
1243 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1244 if (CHECK(stackid_hmap_fd < 0, "bpf_find_map stackid_hmap",
1245 "err %d errno %d\n", err, errno))
1248 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1249 if (CHECK(stackmap_fd < 0, "bpf_find_map stackmap", "err %d errno %d\n",
1253 stack_amap_fd = bpf_find_map(__func__, obj, "stack_amap");
1254 if (CHECK(stack_amap_fd < 0, "bpf_find_map stack_amap",
1255 "err %d errno %d\n", err, errno))
1258 assert(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null")
1260 assert(system("./urandom_read") == 0);
1261 /* disable stack trace collection */
1264 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1266 /* for every element in stackid_hmap, we can find a corresponding one
1267 * in stackmap, and vise versa.
1269 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1270 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1271 "err %d errno %d\n", err, errno))
1274 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1275 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1276 "err %d errno %d\n", err, errno))
1279 err = extract_build_id(buf, 256);
1281 if (CHECK(err, "get build_id with readelf",
1282 "err %d errno %d\n", err, errno))
1285 err = bpf_map_get_next_key(stackmap_fd, NULL, &key);
1286 if (CHECK(err, "get_next_key from stackmap",
1287 "err %d, errno %d\n", err, errno))
1293 err = bpf_map_lookup_elem(stackmap_fd, &key, id_offs);
1294 if (CHECK(err, "lookup_elem from stackmap",
1295 "err %d, errno %d\n", err, errno))
1297 for (i = 0; i < PERF_MAX_STACK_DEPTH; ++i)
1298 if (id_offs[i].status == BPF_STACK_BUILD_ID_VALID &&
1299 id_offs[i].offset != 0) {
1300 for (j = 0; j < 20; ++j)
1301 sprintf(build_id + 2 * j, "%02x",
1302 id_offs[i].build_id[j] & 0xff);
1303 if (strstr(buf, build_id) != NULL)
1304 build_id_matches = 1;
1307 } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
1309 /* stack_map_get_build_id_offset() is racy and sometimes can return
1310 * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
1311 * try it one more time.
1313 if (build_id_matches < 1 && retry--) {
1314 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1316 bpf_object__close(obj);
1317 printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
1322 if (CHECK(build_id_matches < 1, "build id match",
1323 "Didn't find expected build ID from the map\n"))
1326 stack_trace_len = PERF_MAX_STACK_DEPTH
1327 * sizeof(struct bpf_stack_build_id);
1328 err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len);
1329 CHECK(err, "compare_stack_ips stackmap vs. stack_amap",
1330 "err %d errno %d\n", err, errno);
1333 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1339 bpf_object__close(obj);
1345 static void test_stacktrace_build_id_nmi(void)
1347 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
1348 const char *file = "./test_stacktrace_build_id.o";
1349 int err, pmu_fd, prog_fd;
1350 struct perf_event_attr attr = {
1351 .sample_freq = 5000,
1353 .type = PERF_TYPE_HARDWARE,
1354 .config = PERF_COUNT_HW_CPU_CYCLES,
1356 __u32 key, previous_key, val, duration = 0;
1357 struct bpf_object *obj;
1360 struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
1361 int build_id_matches = 0;
1365 err = bpf_prog_load(file, BPF_PROG_TYPE_PERF_EVENT, &obj, &prog_fd);
1366 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
1369 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1370 0 /* cpu 0 */, -1 /* group id */,
1372 if (CHECK(pmu_fd < 0, "perf_event_open",
1373 "err %d errno %d. Does the test host support PERF_COUNT_HW_CPU_CYCLES?\n",
1377 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1378 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
1382 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1383 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
1388 control_map_fd = bpf_find_map(__func__, obj, "control_map");
1389 if (CHECK(control_map_fd < 0, "bpf_find_map control_map",
1390 "err %d errno %d\n", err, errno))
1393 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
1394 if (CHECK(stackid_hmap_fd < 0, "bpf_find_map stackid_hmap",
1395 "err %d errno %d\n", err, errno))
1398 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
1399 if (CHECK(stackmap_fd < 0, "bpf_find_map stackmap", "err %d errno %d\n",
1403 stack_amap_fd = bpf_find_map(__func__, obj, "stack_amap");
1404 if (CHECK(stack_amap_fd < 0, "bpf_find_map stack_amap",
1405 "err %d errno %d\n", err, errno))
1408 assert(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null")
1410 assert(system("taskset 0x1 ./urandom_read 100000") == 0);
1411 /* disable stack trace collection */
1414 bpf_map_update_elem(control_map_fd, &key, &val, 0);
1416 /* for every element in stackid_hmap, we can find a corresponding one
1417 * in stackmap, and vise versa.
1419 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
1420 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
1421 "err %d errno %d\n", err, errno))
1424 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
1425 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
1426 "err %d errno %d\n", err, errno))
1429 err = extract_build_id(buf, 256);
1431 if (CHECK(err, "get build_id with readelf",
1432 "err %d errno %d\n", err, errno))
1435 err = bpf_map_get_next_key(stackmap_fd, NULL, &key);
1436 if (CHECK(err, "get_next_key from stackmap",
1437 "err %d, errno %d\n", err, errno))
1443 err = bpf_map_lookup_elem(stackmap_fd, &key, id_offs);
1444 if (CHECK(err, "lookup_elem from stackmap",
1445 "err %d, errno %d\n", err, errno))
1447 for (i = 0; i < PERF_MAX_STACK_DEPTH; ++i)
1448 if (id_offs[i].status == BPF_STACK_BUILD_ID_VALID &&
1449 id_offs[i].offset != 0) {
1450 for (j = 0; j < 20; ++j)
1451 sprintf(build_id + 2 * j, "%02x",
1452 id_offs[i].build_id[j] & 0xff);
1453 if (strstr(buf, build_id) != NULL)
1454 build_id_matches = 1;
1457 } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
1459 /* stack_map_get_build_id_offset() is racy and sometimes can return
1460 * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
1461 * try it one more time.
1463 if (build_id_matches < 1 && retry--) {
1464 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1466 bpf_object__close(obj);
1467 printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
1472 if (CHECK(build_id_matches < 1, "build id match",
1473 "Didn't find expected build ID from the map\n"))
1477 * We intentionally skip compare_stack_ips(). This is because we
1478 * only support one in_nmi() ips-to-build_id translation per cpu
1479 * at any time, thus stack_amap here will always fallback to
1480 * BPF_STACK_BUILD_ID_IP;
1484 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
1490 bpf_object__close(obj);
1493 #define MAX_CNT_RAWTP 10ull
1494 #define MAX_STACK_RAWTP 100
1495 struct get_stack_trace_t {
1497 int kern_stack_size;
1498 int user_stack_size;
1499 int user_stack_buildid_size;
1500 __u64 kern_stack[MAX_STACK_RAWTP];
1501 __u64 user_stack[MAX_STACK_RAWTP];
1502 struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP];
1505 static int get_stack_print_output(void *data, int size)
1507 bool good_kern_stack = false, good_user_stack = false;
1508 const char *nonjit_func = "___bpf_prog_run";
1509 struct get_stack_trace_t *e = data;
1516 if (size < sizeof(struct get_stack_trace_t)) {
1517 __u64 *raw_data = data;
1520 num_stack = size / sizeof(__u64);
1521 /* If jit is enabled, we do not have a good way to
1522 * verify the sanity of the kernel stack. So we
1523 * just assume it is good if the stack is not empty.
1524 * This could be improved in the future.
1527 found = num_stack > 0;
1529 for (i = 0; i < num_stack; i++) {
1530 ks = ksym_search(raw_data[i]);
1531 if (strcmp(ks->name, nonjit_func) == 0) {
1538 good_kern_stack = true;
1539 good_user_stack = true;
1542 num_stack = e->kern_stack_size / sizeof(__u64);
1544 good_kern_stack = num_stack > 0;
1546 for (i = 0; i < num_stack; i++) {
1547 ks = ksym_search(e->kern_stack[i]);
1548 if (strcmp(ks->name, nonjit_func) == 0) {
1549 good_kern_stack = true;
1554 if (e->user_stack_size > 0 && e->user_stack_buildid_size > 0)
1555 good_user_stack = true;
1557 if (!good_kern_stack || !good_user_stack)
1558 return LIBBPF_PERF_EVENT_ERROR;
1560 if (cnt == MAX_CNT_RAWTP)
1561 return LIBBPF_PERF_EVENT_DONE;
1563 return LIBBPF_PERF_EVENT_CONT;
1566 static void test_get_stack_raw_tp(void)
1568 const char *file = "./test_get_stack_rawtp.o";
1569 int i, efd, err, prog_fd, pmu_fd, perfmap_fd;
1570 struct perf_event_attr attr = {};
1571 struct timespec tv = {0, 10};
1572 __u32 key = 0, duration = 0;
1573 struct bpf_object *obj;
1575 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
1576 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1579 efd = bpf_raw_tracepoint_open("sys_enter", prog_fd);
1580 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
1583 perfmap_fd = bpf_find_map(__func__, obj, "perfmap");
1584 if (CHECK(perfmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
1588 err = load_kallsyms();
1589 if (CHECK(err < 0, "load_kallsyms", "err %d errno %d\n", err, errno))
1592 attr.sample_type = PERF_SAMPLE_RAW;
1593 attr.type = PERF_TYPE_SOFTWARE;
1594 attr.config = PERF_COUNT_SW_BPF_OUTPUT;
1595 pmu_fd = syscall(__NR_perf_event_open, &attr, getpid()/*pid*/, -1/*cpu*/,
1597 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd,
1601 err = bpf_map_update_elem(perfmap_fd, &key, &pmu_fd, BPF_ANY);
1602 if (CHECK(err < 0, "bpf_map_update_elem", "err %d errno %d\n", err,
1606 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1607 if (CHECK(err < 0, "ioctl PERF_EVENT_IOC_ENABLE", "err %d errno %d\n",
1611 err = perf_event_mmap(pmu_fd);
1612 if (CHECK(err < 0, "perf_event_mmap", "err %d errno %d\n", err, errno))
1615 /* trigger some syscall action */
1616 for (i = 0; i < MAX_CNT_RAWTP; i++)
1617 nanosleep(&tv, NULL);
1619 err = perf_event_poller(pmu_fd, get_stack_print_output);
1620 if (CHECK(err < 0, "perf_event_poller", "err %d errno %d\n", err, errno))
1623 goto close_prog_noerr;
1627 bpf_object__close(obj);
1630 static void test_task_fd_query_rawtp(void)
1632 const char *file = "./test_get_stack_rawtp.o";
1633 __u64 probe_offset, probe_addr;
1634 __u32 len, prog_id, fd_type;
1635 struct bpf_object *obj;
1636 int efd, err, prog_fd;
1640 err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
1641 if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
1644 efd = bpf_raw_tracepoint_open("sys_enter", prog_fd);
1645 if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
1648 /* query (getpid(), efd) */
1650 err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id,
1651 &fd_type, &probe_offset, &probe_addr);
1652 if (CHECK(err < 0, "bpf_task_fd_query", "err %d errno %d\n", err,
1656 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1657 strcmp(buf, "sys_enter") == 0;
1658 if (CHECK(!err, "check_results", "fd_type %d tp_name %s\n",
1664 err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id,
1665 &fd_type, &probe_offset, &probe_addr);
1666 if (CHECK(err < 0, "bpf_task_fd_query (len = 0)", "err %d errno %d\n",
1669 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1670 len == strlen("sys_enter");
1671 if (CHECK(!err, "check_results", "fd_type %d len %u\n", fd_type, len))
1674 /* test empty buffer */
1676 err = bpf_task_fd_query(getpid(), efd, 0, 0, &len, &prog_id,
1677 &fd_type, &probe_offset, &probe_addr);
1678 if (CHECK(err < 0, "bpf_task_fd_query (buf = 0)", "err %d errno %d\n",
1681 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1682 len == strlen("sys_enter");
1683 if (CHECK(!err, "check_results", "fd_type %d len %u\n", fd_type, len))
1686 /* test smaller buffer */
1688 err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id,
1689 &fd_type, &probe_offset, &probe_addr);
1690 if (CHECK(err >= 0 || errno != ENOSPC, "bpf_task_fd_query (len = 3)",
1691 "err %d errno %d\n", err, errno))
1693 err = fd_type == BPF_FD_TYPE_RAW_TRACEPOINT &&
1694 len == strlen("sys_enter") &&
1695 strcmp(buf, "sy") == 0;
1696 if (CHECK(!err, "check_results", "fd_type %d len %u\n", fd_type, len))
1699 goto close_prog_noerr;
1703 bpf_object__close(obj);
1706 static void test_task_fd_query_tp_core(const char *probe_name,
1707 const char *tp_name)
1709 const char *file = "./test_tracepoint.o";
1710 int err, bytes, efd, prog_fd, pmu_fd;
1711 struct perf_event_attr attr = {};
1712 __u64 probe_offset, probe_addr;
1713 __u32 len, prog_id, fd_type;
1714 struct bpf_object *obj;
1718 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
1719 if (CHECK(err, "bpf_prog_load", "err %d errno %d\n", err, errno))
1722 snprintf(buf, sizeof(buf),
1723 "/sys/kernel/debug/tracing/events/%s/id", probe_name);
1724 efd = open(buf, O_RDONLY, 0);
1725 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
1727 bytes = read(efd, buf, sizeof(buf));
1729 if (CHECK(bytes <= 0 || bytes >= sizeof(buf), "read",
1730 "bytes %d errno %d\n", bytes, errno))
1733 attr.config = strtol(buf, NULL, 0);
1734 attr.type = PERF_TYPE_TRACEPOINT;
1735 attr.sample_type = PERF_SAMPLE_RAW;
1736 attr.sample_period = 1;
1737 attr.wakeup_events = 1;
1738 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
1739 0 /* cpu 0 */, -1 /* group id */,
1741 if (CHECK(err, "perf_event_open", "err %d errno %d\n", err, errno))
1744 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
1745 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", err,
1749 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
1750 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", err,
1754 /* query (getpid(), pmu_fd) */
1756 err = bpf_task_fd_query(getpid(), pmu_fd, 0, buf, &len, &prog_id,
1757 &fd_type, &probe_offset, &probe_addr);
1758 if (CHECK(err < 0, "bpf_task_fd_query", "err %d errno %d\n", err,
1762 err = (fd_type == BPF_FD_TYPE_TRACEPOINT) && !strcmp(buf, tp_name);
1763 if (CHECK(!err, "check_results", "fd_type %d tp_name %s\n",
1768 goto close_prog_noerr;
1775 bpf_object__close(obj);
1778 static void test_task_fd_query_tp(void)
1780 test_task_fd_query_tp_core("sched/sched_switch",
1782 test_task_fd_query_tp_core("syscalls/sys_enter_read",
1786 static void test_reference_tracking()
1788 const char *file = "./test_sk_lookup_kern.o";
1789 struct bpf_object *obj;
1790 struct bpf_program *prog;
1794 obj = bpf_object__open(file);
1800 bpf_object__for_each_program(prog, obj) {
1803 /* Ignore .text sections */
1804 title = bpf_program__title(prog, false);
1805 if (strstr(title, ".text") != NULL)
1808 bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
1810 /* Expect verifier failure if test name has 'fail' */
1811 if (strstr(title, "fail") != NULL) {
1812 libbpf_set_print(NULL, NULL, NULL);
1813 err = !bpf_program__load(prog, "GPL", 0);
1814 libbpf_set_print(printf, printf, NULL);
1816 err = bpf_program__load(prog, "GPL", 0);
1818 CHECK(err, title, "\n");
1820 bpf_object__close(obj);
1828 static void test_queue_stack_map(int type)
1830 const int MAP_SIZE = 32;
1831 __u32 vals[MAP_SIZE], duration, retval, size, val;
1832 int i, err, prog_fd, map_in_fd, map_out_fd;
1833 char file[32], buf[128];
1834 struct bpf_object *obj;
1835 struct iphdr *iph = (void *)buf + sizeof(struct ethhdr);
1837 /* Fill test values to be used */
1838 for (i = 0; i < MAP_SIZE; i++)
1842 strncpy(file, "./test_queue_map.o", sizeof(file));
1843 else if (type == STACK)
1844 strncpy(file, "./test_stack_map.o", sizeof(file));
1848 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
1854 map_in_fd = bpf_find_map(__func__, obj, "map_in");
1858 map_out_fd = bpf_find_map(__func__, obj, "map_out");
1862 /* Push 32 elements to the input map */
1863 for (i = 0; i < MAP_SIZE; i++) {
1864 err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0);
1871 /* The eBPF program pushes iph.saddr in the output map,
1872 * pops the input map and saves this value in iph.daddr
1874 for (i = 0; i < MAP_SIZE; i++) {
1875 if (type == QUEUE) {
1877 pkt_v4.iph.saddr = vals[i] * 5;
1878 } else if (type == STACK) {
1879 val = vals[MAP_SIZE - 1 - i];
1880 pkt_v4.iph.saddr = vals[MAP_SIZE - 1 - i] * 5;
1883 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
1884 buf, &size, &retval, &duration);
1885 if (err || retval || size != sizeof(pkt_v4) ||
1890 CHECK(err || retval || size != sizeof(pkt_v4) || iph->daddr != val,
1892 "err %d errno %d retval %d size %d iph->daddr %u\n",
1893 err, errno, retval, size, iph->daddr);
1895 /* Queue is empty, program should return TC_ACT_SHOT */
1896 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
1897 buf, &size, &retval, &duration);
1898 CHECK(err || retval != 2 /* TC_ACT_SHOT */|| size != sizeof(pkt_v4),
1899 "check-queue-stack-map-empty",
1900 "err %d errno %d retval %d size %d\n",
1901 err, errno, retval, size);
1903 /* Check that the program pushed elements correctly */
1904 for (i = 0; i < MAP_SIZE; i++) {
1905 err = bpf_map_lookup_and_delete_elem(map_out_fd, NULL, &val);
1906 if (err || val != vals[i] * 5)
1910 CHECK(i != MAP_SIZE && (err || val != vals[i] * 5),
1911 "bpf_map_push_elem", "err %d value %u\n", err, val);
1914 pkt_v4.iph.saddr = 0;
1915 bpf_object__close(obj);
1918 #define CHECK_FLOW_KEYS(desc, got, expected) \
1919 CHECK(memcmp(&got, &expected, sizeof(got)) != 0, \
1923 "addr_proto=0x%x/0x%x " \
1925 "is_first_frag=%u/%u " \
1927 "n_proto=0x%x/0x%x " \
1930 got.nhoff, expected.nhoff, \
1931 got.thoff, expected.thoff, \
1932 got.addr_proto, expected.addr_proto, \
1933 got.is_frag, expected.is_frag, \
1934 got.is_first_frag, expected.is_first_frag, \
1935 got.is_encap, expected.is_encap, \
1936 got.n_proto, expected.n_proto, \
1937 got.sport, expected.sport, \
1938 got.dport, expected.dport)
1940 static struct bpf_flow_keys pkt_v4_flow_keys = {
1942 .thoff = sizeof(struct iphdr),
1943 .addr_proto = ETH_P_IP,
1944 .ip_proto = IPPROTO_TCP,
1945 .n_proto = bpf_htons(ETH_P_IP),
1948 static struct bpf_flow_keys pkt_v6_flow_keys = {
1950 .thoff = sizeof(struct ipv6hdr),
1951 .addr_proto = ETH_P_IPV6,
1952 .ip_proto = IPPROTO_TCP,
1953 .n_proto = bpf_htons(ETH_P_IPV6),
1956 static void test_flow_dissector(void)
1958 struct bpf_flow_keys flow_keys;
1959 struct bpf_object *obj;
1960 __u32 duration, retval;
1964 err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
1965 "jmp_table", &prog_fd);
1971 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
1972 &flow_keys, &size, &retval, &duration);
1973 CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv4",
1974 "err %d errno %d retval %d duration %d size %u/%lu\n",
1975 err, errno, retval, duration, size, sizeof(flow_keys));
1976 CHECK_FLOW_KEYS("ipv4_flow_keys", flow_keys, pkt_v4_flow_keys);
1978 err = bpf_prog_test_run(prog_fd, 10, &pkt_v6, sizeof(pkt_v6),
1979 &flow_keys, &size, &retval, &duration);
1980 CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv6",
1981 "err %d errno %d retval %d duration %d size %u/%lu\n",
1982 err, errno, retval, duration, size, sizeof(flow_keys));
1983 CHECK_FLOW_KEYS("ipv6_flow_keys", flow_keys, pkt_v6_flow_keys);
1985 bpf_object__close(obj);
1988 static void *test_spin_lock(void *arg)
1990 __u32 duration, retval;
1991 int err, prog_fd = *(u32 *) arg;
1993 err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4),
1994 NULL, NULL, &retval, &duration);
1995 CHECK(err || retval, "",
1996 "err %d errno %d retval %d duration %d\n",
1997 err, errno, retval, duration);
2001 static void test_spinlock(void)
2003 const char *file = "./test_spin_lock.o";
2004 pthread_t thread_id[4];
2005 struct bpf_object *obj;
2010 err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
2012 printf("test_spin_lock:bpf_prog_load errno %d\n", errno);
2015 for (i = 0; i < 4; i++)
2016 assert(pthread_create(&thread_id[i], NULL,
2017 &test_spin_lock, &prog_fd) == 0);
2018 for (i = 0; i < 4; i++)
2019 assert(pthread_join(thread_id[i], &ret) == 0 &&
2020 ret == (void *)&prog_fd);
2021 goto close_prog_noerr;
2025 bpf_object__close(obj);
2032 jit_enabled = is_jit_enabled();
2035 test_prog_run_xattr();
2037 test_xdp_adjust_tail();
2039 test_xdp_noinline();
2042 test_pkt_md_access();
2044 test_tp_attach_query();
2045 test_stacktrace_map();
2046 test_stacktrace_build_id();
2047 test_stacktrace_build_id_nmi();
2048 test_stacktrace_map_raw_tp();
2049 test_get_stack_raw_tp();
2050 test_task_fd_query_rawtp();
2051 test_task_fd_query_tp();
2052 test_reference_tracking();
2053 test_queue_stack_map(QUEUE);
2054 test_queue_stack_map(STACK);
2055 test_flow_dissector();
2058 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
2059 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;