843a6715924f2ccefc4f70d943548a2fcab5ad05
[linux-2.6-block.git] / tools / testing / selftests / net / forwarding / lib.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3
4 ##############################################################################
5 # Defines
6
7 # Can be overridden by the configuration file.
8 PING=${PING:=ping}
9 PING6=${PING6:=ping6}
10 MZ=${MZ:=mausezahn}
11 ARPING=${ARPING:=arping}
12 TEAMD=${TEAMD:=teamd}
13 WAIT_TIME=${WAIT_TIME:=5}
14 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
15 PAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
16 NETIF_TYPE=${NETIF_TYPE:=veth}
17 NETIF_CREATE=${NETIF_CREATE:=yes}
18
19 relative_path="${BASH_SOURCE%/*}"
20 if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
21         relative_path="."
22 fi
23
24 if [[ -f $relative_path/forwarding.config ]]; then
25         source "$relative_path/forwarding.config"
26 fi
27
28 ##############################################################################
29 # Sanity checks
30
31 check_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
40 check_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
49 check_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
58 if [[ "$(id -u)" -ne 0 ]]; then
59         echo "SKIP: need root privileges"
60         exit 0
61 fi
62
63 if [[ "$CHECK_TC" = "yes" ]]; then
64         check_tc_version
65 fi
66
67 require_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
77 require_command jq
78 require_command $MZ
79
80 if [[ ! -v NUM_NETIFS ]]; then
81         echo "SKIP: importer does not define \"NUM_NETIFS\""
82         exit 1
83 fi
84
85 ##############################################################################
86 # Command line options handling
87
88 count=0
89
90 while [[ $# -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
98 done
99
100 ##############################################################################
101 # Network interfaces configuration
102
103 create_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
123 create_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
134 if [[ "$NETIF_CREATE" = "yes" ]]; then
135         create_netif
136 fi
137
138 for 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
144 done
145
146 ##############################################################################
147 # Helpers
148
149 # Exit status to return at the end. Set in case one of the tests fails.
150 EXIT_STATUS=0
151 # Per-test return value. Clear at the beginning of each test.
152 RET=0
153
154 check_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
165 check_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
176 check_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
189 log_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
216 log_info()
217 {
218         local msg=$1
219
220         echo "INFO: $msg"
221 }
222
223 setup_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
238 setup_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
250 pre_cleanup()
251 {
252         if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
253                 echo "Pausing before cleanup, hit any key to continue"
254                 read
255         fi
256 }
257
258 vrf_prepare()
259 {
260         ip -4 rule add pref 32765 table local
261         ip -4 rule del pref 0
262         ip -6 rule add pref 32765 table local
263         ip -6 rule del pref 0
264 }
265
266 vrf_cleanup()
267 {
268         ip -6 rule add pref 0 table local
269         ip -6 rule del pref 32765
270         ip -4 rule add pref 0 table local
271         ip -4 rule del pref 32765
272 }
273
274 __last_tb_id=0
275 declare -A __TB_IDS
276
277 __vrf_td_id_assign()
278 {
279         local vrf_name=$1
280
281         __last_tb_id=$((__last_tb_id + 1))
282         __TB_IDS[$vrf_name]=$__last_tb_id
283         return $__last_tb_id
284 }
285
286 __vrf_td_id_lookup()
287 {
288         local vrf_name=$1
289
290         return ${__TB_IDS[$vrf_name]}
291 }
292
293 vrf_create()
294 {
295         local vrf_name=$1
296         local tb_id
297
298         __vrf_td_id_assign $vrf_name
299         tb_id=$?
300
301         ip link add dev $vrf_name type vrf table $tb_id
302         ip -4 route add table $tb_id unreachable default metric 4278198272
303         ip -6 route add table $tb_id unreachable default metric 4278198272
304 }
305
306 vrf_destroy()
307 {
308         local vrf_name=$1
309         local tb_id
310
311         __vrf_td_id_lookup $vrf_name
312         tb_id=$?
313
314         ip -6 route del table $tb_id unreachable default metric 4278198272
315         ip -4 route del table $tb_id unreachable default metric 4278198272
316         ip link del dev $vrf_name
317 }
318
319 __addr_add_del()
320 {
321         local if_name=$1
322         local add_del=$2
323         local array
324
325         shift
326         shift
327         array=("${@}")
328
329         for addrstr in "${array[@]}"; do
330                 ip address $add_del $addrstr dev $if_name
331         done
332 }
333
334 __simple_if_init()
335 {
336         local if_name=$1; shift
337         local vrf_name=$1; shift
338         local addrs=("${@}")
339
340         ip link set dev $if_name master $vrf_name
341         ip link set dev $if_name up
342
343         __addr_add_del $if_name add "${addrs[@]}"
344 }
345
346 __simple_if_fini()
347 {
348         local if_name=$1; shift
349         local addrs=("${@}")
350
351         __addr_add_del $if_name del "${addrs[@]}"
352
353         ip link set dev $if_name down
354         ip link set dev $if_name nomaster
355 }
356
357 simple_if_init()
358 {
359         local if_name=$1
360         local vrf_name
361         local array
362
363         shift
364         vrf_name=v$if_name
365         array=("${@}")
366
367         vrf_create $vrf_name
368         ip link set dev $vrf_name up
369         __simple_if_init $if_name $vrf_name "${array[@]}"
370 }
371
372 simple_if_fini()
373 {
374         local if_name=$1
375         local vrf_name
376         local array
377
378         shift
379         vrf_name=v$if_name
380         array=("${@}")
381
382         __simple_if_fini $if_name "${array[@]}"
383         vrf_destroy $vrf_name
384 }
385
386 tunnel_create()
387 {
388         local name=$1; shift
389         local type=$1; shift
390         local local=$1; shift
391         local remote=$1; shift
392
393         ip link add name $name type $type \
394            local $local remote $remote "$@"
395         ip link set dev $name up
396 }
397
398 tunnel_destroy()
399 {
400         local name=$1; shift
401
402         ip link del dev $name
403 }
404
405 vlan_create()
406 {
407         local if_name=$1; shift
408         local vid=$1; shift
409         local vrf=$1; shift
410         local ips=("${@}")
411         local name=$if_name.$vid
412
413         ip link add name $name link $if_name type vlan id $vid
414         if [ "$vrf" != "" ]; then
415                 ip link set dev $name master $vrf
416         fi
417         ip link set dev $name up
418         __addr_add_del $name add "${ips[@]}"
419 }
420
421 vlan_destroy()
422 {
423         local if_name=$1; shift
424         local vid=$1; shift
425         local name=$if_name.$vid
426
427         ip link del dev $name
428 }
429
430 team_create()
431 {
432         local if_name=$1; shift
433         local mode=$1; shift
434
435         require_command $TEAMD
436         $TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
437         for slave in "$@"; do
438                 ip link set dev $slave down
439                 ip link set dev $slave master $if_name
440                 ip link set dev $slave up
441         done
442         ip link set dev $if_name up
443 }
444
445 team_destroy()
446 {
447         local if_name=$1; shift
448
449         $TEAMD -t $if_name -k
450 }
451
452 master_name_get()
453 {
454         local if_name=$1
455
456         ip -j link show dev $if_name | jq -r '.[]["master"]'
457 }
458
459 link_stats_tx_packets_get()
460 {
461        local if_name=$1
462
463        ip -j -s link show dev $if_name | jq '.[]["stats64"]["tx"]["packets"]'
464 }
465
466 tc_rule_stats_get()
467 {
468         local dev=$1; shift
469         local pref=$1; shift
470         local dir=$1; shift
471
472         tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
473             | jq '.[1].options.actions[].stats.packets'
474 }
475
476 mac_get()
477 {
478         local if_name=$1
479
480         ip -j link show dev $if_name | jq -r '.[]["address"]'
481 }
482
483 bridge_ageing_time_get()
484 {
485         local bridge=$1
486         local ageing_time
487
488         # Need to divide by 100 to convert to seconds.
489         ageing_time=$(ip -j -d link show dev $bridge \
490                       | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
491         echo $((ageing_time / 100))
492 }
493
494 declare -A SYSCTL_ORIG
495 sysctl_set()
496 {
497         local key=$1; shift
498         local value=$1; shift
499
500         SYSCTL_ORIG[$key]=$(sysctl -n $key)
501         sysctl -qw $key=$value
502 }
503
504 sysctl_restore()
505 {
506         local key=$1; shift
507
508         sysctl -qw $key=${SYSCTL_ORIG["$key"]}
509 }
510
511 forwarding_enable()
512 {
513         sysctl_set net.ipv4.conf.all.forwarding 1
514         sysctl_set net.ipv6.conf.all.forwarding 1
515 }
516
517 forwarding_restore()
518 {
519         sysctl_restore net.ipv6.conf.all.forwarding
520         sysctl_restore net.ipv4.conf.all.forwarding
521 }
522
523 tc_offload_check()
524 {
525         local num_netifs=${1:-$NUM_NETIFS}
526
527         for ((i = 1; i <= num_netifs; ++i)); do
528                 ethtool -k ${NETIFS[p$i]} \
529                         | grep "hw-tc-offload: on" &> /dev/null
530                 if [[ $? -ne 0 ]]; then
531                         return 1
532                 fi
533         done
534
535         return 0
536 }
537
538 trap_install()
539 {
540         local dev=$1; shift
541         local direction=$1; shift
542
543         # Some devices may not support or need in-hardware trapping of traffic
544         # (e.g. the veth pairs that this library creates for non-existent
545         # loopbacks). Use continue instead, so that there is a filter in there
546         # (some tests check counters), and so that other filters are still
547         # processed.
548         tc filter add dev $dev $direction pref 1 \
549                 flower skip_sw action trap 2>/dev/null \
550             || tc filter add dev $dev $direction pref 1 \
551                        flower action continue
552 }
553
554 trap_uninstall()
555 {
556         local dev=$1; shift
557         local direction=$1; shift
558
559         tc filter del dev $dev $direction pref 1 flower
560 }
561
562 slow_path_trap_install()
563 {
564         # For slow-path testing, we need to install a trap to get to
565         # slow path the packets that would otherwise be switched in HW.
566         if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
567                 trap_install "$@"
568         fi
569 }
570
571 slow_path_trap_uninstall()
572 {
573         if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
574                 trap_uninstall "$@"
575         fi
576 }
577
578 __icmp_capture_add_del()
579 {
580         local add_del=$1; shift
581         local pref=$1; shift
582         local vsuf=$1; shift
583         local tundev=$1; shift
584         local filter=$1; shift
585
586         tc filter $add_del dev "$tundev" ingress \
587            proto ip$vsuf pref $pref \
588            flower ip_proto icmp$vsuf $filter \
589            action pass
590 }
591
592 icmp_capture_install()
593 {
594         __icmp_capture_add_del add 100 "" "$@"
595 }
596
597 icmp_capture_uninstall()
598 {
599         __icmp_capture_add_del del 100 "" "$@"
600 }
601
602 icmp6_capture_install()
603 {
604         __icmp_capture_add_del add 100 v6 "$@"
605 }
606
607 icmp6_capture_uninstall()
608 {
609         __icmp_capture_add_del del 100 v6 "$@"
610 }
611
612 __vlan_capture_add_del()
613 {
614         local add_del=$1; shift
615         local pref=$1; shift
616         local dev=$1; shift
617         local filter=$1; shift
618
619         tc filter $add_del dev "$dev" ingress \
620            proto 802.1q pref $pref \
621            flower $filter \
622            action pass
623 }
624
625 vlan_capture_install()
626 {
627         __vlan_capture_add_del add 100 "$@"
628 }
629
630 vlan_capture_uninstall()
631 {
632         __vlan_capture_add_del del 100 "$@"
633 }
634
635 matchall_sink_create()
636 {
637         local dev=$1; shift
638
639         tc qdisc add dev $dev clsact
640         tc filter add dev $dev ingress \
641            pref 10000 \
642            matchall \
643            action drop
644 }
645
646 tests_run()
647 {
648         local current_test
649
650         for current_test in ${TESTS:-$ALL_TESTS}; do
651                 $current_test
652         done
653 }
654
655 multipath_eval()
656 {
657         local desc="$1"
658         local weight_rp12=$2
659         local weight_rp13=$3
660         local packets_rp12=$4
661         local packets_rp13=$5
662         local weights_ratio packets_ratio diff
663
664         RET=0
665
666         if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
667                 weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
668                                 | bc -l)
669         else
670                 weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
671                                 | bc -l)
672         fi
673
674         if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
675                check_err 1 "Packet difference is 0"
676                log_test "Multipath"
677                log_info "Expected ratio $weights_ratio"
678                return
679         fi
680
681         if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
682                 packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
683                                 | bc -l)
684         else
685                 packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
686                                 | bc -l)
687         fi
688
689         diff=$(echo $weights_ratio - $packets_ratio | bc -l)
690         diff=${diff#-}
691
692         test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
693         check_err $? "Too large discrepancy between expected and measured ratios"
694         log_test "$desc"
695         log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
696 }
697
698 ##############################################################################
699 # Tests
700
701 ping_do()
702 {
703         local if_name=$1
704         local dip=$2
705         local vrf_name
706
707         vrf_name=$(master_name_get $if_name)
708         ip vrf exec $vrf_name $PING $dip -c 10 -i 0.1 -w 2 &> /dev/null
709 }
710
711 ping_test()
712 {
713         RET=0
714
715         ping_do $1 $2
716         check_err $?
717         log_test "ping"
718 }
719
720 ping6_do()
721 {
722         local if_name=$1
723         local dip=$2
724         local vrf_name
725
726         vrf_name=$(master_name_get $if_name)
727         ip vrf exec $vrf_name $PING6 $dip -c 10 -i 0.1 -w 2 &> /dev/null
728 }
729
730 ping6_test()
731 {
732         RET=0
733
734         ping6_do $1 $2
735         check_err $?
736         log_test "ping6"
737 }
738
739 learning_test()
740 {
741         local bridge=$1
742         local br_port1=$2       # Connected to `host1_if`.
743         local host1_if=$3
744         local host2_if=$4
745         local mac=de:ad:be:ef:13:37
746         local ageing_time
747
748         RET=0
749
750         bridge -j fdb show br $bridge brport $br_port1 \
751                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
752         check_fail $? "Found FDB record when should not"
753
754         # Disable unknown unicast flooding on `br_port1` to make sure
755         # packets are only forwarded through the port after a matching
756         # FDB entry was installed.
757         bridge link set dev $br_port1 flood off
758
759         tc qdisc add dev $host1_if ingress
760         tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
761                 flower dst_mac $mac action drop
762
763         $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
764         sleep 1
765
766         tc -j -s filter show dev $host1_if ingress \
767                 | jq -e ".[] | select(.options.handle == 101) \
768                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
769         check_fail $? "Packet reached second host when should not"
770
771         $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
772         sleep 1
773
774         bridge -j fdb show br $bridge brport $br_port1 \
775                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
776         check_err $? "Did not find FDB record when should"
777
778         $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
779         sleep 1
780
781         tc -j -s filter show dev $host1_if ingress \
782                 | jq -e ".[] | select(.options.handle == 101) \
783                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
784         check_err $? "Packet did not reach second host when should"
785
786         # Wait for 10 seconds after the ageing time to make sure FDB
787         # record was aged-out.
788         ageing_time=$(bridge_ageing_time_get $bridge)
789         sleep $((ageing_time + 10))
790
791         bridge -j fdb show br $bridge brport $br_port1 \
792                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
793         check_fail $? "Found FDB record when should not"
794
795         bridge link set dev $br_port1 learning off
796
797         $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
798         sleep 1
799
800         bridge -j fdb show br $bridge brport $br_port1 \
801                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
802         check_fail $? "Found FDB record when should not"
803
804         bridge link set dev $br_port1 learning on
805
806         tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
807         tc qdisc del dev $host1_if ingress
808
809         bridge link set dev $br_port1 flood on
810
811         log_test "FDB learning"
812 }
813
814 flood_test_do()
815 {
816         local should_flood=$1
817         local mac=$2
818         local ip=$3
819         local host1_if=$4
820         local host2_if=$5
821         local err=0
822
823         # Add an ACL on `host2_if` which will tell us whether the packet
824         # was flooded to it or not.
825         tc qdisc add dev $host2_if ingress
826         tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
827                 flower dst_mac $mac action drop
828
829         $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
830         sleep 1
831
832         tc -j -s filter show dev $host2_if ingress \
833                 | jq -e ".[] | select(.options.handle == 101) \
834                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
835         if [[ $? -ne 0 && $should_flood == "true" || \
836               $? -eq 0 && $should_flood == "false" ]]; then
837                 err=1
838         fi
839
840         tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
841         tc qdisc del dev $host2_if ingress
842
843         return $err
844 }
845
846 flood_unicast_test()
847 {
848         local br_port=$1
849         local host1_if=$2
850         local host2_if=$3
851         local mac=de:ad:be:ef:13:37
852         local ip=192.0.2.100
853
854         RET=0
855
856         bridge link set dev $br_port flood off
857
858         flood_test_do false $mac $ip $host1_if $host2_if
859         check_err $? "Packet flooded when should not"
860
861         bridge link set dev $br_port flood on
862
863         flood_test_do true $mac $ip $host1_if $host2_if
864         check_err $? "Packet was not flooded when should"
865
866         log_test "Unknown unicast flood"
867 }
868
869 flood_multicast_test()
870 {
871         local br_port=$1
872         local host1_if=$2
873         local host2_if=$3
874         local mac=01:00:5e:00:00:01
875         local ip=239.0.0.1
876
877         RET=0
878
879         bridge link set dev $br_port mcast_flood off
880
881         flood_test_do false $mac $ip $host1_if $host2_if
882         check_err $? "Packet flooded when should not"
883
884         bridge link set dev $br_port mcast_flood on
885
886         flood_test_do true $mac $ip $host1_if $host2_if
887         check_err $? "Packet was not flooded when should"
888
889         log_test "Unregistered multicast flood"
890 }
891
892 flood_test()
893 {
894         # `br_port` is connected to `host2_if`
895         local br_port=$1
896         local host1_if=$2
897         local host2_if=$3
898
899         flood_unicast_test $br_port $host1_if $host2_if
900         flood_multicast_test $br_port $host1_if $host2_if
901 }