Skip to content

Commit f628fcc

Browse files
ameryhungKernel Patches Daemon
authored andcommitted
selftests/bpf: Test BPF_PROG_ASSOC_STRUCT_OPS command
Test BPF_PROG_ASSOC_STRUCT_OPS command that associates a BPF program with a struct_ops. The test follows the same logic in commit ba7000f ("selftests/bpf: Test multi_st_ops and calling kfuncs from different programs"), but instead of using map id to identify a specific struct_ops, this test uses the new BPF command to associate a struct_ops with a program. The test consists of two sets of almost identical struct_ops maps and BPF programs associated with the map. Their only difference is the unique value returned by bpf_testmod_multi_st_ops::test_1(). The test first loads the programs and associates them with struct_ops maps. Then, it exercises the BPF programs. They will in turn call kfunc bpf_kfunc_multi_st_ops_test_1_prog_arg() to trigger test_1() of the associated struct_ops map, and then check if the right unique value is returned. Signed-off-by: Amery Hung <[email protected]>
1 parent 76f615e commit f628fcc

File tree

4 files changed

+195
-0
lines changed

4 files changed

+195
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <test_progs.h>
4+
#include "struct_ops_assoc.skel.h"
5+
6+
static void test_st_ops_assoc(void)
7+
{
8+
struct struct_ops_assoc *skel = NULL;
9+
int err, pid;
10+
11+
skel = struct_ops_assoc__open_and_load();
12+
if (!ASSERT_OK_PTR(skel, "struct_ops_assoc__open"))
13+
goto out;
14+
15+
/* cannot explicitly associate struct_ops program */
16+
err = bpf_program__assoc_struct_ops(skel->progs.test_1_a,
17+
skel->maps.st_ops_map_a, NULL);
18+
ASSERT_ERR(err, "bpf_program__assoc_struct_ops");
19+
20+
err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog_a,
21+
skel->maps.st_ops_map_a, NULL);
22+
ASSERT_OK(err, "bpf_program__assoc_struct_ops");
23+
24+
err = bpf_program__assoc_struct_ops(skel->progs.sys_enter_prog_a,
25+
skel->maps.st_ops_map_a, NULL);
26+
ASSERT_OK(err, "bpf_program__assoc_struct_ops");
27+
28+
err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog_b,
29+
skel->maps.st_ops_map_b, NULL);
30+
ASSERT_OK(err, "bpf_program__assoc_struct_ops");
31+
32+
err = bpf_program__assoc_struct_ops(skel->progs.sys_enter_prog_b,
33+
skel->maps.st_ops_map_b, NULL);
34+
ASSERT_OK(err, "bpf_program__assoc_struct_ops");
35+
36+
/* sys_enter_prog_a already associated with map_a */
37+
err = bpf_program__assoc_struct_ops(skel->progs.sys_enter_prog_a,
38+
skel->maps.st_ops_map_b, NULL);
39+
ASSERT_ERR(err, "bpf_program__assoc_struct_ops");
40+
41+
err = struct_ops_assoc__attach(skel);
42+
if (!ASSERT_OK(err, "struct_ops_assoc__attach"))
43+
goto out;
44+
45+
/* run tracing prog that calls .test_1 and checks return */
46+
pid = getpid();
47+
skel->bss->test_pid = pid;
48+
sys_gettid();
49+
skel->bss->test_pid = 0;
50+
51+
ASSERT_EQ(skel->bss->test_err_a, 0, "skel->bss->test_err_a");
52+
ASSERT_EQ(skel->bss->test_err_b, 0, "skel->bss->test_err_b");
53+
54+
/* run syscall_prog that calls .test_1 and checks return */
55+
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog_a), NULL);
56+
ASSERT_OK(err, "bpf_prog_test_run_opts");
57+
58+
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog_b), NULL);
59+
ASSERT_OK(err, "bpf_prog_test_run_opts");
60+
61+
ASSERT_EQ(skel->bss->test_err_a, 0, "skel->bss->test_err_a");
62+
ASSERT_EQ(skel->bss->test_err_b, 0, "skel->bss->test_err_b");
63+
64+
out:
65+
struct_ops_assoc__destroy(skel);
66+
}
67+
68+
void test_struct_ops_assoc(void)
69+
{
70+
if (test__start_subtest("st_ops_assoc"))
71+
test_st_ops_assoc();
72+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_tracing.h>
5+
#include "bpf_misc.h"
6+
#include "../test_kmods/bpf_testmod.h"
7+
#include "../test_kmods/bpf_testmod_kfunc.h"
8+
9+
char _license[] SEC("license") = "GPL";
10+
11+
int test_pid;
12+
13+
/* Programs associated with st_ops_map_a */
14+
15+
#define MAP_A_MAGIC 1234
16+
int test_err_a;
17+
18+
SEC("struct_ops")
19+
int BPF_PROG(test_1_a, struct st_ops_args *args)
20+
{
21+
return MAP_A_MAGIC;
22+
}
23+
24+
SEC("tp_btf/sys_enter")
25+
int BPF_PROG(sys_enter_prog_a, struct pt_regs *regs, long id)
26+
{
27+
struct st_ops_args args = {};
28+
struct task_struct *task;
29+
int ret;
30+
31+
task = bpf_get_current_task_btf();
32+
if (!test_pid || task->pid != test_pid)
33+
return 0;
34+
35+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(&args, NULL);
36+
if (ret != MAP_A_MAGIC)
37+
test_err_a++;
38+
39+
return 0;
40+
}
41+
42+
SEC("syscall")
43+
int syscall_prog_a(void *ctx)
44+
{
45+
struct st_ops_args args = {};
46+
int ret;
47+
48+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(&args, NULL);
49+
if (ret != MAP_A_MAGIC)
50+
test_err_a++;
51+
52+
return 0;
53+
}
54+
55+
SEC(".struct_ops.link")
56+
struct bpf_testmod_multi_st_ops st_ops_map_a = {
57+
.test_1 = (void *)test_1_a,
58+
};
59+
60+
/* Programs associated with st_ops_map_b */
61+
62+
#define MAP_B_MAGIC 5678
63+
int test_err_b;
64+
65+
SEC("struct_ops")
66+
int BPF_PROG(test_1_b, struct st_ops_args *args)
67+
{
68+
return MAP_B_MAGIC;
69+
}
70+
71+
SEC("tp_btf/sys_enter")
72+
int BPF_PROG(sys_enter_prog_b, struct pt_regs *regs, long id)
73+
{
74+
struct st_ops_args args = {};
75+
struct task_struct *task;
76+
int ret;
77+
78+
task = bpf_get_current_task_btf();
79+
if (!test_pid || task->pid != test_pid)
80+
return 0;
81+
82+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(&args, NULL);
83+
if (ret != MAP_B_MAGIC)
84+
test_err_b++;
85+
86+
return 0;
87+
}
88+
89+
SEC("syscall")
90+
int syscall_prog_b(void *ctx)
91+
{
92+
struct st_ops_args args = {};
93+
int ret;
94+
95+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(&args, NULL);
96+
if (ret != MAP_B_MAGIC)
97+
test_err_b++;
98+
99+
return 0;
100+
}
101+
102+
SEC(".struct_ops.link")
103+
struct bpf_testmod_multi_st_ops st_ops_map_b = {
104+
.test_1 = (void *)test_1_b,
105+
};

tools/testing/selftests/bpf/test_kmods/bpf_testmod.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,7 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
11081108
}
11091109

