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