1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 3 4 # Uncomment to see generated bytecode 5 #VERBOSE=verbose 6 7 NS1=lwt_ns1 8 NS2=lwt_ns2 9 VETH0=tst_lwt1a 10 VETH1=tst_lwt1b 11 VETH2=tst_lwt2a 12 VETH3=tst_lwt2b 13 IPVETH0="192.168.254.1" 14 IPVETH1="192.168.254.2" 15 IPVETH1b="192.168.254.3" 16 17 IPVETH2="192.168.111.1" 18 IPVETH3="192.168.111.2" 19 20 IP_LOCAL="192.168.99.1" 21 22 PROG_SRC="test_lwt_bpf.c" 23 BPF_PROG="test_lwt_bpf.o" 24 TRACE_ROOT=/sys/kernel/tracing 25 CONTEXT_INFO=$(cat ${TRACE_ROOT}/trace_options | grep context) 26 27 function 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 40 function 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 53 function 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 67 function get_trace { 68 set +x 69 cat ${TRACE_ROOT}/trace | grep -v '^#' 70 set -x 71 } 72 73 function 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 78 function 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 91 function 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 99 function 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 105 function expect_fail { 106 set +x 107 echo "FAIL:" 108 echo "Expected: $1" 109 echo "Got: $2" 110 set -x 111 exit 1 112 } 113 114 function 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 129 function test_start { 130 set +x 131 echo "----------------------------------------------------------------" 132 echo "Starting test: $*" 133 echo "----------------------------------------------------------------" 134 set -x 135 } 136 137 function failure { 138 get_trace 139 echo "FAIL: $*" 140 exit 1 141 } 142 143 function 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)" " 150 len 84 hash 0 protocol 8 151 cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX 152 len 84 hash 0 protocol 8 153 cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX 154 len 84 hash 0 protocol 8 155 cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX" || exit 1 156 remove_prog xmit 157 } 158 159 function 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)" " 166 len 84 hash 0 protocol 8 167 cb 1234 ingress_ifindex 0 ifindex 0 168 len 84 hash 0 protocol 8 169 cb 1234 ingress_ifindex 0 ifindex 0 170 len 84 hash 0 protocol 8 171 cb 1234 ingress_ifindex 0 ifindex 0" || exit 1 172 remove_prog out 173 } 174 175 function 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)" " 184 len 84 hash 0 protocol 8 185 cb 1234 ingress_ifindex 1 ifindex 1 186 len 84 hash 0 protocol 8 187 cb 1234 ingress_ifindex 1 ifindex 1 188 len 84 hash 0 protocol 8 189 cb 1234 ingress_ifindex 1 ifindex 1 190 len 84 hash 0 protocol 8 191 cb 1234 ingress_ifindex 1 ifindex 1 192 len 84 hash 0 protocol 8 193 cb 1234 ingress_ifindex 1 ifindex 1 194 len 84 hash 0 protocol 8 195 cb 1234 ingress_ifindex 1 ifindex 1" || exit 1 196 remove_prog in 197 } 198 199 function 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)" " 206 src: 1fea8c0 dst: 2fea8c0 207 src: 1fea8c0 dst: 2fea8c0 208 src: 1fea8c0 dst: 2fea8c0" || exit 1 209 remove_prog $1 210 } 211 212 function 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)" " 221 src: 163a8c0 dst: 163a8c0 222 src: 163a8c0 dst: 163a8c0 223 src: 163a8c0 dst: 163a8c0 224 src: 163a8c0 dst: 163a8c0 225 src: 163a8c0 dst: 163a8c0 226 src: 163a8c0 dst: 163a8c0" || exit 1 227 remove_prog in 228 } 229 230 function 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)" " 237 cb0: 0 cb1: 0 cb2: 0 238 cb3: 0 cb4: 0 239 cb0: 0 cb1: 0 cb2: 0 240 cb3: 0 cb4: 0 241 cb0: 0 cb1: 0 cb2: 0 242 cb3: 0 cb4: 0" || exit 1 243 remove_prog $1 244 } 245 246 function 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)" " 255 cb0: 0 cb1: 0 cb2: 0 256 cb3: 0 cb4: 0 257 cb0: 0 cb1: 0 cb2: 0 258 cb3: 0 cb4: 0 259 cb0: 0 cb1: 0 cb2: 0 260 cb3: 0 cb4: 0 261 cb0: 0 cb1: 0 cb2: 0 262 cb3: 0 cb4: 0 263 cb0: 0 cb1: 0 cb2: 0 264 cb3: 0 cb4: 0 265 cb0: 0 cb1: 0 cb2: 0 266 cb3: 0 cb4: 0" || exit 1 267 remove_prog in 268 } 269 270 function 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)" " 277 dropping with: 2 278 dropping with: 2 279 dropping with: 2" || exit 1 280 remove_prog $1 281 } 282 283 function 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)" " 290 dropping with: 2 291 dropping with: 2 292 dropping with: 2" || exit 1 293 remove_prog in 294 } 295 296 function 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)" " 303 redirected to $DST_IFINDEX 304 redirected to $DST_IFINDEX 305 redirected to $DST_IFINDEX" || exit 1 306 remove_prog xmit 307 } 308 309 function 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)" " 316 redirected to $DST_IFINDEX 317 redirected to $DST_IFINDEX 318 redirected to $DST_IFINDEX" || exit 1 319 remove_prog xmit 320 } 321 322 function 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)" " 329 out: rewriting from 2fea8c0 to 3fea8c0 330 out: rewriting from 2fea8c0 to 3fea8c0 331 out: rewriting from 2fea8c0 to 3fea8c0" || exit 1 332 remove_prog out 333 } 334 335 function 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)" " 342 Set initial 96 bytes of header to FF 343 Set initial 96 bytes of header to FF 344 Set initial 96 bytes of header to FF" || exit 1 345 remove_prog xmit 346 } 347 348 function 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 358 function 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 368 cleanup 369 setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b 370 setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3 371 ip netns exec $NS1 netserver 372 echo 1 > ${TRACE_ROOT}/tracing_on 373 echo nocontext-info > ${TRACE_ROOT}/trace_options 374 375 DST_MAC=$(lookup_mac $VETH1 $NS1) 376 SRC_MAC=$(lookup_mac $VETH0) 377 DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex) 378 379 CLANG_OPTS="-O2 --target=bpf -I ../include/" 380 CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX" 381 clang $CLANG_OPTS -c $PROG_SRC -o $BPF_PROG 382 383 test_ctx_xmit 384 test_ctx_out 385 test_ctx_in 386 test_data "xmit" 387 test_data "out" 388 test_data_in 389 test_cb "xmit" 390 test_cb "out" 391 test_cb_in 392 test_drop_all "xmit" 393 test_drop_all "out" 394 test_drop_all_in 395 test_rewrite 396 test_push_ll_and_redirect 397 test_no_l2_and_redirect 398 test_fill_garbage 399 test_netperf_nop 400 test_netperf_redirect 401 402 cleanup 403 echo 0 > ${TRACE_ROOT}/tracing_on 404 echo $CONTEXT_INFO > ${TRACE_ROOT}/trace_options 405 exit 0
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.