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
This commit is contained in:
parent
00389c58ff
commit
3cccbaa033
|
@ -31,6 +31,7 @@ test_tcp_check_syncookie_user
|
|||
test_sysctl
|
||||
xdping
|
||||
test_cpp
|
||||
*.subskel.h
|
||||
*.skel.h
|
||||
*.lskel.h
|
||||
/no_alu32
|
||||
|
|
|
@ -327,7 +327,13 @@ endef
|
|||
SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
|
||||
|
||||
LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \
|
||||
linked_vars.skel.h linked_maps.skel.h
|
||||
linked_vars.skel.h linked_maps.skel.h \
|
||||
test_subskeleton.skel.h test_subskeleton_lib.skel.h
|
||||
|
||||
# In the subskeleton case, we want the test_subskeleton_lib.subskel.h file
|
||||
# but that's created as a side-effect of the skel.h generation.
|
||||
test_subskeleton.skel.h-deps := test_subskeleton_lib2.o test_subskeleton_lib.o test_subskeleton.o
|
||||
test_subskeleton_lib.skel.h-deps := test_subskeleton_lib2.o test_subskeleton_lib.o
|
||||
|
||||
LSKELS := kfunc_call_test.c fentry_test.c fexit_test.c fexit_sleep.c \
|
||||
test_ringbuf.c atomics.c trace_printk.c trace_vprintk.c \
|
||||
|
@ -405,6 +411,7 @@ $(TRUNNER_BPF_SKELS): %.skel.h: %.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
|
|||
$(Q)$$(BPFTOOL) gen object $$(<:.o=.linked3.o) $$(<:.o=.linked2.o)
|
||||
$(Q)diff $$(<:.o=.linked2.o) $$(<:.o=.linked3.o)
|
||||
$(Q)$$(BPFTOOL) gen skeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.o=)) > $$@
|
||||
$(Q)$$(BPFTOOL) gen subskeleton $$(<:.o=.linked3.o) name $$(notdir $$(<:.o=)) > $$(@:.skel.h=.subskel.h)
|
||||
|
||||
$(TRUNNER_BPF_LSKELS): %.lskel.h: %.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
|
||||
$$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@)
|
||||
|
@ -422,6 +429,7 @@ $(TRUNNER_BPF_SKELS_LINKED): $(TRUNNER_BPF_OBJS) $(BPFTOOL) | $(TRUNNER_OUTPUT)
|
|||
$(Q)diff $$(@:.skel.h=.linked2.o) $$(@:.skel.h=.linked3.o)
|
||||
$$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@)
|
||||
$(Q)$$(BPFTOOL) gen skeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$@
|
||||
$(Q)$$(BPFTOOL) gen subskeleton $$(@:.skel.h=.linked3.o) name $$(notdir $$(@:.skel.h=)) > $$(@:.skel.h=.subskel.h)
|
||||
endif
|
||||
|
||||
# ensure we set up tests.h header generation rule just once
|
||||
|
@ -559,6 +567,6 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
|
|||
EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \
|
||||
prog_tests/tests.h map_tests/tests.h verifier/tests.h \
|
||||
feature bpftool \
|
||||
$(addprefix $(OUTPUT)/,*.o *.skel.h *.lskel.h no_alu32 bpf_gcc bpf_testmod.ko)
|
||||
$(addprefix $(OUTPUT)/,*.o *.skel.h *.lskel.h *.subskel.h no_alu32 bpf_gcc bpf_testmod.ko)
|
||||
|
||||
.PHONY: docs docs-clean
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include <test_progs.h>
|
||||
#include "test_subskeleton.skel.h"
|
||||
#include "test_subskeleton_lib.subskel.h"
|
||||
|
||||
static void subskeleton_lib_setup(struct bpf_object *obj)
|
||||
{
|
||||
struct test_subskeleton_lib *lib = test_subskeleton_lib__open(obj);
|
||||
|
||||
if (!ASSERT_OK_PTR(lib, "open subskeleton"))
|
||||
return;
|
||||
|
||||
*lib->rodata.var1 = 1;
|
||||
*lib->data.var2 = 2;
|
||||
lib->bss.var3->var3_1 = 3;
|
||||
lib->bss.var3->var3_2 = 4;
|
||||
|
||||
test_subskeleton_lib__destroy(lib);
|
||||
}
|
||||
|
||||
static int subskeleton_lib_subresult(struct bpf_object *obj)
|
||||
{
|
||||
struct test_subskeleton_lib *lib = test_subskeleton_lib__open(obj);
|
||||
int result;
|
||||
|
||||
if (!ASSERT_OK_PTR(lib, "open subskeleton"))
|
||||
return -EINVAL;
|
||||
|
||||
result = *lib->bss.libout1;
|
||||
ASSERT_EQ(result, 1 + 2 + 3 + 4 + 5 + 6, "lib subresult");
|
||||
|
||||
ASSERT_OK_PTR(lib->progs.lib_perf_handler, "lib_perf_handler");
|
||||
ASSERT_STREQ(bpf_program__name(lib->progs.lib_perf_handler),
|
||||
"lib_perf_handler", "program name");
|
||||
|
||||
ASSERT_OK_PTR(lib->maps.map1, "map1");
|
||||
ASSERT_STREQ(bpf_map__name(lib->maps.map1), "map1", "map name");
|
||||
|
||||
ASSERT_EQ(*lib->data.var5, 5, "__weak var5");
|
||||
ASSERT_EQ(*lib->data.var6, 6, "extern var6");
|
||||
ASSERT_TRUE(*lib->kconfig.CONFIG_BPF_SYSCALL, "CONFIG_BPF_SYSCALL");
|
||||
|
||||
test_subskeleton_lib__destroy(lib);
|
||||
return result;
|
||||
}
|
||||
|
||||
void test_subskeleton(void)
|
||||
{
|
||||
int err, result;
|
||||
struct test_subskeleton *skel;
|
||||
|
||||
skel = test_subskeleton__open();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
return;
|
||||
|
||||
skel->rodata->rovar1 = 10;
|
||||
skel->rodata->var1 = 1;
|
||||
subskeleton_lib_setup(skel->obj);
|
||||
|
||||
err = test_subskeleton__load(skel);
|
||||
if (!ASSERT_OK(err, "skel_load"))
|
||||
goto cleanup;
|
||||
|
||||
err = test_subskeleton__attach(skel);
|
||||
if (!ASSERT_OK(err, "skel_attach"))
|
||||
goto cleanup;
|
||||
|
||||
/* trigger tracepoint */
|
||||
usleep(1);
|
||||
|
||||
result = subskeleton_lib_subresult(skel->obj) * 10;
|
||||
ASSERT_EQ(skel->bss->out1, result, "unexpected calculation");
|
||||
|
||||
cleanup:
|
||||
test_subskeleton__destroy(skel);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/* volatile to force a read, compiler may assume 0 otherwise */
|
||||
const volatile int rovar1;
|
||||
int out1;
|
||||
|
||||
/* Override weak symbol in test_subskeleton_lib */
|
||||
int var5 = 5;
|
||||
|
||||
extern volatile bool CONFIG_BPF_SYSCALL __kconfig;
|
||||
|
||||
extern int lib_routine(void);
|
||||
|
||||
SEC("raw_tp/sys_enter")
|
||||
int handler1(const void *ctx)
|
||||
{
|
||||
(void) CONFIG_BPF_SYSCALL;
|
||||
|
||||
out1 = lib_routine() * rovar1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char LICENSE[] SEC("license") = "GPL";
|
|
@ -0,0 +1,61 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/* volatile to force a read */
|
||||
const volatile int var1;
|
||||
volatile int var2 = 1;
|
||||
struct {
|
||||
int var3_1;
|
||||
__s64 var3_2;
|
||||
} var3;
|
||||
int libout1;
|
||||
|
||||
extern volatile bool CONFIG_BPF_SYSCALL __kconfig;
|
||||
|
||||
int var4[4];
|
||||
|
||||
__weak int var5 SEC(".data");
|
||||
|
||||
/* Fully contained within library extern-and-definition */
|
||||
extern int var6;
|
||||
|
||||
int var7 SEC(".data.custom");
|
||||
|
||||
int (*fn_ptr)(void);
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
__uint(max_entries, 16);
|
||||
} map1 SEC(".maps");
|
||||
|
||||
extern struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
__uint(max_entries, 16);
|
||||
} map2 SEC(".maps");
|
||||
|
||||
int lib_routine(void)
|
||||
{
|
||||
__u32 key = 1, value = 2;
|
||||
|
||||
(void) CONFIG_BPF_SYSCALL;
|
||||
bpf_map_update_elem(&map2, &key, &value, BPF_ANY);
|
||||
|
||||
libout1 = var1 + var2 + var3.var3_1 + var3.var3_2 + var5 + var6;
|
||||
return libout1;
|
||||
}
|
||||
|
||||
SEC("perf_event")
|
||||
int lib_perf_handler(struct pt_regs *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char LICENSE[] SEC("license") = "GPL";
|
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
int var6 = 6;
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
__uint(max_entries, 16);
|
||||
} map2 SEC(".maps");
|
||||
|
||||
char LICENSE[] SEC("license") = "GPL";
|
Loading…
Reference in New Issue