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