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