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