summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2019-09-12 12:05:43 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2019-09-16 03:32:00 -0400
commit4ce150b6a412f14074400eac5fc39d1a71c4ef0a (patch)
tree121c913c2aadff0b9419c94ca58baa53bf4f3563 /tools
parenta2c11b034142b9de9ab236aeeb53d6f39c3508aa (diff)
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>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/bpf/Makefile65
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h24
-rw-r--r--tools/testing/selftests/bpf/progs/test_tc_edt.c1
3 files changed, 67 insertions, 23 deletions
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 7f3196af1ae4..6889c19a628c 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -17,6 +17,7 @@ LLC ?= llc
17LLVM_OBJCOPY ?= llvm-objcopy 17LLVM_OBJCOPY ?= llvm-objcopy
18LLVM_READELF ?= llvm-readelf 18LLVM_READELF ?= llvm-readelf
19BTF_PAHOLE ?= pahole 19BTF_PAHOLE ?= pahole
20BPF_GCC ?= $(shell command -v bpf-gcc;)
20CFLAGS += -g -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(BPFDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include \ 21CFLAGS += -g -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(BPFDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include \
21 -Dbpf_prog_load=bpf_prog_test_load \ 22 -Dbpf_prog_load=bpf_prog_test_load \
22 -Dbpf_load_program=bpf_test_load_program 23 -Dbpf_load_program=bpf_test_load_program
@@ -46,6 +47,10 @@ ifneq ($(SUBREG_CODEGEN),)
46TEST_GEN_FILES += $(patsubst %.o,alu32/%.o, $(BPF_OBJ_FILES)) 47TEST_GEN_FILES += $(patsubst %.o,alu32/%.o, $(BPF_OBJ_FILES))
47endif 48endif
48 49
50ifneq ($(BPF_GCC),)
51TEST_GEN_FILES += $(patsubst %.o,bpf_gcc/%.o, $(BPF_OBJ_FILES))
52endif
53
49# Order correspond to 'make run_tests' order 54# Order correspond to 'make run_tests' order
50TEST_PROGS := test_kmod.sh \ 55TEST_PROGS := test_kmod.sh \
51 test_libbpf.sh \ 56 test_libbpf.sh \
@@ -137,16 +142,19 @@ endif
137# 142#
138# Use '-idirafter': Don't interfere with include mechanics except where the 143# Use '-idirafter': Don't interfere with include mechanics except where the
139# build would have failed anyways. 144# build would have failed anyways.
140CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \ 145define get_sys_includes
146$(shell $(1) -v -E - </dev/null 2>&1 \
141 | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') 147 | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
148endef
149CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
150BPF_CFLAGS = -I. -I./include/uapi -I../../../include/uapi \
151 -I$(OUTPUT)/../usr/include -D__TARGET_ARCH_$(SRCARCH)
142 152
143CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \ 153CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
144 $(CLANG_SYS_INCLUDES) \ 154 -Wno-compare-distinct-pointer-types
145 -Wno-compare-distinct-pointer-types \
146 -D__TARGET_ARCH_$(SRCARCH)
147 155
148$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline 156$(OUTPUT)/test_l4lb_noinline.o: BPF_CFLAGS += -fno-inline
149$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline 157$(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline
150 158
151$(OUTPUT)/test_queue_map.o: test_queue_stack_map.h 159$(OUTPUT)/test_queue_map.o: test_queue_stack_map.h
152$(OUTPUT)/test_stack_map.o: test_queue_stack_map.h 160$(OUTPUT)/test_stack_map.o: test_queue_stack_map.h
@@ -163,12 +171,12 @@ BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
163 /bin/rm -f ./llvm_btf_verify.o) 171 /bin/rm -f ./llvm_btf_verify.o)
164 172
165ifneq ($(BTF_LLVM_PROBE),) 173ifneq ($(BTF_LLVM_PROBE),)
166 CLANG_FLAGS += -g 174 BPF_CFLAGS += -g
167else 175else
168ifneq ($(BTF_LLC_PROBE),) 176ifneq ($(BTF_LLC_PROBE),)
169ifneq ($(BTF_PAHOLE_PROBE),) 177ifneq ($(BTF_PAHOLE_PROBE),)
170ifneq ($(BTF_OBJCOPY_PROBE),) 178ifneq ($(BTF_OBJCOPY_PROBE),)
171 CLANG_FLAGS += -g 179 BPF_CFLAGS += -g
172 LLC_FLAGS += -mattr=dwarfris 180 LLC_FLAGS += -mattr=dwarfris
173 DWARF2BTF = y 181 DWARF2BTF = y
174endif 182endif
@@ -202,8 +210,8 @@ $(ALU32_BUILD_DIR)/test_progs_32: prog_tests/*.c
202 210
203$(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR)/test_progs_32 \ 211$(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR)/test_progs_32 \
204 | $(ALU32_BUILD_DIR) 212 | $(ALU32_BUILD_DIR)
205 ($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \ 213 ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \
206 echo "clang failed") | \ 214 -c $< -o - || echo "clang failed") | \
207 $(LLC) -march=bpf -mattr=+alu32 -mcpu=$(CPU) $(LLC_FLAGS) \ 215 $(LLC) -march=bpf -mattr=+alu32 -mcpu=$(CPU) $(LLC_FLAGS) \
208 -filetype=obj -o $@ 216 -filetype=obj -o $@
209ifeq ($(DWARF2BTF),y) 217ifeq ($(DWARF2BTF),y)
@@ -211,10 +219,37 @@ ifeq ($(DWARF2BTF),y)
211endif 219endif
212endif 220endif
213 221
222ifneq ($(BPF_GCC),)
223GCC_SYS_INCLUDES = $(call get_sys_includes,gcc)
224IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \
225 grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
226ifeq ($(IS_LITTLE_ENDIAN),)
227MENDIAN=-mbig-endian
228else
229MENDIAN=-mlittle-endian
230endif
231BPF_GCC_CFLAGS = $(GCC_SYS_INCLUDES) $(MENDIAN)
232BPF_GCC_BUILD_DIR = $(OUTPUT)/bpf_gcc
233TEST_CUSTOM_PROGS += $(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc
234$(BPF_GCC_BUILD_DIR):
235 mkdir -p $@
236
237$(BPF_GCC_BUILD_DIR)/urandom_read: $(OUTPUT)/urandom_read | $(BPF_GCC_BUILD_DIR)
238 cp $< $@
239
240$(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc: $(OUTPUT)/test_progs \
241 | $(BPF_GCC_BUILD_DIR)
242 cp $< $@
243
244$(BPF_GCC_BUILD_DIR)/%.o: progs/%.c $(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc \
245 | $(BPF_GCC_BUILD_DIR)
246 $(BPF_GCC) $(BPF_CFLAGS) $(BPF_GCC_CFLAGS) -O2 -c $< -o $@
247endif
248
214# Have one program compiled without "-target bpf" to test whether libbpf loads 249# Have one program compiled without "-target bpf" to test whether libbpf loads
215# it successfully 250# it successfully
216$(OUTPUT)/test_xdp.o: progs/test_xdp.c 251$(OUTPUT)/test_xdp.o: progs/test_xdp.c
217 ($(CLANG) $(CLANG_FLAGS) -O2 -emit-llvm -c $< -o - || \ 252 ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -emit-llvm -c $< -o - || \
218 echo "clang failed") | \ 253 echo "clang failed") | \
219 $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@ 254 $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
220ifeq ($(DWARF2BTF),y) 255ifeq ($(DWARF2BTF),y)
@@ -222,8 +257,8 @@ ifeq ($(DWARF2BTF),y)
222endif 257endif
223 258
224$(OUTPUT)/%.o: progs/%.c 259$(OUTPUT)/%.o: progs/%.c
225 ($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \ 260 ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \
226 echo "clang failed") | \ 261 -c $< -o - || echo "clang failed") | \
227 $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@ 262 $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
228ifeq ($(DWARF2BTF),y) 263ifeq ($(DWARF2BTF),y)
229 $(BTF_PAHOLE) -J $@ 264 $(BTF_PAHOLE) -J $@
@@ -282,6 +317,6 @@ $(VERIFIER_TESTS_H): $(VERIFIER_TEST_FILES) | $(VERIFIER_TESTS_DIR)
282 echo '#endif' \ 317 echo '#endif' \
283 ) > $(VERIFIER_TESTS_H)) 318 ) > $(VERIFIER_TESTS_H))
284 319
285EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \ 320EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) $(BPF_GCC_BUILD_DIR) \
286 $(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \ 321 $(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \
287 feature 322 feature
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index 6c4930bc6e2e..54a50699bbfd 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -1,12 +1,6 @@
1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2#ifndef __BPF_HELPERS_H 2#ifndef __BPF_HELPERS__
3#define __BPF_HELPERS_H 3#define __BPF_HELPERS__
4
5/* helper macro to place programs, maps, license in
6 * different sections in elf_bpf file. Section names
7 * are interpreted by elf_bpf loader
8 */
9#define SEC(NAME) __attribute__((section(NAME), used))
10 4
11#define __uint(name, val) int (*name)[val] 5#define __uint(name, val) int (*name)[val]
12#define __type(name, val) val *name 6#define __type(name, val) val *name
@@ -19,6 +13,14 @@
19 ##__VA_ARGS__); \ 13 ##__VA_ARGS__); \
20}) 14})
21 15
16#ifdef __clang__
17
18/* helper macro to place programs, maps, license in
19 * different sections in elf_bpf file. Section names
20 * are interpreted by elf_bpf loader
21 */
22#define SEC(NAME) __attribute__((section(NAME), used))
23
22/* helper functions called from eBPF programs written in C */ 24/* helper functions called from eBPF programs written in C */
23static void *(*bpf_map_lookup_elem)(void *map, const void *key) = 25static void *(*bpf_map_lookup_elem)(void *map, const void *key) =
24 (void *) BPF_FUNC_map_lookup_elem; 26 (void *) BPF_FUNC_map_lookup_elem;
@@ -256,6 +258,12 @@ struct bpf_map_def {
256 unsigned int numa_node; 258 unsigned int numa_node;
257}; 259};
258 260
261#else
262
263#include <bpf-helpers.h>
264
265#endif
266
259#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ 267#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
260 struct ____btf_map_##name { \ 268 struct ____btf_map_##name { \
261 type_key key; \ 269 type_key key; \
diff --git a/tools/testing/selftests/bpf/progs/test_tc_edt.c b/tools/testing/selftests/bpf/progs/test_tc_edt.c
index 3af64c470d64..0961415ba477 100644
--- a/tools/testing/selftests/bpf/progs/test_tc_edt.c
+++ b/tools/testing/selftests/bpf/progs/test_tc_edt.c
@@ -2,6 +2,7 @@
2#include <stdint.h> 2#include <stdint.h>
3#include <linux/bpf.h> 3#include <linux/bpf.h>
4#include <linux/if_ether.h> 4#include <linux/if_ether.h>
5#include <linux/stddef.h>
5#include <linux/in.h> 6#include <linux/in.h>
6#include <linux/ip.h> 7#include <linux/ip.h>
7#include <linux/pkt_cls.h> 8#include <linux/pkt_cls.h>