selftests/bpf: add bpf-gcc support
Now that binutils and gcc support for BPF is upstream, make use of it in BPF selftests using alu32-like approach. Share as much as possible of CFLAGS calculation with clang. Fixes only obvious issues, leaving more complex ones for later: - Use gcc-provided bpf-helpers.h instead of manually defining the helpers, change bpf_helpers.h include guard to avoid conflict. - Include <linux/stddef.h> for __always_inline. - Add $(OUTPUT)/../usr/include to include path in order to use local kernel headers instead of system kernel headers when building with O=. In order to activate the bpf-gcc support, one needs to configure binutils and gcc with --target=bpf and make them available in $PATH. In particular, gcc must be installed as `bpf-gcc`, which is the default. Right now with binutils 25a2915e8dba and gcc r275589 only a handful of tests work: # ./test_progs_bpf_gcc # Summary: 7/39 PASSED, 1 SKIPPED, 98 FAILED The reason for those failures are as follows: - Build errors: - `error: too many function arguments for eBPF` for __always_inline functions read_str_var and read_map_var - must be inlining issue, and for process_l3_headers_v6, which relies on optimizing away function arguments. - `error: indirect call in function, which are not supported by eBPF` where there are no obvious indirect calls in the source calls, e.g. in __encap_ipip_none. - `error: field 'lock' has incomplete type` for fields of `struct bpf_spin_lock` type - bpf_spin_lock is re#defined by bpf-helpers.h, so its usage is sensitive to order of #includes. - `error: eBPF stack limit exceeded` in sysctl_tcp_mem. - Load errors: - Missing object files due to above build errors. - `libbpf: failed to create map (name: 'test_ver.bss')`. - `libbpf: object file doesn't contain bpf program`. - `libbpf: Program '.text' contains unrecognized relo data pointing to section 0`. - `libbpf: BTF is required, but is missing or corrupted` - no BTF support in gcc yet. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Cc: Jose E. Marchesi <jose.marchesi@oracle.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
a2c11b0341
commit
4ce150b6a4
@ -17,6 +17,7 @@ LLC ?= llc
|
||||
LLVM_OBJCOPY ?= llvm-objcopy
|
||||
LLVM_READELF ?= llvm-readelf
|
||||
BTF_PAHOLE ?= pahole
|
||||
BPF_GCC ?= $(shell command -v bpf-gcc;)
|
||||
CFLAGS += -g -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(BPFDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include \
|
||||
-Dbpf_prog_load=bpf_prog_test_load \
|
||||
-Dbpf_load_program=bpf_test_load_program
|
||||
@ -46,6 +47,10 @@ ifneq ($(SUBREG_CODEGEN),)
|
||||
TEST_GEN_FILES += $(patsubst %.o,alu32/%.o, $(BPF_OBJ_FILES))
|
||||
endif
|
||||
|
||||
ifneq ($(BPF_GCC),)
|
||||
TEST_GEN_FILES += $(patsubst %.o,bpf_gcc/%.o, $(BPF_OBJ_FILES))
|
||||
endif
|
||||
|
||||
# Order correspond to 'make run_tests' order
|
||||
TEST_PROGS := test_kmod.sh \
|
||||
test_libbpf.sh \
|
||||
@ -137,16 +142,19 @@ endif
|
||||
#
|
||||
# Use '-idirafter': Don't interfere with include mechanics except where the
|
||||
# build would have failed anyways.
|
||||
CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \
|
||||
define get_sys_includes
|
||||
$(shell $(1) -v -E - </dev/null 2>&1 \
|
||||
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
|
||||
endef
|
||||
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
|
||||
BPF_CFLAGS = -I. -I./include/uapi -I../../../include/uapi \
|
||||
-I$(OUTPUT)/../usr/include -D__TARGET_ARCH_$(SRCARCH)
|
||||
|
||||
CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \
|
||||
$(CLANG_SYS_INCLUDES) \
|
||||
-Wno-compare-distinct-pointer-types \
|
||||
-D__TARGET_ARCH_$(SRCARCH)
|
||||
CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
|
||||
-Wno-compare-distinct-pointer-types
|
||||
|
||||
$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline
|
||||
$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
|
||||
$(OUTPUT)/test_l4lb_noinline.o: BPF_CFLAGS += -fno-inline
|
||||
$(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline
|
||||
|
||||
$(OUTPUT)/test_queue_map.o: test_queue_stack_map.h
|
||||
$(OUTPUT)/test_stack_map.o: test_queue_stack_map.h
|
||||
@ -163,12 +171,12 @@ BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
|
||||
/bin/rm -f ./llvm_btf_verify.o)
|
||||
|
||||
ifneq ($(BTF_LLVM_PROBE),)
|
||||
CLANG_FLAGS += -g
|
||||
BPF_CFLAGS += -g
|
||||
else
|
||||
ifneq ($(BTF_LLC_PROBE),)
|
||||
ifneq ($(BTF_PAHOLE_PROBE),)
|
||||
ifneq ($(BTF_OBJCOPY_PROBE),)
|
||||
CLANG_FLAGS += -g
|
||||
BPF_CFLAGS += -g
|
||||
LLC_FLAGS += -mattr=dwarfris
|
||||
DWARF2BTF = y
|
||||
endif
|
||||
@ -202,8 +210,8 @@ $(ALU32_BUILD_DIR)/test_progs_32: prog_tests/*.c
|
||||
|
||||
$(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR)/test_progs_32 \
|
||||
| $(ALU32_BUILD_DIR)
|
||||
($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \
|
||||
echo "clang failed") | \
|
||||
($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \
|
||||
-c $< -o - || echo "clang failed") | \
|
||||
$(LLC) -march=bpf -mattr=+alu32 -mcpu=$(CPU) $(LLC_FLAGS) \
|
||||
-filetype=obj -o $@
|
||||
ifeq ($(DWARF2BTF),y)
|
||||
@ -211,10 +219,37 @@ ifeq ($(DWARF2BTF),y)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(BPF_GCC),)
|
||||
GCC_SYS_INCLUDES = $(call get_sys_includes,gcc)
|
||||
IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \
|
||||
grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
|
||||
ifeq ($(IS_LITTLE_ENDIAN),)
|
||||
MENDIAN=-mbig-endian
|
||||
else
|
||||
MENDIAN=-mlittle-endian
|
||||
endif
|
||||
BPF_GCC_CFLAGS = $(GCC_SYS_INCLUDES) $(MENDIAN)
|
||||
BPF_GCC_BUILD_DIR = $(OUTPUT)/bpf_gcc
|
||||
TEST_CUSTOM_PROGS += $(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc
|
||||
$(BPF_GCC_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(BPF_GCC_BUILD_DIR)/urandom_read: $(OUTPUT)/urandom_read | $(BPF_GCC_BUILD_DIR)
|
||||
cp $< $@
|
||||
|
||||
$(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc: $(OUTPUT)/test_progs \
|
||||
| $(BPF_GCC_BUILD_DIR)
|
||||
cp $< $@
|
||||
|
||||
$(BPF_GCC_BUILD_DIR)/%.o: progs/%.c $(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc \
|
||||
| $(BPF_GCC_BUILD_DIR)
|
||||
$(BPF_GCC) $(BPF_CFLAGS) $(BPF_GCC_CFLAGS) -O2 -c $< -o $@
|
||||
endif
|
||||
|
||||
# Have one program compiled without "-target bpf" to test whether libbpf loads
|
||||
# it successfully
|
||||
$(OUTPUT)/test_xdp.o: progs/test_xdp.c
|
||||
($(CLANG) $(CLANG_FLAGS) -O2 -emit-llvm -c $< -o - || \
|
||||
($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -emit-llvm -c $< -o - || \
|
||||
echo "clang failed") | \
|
||||
$(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
|
||||
ifeq ($(DWARF2BTF),y)
|
||||
@ -222,8 +257,8 @@ ifeq ($(DWARF2BTF),y)
|
||||
endif
|
||||
|
||||
$(OUTPUT)/%.o: progs/%.c
|
||||
($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \
|
||||
echo "clang failed") | \
|
||||
($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \
|
||||
-c $< -o - || echo "clang failed") | \
|
||||
$(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
|
||||
ifeq ($(DWARF2BTF),y)
|
||||
$(BTF_PAHOLE) -J $@
|
||||
@ -282,6 +317,6 @@ $(VERIFIER_TESTS_H): $(VERIFIER_TEST_FILES) | $(VERIFIER_TESTS_DIR)
|
||||
echo '#endif' \
|
||||
) > $(VERIFIER_TESTS_H))
|
||||
|
||||
EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \
|
||||
EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) $(BPF_GCC_BUILD_DIR) \
|
||||
$(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \
|
||||
feature
|
||||
|
@ -1,12 +1,6 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
#ifndef __BPF_HELPERS_H
|
||||
#define __BPF_HELPERS_H
|
||||
|
||||
/* helper macro to place programs, maps, license in
|
||||
* different sections in elf_bpf file. Section names
|
||||
* are interpreted by elf_bpf loader
|
||||
*/
|
||||
#define SEC(NAME) __attribute__((section(NAME), used))
|
||||
#ifndef __BPF_HELPERS__
|
||||
#define __BPF_HELPERS__
|
||||
|
||||
#define __uint(name, val) int (*name)[val]
|
||||
#define __type(name, val) val *name
|
||||
@ -19,6 +13,14 @@
|
||||
##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
/* helper macro to place programs, maps, license in
|
||||
* different sections in elf_bpf file. Section names
|
||||
* are interpreted by elf_bpf loader
|
||||
*/
|
||||
#define SEC(NAME) __attribute__((section(NAME), used))
|
||||
|
||||
/* helper functions called from eBPF programs written in C */
|
||||
static void *(*bpf_map_lookup_elem)(void *map, const void *key) =
|
||||
(void *) BPF_FUNC_map_lookup_elem;
|
||||
@ -256,6 +258,12 @@ struct bpf_map_def {
|
||||
unsigned int numa_node;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <bpf-helpers.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
|
||||
struct ____btf_map_##name { \
|
||||
type_key key; \
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdint.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
|
Loading…
Reference in New Issue
Block a user