2 # SPDX-License-Identifier: GPL-2.0
4 ##############################################################################
7 # Kselftest framework requirement - SKIP code is 4.
10 # Can be overridden by the configuration file.
14 ARPING=${ARPING:=arping}
16 WAIT_TIME=${WAIT_TIME:=5}
17 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
18 PAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
19 NETIF_TYPE=${NETIF_TYPE:=veth}
20 NETIF_CREATE=${NETIF_CREATE:=yes}
22 MC_CLI=${MC_CLI:=smcroutectl}
23 PING_COUNT=${PING_COUNT:=10}
24 PING_TIMEOUT=${PING_TIMEOUT:=5}
25 WAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
26 INTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600}
27 LOW_AGEING_TIME=${LOW_AGEING_TIME:=1000}
28 REQUIRE_JQ=${REQUIRE_JQ:=yes}
29 REQUIRE_MZ=${REQUIRE_MZ:=yes}
30 REQUIRE_MTOOLS=${REQUIRE_MTOOLS:=no}
31 STABLE_MAC_ADDRS=${STABLE_MAC_ADDRS:=no}
32 TCPDUMP_EXTRA_FLAGS=${TCPDUMP_EXTRA_FLAGS:=}
34 relative_path="${BASH_SOURCE%/*}"
35 if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
39 if [[ -f $relative_path/forwarding.config ]]; then
40 source "$relative_path/forwarding.config"
43 ##############################################################################
49 if [[ $? -ne 0 ]]; then
50 echo "SKIP: iproute2 too old; tc is missing JSON support"
55 # Old versions of tc don't understand "mpls_uc"
56 check_tc_mpls_support()
60 tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
61 matchall action pipe &> /dev/null
62 if [[ $? -ne 0 ]]; then
63 echo "SKIP: iproute2 too old; tc is missing MPLS support"
66 tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
70 # Old versions of tc produce invalid json output for mpls lse statistics
71 check_tc_mpls_lse_stats()
76 tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
77 flower mpls lse depth 2 \
78 action continue &> /dev/null
80 if [[ $? -ne 0 ]]; then
81 echo "SKIP: iproute2 too old; tc-flower is missing extended MPLS support"
85 tc -j filter show dev $dev ingress protocol mpls_uc | jq . &> /dev/null
87 tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
90 if [[ $ret -ne 0 ]]; then
91 echo "SKIP: iproute2 too old; tc-flower produces invalid json output for extended MPLS filters"
96 check_tc_shblock_support()
98 tc filter help 2>&1 | grep block &> /dev/null
99 if [[ $? -ne 0 ]]; then
100 echo "SKIP: iproute2 too old; tc is missing shared block support"
105 check_tc_chain_support()
107 tc help 2>&1|grep chain &> /dev/null
108 if [[ $? -ne 0 ]]; then
109 echo "SKIP: iproute2 too old; tc is missing chain support"
114 check_tc_action_hw_stats_support()
116 tc actions help 2>&1 | grep -q hw_stats
117 if [[ $? -ne 0 ]]; then
118 echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
123 check_ethtool_lanes_support()
125 ethtool --help 2>&1| grep lanes &> /dev/null
126 if [[ $? -ne 0 ]]; then
127 echo "SKIP: ethtool too old; it is missing lanes support"
132 check_locked_port_support()
134 if ! bridge -d link show | grep -q " locked"; then
135 echo "SKIP: iproute2 too old; Locked port feature not supported."
140 if [[ "$(id -u)" -ne 0 ]]; then
141 echo "SKIP: need root privileges"
145 if [[ "$CHECK_TC" = "yes" ]]; then
153 if [[ ! -x "$(command -v "$cmd")" ]]; then
154 echo "SKIP: $cmd not installed"
159 if [[ "$REQUIRE_JQ" = "yes" ]]; then
162 if [[ "$REQUIRE_MZ" = "yes" ]]; then
165 if [[ "$REQUIRE_MTOOLS" = "yes" ]]; then
166 # https://github.com/vladimiroltean/mtools/
167 # patched for IPv6 support
168 require_command msend
169 require_command mreceive
172 if [[ ! -v NUM_NETIFS ]]; then
173 echo "SKIP: importer does not define \"NUM_NETIFS\""
177 ##############################################################################
178 # Command line options handling
182 while [[ $# -gt 0 ]]; do
183 if [[ "$count" -eq "0" ]]; then
192 ##############################################################################
193 # Network interfaces configuration
199 for ((i = 1; i <= NUM_NETIFS; ++i)); do
202 ip link show dev ${NETIFS[p$i]} &> /dev/null
203 if [[ $? -ne 0 ]]; then
204 ip link add ${NETIFS[p$i]} type veth \
205 peer name ${NETIFS[p$j]}
206 if [[ $? -ne 0 ]]; then
207 echo "Failed to create netif"
217 case "$NETIF_TYPE" in
218 veth) create_netif_veth
220 *) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
226 declare -A MAC_ADDR_ORIG
232 for ((i = 1; i <= NUM_NETIFS; ++i)); do
234 new_addr=$(printf "00:01:02:03:04:%02x" $i)
236 MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
238 MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
239 ip link set dev $dev address $new_addr
247 for ((i = 1; i <= NUM_NETIFS; ++i)); do
249 ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
253 if [[ "$NETIF_CREATE" = "yes" ]]; then
257 if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
261 for ((i = 1; i <= NUM_NETIFS; ++i)); do
262 ip link show dev ${NETIFS[p$i]} &> /dev/null
263 if [[ $? -ne 0 ]]; then
264 echo "SKIP: could not find all required interfaces"
269 ##############################################################################
272 # Exit status to return at the end. Set in case one of the tests fails.
274 # Per-test return value. Clear at the beginning of each test.
282 if [[ $RET -eq 0 && $err -ne 0 ]]; then
293 if [[ $RET -eq 0 && $err -eq 0 ]]; then
301 local should_fail=$1; shift
305 if ((should_fail)); then
306 check_fail $err "$what succeeded, but should have failed"
308 check_err $err "$what failed"
317 if [[ $# -eq 2 ]]; then
321 if [[ $RET -ne 0 ]]; then
323 printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str"
324 if [[ ! -z "$retmsg" ]]; then
325 printf "\t%s\n" "$retmsg"
327 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
328 echo "Hit enter to continue, 'q' to quit"
330 [ "$a" = "q" ] && exit 1
335 printf "TEST: %-60s [ OK ]\n" "$test_name $opt_str"
344 printf "TEST: %-60s [SKIP]\n" "$test_name $opt_str"
357 local timeout=$1; shift
359 local start_time="$(date -u +%s%3N)"
370 local current_time="$(date -u +%s%3N)"
371 if ((current_time - start_time > timeout)); then
389 for cur in ${arr[@]}; do
390 if [[ $cur -gt $max ]]; then
404 if [ "$1" == "self" ] || [ "$1" == "master" ]; then
406 if [ "$1" == "-v" ]; then
411 $@ | grep $addr | grep $flag "$word"
416 "$@" | grep -q "Link detected: yes"
421 "$@" | grep -q offload
432 local current=$("$@")
438 busywait_for_counter()
440 local timeout=$1; shift
441 local delta=$1; shift
444 busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
450 local wait_time=${1:-$WAIT_TIME}; shift
452 setup_wait_dev_with_timeout "$dev" $INTERFACE_TIMEOUT $wait_time
456 log_test setup_wait_dev ": Interface $dev does not come up."
461 setup_wait_dev_with_timeout()
464 local max_iterations=${1:-$WAIT_TIMEOUT}; shift
465 local wait_time=${1:-$WAIT_TIME}; shift
468 for ((i = 1; i <= $max_iterations; ++i)); do
469 ip link show dev $dev up \
470 | grep 'state UP' &> /dev/null
471 if [[ $? -ne 0 ]]; then
484 local num_netifs=${1:-$NUM_NETIFS}
487 for ((i = 1; i <= num_netifs; ++i)); do
488 setup_wait_dev ${NETIFS[p$i]} 0
491 # Make sure links are ready.
504 # it the command fails, return error right away
506 if [[ $ret -ne 0 ]]; then
509 output=$(echo $output | jq -r $jq_opts "$jq_exp")
511 if [[ $ret -ne 0 ]]; then
515 # return success only in case of non-empty output
519 lldpad_app_wait_set()
523 while lldptool -t -i $dev -V APP -c app | grep -Eq "pending|unknown"; do
524 echo "$dev: waiting for lldpad to push pending APP updates"
529 lldpad_app_wait_del()
531 # Give lldpad a chance to push down the changes. If the device is downed
532 # too soon, the updates will be left pending. However, they will have
533 # been struck off the lldpad's DB already, so we won't be able to tell
534 # they are pending. Then on next test iteration this would cause
535 # weirdness as newly-added APP rules conflict with the old ones,
536 # sometimes getting stuck in an "unknown" state.
542 if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
543 echo "Pausing before cleanup, hit any key to continue"
547 if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
554 ip -4 rule add pref 32765 table local
555 ip -4 rule del pref 0
556 ip -6 rule add pref 32765 table local
557 ip -6 rule del pref 0
562 ip -6 rule add pref 0 table local
563 ip -6 rule del pref 32765
564 ip -4 rule add pref 0 table local
565 ip -4 rule del pref 32765
575 __last_tb_id=$((__last_tb_id + 1))
576 __TB_IDS[$vrf_name]=$__last_tb_id
584 return ${__TB_IDS[$vrf_name]}
592 __vrf_td_id_assign $vrf_name
595 ip link add dev $vrf_name type vrf table $tb_id
596 ip -4 route add table $tb_id unreachable default metric 4278198272
597 ip -6 route add table $tb_id unreachable default metric 4278198272
605 __vrf_td_id_lookup $vrf_name
608 ip -6 route del table $tb_id unreachable default metric 4278198272
609 ip -4 route del table $tb_id unreachable default metric 4278198272
610 ip link del dev $vrf_name
623 for addrstr in "${array[@]}"; do
624 ip address $add_del $addrstr dev $if_name
630 local if_name=$1; shift
631 local vrf_name=$1; shift
634 ip link set dev $if_name master $vrf_name
635 ip link set dev $if_name up
637 __addr_add_del $if_name add "${addrs[@]}"
642 local if_name=$1; shift
645 __addr_add_del $if_name del "${addrs[@]}"
647 ip link set dev $if_name down
648 ip link set dev $if_name nomaster
662 ip link set dev $vrf_name up
663 __simple_if_init $if_name $vrf_name "${array[@]}"
676 __simple_if_fini $if_name "${array[@]}"
677 vrf_destroy $vrf_name
684 local local=$1; shift
685 local remote=$1; shift
687 ip link add name $name type $type \
688 local $local remote $remote "$@"
689 ip link set dev $name up
696 ip link del dev $name
701 local if_name=$1; shift
705 local name=$if_name.$vid
707 ip link add name $name link $if_name type vlan id $vid
708 if [ "$vrf" != "" ]; then
709 ip link set dev $name master $vrf
711 ip link set dev $name up
712 __addr_add_del $name add "${ips[@]}"
717 local if_name=$1; shift
719 local name=$if_name.$vid
721 ip link del dev $name
726 local if_name=$1; shift
729 require_command $TEAMD
730 $TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
731 for slave in "$@"; do
732 ip link set dev $slave down
733 ip link set dev $slave master $if_name
734 ip link set dev $slave up
736 ip link set dev $if_name up
741 local if_name=$1; shift
743 $TEAMD -t $if_name -k
750 ip -j link show dev $if_name | jq -r '.[]["master"]'
755 local if_name=$1; shift
759 ip -j -s link show dev $if_name \
760 | jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
763 link_stats_tx_packets_get()
765 link_stats_get $1 tx packets
768 link_stats_rx_errors_get()
770 link_stats_get $1 rx errors
778 local selector=${1:-.packets}; shift
780 tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
781 | jq ".[1].options.actions[].stats$selector"
784 tc_rule_handle_stats_get()
787 local handle=$1; shift
788 local selector=${1:-.packets}; shift
790 tc -j -s filter show $id \
791 | jq ".[] | select(.options.handle == $handle) | \
792 .options.actions[0].stats$selector"
800 ethtool -S $dev | grep "^ *$stat:" | head -n 1 | cut -d: -f2
806 local handle=$1; shift
807 local selector=$1; shift
809 tc -j -s qdisc show dev "$dev" \
810 | jq '.[] | select(.handle == "'"$handle"'") | '"$selector"
813 qdisc_parent_stats_get()
816 local parent=$1; shift
817 local selector=$1; shift
819 tc -j -s qdisc show dev "$dev" invisible \
820 | jq '.[] | select(.parent == "'"$parent"'") | '"$selector"
828 cat /proc/net/dev_snmp6/$dev | grep "^$stat" | cut -f2
833 local suite=$1; shift
834 local if_name=$1; shift
838 ip -j stats show dev $if_name group offload subgroup $suite |
839 jq ".[0].stats64.$dir.$stat"
844 local speed=$1; shift
846 for unit in bps Kbps Mbps Gbps; do
847 if (($(echo "$speed < 1024" | bc))); then
851 speed=$(echo "scale=1; $speed / 1024" | bc)
861 local interval=$1; shift
863 echo $((8 * (t1 - t0) / interval))
870 local interval=$1; shift
872 echo $(((t1 - t0) / interval))
879 ip -j link show dev $if_name | jq -r '.[]["address"]'
886 ip -j addr show dev $if_name | \
887 jq -r '.[]["addr_info"][] | select(.scope == "link").local' | \
891 bridge_ageing_time_get()
896 # Need to divide by 100 to convert to seconds.
897 ageing_time=$(ip -j -d link show dev $bridge \
898 | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
899 echo $((ageing_time / 100))
902 declare -A SYSCTL_ORIG
906 local value=$1; shift
908 SYSCTL_ORIG[$key]=$(sysctl -n $key)
909 sysctl -qw $key=$value
916 sysctl -qw $key=${SYSCTL_ORIG["$key"]}
921 sysctl_set net.ipv4.conf.all.forwarding 1
922 sysctl_set net.ipv6.conf.all.forwarding 1
927 sysctl_restore net.ipv6.conf.all.forwarding
928 sysctl_restore net.ipv4.conf.all.forwarding
937 MTU_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].mtu')
938 ip link set dev $dev mtu $mtu
945 ip link set dev $dev mtu ${MTU_ORIG["$dev"]}
950 local num_netifs=${1:-$NUM_NETIFS}
952 for ((i = 1; i <= num_netifs; ++i)); do
953 ethtool -k ${NETIFS[p$i]} \
954 | grep "hw-tc-offload: on" &> /dev/null
955 if [[ $? -ne 0 ]]; then
966 local direction=$1; shift
968 # Some devices may not support or need in-hardware trapping of traffic
969 # (e.g. the veth pairs that this library creates for non-existent
970 # loopbacks). Use continue instead, so that there is a filter in there
971 # (some tests check counters), and so that other filters are still
973 tc filter add dev $dev $direction pref 1 \
974 flower skip_sw action trap 2>/dev/null \
975 || tc filter add dev $dev $direction pref 1 \
976 flower action continue
982 local direction=$1; shift
984 tc filter del dev $dev $direction pref 1 flower
987 slow_path_trap_install()
989 # For slow-path testing, we need to install a trap to get to
990 # slow path the packets that would otherwise be switched in HW.
991 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
996 slow_path_trap_uninstall()
998 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
1003 __icmp_capture_add_del()
1005 local add_del=$1; shift
1006 local pref=$1; shift
1007 local vsuf=$1; shift
1008 local tundev=$1; shift
1009 local filter=$1; shift
1011 tc filter $add_del dev "$tundev" ingress \
1012 proto ip$vsuf pref $pref \
1013 flower ip_proto icmp$vsuf $filter \
1017 icmp_capture_install()
1019 __icmp_capture_add_del add 100 "" "$@"
1022 icmp_capture_uninstall()
1024 __icmp_capture_add_del del 100 "" "$@"
1027 icmp6_capture_install()
1029 __icmp_capture_add_del add 100 v6 "$@"
1032 icmp6_capture_uninstall()
1034 __icmp_capture_add_del del 100 v6 "$@"
1037 __vlan_capture_add_del()
1039 local add_del=$1; shift
1040 local pref=$1; shift
1042 local filter=$1; shift
1044 tc filter $add_del dev "$dev" ingress \
1045 proto 802.1q pref $pref \
1050 vlan_capture_install()
1052 __vlan_capture_add_del add 100 "$@"
1055 vlan_capture_uninstall()
1057 __vlan_capture_add_del del 100 "$@"
1060 __dscp_capture_add_del()
1062 local add_del=$1; shift
1064 local base=$1; shift
1067 for prio in {0..7}; do
1068 dscp=$((base + prio))
1069 __icmp_capture_add_del $add_del $((dscp + 100)) "" $dev \
1070 "skip_hw ip_tos $((dscp << 2))"
1074 dscp_capture_install()
1077 local base=$1; shift
1079 __dscp_capture_add_del add $dev $base
1082 dscp_capture_uninstall()
1085 local base=$1; shift
1087 __dscp_capture_add_del del $dev $base
1093 local base=$1; shift
1095 for prio in {0..7}; do
1096 local dscp=$((base + prio))
1097 local t=$(tc_rule_stats_get $dev $((dscp + 100)))
1102 matchall_sink_create()
1106 tc qdisc add dev $dev clsact
1107 tc filter add dev $dev ingress \
1117 for current_test in ${TESTS:-$ALL_TESTS}; do
1125 local weight_rp12=$2
1126 local weight_rp13=$3
1127 local packets_rp12=$4
1128 local packets_rp13=$5
1129 local weights_ratio packets_ratio diff
1133 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1134 weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
1137 weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
1141 if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
1142 check_err 1 "Packet difference is 0"
1143 log_test "Multipath"
1144 log_info "Expected ratio $weights_ratio"
1148 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1149 packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
1152 packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
1156 diff=$(echo $weights_ratio - $packets_ratio | bc -l)
1159 test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
1160 check_err $? "Too large discrepancy between expected and measured ratios"
1162 log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
1167 local name=$1; shift
1169 ip netns exec $name bash <<-EOF
1172 $(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
1176 ##############################################################################
1186 vrf_name=$(master_name_get $if_name)
1187 ip vrf exec $vrf_name \
1188 $PING $args $dip -c $PING_COUNT -i 0.1 \
1189 -w $PING_TIMEOUT &> /dev/null
1208 vrf_name=$(master_name_get $if_name)
1209 ip vrf exec $vrf_name \
1210 $PING6 $args $dip -c $PING_COUNT -i 0.1 \
1211 -w $PING_TIMEOUT &> /dev/null
1226 local br_port1=$2 # Connected to `host1_if`.
1229 local mac=de:ad:be:ef:13:37
1234 bridge -j fdb show br $bridge brport $br_port1 \
1235 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1236 check_fail $? "Found FDB record when should not"
1238 # Disable unknown unicast flooding on `br_port1` to make sure
1239 # packets are only forwarded through the port after a matching
1240 # FDB entry was installed.
1241 bridge link set dev $br_port1 flood off
1243 tc qdisc add dev $host1_if ingress
1244 tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
1245 flower dst_mac $mac action drop
1247 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
1250 tc -j -s filter show dev $host1_if ingress \
1251 | jq -e ".[] | select(.options.handle == 101) \
1252 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1253 check_fail $? "Packet reached second host when should not"
1255 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
1258 bridge -j fdb show br $bridge brport $br_port1 \
1259 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1260 check_err $? "Did not find FDB record when should"
1262 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
1265 tc -j -s filter show dev $host1_if ingress \
1266 | jq -e ".[] | select(.options.handle == 101) \
1267 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1268 check_err $? "Packet did not reach second host when should"
1270 # Wait for 10 seconds after the ageing time to make sure FDB
1271 # record was aged-out.
1272 ageing_time=$(bridge_ageing_time_get $bridge)
1273 sleep $((ageing_time + 10))
1275 bridge -j fdb show br $bridge brport $br_port1 \
1276 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1277 check_fail $? "Found FDB record when should not"
1279 bridge link set dev $br_port1 learning off
1281 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
1284 bridge -j fdb show br $bridge brport $br_port1 \
1285 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1286 check_fail $? "Found FDB record when should not"
1288 bridge link set dev $br_port1 learning on
1290 tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
1291 tc qdisc del dev $host1_if ingress
1293 bridge link set dev $br_port1 flood on
1295 log_test "FDB learning"
1300 local should_flood=$1
1307 # Add an ACL on `host2_if` which will tell us whether the packet
1308 # was flooded to it or not.
1309 tc qdisc add dev $host2_if ingress
1310 tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
1311 flower dst_mac $mac action drop
1313 $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
1316 tc -j -s filter show dev $host2_if ingress \
1317 | jq -e ".[] | select(.options.handle == 101) \
1318 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1319 if [[ $? -ne 0 && $should_flood == "true" || \
1320 $? -eq 0 && $should_flood == "false" ]]; then
1324 tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
1325 tc qdisc del dev $host2_if ingress
1330 flood_unicast_test()
1335 local mac=de:ad:be:ef:13:37
1336 local ip=192.0.2.100
1340 bridge link set dev $br_port flood off
1342 flood_test_do false $mac $ip $host1_if $host2_if
1343 check_err $? "Packet flooded when should not"
1345 bridge link set dev $br_port flood on
1347 flood_test_do true $mac $ip $host1_if $host2_if
1348 check_err $? "Packet was not flooded when should"
1350 log_test "Unknown unicast flood"
1353 flood_multicast_test()
1358 local mac=01:00:5e:00:00:01
1363 bridge link set dev $br_port mcast_flood off
1365 flood_test_do false $mac $ip $host1_if $host2_if
1366 check_err $? "Packet flooded when should not"
1368 bridge link set dev $br_port mcast_flood on
1370 flood_test_do true $mac $ip $host1_if $host2_if
1371 check_err $? "Packet was not flooded when should"
1373 log_test "Unregistered multicast flood"
1378 # `br_port` is connected to `host2_if`
1383 flood_unicast_test $br_port $host1_if $host2_if
1384 flood_multicast_test $br_port $host1_if $host2_if
1389 local pktsize=$1; shift
1390 local proto=$1; shift
1391 local h_in=$1; shift # Where the traffic egresses the host
1394 local dmac=$1; shift
1396 $MZ $h_in -p $pktsize -A $sip -B $dip -c 0 \
1397 -a own -b $dmac -t "$proto" -q "$@" &
1401 start_traffic_pktsize()
1403 local pktsize=$1; shift
1405 __start_traffic $pktsize udp "$@"
1408 start_tcp_traffic_pktsize()
1410 local pktsize=$1; shift
1412 __start_traffic $pktsize tcp "$@"
1417 start_traffic_pktsize 8000 "$@"
1422 start_tcp_traffic_pktsize 8000 "$@"
1427 # Suppress noise from killing mausezahn.
1428 { kill %% && wait %%; } 2>/dev/null
1437 local if_name=$1; shift
1440 capfile[$if_name]=$(mktemp)
1441 capout[$if_name]=$(mktemp)
1446 ns_cmd="ip netns exec ${ns}"
1449 if [ -z $SUDO_USER ] ; then
1452 capuser="-Z $SUDO_USER"
1455 $ns_cmd tcpdump $TCPDUMP_EXTRA_FLAGS -e -n -Q in -i $if_name \
1456 -s 65535 -B 32768 $capuser -w ${capfile[$if_name]} \
1457 > "${capout[$if_name]}" 2>&1 &
1466 local pid=${cappid[$if_name]}
1468 $ns_cmd kill "$pid" && wait "$pid"
1476 rm ${capfile[$if_name]} ${capout[$if_name]}
1483 tcpdump -e -n -r ${capfile[$if_name]} 2>&1
1486 # return 0 if the packet wasn't seen on host2_if or 1 if it was
1498 # basic check to see if we were passed an IPv4 address, if not assume IPv6
1499 if [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
1504 # Add an ACL on `host2_if` which will tell us whether the packet
1505 # was received by it or not.
1506 tc qdisc add dev $host2_if ingress
1507 tc filter add dev $host2_if ingress protocol $tc_proto pref 1 handle 101 \
1508 flower ip_proto udp dst_mac $mac action drop
1510 $MZ $host1_if $mz_v6arg -c 1 -p 64 -b $mac -A $src_ip -B $ip -t udp "dp=4096,sp=2048" -q
1513 tc -j -s filter show dev $host2_if ingress \
1514 | jq -e ".[] | select(.options.handle == 101) \
1515 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1516 if [[ $? -eq 0 ]]; then
1520 tc filter del dev $host2_if ingress protocol $tc_proto pref 1 handle 101 flower
1521 tc qdisc del dev $host2_if ingress
1526 brmcast_check_sg_entries()
1528 local report=$1; shift
1532 for src in "${slist[@]}"; do
1533 sarg="${sarg} and .source_list[].address == \"$src\""
1535 bridge -j -d -s mdb show dev br0 \
1536 | jq -e ".[].mdb[] | \
1537 select(.grp == \"$TEST_GROUP\" and .source_list != null $sarg)" &>/dev/null
1538 check_err $? "Wrong *,G entry source list after $report report"
1540 for sgent in "${slist[@]}"; do
1541 bridge -j -d -s mdb show dev br0 \
1542 | jq -e ".[].mdb[] | \
1543 select(.grp == \"$TEST_GROUP\" and .src == \"$sgent\")" &>/dev/null
1544 check_err $? "Missing S,G entry ($sgent, $TEST_GROUP)"
1548 brmcast_check_sg_fwding()
1550 local should_fwd=$1; shift
1551 local sources=("$@")
1553 for src in "${sources[@]}"; do
1556 mcast_packet_test $TEST_GROUP_MAC $src $TEST_GROUP $h2 $h1
1558 if [ $should_fwd -eq 1 ]; then
1559 check_fail $retval "Didn't forward traffic from S,G ($src, $TEST_GROUP)"
1561 check_err $retval "Forwarded traffic for blocked S,G ($src, $TEST_GROUP)"
1566 brmcast_check_sg_state()
1568 local is_blocked=$1; shift
1569 local sources=("$@")
1572 if [ $is_blocked -eq 1 ]; then
1576 for src in "${sources[@]}"; do
1577 bridge -j -d -s mdb show dev br0 \
1578 | jq -e ".[].mdb[] | \
1579 select(.grp == \"$TEST_GROUP\" and .source_list != null) |
1581 select(.address == \"$src\") |
1582 select(.timer == \"0.00\")" &>/dev/null
1583 check_err_fail $should_fail $? "Entry $src has zero timer"
1585 bridge -j -d -s mdb show dev br0 \
1586 | jq -e ".[].mdb[] | \
1587 select(.grp == \"$TEST_GROUP\" and .src == \"$src\" and \
1588 .flags[] == \"blocked\")" &>/dev/null
1589 check_err_fail $should_fail $? "Entry $src has blocked flag"
1597 local vrf_name=$(master_name_get $if_name)
1599 # We don't care about actual reception, just about joining the
1600 # IP multicast group and adding the L2 address to the device's
1601 # MAC filtering table
1602 ip vrf exec $vrf_name \
1603 mreceive -g $group -I $if_name > /dev/null 2>&1 &
1611 kill "$mreceive_pid" && wait "$mreceive_pid"
1618 local vrf_name=$(master_name_get $if_name)
1620 ip vrf exec $vrf_name \
1621 msend -g $groups -I $if_name -c 1 > /dev/null 2>&1
1626 local mtype=$1; shift
1627 local ip=${1-ip}; shift
1629 # start the monitor in the background
1630 tmpfile=`mktemp /var/run/nexthoptestXXX`
1631 mpid=`($ip monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
1633 echo "$mpid $tmpfile"
1638 local mpid=$1; shift
1639 local tmpfile=$1; shift
1641 local what=$1; shift
1645 local lines=`grep '^\w' $tmpfile | wc -l`
1647 check_err $? "$what: $lines lines of events, expected $el"
1651 hw_stats_monitor_test()
1654 local type=$1; shift
1655 local make_suitable=$1; shift
1656 local make_unsuitable=$1; shift
1657 local ip=${1-ip}; shift
1661 # Expect a notification about enablement.
1662 local ipmout=$(start_ip_monitor stats "$ip")
1663 $ip stats set dev $dev ${type}_stats on
1664 stop_ip_monitor $ipmout 1 "${type}_stats enablement"
1666 # Expect a notification about offload.
1667 local ipmout=$(start_ip_monitor stats "$ip")
1669 stop_ip_monitor $ipmout 1 "${type}_stats installation"
1671 # Expect a notification about loss of offload.
1672 local ipmout=$(start_ip_monitor stats "$ip")
1674 stop_ip_monitor $ipmout 1 "${type}_stats deinstallation"
1676 # Expect a notification about disablement
1677 local ipmout=$(start_ip_monitor stats "$ip")
1678 $ip stats set dev $dev ${type}_stats off
1679 stop_ip_monitor $ipmout 1 "${type}_stats disablement"
1681 log_test "${type}_stats notifications"