1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# Uncomment to see generated bytecode 5#VERBOSE=verbose 6 7NS1=lwt_ns1 8NS2=lwt_ns2 9VETH0=tst_lwt1a 10VETH1=tst_lwt1b 11VETH2=tst_lwt2a 12VETH3=tst_lwt2b 13IPVETH0="192.168.254.1" 14IPVETH1="192.168.254.2" 15IPVETH1b="192.168.254.3" 16 17IPVETH2="192.168.111.1" 18IPVETH3="192.168.111.2" 19 20IP_LOCAL="192.168.99.1" 21 22PROG_SRC="test_lwt_bpf.c" 23BPF_PROG="test_lwt_bpf.o" 24TRACE_ROOT=/sys/kernel/debug/tracing 25CONTEXT_INFO=$(cat ${TRACE_ROOT}/trace_options | grep context) 26 27function lookup_mac() 28{ 29 set +x 30 if [ ! -z "$2" ]; then 31 MAC=$(ip netns exec $2 ip link show $1 | grep ether | awk '{print $2}') 32 else 33 MAC=$(ip link show $1 | grep ether | awk '{print $2}') 34 fi 35 MAC="${MAC//:/}" 36 echo "0x${MAC:10:2}${MAC:8:2}${MAC:6:2}${MAC:4:2}${MAC:2:2}${MAC:0:2}" 37 set -x 38} 39 40function cleanup { 41 set +ex 42 rm $BPF_PROG 2> /dev/null 43 ip link del $VETH0 2> /dev/null 44 ip link del $VETH1 2> /dev/null 45 ip link del $VETH2 2> /dev/null 46 ip link del $VETH3 2> /dev/null 47 ip netns exec $NS1 killall netserver 48 ip netns delete $NS1 2> /dev/null 49 ip netns delete $NS2 2> /dev/null 50 set -ex 51} 52 53function setup_one_veth { 54 ip netns add $1 55 ip link add $2 type veth peer name $3 56 ip link set dev $2 up 57 ip addr add $4/24 dev $2 58 ip link set $3 netns $1 59 ip netns exec $1 ip link set dev $3 up 60 ip netns exec $1 ip addr add $5/24 dev $3 61 62 if [ "$6" ]; then 63 ip netns exec $1 ip addr add $6/32 dev $3 64 fi 65} 66 67function get_trace { 68 set +x 69 cat ${TRACE_ROOT}/trace | grep -v '^#' 70 set -x 71} 72 73function cleanup_routes { 74 ip route del ${IPVETH1}/32 dev $VETH0 2> /dev/null || true 75 ip route del table local local ${IP_LOCAL}/32 dev lo 2> /dev/null || true 76} 77 78function install_test { 79 cleanup_routes 80 cp /dev/null ${TRACE_ROOT}/trace 81 82 OPTS="encap bpf headroom 14 $1 obj $BPF_PROG section $2 $VERBOSE" 83 84 if [ "$1" == "in" ]; then 85 ip route add table local local ${IP_LOCAL}/32 $OPTS dev lo 86 else 87 ip route add ${IPVETH1}/32 $OPTS dev $VETH0 88 fi 89} 90 91function remove_prog { 92 if [ "$1" == "in" ]; then 93 ip route del table local local ${IP_LOCAL}/32 dev lo 94 else 95 ip route del ${IPVETH1}/32 dev $VETH0 96 fi 97} 98 99function filter_trace { 100 # Add newline to allow starting EXPECT= variables on newline 101 NL=$'\n' 102 echo "${NL}$*" | sed -e 's/bpf_trace_printk: //g' 103} 104 105function expect_fail { 106 set +x 107 echo "FAIL:" 108 echo "Expected: $1" 109 echo "Got: $2" 110 set -x 111 exit 1 112} 113 114function match_trace { 115 set +x 116 RET=0 117 TRACE=$1 118 EXPECT=$2 119 GOT="$(filter_trace "$TRACE")" 120 121 [ "$GOT" != "$EXPECT" ] && { 122 expect_fail "$EXPECT" "$GOT" 123 RET=1 124 } 125 set -x 126 return $RET 127} 128 129function test_start { 130 set +x 131 echo "----------------------------------------------------------------" 132 echo "Starting test: $*" 133 echo "----------------------------------------------------------------" 134 set -x 135} 136 137function failure { 138 get_trace 139 echo "FAIL: $*" 140 exit 1 141} 142 143function test_ctx_xmit { 144 test_start "test_ctx on lwt xmit" 145 install_test xmit test_ctx 146 ping -c 3 $IPVETH1 || { 147 failure "test_ctx xmit: packets are dropped" 148 } 149 match_trace "$(get_trace)" " 150len 84 hash 0 protocol 8 151cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX 152len 84 hash 0 protocol 8 153cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX 154len 84 hash 0 protocol 8 155cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX" || exit 1 156 remove_prog xmit 157} 158 159function test_ctx_out { 160 test_start "test_ctx on lwt out" 161 install_test out test_ctx 162 ping -c 3 $IPVETH1 || { 163 failure "test_ctx out: packets are dropped" 164 } 165 match_trace "$(get_trace)" " 166len 84 hash 0 protocol 8 167cb 1234 ingress_ifindex 0 ifindex 0 168len 84 hash 0 protocol 8 169cb 1234 ingress_ifindex 0 ifindex 0 170len 84 hash 0 protocol 8 171cb 1234 ingress_ifindex 0 ifindex 0" || exit 1 172 remove_prog out 173} 174 175function test_ctx_in { 176 test_start "test_ctx on lwt in" 177 install_test in test_ctx 178 ping -c 3 $IP_LOCAL || { 179 failure "test_ctx out: packets are dropped" 180 } 181 # We will both request & reply packets as the packets will 182 # be from $IP_LOCAL => $IP_LOCAL 183 match_trace "$(get_trace)" " 184len 84 hash 0 protocol 8 185cb 1234 ingress_ifindex 1 ifindex 1 186len 84 hash 0 protocol 8 187cb 1234 ingress_ifindex 1 ifindex 1 188len 84 hash 0 protocol 8 189cb 1234 ingress_ifindex 1 ifindex 1 190len 84 hash 0 protocol 8 191cb 1234 ingress_ifindex 1 ifindex 1 192len 84 hash 0 protocol 8 193cb 1234 ingress_ifindex 1 ifindex 1 194len 84 hash 0 protocol 8 195cb 1234 ingress_ifindex 1 ifindex 1" || exit 1 196 remove_prog in 197} 198 199function test_data { 200 test_start "test_data on lwt $1" 201 install_test $1 test_data 202 ping -c 3 $IPVETH1 || { 203 failure "test_data ${1}: packets are dropped" 204 } 205 match_trace "$(get_trace)" " 206src: 1fea8c0 dst: 2fea8c0 207src: 1fea8c0 dst: 2fea8c0 208src: 1fea8c0 dst: 2fea8c0" || exit 1 209 remove_prog $1 210} 211 212function test_data_in { 213 test_start "test_data on lwt in" 214 install_test in test_data 215 ping -c 3 $IP_LOCAL || { 216 failure "test_data in: packets are dropped" 217 } 218 # We will both request & reply packets as the packets will 219 # be from $IP_LOCAL => $IP_LOCAL 220 match_trace "$(get_trace)" " 221src: 163a8c0 dst: 163a8c0 222src: 163a8c0 dst: 163a8c0 223src: 163a8c0 dst: 163a8c0 224src: 163a8c0 dst: 163a8c0 225src: 163a8c0 dst: 163a8c0 226src: 163a8c0 dst: 163a8c0" || exit 1 227 remove_prog in 228} 229 230function test_cb { 231 test_start "test_cb on lwt $1" 232 install_test $1 test_cb 233 ping -c 3 $IPVETH1 || { 234 failure "test_cb ${1}: packets are dropped" 235 } 236 match_trace "$(get_trace)" " 237cb0: 0 cb1: 0 cb2: 0 238cb3: 0 cb4: 0 239cb0: 0 cb1: 0 cb2: 0 240cb3: 0 cb4: 0 241cb0: 0 cb1: 0 cb2: 0 242cb3: 0 cb4: 0" || exit 1 243 remove_prog $1 244} 245 246function test_cb_in { 247 test_start "test_cb on lwt in" 248 install_test in test_cb 249 ping -c 3 $IP_LOCAL || { 250 failure "test_cb in: packets are dropped" 251 } 252 # We will both request & reply packets as the packets will 253 # be from $IP_LOCAL => $IP_LOCAL 254 match_trace "$(get_trace)" " 255cb0: 0 cb1: 0 cb2: 0 256cb3: 0 cb4: 0 257cb0: 0 cb1: 0 cb2: 0 258cb3: 0 cb4: 0 259cb0: 0 cb1: 0 cb2: 0 260cb3: 0 cb4: 0 261cb0: 0 cb1: 0 cb2: 0 262cb3: 0 cb4: 0 263cb0: 0 cb1: 0 cb2: 0 264cb3: 0 cb4: 0 265cb0: 0 cb1: 0 cb2: 0 266cb3: 0 cb4: 0" || exit 1 267 remove_prog in 268} 269 270function test_drop_all { 271 test_start "test_drop_all on lwt $1" 272 install_test $1 drop_all 273 ping -c 3 $IPVETH1 && { 274 failure "test_drop_all ${1}: Unexpected success of ping" 275 } 276 match_trace "$(get_trace)" " 277dropping with: 2 278dropping with: 2 279dropping with: 2" || exit 1 280 remove_prog $1 281} 282 283function test_drop_all_in { 284 test_start "test_drop_all on lwt in" 285 install_test in drop_all 286 ping -c 3 $IP_LOCAL && { 287 failure "test_drop_all in: Unexpected success of ping" 288 } 289 match_trace "$(get_trace)" " 290dropping with: 2 291dropping with: 2 292dropping with: 2" || exit 1 293 remove_prog in 294} 295 296function test_push_ll_and_redirect { 297 test_start "test_push_ll_and_redirect on lwt xmit" 298 install_test xmit push_ll_and_redirect 299 ping -c 3 $IPVETH1 || { 300 failure "Redirected packets appear to be dropped" 301 } 302 match_trace "$(get_trace)" " 303redirected to $DST_IFINDEX 304redirected to $DST_IFINDEX 305redirected to $DST_IFINDEX" || exit 1 306 remove_prog xmit 307} 308 309function test_no_l2_and_redirect { 310 test_start "test_no_l2_and_redirect on lwt xmit" 311 install_test xmit fill_garbage_and_redirect 312 ping -c 3 $IPVETH1 && { 313 failure "Unexpected success despite lack of L2 header" 314 } 315 match_trace "$(get_trace)" " 316redirected to $DST_IFINDEX 317redirected to $DST_IFINDEX 318redirected to $DST_IFINDEX" || exit 1 319 remove_prog xmit 320} 321 322function test_rewrite { 323 test_start "test_rewrite on lwt xmit" 324 install_test xmit test_rewrite 325 ping -c 3 $IPVETH1 || { 326 failure "Rewritten packets appear to be dropped" 327 } 328 match_trace "$(get_trace)" " 329out: rewriting from 2fea8c0 to 3fea8c0 330out: rewriting from 2fea8c0 to 3fea8c0 331out: rewriting from 2fea8c0 to 3fea8c0" || exit 1 332 remove_prog out 333} 334 335function test_fill_garbage { 336 test_start "test_fill_garbage on lwt xmit" 337 install_test xmit fill_garbage 338 ping -c 3 $IPVETH1 && { 339 failure "test_drop_all ${1}: Unexpected success of ping" 340 } 341 match_trace "$(get_trace)" " 342Set initial 96 bytes of header to FF 343Set initial 96 bytes of header to FF 344Set initial 96 bytes of header to FF" || exit 1 345 remove_prog xmit 346} 347 348function test_netperf_nop { 349 test_start "test_netperf_nop on lwt xmit" 350 install_test xmit nop 351 netperf -H $IPVETH1 -t TCP_STREAM || { 352 failure "packets appear to be dropped" 353 } 354 match_trace "$(get_trace)" ""|| exit 1 355 remove_prog xmit 356} 357 358function test_netperf_redirect { 359 test_start "test_netperf_redirect on lwt xmit" 360 install_test xmit push_ll_and_redirect_silent 361 netperf -H $IPVETH1 -t TCP_STREAM || { 362 failure "Rewritten packets appear to be dropped" 363 } 364 match_trace "$(get_trace)" ""|| exit 1 365 remove_prog xmit 366} 367 368cleanup 369setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b 370setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3 371ip netns exec $NS1 netserver 372echo 1 > ${TRACE_ROOT}/tracing_on 373echo nocontext-info > ${TRACE_ROOT}/trace_options 374 375DST_MAC=$(lookup_mac $VETH1 $NS1) 376SRC_MAC=$(lookup_mac $VETH0) 377DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex) 378 379CLANG_OPTS="-O2 -target bpf -I ../include/" 380CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX" 381clang $CLANG_OPTS -c $PROG_SRC -o $BPF_PROG 382 383test_ctx_xmit 384test_ctx_out 385test_ctx_in 386test_data "xmit" 387test_data "out" 388test_data_in 389test_cb "xmit" 390test_cb "out" 391test_cb_in 392test_drop_all "xmit" 393test_drop_all "out" 394test_drop_all_in 395test_rewrite 396test_push_ll_and_redirect 397test_no_l2_and_redirect 398test_fill_garbage 399test_netperf_nop 400test_netperf_redirect 401 402cleanup 403echo 0 > ${TRACE_ROOT}/tracing_on 404echo $CONTEXT_INFO > ${TRACE_ROOT}/trace_options 405exit 0 406