1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2017 Facebook
4 #include "test_progs.h"
5 #include "cgroup_helpers.h"
6 #include "bpf_rlimit.h"
10 /* defined in test_progs.h */
13 struct prog_test_def
{
14 const char *test_name
;
16 void (*run_test
)(void);
21 bool need_cgroup_cleanup
;
23 const char *subtest_name
;
26 /* store counts before subtest started */
30 static bool should_run(struct test_selector
*sel
, int num
, const char *name
)
32 if (sel
->name
&& sel
->name
[0] && !strstr(name
, sel
->name
))
38 return num
< sel
->num_set_len
&& sel
->num_set
[num
];
41 static void dump_test_log(const struct prog_test_def
*test
, bool failed
)
43 if (stdout
== env
.stdout
)
46 fflush(stdout
); /* exports env.log_buf & env.log_cnt */
48 if (env
.verbose
|| test
->force_log
|| failed
) {
50 env
.log_buf
[env
.log_cnt
] = '\0';
51 fprintf(env
.stdout
, "%s", env
.log_buf
);
52 if (env
.log_buf
[env
.log_cnt
- 1] != '\n')
53 fprintf(env
.stdout
, "\n");
57 fseeko(stdout
, 0, SEEK_SET
); /* rewind */
60 static void skip_account(void)
62 if (env
.test
->skip_cnt
) {
64 env
.test
->skip_cnt
= 0;
68 void test__end_subtest()
70 struct prog_test_def
*test
= env
.test
;
71 int sub_error_cnt
= test
->error_cnt
- test
->old_error_cnt
;
79 dump_test_log(test
, sub_error_cnt
);
81 fprintf(env
.stdout
, "#%d/%d %s:%s\n",
82 test
->test_num
, test
->subtest_num
,
83 test
->subtest_name
, sub_error_cnt
? "FAIL" : "OK");
86 bool test__start_subtest(const char *name
)
88 struct prog_test_def
*test
= env
.test
;
90 if (test
->subtest_name
) {
92 test
->subtest_name
= NULL
;
97 if (!name
|| !name
[0]) {
99 "Subtest #%d didn't provide sub-test name!\n",
104 if (!should_run(&env
.subtest_selector
, test
->subtest_num
, name
))
107 test
->subtest_name
= name
;
108 env
.test
->old_error_cnt
= env
.test
->error_cnt
;
113 void test__force_log() {
114 env
.test
->force_log
= true;
117 void test__skip(void)
119 env
.test
->skip_cnt
++;
122 void test__fail(void)
124 env
.test
->error_cnt
++;
127 int test__join_cgroup(const char *path
)
131 if (!env
.test
->need_cgroup_cleanup
) {
132 if (setup_cgroup_environment()) {
134 "#%d %s: Failed to setup cgroup environment\n",
135 env
.test
->test_num
, env
.test
->test_name
);
139 env
.test
->need_cgroup_cleanup
= true;
142 fd
= create_and_get_cgroup(path
);
145 "#%d %s: Failed to create cgroup '%s' (errno=%d)\n",
146 env
.test
->test_num
, env
.test
->test_name
, path
, errno
);
150 if (join_cgroup(path
)) {
152 "#%d %s: Failed to join cgroup '%s' (errno=%d)\n",
153 env
.test
->test_num
, env
.test
->test_name
, path
, errno
);
160 struct ipv4_packet pkt_v4
= {
161 .eth
.h_proto
= __bpf_constant_htons(ETH_P_IP
),
163 .iph
.protocol
= IPPROTO_TCP
,
164 .iph
.tot_len
= __bpf_constant_htons(MAGIC_BYTES
),
169 struct ipv6_packet pkt_v6
= {
170 .eth
.h_proto
= __bpf_constant_htons(ETH_P_IPV6
),
171 .iph
.nexthdr
= IPPROTO_TCP
,
172 .iph
.payload_len
= __bpf_constant_htons(MAGIC_BYTES
),
177 int bpf_find_map(const char *test
, struct bpf_object
*obj
, const char *name
)
181 map
= bpf_object__find_map_by_name(obj
, name
);
183 printf("%s:FAIL:map '%s' not found\n", test
, name
);
187 return bpf_map__fd(map
);
190 static bool is_jit_enabled(void)
192 const char *jit_sysctl
= "/proc/sys/net/core/bpf_jit_enable";
193 bool enabled
= false;
196 sysctl_fd
= open(jit_sysctl
, 0, O_RDONLY
);
197 if (sysctl_fd
!= -1) {
200 if (read(sysctl_fd
, &tmpc
, sizeof(tmpc
)) == 1)
201 enabled
= (tmpc
!= '0');
208 int compare_map_keys(int map1_fd
, int map2_fd
)
211 char val_buf
[PERF_MAX_STACK_DEPTH
*
212 sizeof(struct bpf_stack_build_id
)];
215 err
= bpf_map_get_next_key(map1_fd
, NULL
, &key
);
218 err
= bpf_map_lookup_elem(map2_fd
, &key
, val_buf
);
222 while (bpf_map_get_next_key(map1_fd
, &key
, &next_key
) == 0) {
223 err
= bpf_map_lookup_elem(map2_fd
, &next_key
, val_buf
);
235 int compare_stack_ips(int smap_fd
, int amap_fd
, int stack_trace_len
)
237 __u32 key
, next_key
, *cur_key_p
, *next_key_p
;
238 char *val_buf1
, *val_buf2
;
241 val_buf1
= malloc(stack_trace_len
);
242 val_buf2
= malloc(stack_trace_len
);
245 while (bpf_map_get_next_key(smap_fd
, cur_key_p
, next_key_p
) == 0) {
246 err
= bpf_map_lookup_elem(smap_fd
, next_key_p
, val_buf1
);
249 err
= bpf_map_lookup_elem(amap_fd
, next_key_p
, val_buf2
);
252 for (i
= 0; i
< stack_trace_len
; i
++) {
253 if (val_buf1
[i
] != val_buf2
[i
]) {
260 next_key_p
= &next_key
;
271 int extract_build_id(char *build_id
, size_t size
)
277 fp
= popen("readelf -n ./urandom_read | grep 'Build ID'", "r");
281 if (getline(&line
, &len
, fp
) == -1)
287 memcpy(build_id
, line
, len
);
288 build_id
[len
] = '\0';
295 void *spin_lock_thread(void *arg
)
297 __u32 duration
, retval
;
298 int err
, prog_fd
= *(u32
*) arg
;
300 err
= bpf_prog_test_run(prog_fd
, 10000, &pkt_v4
, sizeof(pkt_v4
),
301 NULL
, NULL
, &retval
, &duration
);
302 CHECK(err
|| retval
, "",
303 "err %d errno %d retval %d duration %d\n",
304 err
, errno
, retval
, duration
);
308 /* extern declarations for test funcs */
309 #define DEFINE_TEST(name) extern void test_##name();
310 #include <prog_tests/tests.h>
313 static struct prog_test_def prog_test_defs
[] = {
314 #define DEFINE_TEST(name) { \
315 .test_name = #name, \
316 .run_test = &test_##name, \
318 #include <prog_tests/tests.h>
321 const int prog_test_cnt
= ARRAY_SIZE(prog_test_defs
);
323 const char *argp_program_version
= "test_progs 0.1";
324 const char *argp_program_bug_address
= "<bpf@vger.kernel.org>";
325 const char argp_program_doc
[] = "BPF selftests test runner";
330 ARG_VERIFIER_STATS
= 's',
334 static const struct argp_option opts
[] = {
335 { "num", ARG_TEST_NUM
, "NUM", 0,
336 "Run test number NUM only " },
337 { "name", ARG_TEST_NAME
, "NAME", 0,
338 "Run tests with names containing NAME" },
339 { "verifier-stats", ARG_VERIFIER_STATS
, NULL
, 0,
340 "Output verifier statistics", },
341 { "verbose", ARG_VERBOSE
, "LEVEL", OPTION_ARG_OPTIONAL
,
342 "Verbose output (use -vv for extra verbose output)" },
346 static int libbpf_print_fn(enum libbpf_print_level level
,
347 const char *format
, va_list args
)
349 if (!env
.very_verbose
&& level
== LIBBPF_DEBUG
)
351 vprintf(format
, args
);
355 int parse_num_list(const char *s
, struct test_selector
*sel
)
357 int i
, set_len
= 0, num
, start
= 0, end
= -1;
358 bool *set
= NULL
, *tmp
, parsing_end
= false;
363 num
= strtol(s
, &next
, 10);
372 if (!parsing_end
&& *next
== '-') {
376 } else if (*next
== ',') {
380 } else if (*next
== '\0') {
391 if (end
+ 1 > set_len
) {
393 tmp
= realloc(set
, set_len
);
400 for (i
= start
; i
<= end
; i
++) {
410 sel
->num_set_len
= set_len
;
415 static error_t
parse_arg(int key
, char *arg
, struct argp_state
*state
)
417 struct test_env
*env
= state
->input
;
421 char *subtest_str
= strchr(arg
, '/');
425 if (parse_num_list(subtest_str
+ 1,
426 &env
->subtest_selector
)) {
428 "Failed to parse subtest numbers.\n");
432 if (parse_num_list(arg
, &env
->test_selector
)) {
433 fprintf(stderr
, "Failed to parse test numbers.\n");
438 case ARG_TEST_NAME
: {
439 char *subtest_str
= strchr(arg
, '/');
443 env
->subtest_selector
.name
= strdup(subtest_str
+ 1);
444 if (!env
->subtest_selector
.name
)
447 env
->test_selector
.name
= strdup(arg
);
448 if (!env
->test_selector
.name
)
452 case ARG_VERIFIER_STATS
:
453 env
->verifier_stats
= true;
457 if (strcmp(arg
, "v") == 0) {
458 env
->very_verbose
= true;
461 "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n",
474 return ARGP_ERR_UNKNOWN
;
479 static void stdio_hijack(void)
486 /* nothing to do, output to stdout by default */
490 /* stdout and stderr -> buffer */
493 stdout
= open_memstream(&env
.log_buf
, &env
.log_cnt
);
496 perror("open_memstream");
504 static void stdio_restore(void)
507 if (stdout
== env
.stdout
)
521 int main(int argc
, char **argv
)
523 static const struct argp argp
= {
526 .doc
= argp_program_doc
,
530 err
= argp_parse(&argp
, argc
, argv
, 0, NULL
, &env
);
534 libbpf_set_print(libbpf_print_fn
);
538 env
.jit_enabled
= is_jit_enabled();
541 for (i
= 0; i
< prog_test_cnt
; i
++) {
542 struct prog_test_def
*test
= &prog_test_defs
[i
];
545 test
->test_num
= i
+ 1;
547 if (!should_run(&env
.test_selector
,
548 test
->test_num
, test
->test_name
))
552 /* ensure last sub-test is finalized properly */
553 if (test
->subtest_name
)
563 dump_test_log(test
, test
->error_cnt
);
565 fprintf(env
.stdout
, "#%d %s:%s\n",
566 test
->test_num
, test
->test_name
,
567 test
->error_cnt
? "FAIL" : "OK");
569 if (test
->need_cgroup_cleanup
)
570 cleanup_cgroup_environment();
573 printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
574 env
.succ_cnt
, env
.sub_succ_cnt
, env
.skip_cnt
, env
.fail_cnt
);
576 free(env
.test_selector
.num_set
);
577 free(env
.subtest_selector
.num_set
);
579 return env
.fail_cnt
? EXIT_FAILURE
: EXIT_SUCCESS
;