1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2017 Facebook 3 */ 4 #include "test_progs.h" 5 #include "bpf_rlimit.h" 6 #include <argp.h> 7 #include <string.h> 8 9 /* defined in test_progs.h */ 10 struct test_env env; 11 12 struct prog_test_def { 13 const char *test_name; 14 int test_num; 15 void (*run_test)(void); 16 bool force_log; 17 int error_cnt; 18 int skip_cnt; 19 bool tested; 20 21 const char *subtest_name; 22 int subtest_num; 23 24 /* store counts before subtest started */ 25 int old_error_cnt; 26 }; 27 28 static bool should_run(struct test_selector *sel, int num, const char *name) 29 { 30 if (sel->name && sel->name[0] && !strstr(name, sel->name)) 31 return false; 32 33 if (!sel->num_set) 34 return true; 35 36 return num < sel->num_set_len && sel->num_set[num]; 37 } 38 39 static void dump_test_log(const struct prog_test_def *test, bool failed) 40 { 41 if (stdout == env.stdout) 42 return; 43 44 fflush(stdout); /* exports env.log_buf & env.log_cnt */ 45 46 if (env.verbose || test->force_log || failed) { 47 if (env.log_cnt) { 48 env.log_buf[env.log_cnt] = '\0'; 49 fprintf(env.stdout, "%s", env.log_buf); 50 if (env.log_buf[env.log_cnt - 1] != '\n') 51 fprintf(env.stdout, "\n"); 52 } 53 } 54 55 fseeko(stdout, 0, SEEK_SET); /* rewind */ 56 } 57 58 static void skip_account(void) 59 { 60 if (env.test->skip_cnt) { 61 env.skip_cnt++; 62 env.test->skip_cnt = 0; 63 } 64 } 65 66 void test__end_subtest() 67 { 68 struct prog_test_def *test = env.test; 69 int sub_error_cnt = test->error_cnt - test->old_error_cnt; 70 71 if (sub_error_cnt) 72 env.fail_cnt++; 73 else 74 env.sub_succ_cnt++; 75 skip_account(); 76 77 dump_test_log(test, sub_error_cnt); 78 79 fprintf(env.stdout, "#%d/%d %s:%s\n", 80 test->test_num, test->subtest_num, 81 test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); 82 } 83 84 bool test__start_subtest(const char *name) 85 { 86 struct prog_test_def *test = env.test; 87 88 if (test->subtest_name) { 89 test__end_subtest(); 90 test->subtest_name = NULL; 91 } 92 93 test->subtest_num++; 94 95 if (!name || !name[0]) { 96 fprintf(env.stderr, 97 "Subtest #%d didn't provide sub-test name!\n", 98 test->subtest_num); 99 return false; 100 } 101 102 if (!should_run(&env.subtest_selector, test->subtest_num, name)) 103 return false; 104 105 test->subtest_name = name; 106 env.test->old_error_cnt = env.test->error_cnt; 107 108 return true; 109 } 110 111 void test__force_log() { 112 env.test->force_log = true; 113 } 114 115 void test__skip(void) 116 { 117 env.test->skip_cnt++; 118 } 119 120 void test__fail(void) 121 { 122 env.test->error_cnt++; 123 } 124 125 struct ipv4_packet pkt_v4 = { 126 .eth.h_proto = __bpf_constant_htons(ETH_P_IP), 127 .iph.ihl = 5, 128 .iph.protocol = IPPROTO_TCP, 129 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), 130 .tcp.urg_ptr = 123, 131 .tcp.doff = 5, 132 }; 133 134 struct ipv6_packet pkt_v6 = { 135 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), 136 .iph.nexthdr = IPPROTO_TCP, 137 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), 138 .tcp.urg_ptr = 123, 139 .tcp.doff = 5, 140 }; 141 142 int bpf_find_map(const char *test, struct bpf_object *obj, const char *name) 143 { 144 struct bpf_map *map; 145 146 map = bpf_object__find_map_by_name(obj, name); 147 if (!map) { 148 printf("%s:FAIL:map '%s' not found\n", test, name); 149 test__fail(); 150 return -1; 151 } 152 return bpf_map__fd(map); 153 } 154 155 static bool is_jit_enabled(void) 156 { 157 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable"; 158 bool enabled = false; 159 int sysctl_fd; 160 161 sysctl_fd = open(jit_sysctl, 0, O_RDONLY); 162 if (sysctl_fd != -1) { 163 char tmpc; 164 165 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1) 166 enabled = (tmpc != '0'); 167 close(sysctl_fd); 168 } 169 170 return enabled; 171 } 172 173 int compare_map_keys(int map1_fd, int map2_fd) 174 { 175 __u32 key, next_key; 176 char val_buf[PERF_MAX_STACK_DEPTH * 177 sizeof(struct bpf_stack_build_id)]; 178 int err; 179 180 err = bpf_map_get_next_key(map1_fd, NULL, &key); 181 if (err) 182 return err; 183 err = bpf_map_lookup_elem(map2_fd, &key, val_buf); 184 if (err) 185 return err; 186 187 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) { 188 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf); 189 if (err) 190 return err; 191 192 key = next_key; 193 } 194 if (errno != ENOENT) 195 return -1; 196 197 return 0; 198 } 199 200 int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len) 201 { 202 __u32 key, next_key, *cur_key_p, *next_key_p; 203 char *val_buf1, *val_buf2; 204 int i, err = 0; 205 206 val_buf1 = malloc(stack_trace_len); 207 val_buf2 = malloc(stack_trace_len); 208 cur_key_p = NULL; 209 next_key_p = &key; 210 while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) { 211 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1); 212 if (err) 213 goto out; 214 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2); 215 if (err) 216 goto out; 217 for (i = 0; i < stack_trace_len; i++) { 218 if (val_buf1[i] != val_buf2[i]) { 219 err = -1; 220 goto out; 221 } 222 } 223 key = *next_key_p; 224 cur_key_p = &key; 225 next_key_p = &next_key; 226 } 227 if (errno != ENOENT) 228 err = -1; 229 230 out: 231 free(val_buf1); 232 free(val_buf2); 233 return err; 234 } 235 236 int extract_build_id(char *build_id, size_t size) 237 { 238 FILE *fp; 239 char *line = NULL; 240 size_t len = 0; 241 242 fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r"); 243 if (fp == NULL) 244 return -1; 245 246 if (getline(&line, &len, fp) == -1) 247 goto err; 248 fclose(fp); 249 250 if (len > size) 251 len = size; 252 memcpy(build_id, line, len); 253 build_id[len] = '\0'; 254 return 0; 255 err: 256 fclose(fp); 257 return -1; 258 } 259 260 void *spin_lock_thread(void *arg) 261 { 262 __u32 duration, retval; 263 int err, prog_fd = *(u32 *) arg; 264 265 err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4), 266 NULL, NULL, &retval, &duration); 267 CHECK(err || retval, "", 268 "err %d errno %d retval %d duration %d\n", 269 err, errno, retval, duration); 270 pthread_exit(arg); 271 } 272 273 /* extern declarations for test funcs */ 274 #define DEFINE_TEST(name) extern void test_##name(); 275 #include <prog_tests/tests.h> 276 #undef DEFINE_TEST 277 278 static struct prog_test_def prog_test_defs[] = { 279 #define DEFINE_TEST(name) { \ 280 .test_name = #name, \ 281 .run_test = &test_##name, \ 282 }, 283 #include <prog_tests/tests.h> 284 #undef DEFINE_TEST 285 }; 286 const int prog_test_cnt = ARRAY_SIZE(prog_test_defs); 287 288 const char *argp_program_version = "test_progs 0.1"; 289 const char *argp_program_bug_address = "<bpf@vger.kernel.org>"; 290 const char argp_program_doc[] = "BPF selftests test runner"; 291 292 enum ARG_KEYS { 293 ARG_TEST_NUM = 'n', 294 ARG_TEST_NAME = 't', 295 ARG_VERIFIER_STATS = 's', 296 ARG_VERBOSE = 'v', 297 }; 298 299 static const struct argp_option opts[] = { 300 { "num", ARG_TEST_NUM, "NUM", 0, 301 "Run test number NUM only " }, 302 { "name", ARG_TEST_NAME, "NAME", 0, 303 "Run tests with names containing NAME" }, 304 { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0, 305 "Output verifier statistics", }, 306 { "verbose", ARG_VERBOSE, "LEVEL", OPTION_ARG_OPTIONAL, 307 "Verbose output (use -vv for extra verbose output)" }, 308 {}, 309 }; 310 311 static int libbpf_print_fn(enum libbpf_print_level level, 312 const char *format, va_list args) 313 { 314 if (!env.very_verbose && level == LIBBPF_DEBUG) 315 return 0; 316 vprintf(format, args); 317 return 0; 318 } 319 320 int parse_num_list(const char *s, struct test_selector *sel) 321 { 322 int i, set_len = 0, num, start = 0, end = -1; 323 bool *set = NULL, *tmp, parsing_end = false; 324 char *next; 325 326 while (s[0]) { 327 errno = 0; 328 num = strtol(s, &next, 10); 329 if (errno) 330 return -errno; 331 332 if (parsing_end) 333 end = num; 334 else 335 start = num; 336 337 if (!parsing_end && *next == '-') { 338 s = next + 1; 339 parsing_end = true; 340 continue; 341 } else if (*next == ',') { 342 parsing_end = false; 343 s = next + 1; 344 end = num; 345 } else if (*next == '\0') { 346 parsing_end = false; 347 s = next; 348 end = num; 349 } else { 350 return -EINVAL; 351 } 352 353 if (start > end) 354 return -EINVAL; 355 356 if (end + 1 > set_len) { 357 set_len = end + 1; 358 tmp = realloc(set, set_len); 359 if (!tmp) { 360 free(set); 361 return -ENOMEM; 362 } 363 set = tmp; 364 } 365 for (i = start; i <= end; i++) { 366 set[i] = true; 367 } 368 369 } 370 371 if (!set) 372 return -EINVAL; 373 374 sel->num_set = set; 375 sel->num_set_len = set_len; 376 377 return 0; 378 } 379 380 static error_t parse_arg(int key, char *arg, struct argp_state *state) 381 { 382 struct test_env *env = state->input; 383 384 switch (key) { 385 case ARG_TEST_NUM: { 386 char *subtest_str = strchr(arg, '/'); 387 388 if (subtest_str) { 389 *subtest_str = '\0'; 390 if (parse_num_list(subtest_str + 1, 391 &env->subtest_selector)) { 392 fprintf(stderr, 393 "Failed to parse subtest numbers.\n"); 394 return -EINVAL; 395 } 396 } 397 if (parse_num_list(arg, &env->test_selector)) { 398 fprintf(stderr, "Failed to parse test numbers.\n"); 399 return -EINVAL; 400 } 401 break; 402 } 403 case ARG_TEST_NAME: { 404 char *subtest_str = strchr(arg, '/'); 405 406 if (subtest_str) { 407 *subtest_str = '\0'; 408 env->subtest_selector.name = strdup(subtest_str + 1); 409 if (!env->subtest_selector.name) 410 return -ENOMEM; 411 } 412 env->test_selector.name = strdup(arg); 413 if (!env->test_selector.name) 414 return -ENOMEM; 415 break; 416 } 417 case ARG_VERIFIER_STATS: 418 env->verifier_stats = true; 419 break; 420 case ARG_VERBOSE: 421 if (arg) { 422 if (strcmp(arg, "v") == 0) { 423 env->very_verbose = true; 424 } else { 425 fprintf(stderr, 426 "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n", 427 arg); 428 return -EINVAL; 429 } 430 } 431 env->verbose = true; 432 break; 433 case ARGP_KEY_ARG: 434 argp_usage(state); 435 break; 436 case ARGP_KEY_END: 437 break; 438 default: 439 return ARGP_ERR_UNKNOWN; 440 } 441 return 0; 442 } 443 444 static void stdio_hijack(void) 445 { 446 #ifdef __GLIBC__ 447 env.stdout = stdout; 448 env.stderr = stderr; 449 450 if (env.verbose) { 451 /* nothing to do, output to stdout by default */ 452 return; 453 } 454 455 /* stdout and stderr -> buffer */ 456 fflush(stdout); 457 458 stdout = open_memstream(&env.log_buf, &env.log_cnt); 459 if (!stdout) { 460 stdout = env.stdout; 461 perror("open_memstream"); 462 return; 463 } 464 465 stderr = stdout; 466 #endif 467 } 468 469 static void stdio_restore(void) 470 { 471 #ifdef __GLIBC__ 472 if (stdout == env.stdout) 473 return; 474 475 fclose(stdout); 476 free(env.log_buf); 477 478 env.log_buf = NULL; 479 env.log_cnt = 0; 480 481 stdout = env.stdout; 482 stderr = env.stderr; 483 #endif 484 } 485 486 int main(int argc, char **argv) 487 { 488 static const struct argp argp = { 489 .options = opts, 490 .parser = parse_arg, 491 .doc = argp_program_doc, 492 }; 493 int err, i; 494 495 err = argp_parse(&argp, argc, argv, 0, NULL, &env); 496 if (err) 497 return err; 498 499 libbpf_set_print(libbpf_print_fn); 500 501 srand(time(NULL)); 502 503 env.jit_enabled = is_jit_enabled(); 504 505 stdio_hijack(); 506 for (i = 0; i < prog_test_cnt; i++) { 507 struct prog_test_def *test = &prog_test_defs[i]; 508 509 env.test = test; 510 test->test_num = i + 1; 511 512 if (!should_run(&env.test_selector, 513 test->test_num, test->test_name)) 514 continue; 515 516 test->run_test(); 517 /* ensure last sub-test is finalized properly */ 518 if (test->subtest_name) 519 test__end_subtest(); 520 521 test->tested = true; 522 if (test->error_cnt) 523 env.fail_cnt++; 524 else 525 env.succ_cnt++; 526 skip_account(); 527 528 dump_test_log(test, test->error_cnt); 529 530 fprintf(env.stdout, "#%d %s:%s\n", 531 test->test_num, test->test_name, 532 test->error_cnt ? "FAIL" : "OK"); 533 } 534 stdio_restore(); 535 printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n", 536 env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt); 537 538 free(env.test_selector.num_set); 539 free(env.subtest_selector.num_set); 540 541 return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 542 } 543