Commit f91b2566 authored by Simon Sundberg's avatar Simon Sundberg Committed by Alexei Starovoitov

selftests/bpf: Add test for kfunc module order

Add a test case for kfuncs from multiple external modules, checking
that the correct kfuncs are called regardless of which order they're
called in. Specifically, check that calling the kfuncs in an order
different from the one the modules' BTF are loaded in works.
Signed-off-by: default avatarSimon Sundberg <simon.sundberg@kau.se>
Acked-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: default avatarToke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/r/20241010-fix-kfunc-btf-caching-for-modules-v2-3-745af6c1af98@redhat.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 4192bb29
......@@ -157,7 +157,8 @@ TEST_GEN_PROGS_EXTENDED = \
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 bpf_test_no_cfi.ko
xdp_features bpf_test_no_cfi.ko bpf_test_modorder_x.ko \
bpf_test_modorder_y.ko
TEST_GEN_FILES += liburandom_read.so urandom_read sign-file uprobe_multi
......@@ -303,6 +304,19 @@ $(OUTPUT)/bpf_test_no_cfi.ko: $(VMLINUX_BTF) $(RESOLVE_BTFIDS) $(wildcard bpf_te
$(Q)$(MAKE) $(submake_extras) RESOLVE_BTFIDS=$(RESOLVE_BTFIDS) -C bpf_test_no_cfi
$(Q)cp bpf_test_no_cfi/bpf_test_no_cfi.ko $@
$(OUTPUT)/bpf_test_modorder_x.ko: $(VMLINUX_BTF) $(RESOLVE_BTFIDS) $(wildcard bpf_test_modorder_x/Makefile bpf_test_modorder_x/*.[ch])
$(call msg,MOD,,$@)
$(Q)$(RM) bpf_test_modorder_x/bpf_test_modorder_x.ko # force re-compilation
$(Q)$(MAKE) $(submake_extras) RESOLVE_BTFIDS=$(RESOLVE_BTFIDS) -C bpf_test_modorder_x
$(Q)cp bpf_test_modorder_x/bpf_test_modorder_x.ko $@
$(OUTPUT)/bpf_test_modorder_y.ko: $(VMLINUX_BTF) $(RESOLVE_BTFIDS) $(wildcard bpf_test_modorder_y/Makefile bpf_test_modorder_y/*.[ch])
$(call msg,MOD,,$@)
$(Q)$(RM) bpf_test_modorder_y/bpf_test_modorder_y.ko # force re-compilation
$(Q)$(MAKE) $(submake_extras) RESOLVE_BTFIDS=$(RESOLVE_BTFIDS) -C bpf_test_modorder_y
$(Q)cp bpf_test_modorder_y/bpf_test_modorder_y.ko $@
DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
ifneq ($(CROSS_COMPILE),)
CROSS_BPFTOOL := $(SCRATCH_DIR)/sbin/bpftool
......@@ -722,6 +736,8 @@ TRUNNER_EXTRA_SOURCES := test_progs.c \
ip_check_defrag_frags.h
TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \
$(OUTPUT)/bpf_test_no_cfi.ko \
$(OUTPUT)/bpf_test_modorder_x.ko \
$(OUTPUT)/bpf_test_modorder_y.ko \
$(OUTPUT)/liburandom_read.so \
$(OUTPUT)/xdp_synproxy \
$(OUTPUT)/sign-file \
......@@ -856,6 +872,8 @@ EXTRA_CLEAN := $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \
$(addprefix $(OUTPUT)/,*.o *.d *.skel.h *.lskel.h *.subskel.h \
no_alu32 cpuv4 bpf_gcc bpf_testmod.ko \
bpf_test_no_cfi.ko \
bpf_test_modorder_x.ko \
bpf_test_modorder_y.ko \
liburandom_read.so) \
$(OUTPUT)/FEATURE-DUMP.selftests
......
BPF_TESTMOD_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
KDIR ?= $(abspath $(BPF_TESTMOD_DIR)/../../../../..)
ifeq ($(V),1)
Q =
else
Q = @
endif
MODULES = bpf_test_modorder_x.ko
obj-m += bpf_test_modorder_x.o
all:
+$(Q)make -C $(KDIR) M=$(BPF_TESTMOD_DIR) modules
clean:
+$(Q)make -C $(KDIR) M=$(BPF_TESTMOD_DIR) clean
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/module.h>
#include <linux/init.h>
__bpf_kfunc_start_defs();
__bpf_kfunc int bpf_test_modorder_retx(void)
{
return 'x';
}
__bpf_kfunc_end_defs();
BTF_KFUNCS_START(bpf_test_modorder_kfunc_x_ids)
BTF_ID_FLAGS(func, bpf_test_modorder_retx);
BTF_KFUNCS_END(bpf_test_modorder_kfunc_x_ids)
static const struct btf_kfunc_id_set bpf_test_modorder_x_set = {
.owner = THIS_MODULE,
.set = &bpf_test_modorder_kfunc_x_ids,
};
static int __init bpf_test_modorder_x_init(void)
{
return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
&bpf_test_modorder_x_set);
}
static void __exit bpf_test_modorder_x_exit(void)
{
}
module_init(bpf_test_modorder_x_init);
module_exit(bpf_test_modorder_x_exit);
MODULE_DESCRIPTION("BPF selftest ordertest module X");
MODULE_LICENSE("GPL");
BPF_TESTMOD_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
KDIR ?= $(abspath $(BPF_TESTMOD_DIR)/../../../../..)
ifeq ($(V),1)
Q =
else
Q = @
endif
MODULES = bpf_test_modorder_y.ko
obj-m += bpf_test_modorder_y.o
all:
+$(Q)make -C $(KDIR) M=$(BPF_TESTMOD_DIR) modules
clean:
+$(Q)make -C $(KDIR) M=$(BPF_TESTMOD_DIR) clean
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/module.h>
#include <linux/init.h>
__bpf_kfunc_start_defs();
__bpf_kfunc int bpf_test_modorder_rety(void)
{
return 'y';
}
__bpf_kfunc_end_defs();
BTF_KFUNCS_START(bpf_test_modorder_kfunc_y_ids)
BTF_ID_FLAGS(func, bpf_test_modorder_rety);
BTF_KFUNCS_END(bpf_test_modorder_kfunc_y_ids)
static const struct btf_kfunc_id_set bpf_test_modorder_y_set = {
.owner = THIS_MODULE,
.set = &bpf_test_modorder_kfunc_y_ids,
};
static int __init bpf_test_modorder_y_init(void)
{
return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
&bpf_test_modorder_y_set);
}
static void __exit bpf_test_modorder_y_exit(void)
{
}
module_init(bpf_test_modorder_y_init);
module_exit(bpf_test_modorder_y_exit);
MODULE_DESCRIPTION("BPF selftest ordertest module Y");
MODULE_LICENSE("GPL");
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
#include <testing_helpers.h>
#include "kfunc_module_order.skel.h"
static int test_run_prog(const struct bpf_program *prog,
struct bpf_test_run_opts *opts)
{
int err;
err = bpf_prog_test_run_opts(bpf_program__fd(prog), opts);
if (!ASSERT_OK(err, "bpf_prog_test_run_opts"))
return err;
if (!ASSERT_EQ((int)opts->retval, 0, bpf_program__name(prog)))
return -EINVAL;
return 0;
}
void test_kfunc_module_order(void)
{
struct kfunc_module_order *skel;
char pkt_data[64] = {};
int err = 0;
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, test_opts, .data_in = pkt_data,
.data_size_in = sizeof(pkt_data));
err = load_module("bpf_test_modorder_x.ko",
env_verbosity > VERBOSE_NONE);
if (!ASSERT_OK(err, "load bpf_test_modorder_x.ko"))
return;
err = load_module("bpf_test_modorder_y.ko",
env_verbosity > VERBOSE_NONE);
if (!ASSERT_OK(err, "load bpf_test_modorder_y.ko"))
goto exit_modx;
skel = kfunc_module_order__open_and_load();
if (!ASSERT_OK_PTR(skel, "kfunc_module_order__open_and_load()")) {
err = -EINVAL;
goto exit_mods;
}
test_run_prog(skel->progs.call_kfunc_xy, &test_opts);
test_run_prog(skel->progs.call_kfunc_yx, &test_opts);
kfunc_module_order__destroy(skel);
exit_mods:
unload_module("bpf_test_modorder_y", env_verbosity > VERBOSE_NONE);
exit_modx:
unload_module("bpf_test_modorder_x", env_verbosity > VERBOSE_NONE);
}
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
extern int bpf_test_modorder_retx(void) __ksym;
extern int bpf_test_modorder_rety(void) __ksym;
SEC("classifier")
int call_kfunc_xy(struct __sk_buff *skb)
{
int ret1, ret2;
ret1 = bpf_test_modorder_retx();
ret2 = bpf_test_modorder_rety();
return ret1 == 'x' && ret2 == 'y' ? 0 : -1;
}
SEC("classifier")
int call_kfunc_yx(struct __sk_buff *skb)
{
int ret1, ret2;
ret1 = bpf_test_modorder_rety();
ret2 = bpf_test_modorder_retx();
return ret1 == 'y' && ret2 == 'x' ? 0 : -1;
}
char _license[] SEC("license") = "GPL";
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment