new file mode 120000
@@ -0,0 +1 @@
+../../../tools/testing/selftests/bpf/bpf_testmod/bpf_testmod-events.h
\ No newline at end of file
@@ -100,4 +100,13 @@ config BPF_LSM
If you are unsure how to answer this question, answer N.
+config BPF_TEST_MODULE
+ bool "Build the module for BPF selftests as a built-in"
+ depends on BPF_SYSCALL
+ depends on BPF_JIT
+ depends on !MODULES
+ default n
+ help
+ This allows most of the bpf selftests to run without modules.
+
endmenu # "BPF subsystem"
@@ -46,3 +46,5 @@ obj-$(CONFIG_BPF_PRELOAD) += preload/
obj-$(CONFIG_BPF_SYSCALL) += relo_core.o
$(obj)/relo_core.o: $(srctree)/tools/lib/bpf/relo_core.c FORCE
$(call if_changed_rule,cc_o_c)
+
+obj-$(CONFIG_BPF_TEST_MODULE) += bpf_testmod/
new file mode 100644
@@ -0,0 +1 @@
+obj-y += bpf_testmod.o
new file mode 120000
@@ -0,0 +1 @@
+../../../tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
\ No newline at end of file
new file mode 120000
@@ -0,0 +1 @@
+../../../tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h
\ No newline at end of file
new file mode 120000
@@ -0,0 +1 @@
+../../../tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h
\ No newline at end of file
@@ -573,10 +573,12 @@ __bpf_kfunc int bpf_modify_return_test2(int a, int *b, short c, int d,
return a + *b + c + d + (long)e + f + g;
}
+#if !IS_ENABLED(CONFIG_BPF_TEST_MODULE)
int noinline bpf_fentry_shadow_test(int a)
{
return a + 1;
}
+#endif
struct prog_test_member1 {
int a;
@@ -108,9 +108,16 @@ TEST_PROGS_EXTENDED := with_addr.sh \
# Compile but not part of 'make run_tests'
TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \
flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
- test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \
- xskxceiver xdp_redirect_multi xdp_synproxy veristat xdp_hw_metadata \
- xdp_features
+ test_lirc_mode2_user xdping test_cpp runqslower bench xskxceiver \
+ xdp_redirect_multi xdp_synproxy veristat xdp_hw_metadata xdp_features
+
+RUN_TESTS_WITHOUT_MODULES ?= 0
+TRUNNER_EXTRA_CFLAGS ?=
+
+ifeq ($(RUN_TESTS_WITHOUT_MODULES),0)
+TEST_GEN_PROGS_EXTENDED += bpf_testmod.ko
+TRUNNER_EXTRA_CFLAGS += -DBPF_TESTMOD_EXTERNAL
+endif
TEST_GEN_FILES += liburandom_read.so urandom_read sign-file uprobe_multi
@@ -400,22 +407,22 @@ $(OUTPUT)/cgroup_getset_retval_hooks.o: cgroup_getset_retval_hooks.h
# $3 - CFLAGS
define CLANG_BPF_BUILD_RULE
$(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2)
- $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v3 -o $2
+ $(Q)$(CLANG) $3 $(TRUNNER_EXTRA_CFLAGS) -O2 --target=bpf -c $1 -mcpu=v3 -o $2
endef
# Similar to CLANG_BPF_BUILD_RULE, but with disabled alu32
define CLANG_NOALU32_BPF_BUILD_RULE
$(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2)
- $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v2 -o $2
+ $(Q)$(CLANG) $3 $(TRUNNER_EXTRA_CFLAGS) -O2 --target=bpf -c $1 -mcpu=v2 -o $2
endef
# Similar to CLANG_BPF_BUILD_RULE, but with cpu-v4
define CLANG_CPUV4_BPF_BUILD_RULE
$(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2)
- $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v4 -o $2
+ $(Q)$(CLANG) $3 $(TRUNNER_EXTRA_CFLAGS) -O2 --target=bpf -c $1 -mcpu=v4 -o $2
endef
# Build BPF object using GCC
define GCC_BPF_BUILD_RULE
$(call msg,GCC-BPF,$(TRUNNER_BINARY),$2)
- $(Q)$(BPF_GCC) $3 -O2 -c $1 -o $2
+ $(Q)$(BPF_GCC) $3 $(TRUNNER_EXTRA_CFLAGS) -O2 -c $1 -o $2
endef
SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
@@ -605,7 +612,7 @@ TRUNNER_EXTRA_SOURCES := test_progs.c \
json_writer.c \
flow_dissector_load.h \
ip_check_defrag_frags.h
-TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \
+TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read \
$(OUTPUT)/liburandom_read.so \
$(OUTPUT)/xdp_synproxy \
$(OUTPUT)/sign-file \
@@ -614,6 +621,11 @@ TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \
verify_sig_setup.sh \
$(wildcard progs/btf_dump_test_case_*.c) \
$(wildcard progs/*.bpf.o)
+
+ifeq ($(RUN_TESTS_WITHOUT_MODULES),0)
+TRUNNER_EXTRA_FILES += $(OUTPUT)/bpf_testmod.ko
+endif
+
TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE
TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS) -DENABLE_ATOMICS_TESTS
$(eval $(call DEFINE_TEST_RUNNER,test_progs))
@@ -10,7 +10,7 @@ endif
MODULES = bpf_testmod.ko
obj-m += bpf_testmod.o
-CFLAGS_bpf_testmod.o = -I$(src)
+CFLAGS_bpf_testmod.o = -I$(src) -DBPF_TESTMOD_EXTERNAL
all:
+$(Q)make -C $(KDIR) M=$(BPF_TESTMOD_DIR) modules
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020 Facebook */
+
#undef TRACE_SYSTEM
#define TRACE_SYSTEM bpf_testmod
@@ -7,7 +8,10 @@
#define _BPF_TESTMOD_EVENTS_H
#include <linux/tracepoint.h>
+
+#ifdef BPF_TESTMOD_EXTERNAL
#include "bpf_testmod.h"
+#endif
TRACE_EVENT(bpf_testmod_test_read,
TP_PROTO(struct task_struct *task, struct bpf_testmod_test_read_ctx *ctx),
@@ -51,7 +55,9 @@ BPF_TESTMOD_DECLARE_TRACE(bpf_testmod_test_writable_bare,
#endif /* _BPF_TESTMOD_EVENTS_H */
+#ifdef BPF_TESTMOD_EXTERNAL
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE bpf_testmod-events
+#endif
#include <trace/define_trace.h>
@@ -12,7 +12,11 @@
#include "bpf_testmod_kfunc.h"
#define CREATE_TRACE_POINTS
+#ifdef BPF_TESTMOD_EXTERNAL
#include "bpf_testmod-events.h"
+#else
+#include "trace/events/bpf_testmod.h"
+#endif
typedef int (*func_proto_typedef)(long);
typedef int (*func_proto_typedef_nested1)(func_proto_typedef);
@@ -26,6 +26,7 @@ struct prog_test_ref_kfunc {
};
#endif
+#if defined(BPF_TESTMOD_EXTERNAL) || defined(__KERNEL__)
struct prog_test_pass1 {
int x0;
struct {
@@ -63,6 +64,7 @@ struct prog_test_fail3 {
char arr1[2];
char arr2[];
};
+#endif
struct prog_test_ref_kfunc *
bpf_kfunc_call_test_acquire(unsigned long *scalar_ptr) __ksym;
@@ -44,11 +44,6 @@ CONFIG_IPV6_TUNNEL=y
CONFIG_KEYS=y
CONFIG_LIRC=y
CONFIG_LWTUNNEL=y
-CONFIG_MODULE_SIG=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
CONFIG_MPLS=y
CONFIG_MPLS_IPTUNNEL=y
CONFIG_MPLS_ROUTING=y
new file mode 100644
@@ -0,0 +1,5 @@
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
new file mode 100644
@@ -0,0 +1 @@
+CONFIG_BPF_TEST_MODULE=y
@@ -4,6 +4,7 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_testmod_btf_type_tag_1 {
int a;
};
@@ -11,6 +12,7 @@ struct bpf_testmod_btf_type_tag_1 {
struct bpf_testmod_btf_type_tag_2 {
struct bpf_testmod_btf_type_tag_1 *p;
};
+#endif
__u64 g;
@@ -4,6 +4,7 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_testmod_btf_type_tag_1 {
int a;
};
@@ -11,6 +12,7 @@ struct bpf_testmod_btf_type_tag_1 {
struct bpf_testmod_btf_type_tag_2 {
struct bpf_testmod_btf_type_tag_1 *p;
};
+#endif
int g;
@@ -67,9 +67,11 @@ struct __sk_bUfF /* it will not exist in vmlinux */ {
int len;
} __attribute__((preserve_access_index));
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_testmod_test_read_ctx /* it exists in bpf_testmod */ {
size_t len;
} __attribute__((preserve_access_index));
+#endif
SEC("tc")
int balancer_ingress(struct __sk_buff *ctx)
@@ -5,10 +5,12 @@
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_iter_testmod_seq {
u64 :64;
u64 :64;
};
+#endif
extern int bpf_iter_testmod_seq_new(struct bpf_iter_testmod_seq *it, s64 value, int cnt) __ksym;
extern s64 *bpf_iter_testmod_seq_next(struct bpf_iter_testmod_seq *it) __ksym;
@@ -8,12 +8,14 @@
char _license[] SEC("license") = "GPL";
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_testmod_test_read_ctx {
/* field order is mixed up */
size_t len;
char *buf;
loff_t off;
} __attribute__((preserve_access_index));
+#endif
struct {
char in[256];
@@ -48,9 +48,11 @@ int map_val_prog(const void *ctx)
}
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_testmod_struct_arg_1 {
int a;
};
+#endif
long long int_member;
@@ -5,7 +5,10 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
+
+#ifdef BPF_TESTMOD_EXTERNAL
#include "../bpf_testmod/bpf_testmod.h"
+#endif
__u32 raw_tp_read_sz = 0;
@@ -5,6 +5,7 @@
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_helpers.h>
+#ifdef BPF_TESTMOD_EXTERNAL
struct bpf_testmod_struct_arg_1 {
int a;
};
@@ -22,6 +23,7 @@ struct bpf_testmod_struct_arg_4 {
u64 a;
int b;
};
+#endif
long t1_a_a, t1_a_b, t1_b, t1_c, t1_ret, t1_nregs;
__u64 t1_reg0, t1_reg1, t1_reg2, t1_reg3;
@@ -342,6 +342,12 @@ int unload_bpf_testmod(bool verbose)
{
if (kern_sync_rcu())
fprintf(stdout, "Failed to trigger kernel-side RCU sync!\n");
+
+ if (access("/proc/modules", F_OK)) {
+ fprintf(stdout, "Modules are disabled, fake unload success\n");
+ return 0;
+ }
+
if (delete_module("bpf_testmod", 0)) {
if (errno == ENOENT) {
if (verbose)
@@ -363,6 +369,14 @@ int load_bpf_testmod(bool verbose)
if (verbose)
fprintf(stdout, "Loading bpf_testmod.ko...\n");
+ if (access("/proc/modules", F_OK)) {
+ if (!access("/sys/kernel/debug/tracing/events/bpf_testmod", F_OK))
+ return 0;
+
+ fprintf(stdout, "Modules are disabled, testmod not built-in\n");
+ return -ENOENT;
+ }
+
fd = open("bpf_testmod.ko", O_RDONLY);
if (fd < 0) {
fprintf(stdout, "Can't find bpf_testmod.ko kernel module: %d\n", -errno);
@@ -44,11 +44,12 @@ NUM_COMPILE_JOBS="$(nproc)"
LOG_FILE_BASE="$(date +"bpf_selftests.%Y-%m-%d_%H-%M-%S")"
LOG_FILE="${LOG_FILE_BASE}.log"
EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status"
+MODULES="yes"
usage()
{
cat <<EOF
-Usage: $0 [-i] [-s] [-d <output_dir>] -- [<command>]
+Usage: $0 [-i] [-s] [-n] [-d <output_dir>] -- [<command>]
<command> is the command you would normally run when you are in
tools/testing/selftests/bpf. e.g:
@@ -76,6 +77,7 @@ Options:
-s) Instead of powering off the VM, start an interactive
shell. If <command> is specified, the shell runs after
the command finishes executing
+ -n) Run tests with CONFIG_MODULES=n
EOF
}
@@ -341,7 +343,7 @@ main()
local exit_command="poweroff -f"
local debug_shell="no"
- while getopts ':hskid:j:' opt; do
+ while getopts ':hskid:j:n' opt; do
case ${opt} in
i)
update_image="yes"
@@ -357,6 +359,9 @@ main()
debug_shell="yes"
exit_command="bash"
;;
+ n)
+ MODULES="no"
+ ;;
h)
usage
exit 0
@@ -409,12 +414,27 @@ main()
echo "Output directory: ${OUTPUT_DIR}"
+ if [[ "${MODULES}" == "yes" ]]; then
+ KCONFIG_REL_PATHS+=("tools/testing/selftests/bpf/config.mods")
+ else
+ make_command="${make_command} RUN_TESTS_WITHOUT_MODULES=1"
+ KCONFIG_REL_PATHS+=("tools/testing/selftests/bpf/config.nomods")
+ fi
+
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${mount_dir}"
update_kconfig "${kernel_checkout}" "${kconfig_file}"
recompile_kernel "${kernel_checkout}" "${make_command}"
+ # Touch the opposite mods/nomods config we used to ensure the
+ # kernel is rebuilt when the user adds or drops the -n flag.
+ if [[ "${MODULES}" == "yes" ]]; then
+ touch -m "tools/testing/selftests/bpf/config.nomods"
+ else
+ touch -m "tools/testing/selftests/bpf/config.mods"
+ fi
+
if [[ "${update_image}" == "no" && ! -f "${rootfs_img}" ]]; then
echo "rootfs image not found in ${rootfs_img}"
update_image="yes"
This symlinks bpf_testmod into the main source, so it can be built-in for running selftests in the new !MODULES case. To be clear, no changes to the existing selftests are required: this only exists to enable testing the new case which was not previously possible. I'm sure somebody will be able to suggest a less ugly way I can do this... Signed-off-by: Calvin Owens <jcalvinowens@gmail.com> --- include/trace/events/bpf_testmod.h | 1 + kernel/bpf/Kconfig | 9 ++++++ kernel/bpf/Makefile | 2 ++ kernel/bpf/bpf_testmod/Makefile | 1 + kernel/bpf/bpf_testmod/bpf_testmod.c | 1 + kernel/bpf/bpf_testmod/bpf_testmod.h | 1 + kernel/bpf/bpf_testmod/bpf_testmod_kfunc.h | 1 + net/bpf/test_run.c | 2 ++ tools/testing/selftests/bpf/Makefile | 28 +++++++++++++------ .../selftests/bpf/bpf_testmod/Makefile | 2 +- .../bpf/bpf_testmod/bpf_testmod-events.h | 6 ++++ .../selftests/bpf/bpf_testmod/bpf_testmod.c | 4 +++ .../bpf/bpf_testmod/bpf_testmod_kfunc.h | 2 ++ tools/testing/selftests/bpf/config | 5 ---- tools/testing/selftests/bpf/config.mods | 5 ++++ tools/testing/selftests/bpf/config.nomods | 1 + .../selftests/bpf/progs/btf_type_tag_percpu.c | 2 ++ .../selftests/bpf/progs/btf_type_tag_user.c | 2 ++ tools/testing/selftests/bpf/progs/core_kern.c | 2 ++ .../selftests/bpf/progs/iters_testmod_seq.c | 2 ++ .../bpf/progs/test_core_reloc_module.c | 2 ++ .../selftests/bpf/progs/test_ldsx_insn.c | 2 ++ .../selftests/bpf/progs/test_module_attach.c | 3 ++ .../selftests/bpf/progs/tracing_struct.c | 2 ++ tools/testing/selftests/bpf/testing_helpers.c | 14 ++++++++++ tools/testing/selftests/bpf/vmtest.sh | 24 ++++++++++++++-- 26 files changed, 110 insertions(+), 16 deletions(-) create mode 120000 include/trace/events/bpf_testmod.h create mode 100644 kernel/bpf/bpf_testmod/Makefile create mode 120000 kernel/bpf/bpf_testmod/bpf_testmod.c create mode 120000 kernel/bpf/bpf_testmod/bpf_testmod.h create mode 120000 kernel/bpf/bpf_testmod/bpf_testmod_kfunc.h create mode 100644 tools/testing/selftests/bpf/config.mods create mode 100644 tools/testing/selftests/bpf/config.nomods