1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4############################################################################## 5# Defines 6 7# Can be overridden by the configuration file. 8PING=${PING:=ping} 9PING6=${PING6:=ping6} 10MZ=${MZ:=mausezahn} 11ARPING=${ARPING:=arping} 12TEAMD=${TEAMD:=teamd} 13WAIT_TIME=${WAIT_TIME:=5} 14PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 15PAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no} 16NETIF_TYPE=${NETIF_TYPE:=veth} 17NETIF_CREATE=${NETIF_CREATE:=yes} 18 19relative_path="${BASH_SOURCE%/*}" 20if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then 21 relative_path="." 22fi 23 24if [[ -f $relative_path/forwarding.config ]]; then 25 source "$relative_path/forwarding.config" 26fi 27 28############################################################################## 29# Sanity checks 30 31check_tc_version() 32{ 33 tc -j &> /dev/null 34 if [[ $? -ne 0 ]]; then 35 echo "SKIP: iproute2 too old; tc is missing JSON support" 36 exit 1 37 fi 38} 39 40check_tc_shblock_support() 41{ 42 tc filter help 2>&1 | grep block &> /dev/null 43 if [[ $? -ne 0 ]]; then 44 echo "SKIP: iproute2 too old; tc is missing shared block support" 45 exit 1 46 fi 47} 48 49check_tc_chain_support() 50{ 51 tc help 2>&1|grep chain &> /dev/null 52 if [[ $? -ne 0 ]]; then 53 echo "SKIP: iproute2 too old; tc is missing chain support" 54 exit 1 55 fi 56} 57 58if [[ "$(id -u)" -ne 0 ]]; then 59 echo "SKIP: need root privileges" 60 exit 0 61fi 62 63if [[ "$CHECK_TC" = "yes" ]]; then 64 check_tc_version 65fi 66 67require_command() 68{ 69 local cmd=$1; shift 70 71 if [[ ! -x "$(command -v "$cmd")" ]]; then 72 echo "SKIP: $cmd not installed" 73 exit 1 74 fi 75} 76 77require_command jq 78require_command $MZ 79 80if [[ ! -v NUM_NETIFS ]]; then 81 echo "SKIP: importer does not define \"NUM_NETIFS\"" 82 exit 1 83fi 84 85############################################################################## 86# Command line options handling 87 88count=0 89 90while [[ $# -gt 0 ]]; do 91 if [[ "$count" -eq "0" ]]; then 92 unset NETIFS 93 declare -A NETIFS 94 fi 95 count=$((count + 1)) 96 NETIFS[p$count]="$1" 97 shift 98done 99 100############################################################################## 101# Network interfaces configuration 102 103create_netif_veth() 104{ 105 local i 106 107 for i in $(eval echo {1..$NUM_NETIFS}); do 108 local j=$((i+1)) 109 110 ip link show dev ${NETIFS[p$i]} &> /dev/null 111 if [[ $? -ne 0 ]]; then 112 ip link add ${NETIFS[p$i]} type veth \ 113 peer name ${NETIFS[p$j]} 114 if [[ $? -ne 0 ]]; then 115 echo "Failed to create netif" 116 exit 1 117 fi 118 fi 119 i=$j 120 done 121} 122 123create_netif() 124{ 125 case "$NETIF_TYPE" in 126 veth) create_netif_veth 127 ;; 128 *) echo "Can not create interfaces of type \'$NETIF_TYPE\'" 129 exit 1 130 ;; 131 esac 132} 133 134if [[ "$NETIF_CREATE" = "yes" ]]; then 135 create_netif 136fi 137 138for i in $(eval echo {1..$NUM_NETIFS}); do 139 ip link show dev ${NETIFS[p$i]} &> /dev/null 140 if [[ $? -ne 0 ]]; then 141 echo "SKIP: could not find all required interfaces" 142 exit 1 143 fi 144done 145 146############################################################################## 147# Helpers 148 149# Exit status to return at the end. Set in case one of the tests fails. 150EXIT_STATUS=0 151# Per-test return value. Clear at the beginning of each test. 152RET=0 153 154check_err() 155{ 156 local err=$1 157 local msg=$2 158 159 if [[ $RET -eq 0 && $err -ne 0 ]]; then 160 RET=$err 161 retmsg=$msg 162 fi 163} 164 165check_fail() 166{ 167 local err=$1 168 local msg=$2 169 170 if [[ $RET -eq 0 && $err -eq 0 ]]; then 171 RET=1 172 retmsg=$msg 173 fi 174} 175 176check_err_fail() 177{ 178 local should_fail=$1; shift 179 local err=$1; shift 180 local what=$1; shift 181 182 if ((should_fail)); then 183 check_fail $err "$what succeeded, but should have failed" 184 else 185 check_err $err "$what failed" 186 fi 187} 188 189log_test() 190{ 191 local test_name=$1 192 local opt_str=$2 193 194 if [[ $# -eq 2 ]]; then 195 opt_str="($opt_str)" 196 fi 197 198 if [[ $RET -ne 0 ]]; then 199 EXIT_STATUS=1 200 printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str" 201 if [[ ! -z "$retmsg" ]]; then 202 printf "\t%s\n" "$retmsg" 203 fi 204 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 205 echo "Hit enter to continue, 'q' to quit" 206 read a 207 [ "$a" = "q" ] && exit 1 208 fi 209 return 1 210 fi 211 212 printf "TEST: %-60s [PASS]\n" "$test_name $opt_str" 213 return 0 214} 215 216log_info() 217{ 218 local msg=$1 219 220 echo "INFO: $msg" 221} 222 223setup_wait_dev() 224{ 225 local dev=$1; shift 226 227 while true; do 228 ip link show dev $dev up \ 229 | grep 'state UP' &> /dev/null 230 if [[ $? -ne 0 ]]; then 231 sleep 1 232 else 233 break 234 fi 235 done 236} 237 238setup_wait() 239{ 240 local num_netifs=${1:-$NUM_NETIFS} 241 242 for ((i = 1; i <= num_netifs; ++i)); do 243 setup_wait_dev ${NETIFS[p$i]} 244 done 245 246 # Make sure links are ready. 247 sleep $WAIT_TIME 248} 249 250lldpad_app_wait_set() 251{ 252 local dev=$1; shift 253 254 while lldptool -t -i $dev -V APP -c app | grep -q pending; do 255 echo "$dev: waiting for lldpad to push pending APP updates" 256 sleep 5 257 done 258} 259 260lldpad_app_wait_del() 261{ 262 # Give lldpad a chance to push down the changes. If the device is downed 263 # too soon, the updates will be left pending. However, they will have 264 # been struck off the lldpad's DB already, so we won't be able to tell 265 # they are pending. Then on next test iteration this would cause 266 # weirdness as newly-added APP rules conflict with the old ones, 267 # sometimes getting stuck in an "unknown" state. 268 sleep 5 269} 270 271pre_cleanup() 272{ 273 if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then 274 echo "Pausing before cleanup, hit any key to continue" 275 read 276 fi 277} 278 279vrf_prepare() 280{ 281 ip -4 rule add pref 32765 table local 282 ip -4 rule del pref 0 283 ip -6 rule add pref 32765 table local 284 ip -6 rule del pref 0 285} 286 287vrf_cleanup() 288{ 289 ip -6 rule add pref 0 table local 290 ip -6 rule del pref 32765 291 ip -4 rule add pref 0 table local 292 ip -4 rule del pref 32765 293} 294 295__last_tb_id=0 296declare -A __TB_IDS 297 298__vrf_td_id_assign() 299{ 300 local vrf_name=$1 301 302 __last_tb_id=$((__last_tb_id + 1)) 303 __TB_IDS[$vrf_name]=$__last_tb_id 304 return $__last_tb_id 305} 306 307__vrf_td_id_lookup() 308{ 309 local vrf_name=$1 310 311 return ${__TB_IDS[$vrf_name]} 312} 313 314vrf_create() 315{ 316 local vrf_name=$1 317 local tb_id 318 319 __vrf_td_id_assign $vrf_name 320 tb_id=$? 321 322 ip link add dev $vrf_name type vrf table $tb_id 323 ip -4 route add table $tb_id unreachable default metric 4278198272 324 ip -6 route add table $tb_id unreachable default metric 4278198272 325} 326 327vrf_destroy() 328{ 329 local vrf_name=$1 330 local tb_id 331 332 __vrf_td_id_lookup $vrf_name 333 tb_id=$? 334 335 ip -6 route del table $tb_id unreachable default metric 4278198272 336 ip -4 route del table $tb_id unreachable default metric 4278198272 337 ip link del dev $vrf_name 338} 339 340__addr_add_del() 341{ 342 local if_name=$1 343 local add_del=$2 344 local array 345 346 shift 347 shift 348 array=("${@}") 349 350 for addrstr in "${array[@]}"; do 351 ip address $add_del $addrstr dev $if_name 352 done 353} 354 355__simple_if_init() 356{ 357 local if_name=$1; shift 358 local vrf_name=$1; shift 359 local addrs=("${@}") 360 361 ip link set dev $if_name master $vrf_name 362 ip link set dev $if_name up 363 364 __addr_add_del $if_name add "${addrs[@]}" 365} 366 367__simple_if_fini() 368{ 369 local if_name=$1; shift 370 local addrs=("${@}") 371 372 __addr_add_del $if_name del "${addrs[@]}" 373 374 ip link set dev $if_name down 375 ip link set dev $if_name nomaster 376} 377 378simple_if_init() 379{ 380 local if_name=$1 381 local vrf_name 382 local array 383 384 shift 385 vrf_name=v$if_name 386 array=("${@}") 387 388 vrf_create $vrf_name 389 ip link set dev $vrf_name up 390 __simple_if_init $if_name $vrf_name "${array[@]}" 391} 392 393simple_if_fini() 394{ 395 local if_name=$1 396 local vrf_name 397 local array 398 399 shift 400 vrf_name=v$if_name 401 array=("${@}") 402 403 __simple_if_fini $if_name "${array[@]}" 404 vrf_destroy $vrf_name 405} 406 407tunnel_create() 408{ 409 local name=$1; shift 410 local type=$1; shift 411 local local=$1; shift 412 local remote=$1; shift 413 414 ip link add name $name type $type \ 415 local $local remote $remote "$@" 416 ip link set dev $name up 417} 418 419tunnel_destroy() 420{ 421 local name=$1; shift 422 423 ip link del dev $name 424} 425 426vlan_create() 427{ 428 local if_name=$1; shift 429 local vid=$1; shift 430 local vrf=$1; shift 431 local ips=("${@}") 432 local name=$if_name.$vid 433 434 ip link add name $name link $if_name type vlan id $vid 435 if [ "$vrf" != "" ]; then 436 ip link set dev $name master $vrf 437 fi 438 ip link set dev $name up 439 __addr_add_del $name add "${ips[@]}" 440} 441 442vlan_destroy() 443{ 444 local if_name=$1; shift 445 local vid=$1; shift 446 local name=$if_name.$vid 447 448 ip link del dev $name 449} 450 451team_create() 452{ 453 local if_name=$1; shift 454 local mode=$1; shift 455 456 require_command $TEAMD 457 $TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}' 458 for slave in "$@"; do 459 ip link set dev $slave down 460 ip link set dev $slave master $if_name 461 ip link set dev $slave up 462 done 463 ip link set dev $if_name up 464} 465 466team_destroy() 467{ 468 local if_name=$1; shift 469 470 $TEAMD -t $if_name -k 471} 472 473master_name_get() 474{ 475 local if_name=$1 476 477 ip -j link show dev $if_name | jq -r '.[]["master"]' 478} 479 480link_stats_tx_packets_get() 481{ 482 local if_name=$1 483 484 ip -j -s link show dev $if_name | jq '.[]["stats64"]["tx"]["packets"]' 485} 486 487tc_rule_stats_get() 488{ 489 local dev=$1; shift 490 local pref=$1; shift 491 local dir=$1; shift 492 493 tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \ 494 | jq '.[1].options.actions[].stats.packets' 495} 496 497mac_get() 498{ 499 local if_name=$1 500 501 ip -j link show dev $if_name | jq -r '.[]["address"]' 502} 503 504bridge_ageing_time_get() 505{ 506 local bridge=$1 507 local ageing_time 508 509 # Need to divide by 100 to convert to seconds. 510 ageing_time=$(ip -j -d link show dev $bridge \ 511 | jq '.[]["linkinfo"]["info_data"]["ageing_time"]') 512 echo $((ageing_time / 100)) 513} 514 515declare -A SYSCTL_ORIG 516sysctl_set() 517{ 518 local key=$1; shift 519 local value=$1; shift 520 521 SYSCTL_ORIG[$key]=$(sysctl -n $key) 522 sysctl -qw $key=$value 523} 524 525sysctl_restore() 526{ 527 local key=$1; shift 528 529 sysctl -qw $key=${SYSCTL_ORIG["$key"]} 530} 531 532forwarding_enable() 533{ 534 sysctl_set net.ipv4.conf.all.forwarding 1 535 sysctl_set net.ipv6.conf.all.forwarding 1 536} 537 538forwarding_restore() 539{ 540 sysctl_restore net.ipv6.conf.all.forwarding 541 sysctl_restore net.ipv4.conf.all.forwarding 542} 543 544tc_offload_check() 545{ 546 local num_netifs=${1:-$NUM_NETIFS} 547 548 for ((i = 1; i <= num_netifs; ++i)); do 549 ethtool -k ${NETIFS[p$i]} \ 550 | grep "hw-tc-offload: on" &> /dev/null 551 if [[ $? -ne 0 ]]; then 552 return 1 553 fi 554 done 555 556 return 0 557} 558 559trap_install() 560{ 561 local dev=$1; shift 562 local direction=$1; shift 563 564 # Some devices may not support or need in-hardware trapping of traffic 565 # (e.g. the veth pairs that this library creates for non-existent 566 # loopbacks). Use continue instead, so that there is a filter in there 567 # (some tests check counters), and so that other filters are still 568 # processed. 569 tc filter add dev $dev $direction pref 1 \ 570 flower skip_sw action trap 2>/dev/null \ 571 || tc filter add dev $dev $direction pref 1 \ 572 flower action continue 573} 574 575trap_uninstall() 576{ 577 local dev=$1; shift 578 local direction=$1; shift 579 580 tc filter del dev $dev $direction pref 1 flower 581} 582 583slow_path_trap_install() 584{ 585 # For slow-path testing, we need to install a trap to get to 586 # slow path the packets that would otherwise be switched in HW. 587 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then 588 trap_install "$@" 589 fi 590} 591 592slow_path_trap_uninstall() 593{ 594 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then 595 trap_uninstall "$@" 596 fi 597} 598 599__icmp_capture_add_del() 600{ 601 local add_del=$1; shift 602 local pref=$1; shift 603 local vsuf=$1; shift 604 local tundev=$1; shift 605 local filter=$1; shift 606 607 tc filter $add_del dev "$tundev" ingress \ 608 proto ip$vsuf pref $pref \ 609 flower ip_proto icmp$vsuf $filter \ 610 action pass 611} 612 613icmp_capture_install() 614{ 615 __icmp_capture_add_del add 100 "" "$@" 616} 617 618icmp_capture_uninstall() 619{ 620 __icmp_capture_add_del del 100 "" "$@" 621} 622 623icmp6_capture_install() 624{ 625 __icmp_capture_add_del add 100 v6 "$@" 626} 627 628icmp6_capture_uninstall() 629{ 630 __icmp_capture_add_del del 100 v6 "$@" 631} 632 633__vlan_capture_add_del() 634{ 635 local add_del=$1; shift 636 local pref=$1; shift 637 local dev=$1; shift 638 local filter=$1; shift 639 640 tc filter $add_del dev "$dev" ingress \ 641 proto 802.1q pref $pref \ 642 flower $filter \ 643 action pass 644} 645 646vlan_capture_install() 647{ 648 __vlan_capture_add_del add 100 "$@" 649} 650 651vlan_capture_uninstall() 652{ 653 __vlan_capture_add_del del 100 "$@" 654} 655 656__dscp_capture_add_del() 657{ 658 local add_del=$1; shift 659 local dev=$1; shift 660 local base=$1; shift 661 local dscp; 662 663 for prio in {0..7}; do 664 dscp=$((base + prio)) 665 __icmp_capture_add_del $add_del $((dscp + 100)) "" $dev \ 666 "skip_hw ip_tos $((dscp << 2))" 667 done 668} 669 670dscp_capture_install() 671{ 672 local dev=$1; shift 673 local base=$1; shift 674 675 __dscp_capture_add_del add $dev $base 676} 677 678dscp_capture_uninstall() 679{ 680 local dev=$1; shift 681 local base=$1; shift 682 683 __dscp_capture_add_del del $dev $base 684} 685 686dscp_fetch_stats() 687{ 688 local dev=$1; shift 689 local base=$1; shift 690 691 for prio in {0..7}; do 692 local dscp=$((base + prio)) 693 local t=$(tc_rule_stats_get $dev $((dscp + 100))) 694 echo "[$dscp]=$t " 695 done 696} 697 698matchall_sink_create() 699{ 700 local dev=$1; shift 701 702 tc qdisc add dev $dev clsact 703 tc filter add dev $dev ingress \ 704 pref 10000 \ 705 matchall \ 706 action drop 707} 708 709tests_run() 710{ 711 local current_test 712 713 for current_test in ${TESTS:-$ALL_TESTS}; do 714 $current_test 715 done 716} 717 718multipath_eval() 719{ 720 local desc="$1" 721 local weight_rp12=$2 722 local weight_rp13=$3 723 local packets_rp12=$4 724 local packets_rp13=$5 725 local weights_ratio packets_ratio diff 726 727 RET=0 728 729 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then 730 weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \ 731 | bc -l) 732 else 733 weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \ 734 | bc -l) 735 fi 736 737 if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then 738 check_err 1 "Packet difference is 0" 739 log_test "Multipath" 740 log_info "Expected ratio $weights_ratio" 741 return 742 fi 743 744 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then 745 packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \ 746 | bc -l) 747 else 748 packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \ 749 | bc -l) 750 fi 751 752 diff=$(echo $weights_ratio - $packets_ratio | bc -l) 753 diff=${diff#-} 754 755 test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0 756 check_err $? "Too large discrepancy between expected and measured ratios" 757 log_test "$desc" 758 log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio" 759} 760 761############################################################################## 762# Tests 763 764ping_do() 765{ 766 local if_name=$1 767 local dip=$2 768 local vrf_name 769 770 vrf_name=$(master_name_get $if_name) 771 ip vrf exec $vrf_name $PING $dip -c 10 -i 0.1 -w 2 &> /dev/null 772} 773 774ping_test() 775{ 776 RET=0 777 778 ping_do $1 $2 779 check_err $? 780 log_test "ping" 781} 782 783ping6_do() 784{ 785 local if_name=$1 786 local dip=$2 787 local vrf_name 788 789 vrf_name=$(master_name_get $if_name) 790 ip vrf exec $vrf_name $PING6 $dip -c 10 -i 0.1 -w 2 &> /dev/null 791} 792 793ping6_test() 794{ 795 RET=0 796 797 ping6_do $1 $2 798 check_err $? 799 log_test "ping6" 800} 801 802learning_test() 803{ 804 local bridge=$1 805 local br_port1=$2 # Connected to `host1_if`. 806 local host1_if=$3 807 local host2_if=$4 808 local mac=de:ad:be:ef:13:37 809 local ageing_time 810 811 RET=0 812 813 bridge -j fdb show br $bridge brport $br_port1 \ 814 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null 815 check_fail $? "Found FDB record when should not" 816 817 # Disable unknown unicast flooding on `br_port1` to make sure 818 # packets are only forwarded through the port after a matching 819 # FDB entry was installed. 820 bridge link set dev $br_port1 flood off 821 822 tc qdisc add dev $host1_if ingress 823 tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \ 824 flower dst_mac $mac action drop 825 826 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q 827 sleep 1 828 829 tc -j -s filter show dev $host1_if ingress \ 830 | jq -e ".[] | select(.options.handle == 101) \ 831 | select(.options.actions[0].stats.packets == 1)" &> /dev/null 832 check_fail $? "Packet reached second host when should not" 833 834 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q 835 sleep 1 836 837 bridge -j fdb show br $bridge brport $br_port1 \ 838 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null 839 check_err $? "Did not find FDB record when should" 840 841 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q 842 sleep 1 843 844 tc -j -s filter show dev $host1_if ingress \ 845 | jq -e ".[] | select(.options.handle == 101) \ 846 | select(.options.actions[0].stats.packets == 1)" &> /dev/null 847 check_err $? "Packet did not reach second host when should" 848 849 # Wait for 10 seconds after the ageing time to make sure FDB 850 # record was aged-out. 851 ageing_time=$(bridge_ageing_time_get $bridge) 852 sleep $((ageing_time + 10)) 853 854 bridge -j fdb show br $bridge brport $br_port1 \ 855 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null 856 check_fail $? "Found FDB record when should not" 857 858 bridge link set dev $br_port1 learning off 859 860 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q 861 sleep 1 862 863 bridge -j fdb show br $bridge brport $br_port1 \ 864 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null 865 check_fail $? "Found FDB record when should not" 866 867 bridge link set dev $br_port1 learning on 868 869 tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower 870 tc qdisc del dev $host1_if ingress 871 872 bridge link set dev $br_port1 flood on 873 874 log_test "FDB learning" 875} 876 877flood_test_do() 878{ 879 local should_flood=$1 880 local mac=$2 881 local ip=$3 882 local host1_if=$4 883 local host2_if=$5 884 local err=0 885 886 # Add an ACL on `host2_if` which will tell us whether the packet 887 # was flooded to it or not. 888 tc qdisc add dev $host2_if ingress 889 tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \ 890 flower dst_mac $mac action drop 891 892 $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q 893 sleep 1 894 895 tc -j -s filter show dev $host2_if ingress \ 896 | jq -e ".[] | select(.options.handle == 101) \ 897 | select(.options.actions[0].stats.packets == 1)" &> /dev/null 898 if [[ $? -ne 0 && $should_flood == "true" || \ 899 $? -eq 0 && $should_flood == "false" ]]; then 900 err=1 901 fi 902 903 tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower 904 tc qdisc del dev $host2_if ingress 905 906 return $err 907} 908 909flood_unicast_test() 910{ 911 local br_port=$1 912 local host1_if=$2 913 local host2_if=$3 914 local mac=de:ad:be:ef:13:37 915 local ip=192.0.2.100 916 917 RET=0 918 919 bridge link set dev $br_port flood off 920 921 flood_test_do false $mac $ip $host1_if $host2_if 922 check_err $? "Packet flooded when should not" 923 924 bridge link set dev $br_port flood on 925 926 flood_test_do true $mac $ip $host1_if $host2_if 927 check_err $? "Packet was not flooded when should" 928 929 log_test "Unknown unicast flood" 930} 931 932flood_multicast_test() 933{ 934 local br_port=$1 935 local host1_if=$2 936 local host2_if=$3 937 local mac=01:00:5e:00:00:01 938 local ip=239.0.0.1 939 940 RET=0 941 942 bridge link set dev $br_port mcast_flood off 943 944 flood_test_do false $mac $ip $host1_if $host2_if 945 check_err $? "Packet flooded when should not" 946 947 bridge link set dev $br_port mcast_flood on 948 949 flood_test_do true $mac $ip $host1_if $host2_if 950 check_err $? "Packet was not flooded when should" 951 952 log_test "Unregistered multicast flood" 953} 954 955flood_test() 956{ 957 # `br_port` is connected to `host2_if` 958 local br_port=$1 959 local host1_if=$2 960 local host2_if=$3 961 962 flood_unicast_test $br_port $host1_if $host2_if 963 flood_multicast_test $br_port $host1_if $host2_if 964} 965