XDP support will be used by a later patch to test the GRO path in a net namespace, leveraging the veth XDP implementation. To avoid breaking existing setup, XDP support is conditionally enabled and build only if llc is locally available.
rfc v2 -> rfc v3: - move 'x' option handling here Signed-off-by: Paolo Abeni <pab...@redhat.com> --- tools/testing/selftests/net/Makefile | 69 +++++++++++++++++++ tools/testing/selftests/net/udpgso_bench_rx.c | 41 ++++++++++- tools/testing/selftests/net/xdp_dummy.c | 13 ++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/net/xdp_dummy.c diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 256d82d5fa87..176459b7c4d6 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -16,8 +16,77 @@ TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls KSFT_KHDR_INSTALL := 1 + +# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: +# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang +LLC ?= llc +CLANG ?= clang +LLVM_OBJCOPY ?= llvm-objcopy +BTF_PAHOLE ?= pahole +HAS_LLC := $(shell which $(LLC) 2>/dev/null) + +# conditional enable testes requiring llc +ifneq (, $(HAS_LLC)) +TEST_GEN_FILES += xdp_dummy.o +endif + include ../lib.mk +ifneq (, $(HAS_LLC)) + +# Detect that we're cross compiling and use the cross compiler +ifdef CROSS_COMPILE +CLANG_ARCH_ARGS = -target $(ARCH) +endif + +PROBE := $(shell $(LLC) -march=bpf -mcpu=probe -filetype=null /dev/null 2>&1) + +# Let newer LLVM versions transparently probe the kernel for availability +# of full BPF instruction set. +ifeq ($(PROBE),) + CPU ?= probe +else + CPU ?= generic +endif + +SRC_PATH := $(abspath ../../../..) +LIB_PATH := $(SRC_PATH)/tools/lib +XDP_CFLAGS := -D SUPPORT_XDP=1 -I$(LIB_PATH) +LIBBPF = $(LIB_PATH)/bpf/libbpf.a +BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) +BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) +BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') +CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \ + | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') +CLANG_FLAGS = -I. -I$(SRC_PATH)/include -I../bpf/ \ + $(CLANG_SYS_INCLUDES) -Wno-compare-distinct-pointer-types + +ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),) + CLANG_CFLAGS += -g + LLC_FLAGS += -mattr=dwarfris + DWARF2BTF = y +endif + +$(LIBBPF): FORCE +# Fix up variables inherited from Kbuild that tools/ build system won't like + $(MAKE) -C $(dir $@) RM='rm -rf' LDFLAGS= srctree=$(SRC_PATH) O= $(nodir $@) + +$(OUTPUT)/udpgso_bench_rx: $(OUTPUT)/udpgso_bench_rx.c $(LIBBPF) + $(CC) -o $@ $(XDP_CFLAGS) $(CFLAGS) $(LOADLIBES) $(LDLIBS) $^ -lelf + +FORCE: + +# bpf program[s] generation +$(OUTPUT)/%.o: %.c + $(CLANG) $(CLANG_FLAGS) \ + -O2 -target bpf -emit-llvm -c $< -o - | \ + $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@ +ifeq ($(DWARF2BTF),y) + $(BTF_PAHOLE) -J $@ +endif + +endif + $(OUTPUT)/reuseport_bpf_numa: LDFLAGS += -lnuma $(OUTPUT)/tcp_mmap: LDFLAGS += -lpthread $(OUTPUT)/tcp_inq: LDFLAGS += -lpthread diff --git a/tools/testing/selftests/net/udpgso_bench_rx.c b/tools/testing/selftests/net/udpgso_bench_rx.c index 8f48d7fb32cf..5dcb719abe04 100644 --- a/tools/testing/selftests/net/udpgso_bench_rx.c +++ b/tools/testing/selftests/net/udpgso_bench_rx.c @@ -31,6 +31,10 @@ #include <sys/wait.h> #include <unistd.h> +#ifdef SUPPORT_XDP +#include "bpf/libbpf.h" +#endif + #ifndef UDP_GRO #define UDP_GRO 104 #endif @@ -40,6 +44,9 @@ static bool cfg_tcp; static bool cfg_verify; static bool cfg_read_all; static bool cfg_gro_segment; +#ifdef SUPPORT_XDP +static int cfg_xdp_iface; +#endif static bool interrupted; static unsigned long packets, bytes; @@ -202,14 +209,14 @@ static void do_flush_udp(int fd) static void usage(const char *filepath) { - error(1, 0, "Usage: %s [-Grtv] [-p port]", filepath); + error(1, 0, "Usage: %s [-Grtv] [-p port] [-x device]", filepath); } static void parse_opts(int argc, char **argv) { int c; - while ((c = getopt(argc, argv, "Gp:rtv")) != -1) { + while ((c = getopt(argc, argv, "Gp:rtvx:")) != -1) { switch (c) { case 'G': cfg_gro_segment = true; @@ -227,6 +234,13 @@ static void parse_opts(int argc, char **argv) cfg_verify = true; cfg_read_all = true; break; +#ifdef SUPPORT_XDP + case 'x': + cfg_xdp_iface = if_nametoindex(optarg); + if (!cfg_xdp_iface) + error(1, errno, "unknown interface %s", optarg); + break; +#endif } } @@ -240,6 +254,9 @@ static void parse_opts(int argc, char **argv) static void do_recv(void) { unsigned long tnow, treport; +#ifdef SUPPORT_XDP + int prog_fd = -1; +#endif int fd; fd = do_socket(cfg_tcp); @@ -250,6 +267,22 @@ static void do_recv(void) error(1, errno, "setsockopt UDP_GRO"); } +#ifdef SUPPORT_XDP + if (cfg_xdp_iface) { + struct bpf_prog_load_attr prog_load_attr = { + .prog_type = BPF_PROG_TYPE_XDP, + .file = "xdp_dummy.o", + }; + struct bpf_object *obj; + + if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) + error(1, errno, "xdp program load failed\n"); + + if (bpf_set_link_xdp_fd(cfg_xdp_iface, prog_fd, 0) < 0) + error(1, errno, "link set xdp fd failed\n"); + } +#endif + treport = gettimeofday_ms() + 1000; do { do_poll(fd); @@ -274,6 +307,10 @@ static void do_recv(void) if (close(fd)) error(1, errno, "close"); +#ifdef SUPPORT_XDP + if (cfg_xdp_iface && bpf_set_link_xdp_fd(cfg_xdp_iface, -1, 0)) + error(1, errno, "removing xdp program"); +#endif } int main(int argc, char **argv) diff --git a/tools/testing/selftests/net/xdp_dummy.c b/tools/testing/selftests/net/xdp_dummy.c new file mode 100644 index 000000000000..1a64cf5099ed --- /dev/null +++ b/tools/testing/selftests/net/xdp_dummy.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define KBUILD_MODNAME "xdp_dummy" +#include <uapi/linux/bpf.h> +#include "bpf_helpers.h" + +SEC("xdp_dummy") +int xdp_dummy_prog(struct xdp_md *ctx) +{ + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL"; -- 2.17.2