Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Test subskeleton functionality

This patch changes the selftests/bpf Makefile to also generate
a subskel.h for every skel.h it would have normally generated.

Separately, it also introduces a new subskeleton test which tests
library objects, externs, weak symbols, kconfigs, and user maps.

Signed-off-by: Delyan Kratunov <delyank@fb.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/1bd24956940bbbfe169bb34f7f87b11df52ef011.1647473511.git.delyank@fb.com

authored by

Delyan Kratunov and committed by
Andrii Nakryiko
3cccbaa0 00389c58

+194 -2
+1
tools/testing/selftests/bpf/.gitignore
··· 31 31 test_sysctl 32 32 xdping 33 33 test_cpp 34 + *.subskel.h 34 35 *.skel.h 35 36 *.lskel.h 36 37 /no_alu32
+10 -2
tools/testing/selftests/bpf/Makefile
··· 327 327 SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c 328 328 329 329 LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \ 330 - linked_vars.skel.h linked_maps.skel.h 330 + linked_vars.skel.h linked_maps.skel.h \ 331 + test_subskeleton.skel.h test_subskeleton_lib.skel.h 332 + 333 + # In the subskeleton case, we want the test_subskeleton_lib.subskel.h file 334 + # but that's created as a side-effect of the skel.h generation. 335 + test_subskeleton.skel.h-deps := test_subskeleton_lib2.o test_subskeleton_lib.o test_subskeleton.o 336 + test_subskeleton_lib.skel.h-deps := test_subskeleton_lib2.o test_subskeleton_lib.o 331 337 332 338 LSKELS := kfunc_call_test.c fentry_test.c fexit_test.c fexit_sleep.c \ 333 339 test_ringbuf.c atomics.c trace_printk.c trace_vprintk.c \ ··· 411 405 $(Q)$$(BPFTOOL) gen object $$(<:.o=.linked3.o) $$(<:.o=.linked2.o) 412 406 $(Q)diff $$(<:.o=.linked2.o) $$(<:.o=.linked3.o) 413 407 $(Q)$$(BPFTOOL) gen skeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.o=)) > $$@ 408 + $(Q)$$(BPFTOOL) gen subskeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.o=)) > $$(@:.skel.h=.subskel.h) 414 409 415 410 $(TRUNNER_BPF_LSKELS): %.lskel.h: %.o $(BPFTOOL) | $(TRUNNER_OUTPUT) 416 411 $$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@) ··· 429 422 $(Q)diff $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked3.o) 430 423 $$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@) 431 424 $(Q)$$(BPFTOOL) gen skeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$@ 425 + $(Q)$$(BPFTOOL) gen subskeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$(@:.skel.h=.subskel.h) 432 426 endif 433 427 434 428 # ensure we set up tests.h header generation rule just once ··· 567 559 EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ 568 560 prog_tests/tests.h map_tests/tests.h verifier/tests.h \ 569 561 feature bpftool \ 570 - $(addprefix $(OUTPUT)/,*.o *.skel.h *.lskel.h no_alu32 bpf_gcc bpf_testmod.ko) 562 + $(addprefix $(OUTPUT)/,*.o *.skel.h *.lskel.h *.subskel.h no_alu32 bpf_gcc bpf_testmod.ko) 571 563 572 564 .PHONY: docs docs-clean
+78
tools/testing/selftests/bpf/prog_tests/subskeleton.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <test_progs.h> 5 + #include "test_subskeleton.skel.h" 6 + #include "test_subskeleton_lib.subskel.h" 7 + 8 + static void subskeleton_lib_setup(struct bpf_object *obj) 9 + { 10 + struct test_subskeleton_lib *lib = test_subskeleton_lib__open(obj); 11 + 12 + if (!ASSERT_OK_PTR(lib, "open subskeleton")) 13 + return; 14 + 15 + *lib->rodata.var1 = 1; 16 + *lib->data.var2 = 2; 17 + lib->bss.var3->var3_1 = 3; 18 + lib->bss.var3->var3_2 = 4; 19 + 20 + test_subskeleton_lib__destroy(lib); 21 + } 22 + 23 + static int subskeleton_lib_subresult(struct bpf_object *obj) 24 + { 25 + struct test_subskeleton_lib *lib = test_subskeleton_lib__open(obj); 26 + int result; 27 + 28 + if (!ASSERT_OK_PTR(lib, "open subskeleton")) 29 + return -EINVAL; 30 + 31 + result = *lib->bss.libout1; 32 + ASSERT_EQ(result, 1 + 2 + 3 + 4 + 5 + 6, "lib subresult"); 33 + 34 + ASSERT_OK_PTR(lib->progs.lib_perf_handler, "lib_perf_handler"); 35 + ASSERT_STREQ(bpf_program__name(lib->progs.lib_perf_handler), 36 + "lib_perf_handler", "program name"); 37 + 38 + ASSERT_OK_PTR(lib->maps.map1, "map1"); 39 + ASSERT_STREQ(bpf_map__name(lib->maps.map1), "map1", "map name"); 40 + 41 + ASSERT_EQ(*lib->data.var5, 5, "__weak var5"); 42 + ASSERT_EQ(*lib->data.var6, 6, "extern var6"); 43 + ASSERT_TRUE(*lib->kconfig.CONFIG_BPF_SYSCALL, "CONFIG_BPF_SYSCALL"); 44 + 45 + test_subskeleton_lib__destroy(lib); 46 + return result; 47 + } 48 + 49 + void test_subskeleton(void) 50 + { 51 + int err, result; 52 + struct test_subskeleton *skel; 53 + 54 + skel = test_subskeleton__open(); 55 + if (!ASSERT_OK_PTR(skel, "skel_open")) 56 + return; 57 + 58 + skel->rodata->rovar1 = 10; 59 + skel->rodata->var1 = 1; 60 + subskeleton_lib_setup(skel->obj); 61 + 62 + err = test_subskeleton__load(skel); 63 + if (!ASSERT_OK(err, "skel_load")) 64 + goto cleanup; 65 + 66 + err = test_subskeleton__attach(skel); 67 + if (!ASSERT_OK(err, "skel_attach")) 68 + goto cleanup; 69 + 70 + /* trigger tracepoint */ 71 + usleep(1); 72 + 73 + result = subskeleton_lib_subresult(skel->obj) * 10; 74 + ASSERT_EQ(skel->bss->out1, result, "unexpected calculation"); 75 + 76 + cleanup: 77 + test_subskeleton__destroy(skel); 78 + }
+28
tools/testing/selftests/bpf/progs/test_subskeleton.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <stdbool.h> 5 + #include <linux/bpf.h> 6 + #include <bpf/bpf_helpers.h> 7 + 8 + /* volatile to force a read, compiler may assume 0 otherwise */ 9 + const volatile int rovar1; 10 + int out1; 11 + 12 + /* Override weak symbol in test_subskeleton_lib */ 13 + int var5 = 5; 14 + 15 + extern volatile bool CONFIG_BPF_SYSCALL __kconfig; 16 + 17 + extern int lib_routine(void); 18 + 19 + SEC("raw_tp/sys_enter") 20 + int handler1(const void *ctx) 21 + { 22 + (void) CONFIG_BPF_SYSCALL; 23 + 24 + out1 = lib_routine() * rovar1; 25 + return 0; 26 + } 27 + 28 + char LICENSE[] SEC("license") = "GPL";
+61
tools/testing/selftests/bpf/progs/test_subskeleton_lib.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <stdbool.h> 5 + #include <linux/bpf.h> 6 + #include <bpf/bpf_helpers.h> 7 + 8 + /* volatile to force a read */ 9 + const volatile int var1; 10 + volatile int var2 = 1; 11 + struct { 12 + int var3_1; 13 + __s64 var3_2; 14 + } var3; 15 + int libout1; 16 + 17 + extern volatile bool CONFIG_BPF_SYSCALL __kconfig; 18 + 19 + int var4[4]; 20 + 21 + __weak int var5 SEC(".data"); 22 + 23 + /* Fully contained within library extern-and-definition */ 24 + extern int var6; 25 + 26 + int var7 SEC(".data.custom"); 27 + 28 + int (*fn_ptr)(void); 29 + 30 + struct { 31 + __uint(type, BPF_MAP_TYPE_HASH); 32 + __type(key, __u32); 33 + __type(value, __u32); 34 + __uint(max_entries, 16); 35 + } map1 SEC(".maps"); 36 + 37 + extern struct { 38 + __uint(type, BPF_MAP_TYPE_HASH); 39 + __type(key, __u32); 40 + __type(value, __u32); 41 + __uint(max_entries, 16); 42 + } map2 SEC(".maps"); 43 + 44 + int lib_routine(void) 45 + { 46 + __u32 key = 1, value = 2; 47 + 48 + (void) CONFIG_BPF_SYSCALL; 49 + bpf_map_update_elem(&map2, &key, &value, BPF_ANY); 50 + 51 + libout1 = var1 + var2 + var3.var3_1 + var3.var3_2 + var5 + var6; 52 + return libout1; 53 + } 54 + 55 + SEC("perf_event") 56 + int lib_perf_handler(struct pt_regs *ctx) 57 + { 58 + return 0; 59 + } 60 + 61 + char LICENSE[] SEC("license") = "GPL";
+16
tools/testing/selftests/bpf/progs/test_subskeleton_lib2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <linux/bpf.h> 5 + #include <bpf/bpf_helpers.h> 6 + 7 + int var6 = 6; 8 + 9 + struct { 10 + __uint(type, BPF_MAP_TYPE_HASH); 11 + __type(key, __u32); 12 + __type(value, __u32); 13 + __uint(max_entries, 16); 14 + } map2 SEC(".maps"); 15 + 16 + char LICENSE[] SEC("license") = "GPL";