linux/tools/testing/selftests/bpf/prog_tests/core_extern.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2019 Facebook */
   3
   4#include <test_progs.h>
   5#include <sys/mman.h>
   6#include <sys/utsname.h>
   7#include <linux/version.h>
   8#include "test_core_extern.skel.h"
   9
  10static uint32_t get_kernel_version(void)
  11{
  12        uint32_t major, minor, patch;
  13        struct utsname info;
  14
  15        uname(&info);
  16        if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)
  17                return 0;
  18        return KERNEL_VERSION(major, minor, patch);
  19}
  20
  21#define CFG "CONFIG_BPF_SYSCALL=n\n"
  22
  23static struct test_case {
  24        const char *name;
  25        const char *cfg;
  26        bool fails;
  27        struct test_core_extern__data data;
  28} test_cases[] = {
  29        { .name = "default search path", .data = { .bpf_syscall = true } },
  30        {
  31                .name = "custom values",
  32                .cfg = "CONFIG_BPF_SYSCALL=n\n"
  33                       "CONFIG_TRISTATE=m\n"
  34                       "CONFIG_BOOL=y\n"
  35                       "CONFIG_CHAR=100\n"
  36                       "CONFIG_USHORT=30000\n"
  37                       "CONFIG_INT=123456\n"
  38                       "CONFIG_ULONG=0xDEADBEEFC0DE\n"
  39                       "CONFIG_STR=\"abracad\"\n"
  40                       "CONFIG_MISSING=0",
  41                .data = {
  42                        .bpf_syscall = false,
  43                        .tristate_val = TRI_MODULE,
  44                        .bool_val = true,
  45                        .char_val = 100,
  46                        .ushort_val = 30000,
  47                        .int_val = 123456,
  48                        .ulong_val = 0xDEADBEEFC0DE,
  49                        .str_val = "abracad",
  50                },
  51        },
  52        /* TRISTATE */
  53        { .name = "tristate (y)", .cfg = CFG"CONFIG_TRISTATE=y\n",
  54          .data = { .tristate_val = TRI_YES } },
  55        { .name = "tristate (n)", .cfg = CFG"CONFIG_TRISTATE=n\n",
  56          .data = { .tristate_val = TRI_NO } },
  57        { .name = "tristate (m)", .cfg = CFG"CONFIG_TRISTATE=m\n",
  58          .data = { .tristate_val = TRI_MODULE } },
  59        { .name = "tristate (int)", .fails = 1, .cfg = CFG"CONFIG_TRISTATE=1" },
  60        { .name = "tristate (bad)", .fails = 1, .cfg = CFG"CONFIG_TRISTATE=M" },
  61        /* BOOL */
  62        { .name = "bool (y)", .cfg = CFG"CONFIG_BOOL=y\n",
  63          .data = { .bool_val = true } },
  64        { .name = "bool (n)", .cfg = CFG"CONFIG_BOOL=n\n",
  65          .data = { .bool_val = false } },
  66        { .name = "bool (tristate)", .fails = 1, .cfg = CFG"CONFIG_BOOL=m" },
  67        { .name = "bool (int)", .fails = 1, .cfg = CFG"CONFIG_BOOL=1" },
  68        /* CHAR */
  69        { .name = "char (tristate)", .cfg = CFG"CONFIG_CHAR=m\n",
  70          .data = { .char_val = 'm' } },
  71        { .name = "char (bad)", .fails = 1, .cfg = CFG"CONFIG_CHAR=q\n" },
  72        { .name = "char (empty)", .fails = 1, .cfg = CFG"CONFIG_CHAR=\n" },
  73        { .name = "char (str)", .fails = 1, .cfg = CFG"CONFIG_CHAR=\"y\"\n" },
  74        /* STRING */
  75        { .name = "str (empty)", .cfg = CFG"CONFIG_STR=\"\"\n",
  76          .data = { .str_val = "\0\0\0\0\0\0\0" } },
  77        { .name = "str (padded)", .cfg = CFG"CONFIG_STR=\"abra\"\n",
  78          .data = { .str_val = "abra\0\0\0" } },
  79        { .name = "str (too long)", .cfg = CFG"CONFIG_STR=\"abracada\"\n",
  80          .data = { .str_val = "abracad" } },
  81        { .name = "str (no value)", .fails = 1, .cfg = CFG"CONFIG_STR=\n" },
  82        { .name = "str (bad value)", .fails = 1, .cfg = CFG"CONFIG_STR=bla\n" },
  83        /* INTEGERS */
  84        {
  85                .name = "integer forms",
  86                .cfg = CFG
  87                       "CONFIG_CHAR=0xA\n"
  88                       "CONFIG_USHORT=0462\n"
  89                       "CONFIG_INT=-100\n"
  90                       "CONFIG_ULONG=+1000000000000",
  91                .data = {
  92                        .char_val = 0xA,
  93                        .ushort_val = 0462,
  94                        .int_val = -100,
  95                        .ulong_val = 1000000000000,
  96                },
  97        },
  98        { .name = "int (bad)", .fails = 1, .cfg = CFG"CONFIG_INT=abc" },
  99        { .name = "int (str)", .fails = 1, .cfg = CFG"CONFIG_INT=\"abc\"" },
 100        { .name = "int (empty)", .fails = 1, .cfg = CFG"CONFIG_INT=" },
 101        { .name = "int (mixed)", .fails = 1, .cfg = CFG"CONFIG_INT=123abc" },
 102        { .name = "int (max)", .cfg = CFG"CONFIG_INT=2147483647",
 103          .data = { .int_val = 2147483647 } },
 104        { .name = "int (min)", .cfg = CFG"CONFIG_INT=-2147483648",
 105          .data = { .int_val = -2147483648 } },
 106        { .name = "int (max+1)", .fails = 1, .cfg = CFG"CONFIG_INT=2147483648" },
 107        { .name = "int (min-1)", .fails = 1, .cfg = CFG"CONFIG_INT=-2147483649" },
 108        { .name = "ushort (max)", .cfg = CFG"CONFIG_USHORT=65535",
 109          .data = { .ushort_val = 65535 } },
 110        { .name = "ushort (min)", .cfg = CFG"CONFIG_USHORT=0",
 111          .data = { .ushort_val = 0 } },
 112        { .name = "ushort (max+1)", .fails = 1, .cfg = CFG"CONFIG_USHORT=65536" },
 113        { .name = "ushort (min-1)", .fails = 1, .cfg = CFG"CONFIG_USHORT=-1" },
 114        { .name = "u64 (max)", .cfg = CFG"CONFIG_ULONG=0xffffffffffffffff",
 115          .data = { .ulong_val = 0xffffffffffffffff } },
 116        { .name = "u64 (min)", .cfg = CFG"CONFIG_ULONG=0",
 117          .data = { .ulong_val = 0 } },
 118        { .name = "u64 (max+1)", .fails = 1, .cfg = CFG"CONFIG_ULONG=0x10000000000000000" },
 119};
 120
 121void test_core_extern(void)
 122{
 123        const uint32_t kern_ver = get_kernel_version();
 124        int err, duration = 0, i, j;
 125        struct test_core_extern *skel = NULL;
 126        uint64_t *got, *exp;
 127        int n = sizeof(*skel->data) / sizeof(uint64_t);
 128
 129        for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
 130                struct test_case *t = &test_cases[i];
 131                DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
 132                        .kconfig = t->cfg,
 133                );
 134
 135                if (!test__start_subtest(t->name))
 136                        continue;
 137
 138                skel = test_core_extern__open_opts(&opts);
 139                if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
 140                        goto cleanup;
 141                err = test_core_extern__load(skel);
 142                if (t->fails) {
 143                        CHECK(!err, "skel_load",
 144                              "shouldn't succeed open/load of skeleton\n");
 145                        goto cleanup;
 146                } else if (CHECK(err, "skel_load",
 147                                 "failed to open/load skeleton\n")) {
 148                        goto cleanup;
 149                }
 150                err = test_core_extern__attach(skel);
 151                if (CHECK(err, "attach_raw_tp", "failed attach: %d\n", err))
 152                        goto cleanup;
 153
 154                usleep(1);
 155
 156                t->data.kern_ver = kern_ver;
 157                t->data.missing_val = 0xDEADC0DE;
 158                got = (uint64_t *)skel->data;
 159                exp = (uint64_t *)&t->data;
 160                for (j = 0; j < n; j++) {
 161                        CHECK(got[j] != exp[j], "check_res",
 162                              "result #%d: expected %llx, but got %llx\n",
 163                               j, (__u64)exp[j], (__u64)got[j]);
 164                }
 165cleanup:
 166                test_core_extern__destroy(skel);
 167                skel = NULL;
 168        }
 169}
 170