Skip to content

Commit 5a8ea82

Browse files
anakryikoborkmann
authored andcommitted
selftests/bpf: Add libbpf feature-probing API selftests
Add selftests for prog/map/prog+helper feature probing APIs. Prog and map selftests are designed in such a way that they will always test all the possible prog/map types, based on running kernel's vmlinux BTF enum definition. This way we'll always be sure that when adding new BPF program types or map types, libbpf will be always updated accordingly to be able to feature-detect them. BPF prog_helper selftest will have to be manually extended with interesting and important prog+helper combinations, it's easy, but can't be completely automated. Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Dave Marchevsky <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 878d8de commit 5a8ea82

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

tools/testing/selftests/bpf/config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ CONFIG_IPV6_SIT=m
3838
CONFIG_BPF_JIT=y
3939
CONFIG_BPF_LSM=y
4040
CONFIG_SECURITY=y
41+
CONFIG_RC_CORE=y
4142
CONFIG_LIRC=y
43+
CONFIG_BPF_LIRC_MODE2=y
4244
CONFIG_IMA=y
4345
CONFIG_SECURITYFS=y
4446
CONFIG_IMA_WRITE_POLICY=y
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2021 Facebook */
3+
4+
#include <test_progs.h>
5+
#include <bpf/btf.h>
6+
7+
void test_libbpf_probe_prog_types(void)
8+
{
9+
struct btf *btf;
10+
const struct btf_type *t;
11+
const struct btf_enum *e;
12+
int i, n, id;
13+
14+
btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
15+
if (!ASSERT_OK_PTR(btf, "btf_parse"))
16+
return;
17+
18+
/* find enum bpf_prog_type and enumerate each value */
19+
id = btf__find_by_name_kind(btf, "bpf_prog_type", BTF_KIND_ENUM);
20+
if (!ASSERT_GT(id, 0, "bpf_prog_type_id"))
21+
goto cleanup;
22+
t = btf__type_by_id(btf, id);
23+
if (!ASSERT_OK_PTR(t, "bpf_prog_type_enum"))
24+
goto cleanup;
25+
26+
for (e = btf_enum(t), i = 0, n = btf_vlen(t); i < n; e++, i++) {
27+
const char *prog_type_name = btf__str_by_offset(btf, e->name_off);
28+
enum bpf_prog_type prog_type = (enum bpf_prog_type)e->val;
29+
int res;
30+
31+
if (prog_type == BPF_PROG_TYPE_UNSPEC)
32+
continue;
33+
34+
if (!test__start_subtest(prog_type_name))
35+
continue;
36+
37+
res = libbpf_probe_bpf_prog_type(prog_type, NULL);
38+
ASSERT_EQ(res, 1, prog_type_name);
39+
}
40+
41+
cleanup:
42+
btf__free(btf);
43+
}
44+
45+
void test_libbpf_probe_map_types(void)
46+
{
47+
struct btf *btf;
48+
const struct btf_type *t;
49+
const struct btf_enum *e;
50+
int i, n, id;
51+
52+
btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
53+
if (!ASSERT_OK_PTR(btf, "btf_parse"))
54+
return;
55+
56+
/* find enum bpf_map_type and enumerate each value */
57+
id = btf__find_by_name_kind(btf, "bpf_map_type", BTF_KIND_ENUM);
58+
if (!ASSERT_GT(id, 0, "bpf_map_type_id"))
59+
goto cleanup;
60+
t = btf__type_by_id(btf, id);
61+
if (!ASSERT_OK_PTR(t, "bpf_map_type_enum"))
62+
goto cleanup;
63+
64+
for (e = btf_enum(t), i = 0, n = btf_vlen(t); i < n; e++, i++) {
65+
const char *map_type_name = btf__str_by_offset(btf, e->name_off);
66+
enum bpf_map_type map_type = (enum bpf_map_type)e->val;
67+
int res;
68+
69+
if (map_type == BPF_MAP_TYPE_UNSPEC)
70+
continue;
71+
72+
if (!test__start_subtest(map_type_name))
73+
continue;
74+
75+
res = libbpf_probe_bpf_map_type(map_type, NULL);
76+
ASSERT_EQ(res, 1, map_type_name);
77+
}
78+
79+
cleanup:
80+
btf__free(btf);
81+
}
82+
83+
void test_libbpf_probe_helpers(void)
84+
{
85+
#define CASE(prog, helper, supp) { \
86+
.prog_type_name = "BPF_PROG_TYPE_" # prog, \
87+
.helper_name = "bpf_" # helper, \
88+
.prog_type = BPF_PROG_TYPE_ ## prog, \
89+
.helper_id = BPF_FUNC_ ## helper, \
90+
.supported = supp, \
91+
}
92+
const struct case_def {
93+
const char *prog_type_name;
94+
const char *helper_name;
95+
enum bpf_prog_type prog_type;
96+
enum bpf_func_id helper_id;
97+
bool supported;
98+
} cases[] = {
99+
CASE(KPROBE, unspec, false),
100+
CASE(KPROBE, map_lookup_elem, true),
101+
CASE(KPROBE, loop, true),
102+
103+
CASE(KPROBE, ktime_get_coarse_ns, false),
104+
CASE(SOCKET_FILTER, ktime_get_coarse_ns, true),
105+
106+
CASE(KPROBE, sys_bpf, false),
107+
CASE(SYSCALL, sys_bpf, true),
108+
};
109+
size_t case_cnt = ARRAY_SIZE(cases), i;
110+
char buf[128];
111+
112+
for (i = 0; i < case_cnt; i++) {
113+
const struct case_def *d = &cases[i];
114+
int res;
115+
116+
snprintf(buf, sizeof(buf), "%s+%s", d->prog_type_name, d->helper_name);
117+
118+
if (!test__start_subtest(buf))
119+
continue;
120+
121+
res = libbpf_probe_bpf_helper(d->prog_type, d->helper_id, NULL);
122+
ASSERT_EQ(res, d->supported, buf);
123+
}
124+
}

0 commit comments

Comments
 (0)