0001
0002 #include <test_progs.h>
0003 #include <network_helpers.h>
0004
0005 static void test_global_data_number(struct bpf_object *obj, __u32 duration)
0006 {
0007 int i, err, map_fd;
0008 __u64 num;
0009
0010 map_fd = bpf_find_map(__func__, obj, "result_number");
0011 if (CHECK_FAIL(map_fd < 0))
0012 return;
0013
0014 struct {
0015 char *name;
0016 uint32_t key;
0017 __u64 num;
0018 } tests[] = {
0019 { "relocate .bss reference", 0, 0 },
0020 { "relocate .data reference", 1, 42 },
0021 { "relocate .rodata reference", 2, 24 },
0022 { "relocate .bss reference", 3, 0 },
0023 { "relocate .data reference", 4, 0xffeeff },
0024 { "relocate .rodata reference", 5, 0xabab },
0025 { "relocate .bss reference", 6, 1234 },
0026 { "relocate .bss reference", 7, 0 },
0027 { "relocate .rodata reference", 8, 0xab },
0028 { "relocate .rodata reference", 9, 0x1111111111111111 },
0029 { "relocate .rodata reference", 10, ~0 },
0030 };
0031
0032 for (i = 0; i < ARRAY_SIZE(tests); i++) {
0033 err = bpf_map_lookup_elem(map_fd, &tests[i].key, &num);
0034 CHECK(err || num != tests[i].num, tests[i].name,
0035 "err %d result %llx expected %llx\n",
0036 err, num, tests[i].num);
0037 }
0038 }
0039
0040 static void test_global_data_string(struct bpf_object *obj, __u32 duration)
0041 {
0042 int i, err, map_fd;
0043 char str[32];
0044
0045 map_fd = bpf_find_map(__func__, obj, "result_string");
0046 if (CHECK_FAIL(map_fd < 0))
0047 return;
0048
0049 struct {
0050 char *name;
0051 uint32_t key;
0052 char str[32];
0053 } tests[] = {
0054 { "relocate .rodata reference", 0, "abcdefghijklmnopqrstuvwxyz" },
0055 { "relocate .data reference", 1, "abcdefghijklmnopqrstuvwxyz" },
0056 { "relocate .bss reference", 2, "" },
0057 { "relocate .data reference", 3, "abcdexghijklmnopqrstuvwxyz" },
0058 { "relocate .bss reference", 4, "\0\0hello" },
0059 };
0060
0061 for (i = 0; i < ARRAY_SIZE(tests); i++) {
0062 err = bpf_map_lookup_elem(map_fd, &tests[i].key, str);
0063 CHECK(err || memcmp(str, tests[i].str, sizeof(str)),
0064 tests[i].name, "err %d result \'%s\' expected \'%s\'\n",
0065 err, str, tests[i].str);
0066 }
0067 }
0068
0069 struct foo {
0070 __u8 a;
0071 __u32 b;
0072 __u64 c;
0073 };
0074
0075 static void test_global_data_struct(struct bpf_object *obj, __u32 duration)
0076 {
0077 int i, err, map_fd;
0078 struct foo val;
0079
0080 map_fd = bpf_find_map(__func__, obj, "result_struct");
0081 if (CHECK_FAIL(map_fd < 0))
0082 return;
0083
0084 struct {
0085 char *name;
0086 uint32_t key;
0087 struct foo val;
0088 } tests[] = {
0089 { "relocate .rodata reference", 0, { 42, 0xfefeefef, 0x1111111111111111ULL, } },
0090 { "relocate .bss reference", 1, { } },
0091 { "relocate .rodata reference", 2, { } },
0092 { "relocate .data reference", 3, { 41, 0xeeeeefef, 0x2111111111111111ULL, } },
0093 };
0094
0095 for (i = 0; i < ARRAY_SIZE(tests); i++) {
0096 err = bpf_map_lookup_elem(map_fd, &tests[i].key, &val);
0097 CHECK(err || memcmp(&val, &tests[i].val, sizeof(val)),
0098 tests[i].name, "err %d result { %u, %u, %llu } expected { %u, %u, %llu }\n",
0099 err, val.a, val.b, val.c, tests[i].val.a, tests[i].val.b, tests[i].val.c);
0100 }
0101 }
0102
0103 static void test_global_data_rdonly(struct bpf_object *obj, __u32 duration)
0104 {
0105 int err = -ENOMEM, map_fd, zero = 0;
0106 struct bpf_map *map, *map2;
0107 __u8 *buff;
0108
0109 map = bpf_object__find_map_by_name(obj, "test_glo.rodata");
0110 if (!ASSERT_OK_PTR(map, "map"))
0111 return;
0112 if (!ASSERT_TRUE(bpf_map__is_internal(map), "is_internal"))
0113 return;
0114
0115
0116 map2 = bpf_object__find_map_by_name(obj, ".rodata");
0117 if (!ASSERT_EQ(map, map2, "same_maps"))
0118 return;
0119
0120 map_fd = bpf_map__fd(map);
0121 if (CHECK_FAIL(map_fd < 0))
0122 return;
0123
0124 buff = malloc(bpf_map__value_size(map));
0125 if (buff)
0126 err = bpf_map_update_elem(map_fd, &zero, buff, 0);
0127 free(buff);
0128 CHECK(!err || errno != EPERM, "test .rodata read-only map",
0129 "err %d errno %d\n", err, errno);
0130 }
0131
0132 void test_global_data(void)
0133 {
0134 const char *file = "./test_global_data.o";
0135 struct bpf_object *obj;
0136 int err, prog_fd;
0137 LIBBPF_OPTS(bpf_test_run_opts, topts,
0138 .data_in = &pkt_v4,
0139 .data_size_in = sizeof(pkt_v4),
0140 .repeat = 1,
0141 );
0142
0143 err = bpf_prog_test_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
0144 if (!ASSERT_OK(err, "load program"))
0145 return;
0146
0147 err = bpf_prog_test_run_opts(prog_fd, &topts);
0148 ASSERT_OK(err, "pass global data run err");
0149 ASSERT_OK(topts.retval, "pass global data run retval");
0150
0151 test_global_data_number(obj, topts.duration);
0152 test_global_data_string(obj, topts.duration);
0153 test_global_data_struct(obj, topts.duration);
0154 test_global_data_rdonly(obj, topts.duration);
0155
0156 bpf_object__close(obj);
0157 }