forked from Minki/linux
f74599f7c5
Adds a series of tests to verify the functionality of attaching BPF programs at LWT hooks. Also adds a sample which collects a histogram of packet sizes which pass through an LWT hook. $ ./lwt_len_hist.sh Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family AF_UNSPEC MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.253.2 () port 0 AF_INET : demo Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 10.00 39857.69 1 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 22 | | 64 -> 127 : 98 | | 128 -> 255 : 213 | | 256 -> 511 : 1444251 |******** | 512 -> 1023 : 660610 |*** | 1024 -> 2047 : 535241 |** | 2048 -> 4095 : 19 | | 4096 -> 8191 : 180 | | 8192 -> 16383 : 5578023 |************************************* | 16384 -> 32767 : 632099 |*** | 32768 -> 65535 : 6575 | | Signed-off-by: Thomas Graf <tgraf@suug.ch> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
400 lines
8.9 KiB
Bash
400 lines
8.9 KiB
Bash
#!/bin/bash
|
|
|
|
# Uncomment to see generated bytecode
|
|
#VERBOSE=verbose
|
|
|
|
NS1=lwt_ns1
|
|
NS2=lwt_ns2
|
|
VETH0=tst_lwt1a
|
|
VETH1=tst_lwt1b
|
|
VETH2=tst_lwt2a
|
|
VETH3=tst_lwt2b
|
|
IPVETH0="192.168.254.1"
|
|
IPVETH1="192.168.254.2"
|
|
IPVETH1b="192.168.254.3"
|
|
|
|
IPVETH2="192.168.111.1"
|
|
IPVETH3="192.168.111.2"
|
|
|
|
IP_LOCAL="192.168.99.1"
|
|
|
|
TRACE_ROOT=/sys/kernel/debug/tracing
|
|
|
|
function lookup_mac()
|
|
{
|
|
set +x
|
|
if [ ! -z "$2" ]; then
|
|
MAC=$(ip netns exec $2 ip link show $1 | grep ether | awk '{print $2}')
|
|
else
|
|
MAC=$(ip link show $1 | grep ether | awk '{print $2}')
|
|
fi
|
|
MAC="${MAC//:/}"
|
|
echo "0x${MAC:10:2}${MAC:8:2}${MAC:6:2}${MAC:4:2}${MAC:2:2}${MAC:0:2}"
|
|
set -x
|
|
}
|
|
|
|
function cleanup {
|
|
set +ex
|
|
rm test_lwt_bpf.o 2> /dev/null
|
|
ip link del $VETH0 2> /dev/null
|
|
ip link del $VETH1 2> /dev/null
|
|
ip link del $VETH2 2> /dev/null
|
|
ip link del $VETH3 2> /dev/null
|
|
ip netns exec $NS1 killall netserver
|
|
ip netns delete $NS1 2> /dev/null
|
|
ip netns delete $NS2 2> /dev/null
|
|
set -ex
|
|
}
|
|
|
|
function setup_one_veth {
|
|
ip netns add $1
|
|
ip link add $2 type veth peer name $3
|
|
ip link set dev $2 up
|
|
ip addr add $4/24 dev $2
|
|
ip link set $3 netns $1
|
|
ip netns exec $1 ip link set dev $3 up
|
|
ip netns exec $1 ip addr add $5/24 dev $3
|
|
|
|
if [ "$6" ]; then
|
|
ip netns exec $1 ip addr add $6/32 dev $3
|
|
fi
|
|
}
|
|
|
|
function get_trace {
|
|
set +x
|
|
cat ${TRACE_ROOT}/trace | grep -v '^#'
|
|
set -x
|
|
}
|
|
|
|
function cleanup_routes {
|
|
ip route del ${IPVETH1}/32 dev $VETH0 2> /dev/null || true
|
|
ip route del table local local ${IP_LOCAL}/32 dev lo 2> /dev/null || true
|
|
}
|
|
|
|
function install_test {
|
|
cleanup_routes
|
|
cp /dev/null ${TRACE_ROOT}/trace
|
|
|
|
OPTS="encap bpf headroom 14 $1 obj test_lwt_bpf.o section $2 $VERBOSE"
|
|
|
|
if [ "$1" == "in" ]; then
|
|
ip route add table local local ${IP_LOCAL}/32 $OPTS dev lo
|
|
else
|
|
ip route add ${IPVETH1}/32 $OPTS dev $VETH0
|
|
fi
|
|
}
|
|
|
|
function remove_prog {
|
|
if [ "$1" == "in" ]; then
|
|
ip route del table local local ${IP_LOCAL}/32 dev lo
|
|
else
|
|
ip route del ${IPVETH1}/32 dev $VETH0
|
|
fi
|
|
}
|
|
|
|
function filter_trace {
|
|
# Add newline to allow starting EXPECT= variables on newline
|
|
NL=$'\n'
|
|
echo "${NL}$*" | sed -e 's/^.*: : //g'
|
|
}
|
|
|
|
function expect_fail {
|
|
set +x
|
|
echo "FAIL:"
|
|
echo "Expected: $1"
|
|
echo "Got: $2"
|
|
set -x
|
|
exit 1
|
|
}
|
|
|
|
function match_trace {
|
|
set +x
|
|
RET=0
|
|
TRACE=$1
|
|
EXPECT=$2
|
|
GOT="$(filter_trace "$TRACE")"
|
|
|
|
[ "$GOT" != "$EXPECT" ] && {
|
|
expect_fail "$EXPECT" "$GOT"
|
|
RET=1
|
|
}
|
|
set -x
|
|
return $RET
|
|
}
|
|
|
|
function test_start {
|
|
set +x
|
|
echo "----------------------------------------------------------------"
|
|
echo "Starting test: $*"
|
|
echo "----------------------------------------------------------------"
|
|
set -x
|
|
}
|
|
|
|
function failure {
|
|
get_trace
|
|
echo "FAIL: $*"
|
|
exit 1
|
|
}
|
|
|
|
function test_ctx_xmit {
|
|
test_start "test_ctx on lwt xmit"
|
|
install_test xmit test_ctx
|
|
ping -c 3 $IPVETH1 || {
|
|
failure "test_ctx xmit: packets are dropped"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX" || exit 1
|
|
remove_prog xmit
|
|
}
|
|
|
|
function test_ctx_out {
|
|
test_start "test_ctx on lwt out"
|
|
install_test out test_ctx
|
|
ping -c 3 $IPVETH1 || {
|
|
failure "test_ctx out: packets are dropped"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
len 84 hash 0 protocol 0
|
|
cb 1234 ingress_ifindex 0 ifindex 0
|
|
len 84 hash 0 protocol 0
|
|
cb 1234 ingress_ifindex 0 ifindex 0
|
|
len 84 hash 0 protocol 0
|
|
cb 1234 ingress_ifindex 0 ifindex 0" || exit 1
|
|
remove_prog out
|
|
}
|
|
|
|
function test_ctx_in {
|
|
test_start "test_ctx on lwt in"
|
|
install_test in test_ctx
|
|
ping -c 3 $IP_LOCAL || {
|
|
failure "test_ctx out: packets are dropped"
|
|
}
|
|
# We will both request & reply packets as the packets will
|
|
# be from $IP_LOCAL => $IP_LOCAL
|
|
match_trace "$(get_trace)" "
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 1 ifindex 1
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 1 ifindex 1
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 1 ifindex 1
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 1 ifindex 1
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 1 ifindex 1
|
|
len 84 hash 0 protocol 8
|
|
cb 1234 ingress_ifindex 1 ifindex 1" || exit 1
|
|
remove_prog in
|
|
}
|
|
|
|
function test_data {
|
|
test_start "test_data on lwt $1"
|
|
install_test $1 test_data
|
|
ping -c 3 $IPVETH1 || {
|
|
failure "test_data ${1}: packets are dropped"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
src: 1fea8c0 dst: 2fea8c0
|
|
src: 1fea8c0 dst: 2fea8c0
|
|
src: 1fea8c0 dst: 2fea8c0" || exit 1
|
|
remove_prog $1
|
|
}
|
|
|
|
function test_data_in {
|
|
test_start "test_data on lwt in"
|
|
install_test in test_data
|
|
ping -c 3 $IP_LOCAL || {
|
|
failure "test_data in: packets are dropped"
|
|
}
|
|
# We will both request & reply packets as the packets will
|
|
# be from $IP_LOCAL => $IP_LOCAL
|
|
match_trace "$(get_trace)" "
|
|
src: 163a8c0 dst: 163a8c0
|
|
src: 163a8c0 dst: 163a8c0
|
|
src: 163a8c0 dst: 163a8c0
|
|
src: 163a8c0 dst: 163a8c0
|
|
src: 163a8c0 dst: 163a8c0
|
|
src: 163a8c0 dst: 163a8c0" || exit 1
|
|
remove_prog in
|
|
}
|
|
|
|
function test_cb {
|
|
test_start "test_cb on lwt $1"
|
|
install_test $1 test_cb
|
|
ping -c 3 $IPVETH1 || {
|
|
failure "test_cb ${1}: packets are dropped"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0" || exit 1
|
|
remove_prog $1
|
|
}
|
|
|
|
function test_cb_in {
|
|
test_start "test_cb on lwt in"
|
|
install_test in test_cb
|
|
ping -c 3 $IP_LOCAL || {
|
|
failure "test_cb in: packets are dropped"
|
|
}
|
|
# We will both request & reply packets as the packets will
|
|
# be from $IP_LOCAL => $IP_LOCAL
|
|
match_trace "$(get_trace)" "
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0
|
|
cb0: 0 cb1: 0 cb2: 0
|
|
cb3: 0 cb4: 0" || exit 1
|
|
remove_prog in
|
|
}
|
|
|
|
function test_drop_all {
|
|
test_start "test_drop_all on lwt $1"
|
|
install_test $1 drop_all
|
|
ping -c 3 $IPVETH1 && {
|
|
failure "test_drop_all ${1}: Unexpected success of ping"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
dropping with: 2
|
|
dropping with: 2
|
|
dropping with: 2" || exit 1
|
|
remove_prog $1
|
|
}
|
|
|
|
function test_drop_all_in {
|
|
test_start "test_drop_all on lwt in"
|
|
install_test in drop_all
|
|
ping -c 3 $IP_LOCAL && {
|
|
failure "test_drop_all in: Unexpected success of ping"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
dropping with: 2
|
|
dropping with: 2
|
|
dropping with: 2" || exit 1
|
|
remove_prog in
|
|
}
|
|
|
|
function test_push_ll_and_redirect {
|
|
test_start "test_push_ll_and_redirect on lwt xmit"
|
|
install_test xmit push_ll_and_redirect
|
|
ping -c 3 $IPVETH1 || {
|
|
failure "Redirected packets appear to be dropped"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
redirected to $DST_IFINDEX
|
|
redirected to $DST_IFINDEX
|
|
redirected to $DST_IFINDEX" || exit 1
|
|
remove_prog xmit
|
|
}
|
|
|
|
function test_no_l2_and_redirect {
|
|
test_start "test_no_l2_and_redirect on lwt xmit"
|
|
install_test xmit fill_garbage_and_redirect
|
|
ping -c 3 $IPVETH1 && {
|
|
failure "Unexpected success despite lack of L2 header"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
redirected to $DST_IFINDEX
|
|
redirected to $DST_IFINDEX
|
|
redirected to $DST_IFINDEX" || exit 1
|
|
remove_prog xmit
|
|
}
|
|
|
|
function test_rewrite {
|
|
test_start "test_rewrite on lwt xmit"
|
|
install_test xmit test_rewrite
|
|
ping -c 3 $IPVETH1 || {
|
|
failure "Rewritten packets appear to be dropped"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
out: rewriting from 2fea8c0 to 3fea8c0
|
|
out: rewriting from 2fea8c0 to 3fea8c0
|
|
out: rewriting from 2fea8c0 to 3fea8c0" || exit 1
|
|
remove_prog out
|
|
}
|
|
|
|
function test_fill_garbage {
|
|
test_start "test_fill_garbage on lwt xmit"
|
|
install_test xmit fill_garbage
|
|
ping -c 3 $IPVETH1 && {
|
|
failure "test_drop_all ${1}: Unexpected success of ping"
|
|
}
|
|
match_trace "$(get_trace)" "
|
|
Set initial 96 bytes of header to FF
|
|
Set initial 96 bytes of header to FF
|
|
Set initial 96 bytes of header to FF" || exit 1
|
|
remove_prog xmit
|
|
}
|
|
|
|
function test_netperf_nop {
|
|
test_start "test_netperf_nop on lwt xmit"
|
|
install_test xmit nop
|
|
netperf -H $IPVETH1 -t TCP_STREAM || {
|
|
failure "packets appear to be dropped"
|
|
}
|
|
match_trace "$(get_trace)" ""|| exit 1
|
|
remove_prog xmit
|
|
}
|
|
|
|
function test_netperf_redirect {
|
|
test_start "test_netperf_redirect on lwt xmit"
|
|
install_test xmit push_ll_and_redirect_silent
|
|
netperf -H $IPVETH1 -t TCP_STREAM || {
|
|
failure "Rewritten packets appear to be dropped"
|
|
}
|
|
match_trace "$(get_trace)" ""|| exit 1
|
|
remove_prog xmit
|
|
}
|
|
|
|
cleanup
|
|
setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b
|
|
setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3
|
|
ip netns exec $NS1 netserver
|
|
echo 1 > ${TRACE_ROOT}/tracing_on
|
|
|
|
DST_MAC=$(lookup_mac $VETH1 $NS1)
|
|
SRC_MAC=$(lookup_mac $VETH0)
|
|
DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex)
|
|
|
|
CLANG_OPTS="-O2 -target bpf -I ../include/"
|
|
CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX"
|
|
clang $CLANG_OPTS -c test_lwt_bpf.c -o test_lwt_bpf.o
|
|
|
|
test_ctx_xmit
|
|
test_ctx_out
|
|
test_ctx_in
|
|
test_data "xmit"
|
|
test_data "out"
|
|
test_data_in
|
|
test_cb "xmit"
|
|
test_cb "out"
|
|
test_cb_in
|
|
test_drop_all "xmit"
|
|
test_drop_all "out"
|
|
test_drop_all_in
|
|
test_rewrite
|
|
test_push_ll_and_redirect
|
|
test_no_l2_and_redirect
|
|
test_fill_garbage
|
|
test_netperf_nop
|
|
test_netperf_redirect
|
|
|
|
cleanup
|
|
echo 0 > ${TRACE_ROOT}/tracing_on
|
|
exit 0
|