Add selftests covering selective kernel module BTF loading through bpf_object_open_opts. The tests verify that loading succeeds when the required module BTF is requested, fails when only an unrelated module BTF is requested, and skips loading all module BTFs when an empty module BTF name list is provided. Signed-off-by: Fuyu Zhao --- .../bpf/prog_tests/btf_module_names.c | 93 +++++++++++++++++++ .../selftests/bpf/progs/btf_module_names.c | 13 +++ 2 files changed, 106 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_module_names.c create mode 100644 tools/testing/selftests/bpf/progs/btf_module_names.c diff --git a/tools/testing/selftests/bpf/prog_tests/btf_module_names.c b/tools/testing/selftests/bpf/prog_tests/btf_module_names.c new file mode 100644 index 000000000000..d5674cad0017 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/btf_module_names.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "btf_module_names.skel.h" + +static void btf_module_names_load(void) +{ + struct btf_module_names *skel = NULL; + int ret; + static const char *mod_names[] = { "bpf_testmod" }; + + LIBBPF_OPTS(bpf_object_open_opts, opts, + .btf_module_names = mod_names, + .nr_btf_module_names = 1, + ); + + skel = btf_module_names__open_opts(&opts); + if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts")) + goto out; + + ret = btf_module_names__load(skel); + ASSERT_OK(ret, "btf_module_names__load"); +out: + btf_module_names__destroy(skel); +} + +/* + * Verify that an unrequested module BTF is skipped. The BPF program + * requires the BTF of bpf_testmod, but bpf_testmod is not specified in + * btf_module_names, so its BTF is skipped and the BPF program fails to load. + */ +static void btf_module_names_skip(void) +{ + struct btf_module_names *skel = NULL; + int ret; + static const char *mod_names[] = { "module_nonexist" }; + + LIBBPF_OPTS(bpf_object_open_opts, opts, + .btf_module_names = mod_names, + .nr_btf_module_names = 1, + ); + + skel = btf_module_names__open_opts(&opts); + if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts")) + goto out; + + ret = btf_module_names__load(skel); + ASSERT_ERR(ret, "btf_module_names__load"); + +out: + btf_module_names__destroy(skel); +} + +/* + * Verify that an empty filter skips loading all module BTFs. The BPF + * program requires bpf_testmod BTF, so it fails to load. + */ +static void btf_module_names_empty(void) +{ + struct btf_module_names *skel = NULL; + int ret; + static const char *mod_names[] = { "foo" }; + + LIBBPF_OPTS(bpf_object_open_opts, opts, + .btf_module_names = mod_names, + ); + + skel = btf_module_names__open_opts(&opts); + if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts empty")) + goto out; + + ret = btf_module_names__load(skel); + ASSERT_ERR(ret, "btf_module_names__load empty"); + +out: + btf_module_names__destroy(skel); +} + +void test_btf_module_names(void) +{ + if (!env.has_testmod) { + test__skip(); + return; + } + + if (test__start_subtest("btf_module_names_load")) + btf_module_names_load(); + + if (test__start_subtest("btf_module_names_skip")) + btf_module_names_skip(); + + if (test__start_subtest("btf_module_names_empty")) + btf_module_names_empty(); +} diff --git a/tools/testing/selftests/bpf/progs/btf_module_names.c b/tools/testing/selftests/bpf/progs/btf_module_names.c new file mode 100644 index 000000000000..232adc0f33f6 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf_module_names.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +SEC("fentry/bpf_testmod_loop_test") +int BPF_PROG(test_btf_module_names) +{ + return 0; +} + +char _license[] SEC("license") = "GPL"; -- 2.34.1