1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2017 Facebook 3 */ 4 #include "test_progs.h" 5 #include "cgroup_helpers.h" 6 #include "bpf_rlimit.h" 7 #include <argp.h> 8 #include <string.h> 9 #include <signal.h> 10 #include <execinfo.h> /* backtrace */ 11 12 /* defined in test_progs.h */ 13 struct test_env env = {}; 14 15 struct prog_test_def { 16 const char *test_name; 17 int test_num; 18 void (*run_test)(void); 19 bool force_log; 20 int error_cnt; 21 int skip_cnt; 22 bool tested; 23 bool need_cgroup_cleanup; 24 25 char *subtest_name; 26 int subtest_num; 27 28 /* store counts before subtest started */ 29 int old_error_cnt; 30 }; 31 32 static bool should_run(struct test_selector *sel, int num, const char *name) 33 { 34 int i; 35 36 for (i = 0; i < sel->blacklist.cnt; i++) { 37 if (strstr(name, sel->blacklist.strs[i])) 38 return false; 39 } 40 41 for (i = 0; i < sel->whitelist.cnt; i++) { 42 if (strstr(name, sel->whitelist.strs[i])) 43 return true; 44 } 45 46 if (!sel->whitelist.cnt && !sel->num_set) 47 return true; 48 49 return num < sel->num_set_len && sel->num_set[num]; 50 } 51 52 static void dump_test_log(const struct prog_test_def *test, bool failed) 53 { 54 if (stdout == env.stdout) 55 return; 56 57 fflush(stdout); /* exports env.log_buf & env.log_cnt */ 58 59 if (env.verbosity > VERBOSE_NONE || test->force_log || failed) { 60 if (env.log_cnt) { 61 env.log_buf[env.log_cnt] = '\0'; 62 fprintf(env.stdout, "%s", env.log_buf); 63 if (env.log_buf[env.log_cnt - 1] != '\n') 64 fprintf(env.stdout, "\n"); 65 } 66 } 67 68 fseeko(stdout, 0, SEEK_SET); /* rewind */ 69 } 70 71 static void skip_account(void) 72 { 73 if (env.test->skip_cnt) { 74 env.skip_cnt++; 75 env.test->skip_cnt = 0; 76 } 77 } 78 79 void test__end_subtest() 80 { 81 struct prog_test_def *test = env.test; 82 int sub_error_cnt = test->error_cnt - test->old_error_cnt; 83 84 if (sub_error_cnt) 85 env.fail_cnt++; 86 else 87 env.sub_succ_cnt++; 88 skip_account(); 89 90 dump_test_log(test, sub_error_cnt); 91 92 fprintf(env.stdout, "#%d/%d %s:%s\n", 93 test->test_num, test->subtest_num, 94 test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); 95 96 free(test->subtest_name); 97 test->subtest_name = NULL; 98 } 99 100 bool test__start_subtest(const char *name) 101 { 102 struct prog_test_def *test = env.test; 103 104 if (test->subtest_name) 105 test__end_subtest(); 106 107 test->subtest_num++; 108 109 if (!name || !name[0]) { 110 fprintf(env.stderr, 111 "Subtest #%d didn't provide sub-test name!\n", 112 test->subtest_num); 113 return false; 114 } 115 116 if (!should_run(&env.subtest_selector, test->subtest_num, name)) 117 return false; 118 119 test->subtest_name = strdup(name); 120 if (!test->subtest_name) { 121 fprintf(env.stderr, 122 "Subtest #%d: failed to copy subtest name!\n", 123 test->subtest_num); 124 return false; 125 } 126 env.test->old_error_cnt = env.test->error_cnt; 127 128 return true; 129 } 130 131 void test__force_log() { 132 env.test->force_log = true; 133 } 134 135 void test__skip(void) 136 { 137 env.test->skip_cnt++; 138 } 139 140 void test__fail(void) 141 { 142 env.test->error_cnt++; 143 } 144 145 int test__join_cgroup(const char *path) 146 { 147 int fd; 148 149 if (!env.test->need_cgroup_cleanup) { 150 if (setup_cgroup_environment()) { 151 fprintf(stderr, 152 "#%d %s: Failed to setup cgroup environment\n", 153 env.test->test_num, env.test->test_name); 154 return -1; 155 } 156 157 env.test->need_cgroup_cleanup = true; 158 } 159 160 fd = create_and_get_cgroup(path); 161 if (fd < 0) { 162 fprintf(stderr, 163 "#%d %s: Failed to create cgroup '%s' (errno=%d)\n", 164 env.test->test_num, env.test->test_name, path, errno); 165 return fd; 166 } 167 168 if (join_cgroup(path)) { 169 fprintf(stderr, 170 "#%d %s: Failed to join cgroup '%s' (errno=%d)\n", 171 env.test->test_num, env.test->test_name, path, errno); 172 return -1; 173 } 174 175 return fd; 176 } 177 178 struct ipv4_packet pkt_v4 = { 179 .eth.h_proto = __bpf_constant_htons(ETH_P_IP), 180 .iph.ihl = 5, 181 .iph.protocol = IPPROTO_TCP, 182 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), 183 .tcp.urg_ptr = 123, 184 .tcp.doff = 5, 185 }; 186 187 struct ipv6_packet pkt_v6 = { 188 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), 189 .iph.nexthdr = IPPROTO_TCP, 190 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), 191 .tcp.urg_ptr = 123, 192 .tcp.doff = 5, 193 }; 194 195 int bpf_find_map(const char *test, struct bpf_object *obj, const char *name) 196 { 197 struct bpf_map *map; 198 199 map = bpf_object__find_map_by_name(obj, name); 200 if (!map) { 201 printf("%s:FAIL:map '%s' not found\n", test, name); 202 test__fail(); 203 return -1; 204 } 205 return bpf_map__fd(map); 206 } 207 208 static bool is_jit_enabled(void) 209 { 210 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable"; 211 bool enabled = false; 212 int sysctl_fd; 213 214 sysctl_fd = open(jit_sysctl, 0, O_RDONLY); 215 if (sysctl_fd != -1) { 216 char tmpc; 217 218 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1) 219 enabled = (tmpc != '0'); 220 close(sysctl_fd); 221 } 222 223 return enabled; 224 } 225 226 int compare_map_keys(int map1_fd, int map2_fd) 227 { 228 __u32 key, next_key; 229 char val_buf[PERF_MAX_STACK_DEPTH * 230 sizeof(struct bpf_stack_build_id)]; 231 int err; 232 233 err = bpf_map_get_next_key(map1_fd, NULL, &key); 234 if (err) 235 return err; 236 err = bpf_map_lookup_elem(map2_fd, &key, val_buf); 237 if (err) 238 return err; 239 240 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) { 241 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf); 242 if (err) 243 return err; 244 245 key = next_key; 246 } 247 if (errno != ENOENT) 248 return -1; 249 250 return 0; 251 } 252 253 int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len) 254 { 255 __u32 key, next_key, *cur_key_p, *next_key_p; 256 char *val_buf1, *val_buf2; 257 int i, err = 0; 258 259 val_buf1 = malloc(stack_trace_len); 260 val_buf2 = malloc(stack_trace_len); 261 cur_key_p = NULL; 262 next_key_p = &key; 263 while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) { 264 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1); 265 if (err) 266 goto out; 267 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2); 268 if (err) 269 goto out; 270 for (i = 0; i < stack_trace_len; i++) { 271 if (val_buf1[i] != val_buf2[i]) { 272 err = -1; 273 goto out; 274 } 275 } 276 key = *next_key_p; 277 cur_key_p = &key; 278 next_key_p = &next_key; 279 } 280 if (errno != ENOENT) 281 err = -1; 282 283 out: 284 free(val_buf1); 285 free(val_buf2); 286 return err; 287 } 288 289 int extract_build_id(char *build_id, size_t size) 290 { 291 FILE *fp; 292 char *line = NULL; 293 size_t len = 0; 294 295 fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r"); 296 if (fp == NULL) 297 return -1; 298 299 if (getline(&line, &len, fp) == -1) 300 goto err; 301 fclose(fp); 302 303 if (len > size) 304 len = size; 305 memcpy(build_id, line, len); 306 build_id[len] = '\0'; 307 return 0; 308 err: 309 fclose(fp); 310 return -1; 311 } 312 313 void *spin_lock_thread(void *arg) 314 { 315 __u32 duration, retval; 316 int err, prog_fd = *(u32 *) arg; 317 318 err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4), 319 NULL, NULL, &retval, &duration); 320 CHECK(err || retval, "", 321 "err %d errno %d retval %d duration %d\n", 322 err, errno, retval, duration); 323 pthread_exit(arg); 324 } 325 326 /* extern declarations for test funcs */ 327 #define DEFINE_TEST(name) extern void test_##name(void); 328 #include <prog_tests/tests.h> 329 #undef DEFINE_TEST 330 331 static struct prog_test_def prog_test_defs[] = { 332 #define DEFINE_TEST(name) { \ 333 .test_name = #name, \ 334 .run_test = &test_##name, \ 335 }, 336 #include <prog_tests/tests.h> 337 #undef DEFINE_TEST 338 }; 339 const int prog_test_cnt = ARRAY_SIZE(prog_test_defs); 340 341 const char *argp_program_version = "test_progs 0.1"; 342 const char *argp_program_bug_address = "<bpf@vger.kernel.org>"; 343 const char argp_program_doc[] = "BPF selftests test runner"; 344 345 enum ARG_KEYS { 346 ARG_TEST_NUM = 'n', 347 ARG_TEST_NAME = 't', 348 ARG_TEST_NAME_BLACKLIST = 'b', 349 ARG_VERIFIER_STATS = 's', 350 ARG_VERBOSE = 'v', 351 }; 352 353 static const struct argp_option opts[] = { 354 { "num", ARG_TEST_NUM, "NUM", 0, 355 "Run test number NUM only " }, 356 { "name", ARG_TEST_NAME, "NAMES", 0, 357 "Run tests with names containing any string from NAMES list" }, 358 { "name-blacklist", ARG_TEST_NAME_BLACKLIST, "NAMES", 0, 359 "Don't run tests with names containing any string from NAMES list" }, 360 { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0, 361 "Output verifier statistics", }, 362 { "verbose", ARG_VERBOSE, "LEVEL", OPTION_ARG_OPTIONAL, 363 "Verbose output (use -vv or -vvv for progressively verbose output)" }, 364 {}, 365 }; 366 367 static int libbpf_print_fn(enum libbpf_print_level level, 368 const char *format, va_list args) 369 { 370 if (env.verbosity < VERBOSE_VERY && level == LIBBPF_DEBUG) 371 return 0; 372 vprintf(format, args); 373 return 0; 374 } 375 376 static int parse_str_list(const char *s, struct str_set *set) 377 { 378 char *input, *state = NULL, *next, **tmp, **strs = NULL; 379 int cnt = 0; 380 381 input = strdup(s); 382 if (!input) 383 return -ENOMEM; 384 385 set->cnt = 0; 386 set->strs = NULL; 387 388 while ((next = strtok_r(state ? NULL : input, ",", &state))) { 389 tmp = realloc(strs, sizeof(*strs) * (cnt + 1)); 390 if (!tmp) 391 goto err; 392 strs = tmp; 393 394 strs[cnt] = strdup(next); 395 if (!strs[cnt]) 396 goto err; 397 398 cnt++; 399 } 400 401 set->cnt = cnt; 402 set->strs = (const char **)strs; 403 free(input); 404 return 0; 405 err: 406 free(strs); 407 free(input); 408 return -ENOMEM; 409 } 410 411 int parse_num_list(const char *s, struct test_selector *sel) 412 { 413 int i, set_len = 0, num, start = 0, end = -1; 414 bool *set = NULL, *tmp, parsing_end = false; 415 char *next; 416 417 while (s[0]) { 418 errno = 0; 419 num = strtol(s, &next, 10); 420 if (errno) 421 return -errno; 422 423 if (parsing_end) 424 end = num; 425 else 426 start = num; 427 428 if (!parsing_end && *next == '-') { 429 s = next + 1; 430 parsing_end = true; 431 continue; 432 } else if (*next == ',') { 433 parsing_end = false; 434 s = next + 1; 435 end = num; 436 } else if (*next == '\0') { 437 parsing_end = false; 438 s = next; 439 end = num; 440 } else { 441 return -EINVAL; 442 } 443 444 if (start > end) 445 return -EINVAL; 446 447 if (end + 1 > set_len) { 448 set_len = end + 1; 449 tmp = realloc(set, set_len); 450 if (!tmp) { 451 free(set); 452 return -ENOMEM; 453 } 454 set = tmp; 455 } 456 for (i = start; i <= end; i++) { 457 set[i] = true; 458 } 459 460 } 461 462 if (!set) 463 return -EINVAL; 464 465 sel->num_set = set; 466 sel->num_set_len = set_len; 467 468 return 0; 469 } 470 471 extern int extra_prog_load_log_flags; 472 473 static error_t parse_arg(int key, char *arg, struct argp_state *state) 474 { 475 struct test_env *env = state->input; 476 477 switch (key) { 478 case ARG_TEST_NUM: { 479 char *subtest_str = strchr(arg, '/'); 480 481 if (subtest_str) { 482 *subtest_str = '\0'; 483 if (parse_num_list(subtest_str + 1, 484 &env->subtest_selector)) { 485 fprintf(stderr, 486 "Failed to parse subtest numbers.\n"); 487 return -EINVAL; 488 } 489 } 490 if (parse_num_list(arg, &env->test_selector)) { 491 fprintf(stderr, "Failed to parse test numbers.\n"); 492 return -EINVAL; 493 } 494 break; 495 } 496 case ARG_TEST_NAME: { 497 char *subtest_str = strchr(arg, '/'); 498 499 if (subtest_str) { 500 *subtest_str = '\0'; 501 if (parse_str_list(subtest_str + 1, 502 &env->subtest_selector.whitelist)) 503 return -ENOMEM; 504 } 505 if (parse_str_list(arg, &env->test_selector.whitelist)) 506 return -ENOMEM; 507 break; 508 } 509 case ARG_TEST_NAME_BLACKLIST: { 510 char *subtest_str = strchr(arg, '/'); 511 512 if (subtest_str) { 513 *subtest_str = '\0'; 514 if (parse_str_list(subtest_str + 1, 515 &env->subtest_selector.blacklist)) 516 return -ENOMEM; 517 } 518 if (parse_str_list(arg, &env->test_selector.blacklist)) 519 return -ENOMEM; 520 break; 521 } 522 case ARG_VERIFIER_STATS: 523 env->verifier_stats = true; 524 break; 525 case ARG_VERBOSE: 526 env->verbosity = VERBOSE_NORMAL; 527 if (arg) { 528 if (strcmp(arg, "v") == 0) { 529 env->verbosity = VERBOSE_VERY; 530 extra_prog_load_log_flags = 1; 531 } else if (strcmp(arg, "vv") == 0) { 532 env->verbosity = VERBOSE_SUPER; 533 extra_prog_load_log_flags = 2; 534 } else { 535 fprintf(stderr, 536 "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n", 537 arg); 538 return -EINVAL; 539 } 540 } 541 break; 542 case ARGP_KEY_ARG: 543 argp_usage(state); 544 break; 545 case ARGP_KEY_END: 546 break; 547 default: 548 return ARGP_ERR_UNKNOWN; 549 } 550 return 0; 551 } 552 553 static void stdio_hijack(void) 554 { 555 #ifdef __GLIBC__ 556 env.stdout = stdout; 557 env.stderr = stderr; 558 559 if (env.verbosity > VERBOSE_NONE) { 560 /* nothing to do, output to stdout by default */ 561 return; 562 } 563 564 /* stdout and stderr -> buffer */ 565 fflush(stdout); 566 567 stdout = open_memstream(&env.log_buf, &env.log_cnt); 568 if (!stdout) { 569 stdout = env.stdout; 570 perror("open_memstream"); 571 return; 572 } 573 574 stderr = stdout; 575 #endif 576 } 577 578 static void stdio_restore(void) 579 { 580 #ifdef __GLIBC__ 581 if (stdout == env.stdout) 582 return; 583 584 fclose(stdout); 585 free(env.log_buf); 586 587 env.log_buf = NULL; 588 env.log_cnt = 0; 589 590 stdout = env.stdout; 591 stderr = env.stderr; 592 #endif 593 } 594 595 /* 596 * Determine if test_progs is running as a "flavored" test runner and switch 597 * into corresponding sub-directory to load correct BPF objects. 598 * 599 * This is done by looking at executable name. If it contains "-flavor" 600 * suffix, then we are running as a flavored test runner. 601 */ 602 int cd_flavor_subdir(const char *exec_name) 603 { 604 /* General form of argv[0] passed here is: 605 * some/path/to/test_progs[-flavor], where -flavor part is optional. 606 * First cut out "test_progs[-flavor]" part, then extract "flavor" 607 * part, if it's there. 608 */ 609 const char *flavor = strrchr(exec_name, '/'); 610 611 if (!flavor) 612 return 0; 613 flavor++; 614 flavor = strrchr(flavor, '-'); 615 if (!flavor) 616 return 0; 617 flavor++; 618 printf("Switching to flavor '%s' subdirectory...\n", flavor); 619 return chdir(flavor); 620 } 621 622 #define MAX_BACKTRACE_SZ 128 623 void crash_handler(int signum) 624 { 625 void *bt[MAX_BACKTRACE_SZ]; 626 size_t sz; 627 628 sz = backtrace(bt, ARRAY_SIZE(bt)); 629 630 if (env.test) 631 dump_test_log(env.test, true); 632 if (env.stdout) 633 stdio_restore(); 634 635 fprintf(stderr, "Caught signal #%d!\nStack trace:\n", signum); 636 backtrace_symbols_fd(bt, sz, STDERR_FILENO); 637 } 638 639 int main(int argc, char **argv) 640 { 641 static const struct argp argp = { 642 .options = opts, 643 .parser = parse_arg, 644 .doc = argp_program_doc, 645 }; 646 struct sigaction sigact = { 647 .sa_handler = crash_handler, 648 .sa_flags = SA_RESETHAND, 649 }; 650 int err, i; 651 652 sigaction(SIGSEGV, &sigact, NULL); 653 654 err = argp_parse(&argp, argc, argv, 0, NULL, &env); 655 if (err) 656 return err; 657 658 err = cd_flavor_subdir(argv[0]); 659 if (err) 660 return err; 661 662 libbpf_set_print(libbpf_print_fn); 663 664 srand(time(NULL)); 665 666 env.jit_enabled = is_jit_enabled(); 667 668 stdio_hijack(); 669 for (i = 0; i < prog_test_cnt; i++) { 670 struct prog_test_def *test = &prog_test_defs[i]; 671 672 env.test = test; 673 test->test_num = i + 1; 674 675 if (!should_run(&env.test_selector, 676 test->test_num, test->test_name)) 677 continue; 678 679 test->run_test(); 680 /* ensure last sub-test is finalized properly */ 681 if (test->subtest_name) 682 test__end_subtest(); 683 684 test->tested = true; 685 if (test->error_cnt) 686 env.fail_cnt++; 687 else 688 env.succ_cnt++; 689 skip_account(); 690 691 dump_test_log(test, test->error_cnt); 692 693 fprintf(env.stdout, "#%d %s:%s\n", 694 test->test_num, test->test_name, 695 test->error_cnt ? "FAIL" : "OK"); 696 697 if (test->need_cgroup_cleanup) 698 cleanup_cgroup_environment(); 699 } 700 stdio_restore(); 701 printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n", 702 env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt); 703 704 free(env.test_selector.blacklist.strs); 705 free(env.test_selector.whitelist.strs); 706 free(env.test_selector.num_set); 707 free(env.subtest_selector.blacklist.strs); 708 free(env.subtest_selector.whitelist.strs); 709 free(env.subtest_selector.num_set); 710 711 return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 712 } 713