Skip to content

Commit 051526a

Browse files
Tao ChenKernel Patches Daemon
Tao Chen
authored and
Kernel Patches Daemon
committed
selftests/bpf: Add libbpf_probe_bpf_kfunc API selftests
Add selftests for prog_kfunc feature probing. Thanks for Eduard providing the libbpf_probe_func_many test case. ./test_progs -t libbpf_probe_kfuncs #153 libbpf_probe_kfuncs:OK Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED ./test_progs -t libbpf_probe_kfuncs_many #154 libbpf_probe_kfuncs_many:OK Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED Cc: Tao Chen <[email protected]> Reviewed-by: Jiri Olsa <[email protected]> Co-developed-by: Eduard Zingerman <[email protected]> Signed-off-by: Eduard Zingerman <[email protected]> Signed-off-by: Tao Chen <[email protected]>
1 parent 5929a16 commit 051526a

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

tools/testing/selftests/bpf/prog_tests/libbpf_probes.c

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,176 @@ void test_libbpf_probe_helpers(void)
126126
ASSERT_EQ(res, d->supported, buf);
127127
}
128128
}
129+
130+
static int module_btf_fd(char *module)
131+
{
132+
int fd, err;
133+
__u32 id = 0, len;
134+
struct bpf_btf_info info;
135+
char name[64];
136+
137+
while (true) {
138+
err = bpf_btf_get_next_id(id, &id);
139+
if (err)
140+
return -1;
141+
142+
fd = bpf_btf_get_fd_by_id(id);
143+
if (fd < 0) {
144+
if (errno == ENOENT)
145+
continue;
146+
return -1;
147+
}
148+
len = sizeof(info);
149+
memset(&info, 0, sizeof(info));
150+
info.name = ptr_to_u64(name);
151+
info.name_len = sizeof(name);
152+
err = bpf_btf_get_info_by_fd(fd, &info, &len);
153+
if (err) {
154+
close(fd);
155+
return -1;
156+
}
157+
/* find target module BTF */
158+
if (!strcmp(name, module))
159+
break;
160+
161+
close(fd);
162+
}
163+
164+
return fd;
165+
}
166+
167+
void test_libbpf_probe_kfuncs(void)
168+
{
169+
int ret, kfunc_id, fd;
170+
char *kfunc = "bpf_cpumask_create";
171+
struct btf *vmlinux_btf = NULL;
172+
struct btf *module_btf = NULL;
173+
174+
vmlinux_btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
175+
if (!ASSERT_OK_PTR(vmlinux_btf, "btf_parse"))
176+
return;
177+
178+
kfunc_id = btf__find_by_name_kind(vmlinux_btf, kfunc, BTF_KIND_FUNC);
179+
if (!ASSERT_GT(kfunc_id, 0, kfunc))
180+
goto cleanup;
181+
182+
/* prog BPF_PROG_TYPE_SYSCALL supports kfunc bpf_cpumask_create */
183+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_SYSCALL, kfunc_id, -1, NULL);
184+
if (!ASSERT_EQ(ret, 1, "kfunc in vmlinux support"))
185+
goto cleanup;
186+
187+
/* prog BPF_PROG_TYPE_KPROBE does not support kfunc bpf_cpumask_create */
188+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_KPROBE, kfunc_id, -1, NULL);
189+
if (!ASSERT_EQ(ret, 0, "kfunc in vmlinux not suuport"))
190+
goto cleanup;
191+
192+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_KPROBE, -1, -1, NULL);
193+
if (!ASSERT_EQ(ret, 0, "invalid kfunc id:-1"))
194+
goto cleanup;
195+
196+
ret = libbpf_probe_bpf_kfunc(100000, kfunc_id, -1, NULL);
197+
if (!ASSERT_ERR(ret, "invalid prog type:100000"))
198+
goto cleanup;
199+
200+
if (!env.has_testmod)
201+
goto cleanup;
202+
203+
module_btf = btf__load_module_btf("bpf_testmod", vmlinux_btf);
204+
if (!ASSERT_OK_PTR(module_btf, "load module BTF"))
205+
goto cleanup;
206+
207+
kfunc_id = btf__find_by_name(module_btf, "bpf_kfunc_call_test1");
208+
if (!ASSERT_GT(kfunc_id, 0, "func not found"))
209+
goto cleanup;
210+
211+
fd = module_btf_fd("bpf_testmod");
212+
if (!ASSERT_GE(fd, 0, "module BTF fd"))
213+
goto cleanup;
214+
215+
/* prog BPF_PROG_TYPE_SYSCALL supports kfunc bpf_kfunc_call_test1 in bpf_testmod */
216+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_SYSCALL, kfunc_id, fd, NULL);
217+
if (!ASSERT_EQ(ret, 1, "kfunc in module BTF support"))
218+
goto cleanup_fd;
219+
220+
/* prog BPF_PROG_TYPE_KPROBE does not support kfunc bpf_kfunc_call_test1
221+
* in bpf_testmod
222+
*/
223+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_KPROBE, kfunc_id, fd, NULL);
224+
if (!ASSERT_EQ(ret, 0, "kfunc in module BTF not support"))
225+
goto cleanup_fd;
226+
227+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_SYSCALL, -1, fd, NULL);
228+
if (!ASSERT_EQ(ret, 0, "invalid kfunc id in module BTF"))
229+
goto cleanup_fd;
230+
231+
ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_SYSCALL, kfunc_id, 100, NULL);
232+
ASSERT_EQ(ret, 0, "invalid BTF fd in module BTF");
233+
234+
cleanup_fd:
235+
close(fd);
236+
cleanup:
237+
btf__free(vmlinux_btf);
238+
btf__free(module_btf);
239+
}
240+
241+
static const struct {
242+
const char *name;
243+
int code;
244+
} program_types[] = {
245+
#define _T(n) { #n, BPF_PROG_TYPE_##n }
246+
_T(KPROBE),
247+
_T(XDP),
248+
_T(SYSCALL),
249+
_T(SCHED_CLS),
250+
_T(SCHED_ACT),
251+
_T(SK_SKB),
252+
_T(SOCKET_FILTER),
253+
_T(CGROUP_SKB),
254+
_T(LWT_OUT),
255+
_T(LWT_IN),
256+
_T(LWT_XMIT),
257+
_T(LWT_SEG6LOCAL),
258+
_T(NETFILTER),
259+
_T(CGROUP_SOCK_ADDR),
260+
_T(SCHED_ACT)
261+
#undef _T
262+
};
263+
264+
void test_libbpf_probe_kfuncs_many(void)
265+
{
266+
int i, kfunc_id, ret, id;
267+
const struct btf_type *t;
268+
struct btf *btf = NULL;
269+
const char *kfunc;
270+
const char *tag;
271+
272+
btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
273+
if (!ASSERT_OK_PTR(btf, "btf_parse"))
274+
return;
275+
for (id = 0; id < btf__type_cnt(btf); ++id) {
276+
t = btf__type_by_id(btf, id);
277+
if (!t)
278+
continue;
279+
if (!btf_is_decl_tag(t))
280+
continue;
281+
tag = btf__name_by_offset(btf, t->name_off);
282+
if (strcmp(tag, "bpf_kfunc") != 0)
283+
continue;
284+
kfunc_id = t->type;
285+
t = btf__type_by_id(btf, kfunc_id);
286+
if (!btf_is_func(t))
287+
continue;
288+
kfunc = btf__name_by_offset(btf, t->name_off);
289+
for (i = 0; i < ARRAY_SIZE(program_types); ++i) {
290+
ret = libbpf_probe_bpf_kfunc(program_types[i].code,
291+
kfunc_id, -1, NULL);
292+
if (ret < 0) {
293+
ASSERT_FAIL("kfunc:%s use prog type:%d",
294+
kfunc, program_types[i].code);
295+
goto cleanup;
296+
}
297+
}
298+
}
299+
cleanup:
300+
btf__free(btf);
301+
}

0 commit comments

Comments
 (0)