Daniel Borkmann says: ==================== pull-request: bpf-next 2019-09-16 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Now that initial BPF backend for gcc has been merged upstream, enable BPF kselftest suite for bpf-gcc. Also fix a BE issue with access to bpf_sysctl.file_pos, from Ilya. 2) Follow-up fix for link-vmlinux.sh to remove bash-specific extensions related to recent work on exposing BTF info through sysfs, from Andrii. 3) AF_XDP zero copy fixes for i40e and ixgbe driver which caused umem headroom to be added twice, from Ciara. 4) Refactoring work to convert sock opt tests into test_progs framework in BPF kselftests, from Stanislav. 5) Fix a general protection fault in dev_map_hash_update_elem(), from Toke. 6) Cleanup to use BPF_PROG_RUN() macro in KCM, from Sami. ====================
Unified · Split
| @@ -197,9 +197,9 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) · 196 unmodified lines | ||
| 197 | 197 | { |
| 198 | 198 | struct xdp_umem *umem = rx_ring->xsk_umem; |
| 199 | 199 | int err, result = I40E_XDP_PASS; |
| 200 | − u64 offset = umem->headroom; | |
| 201 | 200 | struct i40e_ring *xdp_ring; |
| 202 | 201 | struct bpf_prog *xdp_prog; |
| 202 | + u64 offset; | |
| 203 | 203 | u32 act; |
| 204 | 204 | |
| 205 | 205 | rcu_read_lock(); |
| @@ -208,7 +208,7 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) · 2 unmodified lines | ||
| 208 | 208 | */ |
| 209 | 209 | xdp_prog = READ_ONCE(rx_ring->xdp_prog); |
| 210 | 210 | act = bpf_prog_run_xdp(xdp_prog, xdp); |
| 211 | − offset += xdp->data - xdp->data_hard_start; | |
| 211 | + offset = xdp->data - xdp->data_hard_start; | |
| 212 | 212 | |
| 213 | 213 | xdp->handle = xsk_umem_adjust_offset(umem, xdp->handle, offset); |
| 214 | 214 | |
| @@ -145,15 +145,15 @@ static int ixgbe_run_xdp_zc(struct ixgbe_adapter *adapter, · 144 unmodified lines | ||
| 145 | 145 | { |
| 146 | 146 | struct xdp_umem *umem = rx_ring->xsk_umem; |
| 147 | 147 | int err, result = IXGBE_XDP_PASS; |
| 148 | − u64 offset = umem->headroom; | |
| 149 | 148 | struct bpf_prog *xdp_prog; |
| 150 | 149 | struct xdp_frame *xdpf; |
| 150 | + u64 offset; | |
| 151 | 151 | u32 act; |
| 152 | 152 | |
| 153 | 153 | rcu_read_lock(); |
| 154 | 154 | xdp_prog = READ_ONCE(rx_ring->xdp_prog); |
| 155 | 155 | act = bpf_prog_run_xdp(xdp_prog, xdp); |
| 156 | − offset += xdp->data - xdp->data_hard_start; | |
| 156 | + offset = xdp->data - xdp->data_hard_start; | |
| 157 | 157 | |
| 158 | 158 | xdp->handle = xsk_umem_adjust_offset(umem, xdp->handle, offset); |
| 159 | 159 | |
| @@ -749,14 +749,14 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default) · 748 unmodified lines | ||
| 749 | 749 | } |
| 750 | 750 | |
| 751 | 751 | static inline u8 |
| 752 | −bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default) | |
| 752 | +bpf_ctx_narrow_access_offset(u32 off, u32 size, u32 size_default) | |
| 753 | 753 | { |
| 754 | − u8 load_off = off & (size_default - 1); | |
| 754 | + u8 access_off = off & (size_default - 1); | |
| 755 | 755 | |
| 756 | 756 | #ifdef __LITTLE_ENDIAN |
| 757 | − return load_off * 8; | |
| 757 | + return access_off; | |
| 758 | 758 | #else |
| 759 | − return (size_default - (load_off + size)) * 8; | |
| 759 | + return size_default - (access_off + size); | |
| 760 | 760 | #endif |
| 761 | 761 | } |
| 762 | 762 | |
| @@ -1334,6 +1334,7 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type, · 1333 unmodified lines | ||
| 1334 | 1334 | struct bpf_prog *prog, u32 *target_size) |
| 1335 | 1335 | { |
| 1336 | 1336 | struct bpf_insn *insn = insn_buf; |
| 1337 | + u32 read_size; | |
| 1337 | 1338 | |
| 1338 | 1339 | switch (si->off) { |
| 1339 | 1340 | case offsetof(struct bpf_sysctl, write): |
| @@ -1365,7 +1366,9 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type, · 25 unmodified lines | ||
| 1365 | 1366 | treg, si->dst_reg, |
| 1366 | 1367 | offsetof(struct bpf_sysctl_kern, ppos)); |
| 1367 | 1368 | *insn++ = BPF_STX_MEM( |
| 1368 | − BPF_SIZEOF(u32), treg, si->src_reg, 0); | |
| 1369 | + BPF_SIZEOF(u32), treg, si->src_reg, | |
| 1370 | + bpf_ctx_narrow_access_offset( | |
| 1371 | + 0, sizeof(u32), sizeof(loff_t))); | |
| 1369 | 1372 | *insn++ = BPF_LDX_MEM( |
| 1370 | 1373 | BPF_DW, treg, si->dst_reg, |
| 1371 | 1374 | offsetof(struct bpf_sysctl_kern, tmp_reg)); |
| @@ -1374,8 +1377,11 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type, · 2 unmodified lines | ||
| 1374 | 1377 | BPF_FIELD_SIZEOF(struct bpf_sysctl_kern, ppos), |
| 1375 | 1378 | si->dst_reg, si->src_reg, |
| 1376 | 1379 | offsetof(struct bpf_sysctl_kern, ppos)); |
| 1380 | + read_size = bpf_size_to_bytes(BPF_SIZE(si->code)); | |
| 1377 | 1381 | *insn++ = BPF_LDX_MEM( |
| 1378 | − BPF_SIZE(si->code), si->dst_reg, si->dst_reg, 0); | |
| 1382 | + BPF_SIZE(si->code), si->dst_reg, si->dst_reg, | |
| 1383 | + bpf_ctx_narrow_access_offset( | |
| 1384 | + 0, read_size, sizeof(loff_t))); | |
| 1379 | 1385 | } |
| 1380 | 1386 | *target_size = sizeof(u32); |
| 1381 | 1387 | break; |
| @@ -650,19 +650,22 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, · 649 unmodified lines | ||
| 650 | 650 | u32 ifindex = *(u32 *)value; |
| 651 | 651 | u32 idx = *(u32 *)key; |
| 652 | 652 | unsigned long flags; |
| 653 | + int err = -EEXIST; | |
| 653 | 654 | |
| 654 | 655 | if (unlikely(map_flags > BPF_EXIST || !ifindex)) |
| 655 | 656 | return -EINVAL; |
| 656 | 657 | |
| 658 | + spin_lock_irqsave(&dtab->index_lock, flags); | |
| 659 | + | |
| 657 | 660 | old_dev = __dev_map_hash_lookup_elem(map, idx); |
| 658 | 661 | if (old_dev && (map_flags & BPF_NOEXIST)) |
| 659 | − return -EEXIST; | |
| 662 | + goto out_err; | |
| 660 | 663 | |
| 661 | 664 | dev = __dev_map_alloc_node(net, dtab, ifindex, idx); |
| 662 | − if (IS_ERR(dev)) | |
| 663 | − return PTR_ERR(dev); | |
| 664 | − | |
| 665 | − spin_lock_irqsave(&dtab->index_lock, flags); | |
| 665 | + if (IS_ERR(dev)) { | |
| 666 | + err = PTR_ERR(dev); | |
| 667 | + goto out_err; | |
| 668 | + } | |
| 666 | 669 | |
| 667 | 670 | if (old_dev) { |
| 668 | 671 | hlist_del_rcu(&old_dev->index_hlist); |
| @@ -683,6 +686,10 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, · 14 unmodified lines | ||
| 683 | 686 | call_rcu(&old_dev->rcu, __dev_map_entry_free); |
| 684 | 687 | |
| 685 | 688 | return 0; |
| 689 | + | |
| 690 | +out_err: | |
| 691 | + spin_unlock_irqrestore(&dtab->index_lock, flags); | |
| 692 | + return err; | |
| 686 | 693 | } |
| 687 | 694 | |
| 688 | 695 | static int dev_map_hash_update_elem(struct bpf_map *map, void *key, void *value, |
| @@ -8624,8 +8624,8 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) · 8623 unmodified lines | ||
| 8624 | 8624 | } |
| 8625 | 8625 | |
| 8626 | 8626 | if (is_narrower_load && size < target_size) { |
| 8627 | − u8 shift = bpf_ctx_narrow_load_shift(off, size, | |
| 8628 | − size_default); | |
| 8627 | + u8 shift = bpf_ctx_narrow_access_offset( | |
| 8628 | + off, size, size_default) * 8; | |
| 8629 | 8629 | if (ctx_field_size <= 4) { |
| 8630 | 8630 | if (shift) |
| 8631 | 8631 | insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH, |
| @@ -379,7 +379,7 @@ static int kcm_parse_func_strparser(struct strparser *strp, struct sk_buff *skb) · 378 unmodified lines | ||
| 379 | 379 | struct kcm_psock *psock = container_of(strp, struct kcm_psock, strp); |
| 380 | 380 | struct bpf_prog *prog = psock->bpf_prog; |
| 381 | 381 | |
| 382 | − return (*prog->bpf_func)(skb, prog->insnsi); | |
| 382 | + return BPF_PROG_RUN(prog, skb); | |
| 383 | 383 | } |
| 384 | 384 | |
| 385 | 385 | static int kcm_read_sock_done(struct strparser *strp, int err) |
| @@ -685,7 +685,7 @@ static void l2fwd(struct xsk_socket_info *xsk, struct pollfd *fds) · 684 unmodified lines | ||
| 685 | 685 | for (i = 0; i < rcvd; i++) { |
| 686 | 686 | u64 addr = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx)->addr; |
| 687 | 687 | u32 len = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++)->len; |
| 688 | − u64 orig = xsk_umem__extract_addr(addr); | |
| 688 | + u64 orig = addr; | |
| 689 | 689 | |
| 690 | 690 | addr = xsk_umem__add_offset_to_addr(addr); |
| 691 | 691 | char *pkt = xsk_umem__get_data(xsk->umem->buffer, addr); |
| @@ -57,12 +57,16 @@ modpost_link() · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | # Link of vmlinux |
| 59 | 59 | # ${1} - output file |
| 60 | −# ${@:2} - optional extra .o files | |
| 60 | +# ${2}, ${3}, ... - optional extra .o files | |
| 61 | 61 | vmlinux_link() |
| 62 | 62 | { |
| 63 | 63 | local lds="${objtree}/${KBUILD_LDS}" |
| 64 | + local output=${1} | |
| 64 | 65 | local objects |
| 65 | 66 | |
| 67 | + # skip output file argument | |
| 68 | + shift | |
| 69 | + | |
| 66 | 70 | if [ "${SRCARCH}" != "um" ]; then |
| 67 | 71 | objects="--whole-archive \ |
| 68 | 72 | ${KBUILD_VMLINUX_OBJS} \ |
| @@ -70,9 +74,10 @@ vmlinux_link() · 1 unmodified line | ||
| 70 | 74 | --start-group \ |
| 71 | 75 | ${KBUILD_VMLINUX_LIBS} \ |
| 72 | 76 | --end-group \ |
| 73 | − ${@:2}" | |
| 77 | + ${@}" | |
| 74 | 78 | |
| 75 | − ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${1} \ | |
| 79 | + ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \ | |
| 80 | + -o ${output} \ | |
| 76 | 81 | -T ${lds} ${objects} |
| 77 | 82 | else |
| 78 | 83 | objects="-Wl,--whole-archive \ |
| @@ -81,9 +86,10 @@ vmlinux_link() · 2 unmodified lines | ||
| 81 | 86 | -Wl,--start-group \ |
| 82 | 87 | ${KBUILD_VMLINUX_LIBS} \ |
| 83 | 88 | -Wl,--end-group \ |
| 84 | − ${@:2}" | |
| 89 | + ${@}" | |
| 85 | 90 | |
| 86 | − ${CC} ${CFLAGS_vmlinux} -o ${1} \ | |
| 91 | + ${CC} ${CFLAGS_vmlinux} \ | |
| 92 | + -o ${output} \ | |
| 87 | 93 | -Wl,-T,${lds} \ |
| 88 | 94 | ${objects} \ |
| 89 | 95 | -lutil -lrt -lpthread |
| @@ -39,8 +39,3 @@ libbpf.so.* · 38 unmodified lines | ||
| 39 | 39 | test_hashmap |
| 40 | 40 | test_btf_dump |
| 41 | 41 | xdping |
| 42 | −test_sockopt | |
| 43 | −test_sockopt_sk | |
| 44 | −test_sockopt_multi | |
| 45 | −test_sockopt_inherit | |
| 46 | −test_tcp_rtt | |
| @@ -17,6 +17,7 @@ LLC ?= llc · 16 unmodified lines | ||
| 17 | 17 | LLVM_OBJCOPY ?= llvm-objcopy |
| 18 | 18 | LLVM_READELF ?= llvm-readelf |
| 19 | 19 | BTF_PAHOLE ?= pahole |
| 20 | +BPF_GCC ?= $(shell command -v bpf-gcc;) | |
| 20 | 21 | CFLAGS += -g -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(BPFDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include \ |
| 21 | 22 | -Dbpf_prog_load=bpf_prog_test_load \ |
| 22 | 23 | -Dbpf_load_program=bpf_test_load_program |
| @@ -28,8 +29,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test · 5 unmodified lines | ||
| 28 | 29 | test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \ |
| 29 | 30 | test_cgroup_storage test_select_reuseport test_section_names \ |
| 30 | 31 | test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \ |
| 31 | − test_btf_dump test_cgroup_attach xdping test_sockopt test_sockopt_sk \ | |
| 32 | − test_sockopt_multi test_sockopt_inherit test_tcp_rtt | |
| 32 | + test_btf_dump test_cgroup_attach xdping | |
| 33 | 33 | |
| 34 | 34 | BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c))) |
| 35 | 35 | TEST_GEN_FILES = $(BPF_OBJ_FILES) |
| @@ -47,6 +47,10 @@ ifneq ($(SUBREG_CODEGEN),) · 11 unmodified lines | ||
| 47 | 47 | TEST_GEN_FILES += $(patsubst %.o,alu32/%.o, $(BPF_OBJ_FILES)) |
| 48 | 48 | endif |
| 49 | 49 | |
| 50 | +ifneq ($(BPF_GCC),) | |
| 51 | +TEST_GEN_FILES += $(patsubst %.o,bpf_gcc/%.o, $(BPF_OBJ_FILES)) | |
| 52 | +endif | |
| 53 | + | |
| 50 | 54 | # Order correspond to 'make run_tests' order |
| 51 | 55 | TEST_PROGS := test_kmod.sh \ |
| 52 | 56 | test_libbpf.sh \ |
| @@ -106,18 +110,13 @@ $(OUTPUT)/test_socket_cookie: cgroup_helpers.c · 53 unmodified lines | ||
| 106 | 110 | $(OUTPUT)/test_sockmap: cgroup_helpers.c |
| 107 | 111 | $(OUTPUT)/test_tcpbpf_user: cgroup_helpers.c |
| 108 | 112 | $(OUTPUT)/test_tcpnotify_user: cgroup_helpers.c trace_helpers.c |
| 109 | −$(OUTPUT)/test_progs: trace_helpers.c | |
| 113 | +$(OUTPUT)/test_progs: cgroup_helpers.c trace_helpers.c | |
| 110 | 114 | $(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c |
| 111 | 115 | $(OUTPUT)/test_cgroup_storage: cgroup_helpers.c |
| 112 | 116 | $(OUTPUT)/test_netcnt: cgroup_helpers.c |
| 113 | 117 | $(OUTPUT)/test_sock_fields: cgroup_helpers.c |
| 114 | 118 | $(OUTPUT)/test_sysctl: cgroup_helpers.c |
| 115 | 119 | $(OUTPUT)/test_cgroup_attach: cgroup_helpers.c |
| 116 | −$(OUTPUT)/test_sockopt: cgroup_helpers.c | |
| 117 | −$(OUTPUT)/test_sockopt_sk: cgroup_helpers.c | |
| 118 | −$(OUTPUT)/test_sockopt_multi: cgroup_helpers.c | |
| 119 | −$(OUTPUT)/test_sockopt_inherit: cgroup_helpers.c | |
| 120 | −$(OUTPUT)/test_tcp_rtt: cgroup_helpers.c | |
| 121 | 120 | |
| 122 | 121 | .PHONY: force |
| 123 | 122 | |
| @@ -143,16 +142,19 @@ endif · 19 unmodified lines | ||
| 143 | 142 | # |
| 144 | 143 | # Use '-idirafter': Don't interfere with include mechanics except where the |
| 145 | 144 | # build would have failed anyways. |
| 146 | −CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \ | |
| 145 | +define get_sys_includes | |
| 146 | +$(shell $(1) -v -E - </dev/null 2>&1 \ | |
| 147 | 147 | | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') |
| 148 | +endef | |
| 149 | +CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG)) | |
| 150 | +BPF_CFLAGS = -I. -I./include/uapi -I../../../include/uapi \ | |
| 151 | + -I$(OUTPUT)/../usr/include -D__TARGET_ARCH_$(SRCARCH) | |
| 148 | 152 | |
| 149 | −CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \ | |
| 150 | − $(CLANG_SYS_INCLUDES) \ | |
| 151 | − -Wno-compare-distinct-pointer-types \ | |
| 152 | − -D__TARGET_ARCH_$(SRCARCH) | |
| 153 | +CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \ | |
| 154 | + -Wno-compare-distinct-pointer-types | |
| 153 | 155 | |
| 154 | −$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline | |
| 155 | −$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline | |
| 156 | +$(OUTPUT)/test_l4lb_noinline.o: BPF_CFLAGS += -fno-inline | |
| 157 | +$(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline | |
| 156 | 158 | |
| 157 | 159 | $(OUTPUT)/test_queue_map.o: test_queue_stack_map.h |
| 158 | 160 | $(OUTPUT)/test_stack_map.o: test_queue_stack_map.h |
| @@ -169,12 +171,12 @@ BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \ · 10 unmodified lines | ||
| 169 | 171 | /bin/rm -f ./llvm_btf_verify.o) |
| 170 | 172 | |
| 171 | 173 | ifneq ($(BTF_LLVM_PROBE),) |
| 172 | − CLANG_FLAGS += -g | |
| 174 | + BPF_CFLAGS += -g | |
| 173 | 175 | else |
| 174 | 176 | ifneq ($(BTF_LLC_PROBE),) |
| 175 | 177 | ifneq ($(BTF_PAHOLE_PROBE),) |
| 176 | 178 | ifneq ($(BTF_OBJCOPY_PROBE),) |
| 177 | − CLANG_FLAGS += -g | |
| 179 | + BPF_CFLAGS += -g | |
| 178 | 180 | LLC_FLAGS += -mattr=dwarfris |
| 179 | 181 | DWARF2BTF = y |
| 180 | 182 | endif |
| @@ -200,7 +202,7 @@ $(ALU32_BUILD_DIR)/test_progs_32: test_progs.c $(OUTPUT)/libbpf.a\ · 19 unmodified lines | ||
| 200 | 202 | | $(ALU32_BUILD_DIR) |
| 201 | 203 | $(CC) $(TEST_PROGS_CFLAGS) $(CFLAGS) \ |
| 202 | 204 | -o $(ALU32_BUILD_DIR)/test_progs_32 \ |
| 203 | − test_progs.c test_stub.c trace_helpers.c prog_tests/*.c \ | |
| 205 | + test_progs.c test_stub.c cgroup_helpers.c trace_helpers.c prog_tests/*.c \ | |
| 204 | 206 | $(OUTPUT)/libbpf.a $(LDLIBS) |
| 205 | 207 | |
| 206 | 208 | $(ALU32_BUILD_DIR)/test_progs_32: $(PROG_TESTS_H) |
| @@ -208,8 +210,8 @@ $(ALU32_BUILD_DIR)/test_progs_32: prog_tests/*.c · 1 unmodified line | ||
| 208 | 210 | |
| 209 | 211 | $(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR)/test_progs_32 \ |
| 210 | 212 | | $(ALU32_BUILD_DIR) |
| 211 | − ($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \ | |
| 212 | − echo "clang failed") | \ | |
| 213 | + ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \ | |
| 214 | + -c $< -o - || echo "clang failed") | \ | |
| 213 | 215 | $(LLC) -march=bpf -mattr=+alu32 -mcpu=$(CPU) $(LLC_FLAGS) \ |
| 214 | 216 | -filetype=obj -o $@ |
| 215 | 217 | ifeq ($(DWARF2BTF),y) |
| @@ -217,10 +219,37 @@ ifeq ($(DWARF2BTF),y) · 1 unmodified line | ||
| 217 | 219 | endif |
| 218 | 220 | endif |
| 219 | 221 | |
| 222 | +ifneq ($(BPF_GCC),) | |
| 223 | +GCC_SYS_INCLUDES = $(call get_sys_includes,gcc) | |
| 224 | +IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \ | |
| 225 | + grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__') | |
| 226 | +ifeq ($(IS_LITTLE_ENDIAN),) | |
| 227 | +MENDIAN=-mbig-endian | |
| 228 | +else | |
| 229 | +MENDIAN=-mlittle-endian | |
| 230 | +endif | |
| 231 | +BPF_GCC_CFLAGS = $(GCC_SYS_INCLUDES) $(MENDIAN) | |
| 232 | +BPF_GCC_BUILD_DIR = $(OUTPUT)/bpf_gcc | |
| 233 | +TEST_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 $@ | |
| 247 | +endif | |
| 248 | + | |
| 220 | 249 | # Have one program compiled without "-target bpf" to test whether libbpf loads |
| 221 | 250 | # it successfully |
| 222 | 251 | $(OUTPUT)/test_xdp.o: progs/test_xdp.c |
| 223 | − ($(CLANG) $(CLANG_FLAGS) -O2 -emit-llvm -c $< -o - || \ | |
| 252 | + ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -emit-llvm -c $< -o - || \ | |
| 224 | 253 | echo "clang failed") | \ |
| 225 | 254 | $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@ |
| 226 | 255 | ifeq ($(DWARF2BTF),y) |
| @@ -228,8 +257,8 @@ ifeq ($(DWARF2BTF),y) · 1 unmodified line | ||
| 228 | 257 | endif |
| 229 | 258 | |
| 230 | 259 | $(OUTPUT)/%.o: progs/%.c |
| 231 | − ($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \ | |
| 232 | − echo "clang failed") | \ | |
| 260 | + ($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \ | |
| 261 | + -c $< -o - || echo "clang failed") | \ | |
| 233 | 262 | $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@ |
| 234 | 263 | ifeq ($(DWARF2BTF),y) |
| 235 | 264 | $(BTF_PAHOLE) -J $@ |
| @@ -288,6 +317,6 @@ $(VERIFIER_TESTS_H): $(VERIFIER_TEST_FILES) | $(VERIFIER_TESTS_DIR) · 52 unmodified lines | ||
| 288 | 317 | echo '#endif' \ |
| 289 | 318 | ) > $(VERIFIER_TESTS_H)) |
| 290 | 319 | |
| 291 | −EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \ | |
| 320 | +EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) $(BPF_GCC_BUILD_DIR) \ | |
| 292 | 321 | $(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \ |
| 293 | 322 | feature |
| @@ -1,12 +1,6 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ |
| 2 | −#ifndef __BPF_HELPERS_H | |
| 3 | −#define __BPF_HELPERS_H | |
| 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)) | |
| 2 | +#ifndef __BPF_HELPERS__ | |
| 3 | +#define __BPF_HELPERS__ | |
| 10 | 4 | |
| 11 | 5 | #define __uint(name, val) int (*name)[val] |
| 12 | 6 | #define __type(name, val) val *name |
| @@ -19,6 +13,14 @@ · 6 unmodified lines | ||
| 19 | 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 | 24 | /* helper functions called from eBPF programs written in C */ |
| 23 | 25 | static void *(*bpf_map_lookup_elem)(void *map, const void *key) = |
| 24 | 26 | (void *) BPF_FUNC_map_lookup_elem; |
| @@ -256,6 +258,12 @@ struct bpf_map_def { · 231 unmodified lines | ||
| 256 | 258 | unsigned int numa_node; |
| 257 | 259 | }; |
| 258 | 260 | |
| 261 | +#else | |
| 262 | + | |
| 263 | +#include <bpf-helpers.h> | |
| 264 | + | |
| 265 | +#endif | |
| 266 | + | |
| 259 | 267 | #define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ |
| 260 | 268 | struct ____btf_map_##name { \ |
| 261 | 269 | type_key key; \ |
| @@ -1,22 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | − | |
| 3 | −#include <errno.h> | |
| 4 | −#include <stdio.h> | |
| 5 | −#include <unistd.h> | |
| 6 | −#include <sys/types.h> | |
| 7 | −#include <sys/socket.h> | |
| 8 | −#include <netinet/in.h> | |
| 9 | − | |
| 10 | −#include <linux/filter.h> | |
| 11 | −#include <bpf/bpf.h> | |
| 12 | −#include <bpf/libbpf.h> | |
| 13 | − | |
| 14 | −#include "bpf_rlimit.h" | |
| 15 | −#include "bpf_util.h" | |
| 2 | +#include <test_progs.h> | |
| 16 | 3 | #include "cgroup_helpers.h" |
| 17 | 4 | |
| 18 | −#define CG_PATH "/sockopt" | |
| 19 | − | |
| 20 | 5 | static char bpf_log_buf[4096]; |
| 21 | 6 | static bool verbose; |
| 22 | 7 | |
| @@ -983,39 +968,18 @@ close_prog_fd: · 960 unmodified lines | ||
| 983 | 968 | return ret; |
| 984 | 969 | } |
| 985 | 970 | |
| 986 | −int main(int args, char **argv) | |
| 971 | +void test_sockopt(void) | |
| 987 | 972 | { |
| 988 | − int err = EXIT_FAILURE, error_cnt = 0; | |
| 989 | 973 | int cgroup_fd, i; |
| 990 | 974 | |
| 991 | − if (setup_cgroup_environment()) | |
| 992 | − goto cleanup_obj; | |
| 993 | − | |
| 994 | − cgroup_fd = create_and_get_cgroup(CG_PATH); | |
| 995 | − if (cgroup_fd < 0) | |
| 996 | − goto cleanup_cgroup_env; | |
| 997 | − | |
| 998 | − if (join_cgroup(CG_PATH)) | |
| 999 | − goto cleanup_cgroup; | |
| 975 | + cgroup_fd = test__join_cgroup("/sockopt"); | |
| 976 | + if (CHECK_FAIL(cgroup_fd < 0)) | |
| 977 | + return; | |
| 1000 | 978 | |
| 1001 | 979 | for (i = 0; i < ARRAY_SIZE(tests); i++) { |
| 1002 | − int err = run_test(cgroup_fd, &tests[i]); | |
| 1003 | − | |
| 1004 | − if (err) | |
| 1005 | − error_cnt++; | |
| 1006 | − | |
| 1007 | − printf("#%d %s: %s\n", i, err ? "FAIL" : "PASS", | |
| 1008 | − tests[i].descr); | |
| 980 | + test__start_subtest(tests[i].descr); | |
| 981 | + CHECK_FAIL(run_test(cgroup_fd, &tests[i])); | |
| 1009 | 982 | } |
| 1010 | 983 | |
| 1011 | − printf("Summary: %ld PASSED, %d FAILED\n", | |
| 1012 | − ARRAY_SIZE(tests) - error_cnt, error_cnt); | |
| 1013 | − err = error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; | |
| 1014 | − | |
| 1015 | −cleanup_cgroup: | |
| 1016 | 984 | close(cgroup_fd); |
| 1017 | −cleanup_cgroup_env: | |
| 1018 | − cleanup_cgroup_environment(); | |
| 1019 | −cleanup_obj: | |
| 1020 | − return err; | |
| 1021 | 985 | } |
| @@ -1,22 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −#include <error.h> | |
| 3 | −#include <errno.h> | |
| 4 | −#include <stdio.h> | |
| 5 | −#include <unistd.h> | |
| 6 | −#include <sys/types.h> | |
| 7 | −#include <sys/socket.h> | |
| 8 | −#include <netinet/in.h> | |
| 9 | −#include <pthread.h> | |
| 10 | − | |
| 11 | −#include <linux/filter.h> | |
| 12 | −#include <bpf/bpf.h> | |
| 13 | −#include <bpf/libbpf.h> | |
| 14 | − | |
| 15 | −#include "bpf_rlimit.h" | |
| 16 | −#include "bpf_util.h" | |
| 2 | +#include <test_progs.h> | |
| 17 | 3 | #include "cgroup_helpers.h" |
| 18 | 4 | |
| 19 | −#define CG_PATH "/sockopt_inherit" | |
| 20 | 5 | #define SOL_CUSTOM 0xdeadbeef |
| 21 | 6 | #define CUSTOM_INHERIT1 0 |
| 22 | 7 | #define CUSTOM_INHERIT2 1 |
| @@ -74,6 +59,9 @@ static int verify_sockopt(int fd, int optname, const char *msg, char expected) · 51 unmodified lines | ||
| 74 | 59 | return 0; |
| 75 | 60 | } |
| 76 | 61 | |
| 62 | +static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER; | |
| 63 | +static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER; | |
| 64 | + | |
| 77 | 65 | static void *server_thread(void *arg) |
| 78 | 66 | { |
| 79 | 67 | struct sockaddr_storage addr; |
| @@ -82,16 +70,26 @@ static void *server_thread(void *arg) · 2 unmodified lines | ||
| 82 | 70 | int client_fd; |
| 83 | 71 | int err = 0; |
| 84 | 72 | |
| 85 | − if (listen(fd, 1) < 0) | |
| 86 | − error(1, errno, "Failed to listed on socket"); | |
| 73 | + err = listen(fd, 1); | |
| 74 | + | |
| 75 | + pthread_mutex_lock(&server_started_mtx); | |
| 76 | + pthread_cond_signal(&server_started); | |
| 77 | + pthread_mutex_unlock(&server_started_mtx); | |
| 78 | + | |
| 79 | + if (CHECK_FAIL(err < 0)) { | |
| 80 | + perror("Failed to listed on socket"); | |
| 81 | + return NULL; | |
| 82 | + } | |
| 87 | 83 | |
| 88 | 84 | err += verify_sockopt(fd, CUSTOM_INHERIT1, "listen", 1); |
| 89 | 85 | err += verify_sockopt(fd, CUSTOM_INHERIT2, "listen", 1); |
| 90 | 86 | err += verify_sockopt(fd, CUSTOM_LISTENER, "listen", 1); |
| 91 | 87 | |
| 92 | 88 | client_fd = accept(fd, (struct sockaddr *)&addr, &len); |
| 93 | − if (client_fd < 0) | |
| 94 | − error(1, errno, "Failed to accept client"); | |
| 89 | + if (CHECK_FAIL(client_fd < 0)) { | |
| 90 | + perror("Failed to accept client"); | |
| 91 | + return NULL; | |
| 92 | + } | |
| 95 | 93 | |
| 96 | 94 | err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "accept", 1); |
| 97 | 95 | err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "accept", 1); |
| @@ -167,7 +165,7 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) · 69 unmodified lines | ||
| 167 | 165 | return 0; |
| 168 | 166 | } |
| 169 | 167 | |
| 170 | −static int run_test(int cgroup_fd) | |
| 168 | +static void run_test(int cgroup_fd) | |
| 171 | 169 | { |
| 172 | 170 | struct bpf_prog_load_attr attr = { |
| 173 | 171 | .file = "./sockopt_inherit.o", |
| @@ -180,40 +178,41 @@ static int run_test(int cgroup_fd) · 6 unmodified lines | ||
| 180 | 178 | int err; |
| 181 | 179 | |
| 182 | 180 | err = bpf_prog_load_xattr(&attr, &obj, &ignored); |
| 183 | − if (err) { | |
| 184 | − log_err("Failed to load BPF object"); | |
| 185 | − return -1; | |
| 186 | − } | |
| 181 | + if (CHECK_FAIL(err)) | |
| 182 | + return; | |
| 187 | 183 | |
| 188 | 184 | err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); |
| 189 | − if (err) | |
| 185 | + if (CHECK_FAIL(err)) | |
| 190 | 186 | goto close_bpf_object; |
| 191 | 187 | |
| 192 | 188 | err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); |
| 193 | − if (err) | |
| 189 | + if (CHECK_FAIL(err)) | |
| 194 | 190 | goto close_bpf_object; |
| 195 | 191 | |
| 196 | 192 | server_fd = start_server(); |
| 197 | − if (server_fd < 0) { | |
| 198 | − err = -1; | |
| 193 | + if (CHECK_FAIL(server_fd < 0)) | |
| 194 | + goto close_bpf_object; | |
| 195 | + | |
| 196 | + if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread, | |
| 197 | + (void *)&server_fd))) | |
| 199 | 198 | goto close_bpf_object; |
| 200 | − } | |
| 201 | 199 | |
| 202 | − pthread_create(&tid, NULL, server_thread, (void *)&server_fd); | |
| 200 | + pthread_mutex_lock(&server_started_mtx); | |
| 201 | + pthread_cond_wait(&server_started, &server_started_mtx); | |
| 202 | + pthread_mutex_unlock(&server_started_mtx); | |
| 203 | 203 | |
| 204 | 204 | client_fd = connect_to_server(server_fd); |
| 205 | − if (client_fd < 0) { | |
| 206 | − err = -1; | |
| 205 | + if (CHECK_FAIL(client_fd < 0)) | |
| 207 | 206 | goto close_server_fd; |
| 208 | − } | |
| 209 | 207 | |
| 210 | − err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0); | |
| 211 | − err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0); | |
| 212 | − err += verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0); | |
| 208 | + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0)); | |
| 209 | + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0)); | |
| 210 | + CHECK_FAIL(verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0)); | |
| 213 | 211 | |
| 214 | 212 | pthread_join(tid, &server_err); |
| 215 | 213 | |
| 216 | − err += (int)(long)server_err; | |
| 214 | + err = (int)(long)server_err; | |
| 215 | + CHECK_FAIL(err); | |
| 217 | 216 | |
| 218 | 217 | close(client_fd); |
| 219 | 218 | |
| @@ -221,33 +220,16 @@ close_server_fd: · 1 unmodified line | ||
| 221 | 220 | close(server_fd); |
| 222 | 221 | close_bpf_object: |
| 223 | 222 | bpf_object__close(obj); |
| 224 | − return err; | |
| 225 | 223 | } |
| 226 | 224 | |
| 227 | −int main(int args, char **argv) | |
| 225 | +void test_sockopt_inherit(void) | |
| 228 | 226 | { |
| 229 | 227 | int cgroup_fd; |
| 230 | − int err = EXIT_SUCCESS; | |
| 231 | − | |
| 232 | − if (setup_cgroup_environment()) | |
| 233 | − return err; | |
| 234 | − | |
| 235 | − cgroup_fd = create_and_get_cgroup(CG_PATH); | |
| 236 | − if (cgroup_fd < 0) | |
| 237 | − goto cleanup_cgroup_env; | |
| 238 | − | |
| 239 | − if (join_cgroup(CG_PATH)) | |
| 240 | − goto cleanup_cgroup; | |
| 241 | − | |
| 242 | − if (run_test(cgroup_fd)) | |
| 243 | − err = EXIT_FAILURE; | |
| 244 | 228 | |
| 245 | − printf("test_sockopt_inherit: %s\n", | |
| 246 | − err == EXIT_SUCCESS ? "PASSED" : "FAILED"); | |
| 229 | + cgroup_fd = test__join_cgroup("/sockopt_inherit"); | |
| 230 | + if (CHECK_FAIL(cgroup_fd < 0)) | |
| 231 | + return; | |
| 247 | 232 | |
| 248 | −cleanup_cgroup: | |
| 233 | + run_test(cgroup_fd); | |
| 249 | 234 | close(cgroup_fd); |
| 250 | −cleanup_cgroup_env: | |
| 251 | − cleanup_cgroup_environment(); | |
| 252 | − return err; | |
| 253 | 235 | } |
| @@ -1,19 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | − | |
| 3 | −#include <error.h> | |
| 4 | −#include <errno.h> | |
| 5 | −#include <stdio.h> | |
| 6 | −#include <unistd.h> | |
| 7 | −#include <sys/types.h> | |
| 8 | −#include <sys/socket.h> | |
| 9 | −#include <netinet/in.h> | |
| 10 | − | |
| 11 | −#include <linux/filter.h> | |
| 12 | −#include <bpf/bpf.h> | |
| 13 | −#include <bpf/libbpf.h> | |
| 14 | − | |
| 15 | −#include "bpf_rlimit.h" | |
| 16 | −#include "bpf_util.h" | |
| 2 | +#include <test_progs.h> | |
| 17 | 3 | #include "cgroup_helpers.h" |
| 18 | 4 | |
| 19 | 5 | static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) |
| @@ -308,7 +294,7 @@ detach: · 288 unmodified lines | ||
| 308 | 294 | return err; |
| 309 | 295 | } |
| 310 | 296 | |
| 311 | −int main(int argc, char **argv) | |
| 297 | +void test_sockopt_multi(void) | |
| 312 | 298 | { |
| 313 | 299 | struct bpf_prog_load_attr attr = { |
| 314 | 300 | .file = "./sockopt_multi.o", |
| @@ -319,56 +305,28 @@ int main(int argc, char **argv) · 4 unmodified lines | ||
| 319 | 305 | int err = -1; |
| 320 | 306 | int ignored; |
| 321 | 307 | |
| 322 | − if (setup_cgroup_environment()) { | |
| 323 | − log_err("Failed to setup cgroup environment\n"); | |
| 324 | − goto out; | |
| 325 | − } | |
| 326 | − | |
| 327 | − cg_parent = create_and_get_cgroup("/parent"); | |
| 328 | − if (cg_parent < 0) { | |
| 329 | − log_err("Failed to create cgroup /parent\n"); | |
| 330 | − goto out; | |
| 331 | − } | |
| 332 | − | |
| 333 | − cg_child = create_and_get_cgroup("/parent/child"); | |
| 334 | − if (cg_child < 0) { | |
| 335 | − log_err("Failed to create cgroup /parent/child\n"); | |
| 308 | + cg_parent = test__join_cgroup("/parent"); | |
| 309 | + if (CHECK_FAIL(cg_parent < 0)) | |
| 336 | 310 | goto out; |
| 337 | − } | |
| 338 | 311 | |
| 339 | − if (join_cgroup("/parent/child")) { | |
| 340 | − log_err("Failed to join cgroup /parent/child\n"); | |
| 312 | + cg_child = test__join_cgroup("/parent/child"); | |
| 313 | + if (CHECK_FAIL(cg_child < 0)) | |
| 341 | 314 | goto out; |
| 342 | − } | |
| 343 | 315 | |
| 344 | 316 | err = bpf_prog_load_xattr(&attr, &obj, &ignored); |
| 345 | − if (err) { | |
| 346 | − log_err("Failed to load BPF object"); | |
| 317 | + if (CHECK_FAIL(err)) | |
| 347 | 318 | goto out; |
| 348 | − } | |
| 349 | 319 | |
| 350 | 320 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); |
| 351 | − if (sock_fd < 0) { | |
| 352 | − log_err("Failed to create socket"); | |
| 321 | + if (CHECK_FAIL(sock_fd < 0)) | |
| 353 | 322 | goto out; |
| 354 | − } | |
| 355 | 323 | |
| 356 | − if (run_getsockopt_test(obj, cg_parent, cg_child, sock_fd)) | |
| 357 | − err = -1; | |
| 358 | − printf("test_sockopt_multi: getsockopt %s\n", | |
| 359 | − err ? "FAILED" : "PASSED"); | |
| 360 | − | |
| 361 | − if (run_setsockopt_test(obj, cg_parent, cg_child, sock_fd)) | |
| 362 | − err = -1; | |
| 363 | − printf("test_sockopt_multi: setsockopt %s\n", | |
| 364 | − err ? "FAILED" : "PASSED"); | |
| 324 | + CHECK_FAIL(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd)); | |
| 325 | + CHECK_FAIL(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd)); | |
| 365 | 326 | |
| 366 | 327 | out: |
| 367 | 328 | close(sock_fd); |
| 368 | 329 | bpf_object__close(obj); |
| 369 | 330 | close(cg_child); |
| 370 | 331 | close(cg_parent); |
| 371 | − | |
| 372 | − printf("test_sockopt_multi: %s\n", err ? "FAILED" : "PASSED"); | |
| 373 | − return err ? EXIT_FAILURE : EXIT_SUCCESS; | |
| 374 | 332 | } |
| @@ -1,23 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | − | |
| 3 | −#include <errno.h> | |
| 4 | −#include <stdio.h> | |
| 5 | −#include <unistd.h> | |
| 6 | −#include <sys/types.h> | |
| 7 | −#include <sys/socket.h> | |
| 8 | −#include <netinet/in.h> | |
| 9 | −#include <netinet/tcp.h> | |
| 10 | − | |
| 11 | −#include <linux/filter.h> | |
| 12 | −#include <bpf/bpf.h> | |
| 13 | −#include <bpf/libbpf.h> | |
| 14 | − | |
| 15 | −#include "bpf_rlimit.h" | |
| 16 | −#include "bpf_util.h" | |
| 2 | +#include <test_progs.h> | |
| 17 | 3 | #include "cgroup_helpers.h" |
| 18 | 4 | |
| 19 | −#define CG_PATH "/sockopt" | |
| 20 | − | |
| 21 | 5 | #define SOL_CUSTOM 0xdeadbeef |
| 22 | 6 | |
| 23 | 7 | static int getsetsockopt(void) |
| @@ -176,7 +160,7 @@ static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title) · 152 unmodified lines | ||
| 176 | 160 | return 0; |
| 177 | 161 | } |
| 178 | 162 | |
| 179 | −static int run_test(int cgroup_fd) | |
| 163 | +static void run_test(int cgroup_fd) | |
| 180 | 164 | { |
| 181 | 165 | struct bpf_prog_load_attr attr = { |
| 182 | 166 | .file = "./sockopt_sk.o", |
| @@ -186,51 +170,31 @@ static int run_test(int cgroup_fd) · 3 unmodified lines | ||
| 186 | 170 | int err; |
| 187 | 171 | |
| 188 | 172 | err = bpf_prog_load_xattr(&attr, &obj, &ignored); |
| 189 | − if (err) { | |
| 190 | − log_err("Failed to load BPF object"); | |
| 191 | − return -1; | |
| 192 | − } | |
| 173 | + if (CHECK_FAIL(err)) | |
| 174 | + return; | |
| 193 | 175 | |
| 194 | 176 | err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt"); |
| 195 | − if (err) | |
| 177 | + if (CHECK_FAIL(err)) | |
| 196 | 178 | goto close_bpf_object; |
| 197 | 179 | |
| 198 | 180 | err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt"); |
| 199 | − if (err) | |
| 181 | + if (CHECK_FAIL(err)) | |
| 200 | 182 | goto close_bpf_object; |
| 201 | 183 | |
| 202 | − err = getsetsockopt(); | |
| 184 | + CHECK_FAIL(getsetsockopt()); | |
| 203 | 185 | |
| 204 | 186 | close_bpf_object: |
| 205 | 187 | bpf_object__close(obj); |
| 206 | − return err; | |
| 207 | 188 | } |
| 208 | 189 | |
| 209 | −int main(int args, char **argv) | |
| 190 | +void test_sockopt_sk(void) | |
| 210 | 191 | { |
| 211 | 192 | int cgroup_fd; |
| 212 | − int err = EXIT_SUCCESS; | |
| 213 | − | |
| 214 | − if (setup_cgroup_environment()) | |
| 215 | − goto cleanup_obj; | |
| 216 | − | |
| 217 | − cgroup_fd = create_and_get_cgroup(CG_PATH); | |
| 218 | − if (cgroup_fd < 0) | |
| 219 | − goto cleanup_cgroup_env; | |
| 220 | − | |
| 221 | − if (join_cgroup(CG_PATH)) | |
| 222 | − goto cleanup_cgroup; | |
| 223 | − | |
| 224 | − if (run_test(cgroup_fd)) | |
| 225 | − err = EXIT_FAILURE; | |
| 226 | 193 | |
| 227 | − printf("test_sockopt_sk: %s\n", | |
| 228 | − err == EXIT_SUCCESS ? "PASSED" : "FAILED"); | |
| 194 | + cgroup_fd = test__join_cgroup("/sockopt_sk"); | |
| 195 | + if (CHECK_FAIL(cgroup_fd < 0)) | |
| 196 | + return; | |
| 229 | 197 | |
| 230 | −cleanup_cgroup: | |
| 198 | + run_test(cgroup_fd); | |
| 231 | 199 | close(cgroup_fd); |
| 232 | −cleanup_cgroup_env: | |
| 233 | − cleanup_cgroup_environment(); | |
| 234 | −cleanup_obj: | |
| 235 | − return err; | |
| 236 | 200 | } |
| @@ -1,24 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −#include <error.h> | |
| 3 | −#include <errno.h> | |
| 4 | −#include <stdio.h> | |
| 5 | −#include <unistd.h> | |
| 6 | −#include <sys/types.h> | |
| 7 | −#include <sys/socket.h> | |
| 8 | −#include <netinet/in.h> | |
| 9 | −#include <netinet/tcp.h> | |
| 10 | −#include <pthread.h> | |
| 11 | − | |
| 12 | −#include <linux/filter.h> | |
| 13 | −#include <bpf/bpf.h> | |
| 14 | −#include <bpf/libbpf.h> | |
| 15 | − | |
| 16 | −#include "bpf_rlimit.h" | |
| 17 | −#include "bpf_util.h" | |
| 2 | +#include <test_progs.h> | |
| 18 | 3 | #include "cgroup_helpers.h" |
| 19 | 4 | |
| 20 | −#define CG_PATH "/tcp_rtt" | |
| 21 | − | |
| 22 | 5 | struct tcp_rtt_storage { |
| 23 | 6 | __u32 invoked; |
| 24 | 7 | __u32 dsack_dups; |
| @@ -31,8 +14,8 @@ static void send_byte(int fd) · 6 unmodified lines | ||
| 31 | 14 | { |
| 32 | 15 | char b = 0x55; |
| 33 | 16 | |
| 34 | − if (write(fd, &b, sizeof(b)) != 1) | |
| 35 | − error(1, errno, "Failed to send single byte"); | |
| 17 | + if (CHECK_FAIL(write(fd, &b, sizeof(b)) != 1)) | |
| 18 | + perror("Failed to send single byte"); | |
| 36 | 19 | } |
| 37 | 20 | |
| 38 | 21 | static int wait_for_ack(int fd, int retries) |
| @@ -66,8 +49,10 @@ static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked, · 27 unmodified lines | ||
| 66 | 49 | int err = 0; |
| 67 | 50 | struct tcp_rtt_storage val; |
| 68 | 51 | |
| 69 | − if (bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0) | |
| 70 | − error(1, errno, "Failed to read socket storage"); | |
| 52 | + if (CHECK_FAIL(bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0)) { | |
| 53 | + perror("Failed to read socket storage"); | |
| 54 | + return -1; | |
| 55 | + } | |
| 71 | 56 | |
| 72 | 57 | if (val.invoked != invoked) { |
| 73 | 58 | log_err("%s: unexpected bpf_tcp_sock.invoked %d != %d", |
| @@ -225,61 +210,47 @@ static void *server_thread(void *arg) · 151 unmodified lines | ||
| 225 | 210 | int fd = *(int *)arg; |
| 226 | 211 | int client_fd; |
| 227 | 212 | |
| 228 | − if (listen(fd, 1) < 0) | |
| 229 | − error(1, errno, "Failed to listed on socket"); | |
| 213 | + if (CHECK_FAIL(listen(fd, 1)) < 0) { | |
| 214 | + perror("Failed to listed on socket"); | |
| 215 | + return NULL; | |
| 216 | + } | |
| 230 | 217 | |
| 231 | 218 | client_fd = accept(fd, (struct sockaddr *)&addr, &len); |
| 232 | − if (client_fd < 0) | |
| 233 | − error(1, errno, "Failed to accept client"); | |
| 219 | + if (CHECK_FAIL(client_fd < 0)) { | |
| 220 | + perror("Failed to accept client"); | |
| 221 | + return NULL; | |
| 222 | + } | |
| 234 | 223 | |
| 235 | 224 | /* Wait for the next connection (that never arrives) |
| 236 | 225 | * to keep this thread alive to prevent calling |
| 237 | 226 | * close() on client_fd. |
| 238 | 227 | */ |
| 239 | − if (accept(fd, (struct sockaddr *)&addr, &len) >= 0) | |
| 240 | − error(1, errno, "Unexpected success in second accept"); | |
| 228 | + if (CHECK_FAIL(accept(fd, (struct sockaddr *)&addr, &len) >= 0)) { | |
| 229 | + perror("Unexpected success in second accept"); | |
| 230 | + return NULL; | |
| 231 | + } | |
| 241 | 232 | |
| 242 | 233 | close(client_fd); |
| 243 | 234 | |
| 244 | 235 | return NULL; |
| 245 | 236 | } |
| 246 | 237 | |
| 247 | −int main(int args, char **argv) | |
| 238 | +void test_tcp_rtt(void) | |
| 248 | 239 | { |
| 249 | 240 | int server_fd, cgroup_fd; |
| 250 | − int err = EXIT_SUCCESS; | |
| 251 | 241 | pthread_t tid; |
| 252 | 242 | |
| 253 | − if (setup_cgroup_environment()) | |
| 254 | − goto cleanup_obj; | |
| 255 | − | |
| 256 | − cgroup_fd = create_and_get_cgroup(CG_PATH); | |
| 257 | − if (cgroup_fd < 0) | |
| 258 | − goto cleanup_cgroup_env; | |
| 259 | − | |
| 260 | − if (join_cgroup(CG_PATH)) | |
| 261 | − goto cleanup_cgroup; | |
| 243 | + cgroup_fd = test__join_cgroup("/tcp_rtt"); | |
| 244 | + if (CHECK_FAIL(cgroup_fd < 0)) | |
| 245 | + return; | |
| 262 | 246 | |
| 263 | 247 | server_fd = start_server(); |
| 264 | − if (server_fd < 0) { | |
| 265 | − err = EXIT_FAILURE; | |
| 266 | − goto cleanup_cgroup; | |
| 267 | − } | |
| 248 | + if (CHECK_FAIL(server_fd < 0)) | |
| 249 | + goto close_cgroup_fd; | |
| 268 | 250 | |
| 269 | 251 | pthread_create(&tid, NULL, server_thread, (void *)&server_fd); |
| 270 | − | |
| 271 | − if (run_test(cgroup_fd, server_fd)) | |
| 272 | − err = EXIT_FAILURE; | |
| 273 | − | |
| 252 | + CHECK_FAIL(run_test(cgroup_fd, server_fd)); | |
| 274 | 253 | close(server_fd); |
| 275 | − | |
| 276 | − printf("test_sockopt_sk: %s\n", | |
| 277 | − err == EXIT_SUCCESS ? "PASSED" : "FAILED"); | |
| 278 | − | |
| 279 | −cleanup_cgroup: | |
| 254 | +close_cgroup_fd: | |
| 280 | 255 | close(cgroup_fd); |
| 281 | −cleanup_cgroup_env: | |
| 282 | − cleanup_cgroup_environment(); | |
| 283 | −cleanup_obj: | |
| 284 | − return err; | |
| 285 | 256 | } |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | #include <stdint.h> |
| 3 | 3 | #include <linux/bpf.h> |
| 4 | 4 | #include <linux/if_ether.h> |
| 5 | +#include <linux/stddef.h> | |
| 5 | 6 | #include <linux/in.h> |
| 6 | 7 | #include <linux/ip.h> |
| 7 | 8 | #include <linux/pkt_cls.h> |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* Copyright (c) 2017 Facebook |
| 3 | 3 | */ |
| 4 | 4 | #include "test_progs.h" |
| 5 | +#include "cgroup_helpers.h" | |
| 5 | 6 | #include "bpf_rlimit.h" |
| 6 | 7 | #include <argp.h> |
| 7 | 8 | #include <string.h> |
| @@ -17,6 +18,7 @@ struct prog_test_def { · 9 unmodified lines | ||
| 17 | 18 | int error_cnt; |
| 18 | 19 | int skip_cnt; |
| 19 | 20 | bool tested; |
| 21 | + bool need_cgroup_cleanup; | |
| 20 | 22 | |
| 21 | 23 | const char *subtest_name; |
| 22 | 24 | int subtest_num; |
| @@ -122,6 +124,39 @@ void test__fail(void) · 99 unmodified lines | ||
| 122 | 124 | env.test->error_cnt++; |
| 123 | 125 | } |
| 124 | 126 | |
| 127 | +int test__join_cgroup(const char *path) | |
| 128 | +{ | |
| 129 | + int fd; | |
| 130 | + | |
| 131 | + if (!env.test->need_cgroup_cleanup) { | |
| 132 | + if (setup_cgroup_environment()) { | |
| 133 | + fprintf(stderr, | |
| 134 | + "#%d %s: Failed to setup cgroup environment\n", | |
| 135 | + env.test->test_num, env.test->test_name); | |
| 136 | + return -1; | |
| 137 | + } | |
| 138 | + | |
| 139 | + env.test->need_cgroup_cleanup = true; | |
| 140 | + } | |
| 141 | + | |
| 142 | + fd = create_and_get_cgroup(path); | |
| 143 | + if (fd < 0) { | |
| 144 | + fprintf(stderr, | |
| 145 | + "#%d %s: Failed to create cgroup '%s' (errno=%d)\n", | |
| 146 | + env.test->test_num, env.test->test_name, path, errno); | |
| 147 | + return fd; | |
| 148 | + } | |
| 149 | + | |
| 150 | + if (join_cgroup(path)) { | |
| 151 | + fprintf(stderr, | |
| 152 | + "#%d %s: Failed to join cgroup '%s' (errno=%d)\n", | |
| 153 | + env.test->test_num, env.test->test_name, path, errno); | |
| 154 | + return -1; | |
| 155 | + } | |
| 156 | + | |
| 157 | + return fd; | |
| 158 | +} | |
| 159 | + | |
| 125 | 160 | struct ipv4_packet pkt_v4 = { |
| 126 | 161 | .eth.h_proto = __bpf_constant_htons(ETH_P_IP), |
| 127 | 162 | .iph.ihl = 5, |
| @@ -530,6 +565,9 @@ int main(int argc, char **argv) · 402 unmodified lines | ||
| 530 | 565 | fprintf(env.stdout, "#%d %s:%s\n", |
| 531 | 566 | test->test_num, test->test_name, |
| 532 | 567 | test->error_cnt ? "FAIL" : "OK"); |
| 568 | + | |
| 569 | + if (test->need_cgroup_cleanup) | |
| 570 | + cleanup_cgroup_environment(); | |
| 533 | 571 | } |
| 534 | 572 | stdio_restore(); |
| 535 | 573 | printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n", |
| @@ -16,9 +16,10 @@ typedef __u16 __sum16; · 15 unmodified lines | ||
| 16 | 16 | #include <linux/if_packet.h> |
| 17 | 17 | #include <linux/ip.h> |
| 18 | 18 | #include <linux/ipv6.h> |
| 19 | −#include <linux/tcp.h> | |
| 19 | +#include <netinet/tcp.h> | |
| 20 | 20 | #include <linux/filter.h> |
| 21 | 21 | #include <linux/perf_event.h> |
| 22 | +#include <linux/socket.h> | |
| 22 | 23 | #include <linux/unistd.h> |
| 23 | 24 | |
| 24 | 25 | #include <sys/ioctl.h> |
| @@ -71,6 +72,7 @@ extern void test__force_log(); · 46 unmodified lines | ||
| 71 | 72 | extern bool test__start_subtest(const char *name); |
| 72 | 73 | extern void test__skip(void); |
| 73 | 74 | extern void test__fail(void); |
| 75 | +extern int test__join_cgroup(const char *path); | |
| 74 | 76 | |
| 75 | 77 | #define MAGIC_BYTES 123 |
| 76 | 78 | |
| @@ -32,6 +32,7 @@ struct sysctl_test { · 31 unmodified lines | ||
| 32 | 32 | enum bpf_attach_type attach_type; |
| 33 | 33 | const char *sysctl; |
| 34 | 34 | int open_flags; |
| 35 | + int seek; | |
| 35 | 36 | const char *newval; |
| 36 | 37 | const char *oldval; |
| 37 | 38 | enum { |
| @@ -140,7 +141,7 @@ static struct sysctl_test tests[] = { · 102 unmodified lines | ||
| 140 | 141 | /* If (file_pos == X) */ |
| 141 | 142 | BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, |
| 142 | 143 | offsetof(struct bpf_sysctl, file_pos)), |
| 143 | − BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 2), | |
| 144 | + BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2), | |
| 144 | 145 | |
| 145 | 146 | /* return ALLOW; */ |
| 146 | 147 | BPF_MOV64_IMM(BPF_REG_0, 1), |
| @@ -153,6 +154,7 @@ static struct sysctl_test tests[] = { · 6 unmodified lines | ||
| 153 | 154 | .attach_type = BPF_CGROUP_SYSCTL, |
| 154 | 155 | .sysctl = "kernel/ostype", |
| 155 | 156 | .open_flags = O_RDONLY, |
| 157 | + .seek = 3, | |
| 156 | 158 | .result = SUCCESS, |
| 157 | 159 | }, |
| 158 | 160 | { |
| @@ -1481,6 +1483,11 @@ static int access_sysctl(const char *sysctl_path, · 1322 unmodified lines | ||
| 1481 | 1483 | if (fd < 0) |
| 1482 | 1484 | return fd; |
| 1483 | 1485 | |
| 1486 | + if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) { | |
| 1487 | + log_err("lseek(%d) failed", test->seek); | |
| 1488 | + goto err; | |
| 1489 | + } | |
| 1490 | + | |
| 1484 | 1491 | if (test->open_flags == O_RDONLY) { |
| 1485 | 1492 | char buf[128]; |
| 1486 | 1493 | |