2 # SPDX-License-Identifier: GPL-2.0
4 ##############################################################################
7 # Can be overridden by the configuration file.
11 ARPING
=${ARPING:=arping}
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}
19 MC_CLI
=${MC_CLI:=smcroutectl}
20 PING_TIMEOUT
=${PING_TIMEOUT:=5}
21 WAIT_TIMEOUT
=${WAIT_TIMEOUT:=20}
22 INTERFACE_TIMEOUT
=${INTERFACE_TIMEOUT:=600}
24 relative_path
="${BASH_SOURCE%/*}"
25 if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
29 if [[ -f $relative_path/forwarding.config
]]; then
30 source "$relative_path/forwarding.config"
33 ##############################################################################
39 if [[ $?
-ne 0 ]]; then
40 echo "SKIP: iproute2 too old; tc is missing JSON support"
45 check_tc_shblock_support
()
47 tc filter
help 2>&1 |
grep block
&> /dev
/null
48 if [[ $?
-ne 0 ]]; then
49 echo "SKIP: iproute2 too old; tc is missing shared block support"
54 check_tc_chain_support
()
56 tc
help 2>&1|
grep chain
&> /dev
/null
57 if [[ $?
-ne 0 ]]; then
58 echo "SKIP: iproute2 too old; tc is missing chain support"
63 check_tc_action_hw_stats_support
()
65 tc actions
help 2>&1 |
grep -q hw_stats
66 if [[ $?
-ne 0 ]]; then
67 echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
72 if [[ "$(id -u)" -ne 0 ]]; then
73 echo "SKIP: need root privileges"
77 if [[ "$CHECK_TC" = "yes" ]]; then
85 if [[ ! -x "$(command -v "$cmd")" ]]; then
86 echo "SKIP: $cmd not installed"
94 if [[ ! -v NUM_NETIFS
]]; then
95 echo "SKIP: importer does not define \"NUM_NETIFS\""
99 ##############################################################################
100 # Command line options handling
104 while [[ $# -gt 0 ]]; do
105 if [[ "$count" -eq "0" ]]; then
114 ##############################################################################
115 # Network interfaces configuration
121 for ((i
= 1; i
<= NUM_NETIFS
; ++i
)); do
124 ip link show dev
${NETIFS[p$i]} &> /dev
/null
125 if [[ $?
-ne 0 ]]; then
126 ip link add
${NETIFS[p$i]} type veth \
127 peer name
${NETIFS[p$j]}
128 if [[ $?
-ne 0 ]]; then
129 echo "Failed to create netif"
139 case "$NETIF_TYPE" in
140 veth
) create_netif_veth
142 *) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
148 if [[ "$NETIF_CREATE" = "yes" ]]; then
152 for ((i
= 1; i
<= NUM_NETIFS
; ++i
)); do
153 ip link show dev
${NETIFS[p$i]} &> /dev
/null
154 if [[ $?
-ne 0 ]]; then
155 echo "SKIP: could not find all required interfaces"
160 ##############################################################################
163 # Exit status to return at the end. Set in case one of the tests fails.
165 # Per-test return value. Clear at the beginning of each test.
173 if [[ $RET -eq 0 && $err -ne 0 ]]; then
184 if [[ $RET -eq 0 && $err -eq 0 ]]; then
192 local should_fail
=$1; shift
196 if ((should_fail
)); then
197 check_fail
$err "$what succeeded, but should have failed"
199 check_err
$err "$what failed"
208 if [[ $# -eq 2 ]]; then
212 if [[ $RET -ne 0 ]]; then
214 printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str"
215 if [[ ! -z "$retmsg" ]]; then
216 printf "\t%s\n" "$retmsg"
218 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
219 echo "Hit enter to continue, 'q' to quit"
221 [ "$a" = "q" ] && exit 1
226 printf "TEST: %-60s [ OK ]\n" "$test_name $opt_str"
239 local timeout
=$1; shift
241 local start_time
="$(date -u +%s%3N)"
252 local current_time
="$(date -u +%s%3N)"
253 if ((current_time
- start_time
> timeout
)); then
272 if [ "$1" == "self" ] ||
[ "$1" == "master" ]; then
274 if [ "$1" == "-v" ]; then
279 $@ |
grep $addr |
grep $flag "$word"
284 "$@" |
grep -q offload
290 local current
=$
("$@")
296 busywait_for_counter
()
298 local timeout
=$1; shift
299 local delta
=$1; shift
302 busywait
"$timeout" until_counter_is
">= $((base + delta))" "$@"
308 local wait_time
=${1:-$WAIT_TIME}; shift
310 setup_wait_dev_with_timeout
"$dev" $INTERFACE_TIMEOUT $wait_time
314 log_test setup_wait_dev
": Interface $dev does not come up."
319 setup_wait_dev_with_timeout
()
322 local max_iterations
=${1:-$WAIT_TIMEOUT}; shift
323 local wait_time
=${1:-$WAIT_TIME}; shift
326 for ((i
= 1; i
<= $max_iterations; ++i
)); do
327 ip link show dev
$dev up \
328 |
grep 'state UP' &> /dev
/null
329 if [[ $?
-ne 0 ]]; then
342 local num_netifs
=${1:-$NUM_NETIFS}
345 for ((i
= 1; i
<= num_netifs
; ++i
)); do
346 setup_wait_dev
${NETIFS[p$i]} 0
349 # Make sure links are ready.
362 # it the command fails, return error right away
364 if [[ $ret -ne 0 ]]; then
367 output
=$
(echo $output | jq
-r $jq_opts "$jq_exp")
369 if [[ $ret -ne 0 ]]; then
373 # return success only in case of non-empty output
377 lldpad_app_wait_set
()
381 while lldptool
-t -i $dev -V APP
-c app |
grep -Eq "pending|unknown"; do
382 echo "$dev: waiting for lldpad to push pending APP updates"
387 lldpad_app_wait_del
()
389 # Give lldpad a chance to push down the changes. If the device is downed
390 # too soon, the updates will be left pending. However, they will have
391 # been struck off the lldpad's DB already, so we won't be able to tell
392 # they are pending. Then on next test iteration this would cause
393 # weirdness as newly-added APP rules conflict with the old ones,
394 # sometimes getting stuck in an "unknown" state.
400 if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
401 echo "Pausing before cleanup, hit any key to continue"
408 ip
-4 rule add pref
32765 table
local
409 ip
-4 rule del pref
0
410 ip
-6 rule add pref
32765 table
local
411 ip
-6 rule del pref
0
416 ip
-6 rule add pref
0 table
local
417 ip
-6 rule del pref
32765
418 ip
-4 rule add pref
0 table
local
419 ip
-4 rule del pref
32765
429 __last_tb_id
=$
((__last_tb_id
+ 1))
430 __TB_IDS
[$vrf_name]=$__last_tb_id
438 return ${__TB_IDS[$vrf_name]}
446 __vrf_td_id_assign
$vrf_name
449 ip link add dev
$vrf_name type vrf table
$tb_id
450 ip
-4 route add table
$tb_id unreachable default metric
4278198272
451 ip
-6 route add table
$tb_id unreachable default metric
4278198272
459 __vrf_td_id_lookup
$vrf_name
462 ip
-6 route del table
$tb_id unreachable default metric
4278198272
463 ip
-4 route del table
$tb_id unreachable default metric
4278198272
464 ip link del dev
$vrf_name
477 for addrstr
in "${array[@]}"; do
478 ip address
$add_del $addrstr dev
$if_name
484 local if_name
=$1; shift
485 local vrf_name
=$1; shift
488 ip link
set dev
$if_name master
$vrf_name
489 ip link
set dev
$if_name up
491 __addr_add_del
$if_name add
"${addrs[@]}"
496 local if_name
=$1; shift
499 __addr_add_del
$if_name del
"${addrs[@]}"
501 ip link
set dev
$if_name down
502 ip link
set dev
$if_name nomaster
516 ip link
set dev
$vrf_name up
517 __simple_if_init
$if_name $vrf_name "${array[@]}"
530 __simple_if_fini
$if_name "${array[@]}"
531 vrf_destroy
$vrf_name
538 local local=$1; shift
539 local remote
=$1; shift
541 ip link add name
$name type $type \
542 local $local remote
$remote "$@"
543 ip link
set dev
$name up
550 ip link del dev
$name
555 local if_name
=$1; shift
559 local name
=$if_name.
$vid
561 ip link add name
$name link
$if_name type vlan id
$vid
562 if [ "$vrf" != "" ]; then
563 ip link
set dev
$name master
$vrf
565 ip link
set dev
$name up
566 __addr_add_del
$name add
"${ips[@]}"
571 local if_name
=$1; shift
573 local name
=$if_name.
$vid
575 ip link del dev
$name
580 local if_name
=$1; shift
583 require_command
$TEAMD
584 $TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
585 for slave
in "$@"; do
586 ip link
set dev
$slave down
587 ip link
set dev
$slave master
$if_name
588 ip link
set dev
$slave up
590 ip link
set dev
$if_name up
595 local if_name
=$1; shift
597 $TEAMD -t $if_name -k
604 ip
-j link show dev
$if_name | jq
-r '.[]["master"]'
609 local if_name
=$1; shift
613 ip
-j -s link show dev
$if_name \
614 | jq
'.[]["stats64"]["'$dir'"]["'$stat'"]'
617 link_stats_tx_packets_get
()
619 link_stats_get
$1 tx packets
622 link_stats_rx_errors_get
()
624 link_stats_get
$1 rx errors
632 local selector
=${1:-.packets}; shift
634 tc
-j -s filter show dev
$dev ${dir:-ingress} pref
$pref \
635 | jq
".[1].options.actions[].stats$selector"
638 tc_rule_handle_stats_get
()
641 local handle
=$1; shift
642 local selector
=${1:-.packets}; shift
644 tc
-j -s filter show
$id \
645 | jq
".[] | select(.options.handle == $handle) | \
646 .options.actions[0].stats$selector"
654 ethtool
-S $dev |
grep "^ *$stat:" |
head -n 1 | cut
-d: -f2
660 local handle
=$1; shift
661 local selector
=$1; shift
663 tc
-j -s qdisc show dev
"$dev" \
664 | jq
'.[] | select(.handle == "'"$handle"'") | '"$selector"
667 qdisc_parent_stats_get
()
670 local parent
=$1; shift
671 local selector
=$1; shift
673 tc
-j -s qdisc show dev
"$dev" invisible \
674 | jq
'.[] | select(.parent == "'"$parent"'") | '"$selector"
679 local speed
=$1; shift
681 for unit
in bps Kbps Mbps Gbps
; do
682 if (($
(echo "$speed < 1024" |
bc))); then
686 speed
=$
(echo "scale=1; $speed / 1024" |
bc)
696 local interval
=$1; shift
698 echo $
((8 * (t1
- t0
) / interval
))
705 ip
-j link show dev
$if_name | jq
-r '.[]["address"]'
708 bridge_ageing_time_get
()
713 # Need to divide by 100 to convert to seconds.
714 ageing_time
=$
(ip
-j -d link show dev
$bridge \
715 | jq
'.[]["linkinfo"]["info_data"]["ageing_time"]')
716 echo $
((ageing_time
/ 100))
719 declare -A SYSCTL_ORIG
723 local value
=$1; shift
725 SYSCTL_ORIG
[$key]=$
(sysctl
-n $key)
726 sysctl
-qw $key=$value
733 sysctl
-qw $key=${SYSCTL_ORIG["$key"]}
738 sysctl_set net.ipv4.conf.all.forwarding
1
739 sysctl_set net.ipv6.conf.all.forwarding
1
744 sysctl_restore net.ipv6.conf.all.forwarding
745 sysctl_restore net.ipv4.conf.all.forwarding
754 MTU_ORIG
["$dev"]=$
(ip
-j link show dev
$dev | jq
-e '.[].mtu')
755 ip link
set dev
$dev mtu
$mtu
762 ip link
set dev
$dev mtu
${MTU_ORIG["$dev"]}
767 local num_netifs
=${1:-$NUM_NETIFS}
769 for ((i
= 1; i
<= num_netifs
; ++i
)); do
770 ethtool
-k ${NETIFS[p$i]} \
771 |
grep "hw-tc-offload: on" &> /dev
/null
772 if [[ $?
-ne 0 ]]; then
783 local direction
=$1; shift
785 # Some devices may not support or need in-hardware trapping of traffic
786 # (e.g. the veth pairs that this library creates for non-existent
787 # loopbacks). Use continue instead, so that there is a filter in there
788 # (some tests check counters), and so that other filters are still
790 tc filter add dev
$dev $direction pref
1 \
791 flower skip_sw action
trap 2>/dev
/null \
792 || tc filter add dev
$dev $direction pref
1 \
793 flower action
continue
799 local direction
=$1; shift
801 tc filter del dev
$dev $direction pref
1 flower
804 slow_path_trap_install
()
806 # For slow-path testing, we need to install a trap to get to
807 # slow path the packets that would otherwise be switched in HW.
808 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
813 slow_path_trap_uninstall
()
815 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
820 __icmp_capture_add_del
()
822 local add_del
=$1; shift
825 local tundev
=$1; shift
826 local filter
=$1; shift
828 tc filter
$add_del dev
"$tundev" ingress \
829 proto ip
$vsuf pref
$pref \
830 flower ip_proto icmp
$vsuf $filter \
834 icmp_capture_install
()
836 __icmp_capture_add_del add
100 "" "$@"
839 icmp_capture_uninstall
()
841 __icmp_capture_add_del del
100 "" "$@"
844 icmp6_capture_install
()
846 __icmp_capture_add_del add
100 v6
"$@"
849 icmp6_capture_uninstall
()
851 __icmp_capture_add_del del
100 v6
"$@"
854 __vlan_capture_add_del
()
856 local add_del
=$1; shift
859 local filter
=$1; shift
861 tc filter
$add_del dev
"$dev" ingress \
862 proto
802.1q pref
$pref \
867 vlan_capture_install
()
869 __vlan_capture_add_del add
100 "$@"
872 vlan_capture_uninstall
()
874 __vlan_capture_add_del del
100 "$@"
877 __dscp_capture_add_del
()
879 local add_del
=$1; shift
884 for prio
in {0.
.7}; do
885 dscp
=$
((base
+ prio
))
886 __icmp_capture_add_del
$add_del $
((dscp
+ 100)) "" $dev \
887 "skip_hw ip_tos $((dscp << 2))"
891 dscp_capture_install
()
896 __dscp_capture_add_del add
$dev $base
899 dscp_capture_uninstall
()
904 __dscp_capture_add_del del
$dev $base
912 for prio
in {0.
.7}; do
913 local dscp
=$
((base
+ prio
))
914 local t
=$
(tc_rule_stats_get
$dev $
((dscp
+ 100)))
919 matchall_sink_create
()
923 tc qdisc add dev
$dev clsact
924 tc filter add dev
$dev ingress \
934 for current_test
in ${TESTS:-$ALL_TESTS}; do
944 local packets_rp12
=$4
945 local packets_rp13
=$5
946 local weights_ratio packets_ratio
diff
950 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
951 weights_ratio
=$
(echo "scale=2; $weight_rp12 / $weight_rp13" \
954 weights_ratio
=$
(echo "scale=2; $weight_rp13 / $weight_rp12" \
958 if [[ "$packets_rp12" -eq "0" ||
"$packets_rp13" -eq "0" ]]; then
959 check_err
1 "Packet difference is 0"
961 log_info
"Expected ratio $weights_ratio"
965 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
966 packets_ratio
=$
(echo "scale=2; $packets_rp12 / $packets_rp13" \
969 packets_ratio
=$
(echo "scale=2; $packets_rp13 / $packets_rp12" \
973 diff=$
(echo $weights_ratio - $packets_ratio |
bc -l)
976 test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
977 check_err $?
"Too large discrepancy between expected and measured ratios"
979 log_info
"Expected ratio $weights_ratio Measured ratio $packets_ratio"
986 ip netns
exec $name bash
<<-EOF
989 $(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
993 ##############################################################################
1003 vrf_name
=$
(master_name_get
$if_name)
1004 ip vrf
exec $vrf_name \
1005 $PING $args $dip -c 10 -i 0.1 -w $PING_TIMEOUT &> /dev
/null
1024 vrf_name
=$
(master_name_get
$if_name)
1025 ip vrf
exec $vrf_name \
1026 $PING6 $args $dip -c 10 -i 0.1 -w $PING_TIMEOUT &> /dev
/null
1041 local br_port1
=$2 # Connected to `host1_if`.
1044 local mac
=de
:ad
:be
:ef
:13:37
1049 bridge
-j fdb show br
$bridge brport
$br_port1 \
1050 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1051 check_fail $?
"Found FDB record when should not"
1053 # Disable unknown unicast flooding on `br_port1` to make sure
1054 # packets are only forwarded through the port after a matching
1055 # FDB entry was installed.
1056 bridge link
set dev
$br_port1 flood off
1058 tc qdisc add dev
$host1_if ingress
1059 tc filter add dev
$host1_if ingress protocol ip pref
1 handle
101 \
1060 flower dst_mac
$mac action drop
1062 $MZ $host2_if -c 1 -p 64 -b $mac -t ip
-q
1065 tc
-j -s filter show dev
$host1_if ingress \
1066 | jq
-e ".[] | select(.options.handle == 101) \
1067 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1068 check_fail $?
"Packet reached second host when should not"
1070 $MZ $host1_if -c 1 -p 64 -a $mac -t ip
-q
1073 bridge
-j fdb show br
$bridge brport
$br_port1 \
1074 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1075 check_err $?
"Did not find FDB record when should"
1077 $MZ $host2_if -c 1 -p 64 -b $mac -t ip
-q
1080 tc
-j -s filter show dev
$host1_if ingress \
1081 | jq
-e ".[] | select(.options.handle == 101) \
1082 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1083 check_err $?
"Packet did not reach second host when should"
1085 # Wait for 10 seconds after the ageing time to make sure FDB
1086 # record was aged-out.
1087 ageing_time
=$
(bridge_ageing_time_get
$bridge)
1088 sleep $
((ageing_time
+ 10))
1090 bridge
-j fdb show br
$bridge brport
$br_port1 \
1091 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1092 check_fail $?
"Found FDB record when should not"
1094 bridge link
set dev
$br_port1 learning off
1096 $MZ $host1_if -c 1 -p 64 -a $mac -t ip
-q
1099 bridge
-j fdb show br
$bridge brport
$br_port1 \
1100 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1101 check_fail $?
"Found FDB record when should not"
1103 bridge link
set dev
$br_port1 learning on
1105 tc filter del dev
$host1_if ingress protocol ip pref
1 handle
101 flower
1106 tc qdisc del dev
$host1_if ingress
1108 bridge link
set dev
$br_port1 flood on
1110 log_test
"FDB learning"
1115 local should_flood
=$1
1122 # Add an ACL on `host2_if` which will tell us whether the packet
1123 # was flooded to it or not.
1124 tc qdisc add dev
$host2_if ingress
1125 tc filter add dev
$host2_if ingress protocol ip pref
1 handle
101 \
1126 flower dst_mac
$mac action drop
1128 $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip
-q
1131 tc
-j -s filter show dev
$host2_if ingress \
1132 | jq
-e ".[] | select(.options.handle == 101) \
1133 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1134 if [[ $?
-ne 0 && $should_flood == "true" || \
1135 $?
-eq 0 && $should_flood == "false" ]]; then
1139 tc filter del dev
$host2_if ingress protocol ip pref
1 handle
101 flower
1140 tc qdisc del dev
$host2_if ingress
1145 flood_unicast_test
()
1150 local mac
=de
:ad
:be
:ef
:13:37
1151 local ip
=192.0.2.100
1155 bridge link
set dev
$br_port flood off
1157 flood_test_do false
$mac $ip $host1_if $host2_if
1158 check_err $?
"Packet flooded when should not"
1160 bridge link
set dev
$br_port flood on
1162 flood_test_do true
$mac $ip $host1_if $host2_if
1163 check_err $?
"Packet was not flooded when should"
1165 log_test
"Unknown unicast flood"
1168 flood_multicast_test
()
1173 local mac
=01:00:5e
:00:00:01
1178 bridge link
set dev
$br_port mcast_flood off
1180 flood_test_do false
$mac $ip $host1_if $host2_if
1181 check_err $?
"Packet flooded when should not"
1183 bridge link
set dev
$br_port mcast_flood on
1185 flood_test_do true
$mac $ip $host1_if $host2_if
1186 check_err $?
"Packet was not flooded when should"
1188 log_test
"Unregistered multicast flood"
1193 # `br_port` is connected to `host2_if`
1198 flood_unicast_test
$br_port $host1_if $host2_if
1199 flood_multicast_test
$br_port $host1_if $host2_if
1204 local proto
=$1; shift
1205 local h_in
=$1; shift # Where the traffic egresses the host
1208 local dmac
=$1; shift
1210 $MZ $h_in -p 8000 -A $sip -B $dip -c 0 \
1211 -a own
-b $dmac -t "$proto" -q "$@" &
1217 __start_traffic udp
"$@"
1222 __start_traffic tcp
"$@"
1227 # Suppress noise from killing mausezahn.
1228 { kill %% && wait %%; } 2>/dev
/null
1233 local if_name
=$1; shift
1242 ns_cmd
="ip netns exec ${ns}"
1245 if [ -z $SUDO_USER ] ; then
1248 capuser
="-Z $SUDO_USER"
1251 $ns_cmd tcpdump
-e -n -Q in -i $if_name \
1252 -s 65535 -B 32768 $capuser -w $capfile > "$capout" 2>&1 &
1260 $ns_cmd kill $cappid
1271 tcpdump
-e -n -r $capfile 2>&1
1274 # return 0 if the packet wasn't seen on host2_if or 1 if it was
1286 # basic check to see if we were passed an IPv4 address, if not assume IPv6
1287 if [[ ! $ip =~ ^
[0-9]{1,3}\.
[0-9]{1,3}\.
[0-9]{1,3}\.
[0-9]{1,3}$
]]; then
1292 # Add an ACL on `host2_if` which will tell us whether the packet
1293 # was received by it or not.
1294 tc qdisc add dev
$host2_if ingress
1295 tc filter add dev
$host2_if ingress protocol
$tc_proto pref
1 handle
101 \
1296 flower ip_proto udp dst_mac
$mac action drop
1298 $MZ $host1_if $mz_v6arg -c 1 -p 64 -b $mac -A $src_ip -B $ip -t udp
"dp=4096,sp=2048" -q
1301 tc
-j -s filter show dev
$host2_if ingress \
1302 | jq
-e ".[] | select(.options.handle == 101) \
1303 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1304 if [[ $?
-eq 0 ]]; then
1308 tc filter del dev
$host2_if ingress protocol
$tc_proto pref
1 handle
101 flower
1309 tc qdisc del dev
$host2_if ingress
1314 brmcast_check_sg_entries
()
1316 local report
=$1; shift
1320 for src
in "${slist[@]}"; do
1321 sarg
="${sarg} and .source_list[].address == \"$src\""
1323 bridge
-j -d -s mdb show dev br0 \
1324 | jq
-e ".[].mdb[] | \
1325 select(.grp == \"$TEST_GROUP\" and .source_list != null $sarg)" &>/dev
/null
1326 check_err $?
"Wrong *,G entry source list after $report report"
1328 for sgent
in "${slist[@]}"; do
1329 bridge
-j -d -s mdb show dev br0 \
1330 | jq
-e ".[].mdb[] | \
1331 select(.grp == \"$TEST_GROUP\" and .src == \"$sgent\")" &>/dev
/null
1332 check_err $?
"Missing S,G entry ($sgent, $TEST_GROUP)"
1336 brmcast_check_sg_fwding
()
1338 local should_fwd
=$1; shift
1339 local sources
=("$@")
1341 for src
in "${sources[@]}"; do
1344 mcast_packet_test
$TEST_GROUP_MAC $src $TEST_GROUP $h2 $h1
1346 if [ $should_fwd -eq 1 ]; then
1347 check_fail
$retval "Didn't forward traffic from S,G ($src, $TEST_GROUP)"
1349 check_err
$retval "Forwarded traffic for blocked S,G ($src, $TEST_GROUP)"
1354 brmcast_check_sg_state
()
1356 local is_blocked
=$1; shift
1357 local sources
=("$@")
1360 if [ $is_blocked -eq 1 ]; then
1364 for src
in "${sources[@]}"; do
1365 bridge
-j -d -s mdb show dev br0 \
1366 | jq
-e ".[].mdb[] | \
1367 select(.grp == \"$TEST_GROUP\" and .source_list != null) |
1369 select(.address == \"$src\") |
1370 select(.timer == \"0.00\")" &>/dev
/null
1371 check_err_fail
$should_fail $?
"Entry $src has zero timer"
1373 bridge
-j -d -s mdb show dev br0 \
1374 | jq
-e ".[].mdb[] | \
1375 select(.grp == \"$TEST_GROUP\" and .src == \"$src\" and \
1376 .flags[] == \"blocked\")" &>/dev
/null
1377 check_err_fail
$should_fail $?
"Entry $src has blocked flag"