提交 bf91a76b 编写于 作者: D Daniel Borkmann

Merge branch 'bpf-sockmap-selftests'

John Fastabend says:

====================
This series moves ./samples/sockmap into BPF selftests. There are a
few good reasons to do this. First, by pushing this into selftests
the tests will be run automatically. Second, sockmap was not really
a sample of anything anymore, but rather a large set of tests.

Note: There are three recent fixes outstanding against bpf branch
that can be detected occasionally by the automated tests here.

https://patchwork.ozlabs.org/patch/903138/
https://patchwork.ozlabs.org/patch/903139/
https://patchwork.ozlabs.org/patch/903140/
====================
Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
# List of programs to build
hostprogs-y := sockmap
# Libbpf dependencies
LIBBPF := ../../tools/lib/bpf/bpf.o ../../tools/lib/bpf/nlattr.o
HOSTCFLAGS += -I$(objtree)/usr/include
HOSTCFLAGS += -I$(srctree)/tools/lib/
HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
HOSTCFLAGS += -I$(srctree)/tools/lib/ -I$(srctree)/tools/include
HOSTCFLAGS += -I$(srctree)/tools/perf
sockmap-objs := ../bpf/bpf_load.o $(LIBBPF) sockmap_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
always += sockmap_kern.o
HOSTLOADLIBES_sockmap += -lelf -lpthread
# 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
# Trick to allow make to be run from this directory
all:
$(MAKE) -C ../../ $(CURDIR)/
clean:
$(MAKE) -C ../../ M=$(CURDIR) clean
@rm -f *~
$(obj)/syscall_nrs.s: $(src)/syscall_nrs.c
$(call if_changed_dep,cc_s_c)
$(obj)/syscall_nrs.h: $(obj)/syscall_nrs.s FORCE
$(call filechk,offsets,__SYSCALL_NRS_H__)
clean-files += syscall_nrs.h
FORCE:
# Verify LLVM compiler tools are available and bpf target is supported by llc
.PHONY: verify_cmds verify_target_bpf $(CLANG) $(LLC)
verify_cmds: $(CLANG) $(LLC)
@for TOOL in $^ ; do \
if ! (which -- "$${TOOL}" > /dev/null 2>&1); then \
echo "*** ERROR: Cannot find LLVM tool $${TOOL}" ;\
exit 1; \
else true; fi; \
done
verify_target_bpf: verify_cmds
@if ! (${LLC} -march=bpf -mattr=help > /dev/null 2>&1); then \
echo "*** ERROR: LLVM (${LLC}) does not support 'bpf' target" ;\
echo " NOTICE: LLVM version >= 3.7.1 required" ;\
exit 2; \
else true; fi
$(src)/*.c: verify_target_bpf
# asm/sysreg.h - inline assembly used by it is incompatible with llvm.
# But, there is no easy way to fix it, so just exclude it since it is
# useless for BPF samples.
$(obj)/%.o: $(src)/%.c
$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) -I$(obj) \
-D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \
-Wno-compare-distinct-pointer-types \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member -Wno-tautological-compare \
-Wno-unknown-warning-option \
-O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
#Test a bunch of positive cases to verify basic functionality
for prog in "--txmsg_redir --txmsg_skb" "--txmsg_redir --txmsg_ingress" "--txmsg" "--txmsg_redir" "--txmsg_redir --txmsg_ingress" "--txmsg_drop"; do
for t in "sendmsg" "sendpage"; do
for r in 1 10 100; do
for i in 1 10 100; do
for l in 1 10 100; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
done
done
done
done
#Test max iov
t="sendmsg"
r=1
i=1024
l=1
prog="--txmsg"
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
prog="--txmsg_redir"
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
# Test max iov with 1k send
t="sendmsg"
r=1
i=1024
l=1024
prog="--txmsg"
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
prog="--txmsg_redir"
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
# Test apply with 1B
r=1
i=1024
l=1024
prog="--txmsg_apply 1"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply with larger value than send
r=1
i=8
l=1024
prog="--txmsg_apply 2048"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply with apply that never reaches limit
r=1024
i=1
l=1
prog="--txmsg_apply 2048"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply and redirect with 1B
r=1
i=1024
l=1024
prog="--txmsg_redir --txmsg_apply 1"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
prog="--txmsg_redir --txmsg_apply 1 --txmsg_ingress"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
prog="--txmsg_redir --txmsg_apply 1 --txmsg_skb"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply and redirect with larger value than send
r=1
i=8
l=1024
prog="--txmsg_redir --txmsg_apply 2048"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
prog="--txmsg_redir --txmsg_apply 2048 --txmsg_ingress"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
prog="--txmsg_redir --txmsg_apply 2048 --txmsg_skb"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply and redirect with apply that never reaches limit
r=1024
i=1
l=1
prog="--txmsg_apply 2048"
for t in "sendmsg" "sendpage"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with 1B not really useful but test it anyways
r=1
i=1024
l=1024
prog="--txmsg_cork 1"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with a more reasonable 100B
r=1
i=1000
l=1000
prog="--txmsg_cork 100"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with larger value than send
r=1
i=8
l=1024
prog="--txmsg_cork 2048"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with cork that never reaches limit
r=1024
i=1
l=1
prog="--txmsg_cork 2048"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
r=1
i=1024
l=1024
prog="--txmsg_redir --txmsg_cork 1"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with a more reasonable 100B
r=1
i=1000
l=1000
prog="--txmsg_redir --txmsg_cork 100"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with larger value than send
r=1
i=8
l=1024
prog="--txmsg_redir --txmsg_cork 2048"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test cork with cork that never reaches limit
r=1024
i=1
l=1
prog="--txmsg_cork 2048"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# mix and match cork and apply not really useful but valid programs
# Test apply < cork
r=100
i=1
l=5
prog="--txmsg_apply 10 --txmsg_cork 100"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Try again with larger sizes so we hit overflow case
r=100
i=1000
l=2048
prog="--txmsg_apply 4096 --txmsg_cork 8096"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply > cork
r=100
i=1
l=5
prog="--txmsg_apply 100 --txmsg_cork 10"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Again with larger sizes so we hit overflow cases
r=100
i=1000
l=2048
prog="--txmsg_apply 8096 --txmsg_cork 4096"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply = cork
r=100
i=1
l=5
prog="--txmsg_apply 10 --txmsg_cork 10"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
r=100
i=1000
l=2048
prog="--txmsg_apply 4096 --txmsg_cork 4096"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply < cork
r=100
i=1
l=5
prog="--txmsg_redir --txmsg_apply 10 --txmsg_cork 100"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Try again with larger sizes so we hit overflow case
r=100
i=1000
l=2048
prog="--txmsg_redir --txmsg_apply 4096 --txmsg_cork 8096"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply > cork
r=100
i=1
l=5
prog="--txmsg_redir --txmsg_apply 100 --txmsg_cork 10"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Again with larger sizes so we hit overflow cases
r=100
i=1000
l=2048
prog="--txmsg_redir --txmsg_apply 8096 --txmsg_cork 4096"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Test apply = cork
r=100
i=1
l=5
prog="--txmsg_redir --txmsg_apply 10 --txmsg_cork 10"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
r=100
i=1000
l=2048
prog="--txmsg_redir --txmsg_apply 4096 --txmsg_cork 4096"
for t in "sendpage" "sendmsg"; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog"
echo $TEST
$TEST
sleep 2
done
# Tests for bpf_msg_pull_data()
for i in `seq 99 100 1600`; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 0 --txmsg_end $i --txmsg_cork 1600"
echo $TEST
$TEST
sleep 2
done
for i in `seq 199 100 1600`; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 100 --txmsg_end $i --txmsg_cork 1600"
echo $TEST
$TEST
sleep 2
done
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 1500 --txmsg_end 1600 --txmsg_cork 1600"
echo $TEST
$TEST
sleep 2
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 1111 --txmsg_end 1112 --txmsg_cork 1600"
echo $TEST
$TEST
sleep 2
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 1111 --txmsg_end 0 --txmsg_cork 1600"
echo $TEST
$TEST
sleep 2
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 0 --txmsg_end 1601 --txmsg_cork 1600"
echo $TEST
$TEST
sleep 2
TEST="./sockmap --cgroup /mnt/cgroup2/ -t sendpage -r 16 -i 1 -l 100 \
--txmsg --txmsg_start 0 --txmsg_end 1601 --txmsg_cork 1602"
echo $TEST
$TEST
sleep 2
# Run through gamut again with start and end
for prog in "--txmsg" "--txmsg_redir" "--txmsg_drop"; do
for t in "sendmsg" "sendpage"; do
for r in 1 10 100; do
for i in 1 10 100; do
for l in 1 10 100; do
TEST="./sockmap --cgroup /mnt/cgroup2/ -t $t -r $r -i $i -l $l $prog --txmsg_start 1 --txmsg_end 2"
echo $TEST
$TEST
sleep 2
done
done
done
done
done
# Some specific tests to cover specific code paths
./sockmap --cgroup /mnt/cgroup2/ -t sendpage \
-r 5 -i 1 -l 1 --txmsg_redir --txmsg_cork 5 --txmsg_apply 3
./sockmap --cgroup /mnt/cgroup2/ -t sendmsg \
-r 5 -i 1 -l 1 --txmsg_redir --txmsg_cork 5 --txmsg_apply 3
./sockmap --cgroup /mnt/cgroup2/ -t sendpage \
-r 5 -i 1 -l 1 --txmsg_redir --txmsg_cork 5 --txmsg_apply 5
./sockmap --cgroup /mnt/cgroup2/ -t sendmsg \
-r 5 -i 1 -l 1 --txmsg_redir --txmsg_cork 5 --txmsg_apply 5
...@@ -894,6 +894,7 @@ enum bpf_func_id { ...@@ -894,6 +894,7 @@ enum bpf_func_id {
/* BPF_FUNC_skb_set_tunnel_key flags. */ /* BPF_FUNC_skb_set_tunnel_key flags. */
#define BPF_F_ZERO_CSUM_TX (1ULL << 1) #define BPF_F_ZERO_CSUM_TX (1ULL << 1)
#define BPF_F_DONT_FRAGMENT (1ULL << 2) #define BPF_F_DONT_FRAGMENT (1ULL << 2)
#define BPF_F_SEQ_NUMBER (1ULL << 3)
/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and /* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
* BPF_FUNC_perf_event_read_value flags. * BPF_FUNC_perf_event_read_value flags.
......
...@@ -941,4 +941,43 @@ enum { ...@@ -941,4 +941,43 @@ enum {
IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */ IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */
}; };
/* tun section */
enum {
IFLA_TUN_UNSPEC,
IFLA_TUN_OWNER,
IFLA_TUN_GROUP,
IFLA_TUN_TYPE,
IFLA_TUN_PI,
IFLA_TUN_VNET_HDR,
IFLA_TUN_PERSIST,
IFLA_TUN_MULTI_QUEUE,
IFLA_TUN_NUM_QUEUES,
IFLA_TUN_NUM_DISABLED_QUEUES,
__IFLA_TUN_MAX,
};
#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1)
/* rmnet section */
#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0)
#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1)
#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2)
#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3)
enum {
IFLA_RMNET_UNSPEC,
IFLA_RMNET_MUX_ID,
IFLA_RMNET_FLAGS,
__IFLA_RMNET_MAX,
};
#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1)
struct ifla_rmnet_flags {
__u32 flags;
__u32 mask;
};
#endif /* _UAPI_LINUX_IF_LINK_H */ #endif /* _UAPI_LINUX_IF_LINK_H */
...@@ -1961,7 +1961,7 @@ BPF_PROG_TYPE_FNS(raw_tracepoint, BPF_PROG_TYPE_RAW_TRACEPOINT); ...@@ -1961,7 +1961,7 @@ BPF_PROG_TYPE_FNS(raw_tracepoint, BPF_PROG_TYPE_RAW_TRACEPOINT);
BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
static void bpf_program__set_expected_attach_type(struct bpf_program *prog, void bpf_program__set_expected_attach_type(struct bpf_program *prog,
enum bpf_attach_type type) enum bpf_attach_type type)
{ {
prog->expected_attach_type = type; prog->expected_attach_type = type;
......
...@@ -193,6 +193,8 @@ int bpf_program__set_sched_act(struct bpf_program *prog); ...@@ -193,6 +193,8 @@ int bpf_program__set_sched_act(struct bpf_program *prog);
int bpf_program__set_xdp(struct bpf_program *prog); int bpf_program__set_xdp(struct bpf_program *prog);
int bpf_program__set_perf_event(struct bpf_program *prog); int bpf_program__set_perf_event(struct bpf_program *prog);
void bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type); void bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type);
void bpf_program__set_expected_attach_type(struct bpf_program *prog,
enum bpf_attach_type type);
bool bpf_program__is_socket_filter(struct bpf_program *prog); bool bpf_program__is_socket_filter(struct bpf_program *prog);
bool bpf_program__is_tracepoint(struct bpf_program *prog); bool bpf_program__is_tracepoint(struct bpf_program *prog);
......
...@@ -24,7 +24,7 @@ urandom_read: urandom_read.c ...@@ -24,7 +24,7 @@ urandom_read: urandom_read.c
# Order correspond to 'make run_tests' order # Order correspond to 'make run_tests' order
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
test_sock test_btf test_sock test_btf test_sockmap
TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \
...@@ -32,7 +32,7 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test ...@@ -32,7 +32,7 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test
test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \ test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \
sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \ sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \
sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \ sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \
test_btf_haskv.o test_btf_nokv.o test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o
# Order correspond to 'make run_tests' order # Order correspond to 'make run_tests' order
TEST_PROGS := test_kmod.sh \ TEST_PROGS := test_kmod.sh \
...@@ -56,6 +56,7 @@ $(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/libbpf.a ...@@ -56,6 +56,7 @@ $(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/libbpf.a
$(OUTPUT)/test_dev_cgroup: cgroup_helpers.c $(OUTPUT)/test_dev_cgroup: cgroup_helpers.c
$(OUTPUT)/test_sock: cgroup_helpers.c $(OUTPUT)/test_sock: cgroup_helpers.c
$(OUTPUT)/test_sock_addr: cgroup_helpers.c $(OUTPUT)/test_sock_addr: cgroup_helpers.c
$(OUTPUT)/test_sockmap: cgroup_helpers.c
.PHONY: force .PHONY: force
......
/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io // SPDX-License-Identifier: GPL-2.0
* // Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/socket.h> #include <sys/socket.h>
...@@ -25,6 +16,7 @@ ...@@ -25,6 +16,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <time.h> #include <time.h>
#include <sched.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
...@@ -41,19 +33,31 @@ ...@@ -41,19 +33,31 @@
#include <getopt.h> #include <getopt.h>
#include "../bpf/bpf_load.h" #include <bpf/bpf.h>
#include "../bpf/bpf_util.h" #include <bpf/libbpf.h>
#include "../bpf/libbpf.h"
#include "bpf_util.h"
#include "bpf_rlimit.h"
#include "cgroup_helpers.h"
int running; int running;
void running_handler(int a); static void running_handler(int a);
/* randomly selected ports for testing on lo */ /* randomly selected ports for testing on lo */
#define S1_PORT 10000 #define S1_PORT 10000
#define S2_PORT 10001 #define S2_PORT 10001
#define BPF_FILENAME "test_sockmap_kern.o"
#define CG_PATH "/sockmap"
/* global sockets */ /* global sockets */
int s1, s2, c1, c2, p1, p2; int s1, s2, c1, c2, p1, p2;
int test_cnt;
int passed;
int failed;
int map_fd[8];
struct bpf_map *maps[8];
int prog_fd[11];
int txmsg_pass; int txmsg_pass;
int txmsg_noisy; int txmsg_noisy;
...@@ -107,7 +111,7 @@ static void usage(char *argv[]) ...@@ -107,7 +111,7 @@ static void usage(char *argv[])
printf("\n"); printf("\n");
} }
static int sockmap_init_sockets(void) static int sockmap_init_sockets(int verbose)
{ {
int i, err, one = 1; int i, err, one = 1;
struct sockaddr_in addr; struct sockaddr_in addr;
...@@ -207,9 +211,11 @@ static int sockmap_init_sockets(void) ...@@ -207,9 +211,11 @@ static int sockmap_init_sockets(void)
return errno; return errno;
} }
if (verbose) {
printf("connected sockets: c1 <-> p1, c2 <-> p2\n"); printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n", printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
c1, s1, c2, s2); c1, s1, c2, s2);
}
return 0; return 0;
} }
...@@ -226,6 +232,9 @@ struct sockmap_options { ...@@ -226,6 +232,9 @@ struct sockmap_options {
bool sendpage; bool sendpage;
bool data_test; bool data_test;
bool drop_expected; bool drop_expected;
int iov_count;
int iov_length;
int rate;
}; };
static int msg_loop_sendpage(int fd, int iov_length, int cnt, static int msg_loop_sendpage(int fd, int iov_length, int cnt,
...@@ -324,10 +333,12 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, ...@@ -324,10 +333,12 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
clock_gettime(CLOCK_MONOTONIC, &s->end); clock_gettime(CLOCK_MONOTONIC, &s->end);
} else { } else {
int slct, recv, max_fd = fd; int slct, recv, max_fd = fd;
int fd_flags = O_NONBLOCK;
struct timeval timeout; struct timeval timeout;
float total_bytes; float total_bytes;
fd_set w; fd_set w;
fcntl(fd, fd_flags);
total_bytes = (float)iov_count * (float)iov_length * (float)cnt; total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
err = clock_gettime(CLOCK_MONOTONIC, &s->start); err = clock_gettime(CLOCK_MONOTONIC, &s->start);
if (err < 0) if (err < 0)
...@@ -346,6 +357,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, ...@@ -346,6 +357,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
clock_gettime(CLOCK_MONOTONIC, &s->end); clock_gettime(CLOCK_MONOTONIC, &s->end);
goto out_errno; goto out_errno;
} else if (!slct) { } else if (!slct) {
if (opt->verbose)
fprintf(stderr, "unexpected timeout\n"); fprintf(stderr, "unexpected timeout\n");
errno = -EIO; errno = -EIO;
clock_gettime(CLOCK_MONOTONIC, &s->end); clock_gettime(CLOCK_MONOTONIC, &s->end);
...@@ -409,12 +421,14 @@ static inline float recvdBps(struct msg_stats s) ...@@ -409,12 +421,14 @@ static inline float recvdBps(struct msg_stats s)
return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec); return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec);
} }
static int sendmsg_test(int iov_count, int iov_buf, int cnt, static int sendmsg_test(struct sockmap_options *opt)
struct sockmap_options *opt)
{ {
float sent_Bps = 0, recvd_Bps = 0; float sent_Bps = 0, recvd_Bps = 0;
int rx_fd, txpid, rxpid, err = 0; int rx_fd, txpid, rxpid, err = 0;
struct msg_stats s = {0}; struct msg_stats s = {0};
int iov_count = opt->iov_count;
int iov_buf = opt->iov_length;
int cnt = opt->rate;
int status; int status;
errno = 0; errno = 0;
...@@ -433,7 +447,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt, ...@@ -433,7 +447,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
iov_count = 1; iov_count = 1;
err = msg_loop(rx_fd, iov_count, iov_buf, err = msg_loop(rx_fd, iov_count, iov_buf,
cnt, &s, false, opt); cnt, &s, false, opt);
if (err) if (err && opt->verbose)
fprintf(stderr, fprintf(stderr,
"msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n", "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
iov_count, iov_buf, cnt, err); iov_count, iov_buf, cnt, err);
...@@ -443,6 +457,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt, ...@@ -443,6 +457,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
sent_Bps = sentBps(s); sent_Bps = sentBps(s);
recvd_Bps = recvdBps(s); recvd_Bps = recvdBps(s);
} }
if (opt->verbose)
fprintf(stdout, fprintf(stdout,
"rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s\n", "rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s\n",
s.bytes_sent, sent_Bps, sent_Bps/giga, s.bytes_sent, sent_Bps, sent_Bps/giga,
...@@ -470,6 +485,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt, ...@@ -470,6 +485,7 @@ static int sendmsg_test(int iov_count, int iov_buf, int cnt,
sent_Bps = sentBps(s); sent_Bps = sentBps(s);
recvd_Bps = recvdBps(s); recvd_Bps = recvdBps(s);
} }
if (opt->verbose)
fprintf(stdout, fprintf(stdout,
"tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n", "tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n",
s.bytes_sent, sent_Bps, sent_Bps/giga, s.bytes_sent, sent_Bps, sent_Bps/giga,
...@@ -568,102 +584,9 @@ enum { ...@@ -568,102 +584,9 @@ enum {
SENDPAGE, SENDPAGE,
}; };
int main(int argc, char **argv) static int run_options(struct sockmap_options *options, int cg_fd, int test)
{ {
int iov_count = 1, length = 1024, rate = 1, tx_prog_fd; int i, key, next_key, err, tx_prog_fd = -1, zero = 0;
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
int opt, longindex, err, cg_fd = 0;
struct sockmap_options options = {0};
int test = PING_PONG;
char filename[256];
while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:",
long_options, &longindex)) != -1) {
switch (opt) {
case 's':
txmsg_start = atoi(optarg);
break;
case 'e':
txmsg_end = atoi(optarg);
break;
case 'a':
txmsg_apply = atoi(optarg);
break;
case 'k':
txmsg_cork = atoi(optarg);
break;
case 'c':
cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
if (cg_fd < 0) {
fprintf(stderr,
"ERROR: (%i) open cg path failed: %s\n",
cg_fd, optarg);
return cg_fd;
}
break;
case 'r':
rate = atoi(optarg);
break;
case 'v':
options.verbose = 1;
break;
case 'i':
iov_count = atoi(optarg);
break;
case 'l':
length = atoi(optarg);
break;
case 'd':
options.data_test = true;
break;
case 't':
if (strcmp(optarg, "ping") == 0) {
test = PING_PONG;
} else if (strcmp(optarg, "sendmsg") == 0) {
test = SENDMSG;
} else if (strcmp(optarg, "base") == 0) {
test = BASE;
} else if (strcmp(optarg, "base_sendpage") == 0) {
test = BASE_SENDPAGE;
} else if (strcmp(optarg, "sendpage") == 0) {
test = SENDPAGE;
} else {
usage(argv);
return -1;
}
break;
case 0:
break;
case 'h':
default:
usage(argv);
return -1;
}
}
if (!cg_fd) {
fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n",
argv[0]);
return -1;
}
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
return 1;
}
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
running = 1;
/* catch SIGINT */
signal(SIGINT, running_handler);
if (load_bpf_file(filename)) {
fprintf(stderr, "load_bpf_file: (%s) %s\n",
filename, strerror(errno));
return 1;
}
/* If base test skip BPF setup */ /* If base test skip BPF setup */
if (test == BASE || test == BASE_SENDPAGE) if (test == BASE || test == BASE_SENDPAGE)
...@@ -673,8 +596,9 @@ int main(int argc, char **argv) ...@@ -673,8 +596,9 @@ int main(int argc, char **argv)
err = bpf_prog_attach(prog_fd[0], map_fd[0], err = bpf_prog_attach(prog_fd[0], map_fd[0],
BPF_SK_SKB_STREAM_PARSER, 0); BPF_SK_SKB_STREAM_PARSER, 0);
if (err) { if (err) {
fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n", fprintf(stderr,
err, strerror(errno)); "ERROR: bpf_prog_attach (sockmap %i->%i): %d (%s)\n",
prog_fd[0], map_fd[0], err, strerror(errno));
return err; return err;
} }
...@@ -695,7 +619,7 @@ int main(int argc, char **argv) ...@@ -695,7 +619,7 @@ int main(int argc, char **argv)
} }
run: run:
err = sockmap_init_sockets(); err = sockmap_init_sockets(options->verbose);
if (err) { if (err) {
fprintf(stderr, "ERROR: test socket failed: %d\n", err); fprintf(stderr, "ERROR: test socket failed: %d\n", err);
goto out; goto out;
...@@ -729,7 +653,7 @@ int main(int argc, char **argv) ...@@ -729,7 +653,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_prog_attach (txmsg): %d (%s)\n", "ERROR: bpf_prog_attach (txmsg): %d (%s)\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY); err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY);
...@@ -737,7 +661,7 @@ int main(int argc, char **argv) ...@@ -737,7 +661,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (txmsg): %d (%s\n", "ERROR: bpf_map_update_elem (txmsg): %d (%s\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
if (txmsg_redir || txmsg_redir_noisy) if (txmsg_redir || txmsg_redir_noisy)
...@@ -750,7 +674,7 @@ int main(int argc, char **argv) ...@@ -750,7 +674,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (txmsg): %d (%s\n", "ERROR: bpf_map_update_elem (txmsg): %d (%s\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
if (txmsg_apply) { if (txmsg_apply) {
...@@ -760,7 +684,7 @@ int main(int argc, char **argv) ...@@ -760,7 +684,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (apply_bytes): %d (%s\n", "ERROR: bpf_map_update_elem (apply_bytes): %d (%s\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
} }
...@@ -771,7 +695,7 @@ int main(int argc, char **argv) ...@@ -771,7 +695,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (cork_bytes): %d (%s\n", "ERROR: bpf_map_update_elem (cork_bytes): %d (%s\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
} }
...@@ -782,7 +706,7 @@ int main(int argc, char **argv) ...@@ -782,7 +706,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (txmsg_start): %d (%s)\n", "ERROR: bpf_map_update_elem (txmsg_start): %d (%s)\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
} }
...@@ -794,7 +718,7 @@ int main(int argc, char **argv) ...@@ -794,7 +718,7 @@ int main(int argc, char **argv)
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (txmsg_end): %d (%s)\n", "ERROR: bpf_map_update_elem (txmsg_end): %d (%s)\n",
err, strerror(errno)); err, strerror(errno));
return err; goto out;
} }
} }
...@@ -832,11 +756,13 @@ int main(int argc, char **argv) ...@@ -832,11 +756,13 @@ int main(int argc, char **argv)
} }
if (txmsg_skb) { if (txmsg_skb) {
int skb_fd = (test == SENDMSG || test == SENDPAGE) ? p2 : p1; int skb_fd = (test == SENDMSG || test == SENDPAGE) ?
p2 : p1;
int ingress = BPF_F_INGRESS; int ingress = BPF_F_INGRESS;
i = 0; i = 0;
err = bpf_map_update_elem(map_fd[7], &i, &ingress, BPF_ANY); err = bpf_map_update_elem(map_fd[7],
&i, &ingress, BPF_ANY);
if (err) { if (err) {
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n", "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
...@@ -844,7 +770,8 @@ int main(int argc, char **argv) ...@@ -844,7 +770,8 @@ int main(int argc, char **argv)
} }
i = 3; i = 3;
err = bpf_map_update_elem(map_fd[0], &i, &skb_fd, BPF_ANY); err = bpf_map_update_elem(map_fd[0],
&i, &skb_fd, BPF_ANY);
if (err) { if (err) {
fprintf(stderr, fprintf(stderr,
"ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n", "ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
...@@ -854,36 +781,680 @@ int main(int argc, char **argv) ...@@ -854,36 +781,680 @@ int main(int argc, char **argv)
} }
if (txmsg_drop) if (txmsg_drop)
options.drop_expected = true; options->drop_expected = true;
if (test == PING_PONG) if (test == PING_PONG)
err = forever_ping_pong(rate, &options); err = forever_ping_pong(options->rate, options);
else if (test == SENDMSG) { else if (test == SENDMSG) {
options.base = false; options->base = false;
options.sendpage = false; options->sendpage = false;
err = sendmsg_test(iov_count, length, rate, &options); err = sendmsg_test(options);
} else if (test == SENDPAGE) { } else if (test == SENDPAGE) {
options.base = false; options->base = false;
options.sendpage = true; options->sendpage = true;
err = sendmsg_test(iov_count, length, rate, &options); err = sendmsg_test(options);
} else if (test == BASE) { } else if (test == BASE) {
options.base = true; options->base = true;
options.sendpage = false; options->sendpage = false;
err = sendmsg_test(iov_count, length, rate, &options); err = sendmsg_test(options);
} else if (test == BASE_SENDPAGE) { } else if (test == BASE_SENDPAGE) {
options.base = true; options->base = true;
options.sendpage = true; options->sendpage = true;
err = sendmsg_test(iov_count, length, rate, &options); err = sendmsg_test(options);
} else } else
fprintf(stderr, "unknown test\n"); fprintf(stderr, "unknown test\n");
out: out:
/* Detatch and zero all the maps */
bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS); bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS);
bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER);
bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT);
if (tx_prog_fd >= 0)
bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT);
for (i = 0; i < 8; i++) {
key = next_key = 0;
bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
while (bpf_map_get_next_key(map_fd[i], &key, &next_key) == 0) {
bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
key = next_key;
}
}
close(s1); close(s1);
close(s2); close(s2);
close(p1); close(p1);
close(p2); close(p2);
close(c1); close(c1);
close(c2); close(c2);
return err;
}
static char *test_to_str(int test)
{
switch (test) {
case SENDMSG:
return "sendmsg";
case SENDPAGE:
return "sendpage";
}
return "unknown";
}
#define OPTSTRING 60
static void test_options(char *options)
{
memset(options, 0, OPTSTRING);
if (txmsg_pass)
strncat(options, "pass,", OPTSTRING);
if (txmsg_noisy)
strncat(options, "pass_noisy,", OPTSTRING);
if (txmsg_redir)
strncat(options, "redir,", OPTSTRING);
if (txmsg_redir_noisy)
strncat(options, "redir_noisy,", OPTSTRING);
if (txmsg_drop)
strncat(options, "drop,", OPTSTRING);
if (txmsg_apply)
strncat(options, "apply,", OPTSTRING);
if (txmsg_cork)
strncat(options, "cork,", OPTSTRING);
if (txmsg_start)
strncat(options, "start,", OPTSTRING);
if (txmsg_end)
strncat(options, "end,", OPTSTRING);
if (txmsg_ingress)
strncat(options, "ingress,", OPTSTRING);
if (txmsg_skb)
strncat(options, "skb,", OPTSTRING);
}
static int __test_exec(int cgrp, int test, struct sockmap_options *opt)
{
char *options = calloc(60, sizeof(char));
int err;
if (test == SENDPAGE)
opt->sendpage = true;
else
opt->sendpage = false;
if (txmsg_drop)
opt->drop_expected = true;
else
opt->drop_expected = false;
test_options(options);
fprintf(stdout,
"[TEST %i]: (%i, %i, %i, %s, %s): ",
test_cnt, opt->rate, opt->iov_count, opt->iov_length,
test_to_str(test), options);
fflush(stdout);
err = run_options(opt, cgrp, test);
fprintf(stdout, "%s\n", !err ? "PASS" : "FAILED");
test_cnt++;
!err ? passed++ : failed++;
free(options);
return err;
}
static int test_exec(int cgrp, struct sockmap_options *opt)
{
int err = __test_exec(cgrp, SENDMSG, opt);
sched_yield();
if (err)
goto out;
err = __test_exec(cgrp, SENDPAGE, opt);
sched_yield();
out:
return err;
}
static int test_loop(int cgrp)
{
struct sockmap_options opt;
int err, i, l, r;
opt.verbose = 0;
opt.base = false;
opt.sendpage = false;
opt.data_test = false;
opt.drop_expected = false;
opt.iov_count = 0;
opt.iov_length = 0;
opt.rate = 0;
for (r = 1; r < 100; r += 33) {
for (i = 1; i < 100; i += 33) {
for (l = 1; l < 100; l += 33) {
opt.rate = r;
opt.iov_count = i;
opt.iov_length = l;
err = test_exec(cgrp, &opt);
if (err)
goto out;
}
}
}
out:
return err;
}
static int test_txmsg(int cgrp)
{
int err;
txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
txmsg_apply = txmsg_cork = 0;
txmsg_ingress = txmsg_skb = 0;
txmsg_pass = 1;
err = test_loop(cgrp);
txmsg_pass = 0;
if (err)
goto out;
txmsg_redir = 1;
err = test_loop(cgrp);
txmsg_redir = 0;
if (err)
goto out;
txmsg_drop = 1;
err = test_loop(cgrp);
txmsg_drop = 0;
if (err)
goto out;
txmsg_redir = 1;
txmsg_ingress = 1;
err = test_loop(cgrp);
txmsg_redir = 0;
txmsg_ingress = 0;
if (err)
goto out;
out:
txmsg_pass = 0;
txmsg_redir = 0;
txmsg_drop = 0;
return err;
}
static int test_send(struct sockmap_options *opt, int cgrp)
{
int err;
opt->iov_length = 1;
opt->iov_count = 1;
opt->rate = 1;
err = test_exec(cgrp, opt);
if (err)
goto out;
opt->iov_length = 1;
opt->iov_count = 1024;
opt->rate = 1;
err = test_exec(cgrp, opt);
if (err)
goto out;
opt->iov_length = 1024;
opt->iov_count = 1;
opt->rate = 1;
err = test_exec(cgrp, opt);
if (err)
goto out;
opt->iov_length = 1;
opt->iov_count = 1;
opt->rate = 1024;
err = test_exec(cgrp, opt);
if (err)
goto out;
opt->iov_length = 256;
opt->iov_count = 1024;
opt->rate = 10;
err = test_exec(cgrp, opt);
if (err)
goto out;
opt->rate = 100;
opt->iov_count = 1;
opt->iov_length = 5;
err = test_exec(cgrp, opt);
if (err)
goto out;
out:
return err;
}
static int test_mixed(int cgrp)
{
struct sockmap_options opt = {0};
int err;
txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
txmsg_apply = txmsg_cork = 0;
txmsg_start = txmsg_end = 0;
/* Test small and large iov_count values with pass/redir/apply/cork */
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_apply = 1;
txmsg_cork = 0;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_apply = 0;
txmsg_cork = 1;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_apply = 1;
txmsg_cork = 1;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_apply = 1024;
txmsg_cork = 0;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_apply = 0;
txmsg_cork = 1024;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_apply = 1024;
txmsg_cork = 1024;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 1;
txmsg_redir = 0;
txmsg_cork = 4096;
txmsg_apply = 4096;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 0;
txmsg_redir = 1;
txmsg_apply = 1;
txmsg_cork = 0;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 0;
txmsg_redir = 1;
txmsg_apply = 0;
txmsg_cork = 1;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 0;
txmsg_redir = 1;
txmsg_apply = 1024;
txmsg_cork = 0;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 0;
txmsg_redir = 1;
txmsg_apply = 0;
txmsg_cork = 1024;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 0;
txmsg_redir = 1;
txmsg_apply = 1024;
txmsg_cork = 1024;
err = test_send(&opt, cgrp);
if (err)
goto out;
txmsg_pass = 0;
txmsg_redir = 1;
txmsg_cork = 4096;
txmsg_apply = 4096;
err = test_send(&opt, cgrp);
if (err)
goto out;
out:
return err;
}
static int test_start_end(int cgrp)
{
struct sockmap_options opt = {0};
int err, i;
/* Test basic start/end with lots of iov_count and iov_lengths */
txmsg_start = 1;
txmsg_end = 2;
err = test_txmsg(cgrp);
if (err)
goto out;
/* Test start/end with cork */
opt.rate = 16;
opt.iov_count = 1;
opt.iov_length = 100;
txmsg_cork = 1600;
for (i = 99; i <= 1600; i += 100) {
txmsg_start = 0;
txmsg_end = i;
err = test_exec(cgrp, &opt);
if (err)
goto out;
}
/* Test start/end with cork but pull data in middle */
for (i = 199; i <= 1600; i += 100) {
txmsg_start = 100;
txmsg_end = i;
err = test_exec(cgrp, &opt);
if (err)
goto out;
}
/* Test start/end with cork pulling last sg entry */
txmsg_start = 1500;
txmsg_end = 1600;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test start/end pull of single byte in last page */
txmsg_start = 1111;
txmsg_end = 1112;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test start/end with end < start */
txmsg_start = 1111;
txmsg_end = 0;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test start/end with end > data */
txmsg_start = 0;
txmsg_end = 1601;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test start/end with start > data */
txmsg_start = 1601;
txmsg_end = 1600;
err = test_exec(cgrp, &opt);
out:
txmsg_start = 0;
txmsg_end = 0;
return err;
}
char *map_names[] = {
"sock_map",
"sock_map_txmsg",
"sock_map_redir",
"sock_apply_bytes",
"sock_cork_bytes",
"sock_pull_bytes",
"sock_redir_flags",
"sock_skb_opts",
};
int prog_attach_type[] = {
BPF_SK_SKB_STREAM_PARSER,
BPF_SK_SKB_STREAM_VERDICT,
BPF_CGROUP_SOCK_OPS,
BPF_SK_MSG_VERDICT,
BPF_SK_MSG_VERDICT,
BPF_SK_MSG_VERDICT,
BPF_SK_MSG_VERDICT,
BPF_SK_MSG_VERDICT,
BPF_SK_MSG_VERDICT,
BPF_SK_MSG_VERDICT,
};
int prog_type[] = {
BPF_PROG_TYPE_SK_SKB,
BPF_PROG_TYPE_SK_SKB,
BPF_PROG_TYPE_SOCK_OPS,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_SK_MSG,
};
static int populate_progs(void)
{
char *bpf_file = BPF_FILENAME;
struct bpf_program *prog;
struct bpf_object *obj;
int i = 0;
long err;
obj = bpf_object__open(bpf_file);
err = libbpf_get_error(obj);
if (err) {
char err_buf[256];
libbpf_strerror(err, err_buf, sizeof(err_buf));
printf("Unable to load eBPF objects in file '%s' : %s\n",
bpf_file, err_buf);
return -1;
}
bpf_object__for_each_program(prog, obj) {
bpf_program__set_type(prog, prog_type[i]);
bpf_program__set_expected_attach_type(prog,
prog_attach_type[i]);
i++;
}
i = bpf_object__load(obj);
i = 0;
bpf_object__for_each_program(prog, obj) {
prog_fd[i] = bpf_program__fd(prog);
i++;
}
for (i = 0; i < sizeof(map_fd)/sizeof(int); i++) {
maps[i] = bpf_object__find_map_by_name(obj, map_names[i]);
map_fd[i] = bpf_map__fd(maps[i]);
if (map_fd[i] < 0) {
fprintf(stderr, "load_bpf_file: (%i) %s\n",
map_fd[i], strerror(errno));
return -1;
}
}
return 0;
}
static int test_suite(void)
{
int cg_fd, err;
err = populate_progs();
if (err < 0) {
fprintf(stderr, "ERROR: (%i) load bpf failed\n", err);
return err;
}
if (setup_cgroup_environment()) {
fprintf(stderr, "ERROR: cgroup env failed\n");
return -EINVAL;
}
cg_fd = create_and_get_cgroup(CG_PATH);
if (cg_fd < 0) {
fprintf(stderr,
"ERROR: (%i) open cg path failed: %s\n",
cg_fd, optarg);
return cg_fd;
}
/* Tests basic commands and APIs with range of iov values */
txmsg_start = txmsg_end = 0;
err = test_txmsg(cg_fd);
if (err)
goto out;
/* Tests interesting combinations of APIs used together */
err = test_mixed(cg_fd);
if (err)
goto out;
/* Tests pull_data API using start/end API */
err = test_start_end(cg_fd);
if (err)
goto out;
out:
printf("Summary: %i PASSED %i FAILED\n", passed, failed);
close(cg_fd);
return err;
}
int main(int argc, char **argv)
{
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
int iov_count = 1, length = 1024, rate = 1;
struct sockmap_options options = {0};
int opt, longindex, err, cg_fd = 0;
char *bpf_file = BPF_FILENAME;
int test = PING_PONG;
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
return 1;
}
if (argc < 2)
return test_suite();
while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:",
long_options, &longindex)) != -1) {
switch (opt) {
case 's':
txmsg_start = atoi(optarg);
break;
case 'e':
txmsg_end = atoi(optarg);
break;
case 'a':
txmsg_apply = atoi(optarg);
break;
case 'k':
txmsg_cork = atoi(optarg);
break;
case 'c':
cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
if (cg_fd < 0) {
fprintf(stderr,
"ERROR: (%i) open cg path failed: %s\n",
cg_fd, optarg);
return cg_fd;
}
break;
case 'r':
rate = atoi(optarg);
break;
case 'v':
options.verbose = 1;
break;
case 'i':
iov_count = atoi(optarg);
break;
case 'l':
length = atoi(optarg);
break;
case 'd':
options.data_test = true;
break;
case 't':
if (strcmp(optarg, "ping") == 0) {
test = PING_PONG;
} else if (strcmp(optarg, "sendmsg") == 0) {
test = SENDMSG;
} else if (strcmp(optarg, "base") == 0) {
test = BASE;
} else if (strcmp(optarg, "base_sendpage") == 0) {
test = BASE_SENDPAGE;
} else if (strcmp(optarg, "sendpage") == 0) {
test = SENDPAGE;
} else {
usage(argv);
return -1;
}
break;
case 0:
break;
case 'h':
default:
usage(argv);
return -1;
}
}
if (!cg_fd) {
fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n",
argv[0]);
return -1;
}
err = populate_progs();
if (err) {
fprintf(stderr, "populate program: (%s) %s\n",
bpf_file, strerror(errno));
return 1;
}
running = 1;
/* catch SIGINT */
signal(SIGINT, running_handler);
options.iov_count = iov_count;
options.iov_length = length;
options.rate = rate;
err = run_options(&options, cg_fd, test);
close(cg_fd); close(cg_fd);
return err; return err;
} }
......
/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io // SPDX-License-Identifier: GPL-2.0
* // Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io
* This program is free software; you can redistribute it and/or #include <stddef.h>
* modify it under the terms of version 2 of the GNU General Public #include <string.h>
* License as published by the Free Software Foundation. #include <linux/bpf.h>
* #include <linux/if_ether.h>
* This program is distributed in the hope that it will be useful, but #include <linux/if_packet.h>
* WITHOUT ANY WARRANTY; without even the implied warranty of #include <linux/ip.h>
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #include <linux/ipv6.h>
* General Public License for more details. #include <linux/in.h>
*/ #include <linux/udp.h>
#include <uapi/linux/bpf.h> #include <linux/tcp.h>
#include <uapi/linux/if_ether.h> #include <linux/pkt_cls.h>
#include <uapi/linux/if_packet.h> #include <sys/socket.h>
#include <uapi/linux/ip.h> #include "bpf_helpers.h"
#include "../../tools/testing/selftests/bpf/bpf_helpers.h" #include "bpf_endian.h"
#include "../../tools/testing/selftests/bpf/bpf_endian.h"
/* Sockmap sample program connects a client and a backend together /* Sockmap sample program connects a client and a backend together
* using cgroups. * using cgroups.
...@@ -337,5 +336,5 @@ int bpf_prog10(struct sk_msg_md *msg) ...@@ -337,5 +336,5 @@ int bpf_prog10(struct sk_msg_md *msg)
return SK_DROP; return SK_DROP;
} }
int _version SEC("version") = 1;
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册