Skip to content

Commit 573b920

Browse files
committed
selftests/bpf: add selftests for indirect jumps
Add selftests for indirect jumps. All the indirect jumps are generated from C switch statements, so, if compiled by a compiler which doesn't support indirect jumps, then should pass as well. Signed-off-by: Anton Protopopov <[email protected]>
1 parent a08f759 commit 573b920

File tree

3 files changed

+511
-1
lines changed

3 files changed

+511
-1
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,9 @@ BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
453453
-I$(abspath $(OUTPUT)/../usr/include) \
454454
-std=gnu11 \
455455
-fno-strict-aliasing \
456-
-Wno-compare-distinct-pointer-types
456+
-Wno-compare-distinct-pointer-types \
457+
-Wno-initializer-overrides \
458+
#
457459
# TODO: enable me -Wsign-compare
458460

459461
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <test_progs.h>
4+
5+
#include <linux/if_ether.h>
6+
#include <linux/in.h>
7+
#include <linux/ip.h>
8+
#include <linux/ipv6.h>
9+
#include <linux/in6.h>
10+
#include <linux/udp.h>
11+
#include <linux/tcp.h>
12+
13+
#include <sys/syscall.h>
14+
#include <bpf/bpf.h>
15+
16+
#include "bpf_goto_x.skel.h"
17+
18+
static void __test_run(struct bpf_program *prog, void *ctx_in, size_t ctx_size_in)
19+
{
20+
LIBBPF_OPTS(bpf_test_run_opts, topts,
21+
.ctx_in = ctx_in,
22+
.ctx_size_in = ctx_size_in,
23+
);
24+
int err, prog_fd;
25+
26+
prog_fd = bpf_program__fd(prog);
27+
err = bpf_prog_test_run_opts(prog_fd, &topts);
28+
ASSERT_OK(err, "test_run_opts err");
29+
}
30+
31+
static void check_simple(struct bpf_goto_x *skel,
32+
struct bpf_program *prog,
33+
__u64 ctx_in,
34+
__u64 expected)
35+
{
36+
skel->bss->ret_user = 0;
37+
38+
__test_run(prog, &ctx_in, sizeof(ctx_in));
39+
40+
if (!ASSERT_EQ(skel->bss->ret_user, expected, "skel->bss->ret_user"))
41+
return;
42+
}
43+
44+
static void check_simple_fentry(struct bpf_goto_x *skel,
45+
struct bpf_program *prog,
46+
__u64 ctx_in,
47+
__u64 expected)
48+
{
49+
skel->bss->in_user = ctx_in;
50+
skel->bss->ret_user = 0;
51+
52+
/* trigger */
53+
usleep(1);
54+
55+
if (!ASSERT_EQ(skel->bss->ret_user, expected, "skel->bss->ret_user"))
56+
return;
57+
}
58+
59+
static void check_goto_x_skel(struct bpf_goto_x *skel)
60+
{
61+
int i;
62+
__u64 in[] = {0, 1, 2, 3, 4, 5, 77};
63+
__u64 out[] = {2, 3, 4, 5, 7, 19, 19};
64+
__u64 out2[] = {103, 104, 107, 205, 115, 1019, 1019};
65+
__u64 in3[] = {0, 11, 27, 31, 22, 45, 99};
66+
__u64 out3[] = {2, 3, 4, 5, 19, 19, 19};
67+
__u64 in4[] = {0, 1, 2, 3, 4, 5, 77};
68+
__u64 out4[] = {12, 15, 7 , 15, 12, 15, 15};
69+
70+
for (i = 0; i < ARRAY_SIZE(in); i++)
71+
check_simple(skel, skel->progs.simple_test, in[i], out[i]);
72+
73+
for (i = 0; i < ARRAY_SIZE(in); i++)
74+
check_simple(skel, skel->progs.simple_test2, in[i], out[i]);
75+
76+
for (i = 0; i < ARRAY_SIZE(in); i++)
77+
check_simple(skel, skel->progs.two_switches, in[i], out2[i]);
78+
79+
for (i = 0; i < ARRAY_SIZE(in); i++)
80+
check_simple(skel, skel->progs.big_jump_table, in3[i], out3[i]);
81+
82+
for (i = 0; i < ARRAY_SIZE(in); i++)
83+
check_simple(skel, skel->progs.one_jump_two_maps, in4[i], out4[i]);
84+
85+
for (i = 0; i < ARRAY_SIZE(in); i++)
86+
check_simple(skel, skel->progs.use_static_global1, in[i], out[i]);
87+
88+
for (i = 0; i < ARRAY_SIZE(in); i++)
89+
check_simple(skel, skel->progs.use_static_global2, in[i], out[i]);
90+
91+
for (i = 0; i < ARRAY_SIZE(in); i++)
92+
check_simple(skel, skel->progs.use_nonstatic_global1, in[i], out[i]);
93+
94+
for (i = 0; i < ARRAY_SIZE(in); i++)
95+
check_simple(skel, skel->progs.use_nonstatic_global2, in[i], out[i]);
96+
97+
bpf_program__attach(skel->progs.simple_test_other_sec);
98+
for (i = 0; i < ARRAY_SIZE(in); i++)
99+
check_simple_fentry(skel, skel->progs.simple_test_other_sec, in[i], out[i]);
100+
101+
bpf_program__attach(skel->progs.use_static_global_other_sec);
102+
for (i = 0; i < ARRAY_SIZE(in); i++)
103+
check_simple_fentry(skel, skel->progs.use_static_global_other_sec, in[i], out[i]);
104+
105+
bpf_program__attach(skel->progs.use_nonstatic_global_other_sec);
106+
for (i = 0; i < ARRAY_SIZE(in); i++)
107+
check_simple_fentry(skel, skel->progs.use_nonstatic_global_other_sec, in[i], out[i]);
108+
}
109+
110+
void goto_x_skel(void)
111+
{
112+
struct bpf_goto_x *skel;
113+
int ret;
114+
115+
skel = bpf_goto_x__open();
116+
if (!ASSERT_NEQ(skel, NULL, "bpf_goto_x__open"))
117+
return;
118+
119+
ret = bpf_goto_x__load(skel);
120+
if (!ASSERT_OK(ret, "bpf_goto_x__load"))
121+
return;
122+
123+
check_goto_x_skel(skel);
124+
125+
bpf_goto_x__destroy(skel);
126+
}
127+
128+
void test_bpf_goto_x(void)
129+
{
130+
if (test__start_subtest("goto_x_skel"))
131+
goto_x_skel();
132+
}

0 commit comments

Comments
 (0)