1*ac4d838cSAnton Protopopov // SPDX-License-Identifier: GPL-2.0 2*ac4d838cSAnton Protopopov 3*ac4d838cSAnton Protopopov #include <test_progs.h> 4*ac4d838cSAnton Protopopov 5*ac4d838cSAnton Protopopov #include <linux/if_ether.h> 6*ac4d838cSAnton Protopopov #include <linux/in.h> 7*ac4d838cSAnton Protopopov #include <linux/ip.h> 8*ac4d838cSAnton Protopopov #include <linux/ipv6.h> 9*ac4d838cSAnton Protopopov #include <linux/in6.h> 10*ac4d838cSAnton Protopopov #include <linux/udp.h> 11*ac4d838cSAnton Protopopov #include <linux/tcp.h> 12*ac4d838cSAnton Protopopov 13*ac4d838cSAnton Protopopov #include <sys/syscall.h> 14*ac4d838cSAnton Protopopov #include <bpf/bpf.h> 15*ac4d838cSAnton Protopopov 16*ac4d838cSAnton Protopopov #include "bpf_gotox.skel.h" 17*ac4d838cSAnton Protopopov 18*ac4d838cSAnton Protopopov static void __test_run(struct bpf_program *prog, void *ctx_in, size_t ctx_size_in) 19*ac4d838cSAnton Protopopov { 20*ac4d838cSAnton Protopopov LIBBPF_OPTS(bpf_test_run_opts, topts, 21*ac4d838cSAnton Protopopov .ctx_in = ctx_in, 22*ac4d838cSAnton Protopopov .ctx_size_in = ctx_size_in, 23*ac4d838cSAnton Protopopov ); 24*ac4d838cSAnton Protopopov int err, prog_fd; 25*ac4d838cSAnton Protopopov 26*ac4d838cSAnton Protopopov prog_fd = bpf_program__fd(prog); 27*ac4d838cSAnton Protopopov err = bpf_prog_test_run_opts(prog_fd, &topts); 28*ac4d838cSAnton Protopopov ASSERT_OK(err, "test_run_opts err"); 29*ac4d838cSAnton Protopopov } 30*ac4d838cSAnton Protopopov 31*ac4d838cSAnton Protopopov static void __subtest(struct bpf_gotox *skel, void (*check)(struct bpf_gotox *)) 32*ac4d838cSAnton Protopopov { 33*ac4d838cSAnton Protopopov if (skel->data->skip) 34*ac4d838cSAnton Protopopov test__skip(); 35*ac4d838cSAnton Protopopov else 36*ac4d838cSAnton Protopopov check(skel); 37*ac4d838cSAnton Protopopov } 38*ac4d838cSAnton Protopopov 39*ac4d838cSAnton Protopopov static void check_simple(struct bpf_gotox *skel, 40*ac4d838cSAnton Protopopov struct bpf_program *prog, 41*ac4d838cSAnton Protopopov __u64 ctx_in, 42*ac4d838cSAnton Protopopov __u64 expected) 43*ac4d838cSAnton Protopopov { 44*ac4d838cSAnton Protopopov skel->bss->ret_user = 0; 45*ac4d838cSAnton Protopopov 46*ac4d838cSAnton Protopopov __test_run(prog, &ctx_in, sizeof(ctx_in)); 47*ac4d838cSAnton Protopopov 48*ac4d838cSAnton Protopopov if (!ASSERT_EQ(skel->bss->ret_user, expected, "skel->bss->ret_user")) 49*ac4d838cSAnton Protopopov return; 50*ac4d838cSAnton Protopopov } 51*ac4d838cSAnton Protopopov 52*ac4d838cSAnton Protopopov static void check_simple_fentry(struct bpf_gotox *skel, 53*ac4d838cSAnton Protopopov struct bpf_program *prog, 54*ac4d838cSAnton Protopopov __u64 ctx_in, 55*ac4d838cSAnton Protopopov __u64 expected) 56*ac4d838cSAnton Protopopov { 57*ac4d838cSAnton Protopopov skel->bss->in_user = ctx_in; 58*ac4d838cSAnton Protopopov skel->bss->ret_user = 0; 59*ac4d838cSAnton Protopopov 60*ac4d838cSAnton Protopopov /* trigger */ 61*ac4d838cSAnton Protopopov usleep(1); 62*ac4d838cSAnton Protopopov 63*ac4d838cSAnton Protopopov if (!ASSERT_EQ(skel->bss->ret_user, expected, "skel->bss->ret_user")) 64*ac4d838cSAnton Protopopov return; 65*ac4d838cSAnton Protopopov } 66*ac4d838cSAnton Protopopov 67*ac4d838cSAnton Protopopov /* validate that for two loads of the same jump table libbpf generates only one map */ 68*ac4d838cSAnton Protopopov static void check_one_map_two_jumps(struct bpf_gotox *skel) 69*ac4d838cSAnton Protopopov { 70*ac4d838cSAnton Protopopov struct bpf_prog_info prog_info; 71*ac4d838cSAnton Protopopov struct bpf_map_info map_info; 72*ac4d838cSAnton Protopopov __u32 len; 73*ac4d838cSAnton Protopopov __u32 map_ids[16]; 74*ac4d838cSAnton Protopopov int prog_fd, map_fd; 75*ac4d838cSAnton Protopopov int ret; 76*ac4d838cSAnton Protopopov int i; 77*ac4d838cSAnton Protopopov bool seen = false; 78*ac4d838cSAnton Protopopov 79*ac4d838cSAnton Protopopov memset(&prog_info, 0, sizeof(prog_info)); 80*ac4d838cSAnton Protopopov prog_info.map_ids = (long)map_ids; 81*ac4d838cSAnton Protopopov prog_info.nr_map_ids = ARRAY_SIZE(map_ids); 82*ac4d838cSAnton Protopopov prog_fd = bpf_program__fd(skel->progs.one_map_two_jumps); 83*ac4d838cSAnton Protopopov if (!ASSERT_GE(prog_fd, 0, "bpf_program__fd(one_map_two_jumps)")) 84*ac4d838cSAnton Protopopov return; 85*ac4d838cSAnton Protopopov 86*ac4d838cSAnton Protopopov len = sizeof(prog_info); 87*ac4d838cSAnton Protopopov ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &len); 88*ac4d838cSAnton Protopopov if (!ASSERT_OK(ret, "bpf_obj_get_info_by_fd(prog_fd)")) 89*ac4d838cSAnton Protopopov return; 90*ac4d838cSAnton Protopopov 91*ac4d838cSAnton Protopopov for (i = 0; i < prog_info.nr_map_ids; i++) { 92*ac4d838cSAnton Protopopov map_fd = bpf_map_get_fd_by_id(map_ids[i]); 93*ac4d838cSAnton Protopopov if (!ASSERT_GE(map_fd, 0, "bpf_map_get_fd_by_id")) 94*ac4d838cSAnton Protopopov return; 95*ac4d838cSAnton Protopopov 96*ac4d838cSAnton Protopopov len = sizeof(map_info); 97*ac4d838cSAnton Protopopov memset(&map_info, 0, len); 98*ac4d838cSAnton Protopopov ret = bpf_obj_get_info_by_fd(map_fd, &map_info, &len); 99*ac4d838cSAnton Protopopov if (!ASSERT_OK(ret, "bpf_obj_get_info_by_fd(map_fd)")) { 100*ac4d838cSAnton Protopopov close(map_fd); 101*ac4d838cSAnton Protopopov return; 102*ac4d838cSAnton Protopopov } 103*ac4d838cSAnton Protopopov 104*ac4d838cSAnton Protopopov if (map_info.type == BPF_MAP_TYPE_INSN_ARRAY) { 105*ac4d838cSAnton Protopopov if (!ASSERT_EQ(seen, false, "more than one INSN_ARRAY map")) { 106*ac4d838cSAnton Protopopov close(map_fd); 107*ac4d838cSAnton Protopopov return; 108*ac4d838cSAnton Protopopov } 109*ac4d838cSAnton Protopopov seen = true; 110*ac4d838cSAnton Protopopov } 111*ac4d838cSAnton Protopopov close(map_fd); 112*ac4d838cSAnton Protopopov } 113*ac4d838cSAnton Protopopov 114*ac4d838cSAnton Protopopov ASSERT_EQ(seen, true, "no INSN_ARRAY map"); 115*ac4d838cSAnton Protopopov } 116*ac4d838cSAnton Protopopov 117*ac4d838cSAnton Protopopov static void check_one_switch(struct bpf_gotox *skel) 118*ac4d838cSAnton Protopopov { 119*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 120*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 121*ac4d838cSAnton Protopopov int i; 122*ac4d838cSAnton Protopopov 123*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 124*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.one_switch, in[i], out[i]); 125*ac4d838cSAnton Protopopov } 126*ac4d838cSAnton Protopopov 127*ac4d838cSAnton Protopopov static void check_one_switch_non_zero_sec_off(struct bpf_gotox *skel) 128*ac4d838cSAnton Protopopov { 129*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 130*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 131*ac4d838cSAnton Protopopov int i; 132*ac4d838cSAnton Protopopov 133*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 134*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.one_switch_non_zero_sec_off, in[i], out[i]); 135*ac4d838cSAnton Protopopov } 136*ac4d838cSAnton Protopopov 137*ac4d838cSAnton Protopopov static void check_two_switches(struct bpf_gotox *skel) 138*ac4d838cSAnton Protopopov { 139*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 140*ac4d838cSAnton Protopopov __u64 out[] = {103, 104, 107, 205, 115, 1019, 1019}; 141*ac4d838cSAnton Protopopov int i; 142*ac4d838cSAnton Protopopov 143*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 144*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.two_switches, in[i], out[i]); 145*ac4d838cSAnton Protopopov } 146*ac4d838cSAnton Protopopov 147*ac4d838cSAnton Protopopov static void check_big_jump_table(struct bpf_gotox *skel) 148*ac4d838cSAnton Protopopov { 149*ac4d838cSAnton Protopopov __u64 in[] = {0, 11, 27, 31, 22, 45, 99}; 150*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 19, 19, 19}; 151*ac4d838cSAnton Protopopov int i; 152*ac4d838cSAnton Protopopov 153*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 154*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.big_jump_table, in[i], out[i]); 155*ac4d838cSAnton Protopopov } 156*ac4d838cSAnton Protopopov 157*ac4d838cSAnton Protopopov static void check_one_jump_two_maps(struct bpf_gotox *skel) 158*ac4d838cSAnton Protopopov { 159*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 160*ac4d838cSAnton Protopopov __u64 out[] = {12, 15, 7 , 15, 12, 15, 15}; 161*ac4d838cSAnton Protopopov int i; 162*ac4d838cSAnton Protopopov 163*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 164*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.one_jump_two_maps, in[i], out[i]); 165*ac4d838cSAnton Protopopov } 166*ac4d838cSAnton Protopopov 167*ac4d838cSAnton Protopopov static void check_static_global(struct bpf_gotox *skel) 168*ac4d838cSAnton Protopopov { 169*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 170*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 171*ac4d838cSAnton Protopopov int i; 172*ac4d838cSAnton Protopopov 173*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 174*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.use_static_global1, in[i], out[i]); 175*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 176*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.use_static_global2, in[i], out[i]); 177*ac4d838cSAnton Protopopov } 178*ac4d838cSAnton Protopopov 179*ac4d838cSAnton Protopopov static void check_nonstatic_global(struct bpf_gotox *skel) 180*ac4d838cSAnton Protopopov { 181*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 182*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 183*ac4d838cSAnton Protopopov int i; 184*ac4d838cSAnton Protopopov 185*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 186*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.use_nonstatic_global1, in[i], out[i]); 187*ac4d838cSAnton Protopopov 188*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 189*ac4d838cSAnton Protopopov check_simple(skel, skel->progs.use_nonstatic_global2, in[i], out[i]); 190*ac4d838cSAnton Protopopov } 191*ac4d838cSAnton Protopopov 192*ac4d838cSAnton Protopopov static void check_other_sec(struct bpf_gotox *skel) 193*ac4d838cSAnton Protopopov { 194*ac4d838cSAnton Protopopov struct bpf_link *link; 195*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 196*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 197*ac4d838cSAnton Protopopov int i; 198*ac4d838cSAnton Protopopov 199*ac4d838cSAnton Protopopov link = bpf_program__attach(skel->progs.simple_test_other_sec); 200*ac4d838cSAnton Protopopov if (!ASSERT_OK_PTR(link, "link")) 201*ac4d838cSAnton Protopopov return; 202*ac4d838cSAnton Protopopov 203*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 204*ac4d838cSAnton Protopopov check_simple_fentry(skel, skel->progs.simple_test_other_sec, in[i], out[i]); 205*ac4d838cSAnton Protopopov 206*ac4d838cSAnton Protopopov bpf_link__destroy(link); 207*ac4d838cSAnton Protopopov } 208*ac4d838cSAnton Protopopov 209*ac4d838cSAnton Protopopov static void check_static_global_other_sec(struct bpf_gotox *skel) 210*ac4d838cSAnton Protopopov { 211*ac4d838cSAnton Protopopov struct bpf_link *link; 212*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 213*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 214*ac4d838cSAnton Protopopov int i; 215*ac4d838cSAnton Protopopov 216*ac4d838cSAnton Protopopov link = bpf_program__attach(skel->progs.use_static_global_other_sec); 217*ac4d838cSAnton Protopopov if (!ASSERT_OK_PTR(link, "link")) 218*ac4d838cSAnton Protopopov return; 219*ac4d838cSAnton Protopopov 220*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 221*ac4d838cSAnton Protopopov check_simple_fentry(skel, skel->progs.use_static_global_other_sec, in[i], out[i]); 222*ac4d838cSAnton Protopopov 223*ac4d838cSAnton Protopopov bpf_link__destroy(link); 224*ac4d838cSAnton Protopopov } 225*ac4d838cSAnton Protopopov 226*ac4d838cSAnton Protopopov static void check_nonstatic_global_other_sec(struct bpf_gotox *skel) 227*ac4d838cSAnton Protopopov { 228*ac4d838cSAnton Protopopov struct bpf_link *link; 229*ac4d838cSAnton Protopopov __u64 in[] = {0, 1, 2, 3, 4, 5, 77}; 230*ac4d838cSAnton Protopopov __u64 out[] = {2, 3, 4, 5, 7, 19, 19}; 231*ac4d838cSAnton Protopopov int i; 232*ac4d838cSAnton Protopopov 233*ac4d838cSAnton Protopopov link = bpf_program__attach(skel->progs.use_nonstatic_global_other_sec); 234*ac4d838cSAnton Protopopov if (!ASSERT_OK_PTR(link, "link")) 235*ac4d838cSAnton Protopopov return; 236*ac4d838cSAnton Protopopov 237*ac4d838cSAnton Protopopov for (i = 0; i < ARRAY_SIZE(in); i++) 238*ac4d838cSAnton Protopopov check_simple_fentry(skel, skel->progs.use_nonstatic_global_other_sec, in[i], out[i]); 239*ac4d838cSAnton Protopopov 240*ac4d838cSAnton Protopopov bpf_link__destroy(link); 241*ac4d838cSAnton Protopopov } 242*ac4d838cSAnton Protopopov 243*ac4d838cSAnton Protopopov void test_bpf_gotox(void) 244*ac4d838cSAnton Protopopov { 245*ac4d838cSAnton Protopopov struct bpf_gotox *skel; 246*ac4d838cSAnton Protopopov int ret; 247*ac4d838cSAnton Protopopov 248*ac4d838cSAnton Protopopov skel = bpf_gotox__open(); 249*ac4d838cSAnton Protopopov if (!ASSERT_NEQ(skel, NULL, "bpf_gotox__open")) 250*ac4d838cSAnton Protopopov return; 251*ac4d838cSAnton Protopopov 252*ac4d838cSAnton Protopopov ret = bpf_gotox__load(skel); 253*ac4d838cSAnton Protopopov if (!ASSERT_OK(ret, "bpf_gotox__load")) 254*ac4d838cSAnton Protopopov return; 255*ac4d838cSAnton Protopopov 256*ac4d838cSAnton Protopopov skel->bss->pid = getpid(); 257*ac4d838cSAnton Protopopov 258*ac4d838cSAnton Protopopov if (test__start_subtest("one-switch")) 259*ac4d838cSAnton Protopopov __subtest(skel, check_one_switch); 260*ac4d838cSAnton Protopopov 261*ac4d838cSAnton Protopopov if (test__start_subtest("one-switch-non-zero-sec-offset")) 262*ac4d838cSAnton Protopopov __subtest(skel, check_one_switch_non_zero_sec_off); 263*ac4d838cSAnton Protopopov 264*ac4d838cSAnton Protopopov if (test__start_subtest("two-switches")) 265*ac4d838cSAnton Protopopov __subtest(skel, check_two_switches); 266*ac4d838cSAnton Protopopov 267*ac4d838cSAnton Protopopov if (test__start_subtest("big-jump-table")) 268*ac4d838cSAnton Protopopov __subtest(skel, check_big_jump_table); 269*ac4d838cSAnton Protopopov 270*ac4d838cSAnton Protopopov if (test__start_subtest("static-global")) 271*ac4d838cSAnton Protopopov __subtest(skel, check_static_global); 272*ac4d838cSAnton Protopopov 273*ac4d838cSAnton Protopopov if (test__start_subtest("nonstatic-global")) 274*ac4d838cSAnton Protopopov __subtest(skel, check_nonstatic_global); 275*ac4d838cSAnton Protopopov 276*ac4d838cSAnton Protopopov if (test__start_subtest("other-sec")) 277*ac4d838cSAnton Protopopov __subtest(skel, check_other_sec); 278*ac4d838cSAnton Protopopov 279*ac4d838cSAnton Protopopov if (test__start_subtest("static-global-other-sec")) 280*ac4d838cSAnton Protopopov __subtest(skel, check_static_global_other_sec); 281*ac4d838cSAnton Protopopov 282*ac4d838cSAnton Protopopov if (test__start_subtest("nonstatic-global-other-sec")) 283*ac4d838cSAnton Protopopov __subtest(skel, check_nonstatic_global_other_sec); 284*ac4d838cSAnton Protopopov 285*ac4d838cSAnton Protopopov if (test__start_subtest("one-jump-two-maps")) 286*ac4d838cSAnton Protopopov __subtest(skel, check_one_jump_two_maps); 287*ac4d838cSAnton Protopopov 288*ac4d838cSAnton Protopopov if (test__start_subtest("one-map-two-jumps")) 289*ac4d838cSAnton Protopopov __subtest(skel, check_one_map_two_jumps); 290*ac4d838cSAnton Protopopov 291*ac4d838cSAnton Protopopov bpf_gotox__destroy(skel); 292*ac4d838cSAnton Protopopov } 293