11101110
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
1111+
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_prog_arg(struct st_ops_args *args, void *aux_prog);
11111112

11121113
BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids)
11131114
BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
@@ -1150,6 +1151,7 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_epilogue, KF_TRUSTED_ARGS | KF_SLEEPABL
11501151
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_TRUSTED_ARGS | KF_SLEEPABLE)
11511152
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10, KF_TRUSTED_ARGS)
11521153
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1, KF_TRUSTED_ARGS)
1154+
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_prog_arg, KF_TRUSTED_ARGS)
11531155
BTF_KFUNCS_END(bpf_testmod_check_kfunc_ids)
11541156

11551157
static int bpf_testmod_ops_init(struct btf *btf)
@@ -1611,6 +1613,7 @@ static struct bpf_testmod_multi_st_ops *multi_st_ops_find_nolock(u32 id)
16111613
return NULL;
16121614
}
16131615

1616+
/* Call test_1() of the struct_ops map identified by the id */
16141617
int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id)
16151618
{
16161619
struct bpf_testmod_multi_st_ops *st_ops;
@@ -1626,6 +1629,20 @@ int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id)
16261629
return ret;
16271630
}
16281631

1632+
/* Call test_1() of the associated struct_ops map */
1633+
int bpf_kfunc_multi_st_ops_test_1_prog_arg(struct st_ops_args *args, void *aux__prog)
1634+
{
1635+
struct bpf_prog_aux *prog_aux = (struct bpf_prog_aux *)aux__prog;
1636+
struct bpf_testmod_multi_st_ops *st_ops;
1637+
int ret = -1;
1638+
1639+
st_ops = (struct bpf_testmod_multi_st_ops *)bpf_prog_get_assoc_struct_ops(prog_aux);
1640+
if (st_ops)
1641+
ret = st_ops->test_1(args);
1642+
1643+
return ret;
1644+
}
1645+
16291646
static int multi_st_ops_reg(void *kdata, struct bpf_link *link)
16301647
{
16311648
struct bpf_testmod_multi_st_ops *st_ops =

tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,6 @@ struct task_struct *bpf_kfunc_ret_rcu_test(void) __ksym;
162162
int *bpf_kfunc_ret_rcu_test_nostruct(int rdonly_buf_size) __ksym;
163163

164164
int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id) __ksym;
165+
int bpf_kfunc_multi_st_ops_test_1_prog_arg(struct st_ops_args *args, void *aux__prog) __ksym;
165166

166167
#endif /* _BPF_TESTMOD_KFUNC_H */

0 commit comments

Comments
 (0)