Skip to content

Commit f5da7f1

Browse files
committed
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 5937fe9 commit f5da7f1

File tree

4 files changed

+197
-0
lines changed

4 files changed

+197
-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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
11011101
}
11021102

11031103
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
1104+
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_prog_arg(struct st_ops_args *args, void *aux_prog);
11041105

11051106
BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids)
11061107
BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
@@ -1143,6 +1144,7 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_epilogue, KF_TRUSTED_ARGS | KF_SLEEPABL
11431144
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_TRUSTED_ARGS | KF_SLEEPABLE)
11441145
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10, KF_TRUSTED_ARGS)
11451146
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1, KF_TRUSTED_ARGS)
1147+
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_prog_arg, KF_TRUSTED_ARGS)
11461148
BTF_KFUNCS_END(bpf_testmod_check_kfunc_ids)
11471149

11481150
static int bpf_testmod_ops_init(struct btf *btf)
@@ -1604,6 +1606,7 @@ static struct bpf_testmod_multi_st_ops *multi_st_ops_find_nolock(u32 id)
16041606
return NULL;
16051607
}
16061608

1609+
/* Call test_1() of the struct_ops map identified by the id */
16071610
int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id)
16081611
{
16091612
struct bpf_testmod_multi_st_ops *st_ops;
@@ -1619,6 +1622,22 @@ int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id)
16191622
return ret;
16201623
}
16211624

1625+
/* Call test_1() of the associated struct_ops map */
1626+
int bpf_kfunc_multi_st_ops_test_1_prog_arg(struct st_ops_args *args, void *aux__prog)
1627+
{
1628+
struct bpf_prog_aux *prog_aux = (struct bpf_prog_aux *)aux__prog;
1629+
struct bpf_testmod_multi_st_ops *st_ops;
1630+
int ret = -1;
1631+
1632+
st_ops = (struct bpf_testmod_multi_st_ops *)bpf_prog_get_assoc_struct_ops(prog_aux);
1633+
if (st_ops) {
1634+
ret = st_ops->test_1(args);
1635+
bpf_struct_ops_put(st_ops);
1636+
}
1637+
1638+
return ret;
1639+
}
1640+
16221641
static int multi_st_ops_reg(void *kdata, struct bpf_link *link)
16231642
{
16241643
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)