1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2017 Facebook
3 */
4 #define _GNU_SOURCE
5 #include "test_progs.h"
6 #include "testing_helpers.h"
7 #include "cgroup_helpers.h"
8 #include <argp.h>
9 #include <pthread.h>
10 #include <sched.h>
11 #include <signal.h>
12 #include <string.h>
13 #include <sys/sysinfo.h> /* get_nprocs */
14 #include <netinet/in.h>
15 #include <sys/select.h>
16 #include <sys/socket.h>
17 #include <linux/keyctl.h>
18 #include <sys/un.h>
19 #include <bpf/btf.h>
20 #include <time.h>
21 #include "json_writer.h"
22
23 #include "network_helpers.h"
24 #include "verification_cert.h"
25
26 /* backtrace() and backtrace_symbols_fd() are glibc specific,
27 * use header file when glibc is available and provide stub
28 * implementations when another libc implementation is used.
29 */
30 #ifdef __GLIBC__
31 #include <execinfo.h> /* backtrace */
32 #else
backtrace(void ** buffer,int size)33 __weak int backtrace(void **buffer, int size)
34 {
35 return 0;
36 }
37
backtrace_symbols_fd(void * const * buffer,int size,int fd)38 __weak void backtrace_symbols_fd(void *const *buffer, int size, int fd)
39 {
40 dprintf(fd, "<backtrace not supported>\n");
41 }
42 #endif /*__GLIBC__ */
43
44 int env_verbosity = 0;
45
verbose(void)46 static bool verbose(void)
47 {
48 return env.verbosity > VERBOSE_NONE;
49 }
50
stdio_hijack_init(char ** log_buf,size_t * log_cnt)51 static void stdio_hijack_init(char **log_buf, size_t *log_cnt)
52 {
53 #ifdef __GLIBC__
54 if (verbose() && env.worker_id == -1) {
55 /* nothing to do, output to stdout by default */
56 return;
57 }
58
59 fflush(stdout);
60 fflush(stderr);
61
62 stdout = open_memstream(log_buf, log_cnt);
63 if (!stdout) {
64 stdout = env.stdout_saved;
65 perror("open_memstream");
66 return;
67 }
68
69 if (env.subtest_state)
70 env.subtest_state->stdout_saved = stdout;
71 else
72 env.test_state->stdout_saved = stdout;
73
74 stderr = stdout;
75 #endif
76 }
77
stdio_hijack(char ** log_buf,size_t * log_cnt)78 static void stdio_hijack(char **log_buf, size_t *log_cnt)
79 {
80 #ifdef __GLIBC__
81 if (verbose() && env.worker_id == -1) {
82 /* nothing to do, output to stdout by default */
83 return;
84 }
85
86 env.stdout_saved = stdout;
87 env.stderr_saved = stderr;
88
89 stdio_hijack_init(log_buf, log_cnt);
90 #endif
91 }
92
93 static pthread_mutex_t stdout_lock = PTHREAD_MUTEX_INITIALIZER;
94
stdio_restore(void)95 static void stdio_restore(void)
96 {
97 #ifdef __GLIBC__
98 if (verbose() && env.worker_id == -1) {
99 /* nothing to do, output to stdout by default */
100 return;
101 }
102
103 fflush(stdout);
104
105 pthread_mutex_lock(&stdout_lock);
106
107 if (env.subtest_state) {
108 if (env.subtest_state->stdout_saved)
109 fclose(env.subtest_state->stdout_saved);
110 env.subtest_state->stdout_saved = NULL;
111 stdout = env.test_state->stdout_saved;
112 stderr = env.test_state->stdout_saved;
113 } else {
114 if (env.test_state->stdout_saved)
115 fclose(env.test_state->stdout_saved);
116 env.test_state->stdout_saved = NULL;
117 stdout = env.stdout_saved;
118 stderr = env.stderr_saved;
119 }
120
121 pthread_mutex_unlock(&stdout_lock);
122 #endif
123 }
124
traffic_monitor_print_fn(const char * format,va_list args)125 static int traffic_monitor_print_fn(const char *format, va_list args)
126 {
127 pthread_mutex_lock(&stdout_lock);
128 vfprintf(stdout, format, args);
129 pthread_mutex_unlock(&stdout_lock);
130
131 return 0;
132 }
133
134 /* Adapted from perf/util/string.c */
glob_match(const char * str,const char * pat)135 static bool glob_match(const char *str, const char *pat)
136 {
137 while (*str && *pat && *pat != '*') {
138 if (*str != *pat)
139 return false;
140 str++;
141 pat++;
142 }
143 /* Check wild card */
144 if (*pat == '*') {
145 while (*pat == '*')
146 pat++;
147 if (!*pat) /* Tail wild card matches all */
148 return true;
149 while (*str)
150 if (glob_match(str++, pat))
151 return true;
152 }
153 return !*str && !*pat;
154 }
155
156 #define EXIT_NO_TEST 2
157 #define EXIT_ERR_SETUP_INFRA 3
158
159 /* defined in test_progs.h */
160 struct test_env env = {};
161
162 struct prog_test_def {
163 const char *test_name;
164 int test_num;
165 void (*run_test)(void);
166 void (*run_serial_test)(void);
167 bool should_run;
168 bool need_cgroup_cleanup;
169 bool should_tmon;
170 };
171
172 /* Override C runtime library's usleep() implementation to ensure nanosleep()
173 * is always called. Usleep is frequently used in selftests as a way to
174 * trigger kprobe and tracepoints.
175 */
usleep(useconds_t usec)176 int usleep(useconds_t usec)
177 {
178 struct timespec ts = {
179 .tv_sec = usec / 1000000,
180 .tv_nsec = (usec % 1000000) * 1000,
181 };
182
183 return syscall(__NR_nanosleep, &ts, NULL);
184 }
185
186 /* Watchdog timer is started by watchdog_start() and stopped by watchdog_stop().
187 * If timer is active for longer than env.secs_till_notify,
188 * it prints the name of the current test to the stderr.
189 * If timer is active for longer than env.secs_till_kill,
190 * it kills the thread executing the test by sending a SIGSEGV signal to it.
191 */
watchdog_timer_func(union sigval sigval)192 static void watchdog_timer_func(union sigval sigval)
193 {
194 struct itimerspec timeout = {};
195 char test_name[256];
196 int err;
197
198 if (env.subtest_state)
199 snprintf(test_name, sizeof(test_name), "%s/%s",
200 env.test->test_name, env.subtest_state->name);
201 else
202 snprintf(test_name, sizeof(test_name), "%s",
203 env.test->test_name);
204
205 switch (env.watchdog_state) {
206 case WD_NOTIFY:
207 fprintf(env.stderr_saved, "WATCHDOG: test case %s executes for %d seconds...\n",
208 test_name, env.secs_till_notify);
209 timeout.it_value.tv_sec = env.secs_till_kill - env.secs_till_notify;
210 env.watchdog_state = WD_KILL;
211 err = timer_settime(env.watchdog, 0, &timeout, NULL);
212 if (err)
213 fprintf(env.stderr_saved, "Failed to arm watchdog timer\n");
214 break;
215 case WD_KILL:
216 fprintf(env.stderr_saved,
217 "WATCHDOG: test case %s executes for %d seconds, terminating with SIGSEGV\n",
218 test_name, env.secs_till_kill);
219 pthread_kill(env.main_thread, SIGSEGV);
220 break;
221 }
222 }
223
watchdog_start(void)224 static void watchdog_start(void)
225 {
226 struct itimerspec timeout = {};
227 int err;
228
229 if (env.secs_till_kill == 0)
230 return;
231 if (env.secs_till_notify > 0) {
232 env.watchdog_state = WD_NOTIFY;
233 timeout.it_value.tv_sec = env.secs_till_notify;
234 } else {
235 env.watchdog_state = WD_KILL;
236 timeout.it_value.tv_sec = env.secs_till_kill;
237 }
238 err = timer_settime(env.watchdog, 0, &timeout, NULL);
239 if (err)
240 fprintf(env.stderr_saved, "Failed to start watchdog timer\n");
241 }
242
watchdog_stop(void)243 static void watchdog_stop(void)
244 {
245 struct itimerspec timeout = {};
246 int err;
247
248 env.watchdog_state = WD_NOTIFY;
249 err = timer_settime(env.watchdog, 0, &timeout, NULL);
250 if (err)
251 fprintf(env.stderr_saved, "Failed to stop watchdog timer\n");
252 }
253
watchdog_init(void)254 static void watchdog_init(void)
255 {
256 struct sigevent watchdog_sev = {
257 .sigev_notify = SIGEV_THREAD,
258 .sigev_notify_function = watchdog_timer_func,
259 };
260 int err;
261
262 env.main_thread = pthread_self();
263 err = timer_create(CLOCK_MONOTONIC, &watchdog_sev, &env.watchdog);
264 if (err)
265 fprintf(stderr, "Failed to initialize watchdog timer\n");
266 }
267
should_run(struct test_selector * sel,int num,const char * name)268 static bool should_run(struct test_selector *sel, int num, const char *name)
269 {
270 int i;
271
272 for (i = 0; i < sel->blacklist.cnt; i++) {
273 if (glob_match(name, sel->blacklist.tests[i].name) &&
274 !sel->blacklist.tests[i].subtest_cnt)
275 return false;
276 }
277
278 for (i = 0; i < sel->whitelist.cnt; i++) {
279 if (glob_match(name, sel->whitelist.tests[i].name))
280 return true;
281 }
282
283 if (!sel->whitelist.cnt && !sel->num_set)
284 return true;
285
286 return num < sel->num_set_len && sel->num_set[num];
287 }
288
match_subtest(struct test_filter_set * filter,const char * test_name,const char * subtest_name)289 static bool match_subtest(struct test_filter_set *filter,
290 const char *test_name,
291 const char *subtest_name)
292 {
293 int i, j;
294
295 for (i = 0; i < filter->cnt; i++) {
296 if (glob_match(test_name, filter->tests[i].name)) {
297 if (!filter->tests[i].subtest_cnt)
298 return true;
299
300 for (j = 0; j < filter->tests[i].subtest_cnt; j++) {
301 if (glob_match(subtest_name,
302 filter->tests[i].subtests[j]))
303 return true;
304 }
305 }
306 }
307
308 return false;
309 }
310
match_subtest_desc(struct test_filter_set * filter,const char * test_name,const char * subtest_name,const char * subtest_desc)311 static bool match_subtest_desc(struct test_filter_set *filter,
312 const char *test_name,
313 const char *subtest_name,
314 const char *subtest_desc)
315 {
316 if (match_subtest(filter, test_name, subtest_name))
317 return true;
318
319 if (!subtest_desc || !subtest_desc[0] ||
320 strcmp(subtest_name, subtest_desc) == 0)
321 return false;
322
323 return match_subtest(filter, test_name, subtest_desc);
324 }
325
should_run_subtest(struct test_selector * sel,struct test_selector * subtest_sel,int subtest_num,const char * test_name,const char * subtest_name,const char * subtest_desc)326 static bool should_run_subtest(struct test_selector *sel,
327 struct test_selector *subtest_sel,
328 int subtest_num,
329 const char *test_name,
330 const char *subtest_name,
331 const char *subtest_desc)
332 {
333 if (match_subtest_desc(&sel->blacklist, test_name,
334 subtest_name, subtest_desc))
335 return false;
336
337 if (match_subtest_desc(&sel->whitelist, test_name,
338 subtest_name, subtest_desc))
339 return true;
340
341 if (!sel->whitelist.cnt && !subtest_sel->num_set)
342 return true;
343
344 return subtest_num < subtest_sel->num_set_len && subtest_sel->num_set[subtest_num];
345 }
346
should_tmon(struct test_selector * sel,const char * name)347 static bool should_tmon(struct test_selector *sel, const char *name)
348 {
349 int i;
350
351 for (i = 0; i < sel->whitelist.cnt; i++) {
352 if (glob_match(name, sel->whitelist.tests[i].name) &&
353 !sel->whitelist.tests[i].subtest_cnt)
354 return true;
355 }
356
357 return false;
358 }
359
test_result(bool failed,bool skipped)360 static char *test_result(bool failed, bool skipped)
361 {
362 return failed ? "FAIL" : (skipped ? "SKIP" : "OK");
363 }
364
365 #define TEST_NUM_WIDTH 7
366
print_test_result(const struct prog_test_def * test,const struct test_state * test_state)367 static void print_test_result(const struct prog_test_def *test, const struct test_state *test_state)
368 {
369 int skipped_cnt = test_state->skip_cnt;
370 int subtests_cnt = test_state->subtest_num;
371
372 fprintf(env.stdout_saved, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
373 if (test_state->error_cnt)
374 fprintf(env.stdout_saved, "FAIL");
375 else if (!skipped_cnt)
376 fprintf(env.stdout_saved, "OK");
377 else if (skipped_cnt == subtests_cnt || !subtests_cnt)
378 fprintf(env.stdout_saved, "SKIP");
379 else
380 fprintf(env.stdout_saved, "OK (SKIP: %d/%d)", skipped_cnt, subtests_cnt);
381
382 fprintf(env.stdout_saved, "\n");
383 }
384
print_test_log(char * log_buf,size_t log_cnt)385 static void print_test_log(char *log_buf, size_t log_cnt)
386 {
387 log_buf[log_cnt] = '\0';
388 fprintf(env.stdout_saved, "%s", log_buf);
389 if (log_buf[log_cnt - 1] != '\n')
390 fprintf(env.stdout_saved, "\n");
391 }
392
print_subtest_name(int test_num,int subtest_num,const char * test_name,char * subtest_name,char * result)393 static void print_subtest_name(int test_num, int subtest_num,
394 const char *test_name, char *subtest_name,
395 char *result)
396 {
397 char test_num_str[32];
398
399 snprintf(test_num_str, sizeof(test_num_str), "%d/%d", test_num, subtest_num);
400
401 fprintf(env.stdout_saved, "#%-*s %s/%s",
402 TEST_NUM_WIDTH, test_num_str,
403 test_name, subtest_name);
404
405 if (result)
406 fprintf(env.stdout_saved, ":%s", result);
407
408 fprintf(env.stdout_saved, "\n");
409 }
410
jsonw_write_log_message(json_writer_t * w,char * log_buf,size_t log_cnt)411 static void jsonw_write_log_message(json_writer_t *w, char *log_buf, size_t log_cnt)
412 {
413 /* open_memstream (from stdio_hijack_init) ensures that log_bug is terminated by a
414 * null byte. Yet in parallel mode, log_buf will be NULL if there is no message.
415 */
416 if (log_cnt) {
417 jsonw_string_field(w, "message", log_buf);
418 } else {
419 jsonw_string_field(w, "message", "");
420 }
421 }
422
dump_test_log(const struct prog_test_def * test,const struct test_state * test_state,bool skip_ok_subtests,bool par_exec_result,json_writer_t * w)423 static void dump_test_log(const struct prog_test_def *test,
424 const struct test_state *test_state,
425 bool skip_ok_subtests,
426 bool par_exec_result,
427 json_writer_t *w)
428 {
429 bool test_failed = test_state->error_cnt > 0;
430 bool force_log = test_state->force_log;
431 bool print_test = verbose() || force_log || test_failed;
432 int i;
433 struct subtest_state *subtest_state;
434 bool subtest_failed;
435 bool subtest_filtered;
436 bool print_subtest;
437
438 /* we do not print anything in the worker thread */
439 if (env.worker_id != -1)
440 return;
441
442 /* there is nothing to print when verbose log is used and execution
443 * is not in parallel mode
444 */
445 if (verbose() && !par_exec_result)
446 return;
447
448 if (test_state->log_cnt && print_test)
449 print_test_log(test_state->log_buf, test_state->log_cnt);
450
451 if (w && print_test) {
452 jsonw_start_object(w);
453 jsonw_string_field(w, "name", test->test_name);
454 jsonw_uint_field(w, "number", test->test_num);
455 jsonw_write_log_message(w, test_state->log_buf, test_state->log_cnt);
456 jsonw_bool_field(w, "failed", test_failed);
457 jsonw_name(w, "subtests");
458 jsonw_start_array(w);
459 }
460
461 for (i = 0; i < test_state->subtest_num; i++) {
462 subtest_state = &test_state->subtest_states[i];
463 subtest_failed = subtest_state->error_cnt;
464 subtest_filtered = subtest_state->filtered;
465 print_subtest = verbose() || force_log || subtest_failed;
466
467 if ((skip_ok_subtests && !subtest_failed) || subtest_filtered)
468 continue;
469
470 if (subtest_state->log_cnt && print_subtest) {
471 print_test_log(subtest_state->log_buf,
472 subtest_state->log_cnt);
473 }
474
475 print_subtest_name(test->test_num, i + 1,
476 test->test_name, subtest_state->name,
477 test_result(subtest_state->error_cnt,
478 subtest_state->skipped));
479
480 if (w && print_subtest) {
481 jsonw_start_object(w);
482 jsonw_string_field(w, "name", subtest_state->name);
483 jsonw_uint_field(w, "number", i+1);
484 jsonw_write_log_message(w, subtest_state->log_buf, subtest_state->log_cnt);
485 jsonw_bool_field(w, "failed", subtest_failed);
486 jsonw_end_object(w);
487 }
488 }
489
490 if (w && print_test) {
491 jsonw_end_array(w);
492 jsonw_end_object(w);
493 }
494
495 print_test_result(test, test_state);
496 }
497
498 /* A bunch of tests set custom affinity per-thread and/or per-process. Reset
499 * it after each test/sub-test.
500 */
reset_affinity(void)501 static void reset_affinity(void)
502 {
503 cpu_set_t cpuset;
504 int i, err;
505
506 CPU_ZERO(&cpuset);
507 for (i = 0; i < env.nr_cpus; i++)
508 CPU_SET(i, &cpuset);
509
510 err = sched_setaffinity(0, sizeof(cpuset), &cpuset);
511 if (err < 0) {
512 fprintf(stderr, "Failed to reset process affinity: %d!\n", err);
513 exit(EXIT_ERR_SETUP_INFRA);
514 }
515 err = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
516 if (err < 0) {
517 fprintf(stderr, "Failed to reset thread affinity: %d!\n", err);
518 exit(EXIT_ERR_SETUP_INFRA);
519 }
520 }
521
save_netns(void)522 static void save_netns(void)
523 {
524 env.saved_netns_fd = open("/proc/self/ns/net", O_RDONLY);
525 if (env.saved_netns_fd == -1) {
526 perror("open(/proc/self/ns/net)");
527 exit(EXIT_ERR_SETUP_INFRA);
528 }
529 }
530
restore_netns(void)531 static void restore_netns(void)
532 {
533 if (setns(env.saved_netns_fd, CLONE_NEWNET) == -1) {
534 perror("setns(CLONE_NEWNS)");
535 exit(EXIT_ERR_SETUP_INFRA);
536 }
537 }
538
test__end_subtest(void)539 void test__end_subtest(void)
540 {
541 struct prog_test_def *test = env.test;
542 struct test_state *test_state = env.test_state;
543 struct subtest_state *subtest_state = env.subtest_state;
544
545 if (subtest_state->error_cnt) {
546 test_state->error_cnt++;
547 } else {
548 if (!subtest_state->skipped)
549 test_state->sub_succ_cnt++;
550 else
551 test_state->skip_cnt++;
552 }
553
554 if (verbose() && !env.workers)
555 print_subtest_name(test->test_num, test_state->subtest_num,
556 test->test_name, subtest_state->name,
557 test_result(subtest_state->error_cnt,
558 subtest_state->skipped));
559
560 stdio_restore();
561
562 env.subtest_state = NULL;
563 }
564
test__start_subtest_with_desc(const char * subtest_name,const char * subtest_desc)565 bool test__start_subtest_with_desc(const char *subtest_name, const char *subtest_desc)
566 {
567 struct prog_test_def *test = env.test;
568 struct test_state *state = env.test_state;
569 struct subtest_state *subtest_state;
570 const char *subtest_display_name;
571 size_t sub_state_size = sizeof(*subtest_state);
572
573 if (env.subtest_state)
574 test__end_subtest();
575
576 state->subtest_num++;
577 state->subtest_states =
578 realloc(state->subtest_states,
579 state->subtest_num * sub_state_size);
580 if (!state->subtest_states) {
581 fprintf(stderr, "Not enough memory to allocate subtest result\n");
582 return false;
583 }
584
585 subtest_state = &state->subtest_states[state->subtest_num - 1];
586
587 memset(subtest_state, 0, sub_state_size);
588
589 if (!subtest_name || !subtest_name[0]) {
590 fprintf(env.stderr_saved,
591 "Subtest #%d didn't provide sub-test name!\n",
592 state->subtest_num);
593 return false;
594 }
595
596 subtest_display_name = subtest_desc ? subtest_desc : subtest_name;
597
598 subtest_state->name = strdup(subtest_display_name);
599 if (!subtest_state->name) {
600 fprintf(env.stderr_saved,
601 "Subtest #%d: failed to copy subtest name!\n",
602 state->subtest_num);
603 return false;
604 }
605
606 if (!should_run_subtest(&env.test_selector,
607 &env.subtest_selector,
608 state->subtest_num,
609 test->test_name,
610 subtest_name,
611 subtest_desc)) {
612 subtest_state->filtered = true;
613 return false;
614 }
615
616 subtest_state->should_tmon = match_subtest_desc(&env.tmon_selector.whitelist,
617 test->test_name, subtest_name,
618 subtest_desc);
619
620 env.subtest_state = subtest_state;
621 stdio_hijack_init(&subtest_state->log_buf, &subtest_state->log_cnt);
622 watchdog_start();
623
624 return true;
625 }
626
test__start_subtest(const char * subtest_name)627 bool test__start_subtest(const char *subtest_name)
628 {
629 return test__start_subtest_with_desc(subtest_name, NULL);
630 }
631
test__force_log(void)632 void test__force_log(void)
633 {
634 env.test_state->force_log = true;
635 }
636
test__skip(void)637 void test__skip(void)
638 {
639 if (env.subtest_state)
640 env.subtest_state->skipped = true;
641 else
642 env.test_state->skip_cnt++;
643 }
644
test__fail(void)645 void test__fail(void)
646 {
647 if (env.subtest_state)
648 env.subtest_state->error_cnt++;
649 else
650 env.test_state->error_cnt++;
651 }
652
test__join_cgroup(const char * path)653 int test__join_cgroup(const char *path)
654 {
655 int fd;
656
657 if (!env.test->need_cgroup_cleanup) {
658 if (setup_cgroup_environment()) {
659 fprintf(stderr,
660 "#%d %s: Failed to setup cgroup environment\n",
661 env.test->test_num, env.test->test_name);
662 return -1;
663 }
664
665 env.test->need_cgroup_cleanup = true;
666 }
667
668 fd = create_and_get_cgroup(path);
669 if (fd < 0) {
670 fprintf(stderr,
671 "#%d %s: Failed to create cgroup '%s' (errno=%d)\n",
672 env.test->test_num, env.test->test_name, path, errno);
673 return fd;
674 }
675
676 if (join_cgroup(path)) {
677 fprintf(stderr,
678 "#%d %s: Failed to join cgroup '%s' (errno=%d)\n",
679 env.test->test_num, env.test->test_name, path, errno);
680 return -1;
681 }
682
683 return fd;
684 }
685
bpf_find_map(const char * test,struct bpf_object * obj,const char * name)686 int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
687 {
688 struct bpf_map *map;
689
690 map = bpf_object__find_map_by_name(obj, name);
691 if (!map) {
692 fprintf(stdout, "%s:FAIL:map '%s' not found\n", test, name);
693 test__fail();
694 return -1;
695 }
696 return bpf_map__fd(map);
697 }
698
compare_map_keys(int map1_fd,int map2_fd)699 int compare_map_keys(int map1_fd, int map2_fd)
700 {
701 __u32 key, next_key;
702 char val_buf[PERF_MAX_STACK_DEPTH *
703 sizeof(struct bpf_stack_build_id)];
704 int err;
705
706 err = bpf_map_get_next_key(map1_fd, NULL, &key);
707 if (err)
708 return err;
709 err = bpf_map_lookup_elem(map2_fd, &key, val_buf);
710 if (err)
711 return err;
712
713 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) {
714 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf);
715 if (err)
716 return err;
717
718 key = next_key;
719 }
720 if (errno != ENOENT)
721 return -1;
722
723 return 0;
724 }
725
compare_stack_ips(int smap_fd,int amap_fd,int stack_trace_len)726 int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len)
727 {
728 __u32 key, next_key, *cur_key_p, *next_key_p;
729 char *val_buf1, *val_buf2;
730 int i, err = 0;
731
732 val_buf1 = malloc(stack_trace_len);
733 val_buf2 = malloc(stack_trace_len);
734 cur_key_p = NULL;
735 next_key_p = &key;
736 while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) {
737 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1);
738 if (err)
739 goto out;
740 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2);
741 if (err)
742 goto out;
743 for (i = 0; i < stack_trace_len; i++) {
744 if (val_buf1[i] != val_buf2[i]) {
745 err = -1;
746 goto out;
747 }
748 }
749 key = *next_key_p;
750 cur_key_p = &key;
751 next_key_p = &next_key;
752 }
753 if (errno != ENOENT)
754 err = -1;
755
756 out:
757 free(val_buf1);
758 free(val_buf2);
759 return err;
760 }
761
762 struct netns_obj {
763 char *nsname;
764 struct tmonitor_ctx *tmon;
765 struct nstoken *nstoken;
766 };
767
768 /* Create a new network namespace with the given name.
769 *
770 * Create a new network namespace and set the network namespace of the
771 * current process to the new network namespace if the argument "open" is
772 * true. This function should be paired with netns_free() to release the
773 * resource and delete the network namespace.
774 *
775 * It also implements the functionality of the option "-m" by starting
776 * traffic monitor on the background to capture the packets in this network
777 * namespace if the current test or subtest matching the pattern.
778 *
779 * nsname: the name of the network namespace to create.
780 * open: open the network namespace if true.
781 *
782 * Return: the network namespace object on success, NULL on failure.
783 */
netns_new(const char * nsname,bool open)784 struct netns_obj *netns_new(const char *nsname, bool open)
785 {
786 struct netns_obj *netns_obj = malloc(sizeof(*netns_obj));
787 const char *test_name, *subtest_name;
788 int r;
789
790 if (!netns_obj)
791 return NULL;
792 memset(netns_obj, 0, sizeof(*netns_obj));
793
794 netns_obj->nsname = strdup(nsname);
795 if (!netns_obj->nsname)
796 goto fail;
797
798 /* Create the network namespace */
799 r = make_netns(nsname);
800 if (r)
801 goto fail;
802
803 /* Start traffic monitor */
804 if (env.test->should_tmon ||
805 (env.subtest_state && env.subtest_state->should_tmon)) {
806 test_name = env.test->test_name;
807 subtest_name = env.subtest_state ? env.subtest_state->name : NULL;
808 netns_obj->tmon = traffic_monitor_start(nsname, test_name, subtest_name);
809 if (!netns_obj->tmon) {
810 fprintf(stderr, "Failed to start traffic monitor for %s\n", nsname);
811 goto fail;
812 }
813 } else {
814 netns_obj->tmon = NULL;
815 }
816
817 if (open) {
818 netns_obj->nstoken = open_netns(nsname);
819 if (!netns_obj->nstoken)
820 goto fail;
821 }
822
823 return netns_obj;
824 fail:
825 traffic_monitor_stop(netns_obj->tmon);
826 remove_netns(nsname);
827 free(netns_obj->nsname);
828 free(netns_obj);
829 return NULL;
830 }
831
832 /* Delete the network namespace.
833 *
834 * This function should be paired with netns_new() to delete the namespace
835 * created by netns_new().
836 */
netns_free(struct netns_obj * netns_obj)837 void netns_free(struct netns_obj *netns_obj)
838 {
839 if (!netns_obj)
840 return;
841 traffic_monitor_stop(netns_obj->tmon);
842 close_netns(netns_obj->nstoken);
843 remove_netns(netns_obj->nsname);
844 free(netns_obj->nsname);
845 free(netns_obj);
846 }
847
848 /* extern declarations for test funcs */
849 #define DEFINE_TEST(name) \
850 extern void test_##name(void) __weak; \
851 extern void serial_test_##name(void) __weak;
852 #include <prog_tests/tests.h>
853 #undef DEFINE_TEST
854
855 static struct prog_test_def prog_test_defs[] = {
856 #define DEFINE_TEST(name) { \
857 .test_name = #name, \
858 .run_test = &test_##name, \
859 .run_serial_test = &serial_test_##name, \
860 },
861 #include <prog_tests/tests.h>
862 #undef DEFINE_TEST
863 };
864
865 static const int prog_test_cnt = ARRAY_SIZE(prog_test_defs);
866
867 static struct test_state test_states[ARRAY_SIZE(prog_test_defs)];
868
869 const char *argp_program_version = "test_progs 0.1";
870 const char *argp_program_bug_address = "<bpf@vger.kernel.org>";
871 static const char argp_program_doc[] =
872 "BPF selftests test runner\v"
873 "Options accepting the NAMES parameter take either a comma-separated list\n"
874 "of test names, or a filename prefixed with @. The file contains one name\n"
875 "(or wildcard pattern) per line, and comments beginning with # are ignored.\n"
876 "\n"
877 "These options can be passed repeatedly to read multiple files.\n";
878
879 enum ARG_KEYS {
880 ARG_TEST_NUM = 'n',
881 ARG_TEST_NAME = 't',
882 ARG_TEST_NAME_BLACKLIST = 'b',
883 ARG_VERIFIER_STATS = 's',
884 ARG_VERBOSE = 'v',
885 ARG_GET_TEST_CNT = 'c',
886 ARG_LIST_TEST_NAMES = 'l',
887 ARG_TEST_NAME_GLOB_ALLOWLIST = 'a',
888 ARG_TEST_NAME_GLOB_DENYLIST = 'd',
889 ARG_NUM_WORKERS = 'j',
890 ARG_DEBUG = -1,
891 ARG_JSON_SUMMARY = 'J',
892 ARG_TRAFFIC_MONITOR = 'm',
893 ARG_WATCHDOG_TIMEOUT = 'w',
894 };
895
896 static const struct argp_option opts[] = {
897 { "num", ARG_TEST_NUM, "NUM", 0,
898 "Run test number NUM only " },
899 { "name", ARG_TEST_NAME, "NAMES", 0,
900 "Run tests with names containing any string from NAMES list" },
901 { "name-blacklist", ARG_TEST_NAME_BLACKLIST, "NAMES", 0,
902 "Don't run tests with names containing any string from NAMES list" },
903 { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0,
904 "Output verifier statistics", },
905 { "verbose", ARG_VERBOSE, "LEVEL", OPTION_ARG_OPTIONAL,
906 "Verbose output (use -vv or -vvv for progressively verbose output)" },
907 { "count", ARG_GET_TEST_CNT, NULL, 0,
908 "Get number of selected top-level tests " },
909 { "list", ARG_LIST_TEST_NAMES, NULL, 0,
910 "List test names that would run (without running them) " },
911 { "allow", ARG_TEST_NAME_GLOB_ALLOWLIST, "NAMES", 0,
912 "Run tests with name matching the pattern (supports '*' wildcard)." },
913 { "deny", ARG_TEST_NAME_GLOB_DENYLIST, "NAMES", 0,
914 "Don't run tests with name matching the pattern (supports '*' wildcard)." },
915 { "workers", ARG_NUM_WORKERS, "WORKERS", OPTION_ARG_OPTIONAL,
916 "Number of workers to run in parallel, default to number of cpus." },
917 { "debug", ARG_DEBUG, NULL, 0,
918 "print extra debug information for test_progs." },
919 { "json-summary", ARG_JSON_SUMMARY, "FILE", 0, "Write report in json format to this file."},
920 #ifdef TRAFFIC_MONITOR
921 { "traffic-monitor", ARG_TRAFFIC_MONITOR, "NAMES", 0,
922 "Monitor network traffic of tests with name matching the pattern (supports '*' wildcard)." },
923 #endif
924 { "watchdog-timeout", ARG_WATCHDOG_TIMEOUT, "SECONDS", 0,
925 "Kill the process if tests are not making progress for specified number of seconds." },
926 {},
927 };
928
929 static FILE *libbpf_capture_stream;
930
931 static struct {
932 char *buf;
933 size_t buf_sz;
934 } libbpf_output_capture;
935
936 /* Creates a global memstream capturing INFO and WARN level output
937 * passed to libbpf_print_fn.
938 * Returns 0 on success, negative value on failure.
939 * On failure the description is printed using PRINT_FAIL and
940 * current test case is marked as fail.
941 */
start_libbpf_log_capture(void)942 int start_libbpf_log_capture(void)
943 {
944 if (libbpf_capture_stream) {
945 PRINT_FAIL("%s: libbpf_capture_stream != NULL\n", __func__);
946 return -EINVAL;
947 }
948
949 libbpf_capture_stream = open_memstream(&libbpf_output_capture.buf,
950 &libbpf_output_capture.buf_sz);
951 if (!libbpf_capture_stream) {
952 PRINT_FAIL("%s: open_memstream failed errno=%d\n", __func__, errno);
953 return -EINVAL;
954 }
955
956 return 0;
957 }
958
959 /* Destroys global memstream created by start_libbpf_log_capture().
960 * Returns a pointer to captured data which has to be freed.
961 * Returned buffer is null terminated.
962 */
stop_libbpf_log_capture(void)963 char *stop_libbpf_log_capture(void)
964 {
965 char *buf;
966
967 if (!libbpf_capture_stream)
968 return NULL;
969
970 fputc(0, libbpf_capture_stream);
971 fclose(libbpf_capture_stream);
972 libbpf_capture_stream = NULL;
973 /* get 'buf' after fclose(), see open_memstream() documentation */
974 buf = libbpf_output_capture.buf;
975 memset(&libbpf_output_capture, 0, sizeof(libbpf_output_capture));
976 return buf;
977 }
978
libbpf_print_fn(enum libbpf_print_level level,const char * format,va_list args)979 static int libbpf_print_fn(enum libbpf_print_level level,
980 const char *format, va_list args)
981 {
982 if (libbpf_capture_stream && level != LIBBPF_DEBUG) {
983 va_list args2;
984
985 va_copy(args2, args);
986 vfprintf(libbpf_capture_stream, format, args2);
987 va_end(args2);
988 }
989
990 if (env.verbosity < VERBOSE_VERY && level == LIBBPF_DEBUG)
991 return 0;
992
993 vfprintf(stdout, format, args);
994 return 0;
995 }
996
free_test_filter_set(const struct test_filter_set * set)997 static void free_test_filter_set(const struct test_filter_set *set)
998 {
999 int i, j;
1000
1001 if (!set)
1002 return;
1003
1004 for (i = 0; i < set->cnt; i++) {
1005 free((void *)set->tests[i].name);
1006 for (j = 0; j < set->tests[i].subtest_cnt; j++)
1007 free((void *)set->tests[i].subtests[j]);
1008
1009 free((void *)set->tests[i].subtests);
1010 }
1011
1012 free((void *)set->tests);
1013 }
1014
free_test_selector(struct test_selector * test_selector)1015 static void free_test_selector(struct test_selector *test_selector)
1016 {
1017 free_test_filter_set(&test_selector->blacklist);
1018 free_test_filter_set(&test_selector->whitelist);
1019 free(test_selector->num_set);
1020 }
1021
1022 extern int extra_prog_load_log_flags;
1023
parse_arg(int key,char * arg,struct argp_state * state)1024 static error_t parse_arg(int key, char *arg, struct argp_state *state)
1025 {
1026 struct test_env *env = state->input;
1027 int err = 0;
1028
1029 switch (key) {
1030 case ARG_TEST_NUM: {
1031 char *subtest_str = strchr(arg, '/');
1032
1033 if (subtest_str) {
1034 *subtest_str = '\0';
1035 if (parse_num_list(subtest_str + 1,
1036 &env->subtest_selector.num_set,
1037 &env->subtest_selector.num_set_len)) {
1038 fprintf(stderr,
1039 "Failed to parse subtest numbers.\n");
1040 return -EINVAL;
1041 }
1042 }
1043 if (parse_num_list(arg, &env->test_selector.num_set,
1044 &env->test_selector.num_set_len)) {
1045 fprintf(stderr, "Failed to parse test numbers.\n");
1046 return -EINVAL;
1047 }
1048 break;
1049 }
1050 case ARG_TEST_NAME_GLOB_ALLOWLIST:
1051 case ARG_TEST_NAME: {
1052 if (arg[0] == '@')
1053 err = parse_test_list_file(arg + 1,
1054 &env->test_selector.whitelist,
1055 key == ARG_TEST_NAME_GLOB_ALLOWLIST);
1056 else
1057 err = parse_test_list(arg,
1058 &env->test_selector.whitelist,
1059 key == ARG_TEST_NAME_GLOB_ALLOWLIST);
1060
1061 break;
1062 }
1063 case ARG_TEST_NAME_GLOB_DENYLIST:
1064 case ARG_TEST_NAME_BLACKLIST: {
1065 if (arg[0] == '@')
1066 err = parse_test_list_file(arg + 1,
1067 &env->test_selector.blacklist,
1068 key == ARG_TEST_NAME_GLOB_DENYLIST);
1069 else
1070 err = parse_test_list(arg,
1071 &env->test_selector.blacklist,
1072 key == ARG_TEST_NAME_GLOB_DENYLIST);
1073
1074 break;
1075 }
1076 case ARG_VERIFIER_STATS:
1077 env->verifier_stats = true;
1078 break;
1079 case ARG_VERBOSE:
1080 env->verbosity = VERBOSE_NORMAL;
1081 if (arg) {
1082 if (strcmp(arg, "v") == 0) {
1083 env->verbosity = VERBOSE_VERY;
1084 extra_prog_load_log_flags = 1;
1085 } else if (strcmp(arg, "vv") == 0) {
1086 env->verbosity = VERBOSE_SUPER;
1087 extra_prog_load_log_flags = 2;
1088 } else {
1089 fprintf(stderr,
1090 "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n",
1091 arg);
1092 return -EINVAL;
1093 }
1094 }
1095 env_verbosity = env->verbosity;
1096
1097 if (verbose()) {
1098 if (setenv("SELFTESTS_VERBOSE", "1", 1) == -1) {
1099 fprintf(stderr,
1100 "Unable to setenv SELFTESTS_VERBOSE=1 (errno=%d)",
1101 errno);
1102 return -EINVAL;
1103 }
1104 }
1105
1106 break;
1107 case ARG_GET_TEST_CNT:
1108 env->get_test_cnt = true;
1109 break;
1110 case ARG_LIST_TEST_NAMES:
1111 env->list_test_names = true;
1112 break;
1113 case ARG_NUM_WORKERS:
1114 if (arg) {
1115 env->workers = atoi(arg);
1116 if (!env->workers) {
1117 fprintf(stderr, "Invalid number of worker: %s.", arg);
1118 return -EINVAL;
1119 }
1120 } else {
1121 env->workers = get_nprocs();
1122 }
1123 break;
1124 case ARG_DEBUG:
1125 env->debug = true;
1126 break;
1127 case ARG_JSON_SUMMARY:
1128 env->json = fopen(arg, "w");
1129 if (env->json == NULL) {
1130 perror("Failed to open json summary file");
1131 return -errno;
1132 }
1133 break;
1134 case ARGP_KEY_ARG:
1135 argp_usage(state);
1136 break;
1137 case ARGP_KEY_END:
1138 break;
1139 #ifdef TRAFFIC_MONITOR
1140 case ARG_TRAFFIC_MONITOR:
1141 if (arg[0] == '@')
1142 err = parse_test_list_file(arg + 1,
1143 &env->tmon_selector.whitelist,
1144 true);
1145 else
1146 err = parse_test_list(arg,
1147 &env->tmon_selector.whitelist,
1148 true);
1149 break;
1150 #endif
1151 case ARG_WATCHDOG_TIMEOUT:
1152 env->secs_till_kill = atoi(arg);
1153 if (env->secs_till_kill < 0) {
1154 fprintf(stderr, "Invalid watchdog timeout: %s.\n", arg);
1155 return -EINVAL;
1156 }
1157 if (env->secs_till_kill < env->secs_till_notify) {
1158 env->secs_till_notify = 0;
1159 }
1160 break;
1161 default:
1162 return ARGP_ERR_UNKNOWN;
1163 }
1164 return err;
1165 }
1166
1167 /*
1168 * Determine if test_progs is running as a "flavored" test runner and switch
1169 * into corresponding sub-directory to load correct BPF objects.
1170 *
1171 * This is done by looking at executable name. If it contains "-flavor"
1172 * suffix, then we are running as a flavored test runner.
1173 */
cd_flavor_subdir(const char * exec_name)1174 int cd_flavor_subdir(const char *exec_name)
1175 {
1176 /* General form of argv[0] passed here is:
1177 * some/path/to/test_progs[-flavor], where -flavor part is optional.
1178 * First cut out "test_progs[-flavor]" part, then extract "flavor"
1179 * part, if it's there.
1180 */
1181 const char *flavor = strrchr(exec_name, '/');
1182
1183 if (!flavor)
1184 flavor = exec_name;
1185 else
1186 flavor++;
1187
1188 flavor = strrchr(flavor, '-');
1189 if (!flavor)
1190 return 0;
1191 flavor++;
1192 if (verbose())
1193 fprintf(stdout, "Switching to flavor '%s' subdirectory...\n", flavor);
1194
1195 return chdir(flavor);
1196 }
1197
trigger_module_test_read(int read_sz)1198 int trigger_module_test_read(int read_sz)
1199 {
1200 int fd, err;
1201
1202 fd = open(BPF_TESTMOD_TEST_FILE, O_RDONLY);
1203 err = -errno;
1204 if (!ASSERT_GE(fd, 0, "testmod_file_open"))
1205 return err;
1206
1207 read(fd, NULL, read_sz);
1208 close(fd);
1209
1210 return 0;
1211 }
1212
trigger_module_test_write(int write_sz)1213 int trigger_module_test_write(int write_sz)
1214 {
1215 int fd, err;
1216 char *buf = malloc(write_sz);
1217
1218 if (!buf)
1219 return -ENOMEM;
1220
1221 memset(buf, 'a', write_sz);
1222 buf[write_sz-1] = '\0';
1223
1224 fd = open(BPF_TESTMOD_TEST_FILE, O_WRONLY);
1225 err = -errno;
1226 if (!ASSERT_GE(fd, 0, "testmod_file_open")) {
1227 free(buf);
1228 return err;
1229 }
1230
1231 write(fd, buf, write_sz);
1232 close(fd);
1233 free(buf);
1234 return 0;
1235 }
1236
write_sysctl(const char * sysctl,const char * value)1237 int write_sysctl(const char *sysctl, const char *value)
1238 {
1239 int fd, err, len;
1240
1241 fd = open(sysctl, O_WRONLY);
1242 if (!ASSERT_NEQ(fd, -1, "open sysctl"))
1243 return -1;
1244
1245 len = strlen(value);
1246 err = write(fd, value, len);
1247 close(fd);
1248 if (!ASSERT_EQ(err, len, "write sysctl"))
1249 return -1;
1250
1251 return 0;
1252 }
1253
get_bpf_max_tramp_links_from(struct btf * btf)1254 int get_bpf_max_tramp_links_from(struct btf *btf)
1255 {
1256 const struct btf_enum *e;
1257 const struct btf_type *t;
1258 __u32 i, type_cnt;
1259 const char *name;
1260 __u16 j, vlen;
1261
1262 for (i = 1, type_cnt = btf__type_cnt(btf); i < type_cnt; i++) {
1263 t = btf__type_by_id(btf, i);
1264 if (!t || !btf_is_enum(t) || t->name_off)
1265 continue;
1266 e = btf_enum(t);
1267 for (j = 0, vlen = btf_vlen(t); j < vlen; j++, e++) {
1268 name = btf__str_by_offset(btf, e->name_off);
1269 if (name && !strcmp(name, "BPF_MAX_TRAMP_LINKS"))
1270 return e->val;
1271 }
1272 }
1273
1274 return -1;
1275 }
1276
get_bpf_max_tramp_links(void)1277 int get_bpf_max_tramp_links(void)
1278 {
1279 struct btf *vmlinux_btf;
1280 int ret;
1281
1282 vmlinux_btf = btf__load_vmlinux_btf();
1283 if (!ASSERT_OK_PTR(vmlinux_btf, "vmlinux btf"))
1284 return -1;
1285 ret = get_bpf_max_tramp_links_from(vmlinux_btf);
1286 btf__free(vmlinux_btf);
1287
1288 return ret;
1289 }
1290
dump_crash_log(void)1291 static void dump_crash_log(void)
1292 {
1293 fflush(stdout);
1294 stdout = env.stdout_saved;
1295 stderr = env.stderr_saved;
1296
1297 if (env.test) {
1298 env.test_state->error_cnt++;
1299 dump_test_log(env.test, env.test_state, true, false, NULL);
1300 }
1301 }
1302
1303 #define MAX_BACKTRACE_SZ 128
1304
crash_handler(int signum)1305 void crash_handler(int signum)
1306 {
1307 void *bt[MAX_BACKTRACE_SZ];
1308 size_t sz;
1309
1310 sz = backtrace(bt, ARRAY_SIZE(bt));
1311
1312 dump_crash_log();
1313
1314 if (env.worker_id != -1)
1315 fprintf(stderr, "[%d]: ", env.worker_id);
1316 fprintf(stderr, "Caught signal #%d!\nStack trace:\n", signum);
1317 backtrace_symbols_fd(bt, sz, STDERR_FILENO);
1318 }
1319
1320 #ifdef __SANITIZE_ADDRESS__
__asan_on_error(void)1321 void __asan_on_error(void)
1322 {
1323 dump_crash_log();
1324 }
1325 #endif
1326
hexdump(const char * prefix,const void * buf,size_t len)1327 void hexdump(const char *prefix, const void *buf, size_t len)
1328 {
1329 for (int i = 0; i < len; i++) {
1330 if (!(i % 16)) {
1331 if (i)
1332 fprintf(stdout, "\n");
1333 fprintf(stdout, "%s", prefix);
1334 }
1335 if (i && !(i % 8) && (i % 16))
1336 fprintf(stdout, "\t");
1337 fprintf(stdout, "%02X ", ((uint8_t *)(buf))[i]);
1338 }
1339 fprintf(stdout, "\n");
1340 }
1341
sigint_handler(int signum)1342 static void sigint_handler(int signum)
1343 {
1344 int i;
1345
1346 for (i = 0; i < env.workers; i++)
1347 if (env.worker_socks[i] > 0)
1348 close(env.worker_socks[i]);
1349 }
1350
1351 static int current_test_idx;
1352 static pthread_mutex_t current_test_lock;
1353 static pthread_mutex_t stdout_output_lock;
1354
str_msg(const struct msg * msg,char * buf)1355 static inline const char *str_msg(const struct msg *msg, char *buf)
1356 {
1357 switch (msg->type) {
1358 case MSG_DO_TEST:
1359 sprintf(buf, "MSG_DO_TEST %d", msg->do_test.num);
1360 break;
1361 case MSG_TEST_DONE:
1362 sprintf(buf, "MSG_TEST_DONE %d (log: %d)",
1363 msg->test_done.num,
1364 msg->test_done.have_log);
1365 break;
1366 case MSG_SUBTEST_DONE:
1367 sprintf(buf, "MSG_SUBTEST_DONE %d (log: %d)",
1368 msg->subtest_done.num,
1369 msg->subtest_done.have_log);
1370 break;
1371 case MSG_TEST_LOG:
1372 sprintf(buf, "MSG_TEST_LOG (cnt: %zu, last: %d)",
1373 strlen(msg->test_log.log_buf),
1374 msg->test_log.is_last);
1375 break;
1376 case MSG_EXIT:
1377 sprintf(buf, "MSG_EXIT");
1378 break;
1379 default:
1380 sprintf(buf, "UNKNOWN");
1381 break;
1382 }
1383
1384 return buf;
1385 }
1386
send_message(int sock,const struct msg * msg)1387 static int send_message(int sock, const struct msg *msg)
1388 {
1389 char buf[256];
1390
1391 if (env.debug)
1392 fprintf(stderr, "Sending msg: %s\n", str_msg(msg, buf));
1393 return send(sock, msg, sizeof(*msg), 0);
1394 }
1395
recv_message(int sock,struct msg * msg)1396 static int recv_message(int sock, struct msg *msg)
1397 {
1398 int ret;
1399 char buf[256];
1400
1401 memset(msg, 0, sizeof(*msg));
1402 ret = recv(sock, msg, sizeof(*msg), 0);
1403 if (ret >= 0) {
1404 if (env.debug)
1405 fprintf(stderr, "Received msg: %s\n", str_msg(msg, buf));
1406 }
1407 return ret;
1408 }
1409
ns_is_needed(const char * test_name)1410 static bool ns_is_needed(const char *test_name)
1411 {
1412 if (strlen(test_name) < 3)
1413 return false;
1414
1415 return !strncmp(test_name, "ns_", 3);
1416 }
1417
run_one_test(int test_num)1418 static void run_one_test(int test_num)
1419 {
1420 struct prog_test_def *test = &prog_test_defs[test_num];
1421 struct test_state *state = &test_states[test_num];
1422 struct netns_obj *ns = NULL;
1423
1424 env.test = test;
1425 env.test_state = state;
1426
1427 stdio_hijack(&state->log_buf, &state->log_cnt);
1428
1429 watchdog_start();
1430 if (ns_is_needed(test->test_name))
1431 ns = netns_new(test->test_name, true);
1432 if (test->run_test)
1433 test->run_test();
1434 else if (test->run_serial_test)
1435 test->run_serial_test();
1436 netns_free(ns);
1437 watchdog_stop();
1438
1439 /* ensure last sub-test is finalized properly */
1440 if (env.subtest_state)
1441 test__end_subtest();
1442
1443 state->tested = true;
1444
1445 stdio_restore();
1446
1447 if (verbose() && env.worker_id == -1)
1448 print_test_result(test, state);
1449
1450 reset_affinity();
1451 restore_netns();
1452 if (test->need_cgroup_cleanup)
1453 cleanup_cgroup_environment();
1454
1455 free(stop_libbpf_log_capture());
1456
1457 dump_test_log(test, state, false, false, NULL);
1458 }
1459
1460 struct dispatch_data {
1461 int worker_id;
1462 int sock_fd;
1463 };
1464
read_prog_test_msg(int sock_fd,struct msg * msg,enum msg_type type)1465 static int read_prog_test_msg(int sock_fd, struct msg *msg, enum msg_type type)
1466 {
1467 if (recv_message(sock_fd, msg) < 0)
1468 return 1;
1469
1470 if (msg->type != type) {
1471 printf("%s: unexpected message type %d. expected %d\n", __func__, msg->type, type);
1472 return 1;
1473 }
1474
1475 return 0;
1476 }
1477
dispatch_thread_read_log(int sock_fd,char ** log_buf,size_t * log_cnt)1478 static int dispatch_thread_read_log(int sock_fd, char **log_buf, size_t *log_cnt)
1479 {
1480 FILE *log_fp = NULL;
1481 int result = 0;
1482
1483 log_fp = open_memstream(log_buf, log_cnt);
1484 if (!log_fp)
1485 return 1;
1486
1487 while (true) {
1488 struct msg msg;
1489
1490 if (read_prog_test_msg(sock_fd, &msg, MSG_TEST_LOG)) {
1491 result = 1;
1492 goto out;
1493 }
1494
1495 fprintf(log_fp, "%s", msg.test_log.log_buf);
1496 if (msg.test_log.is_last)
1497 break;
1498 }
1499
1500 out:
1501 fclose(log_fp);
1502 log_fp = NULL;
1503 return result;
1504 }
1505
dispatch_thread_send_subtests(int sock_fd,struct test_state * state)1506 static int dispatch_thread_send_subtests(int sock_fd, struct test_state *state)
1507 {
1508 struct msg msg;
1509 struct subtest_state *subtest_state;
1510 int subtest_num = state->subtest_num;
1511
1512 state->subtest_states = malloc(subtest_num * sizeof(*subtest_state));
1513
1514 for (int i = 0; i < subtest_num; i++) {
1515 subtest_state = &state->subtest_states[i];
1516
1517 memset(subtest_state, 0, sizeof(*subtest_state));
1518
1519 if (read_prog_test_msg(sock_fd, &msg, MSG_SUBTEST_DONE))
1520 return 1;
1521
1522 subtest_state->name = strdup(msg.subtest_done.name);
1523 subtest_state->error_cnt = msg.subtest_done.error_cnt;
1524 subtest_state->skipped = msg.subtest_done.skipped;
1525 subtest_state->filtered = msg.subtest_done.filtered;
1526
1527 /* collect all logs */
1528 if (msg.subtest_done.have_log)
1529 if (dispatch_thread_read_log(sock_fd,
1530 &subtest_state->log_buf,
1531 &subtest_state->log_cnt))
1532 return 1;
1533 }
1534
1535 return 0;
1536 }
1537
dispatch_thread(void * ctx)1538 static void *dispatch_thread(void *ctx)
1539 {
1540 struct dispatch_data *data = ctx;
1541 int sock_fd;
1542
1543 sock_fd = data->sock_fd;
1544
1545 while (true) {
1546 int test_to_run = -1;
1547 struct prog_test_def *test;
1548 struct test_state *state;
1549
1550 /* grab a test */
1551 {
1552 pthread_mutex_lock(¤t_test_lock);
1553
1554 if (current_test_idx >= prog_test_cnt) {
1555 pthread_mutex_unlock(¤t_test_lock);
1556 goto done;
1557 }
1558
1559 test = &prog_test_defs[current_test_idx];
1560 test_to_run = current_test_idx;
1561 current_test_idx++;
1562
1563 pthread_mutex_unlock(¤t_test_lock);
1564 }
1565
1566 if (!test->should_run || test->run_serial_test)
1567 continue;
1568
1569 /* run test through worker */
1570 {
1571 struct msg msg_do_test;
1572
1573 memset(&msg_do_test, 0, sizeof(msg_do_test));
1574 msg_do_test.type = MSG_DO_TEST;
1575 msg_do_test.do_test.num = test_to_run;
1576 if (send_message(sock_fd, &msg_do_test) < 0) {
1577 perror("Fail to send command");
1578 goto done;
1579 }
1580 env.worker_current_test[data->worker_id] = test_to_run;
1581 }
1582
1583 /* wait for test done */
1584 do {
1585 struct msg msg;
1586
1587 if (read_prog_test_msg(sock_fd, &msg, MSG_TEST_DONE))
1588 goto error;
1589 if (test_to_run != msg.test_done.num)
1590 goto error;
1591
1592 state = &test_states[test_to_run];
1593 state->tested = true;
1594 state->error_cnt = msg.test_done.error_cnt;
1595 state->skip_cnt = msg.test_done.skip_cnt;
1596 state->sub_succ_cnt = msg.test_done.sub_succ_cnt;
1597 state->subtest_num = msg.test_done.subtest_num;
1598
1599 /* collect all logs */
1600 if (msg.test_done.have_log) {
1601 if (dispatch_thread_read_log(sock_fd,
1602 &state->log_buf,
1603 &state->log_cnt))
1604 goto error;
1605 }
1606
1607 /* collect all subtests and subtest logs */
1608 if (!state->subtest_num)
1609 break;
1610
1611 if (dispatch_thread_send_subtests(sock_fd, state))
1612 goto error;
1613 } while (false);
1614
1615 pthread_mutex_lock(&stdout_output_lock);
1616 dump_test_log(test, state, false, true, NULL);
1617 pthread_mutex_unlock(&stdout_output_lock);
1618 } /* while (true) */
1619 error:
1620 if (env.debug)
1621 fprintf(stderr, "[%d]: Protocol/IO error: %s.\n", data->worker_id, strerror(errno));
1622
1623 done:
1624 {
1625 struct msg msg_exit;
1626
1627 msg_exit.type = MSG_EXIT;
1628 if (send_message(sock_fd, &msg_exit) < 0) {
1629 if (env.debug)
1630 fprintf(stderr, "[%d]: send_message msg_exit: %s.\n",
1631 data->worker_id, strerror(errno));
1632 }
1633 }
1634 return NULL;
1635 }
1636
calculate_summary_and_print_errors(struct test_env * env)1637 static void calculate_summary_and_print_errors(struct test_env *env)
1638 {
1639 int i;
1640 int succ_cnt = 0, fail_cnt = 0, sub_succ_cnt = 0, skip_cnt = 0;
1641 json_writer_t *w = NULL;
1642
1643 for (i = 0; i < prog_test_cnt; i++) {
1644 struct test_state *state = &test_states[i];
1645
1646 if (!state->tested)
1647 continue;
1648
1649 sub_succ_cnt += state->sub_succ_cnt;
1650 skip_cnt += state->skip_cnt;
1651
1652 if (state->error_cnt)
1653 fail_cnt++;
1654 else
1655 succ_cnt++;
1656 }
1657
1658 if (env->json) {
1659 w = jsonw_new(env->json);
1660 if (!w)
1661 fprintf(env->stderr_saved, "Failed to create new JSON stream.");
1662 }
1663
1664 if (w) {
1665 jsonw_start_object(w);
1666 jsonw_uint_field(w, "success", succ_cnt);
1667 jsonw_uint_field(w, "success_subtest", sub_succ_cnt);
1668 jsonw_uint_field(w, "skipped", skip_cnt);
1669 jsonw_uint_field(w, "failed", fail_cnt);
1670 jsonw_name(w, "results");
1671 jsonw_start_array(w);
1672 }
1673
1674 /*
1675 * We only print error logs summary when there are failed tests and
1676 * verbose mode is not enabled. Otherwise, results may be inconsistent.
1677 *
1678 */
1679 if (!verbose() && fail_cnt) {
1680 printf("\nAll error logs:\n");
1681
1682 /* print error logs again */
1683 for (i = 0; i < prog_test_cnt; i++) {
1684 struct prog_test_def *test = &prog_test_defs[i];
1685 struct test_state *state = &test_states[i];
1686
1687 if (!state->tested || !state->error_cnt)
1688 continue;
1689
1690 dump_test_log(test, state, true, true, w);
1691 }
1692 }
1693
1694 if (w) {
1695 jsonw_end_array(w);
1696 jsonw_end_object(w);
1697 jsonw_destroy(&w);
1698 }
1699
1700 if (env->json)
1701 fclose(env->json);
1702
1703 printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
1704 succ_cnt, sub_succ_cnt, skip_cnt, fail_cnt);
1705
1706 env->succ_cnt = succ_cnt;
1707 env->sub_succ_cnt = sub_succ_cnt;
1708 env->fail_cnt = fail_cnt;
1709 env->skip_cnt = skip_cnt;
1710 }
1711
server_main(void)1712 static void server_main(void)
1713 {
1714 pthread_t *dispatcher_threads;
1715 struct dispatch_data *data;
1716 struct sigaction sigact_int = {
1717 .sa_handler = sigint_handler,
1718 .sa_flags = SA_RESETHAND,
1719 };
1720 int i;
1721
1722 sigaction(SIGINT, &sigact_int, NULL);
1723
1724 dispatcher_threads = calloc(sizeof(pthread_t), env.workers);
1725 data = calloc(sizeof(struct dispatch_data), env.workers);
1726
1727 env.worker_current_test = calloc(sizeof(int), env.workers);
1728 for (i = 0; i < env.workers; i++) {
1729 int rc;
1730
1731 data[i].worker_id = i;
1732 data[i].sock_fd = env.worker_socks[i];
1733 rc = pthread_create(&dispatcher_threads[i], NULL, dispatch_thread, &data[i]);
1734 if (rc < 0) {
1735 perror("Failed to launch dispatcher thread");
1736 exit(EXIT_ERR_SETUP_INFRA);
1737 }
1738 }
1739
1740 /* wait for all dispatcher to finish */
1741 for (i = 0; i < env.workers; i++) {
1742 while (true) {
1743 int ret = pthread_tryjoin_np(dispatcher_threads[i], NULL);
1744
1745 if (!ret) {
1746 break;
1747 } else if (ret == EBUSY) {
1748 if (env.debug)
1749 fprintf(stderr, "Still waiting for thread %d (test %d).\n",
1750 i, env.worker_current_test[i] + 1);
1751 usleep(1000 * 1000);
1752 continue;
1753 } else {
1754 fprintf(stderr, "Unexpected error joining dispatcher thread: %d", ret);
1755 break;
1756 }
1757 }
1758 }
1759 free(dispatcher_threads);
1760 free(env.worker_current_test);
1761 free(data);
1762
1763 /* run serial tests */
1764 save_netns();
1765
1766 for (int i = 0; i < prog_test_cnt; i++) {
1767 struct prog_test_def *test = &prog_test_defs[i];
1768
1769 if (!test->should_run || !test->run_serial_test)
1770 continue;
1771
1772 run_one_test(i);
1773 }
1774
1775 /* generate summary */
1776 fflush(stderr);
1777 fflush(stdout);
1778
1779 calculate_summary_and_print_errors(&env);
1780
1781 /* reap all workers */
1782 for (i = 0; i < env.workers; i++) {
1783 int wstatus, pid;
1784
1785 pid = waitpid(env.worker_pids[i], &wstatus, 0);
1786 if (pid != env.worker_pids[i])
1787 perror("Unable to reap worker");
1788 }
1789 }
1790
worker_main_send_log(int sock,char * log_buf,size_t log_cnt)1791 static void worker_main_send_log(int sock, char *log_buf, size_t log_cnt)
1792 {
1793 char *src;
1794 size_t slen;
1795
1796 src = log_buf;
1797 slen = log_cnt;
1798 while (slen) {
1799 struct msg msg_log;
1800 char *dest;
1801 size_t len;
1802
1803 memset(&msg_log, 0, sizeof(msg_log));
1804 msg_log.type = MSG_TEST_LOG;
1805 dest = msg_log.test_log.log_buf;
1806 len = slen >= MAX_LOG_TRUNK_SIZE ? MAX_LOG_TRUNK_SIZE : slen;
1807 memcpy(dest, src, len);
1808
1809 src += len;
1810 slen -= len;
1811 if (!slen)
1812 msg_log.test_log.is_last = true;
1813
1814 assert(send_message(sock, &msg_log) >= 0);
1815 }
1816 }
1817
free_subtest_state(struct subtest_state * state)1818 static void free_subtest_state(struct subtest_state *state)
1819 {
1820 if (state->log_buf) {
1821 free(state->log_buf);
1822 state->log_buf = NULL;
1823 state->log_cnt = 0;
1824 }
1825 free(state->name);
1826 state->name = NULL;
1827 }
1828
worker_main_send_subtests(int sock,struct test_state * state)1829 static int worker_main_send_subtests(int sock, struct test_state *state)
1830 {
1831 int i, result = 0;
1832 struct msg msg;
1833 struct subtest_state *subtest_state;
1834
1835 memset(&msg, 0, sizeof(msg));
1836 msg.type = MSG_SUBTEST_DONE;
1837
1838 for (i = 0; i < state->subtest_num; i++) {
1839 subtest_state = &state->subtest_states[i];
1840
1841 msg.subtest_done.num = i;
1842
1843 strscpy(msg.subtest_done.name, subtest_state->name, MAX_SUBTEST_NAME);
1844
1845 msg.subtest_done.error_cnt = subtest_state->error_cnt;
1846 msg.subtest_done.skipped = subtest_state->skipped;
1847 msg.subtest_done.filtered = subtest_state->filtered;
1848 msg.subtest_done.have_log = false;
1849
1850 if (verbose() || state->force_log || subtest_state->error_cnt) {
1851 if (subtest_state->log_cnt)
1852 msg.subtest_done.have_log = true;
1853 }
1854
1855 if (send_message(sock, &msg) < 0) {
1856 perror("Fail to send message done");
1857 result = 1;
1858 goto out;
1859 }
1860
1861 /* send logs */
1862 if (msg.subtest_done.have_log)
1863 worker_main_send_log(sock, subtest_state->log_buf, subtest_state->log_cnt);
1864
1865 free_subtest_state(subtest_state);
1866 free(subtest_state->name);
1867 }
1868
1869 out:
1870 for (; i < state->subtest_num; i++)
1871 free_subtest_state(&state->subtest_states[i]);
1872 free(state->subtest_states);
1873 return result;
1874 }
1875
worker_main(int sock)1876 static int worker_main(int sock)
1877 {
1878 save_netns();
1879 watchdog_init();
1880
1881 while (true) {
1882 /* receive command */
1883 struct msg msg;
1884
1885 if (recv_message(sock, &msg) < 0)
1886 goto out;
1887
1888 switch (msg.type) {
1889 case MSG_EXIT:
1890 if (env.debug)
1891 fprintf(stderr, "[%d]: worker exit.\n",
1892 env.worker_id);
1893 goto out;
1894 case MSG_DO_TEST: {
1895 int test_to_run = msg.do_test.num;
1896 struct prog_test_def *test = &prog_test_defs[test_to_run];
1897 struct test_state *state = &test_states[test_to_run];
1898 struct msg msg;
1899
1900 if (env.debug)
1901 fprintf(stderr, "[%d]: #%d:%s running.\n",
1902 env.worker_id,
1903 test_to_run + 1,
1904 test->test_name);
1905
1906 run_one_test(test_to_run);
1907
1908 memset(&msg, 0, sizeof(msg));
1909 msg.type = MSG_TEST_DONE;
1910 msg.test_done.num = test_to_run;
1911 msg.test_done.error_cnt = state->error_cnt;
1912 msg.test_done.skip_cnt = state->skip_cnt;
1913 msg.test_done.sub_succ_cnt = state->sub_succ_cnt;
1914 msg.test_done.subtest_num = state->subtest_num;
1915 msg.test_done.have_log = false;
1916
1917 if (verbose() || state->force_log || state->error_cnt) {
1918 if (state->log_cnt)
1919 msg.test_done.have_log = true;
1920 }
1921 if (send_message(sock, &msg) < 0) {
1922 perror("Fail to send message done");
1923 goto out;
1924 }
1925
1926 /* send logs */
1927 if (msg.test_done.have_log)
1928 worker_main_send_log(sock, state->log_buf, state->log_cnt);
1929
1930 if (state->log_buf) {
1931 free(state->log_buf);
1932 state->log_buf = NULL;
1933 state->log_cnt = 0;
1934 }
1935
1936 if (state->subtest_num)
1937 if (worker_main_send_subtests(sock, state))
1938 goto out;
1939
1940 if (env.debug)
1941 fprintf(stderr, "[%d]: #%d:%s done.\n",
1942 env.worker_id,
1943 test_to_run + 1,
1944 test->test_name);
1945 break;
1946 } /* case MSG_DO_TEST */
1947 default:
1948 if (env.debug)
1949 fprintf(stderr, "[%d]: unknown message.\n", env.worker_id);
1950 return -1;
1951 }
1952 }
1953 out:
1954 return 0;
1955 }
1956
free_test_states(void)1957 static void free_test_states(void)
1958 {
1959 int i, j;
1960
1961 for (i = 0; i < ARRAY_SIZE(prog_test_defs); i++) {
1962 struct test_state *test_state = &test_states[i];
1963
1964 for (j = 0; j < test_state->subtest_num; j++)
1965 free_subtest_state(&test_state->subtest_states[j]);
1966
1967 free(test_state->subtest_states);
1968 free(test_state->log_buf);
1969 test_state->subtest_states = NULL;
1970 test_state->log_buf = NULL;
1971 }
1972 }
1973
register_session_key(const char * key_data,size_t key_data_size)1974 static __u32 register_session_key(const char *key_data, size_t key_data_size)
1975 {
1976 return syscall(__NR_add_key, "asymmetric", "libbpf_session_key",
1977 (const void *)key_data, key_data_size,
1978 KEY_SPEC_SESSION_KEYRING);
1979 }
1980
main(int argc,char ** argv)1981 int main(int argc, char **argv)
1982 {
1983 static const struct argp argp = {
1984 .options = opts,
1985 .parser = parse_arg,
1986 .doc = argp_program_doc,
1987 };
1988 int err, i;
1989
1990 #ifndef __SANITIZE_ADDRESS__
1991 struct sigaction sigact = {
1992 .sa_handler = crash_handler,
1993 .sa_flags = SA_RESETHAND,
1994 };
1995 sigaction(SIGSEGV, &sigact, NULL);
1996 #endif
1997
1998 env.stdout_saved = stdout;
1999 env.stderr_saved = stderr;
2000
2001 env.secs_till_notify = 10;
2002 env.secs_till_kill = 120;
2003 err = argp_parse(&argp, argc, argv, 0, NULL, &env);
2004 if (err)
2005 return err;
2006
2007 err = cd_flavor_subdir(argv[0]);
2008 if (err)
2009 return err;
2010
2011 watchdog_init();
2012
2013 /* Use libbpf 1.0 API mode */
2014 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
2015 libbpf_set_print(libbpf_print_fn);
2016 err = register_session_key((const char *)test_progs_verification_cert,
2017 test_progs_verification_cert_len);
2018 if (err < 0)
2019 return err;
2020
2021 traffic_monitor_set_print(traffic_monitor_print_fn);
2022
2023 srand(time(NULL));
2024
2025 env.jit_enabled = is_jit_enabled();
2026 env.nr_cpus = libbpf_num_possible_cpus();
2027 if (env.nr_cpus < 0) {
2028 fprintf(stderr, "Failed to get number of CPUs: %d!\n",
2029 env.nr_cpus);
2030 return -1;
2031 }
2032
2033 env.has_testmod = true;
2034 if (!env.list_test_names) {
2035 /* ensure previous instance of the module is unloaded */
2036 unload_bpf_testmod(verbose());
2037
2038 if (load_bpf_testmod(verbose())) {
2039 fprintf(env.stderr_saved, "WARNING! Selftests relying on bpf_testmod.ko will be skipped.\n");
2040 env.has_testmod = false;
2041 }
2042 }
2043
2044 /* initializing tests */
2045 for (i = 0; i < prog_test_cnt; i++) {
2046 struct prog_test_def *test = &prog_test_defs[i];
2047
2048 test->test_num = i + 1;
2049 test->should_run = should_run(&env.test_selector,
2050 test->test_num, test->test_name);
2051
2052 if ((test->run_test == NULL && test->run_serial_test == NULL) ||
2053 (test->run_test != NULL && test->run_serial_test != NULL)) {
2054 fprintf(stderr, "Test %d:%s must have either test_%s() or serial_test_%sl() defined.\n",
2055 test->test_num, test->test_name, test->test_name, test->test_name);
2056 exit(EXIT_ERR_SETUP_INFRA);
2057 }
2058 if (test->should_run)
2059 test->should_tmon = should_tmon(&env.tmon_selector, test->test_name);
2060 }
2061
2062 /* ignore workers if we are just listing */
2063 if (env.get_test_cnt || env.list_test_names)
2064 env.workers = 0;
2065
2066 /* launch workers if requested */
2067 env.worker_id = -1; /* main process */
2068 if (env.workers) {
2069 env.worker_pids = calloc(sizeof(pid_t), env.workers);
2070 env.worker_socks = calloc(sizeof(int), env.workers);
2071 if (env.debug)
2072 fprintf(stdout, "Launching %d workers.\n", env.workers);
2073 for (i = 0; i < env.workers; i++) {
2074 int sv[2];
2075 pid_t pid;
2076
2077 if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv) < 0) {
2078 perror("Fail to create worker socket");
2079 return -1;
2080 }
2081 pid = fork();
2082 if (pid < 0) {
2083 perror("Failed to fork worker");
2084 return -1;
2085 } else if (pid != 0) { /* main process */
2086 close(sv[1]);
2087 env.worker_pids[i] = pid;
2088 env.worker_socks[i] = sv[0];
2089 } else { /* inside each worker process */
2090 close(sv[0]);
2091 env.worker_id = i;
2092 return worker_main(sv[1]);
2093 }
2094 }
2095
2096 if (env.worker_id == -1) {
2097 server_main();
2098 goto out;
2099 }
2100 }
2101
2102 /* The rest of the main process */
2103
2104 /* on single mode */
2105 save_netns();
2106
2107 for (i = 0; i < prog_test_cnt; i++) {
2108 struct prog_test_def *test = &prog_test_defs[i];
2109
2110 if (!test->should_run)
2111 continue;
2112
2113 if (env.get_test_cnt) {
2114 env.succ_cnt++;
2115 continue;
2116 }
2117
2118 if (env.list_test_names) {
2119 fprintf(env.stdout_saved, "%s\n", test->test_name);
2120 env.succ_cnt++;
2121 continue;
2122 }
2123
2124 run_one_test(i);
2125 }
2126
2127 if (env.get_test_cnt) {
2128 printf("%d\n", env.succ_cnt);
2129 goto out;
2130 }
2131
2132 if (env.list_test_names)
2133 goto out;
2134
2135 calculate_summary_and_print_errors(&env);
2136
2137 close(env.saved_netns_fd);
2138 out:
2139 if (!env.list_test_names && env.has_testmod)
2140 unload_bpf_testmod(verbose());
2141
2142 free_test_selector(&env.test_selector);
2143 free_test_selector(&env.subtest_selector);
2144 free_test_selector(&env.tmon_selector);
2145 free_test_states();
2146
2147 if (env.succ_cnt + env.fail_cnt + env.skip_cnt == 0)
2148 return EXIT_NO_TEST;
2149
2150 return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
2151 }
2152