406 lines
9.2 KiB
Bash
406 lines
9.2 KiB
Bash
|
#!/bin/bash
|
||
|
# SPDX-License-Identifier: GPL-2.0
|
||
|
|
||
|
# 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"
|
||
|
|
||
|
PROG_SRC="test_lwt_bpf.c"
|
||
|
BPF_PROG="test_lwt_bpf.o"
|
||
|
TRACE_ROOT=/sys/kernel/debug/tracing
|
||
|
CONTEXT_INFO=$(cat ${TRACE_ROOT}/trace_options | grep context)
|
||
|
|
||
|
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 $BPF_PROG 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 $BPF_PROG 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/bpf_trace_printk: //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 8
|
||
|
cb 1234 ingress_ifindex 0 ifindex 0
|
||
|
len 84 hash 0 protocol 8
|
||
|
cb 1234 ingress_ifindex 0 ifindex 0
|
||
|
len 84 hash 0 protocol 8
|
||
|
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
|
||
|
echo nocontext-info > ${TRACE_ROOT}/trace_options
|
||
|
|
||
|
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 $PROG_SRC -o $BPF_PROG
|
||
|
|
||
|
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
|
||
|
echo $CONTEXT_INFO > ${TRACE_ROOT}/trace_options
|
||
|
exit 0
|