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