1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# OVS kernel module self tests 5 6trap ovs_exit_sig EXIT TERM INT ERR 7 8# Kselftest framework requirement - SKIP code is 4. 9ksft_skip=4 10 11PAUSE_ON_FAIL=no 12VERBOSE=0 13TRACING=0 14WAIT_TIMEOUT=5 15 16if test "X$KSFT_MACHINE_SLOW" == "Xyes"; then 17 WAIT_TIMEOUT=10 18fi 19 20tests=" 21 arp_ping eth-arp: Basic arp ping between two NS 22 ct_connect_v4 ip4-ct-xon: Basic ipv4 tcp connection using ct 23 connect_v4 ip4-xon: Basic ipv4 ping between two NS 24 nat_connect_v4 ip4-nat-xon: Basic ipv4 tcp connection via NAT 25 nat_related_v4 ip4-nat-related: ICMP related matches work with SNAT 26 netlink_checks ovsnl: validate netlink attrs and settings 27 upcall_interfaces ovs: test the upcall interfaces 28 tunnel_metadata ovs: test extraction of tunnel metadata 29 drop_reason drop: test drop reasons are emitted 30 pop_vlan vlan: POP_VLAN action strips tag 31 dec_ttl ttl: dec_ttl decrements IP TTL 32 flow_set flow-set: Flow modify 33 action_set set: SET action rewrites fields 34 trunc trunc: output truncation 35 icmpv6 icmpv6: ICMPv6 echo type match 36 sctp_connect_v4 sctp: SCTP flow key matching 37 sctp_connect_v6 sctp6: SCTP flow keys over IPv6 38 sctp_nat_connect_v4 sctpnat4: SCTP NAT translation 39 psample psample: Sampling packets with psample" 40 41info() { 42 [ "${ovs_dir}" != "" ] && 43 echo "`date +"[%m-%d %H:%M:%S]"` $*" >> ${ovs_dir}/debug.log 44 [ $VERBOSE = 0 ] || echo $* 45} 46 47ovs_wait() { 48 info "waiting $WAIT_TIMEOUT s for: $@" 49 50 if "$@" ; then 51 info "wait succeeded immediately" 52 return 0 53 fi 54 55 # A quick re-check helps speed up small races in fast systems. 56 # However, fractional sleeps might not necessarily work. 57 local start=0 58 sleep 0.1 || { sleep 1; start=1; } 59 60 for (( i=start; i<WAIT_TIMEOUT; i++ )); do 61 if "$@" ; then 62 info "wait succeeded after $i seconds" 63 return 0 64 fi 65 sleep 1 66 done 67 info "wait failed after $i seconds" 68 return 1 69} 70 71ovs_base=`pwd` 72sbxs= 73sbx_add () { 74 info "adding sandbox '$1'" 75 76 sbxs="$sbxs $1" 77 78 NO_BIN=0 79 80 # Create sandbox. 81 local d="$ovs_base"/$1 82 if [ -e $d ]; then 83 info "removing $d" 84 rm -rf "$d" 85 fi 86 mkdir "$d" || return 1 87 ovs_setenv $1 88} 89 90ovs_exit_sig() { 91 [ -e ${ovs_dir}/cleanup ] && . "$ovs_dir/cleanup" 92} 93 94on_exit() { 95 echo "$1" > ${ovs_dir}/cleanup.tmp 96 cat ${ovs_dir}/cleanup >> ${ovs_dir}/cleanup.tmp 97 mv ${ovs_dir}/cleanup.tmp ${ovs_dir}/cleanup 98} 99 100ovs_setenv() { 101 sandbox=$1 102 103 ovs_dir=$ovs_base${1:+/$1}; export ovs_dir 104 105 test -e ${ovs_dir}/cleanup || : > ${ovs_dir}/cleanup 106} 107 108ovs_sbx() { 109 if test "X$2" != X; then 110 (ovs_setenv $1; shift; 111 info "run cmd: $@"; "$@" >> ${ovs_dir}/debug.log) 112 else 113 ovs_setenv $1 114 fi 115} 116 117ovs_add_dp () { 118 info "Adding DP/Bridge IF: sbx:$1 dp:$2 {$3, $4, $5}" 119 sbxname="$1" 120 shift 121 ovs_sbx "$sbxname" python3 $ovs_base/ovs-dpctl.py add-dp $* 122 on_exit "ovs_sbx $sbxname python3 $ovs_base/ovs-dpctl.py del-dp $1;" 123} 124 125ovs_add_if () { 126 info "Adding IF to DP: br:$3 if:$4 ($2)" 127 if [ "$5" != "-u" ]; then 128 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if \ 129 -t "$2" "$3" "$4" || return 1 130 else 131 python3 $ovs_base/ovs-dpctl.py add-if \ 132 -u -t "$2" "$3" "$4" >$ovs_dir/$4.out 2>$ovs_dir/$4.err & 133 pid=$! 134 on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null" 135 fi 136} 137 138ovs_del_if () { 139 info "Deleting IF from DP: br:$2 if:$3" 140 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-if "$2" "$3" || return 1 141} 142 143ovs_netns_spawn_daemon() { 144 sbx=$1 145 shift 146 netns=$1 147 shift 148 if [ "$netns" == "_default" ]; then 149 $* >> $ovs_dir/stdout 2>> $ovs_dir/stderr & 150 else 151 ip netns exec $netns $* >> $ovs_dir/stdout 2>> $ovs_dir/stderr & 152 fi 153 pid=$! 154 ovs_sbx "$sbx" on_exit "kill -TERM $pid 2>/dev/null" 155} 156 157ovs_spawn_daemon() { 158 sbx=$1 159 shift 160 ovs_netns_spawn_daemon $sbx "_default" $* 161} 162 163ovs_add_netns_and_veths () { 164 info "Adding netns attached: sbx:$1 dp:$2 {$3, $4, $5}" 165 ovs_sbx "$1" ip netns add "$3" || return 1 166 on_exit "ovs_sbx $1 ip netns del $3" 167 ovs_sbx "$1" ip link add "$4" type veth peer name "$5" || return 1 168 on_exit "ovs_sbx $1 ip link del $4 >/dev/null 2>&1" 169 ovs_sbx "$1" ip link set "$4" up || return 1 170 ovs_sbx "$1" ip link set "$5" netns "$3" || return 1 171 ovs_sbx "$1" ip netns exec "$3" ip link set "$5" up || return 1 172 173 if [ "$6" != "" ]; then 174 ovs_sbx "$1" ip netns exec "$3" ip addr add "$6" dev "$5" \ 175 || return 1 176 fi 177 178 if [ "$7" != "-u" ]; then 179 ovs_add_if "$1" "netdev" "$2" "$4" || return 1 180 else 181 ovs_add_if "$1" "netdev" "$2" "$4" -u || return 1 182 fi 183 184 if [ $TRACING -eq 1 ]; then 185 ovs_netns_spawn_daemon "$1" "$3" tcpdump -l -i any -s 6553 186 ovs_wait grep -q "listening on any" ${ovs_dir}/stderr 187 fi 188 189 return 0 190} 191 192ovs_add_flow () { 193 info "Adding flow to DP: sbx:$1 br:$2 flow:$3 act:$4" 194 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-flow "$2" "$3" "$4" 195 if [ $? -ne 0 ]; then 196 info "Flow [ $3 : $4 ] failed" 197 return 1 198 fi 199 return 0 200} 201 202ovs_mod_flow () { 203 if [ -n "$4" ]; then 204 info "Modifying flow: sbx:$1 br:$2 flow:$3 act:$4" 205 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py \ 206 mod-flow "$2" "$3" "$4" 207 else 208 info "Modifying flow (no actions): sbx:$1 br:$2 flow:$3" 209 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py \ 210 mod-flow "$2" "$3" 211 fi 212 if [ $? -ne 0 ]; then 213 info "Flow modify [ $3 ] failed" 214 return 1 215 fi 216 return 0 217} 218 219ovs_del_flows () { 220 info "Deleting all flows from DP: sbx:$1 br:$2" 221 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-flows "$2" 222 return 0 223} 224 225ovs_drop_record_and_run () { 226 local sbx=$1 227 shift 228 229 perf record -a -q -e skb:kfree_skb -o ${ovs_dir}/perf.data $* \ 230 >> ${ovs_dir}/stdout 2>> ${ovs_dir}/stderr 231 return $? 232} 233 234ovs_drop_reason_count() 235{ 236 local reason=$1 237 238 local perf_output=`perf script -i ${ovs_dir}/perf.data -F trace:event,trace` 239 local pattern="skb:kfree_skb:.*reason: $reason" 240 241 return `echo "$perf_output" | grep "$pattern" | wc -l` 242} 243 244ovs_test_flow_fails () { 245 ERR_MSG="Flow actions may not be safe on all matching packets" 246 247 PRE_TEST=$(dmesg | grep -c "${ERR_MSG}") 248 ovs_add_flow $@ &> /dev/null $@ && return 1 249 POST_TEST=$(dmesg | grep -c "${ERR_MSG}") 250 251 if [ "$PRE_TEST" == "$POST_TEST" ]; then 252 return 1 253 fi 254 return 0 255} 256 257usage() { 258 echo 259 echo "$0 [OPTIONS] [TEST]..." 260 echo "If no TEST argument is given, all tests will be run." 261 echo 262 echo "Options" 263 echo " -t: capture traffic via tcpdump" 264 echo " -v: verbose" 265 echo " -p: pause on failure" 266 echo 267 echo "Available tests${tests}" 268 exit 1 269} 270 271 272test_dec_ttl() { 273 sbx_add "test_dec_ttl" || return $? 274 ovs_add_dp "test_dec_ttl" decttl || return 1 275 276 info "create namespaces" 277 for ns in client server; do 278 ovs_add_netns_and_veths "test_dec_ttl" "decttl" "$ns" \ 279 "${ns:0:1}0" "${ns:0:1}1" || return 1 280 done 281 282 ip netns exec client ip addr add 10.0.0.1/24 dev c1 283 ip netns exec client ip link set c1 up 284 ip netns exec server ip addr add 10.0.0.2/24 dev s1 285 ip netns exec server ip link set s1 up 286 287 # Probe: check if kernel supports dec_ttl action. 288 ovs_add_flow "test_dec_ttl" decttl \ 289 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 290 'dec_ttl(le_1())' &>/dev/null 291 if [ $? -ne 0 ]; then 292 info "no support for dec_ttl - skipping" 293 ovs_exit_sig 294 return $ksft_skip 295 fi 296 297 ovs_del_flows "test_dec_ttl" decttl 298 299 # ARP flows (bidirectional) 300 ovs_add_flow "test_dec_ttl" decttl \ 301 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 302 ovs_add_flow "test_dec_ttl" decttl \ 303 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 304 305 # IP flows with dec_ttl action 306 ovs_add_flow "test_dec_ttl" decttl \ 307 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 308 'dec_ttl(le_1()),2' || return 1 309 ovs_add_flow "test_dec_ttl" decttl \ 310 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ 311 'dec_ttl(le_1()),1' || return 1 312 313 info "verify connectivity with dec_ttl" 314 ovs_sbx "test_dec_ttl" ip netns exec client ping -c 1 -W 2 \ 315 10.0.0.2 || return 1 316 317 info "verify TTL=1 is dropped by dec_ttl" 318 ovs_sbx "test_dec_ttl" ip netns exec client ping -c 1 -W 2 \ 319 -t 1 10.0.0.2 >/dev/null 2>&1 \ 320 && { info "FAIL: ping should fail with TTL=1 and dec_ttl" 321 return 1; } 322 323 return 0 324} 325 326test_flow_set() { 327 sbx_add "test_flow_set" || return $? 328 ovs_add_dp "test_flow_set" flowset || return 1 329 330 info "create namespaces" 331 for ns in client server; do 332 ovs_add_netns_and_veths "test_flow_set" "flowset" "$ns" \ 333 "${ns:0:1}0" "${ns:0:1}1" || return 1 334 done 335 336 ip netns exec client ip addr add 10.0.0.1/24 dev c1 337 ip netns exec client ip link set c1 up 338 ip netns exec server ip addr add 10.0.0.2/24 dev s1 339 ip netns exec server ip link set s1 up 340 341 ovs_add_flow "test_flow_set" flowset \ 342 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 343 ovs_add_flow "test_flow_set" flowset \ 344 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 345 346 local fwd_flow="ufid:00000001-0002-0003-0004-000500060007" 347 fwd_flow="$fwd_flow,in_port(1),eth(),eth_type(0x0800),ipv4()" 348 349 ovs_add_flow "test_flow_set" flowset "$fwd_flow" '2' \ 350 || return 1 351 ovs_add_flow "test_flow_set" flowset \ 352 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 353 354 info "verify initial forwarding" 355 ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \ 356 10.0.0.2 || return 1 357 358 info "mod-flow with new actions (change to drop)" 359 ovs_mod_flow "test_flow_set" flowset "$fwd_flow" 'drop' \ 360 || return 1 361 362 info "verify traffic is now dropped" 363 ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \ 364 10.0.0.2 >/dev/null 2>&1 \ 365 && { info "FAIL: ping should fail after mod-flow to drop" 366 return 1; } 367 368 info "mod-flow without actions" 369 ovs_mod_flow "test_flow_set" flowset "$fwd_flow" || return 1 370 371 info "verify flow retained drop action via dump" 372 python3 "$ovs_base/ovs-dpctl.py" dump-flows flowset \ 373 | grep -q "actions:drop" || \ 374 { info "FAIL: flow not showing drop action"; return 1; } 375 376 info "verify drop actions unchanged" 377 ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \ 378 10.0.0.2 >/dev/null 2>&1 \ 379 && { info "FAIL: ping should still fail after no-actions set" 380 return 1; } 381 382 return 0 383} 384 385test_action_set() { 386 sbx_add "test_action_set" || return $? 387 ovs_add_dp "test_action_set" settest || return 1 388 389 info "create namespaces" 390 for ns in client server; do 391 ovs_add_netns_and_veths "test_action_set" "settest" "$ns" \ 392 "${ns:0:1}0" "${ns:0:1}1" || return 1 393 done 394 395 ip netns exec client ip addr add 10.0.0.1/24 dev c1 396 ip netns exec client ip link set c1 up 397 ip netns exec server ip addr add 10.0.0.2/24 dev s1 398 ip netns exec server ip link set s1 up 399 400 ovs_add_flow "test_action_set" settest \ 401 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 402 ovs_add_flow "test_action_set" settest \ 403 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 404 405 ovs_add_flow "test_action_set" settest \ 406 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1 407 ovs_add_flow "test_action_set" settest \ 408 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 409 410 info "verify connectivity without SET" 411 ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \ 412 10.0.0.2 || return 1 413 414 ovs_del_flows "test_action_set" settest 415 ovs_add_flow "test_action_set" settest \ 416 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 417 ovs_add_flow "test_action_set" settest \ 418 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 419 420 info "set ipv4 dst to unreachable address" 421 ovs_add_flow "test_action_set" settest \ 422 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 423 'set(ipv4(dst=10.0.0.99)),2' || return 1 424 ovs_add_flow "test_action_set" settest \ 425 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 426 427 info "verify ping fails with rewritten dst" 428 ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \ 429 10.0.0.2 >/dev/null 2>&1 \ 430 && { info "FAIL: ping should fail with dst rewritten" 431 return 1; } 432 433 ovs_del_flows "test_action_set" settest 434 ovs_add_flow "test_action_set" settest \ 435 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 436 ovs_add_flow "test_action_set" settest \ 437 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 438 ovs_add_flow "test_action_set" settest \ 439 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1 440 ovs_add_flow "test_action_set" settest \ 441 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 442 443 info "verify connectivity restored without SET" 444 ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \ 445 10.0.0.2 || return 1 446 447 return 0 448} 449 450# trunc test 451# - trunc(14): truncate to ETH_HLEN, strips IP payload, ping fails 452# - trunc(1) and trunc(13): kernel rejects below ETH_HLEN (EINVAL) 453# - restore normal forwarding and verify recovery 454test_trunc() { 455 sbx_add "test_trunc" || return $? 456 ovs_add_dp "test_trunc" trunctest || return 1 457 458 info "create namespaces" 459 for ns in client server; do 460 ovs_add_netns_and_veths "test_trunc" "trunctest" \ 461 "$ns" "${ns:0:1}0" "${ns:0:1}1" || return 1 462 done 463 464 ip netns exec client ip addr add 10.0.0.1/24 dev c1 465 ip netns exec client ip link set c1 up 466 ip netns exec server ip addr add 10.0.0.2/24 dev s1 467 ip netns exec server ip link set s1 up 468 469 ovs_add_flow "test_trunc" trunctest \ 470 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 471 ovs_add_flow "test_trunc" trunctest \ 472 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 473 ovs_add_flow "test_trunc" trunctest \ 474 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 475 '2' || return 1 476 ovs_add_flow "test_trunc" trunctest \ 477 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ 478 '1' || return 1 479 480 info "verify connectivity without truncation" 481 ovs_sbx "test_trunc" ip netns exec client \ 482 ping -c 1 -W 2 10.0.0.2 || return 1 483 484 # trunc below ETH_HLEN must be rejected by the kernel 485 info "verify trunc(1) is rejected" 486 ovs_add_flow "test_trunc" trunctest \ 487 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 488 'trunc(1),2' &> /dev/null \ 489 && { info "trunc(1) should be rejected"; return 1; } 490 491 info "verify trunc(13) is rejected" 492 ovs_add_flow "test_trunc" trunctest \ 493 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 494 'trunc(13),2' &> /dev/null \ 495 && { info "trunc(13) should be rejected"; return 1; } 496 497 ovs_del_flows "test_trunc" trunctest 498 ovs_add_flow "test_trunc" trunctest \ 499 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 500 ovs_add_flow "test_trunc" trunctest \ 501 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 502 503 info "add trunc(14) forwarding flow" 504 ovs_add_flow "test_trunc" trunctest \ 505 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 506 'trunc(14),2' || return 1 507 ovs_add_flow "test_trunc" trunctest \ 508 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ 509 '1' || return 1 510 511 info "verify ping fails with trunc(14)" 512 ovs_sbx "test_trunc" ip netns exec client \ 513 ping -c 1 -W 2 10.0.0.2 >/dev/null 2>&1 \ 514 && { info "ping should fail with trunc(14)" 515 return 1; } 516 517 ovs_del_flows "test_trunc" trunctest 518 ovs_add_flow "test_trunc" trunctest \ 519 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 520 ovs_add_flow "test_trunc" trunctest \ 521 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 522 ovs_add_flow "test_trunc" trunctest \ 523 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 524 '2' || return 1 525 ovs_add_flow "test_trunc" trunctest \ 526 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ 527 '1' || return 1 528 529 info "verify connectivity restored" 530 ovs_sbx "test_trunc" ip netns exec client \ 531 ping -c 1 -W 2 10.0.0.2 || return 1 532 533 return 0 534} 535 536# icmpv6 test 537# - static neighbours to bypass NDP (nud permanent) 538# - icmpv6(type=128) echo request, icmpv6(type=129) echo reply 539# - remove flows and verify ping fails, reinstall and recover 540test_icmpv6() { 541 local t="test_icmpv6" 542 local v6="eth_type(0x86dd),ipv6(proto=58)" 543 544 sbx_add "$t" || return $? 545 ovs_add_dp "$t" icmpv6 || return 1 546 547 info "create namespaces" 548 for ns in client server; do 549 ovs_add_netns_and_veths "$t" "icmpv6" \ 550 "$ns" "${ns:0:1}0" "${ns:0:1}1" || return 1 551 done 552 553 ip netns exec client ip addr add fd00::1/64 dev c1 nodad 554 ip netns exec client ip link set c1 up 555 ip netns exec server ip addr add fd00::2/64 dev s1 nodad 556 ip netns exec server ip link set s1 up 557 558 local cl_mac sl_mac 559 cl_mac=$(ip netns exec client ip link show c1 \ 560 | awk '/link\/ether/ {print $2}') 561 [ -z "$cl_mac" ] && \ 562 { info "failed to get c1 hwaddr"; return 1; } 563 sl_mac=$(ip netns exec server ip link show s1 \ 564 | awk '/link\/ether/ {print $2}') 565 [ -z "$sl_mac" ] && \ 566 { info "failed to get s1 hwaddr"; return 1; } 567 ip netns exec client ip -6 neigh add fd00::2 \ 568 lladdr "$sl_mac" nud permanent dev c1 || return 1 569 ip netns exec server ip -6 neigh add fd00::1 \ 570 lladdr "$cl_mac" nud permanent dev s1 || return 1 571 572 # Probe: check if kernel supports icmpv6 flow key. 573 ovs_add_flow "$t" icmpv6 \ 574 "in_port(1),eth(),$v6,icmpv6(type=128)" \ 575 '2' &>/dev/null 576 if [ $? -ne 0 ]; then 577 info "no support for icmpv6 key - skipping" 578 ovs_exit_sig 579 return $ksft_skip 580 fi 581 ovs_del_flows "$t" icmpv6 582 583 ovs_add_flow "$t" icmpv6 \ 584 "in_port(1),eth(),$v6,icmpv6(type=128)" \ 585 '2' || return 1 586 ovs_add_flow "$t" icmpv6 \ 587 "in_port(2),eth(),$v6,icmpv6(type=129)" \ 588 '1' || return 1 589 590 info "verify ICMPv6 echo with type-specific flows" 591 ovs_sbx "$t" ip netns exec client \ 592 ping -6 -c 1 -W 2 fd00::2 || return 1 593 594 ovs_del_flows "$t" icmpv6 595 596 info "verify ping fails without echo flows" 597 ovs_sbx "$t" ip netns exec client \ 598 ping -6 -c 1 -W 2 fd00::2 >/dev/null 2>&1 \ 599 && { info "ping should fail without flows" 600 return 1; } 601 602 ovs_add_flow "$t" icmpv6 \ 603 "in_port(1),eth(),$v6,icmpv6(type=128)" \ 604 '2' || return 1 605 ovs_add_flow "$t" icmpv6 \ 606 "in_port(2),eth(),$v6,icmpv6(type=129)" \ 607 '1' || return 1 608 609 info "verify connectivity restored" 610 ovs_sbx "$t" ip netns exec client \ 611 ping -6 -c 1 -W 2 fd00::2 || return 1 612 613 return 0 614} 615 616# Check for an SCTP endpoint via /proc, which works without sctp_diag. 617sctp_eps_has() { 618 ip netns exec "$1" awk -v p="$2" '$6==p' /proc/net/sctp/eps | grep -q . 619} 620 621# sctp_connect_v4 test 622# - sctp(dst=4443) matches client-to-server INIT 623# - sctp(src=4443) matches server-to-client INIT-ACK 624# - remove flows and verify connection fails, reinstall and recover 625test_sctp_connect_v4() { 626 local t="test_sctp_connect_v4" 627 local srv_ip=172.31.110.20 628 629 modprobe -q sctp 2>/dev/null || return "$ksft_skip" 630 socat -V 2>&1 | grep -q "define WITH_SCTP" || return "$ksft_skip" 631 632 sbx_add "$t" || return $? 633 ovs_add_dp "$t" sctp4 || return 1 634 635 info "create namespaces" 636 for ns in client server; do 637 ovs_add_netns_and_veths "$t" "sctp4" "$ns" \ 638 "${ns:0:1}0" "${ns:0:1}1" || return 1 639 done 640 641 ip netns exec client ip addr add 172.31.110.10/24 dev c1 642 ip netns exec client ip link set c1 up 643 ip netns exec server ip addr add "${srv_ip}/24" dev s1 644 ip netns exec server ip link set s1 up 645 646 # ARP forwarding 647 ovs_add_flow "$t" sctp4 \ 648 'in_port(1),eth(),eth_type(0x0806),arp()' \ 649 '2' || return 1 650 ovs_add_flow "$t" sctp4 \ 651 'in_port(2),eth(),eth_type(0x0806),arp()' \ 652 '1' || return 1 653 654 # SCTP port matching: dst for request, src for reply 655 ovs_add_flow "$t" sctp4 \ 656 'in_port(1),eth(),eth_type(0x0800),ipv4(proto=132),sctp(dst=4443)' \ 657 '2' || return 1 658 ovs_add_flow "$t" sctp4 \ 659 'in_port(2),eth(),eth_type(0x0800),ipv4(proto=132),sctp(src=4443)' \ 660 '1' || return 1 661 662 # The listener forks a child per association, so one instance serves 663 # the whole test and the flows stay the only variable. -t 1 bounds 664 # how long a child lingers after its association closes. 665 ovs_netns_spawn_daemon "$t" "server" \ 666 socat -u -t 1 SCTP4-LISTEN:4443,fork STDOUT 667 ovs_wait sctp_eps_has server 4443 || return 1 668 669 info "verify SCTP association with port-keyed flows" 670 ovs_sbx "$t" ip netns exec client \ 671 timeout 3 socat -u STDIN "SCTP4-CONNECT:${srv_ip}:4443" </dev/null \ 672 || return 1 673 674 ovs_del_flows "$t" sctp4 675 676 info "verify connection fails without flows" 677 ovs_add_flow "$t" sctp4 \ 678 'in_port(1),eth(),eth_type(0x0806),arp()' \ 679 '2' || return 1 680 ovs_add_flow "$t" sctp4 \ 681 'in_port(2),eth(),eth_type(0x0806),arp()' \ 682 '1' || return 1 683 684 ovs_sbx "$t" ip netns exec client \ 685 timeout 3 socat -u STDIN "SCTP4-CONNECT:${srv_ip}:4443" </dev/null \ 686 >/dev/null 2>&1 \ 687 && { info "connection should fail without flows" 688 return 1; } 689 690 info "reinstall flows and verify recovery" 691 ovs_add_flow "$t" sctp4 \ 692 'in_port(1),eth(),eth_type(0x0800),ipv4(proto=132),sctp(dst=4443)' \ 693 '2' || return 1 694 ovs_add_flow "$t" sctp4 \ 695 'in_port(2),eth(),eth_type(0x0800),ipv4(proto=132),sctp(src=4443)' \ 696 '1' || return 1 697 698 ovs_sbx "$t" ip netns exec client \ 699 timeout 3 socat -u STDIN "SCTP4-CONNECT:${srv_ip}:4443" </dev/null \ 700 || return 1 701 702 return 0 703} 704 705# sctp_connect_v6 test 706# - sctp(dst=4443) matches client-to-server INIT 707# - sctp(src=4443) matches server-to-client INIT-ACK 708# - icmpv6 NS/NA flows forward neighbour discovery 709# - remove flows and verify connection fails, reinstall and recover 710test_sctp_connect_v6() { 711 local t="test_sctp_connect_v6" 712 local v6="eth_type(0x86dd),ipv6(proto=132)" 713 local payload="SCTP6_DATA_OK" 714 local rxfile="${ovs_base}/${t}/sctp-rx.txt" 715 716 modprobe -q sctp 2>/dev/null || return "$ksft_skip" 717 socat -V 2>&1 | grep -q "define WITH_SCTP" || return "$ksft_skip" 718 socat -V 2>&1 | grep -q "define WITH_IP6" || return "$ksft_skip" 719 [ -e /proc/sys/net/ipv6 ] || return "$ksft_skip" 720 721 sbx_add "$t" || return $? 722 ovs_add_dp "$t" sctp6 || return 1 723 724 info "create namespaces" 725 for ns in client server; do 726 ovs_add_netns_and_veths "$t" "sctp6" "$ns" \ 727 "${ns:0:1}0" "${ns:0:1}1" || return 1 728 done 729 730 ip netns exec client ip addr add fd00::1/64 dev c1 nodad 731 ip netns exec client ip link set c1 up 732 ip netns exec server ip addr add fd00::2/64 dev s1 nodad 733 ip netns exec server ip link set s1 up 734 735 # NS/NA forwarding 736 ovs_add_flow "$t" sctp6 \ 737 'in_port(1),eth(),eth_type(0x86dd),ipv6(proto=58),icmpv6()' \ 738 '2' || return 1 739 ovs_add_flow "$t" sctp6 \ 740 'in_port(2),eth(),eth_type(0x86dd),ipv6(proto=58),icmpv6()' \ 741 '1' || return 1 742 743 # SCTP port matching: dst for request, src for reply 744 ovs_add_flow "$t" sctp6 \ 745 "in_port(1),eth(),$v6,sctp(dst=4443)" \ 746 '2' || return 1 747 ovs_add_flow "$t" sctp6 \ 748 "in_port(2),eth(),$v6,sctp(src=4443)" \ 749 '1' || return 1 750 751 # A keyless ipv6(proto=132) install must be refused (EINVAL): 752 # match_validate() requires the sctp() key. Pin the reject side 753 # of that rule; the keyed installs above cover the accept side. 754 # Verify the refusal is EINVAL (missing key), not a parse error. 755 err=$(ovs_sbx "$t" python3 $ovs_base/ovs-dpctl.py add-flow sctp6 \ 756 "in_port(1),eth(),$v6" '2' 2>&1 >/dev/null) \ 757 && { info "keyless SCTP flow should be refused" 758 return 1; } 759 echo "$err" | grep -q "(22," || { 760 info "keyless SCTP flow refused for wrong reason: $err" 761 return 1 762 } 763 764 ovs_netns_spawn_daemon "$t" "server" \ 765 socat -u -t 1 SCTP6-LISTEN:4443,fork \ 766 OPEN:"$rxfile",creat,append 767 ovs_wait sctp_eps_has server 4443 || return 1 768 769 info "verify SCTP association with port-keyed flows" 770 ovs_sbx "$t" ip netns exec client \ 771 timeout 3 socat -u STDIN "SCTP6-CONNECT:[fd00::2]:4443" </dev/null \ 772 || return 1 773 774 info "verify SCTP DATA chunk crosses the datapath" 775 ovs_sbx "$t" ip netns exec client \ 776 timeout 3 socat -u STDIN "SCTP6-CONNECT:[fd00::2]:4443" \ 777 <<< "$payload" || return 1 778 ovs_wait grep -q "$payload" "$rxfile" \ 779 || { info "server did not receive SCTP DATA payload" 780 return 1; } 781 782 ovs_del_flows "$t" sctp6 783 784 info "verify connection fails without flows" 785 ovs_add_flow "$t" sctp6 \ 786 'in_port(1),eth(),eth_type(0x86dd),ipv6(proto=58),icmpv6()' \ 787 '2' || return 1 788 ovs_add_flow "$t" sctp6 \ 789 'in_port(2),eth(),eth_type(0x86dd),ipv6(proto=58),icmpv6()' \ 790 '1' || return 1 791 792 ovs_sbx "$t" ip netns exec client \ 793 timeout 3 socat -u STDIN "SCTP6-CONNECT:[fd00::2]:4443" </dev/null \ 794 >/dev/null 2>&1 \ 795 && { info "connection should fail without flows" 796 return 1; } 797 798 info "reinstall flows and verify recovery" 799 ovs_add_flow "$t" sctp6 \ 800 "in_port(1),eth(),$v6,sctp(dst=4443)" \ 801 '2' || return 1 802 ovs_add_flow "$t" sctp6 \ 803 "in_port(2),eth(),$v6,sctp(src=4443)" \ 804 '1' || return 1 805 806 ovs_sbx "$t" ip netns exec client \ 807 timeout 3 socat -u STDIN "SCTP6-CONNECT:[fd00::2]:4443" </dev/null \ 808 || return 1 809 810 return 0 811} 812 813# psample test 814# - use psample to observe packets 815test_psample() { 816 sbx_add "test_psample" || return $? 817 818 # Add a datapath with per-vport dispatching. 819 ovs_add_dp "test_psample" psample -V 2:1 || return 1 820 821 info "create namespaces" 822 ovs_add_netns_and_veths "test_psample" "psample" \ 823 client c0 c1 172.31.110.10/24 -u || return 1 824 ovs_add_netns_and_veths "test_psample" "psample" \ 825 server s0 s1 172.31.110.20/24 -u || return 1 826 827 # Check if psample actions can be configured. 828 ovs_add_flow "test_psample" psample \ 829 'in_port(1),eth(),eth_type(0x0806),arp()' 'psample(group=1)' &> /dev/null 830 if [ $? == 1 ]; then 831 info "no support for psample - skipping" 832 ovs_exit_sig 833 return $ksft_skip 834 fi 835 836 ovs_del_flows "test_psample" psample 837 838 # Test action verification. 839 OLDIFS=$IFS 840 IFS='*' 841 min_key='in_port(1),eth(),eth_type(0x0800),ipv4()' 842 for testcase in \ 843 "cookie to large"*"psample(group=1,cookie=1615141312111009080706050403020100)" \ 844 "no group with cookie"*"psample(cookie=abcd)" \ 845 "no group"*"psample()"; 846 do 847 set -- $testcase; 848 ovs_test_flow_fails "test_psample" psample $min_key $2 849 if [ $? == 1 ]; then 850 info "failed - $1" 851 return 1 852 fi 853 done 854 IFS=$OLDIFS 855 856 ovs_del_flows "test_psample" psample 857 # Allow ARP 858 ovs_add_flow "test_psample" psample \ 859 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 860 ovs_add_flow "test_psample" psample \ 861 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 862 863 # Sample first 14 bytes of all traffic. 864 ovs_add_flow "test_psample" psample \ 865 "in_port(1),eth(),eth_type(0x0800),ipv4()" \ 866 "trunc(14),psample(group=1,cookie=c0ffee),2" 867 868 # Sample all traffic. In this case, use a sample() action with both 869 # psample and an upcall emulating simultaneous local sampling and 870 # sFlow / IPFIX. 871 nlpid=$(grep -E "listening on upcall packet handler" \ 872 $ovs_dir/s0.out | cut -d ":" -f 2 | tr -d ' ') 873 [ -z "$nlpid" ] && \ 874 { info "failed to get upcall PID"; return 1; } 875 876 ovs_add_flow "test_psample" psample \ 877 "in_port(2),eth(),eth_type(0x0800),ipv4()" \ 878 "sample(sample=100%,actions(psample(group=2,cookie=eeff0c),userspace(pid=${nlpid},userdata=eeff0c))),1" 879 880 # Record psample data. 881 ovs_spawn_daemon "test_psample" python3 $ovs_base/ovs-dpctl.py psample-events 882 ovs_wait grep -q "listening for psample events" ${ovs_dir}/stdout 883 884 # Send a single ping. 885 ovs_sbx "test_psample" ip netns exec client ping -I c1 172.31.110.20 -c 1 || return 1 886 887 # We should have received one userspace action upcall and 2 psample packets. 888 ovs_wait grep -q "userspace action command" $ovs_dir/s0.out || return 1 889 890 # client -> server samples should only contain the first 14 bytes of the packet. 891 ovs_wait grep -qE "rate:4294967295,group:1,cookie:c0ffee data:[0-9a-f]{28}$" \ 892 $ovs_dir/stdout || return 1 893 894 ovs_wait grep -q "rate:4294967295,group:2,cookie:eeff0c" $ovs_dir/stdout || return 1 895 896 return 0 897} 898 899# drop_reason test 900# - drop packets and verify the right drop reason is reported 901test_drop_reason() { 902 which perf >/dev/null 2>&1 || return $ksft_skip 903 which pahole >/dev/null 2>&1 || return $ksft_skip 904 905 ovs_drop_subsys=$(pahole -C skb_drop_reason_subsys | 906 awk '/OPENVSWITCH/ { print $3; }' | 907 tr -d ,) 908 if [ -z "$ovs_drop_subsys" ]; then 909 info "failed to get OVS drop subsys ID" 910 return $ksft_skip 911 fi 912 913 sbx_add "test_drop_reason" || return $? 914 915 ovs_add_dp "test_drop_reason" dropreason || return 1 916 917 info "create namespaces" 918 for ns in client server; do 919 ovs_add_netns_and_veths "test_drop_reason" "dropreason" "$ns" \ 920 "${ns:0:1}0" "${ns:0:1}1" || return 1 921 done 922 923 # Setup client namespace 924 ip netns exec client ip addr add 172.31.110.10/24 dev c1 925 ip netns exec client ip link set c1 up 926 927 # Setup server namespace 928 ip netns exec server ip addr add 172.31.110.20/24 dev s1 929 ip netns exec server ip link set s1 up 930 931 # Check if drop reasons can be sent 932 ovs_add_flow "test_drop_reason" dropreason \ 933 'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(10)' 2>/dev/null 934 if [ $? == 1 ]; then 935 info "no support for drop reasons - skipping" 936 ovs_exit_sig 937 return $ksft_skip 938 fi 939 940 ovs_del_flows "test_drop_reason" dropreason 941 942 # Allow ARP 943 ovs_add_flow "test_drop_reason" dropreason \ 944 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 945 ovs_add_flow "test_drop_reason" dropreason \ 946 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 947 948 # Allow client ICMP traffic but drop return path 949 ovs_add_flow "test_drop_reason" dropreason \ 950 "in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=1),icmp()" '2' 951 ovs_add_flow "test_drop_reason" dropreason \ 952 "in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20,proto=1),icmp()" 'drop' 953 954 ovs_drop_record_and_run "test_drop_reason" ip netns exec client ping -c 2 172.31.110.20 955 ovs_drop_reason_count 0x${ovs_drop_subsys}0001 # OVS_DROP_FLOW_ACTION 956 if [[ "$?" -ne "2" ]]; then 957 info "Did not detect expected drops: $?" 958 return 1 959 fi 960 961 # Drop UDP 6000 traffic with an explicit action and an error code. 962 ovs_add_flow "test_drop_reason" dropreason \ 963 "in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=6000)" \ 964 'drop(42)' 965 # Drop UDP 7000 traffic with an explicit action with no error code. 966 ovs_add_flow "test_drop_reason" dropreason \ 967 "in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=7000)" \ 968 'drop(0)' 969 970 ovs_drop_record_and_run \ 971 "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 6000 972 ovs_drop_reason_count 0x${ovs_drop_subsys}0004 # OVS_DROP_EXPLICIT_ACTION_ERROR 973 if [[ "$?" -ne "1" ]]; then 974 info "Did not detect expected explicit error drops: $?" 975 return 1 976 fi 977 978 ovs_drop_record_and_run \ 979 "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 7000 980 ovs_drop_reason_count 0x${ovs_drop_subsys}0003 # OVS_DROP_EXPLICIT_ACTION 981 if [[ "$?" -ne "1" ]]; then 982 info "Did not detect expected explicit drops: $?" 983 return 1 984 fi 985 986 return 0 987} 988 989# arp_ping test 990# - client has 1500 byte MTU 991# - server has 1500 byte MTU 992# - send ARP ping between two ns 993test_arp_ping () { 994 995 which arping >/dev/null 2>&1 || return $ksft_skip 996 997 sbx_add "test_arp_ping" || return $? 998 999 ovs_add_dp "test_arp_ping" arpping || return 1 1000 1001 info "create namespaces" 1002 for ns in client server; do 1003 ovs_add_netns_and_veths "test_arp_ping" "arpping" "$ns" \ 1004 "${ns:0:1}0" "${ns:0:1}1" || return 1 1005 done 1006 1007 # Setup client namespace 1008 ip netns exec client ip addr add 172.31.110.10/24 dev c1 1009 ip netns exec client ip link set c1 up 1010 HW_CLIENT=$(ip netns exec client ip link show dev c1 \ 1011 | awk '/link\/ether/ {print $2}') 1012 [ -z "$HW_CLIENT" ] && \ 1013 { info "failed to get client hwaddr"; return 1; } 1014 info "Client hwaddr: $HW_CLIENT" 1015 1016 # Setup server namespace 1017 ip netns exec server ip addr add 172.31.110.20/24 dev s1 1018 ip netns exec server ip link set s1 up 1019 HW_SERVER=$(ip netns exec server ip link show dev s1 \ 1020 | awk '/link\/ether/ {print $2}') 1021 [ -z "$HW_SERVER" ] && \ 1022 { info "failed to get server hwaddr"; return 1; } 1023 info "Server hwaddr: $HW_SERVER" 1024 1025 ovs_add_flow "test_arp_ping" arpping \ 1026 "in_port(1),eth(),eth_type(0x0806),arp(sip=172.31.110.10,tip=172.31.110.20,sha=$HW_CLIENT,tha=ff:ff:ff:ff:ff:ff)" '2' || return 1 1027 ovs_add_flow "test_arp_ping" arpping \ 1028 "in_port(2),eth(),eth_type(0x0806),arp()" '1' || return 1 1029 1030 ovs_sbx "test_arp_ping" ip netns exec client arping -I c1 172.31.110.20 -c 1 || return 1 1031 1032 return 0 1033} 1034 1035# ct_connect_v4 test 1036# - client has 1500 byte MTU 1037# - server has 1500 byte MTU 1038# - use ICMP to ping in each direction 1039# - only allow CT state stuff to pass through new in c -> s 1040test_ct_connect_v4 () { 1041 1042 which nc >/dev/null 2>/dev/null || return $ksft_skip 1043 1044 sbx_add "test_ct_connect_v4" || return $? 1045 1046 ovs_add_dp "test_ct_connect_v4" ct4 || return 1 1047 info "create namespaces" 1048 for ns in client server; do 1049 ovs_add_netns_and_veths "test_ct_connect_v4" "ct4" "$ns" \ 1050 "${ns:0:1}0" "${ns:0:1}1" || return 1 1051 done 1052 1053 ip netns exec client ip addr add 172.31.110.10/24 dev c1 1054 ip netns exec client ip link set c1 up 1055 ip netns exec server ip addr add 172.31.110.20/24 dev s1 1056 ip netns exec server ip link set s1 up 1057 1058 # Add forwarding for ARP and ip packets - completely wildcarded 1059 ovs_add_flow "test_ct_connect_v4" ct4 \ 1060 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 1061 ovs_add_flow "test_ct_connect_v4" ct4 \ 1062 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 1063 ovs_add_flow "test_ct_connect_v4" ct4 \ 1064 'ct_state(-trk),eth(),eth_type(0x0800),ipv4()' \ 1065 'ct(commit),recirc(0x1)' || return 1 1066 ovs_add_flow "test_ct_connect_v4" ct4 \ 1067 'recirc_id(0x1),ct_state(+trk+new),in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' \ 1068 '2' || return 1 1069 ovs_add_flow "test_ct_connect_v4" ct4 \ 1070 'recirc_id(0x1),ct_state(+trk+est),in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' \ 1071 '2' || return 1 1072 ovs_add_flow "test_ct_connect_v4" ct4 \ 1073 'recirc_id(0x1),ct_state(+trk+est),in_port(2),eth(),eth_type(0x0800),ipv4(dst=172.31.110.10)' \ 1074 '1' || return 1 1075 ovs_add_flow "test_ct_connect_v4" ct4 \ 1076 'recirc_id(0x1),ct_state(+trk+inv),eth(),eth_type(0x0800),ipv4()' 'drop' || \ 1077 return 1 1078 1079 # do a ping 1080 ovs_sbx "test_ct_connect_v4" ip netns exec client ping 172.31.110.20 -c 3 || return 1 1081 1082 # create an echo server in 'server' 1083 echo "server" | \ 1084 ovs_netns_spawn_daemon "test_ct_connect_v4" "server" \ 1085 nc -lvnp 4443 1086 ovs_sbx "test_ct_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.20 4443 || return 1 1087 1088 # Now test in the other direction (should fail) 1089 echo "client" | \ 1090 ovs_netns_spawn_daemon "test_ct_connect_v4" "client" \ 1091 nc -lvnp 4443 1092 ovs_sbx "test_ct_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.10 4443 1093 if [ $? == 0 ]; then 1094 info "ct connect to client was successful" 1095 return 1 1096 fi 1097 1098 info "done..." 1099 return 0 1100} 1101 1102# connect_v4 test 1103# - client has 1500 byte MTU 1104# - server has 1500 byte MTU 1105# - use ICMP to ping in each direction 1106test_connect_v4 () { 1107 1108 sbx_add "test_connect_v4" || return $? 1109 1110 ovs_add_dp "test_connect_v4" cv4 || return 1 1111 1112 info "create namespaces" 1113 for ns in client server; do 1114 ovs_add_netns_and_veths "test_connect_v4" "cv4" "$ns" \ 1115 "${ns:0:1}0" "${ns:0:1}1" || return 1 1116 done 1117 1118 1119 ip netns exec client ip addr add 172.31.110.10/24 dev c1 1120 ip netns exec client ip link set c1 up 1121 ip netns exec server ip addr add 172.31.110.20/24 dev s1 1122 ip netns exec server ip link set s1 up 1123 1124 # Add forwarding for ARP and ip packets - completely wildcarded 1125 ovs_add_flow "test_connect_v4" cv4 \ 1126 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 1127 ovs_add_flow "test_connect_v4" cv4 \ 1128 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 1129 ovs_add_flow "test_connect_v4" cv4 \ 1130 'in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' '2' || return 1 1131 ovs_add_flow "test_connect_v4" cv4 \ 1132 'in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20)' '1' || return 1 1133 1134 # do a ping 1135 ovs_sbx "test_connect_v4" ip netns exec client ping 172.31.110.20 -c 3 || return 1 1136 1137 info "done..." 1138 return 0 1139} 1140 1141# nat_connect_v4 test 1142# - client has 1500 byte MTU 1143# - server has 1500 byte MTU 1144# - use ICMP to ping in each direction 1145# - only allow CT state stuff to pass through new in c -> s 1146test_nat_connect_v4 () { 1147 which nc >/dev/null 2>/dev/null || return $ksft_skip 1148 1149 sbx_add "test_nat_connect_v4" || return $? 1150 1151 ovs_add_dp "test_nat_connect_v4" nat4 || return 1 1152 info "create namespaces" 1153 for ns in client server; do 1154 ovs_add_netns_and_veths "test_nat_connect_v4" "nat4" "$ns" \ 1155 "${ns:0:1}0" "${ns:0:1}1" || return 1 1156 done 1157 1158 ip netns exec client ip addr add 172.31.110.10/24 dev c1 1159 ip netns exec client ip link set c1 up 1160 ip netns exec server ip addr add 172.31.110.20/24 dev s1 1161 ip netns exec server ip link set s1 up 1162 1163 ip netns exec client ip route add default via 172.31.110.20 1164 1165 ovs_add_flow "test_nat_connect_v4" nat4 \ 1166 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 1167 ovs_add_flow "test_nat_connect_v4" nat4 \ 1168 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 1169 ovs_add_flow "test_nat_connect_v4" nat4 \ 1170 "ct_state(-trk),in_port(1),eth(),eth_type(0x0800),ipv4(dst=192.168.0.20)" \ 1171 "ct(commit,nat(dst=172.31.110.20)),recirc(0x1)" 1172 ovs_add_flow "test_nat_connect_v4" nat4 \ 1173 "ct_state(-trk),in_port(2),eth(),eth_type(0x0800),ipv4()" \ 1174 "ct(commit,nat),recirc(0x2)" 1175 1176 ovs_add_flow "test_nat_connect_v4" nat4 \ 1177 "recirc_id(0x1),ct_state(+trk-inv),in_port(1),eth(),eth_type(0x0800),ipv4()" "2" 1178 ovs_add_flow "test_nat_connect_v4" nat4 \ 1179 "recirc_id(0x2),ct_state(+trk-inv),in_port(2),eth(),eth_type(0x0800),ipv4()" "1" 1180 1181 # do a ping 1182 ovs_sbx "test_nat_connect_v4" ip netns exec client ping 192.168.0.20 -c 3 || return 1 1183 1184 # create an echo server in 'server' 1185 echo "server" | \ 1186 ovs_netns_spawn_daemon "test_nat_connect_v4" "server" \ 1187 nc -lvnp 4443 1188 ovs_sbx "test_nat_connect_v4" ip netns exec client nc -i 1 -zv 192.168.0.20 4443 || return 1 1189 1190 # Now test in the other direction (should fail) 1191 echo "client" | \ 1192 ovs_netns_spawn_daemon "test_nat_connect_v4" "client" \ 1193 nc -lvnp 4443 1194 ovs_sbx "test_nat_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.10 4443 1195 if [ $? == 0 ]; then 1196 info "connect to client was successful" 1197 return 1 1198 fi 1199 1200 info "done..." 1201 return 0 1202} 1203 1204# sctp_nat_connect_v4 test 1205# - SCTP association crosses a ct(commit,nat(dst=ip:port)) DNAT 1206# - post-recirc flows match the translated address and port, so the 1207# SCTP branch of the post-NAT flow key update is load-bearing 1208test_sctp_nat_connect_v4 () { 1209 local t="test_sctp_nat_connect_v4" 1210 local payload="SCTP_NAT_DATA_OK" 1211 local rxfile="${ovs_base}/${t}/sctp-rx.txt" 1212 1213 modprobe -q sctp 2>/dev/null || return "$ksft_skip" 1214 socat -V 2>&1 | grep -q "define WITH_SCTP" || return "$ksft_skip" 1215 # SCTP conntrack is compiled into nf_conntrack.ko, so check that 1216 # loading it actually exposed the SCTP conntrack sysctls. 1217 modprobe -q nf_conntrack 2>/dev/null || return "$ksft_skip" 1218 [ -e /proc/sys/net/netfilter/nf_conntrack_sctp_timeout_established ] \ 1219 || { info "no SCTP conntrack support - skipping" 1220 return "$ksft_skip"; } 1221 1222 sbx_add "test_sctp_nat_connect_v4" || return $? 1223 1224 ovs_add_dp "test_sctp_nat_connect_v4" sctpnat4 || return 1 1225 info "create namespaces" 1226 for ns in client server; do 1227 ovs_add_netns_and_veths "test_sctp_nat_connect_v4" "sctpnat4" \ 1228 "$ns" "${ns:0:1}0" "${ns:0:1}1" || return 1 1229 done 1230 1231 ip netns exec client ip addr add 172.31.110.10/24 dev c1 1232 ip netns exec client ip link set c1 up 1233 ip netns exec server ip addr add 172.31.110.20/24 dev s1 1234 ip netns exec server ip link set s1 up 1235 1236 ip netns exec client ip route add default via 172.31.110.20 1237 1238 # Check if the ct and nat actions can be configured. 1239 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1240 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ 1241 'ct(commit,nat(dst=172.31.110.20:5555)),recirc(0x1)' \ 1242 &> /dev/null 1243 if [ $? == 1 ]; then 1244 info "no support for ct/nat actions - skipping" 1245 ovs_exit_sig 1246 return $ksft_skip 1247 fi 1248 1249 ovs_del_flows "test_sctp_nat_connect_v4" sctpnat4 1250 1251 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1252 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 1253 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1254 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 1255 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1256 "ct_state(-trk),in_port(1),eth(),eth_type(0x0800),"\ 1257"ipv4(dst=192.168.0.20)" \ 1258 "ct(commit,nat(dst=172.31.110.20:5555)),recirc(0x1)" || return 1 1259 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1260 "ct_state(-trk),in_port(2),eth(),eth_type(0x0800),ipv4()" \ 1261 "ct(commit,nat),recirc(0x2)" || return 1 1262 1263 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1264 "recirc_id(0x1),ct_state(+trk-inv),in_port(1),eth(),"\ 1265"eth_type(0x0800),ipv4(dst=172.31.110.20,proto=132),"\ 1266"sctp(dst=5555)" \ 1267 "2" || return 1 1268 ovs_add_flow "test_sctp_nat_connect_v4" sctpnat4 \ 1269 "recirc_id(0x2),ct_state(+trk-inv),in_port(2),eth(),"\ 1270"eth_type(0x0800),ipv4(src=192.168.0.20,proto=132),"\ 1271"sctp(src=4443)" \ 1272 "1" || return 1 1273 1274 ovs_netns_spawn_daemon "test_sctp_nat_connect_v4" "server" \ 1275 socat -u -t 1 SCTP4-LISTEN:5555,fork \ 1276 OPEN:"$rxfile",creat,append 1277 ovs_wait sctp_eps_has server 5555 || return 1 1278 1279 info "verify SCTP association across NAT" 1280 ovs_sbx "test_sctp_nat_connect_v4" ip netns exec client \ 1281 timeout 3 socat -u STDIN "SCTP4-CONNECT:192.168.0.20:4443" \ 1282 </dev/null || return 1 1283 1284 info "verify SCTP DATA chunk crosses NAT" 1285 ovs_sbx "test_sctp_nat_connect_v4" ip netns exec client \ 1286 timeout 3 socat -u STDIN "SCTP4-CONNECT:192.168.0.20:4443" \ 1287 <<< "$payload" || return 1 1288 ovs_wait grep -q "$payload" "$rxfile" \ 1289 || { info "server did not receive SCTP DATA payload" 1290 return 1; } 1291 1292 info "done..." 1293 return 0 1294} 1295 1296# nat_related_v4 test 1297# - client->server ip packets go via SNAT 1298# - client solicits ICMP destination unreachable packet from server 1299# - undo NAT for ICMP reply and test dst ip has been updated 1300test_nat_related_v4 () { 1301 which nc >/dev/null 2>/dev/null || return $ksft_skip 1302 1303 sbx_add "test_nat_related_v4" || return $? 1304 1305 ovs_add_dp "test_nat_related_v4" natrelated4 || return 1 1306 info "create namespaces" 1307 for ns in client server; do 1308 ovs_add_netns_and_veths "test_nat_related_v4" "natrelated4" "$ns" \ 1309 "${ns:0:1}0" "${ns:0:1}1" || return 1 1310 done 1311 1312 ip netns exec client ip addr add 172.31.110.10/24 dev c1 1313 ip netns exec client ip link set c1 up 1314 ip netns exec server ip addr add 172.31.110.20/24 dev s1 1315 ip netns exec server ip link set s1 up 1316 1317 ip netns exec server ip route add 192.168.0.20/32 via 172.31.110.10 1318 1319 # Allow ARP 1320 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1321 "in_port(1),eth(),eth_type(0x0806),arp()" "2" || return 1 1322 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1323 "in_port(2),eth(),eth_type(0x0806),arp()" "1" || return 1 1324 1325 # Allow IP traffic from client->server, rewrite source IP with SNAT to 192.168.0.20 1326 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1327 "ct_state(-trk),in_port(1),eth(),eth_type(0x0800),ipv4(dst=172.31.110.20)" \ 1328 "ct(commit,nat(src=192.168.0.20)),recirc(0x1)" || return 1 1329 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1330 "recirc_id(0x1),ct_state(+trk-inv),in_port(1),eth(),eth_type(0x0800),ipv4()" \ 1331 "2" || return 1 1332 1333 # Allow related ICMP responses back from server and undo NAT to restore original IP 1334 # Drop any ICMP related packets where dst ip hasn't been restored back to original IP 1335 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1336 "ct_state(-trk),in_port(2),eth(),eth_type(0x0800),ipv4()" \ 1337 "ct(commit,nat),recirc(0x2)" || return 1 1338 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1339 "recirc_id(0x2),ct_state(+rel+trk),in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20,dst=172.31.110.10,proto=1),icmp()" \ 1340 "1" || return 1 1341 ovs_add_flow "test_nat_related_v4" natrelated4 \ 1342 "recirc_id(0x2),ct_state(+rel+trk),in_port(2),eth(),eth_type(0x0800),ipv4(dst=192.168.0.20,proto=1),icmp()" \ 1343 "drop" || return 1 1344 1345 # Solicit destination unreachable response from server 1346 ovs_sbx "test_nat_related_v4" ip netns exec client \ 1347 bash -c "echo a | nc -u -w 1 172.31.110.20 10000" 1348 1349 # Check to make sure no packets matched the drop rule with incorrect dst ip 1350 python3 "$ovs_base/ovs-dpctl.py" dump-flows natrelated4 \ 1351 | grep "drop" | grep "packets:0" >/dev/null || return 1 1352 1353 info "done..." 1354 return 0 1355} 1356 1357# netlink_validation 1358# - Create a dp 1359# - check no warning with "old version" simulation 1360test_netlink_checks () { 1361 sbx_add "test_netlink_checks" || return 1 1362 1363 info "setting up new DP" 1364 ovs_add_dp "test_netlink_checks" nv0 || return 1 1365 # now try again 1366 PRE_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+") 1367 ovs_add_dp "test_netlink_checks" nv0 -V 0 || return 1 1368 POST_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+") 1369 if [ "$PRE_TEST" != "$POST_TEST" ]; then 1370 info "failed - gen warning" 1371 return 1 1372 fi 1373 1374 ovs_add_netns_and_veths "test_netlink_checks" nv0 left left0 l0 || \ 1375 return 1 1376 ovs_add_netns_and_veths "test_netlink_checks" nv0 right right0 r0 || \ 1377 return 1 1378 [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \ 1379 wc -l) == 3 ] || \ 1380 return 1 1381 ovs_del_if "test_netlink_checks" nv0 right0 || return 1 1382 [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \ 1383 wc -l) == 2 ] || \ 1384 return 1 1385 1386 info "Checking clone depth" 1387 ERR_MSG="Flow actions may not be safe on all matching packets" 1388 PRE_TEST=$(dmesg | grep -c "${ERR_MSG}") 1389 ovs_add_flow "test_netlink_checks" nv0 \ 1390 'in_port(1),eth(),eth_type(0x800),ipv4()' \ 1391 'clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(drop)))))))))))))))))' \ 1392 >/dev/null 2>&1 && return 1 1393 POST_TEST=$(dmesg | grep -c "${ERR_MSG}") 1394 1395 if [ "$PRE_TEST" == "$POST_TEST" ]; then 1396 info "failed - clone depth too large" 1397 return 1 1398 fi 1399 1400 PRE_TEST=$(dmesg | grep -c "${ERR_MSG}") 1401 ovs_add_flow "test_netlink_checks" nv0 \ 1402 'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(0),2' \ 1403 &> /dev/null && return 1 1404 POST_TEST=$(dmesg | grep -c "${ERR_MSG}") 1405 if [ "$PRE_TEST" == "$POST_TEST" ]; then 1406 info "failed - error not generated" 1407 return 1 1408 fi 1409 return 0 1410} 1411 1412test_upcall_interfaces() { 1413 sbx_add "test_upcall_interfaces" || return 1 1414 1415 info "setting up new DP" 1416 ovs_add_dp "test_upcall_interfaces" ui0 -V 2:1 || return 1 1417 1418 ovs_add_netns_and_veths "test_upcall_interfaces" ui0 upc left0 l0 \ 1419 172.31.110.1/24 -u || return 1 1420 1421 ovs_wait grep -q "listening on upcall packet handler" ${ovs_dir}/left0.out 1422 1423 info "sending arping" 1424 ip netns exec upc arping -I l0 172.31.110.20 -c 1 \ 1425 >$ovs_dir/arping.stdout 2>$ovs_dir/arping.stderr 1426 1427 grep -E "MISS upcall\[0/yes\]: .*arp\(sip=172.31.110.1,tip=172.31.110.20,op=1,sha=" $ovs_dir/left0.out >/dev/null 2>&1 || return 1 1428 return 0 1429} 1430 1431ovs_add_kernel_tunnel() { 1432 local sbxname=$1; shift 1433 local ns=$1; shift 1434 local tnl_type=$1; shift 1435 local name=$1; shift 1436 local addr=$1; shift 1437 1438 info "setting up kernel ${tnl_type} tunnel ${name}" 1439 ovs_sbx "${sbxname}" ip -netns ${ns} link add dev ${name} type ${tnl_type} $* || return 1 1440 on_exit "ovs_sbx ${sbxname} ip -netns ${ns} link del ${name} >/dev/null 2>&1" 1441 ovs_sbx "${sbxname}" ip -netns ${ns} addr add dev ${name} ${addr} || return 1 1442 ovs_sbx "${sbxname}" ip -netns ${ns} link set dev ${name} mtu 1450 up || return 1 1443} 1444 1445test_tunnel_metadata() { 1446 which arping >/dev/null 2>&1 || return $ksft_skip 1447 1448 sbxname="test_tunnel_metadata" 1449 sbx_add "${sbxname}" || return 1 1450 1451 info "setting up new DP" 1452 ovs_add_dp "${sbxname}" tdp0 -V 2:1 || return 1 1453 1454 ovs_add_netns_and_veths "${sbxname}" tdp0 tns left0 l0 \ 1455 172.31.110.1/24 || return 1 1456 1457 info "removing veth interface from openvswitch and setting IP" 1458 ovs_del_if "${sbxname}" tdp0 left0 || return 1 1459 ovs_sbx "${sbxname}" ip addr add 172.31.110.2/24 dev left0 || return 1 1460 ovs_sbx "${sbxname}" ip link set left0 up || return 1 1461 1462 info "setting up tunnel port in openvswitch" 1463 ovs_add_if "${sbxname}" "vxlan" tdp0 ovs-vxlan0 -u || return 1 1464 on_exit "ovs_sbx ${sbxname} ip link del ovs-vxlan0" 1465 ovs_wait ip link show ovs-vxlan0 &>/dev/null || return 1 1466 ovs_sbx "${sbxname}" ip link set ovs-vxlan0 up || return 1 1467 1468 configs=$(echo ' 1469 1 172.31.221.1/24 1155332 32 set udpcsum flags\(df\|csum\) 1470 2 172.31.222.1/24 1234567 45 set noudpcsum flags\(df\) 1471 3 172.31.223.1/24 1020304 23 unset udpcsum flags\(csum\) 1472 4 172.31.224.1/24 1357986 15 unset noudpcsum' | sed '/^$/d') 1473 1474 while read -r i addr id ttl df csum flags; do 1475 ovs_add_kernel_tunnel "${sbxname}" tns vxlan vxlan${i} ${addr} \ 1476 remote 172.31.110.2 id ${id} dstport 4789 \ 1477 ttl ${ttl} df ${df} ${csum} || return 1 1478 done <<< "${configs}" 1479 1480 ovs_wait grep -q 'listening on upcall packet handler' \ 1481 ${ovs_dir}/ovs-vxlan0.out || return 1 1482 1483 info "sending arping" 1484 for i in 1 2 3 4; do 1485 ovs_sbx "${sbxname}" ip netns exec tns \ 1486 arping -I vxlan${i} 172.31.22${i}.2 -c 1 \ 1487 >${ovs_dir}/arping.stdout 2>${ovs_dir}/arping.stderr 1488 done 1489 1490 info "checking that received decapsulated packets carry correct metadata" 1491 while read -r i addr id ttl df csum flags; do 1492 arp_hdr="arp\\(sip=172.31.22${i}.1,tip=172.31.22${i}.2,op=1,sha=" 1493 addrs="src=172.31.110.1,dst=172.31.110.2" 1494 ports="tp_src=[0-9]*,tp_dst=4789" 1495 tnl_md="tunnel\\(tun_id=${id},${addrs},ttl=${ttl},${ports},${flags}\\)" 1496 1497 ovs_sbx "${sbxname}" grep -qE "MISS upcall.*${tnl_md}.*${arp_hdr}" \ 1498 ${ovs_dir}/ovs-vxlan0.out || return 1 1499 done <<< "${configs}" 1500 1501 return 0 1502} 1503 1504test_pop_vlan() { 1505 local sbx="test_pop_vlan" 1506 sbx_add "$sbx" || return $? 1507 ovs_add_dp "$sbx" vlandp || return 1 1508 1509 ovs_add_netns_and_veths "$sbx" vlandp \ 1510 ns1 veth1 ns1veth 192.0.2.1/24 || return 1 1511 ovs_add_netns_and_veths "$sbx" vlandp \ 1512 ns2 veth2 ns2veth 192.0.2.2/24 || return 1 1513 1514 # Baseline: untagged bidirectional forwarding 1515 ovs_add_flow "$sbx" vlandp \ 1516 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 1517 ovs_add_flow "$sbx" vlandp \ 1518 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 1519 ovs_add_flow "$sbx" vlandp \ 1520 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1 1521 ovs_add_flow "$sbx" vlandp \ 1522 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 1523 ovs_sbx "$sbx" ip netns exec ns1 ping -c 3 -W 2 \ 1524 192.0.2.2 || return 1 1525 1526 # VLAN topology: ns1 uses VLAN sub-interface, ns2 is plain 1527 ip -n ns1 link add link ns1veth name ns1veth.10 \ 1528 type vlan id 10 || return 1 1529 on_exit "ip -n ns1 link del ns1veth.10 2>/dev/null" 1530 ip -n ns1 addr add 198.51.100.1/24 dev ns1veth.10 || return 1 1531 ip -n ns1 link set ns1veth.10 up || return 1 1532 ip -n ns2 addr add 198.51.100.2/24 dev ns2veth || return 1 1533 1534 ovs_del_flows "$sbx" vlandp 1535 1536 # Static ARP: avoids VLAN-tagged ARP complexity 1537 local ns1veth10mac ns2mac 1538 ns1veth10mac=$(ip -n ns1 link show ns1veth.10 \ 1539 | awk '/link\/ether/ {print $2}') 1540 [ -z "$ns1veth10mac" ] && \ 1541 { info "failed to get ns1veth10mac"; return 1; } 1542 ns2mac=$(ip -n ns2 link show ns2veth \ 1543 | awk '/link\/ether/ {print $2}') 1544 [ -z "$ns2mac" ] && \ 1545 { info "failed to get ns2mac"; return 1; } 1546 ip -n ns1 neigh replace 198.51.100.2 lladdr "$ns2mac" \ 1547 dev ns1veth.10 nud permanent || return 1 1548 ip -n ns2 neigh replace 198.51.100.1 \ 1549 lladdr "$ns1veth10mac" \ 1550 dev ns2veth nud permanent || return 1 1551 1552 local vlan_match='in_port(1),eth(),eth_type(0x8100),' 1553 vlan_match+='vlan(vid=10),' 1554 vlan_match+='encap(eth_type(0x0800),' 1555 vlan_match+='ipv4(src=198.51.100.1,proto=1),icmp())' 1556 1557 # Negative: forward without pop_vlan -- tagged frame 1558 # is invisible to ns2 (no VLAN sub-interface), ping fails 1559 ovs_add_flow "$sbx" vlandp "$vlan_match" '2' || return 1 1560 ovs_sbx "$sbx" ip netns exec ns1 ping -I ns1veth.10 \ 1561 -c 3 -W 1 198.51.100.2 >/dev/null 2>&1 \ 1562 && { info "FAIL: ping should fail without pop_vlan" 1563 return 1; } 1564 1565 ovs_del_flows "$sbx" vlandp 1566 1567 # Positive: pop_vlan strips tag on forward path, 1568 # push_vlan restores tag on return path -- ping succeeds 1569 ovs_add_flow "$sbx" vlandp \ 1570 "$vlan_match" 'pop_vlan,2' || return 1 1571 ovs_add_flow "$sbx" vlandp \ 1572 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ 1573 'push_vlan(vid=10,pcp=0,tpid=0x8100),1' || return 1 1574 ovs_sbx "$sbx" ip netns exec ns1 ping -I ns1veth.10 \ 1575 -c 3 -W 2 198.51.100.2 || return 1 1576 1577 return 0 1578} 1579 1580run_test() { 1581 ( 1582 tname="$1" 1583 tdesc="$2" 1584 1585 if python3 ovs-dpctl.py -h 2>&1 | \ 1586 grep -E "Need to (install|upgrade) the python" >/dev/null 2>&1; then 1587 stdbuf -o0 printf "TEST: %-60s [PYLIB]\n" "${tdesc}" 1588 return $ksft_skip 1589 fi 1590 1591 python3 ovs-dpctl.py show >/dev/null 2>&1 || \ 1592 echo "[DPCTL] show exception." 1593 1594 if ! lsmod | grep openvswitch >/dev/null 2>&1; then 1595 stdbuf -o0 printf "TEST: %-60s [NOMOD]\n" "${tdesc}" 1596 return $ksft_skip 1597 fi 1598 1599 printf "TEST: %-60s [START]\n" "${tname}" 1600 1601 unset IFS 1602 1603 eval test_${tname} 1604 ret=$? 1605 1606 if [ $ret -eq 0 ]; then 1607 printf "TEST: %-60s [ OK ]\n" "${tdesc}" 1608 ovs_exit_sig 1609 rm -rf "$ovs_dir" 1610 elif [ $ret -eq 1 ]; then 1611 printf "TEST: %-60s [FAIL]\n" "${tdesc}" 1612 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 1613 echo 1614 echo "Pausing. Logs in $ovs_dir/. Hit enter to continue" 1615 read a 1616 fi 1617 ovs_exit_sig 1618 [ "${PAUSE_ON_FAIL}" = "yes" ] || rm -rf "$ovs_dir" 1619 exit 1 1620 elif [ $ret -eq $ksft_skip ]; then 1621 printf "TEST: %-60s [SKIP]\n" "${tdesc}" 1622 elif [ $ret -eq 2 ]; then 1623 rm -rf test_${tname} 1624 run_test "$1" "$2" 1625 fi 1626 1627 return $ret 1628 ) 1629 ret=$? 1630 case $ret in 1631 0) 1632 [ $all_skipped = true ] && [ $exitcode=$ksft_skip ] && exitcode=0 1633 all_skipped=false 1634 ;; 1635 $ksft_skip) 1636 [ $all_skipped = true ] && exitcode=$ksft_skip 1637 ;; 1638 *) 1639 all_skipped=false 1640 exitcode=1 1641 ;; 1642 esac 1643 1644 return $ret 1645} 1646 1647 1648exitcode=0 1649desc=0 1650all_skipped=true 1651 1652while getopts :pvt o 1653do 1654 case $o in 1655 p) PAUSE_ON_FAIL=yes;; 1656 v) VERBOSE=1;; 1657 t) if which tcpdump > /dev/null 2>&1; then 1658 TRACING=1 1659 else 1660 echo "=== tcpdump not available, tracing disabled" 1661 fi 1662 ;; 1663 *) usage;; 1664 esac 1665done 1666shift $(($OPTIND-1)) 1667 1668IFS=" 1669" 1670 1671for arg do 1672 # Check first that all requested tests are available before running any 1673 command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; } 1674done 1675 1676name="" 1677desc="" 1678for t in ${tests}; do 1679 [ "${name}" = "" ] && name="${t}" && continue 1680 [ "${desc}" = "" ] && desc="${t}" 1681 1682 run_this=1 1683 for arg do 1684 [ "${arg}" != "${arg#--*}" ] && continue 1685 [ "${arg}" = "${name}" ] && run_this=1 && break 1686 run_this=0 1687 done 1688 if [ $run_this -eq 1 ]; then 1689 run_test "${name}" "${desc}" 1690 fi 1691 name="" 1692 desc="" 1693done 1694 1695exit ${exitcode} 1696