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