2 # SPDX-License-Identifier: GPL-2.0
4 ##############################################################################
5 # Topology description. p1 looped back to p2, p3 to p4 and so on.
20 # Port that does not have a cable connected.
21 : "${NETIF_NO_CABLE:=eth8}"
23 ##############################################################################
26 # Networking utilities.
28 : "${PING6:=ping6}" # Some distros just use ping.
30 : "${TROUTE6:=traceroute6}"
33 : "${MZ:=mausezahn}" # Some distributions use 'mz'.
36 # Host configuration tools.
39 : "${MC_CLI:=smcroutectl}"
41 # Constants for netdevice bring-up:
42 # Default time in seconds to wait for an interface to come up before giving up
43 # and bailing out. Used during initial setup.
44 : "${INTERFACE_TIMEOUT:=600}"
45 # Like INTERFACE_TIMEOUT, but default for ad-hoc waiting in testing scripts.
46 : "${WAIT_TIMEOUT:=20}"
47 # Time to wait after interfaces participating in the test are all UP.
50 # Whether to pause on, respectively, after a failure and before cleanup.
51 : "${PAUSE_ON_CLEANUP:=no}"
53 # Whether to create virtual interfaces, and what netdevice type they should be.
54 : "${NETIF_CREATE:=yes}"
55 : "${NETIF_TYPE:=veth}"
57 # Constants for ping tests:
58 # How many packets should be sent.
60 # Timeout (in seconds) before ping exits regardless of how many packets have
61 # been sent or received
62 : "${PING_TIMEOUT:=5}"
64 # Minimum ageing_time (in centiseconds) supported by hardware
65 : "${LOW_AGEING_TIME:=1000}"
67 # Whether to check for availability of certain tools.
68 : "${REQUIRE_JQ:=yes}"
69 : "${REQUIRE_MZ:=yes}"
70 : "${REQUIRE_MTOOLS:=no}"
72 # Whether to override MAC addresses on interfaces participating in the test.
73 : "${STABLE_MAC_ADDRS:=no}"
76 : "${TCPDUMP_EXTRA_FLAGS:=}"
78 # Flags for TC filters.
79 : "${TC_FLAG:=skip_hw}"
81 # Whether the machine is "slow" -- i.e. might be incapable of running tests
82 # involving heavy traffic. This might be the case on a debug kernel, a VM, or
83 # e.g. a low-power board.
84 : "${KSFT_MACHINE_SLOW:=no}"
86 ##############################################################################
87 # Find netifs by test-specified driver name
92 local driver_path
="/sys/class/net/$dev/device/driver"
94 if [[ -L $driver_path ]]; then
95 basename `realpath $driver_path`
101 local ifnames
=`ip -j link show | jq -r ".[].ifname"`
104 for ifname
in $ifnames
106 local driver_name
=`driver_name_get $ifname`
107 if [[ ! -z $driver_name && $driver_name == $NETIF_FIND_DRIVER ]]; then
109 NETIFS
[p
$count]="$ifname"
114 # Whether to find netdevice according to the driver speficied by the importer
115 : "${NETIF_FIND_DRIVER:=}"
117 if [[ $NETIF_FIND_DRIVER ]]; then
123 net_forwarding_dir
=$
(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
125 if [[ -f $net_forwarding_dir/forwarding.config
]]; then
126 source "$net_forwarding_dir/forwarding.config"
129 source "$net_forwarding_dir/../lib.sh"
131 ##############################################################################
137 if [[ $?
-ne 0 ]]; then
138 echo "SKIP: iproute2 too old; tc is missing JSON support"
143 # Old versions of tc don't understand "mpls_uc"
144 check_tc_mpls_support
()
148 tc filter add dev
$dev ingress protocol mpls_uc pref
1 handle
1 \
149 matchall action pipe
&> /dev
/null
150 if [[ $?
-ne 0 ]]; then
151 echo "SKIP: iproute2 too old; tc is missing MPLS support"
154 tc filter del dev
$dev ingress protocol mpls_uc pref
1 handle
1 \
158 # Old versions of tc produce invalid json output for mpls lse statistics
159 check_tc_mpls_lse_stats
()
164 tc filter add dev
$dev ingress protocol mpls_uc pref
1 handle
1 \
165 flower mpls lse depth
2 \
166 action
continue &> /dev
/null
168 if [[ $?
-ne 0 ]]; then
169 echo "SKIP: iproute2 too old; tc-flower is missing extended MPLS support"
173 tc
-j filter show dev
$dev ingress protocol mpls_uc | jq .
&> /dev
/null
175 tc filter del dev
$dev ingress protocol mpls_uc pref
1 handle
1 \
178 if [[ $ret -ne 0 ]]; then
179 echo "SKIP: iproute2 too old; tc-flower produces invalid json output for extended MPLS filters"
184 check_tc_shblock_support
()
186 tc filter
help 2>&1 |
grep block
&> /dev
/null
187 if [[ $?
-ne 0 ]]; then
188 echo "SKIP: iproute2 too old; tc is missing shared block support"
193 check_tc_chain_support
()
195 tc
help 2>&1|
grep chain
&> /dev
/null
196 if [[ $?
-ne 0 ]]; then
197 echo "SKIP: iproute2 too old; tc is missing chain support"
202 check_tc_action_hw_stats_support
()
204 tc actions
help 2>&1 |
grep -q hw_stats
205 if [[ $?
-ne 0 ]]; then
206 echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
211 check_tc_fp_support
()
213 tc qdisc add dev lo mqprio
help 2>&1 |
grep -q "fp "
214 if [[ $?
-ne 0 ]]; then
215 echo "SKIP: iproute2 too old; tc is missing frame preemption support"
220 check_ethtool_lanes_support
()
222 ethtool
--help 2>&1|
grep lanes
&> /dev
/null
223 if [[ $?
-ne 0 ]]; then
224 echo "SKIP: ethtool too old; it is missing lanes support"
229 check_ethtool_mm_support
()
231 ethtool
--help 2>&1|
grep -- '--show-mm' &> /dev
/null
232 if [[ $?
-ne 0 ]]; then
233 echo "SKIP: ethtool too old; it is missing MAC Merge layer support"
238 check_ethtool_counter_group_support
()
240 ethtool
--help 2>&1|
grep -- '--all-groups' &> /dev
/null
241 if [[ $?
-ne 0 ]]; then
242 echo "SKIP: ethtool too old; it is missing standard counter group support"
247 check_ethtool_pmac_std_stats_support
()
252 [ 0 -ne $
(ethtool
--json -S $dev --all-groups --src pmac
2>/dev
/null \
253 | jq
".[].\"$grp\" | length") ]
256 check_locked_port_support
()
258 if ! bridge
-d link show |
grep -q " locked"; then
259 echo "SKIP: iproute2 too old; Locked port feature not supported."
264 check_port_mab_support
()
266 if ! bridge
-d link show |
grep -q "mab"; then
267 echo "SKIP: iproute2 too old; MacAuth feature not supported."
272 if [[ "$(id -u)" -ne 0 ]]; then
273 echo "SKIP: need root privileges"
280 local expected
=$1; shift
281 local driver_name
=`driver_name_get $dev`
283 if [[ $driver_name != $expected ]]; then
284 echo "SKIP: expected driver $expected for $dev, got $driver_name instead"
289 if [[ "$CHECK_TC" = "yes" ]]; then
297 if [[ ! -x "$(command -v "$cmd")" ]]; then
298 echo "SKIP: $cmd not installed"
303 # IPv6 support was added in v3.0
304 check_mtools_version
()
306 local version
="$(msend -v)"
309 version
=${version##msend version }
310 major
=$
(echo $version | cut
-d.
-f1)
312 if [ $major -lt 3 ]; then
313 echo "SKIP: expected mtools version 3.0, got $version"
318 if [[ "$REQUIRE_JQ" = "yes" ]]; then
321 if [[ "$REQUIRE_MZ" = "yes" ]]; then
324 if [[ "$REQUIRE_MTOOLS" = "yes" ]]; then
325 # https://github.com/troglobit/mtools
326 require_command msend
327 require_command mreceive
331 ##############################################################################
332 # Command line options handling
336 while [[ $# -gt 0 ]]; do
337 if [[ "$count" -eq "0" ]]; then
346 ##############################################################################
347 # Network interfaces configuration
349 if [[ ! -v NUM_NETIFS
]]; then
350 echo "SKIP: importer does not define \"NUM_NETIFS\""
354 if (( NUM_NETIFS
> ${#NETIFS[@]} )); then
355 echo "SKIP: Importer requires $NUM_NETIFS NETIFS, but only ${#NETIFS[@]} are defined (${NETIFS[@]})"
359 for i
in $
(seq ${#NETIFS[@]}); do
360 if [[ ! ${NETIFS[p$i]} ]]; then
361 echo "SKIP: NETIFS[p$i] not given"
370 for ((i
= 1; i
<= NUM_NETIFS
; ++i
)); do
373 if [ -z ${NETIFS[p$i]} ]; then
374 echo "SKIP: Cannot create interface. Name not specified"
378 ip link show dev
${NETIFS[p$i]} &> /dev
/null
379 if [[ $?
-ne 0 ]]; then
380 ip link add
${NETIFS[p$i]} type veth \
381 peer name
${NETIFS[p$j]}
382 if [[ $?
-ne 0 ]]; then
383 echo "Failed to create netif"
393 case "$NETIF_TYPE" in
394 veth
) create_netif_veth
396 *) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
402 declare -A MAC_ADDR_ORIG
408 for ((i
= 1; i
<= NUM_NETIFS
; ++i
)); do
410 new_addr
=$
(printf "00:01:02:03:04:%02x" $i)
412 MAC_ADDR_ORIG
["$dev"]=$
(ip
-j link show dev
$dev | jq
-e '.[].address')
414 MAC_ADDR_ORIG
["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
415 ip link
set dev
$dev address
$new_addr
423 for ((i
= 1; i
<= NUM_NETIFS
; ++i
)); do
425 ip link
set dev
$dev address
${MAC_ADDR_ORIG["$dev"]}
429 if [[ "$NETIF_CREATE" = "yes" ]]; then
433 if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
437 for ((i
= 1; i
<= NUM_NETIFS
; ++i
)); do
438 ip link show dev
${NETIFS[p$i]} &> /dev
/null
439 if [[ $?
-ne 0 ]]; then
440 echo "SKIP: could not find all required interfaces"
445 ##############################################################################
459 for cur
in ${arr[@]}; do
460 if [[ $cur -gt $max ]]; then
474 if [ "$1" == "self" ] ||
[ "$1" == "master" ]; then
476 if [ "$1" == "-v" ]; then
481 $@ |
grep $addr |
grep $flag "$word"
486 "$@" |
grep -q "Link detected: yes"
491 "$@" |
grep -q offload
502 local wait_time
=${1:-$WAIT_TIME}; shift
504 setup_wait_dev_with_timeout
"$dev" $INTERFACE_TIMEOUT $wait_time
508 log_test setup_wait_dev
": Interface $dev does not come up."
513 setup_wait_dev_with_timeout
()
516 local max_iterations
=${1:-$WAIT_TIMEOUT}; shift
517 local wait_time
=${1:-$WAIT_TIME}; shift
520 for ((i
= 1; i
<= $max_iterations; ++i
)); do
521 ip link show dev
$dev up \
522 |
grep 'state UP' &> /dev
/null
523 if [[ $?
-ne 0 ]]; then
536 local num_netifs
=${1:-$NUM_NETIFS}
539 for ((i
= 1; i
<= num_netifs
; ++i
)); do
540 setup_wait_dev
${NETIFS[p$i]} 0
543 # Make sure links are ready.
550 local timeout
=${1:-$WAIT_TIMEOUT}; shift
552 slowwait
$timeout ip link show dev
$dev &> /dev
/null
555 log_test wait_for_dev
"Interface $dev did not appear."
569 # it the command fails, return error right away
571 if [[ $ret -ne 0 ]]; then
574 output
=$
(echo $output | jq
-r $jq_opts "$jq_exp")
576 if [[ $ret -ne 0 ]]; then
580 # return success only in case of non-empty output
586 if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
587 echo "Pausing before cleanup, hit any key to continue"
591 if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
598 ip
-4 rule add pref
32765 table
local
599 ip
-4 rule del pref
0
600 ip
-6 rule add pref
32765 table
local
601 ip
-6 rule del pref
0
606 ip
-6 rule add pref
0 table
local
607 ip
-6 rule del pref
32765
608 ip
-4 rule add pref
0 table
local
609 ip
-4 rule del pref
32765
619 __last_tb_id
=$
((__last_tb_id
+ 1))
620 __TB_IDS
[$vrf_name]=$__last_tb_id
628 return ${__TB_IDS[$vrf_name]}
636 __vrf_td_id_assign
$vrf_name
639 ip link add dev
$vrf_name type vrf table
$tb_id
640 ip
-4 route add table
$tb_id unreachable default metric
4278198272
641 ip
-6 route add table
$tb_id unreachable default metric
4278198272
649 __vrf_td_id_lookup
$vrf_name
652 ip
-6 route del table
$tb_id unreachable default metric
4278198272
653 ip
-4 route del table
$tb_id unreachable default metric
4278198272
654 ip link del dev
$vrf_name
667 for addrstr
in "${array[@]}"; do
668 ip address
$add_del $addrstr dev
$if_name
674 local if_name
=$1; shift
675 local vrf_name
=$1; shift
678 ip link
set dev
$if_name master
$vrf_name
679 ip link
set dev
$if_name up
681 __addr_add_del
$if_name add
"${addrs[@]}"
686 local if_name
=$1; shift
689 __addr_add_del
$if_name del
"${addrs[@]}"
691 ip link
set dev
$if_name down
692 ip link
set dev
$if_name nomaster
706 ip link
set dev
$vrf_name up
707 __simple_if_init
$if_name $vrf_name "${array[@]}"
720 __simple_if_fini
$if_name "${array[@]}"
721 vrf_destroy
$vrf_name
728 local local=$1; shift
729 local remote
=$1; shift
731 ip link add name
$name type $type \
732 local $local remote
$remote "$@"
733 ip link
set dev
$name up
740 ip link del dev
$name
745 local if_name
=$1; shift
749 local name
=$if_name.
$vid
751 ip link add name
$name link
$if_name type vlan id
$vid
752 if [ "$vrf" != "" ]; then
753 ip link
set dev
$name master
$vrf
755 ip link
set dev
$name up
756 __addr_add_del
$name add
"${ips[@]}"
761 local if_name
=$1; shift
763 local name
=$if_name.
$vid
765 ip link del dev
$name
770 local if_name
=$1; shift
773 require_command
$TEAMD
774 $TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
775 for slave
in "$@"; do
776 ip link
set dev
$slave down
777 ip link
set dev
$slave master
$if_name
778 ip link
set dev
$slave up
780 ip link
set dev
$if_name up
785 local if_name
=$1; shift
787 $TEAMD -t $if_name -k
794 ip
-j link show dev
$if_name | jq
-r '.[]["master"]'
799 local if_name
=$1; shift
803 ip
-j -s link show dev
$if_name \
804 | jq
'.[]["stats64"]["'$dir'"]["'$stat'"]'
807 link_stats_tx_packets_get
()
809 link_stats_get
$1 tx packets
812 link_stats_rx_errors_get
()
814 link_stats_get
$1 rx errors
822 ethtool
-S $dev |
grep "^ *$stat:" |
head -n 1 | cut
-d: -f2
825 ethtool_std_stats_get
()
832 ethtool
--json -S $dev --groups $grp -- --src $src | \
833 jq
'.[]."'"$grp"'"."'$name'"'
839 local handle
=$1; shift
840 local selector
=$1; shift
842 tc
-j -s qdisc show dev
"$dev" \
843 | jq
'.[] | select(.handle == "'"$handle"'") | '"$selector"
846 qdisc_parent_stats_get
()
849 local parent
=$1; shift
850 local selector
=$1; shift
852 tc
-j -s qdisc show dev
"$dev" invisible \
853 | jq
'.[] | select(.parent == "'"$parent"'") | '"$selector"
861 cat /proc
/net
/dev_snmp
6/$dev |
grep "^$stat" | cut
-f2
866 local suite
=$1; shift
867 local if_name
=$1; shift
871 ip
-j stats show dev
$if_name group offload subgroup
$suite |
872 jq
".[0].stats64.$dir.$stat"
878 local group_id
=$1; shift
879 local member_id
=$1; shift
881 ip
-j -s -s nexthop show id
$group_id |
882 jq
--argjson member_id
"$member_id" --arg key
"$key" \
883 '.[].group_stats[] | select(.id == $member_id) | .[$key]'
888 local group_id
=$1; shift
889 local member_id
=$1; shift
891 __nh_stats_get packets
"$group_id" "$member_id"
896 local group_id
=$1; shift
897 local member_id
=$1; shift
899 __nh_stats_get packets_hw
"$group_id" "$member_id"
904 local speed
=$1; shift
906 for unit
in bps Kbps Mbps Gbps
; do
907 if (($
(echo "$speed < 1024" |
bc))); then
911 speed
=$
(echo "scale=1; $speed / 1024" |
bc)
921 local interval
=$1; shift
923 echo $
((8 * (t1
- t0
) / interval
))
930 local interval
=$1; shift
932 echo $
(((t1
- t0
) / interval
))
939 ip
-j link show dev
$if_name | jq
-r '.[]["address"]'
945 local order
="$((1 << 40))"
951 for byte
in $addr; do
953 val
=$
((val
+ order
* byte
))
954 order
=$
((order
>> 8))
966 for ((i
= 40; i
>= 0; i
-= 8)); do
967 byte
=$
(((val
& (0xff << i)) >> i))
969 if [ $i -ne 0 ]; then
979 ip
-j addr show dev
$if_name | \
980 jq
-r '.[]["addr_info"][] | select(.scope == "link").local' | \
984 bridge_ageing_time_get
()
989 # Need to divide by 100 to convert to seconds.
990 ageing_time
=$
(ip
-j -d link show dev
$bridge \
991 | jq
'.[]["linkinfo"]["info_data"]["ageing_time"]')
992 echo $
((ageing_time
/ 100))
995 declare -A SYSCTL_ORIG
1000 SYSCTL_ORIG
[$key]=$
(sysctl
-n $key)
1006 local value
=$1; shift
1009 sysctl
-qw $key="$value"
1016 sysctl
-qw $key="${SYSCTL_ORIG[$key]}"
1021 sysctl_set net.ipv4.conf.all.forwarding
1
1022 sysctl_set net.ipv6.conf.all.forwarding
1
1025 forwarding_restore
()
1027 sysctl_restore net.ipv6.conf.all.forwarding
1028 sysctl_restore net.ipv4.conf.all.forwarding
1037 MTU_ORIG
["$dev"]=$
(ip
-j link show dev
$dev | jq
-e '.[].mtu')
1038 ip link
set dev
$dev mtu
$mtu
1045 ip link
set dev
$dev mtu
${MTU_ORIG["$dev"]}
1050 local num_netifs
=${1:-$NUM_NETIFS}
1052 for ((i
= 1; i
<= num_netifs
; ++i
)); do
1053 ethtool
-k ${NETIFS[p$i]} \
1054 |
grep "hw-tc-offload: on" &> /dev
/null
1055 if [[ $?
-ne 0 ]]; then
1066 local direction
=$1; shift
1068 # Some devices may not support or need in-hardware trapping of traffic
1069 # (e.g. the veth pairs that this library creates for non-existent
1070 # loopbacks). Use continue instead, so that there is a filter in there
1071 # (some tests check counters), and so that other filters are still
1073 tc filter add dev
$dev $direction pref
1 \
1074 flower skip_sw action
trap 2>/dev
/null \
1075 || tc filter add dev
$dev $direction pref
1 \
1076 flower action
continue
1082 local direction
=$1; shift
1084 tc filter del dev
$dev $direction pref
1 flower
1087 __icmp_capture_add_del
()
1089 local add_del
=$1; shift
1090 local pref
=$1; shift
1091 local vsuf
=$1; shift
1092 local tundev
=$1; shift
1093 local filter
=$1; shift
1095 tc filter
$add_del dev
"$tundev" ingress \
1096 proto ip
$vsuf pref
$pref \
1097 flower ip_proto icmp
$vsuf $filter \
1101 icmp_capture_install
()
1103 local tundev
=$1; shift
1104 local filter
=$1; shift
1106 __icmp_capture_add_del add
100 "" "$tundev" "$filter"
1109 icmp_capture_uninstall
()
1111 local tundev
=$1; shift
1112 local filter
=$1; shift
1114 __icmp_capture_add_del del
100 "" "$tundev" "$filter"
1117 icmp6_capture_install
()
1119 local tundev
=$1; shift
1120 local filter
=$1; shift
1122 __icmp_capture_add_del add
100 v6
"$tundev" "$filter"
1125 icmp6_capture_uninstall
()
1127 local tundev
=$1; shift
1128 local filter
=$1; shift
1130 __icmp_capture_add_del del
100 v6
"$tundev" "$filter"
1133 __vlan_capture_add_del
()
1135 local add_del
=$1; shift
1136 local pref
=$1; shift
1138 local filter
=$1; shift
1140 tc filter
$add_del dev
"$dev" ingress \
1141 proto
802.1q pref
$pref \
1146 vlan_capture_install
()
1149 local filter
=$1; shift
1151 __vlan_capture_add_del add
100 "$dev" "$filter"
1154 vlan_capture_uninstall
()
1157 local filter
=$1; shift
1159 __vlan_capture_add_del del
100 "$dev" "$filter"
1162 __dscp_capture_add_del
()
1164 local add_del
=$1; shift
1166 local base
=$1; shift
1169 for prio
in {0.
.7}; do
1170 dscp
=$
((base
+ prio
))
1171 __icmp_capture_add_del
$add_del $
((dscp
+ 100)) "" $dev \
1172 "skip_hw ip_tos $((dscp << 2))"
1176 dscp_capture_install
()
1179 local base
=$1; shift
1181 __dscp_capture_add_del add
$dev $base
1184 dscp_capture_uninstall
()
1187 local base
=$1; shift
1189 __dscp_capture_add_del del
$dev $base
1195 local base
=$1; shift
1197 for prio
in {0.
.7}; do
1198 local dscp
=$
((base
+ prio
))
1199 local t
=$
(tc_rule_stats_get
$dev $
((dscp
+ 100)))
1204 matchall_sink_create
()
1208 tc qdisc add dev
$dev clsact
1209 tc filter add dev
$dev ingress \
1218 defer_scopes_cleanup
1224 local weight_rp12
=$2
1225 local weight_rp13
=$3
1226 local packets_rp12
=$4
1227 local packets_rp13
=$5
1228 local weights_ratio packets_ratio
diff
1232 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1233 weights_ratio
=$
(echo "scale=2; $weight_rp12 / $weight_rp13" \
1236 weights_ratio
=$
(echo "scale=2; $weight_rp13 / $weight_rp12" \
1240 if [[ "$packets_rp12" -eq "0" ||
"$packets_rp13" -eq "0" ]]; then
1241 check_err
1 "Packet difference is 0"
1242 log_test
"Multipath"
1243 log_info
"Expected ratio $weights_ratio"
1247 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1248 packets_ratio
=$
(echo "scale=2; $packets_rp12 / $packets_rp13" \
1251 packets_ratio
=$
(echo "scale=2; $packets_rp13 / $packets_rp12" \
1255 diff=$
(echo $weights_ratio - $packets_ratio |
bc -l)
1258 test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
1259 check_err $?
"Too large discrepancy between expected and measured ratios"
1261 log_info
"Expected ratio $weights_ratio Measured ratio $packets_ratio"
1266 local name
=$1; shift
1268 ip netns
exec $name bash
<<-EOF
1271 $(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
1275 ##############################################################################
1285 vrf_name
=$
(master_name_get
$if_name)
1286 ip vrf
exec $vrf_name \
1287 $PING $args $dip -c $PING_COUNT -i 0.1 \
1288 -w $PING_TIMEOUT &> /dev
/null
1306 log_test
"ping fails$3"
1316 vrf_name
=$
(master_name_get
$if_name)
1317 ip vrf
exec $vrf_name \
1318 $PING6 $args $dip -c $PING_COUNT -i 0.1 \
1319 -w $PING_TIMEOUT &> /dev
/null
1337 log_test
"ping6 fails$3"
1343 local br_port1
=$2 # Connected to `host1_if`.
1346 local mac
=de
:ad
:be
:ef
:13:37
1351 bridge
-j fdb show br
$bridge brport
$br_port1 \
1352 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1353 check_fail $?
"Found FDB record when should not"
1355 # Disable unknown unicast flooding on `br_port1` to make sure
1356 # packets are only forwarded through the port after a matching
1357 # FDB entry was installed.
1358 bridge link
set dev
$br_port1 flood off
1360 ip link
set $host1_if promisc on
1361 tc qdisc add dev
$host1_if ingress
1362 tc filter add dev
$host1_if ingress protocol ip pref
1 handle
101 \
1363 flower dst_mac
$mac action drop
1365 $MZ $host2_if -c 1 -p 64 -b $mac -t ip
-q
1368 tc
-j -s filter show dev
$host1_if ingress \
1369 | jq
-e ".[] | select(.options.handle == 101) \
1370 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1371 check_fail $?
"Packet reached first host when should not"
1373 $MZ $host1_if -c 1 -p 64 -a $mac -t ip
-q
1376 bridge
-j fdb show br
$bridge brport
$br_port1 \
1377 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1378 check_err $?
"Did not find FDB record when should"
1380 $MZ $host2_if -c 1 -p 64 -b $mac -t ip
-q
1383 tc
-j -s filter show dev
$host1_if ingress \
1384 | jq
-e ".[] | select(.options.handle == 101) \
1385 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1386 check_err $?
"Packet did not reach second host when should"
1388 # Wait for 10 seconds after the ageing time to make sure FDB
1389 # record was aged-out.
1390 ageing_time
=$
(bridge_ageing_time_get
$bridge)
1391 sleep $
((ageing_time
+ 10))
1393 bridge
-j fdb show br
$bridge brport
$br_port1 \
1394 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1395 check_fail $?
"Found FDB record when should not"
1397 bridge link
set dev
$br_port1 learning off
1399 $MZ $host1_if -c 1 -p 64 -a $mac -t ip
-q
1402 bridge
-j fdb show br
$bridge brport
$br_port1 \
1403 | jq
-e ".[] | select(.mac == \"$mac\")" &> /dev
/null
1404 check_fail $?
"Found FDB record when should not"
1406 bridge link
set dev
$br_port1 learning on
1408 tc filter del dev
$host1_if ingress protocol ip pref
1 handle
101 flower
1409 tc qdisc del dev
$host1_if ingress
1410 ip link
set $host1_if promisc off
1412 bridge link
set dev
$br_port1 flood on
1414 log_test
"FDB learning"
1419 local should_flood
=$1
1426 # Add an ACL on `host2_if` which will tell us whether the packet
1427 # was flooded to it or not.
1428 ip link
set $host2_if promisc on
1429 tc qdisc add dev
$host2_if ingress
1430 tc filter add dev
$host2_if ingress protocol ip pref
1 handle
101 \
1431 flower dst_mac
$mac action drop
1433 $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip
-q
1436 tc
-j -s filter show dev
$host2_if ingress \
1437 | jq
-e ".[] | select(.options.handle == 101) \
1438 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1439 if [[ $?
-ne 0 && $should_flood == "true" || \
1440 $?
-eq 0 && $should_flood == "false" ]]; then
1444 tc filter del dev
$host2_if ingress protocol ip pref
1 handle
101 flower
1445 tc qdisc del dev
$host2_if ingress
1446 ip link
set $host2_if promisc off
1451 flood_unicast_test
()
1456 local mac
=de
:ad
:be
:ef
:13:37
1457 local ip
=192.0.2.100
1461 bridge link
set dev
$br_port flood off
1463 flood_test_do false
$mac $ip $host1_if $host2_if
1464 check_err $?
"Packet flooded when should not"
1466 bridge link
set dev
$br_port flood on
1468 flood_test_do true
$mac $ip $host1_if $host2_if
1469 check_err $?
"Packet was not flooded when should"
1471 log_test
"Unknown unicast flood"
1474 flood_multicast_test
()
1479 local mac
=01:00:5e
:00:00:01
1484 bridge link
set dev
$br_port mcast_flood off
1486 flood_test_do false
$mac $ip $host1_if $host2_if
1487 check_err $?
"Packet flooded when should not"
1489 bridge link
set dev
$br_port mcast_flood on
1491 flood_test_do true
$mac $ip $host1_if $host2_if
1492 check_err $?
"Packet was not flooded when should"
1494 log_test
"Unregistered multicast flood"
1499 # `br_port` is connected to `host2_if`
1504 flood_unicast_test
$br_port $host1_if $host2_if
1505 flood_multicast_test
$br_port $host1_if $host2_if
1510 local pktsize
=$1; shift
1511 local proto
=$1; shift
1512 local h_in
=$1; shift # Where the traffic egresses the host
1515 local dmac
=$1; shift
1516 local -a mz_args
=("$@")
1518 $MZ $h_in -p $pktsize -A $sip -B $dip -c 0 \
1519 -a own
-b $dmac -t "$proto" -q "${mz_args[@]}" &
1523 start_traffic_pktsize
()
1525 local pktsize
=$1; shift
1526 local h_in
=$1; shift
1529 local dmac
=$1; shift
1530 local -a mz_args
=("$@")
1532 __start_traffic
$pktsize udp
"$h_in" "$sip" "$dip" "$dmac" \
1536 start_tcp_traffic_pktsize
()
1538 local pktsize
=$1; shift
1539 local h_in
=$1; shift
1542 local dmac
=$1; shift
1543 local -a mz_args
=("$@")
1545 __start_traffic
$pktsize tcp
"$h_in" "$sip" "$dip" "$dmac" \
1551 local h_in
=$1; shift
1554 local dmac
=$1; shift
1555 local -a mz_args
=("$@")
1557 start_traffic_pktsize
8000 "$h_in" "$sip" "$dip" "$dmac" \
1563 local h_in
=$1; shift
1566 local dmac
=$1; shift
1567 local -a mz_args
=("$@")
1569 start_tcp_traffic_pktsize
8000 "$h_in" "$sip" "$dip" "$dmac" \
1575 local pid
=${1-%%}; shift
1586 local if_name
=$1; shift
1589 capfile
[$if_name]=$
(mktemp
)
1590 capout
[$if_name]=$
(mktemp
)
1595 ns_cmd
="ip netns exec ${ns}"
1598 if [ -z $SUDO_USER ] ; then
1601 capuser
="-Z $SUDO_USER"
1604 $ns_cmd tcpdump
$TCPDUMP_EXTRA_FLAGS -e -n -Q in -i $if_name \
1605 -s 65535 -B 32768 $capuser -w ${capfile[$if_name]} \
1606 > "${capout[$if_name]}" 2>&1 &
1615 local pid
=${cappid[$if_name]}
1617 $ns_cmd kill "$pid" && wait "$pid"
1625 rm ${capfile[$if_name]} ${capout[$if_name]}
1632 tcpdump
-e -n -r ${capfile[$if_name]} 2>&1
1635 # return 0 if the packet wasn't seen on host2_if or 1 if it was
1647 # basic check to see if we were passed an IPv4 address, if not assume IPv6
1648 if [[ ! $ip =~ ^
[0-9]{1,3}\.
[0-9]{1,3}\.
[0-9]{1,3}\.
[0-9]{1,3}$
]]; then
1653 # Add an ACL on `host2_if` which will tell us whether the packet
1654 # was received by it or not.
1655 tc qdisc add dev
$host2_if ingress
1656 tc filter add dev
$host2_if ingress protocol
$tc_proto pref
1 handle
101 \
1657 flower ip_proto udp dst_mac
$mac action drop
1659 $MZ $host1_if $mz_v6arg -c 1 -p 64 -b $mac -A $src_ip -B $ip -t udp
"dp=4096,sp=2048" -q
1662 tc
-j -s filter show dev
$host2_if ingress \
1663 | jq
-e ".[] | select(.options.handle == 101) \
1664 | select(.options.actions[0].stats.packets == 1)" &> /dev
/null
1665 if [[ $?
-eq 0 ]]; then
1669 tc filter del dev
$host2_if ingress protocol
$tc_proto pref
1 handle
101 flower
1670 tc qdisc del dev
$host2_if ingress
1675 brmcast_check_sg_entries
()
1677 local report
=$1; shift
1681 for src
in "${slist[@]}"; do
1682 sarg
="${sarg} and .source_list[].address == \"$src\""
1684 bridge
-j -d -s mdb show dev br0 \
1685 | jq
-e ".[].mdb[] | \
1686 select(.grp == \"$TEST_GROUP\" and .source_list != null $sarg)" &>/dev
/null
1687 check_err $?
"Wrong *,G entry source list after $report report"
1689 for sgent
in "${slist[@]}"; do
1690 bridge
-j -d -s mdb show dev br0 \
1691 | jq
-e ".[].mdb[] | \
1692 select(.grp == \"$TEST_GROUP\" and .src == \"$sgent\")" &>/dev
/null
1693 check_err $?
"Missing S,G entry ($sgent, $TEST_GROUP)"
1697 brmcast_check_sg_fwding
()
1699 local should_fwd
=$1; shift
1700 local sources
=("$@")
1702 for src
in "${sources[@]}"; do
1705 mcast_packet_test
$TEST_GROUP_MAC $src $TEST_GROUP $h2 $h1
1707 if [ $should_fwd -eq 1 ]; then
1708 check_fail
$retval "Didn't forward traffic from S,G ($src, $TEST_GROUP)"
1710 check_err
$retval "Forwarded traffic for blocked S,G ($src, $TEST_GROUP)"
1715 brmcast_check_sg_state
()
1717 local is_blocked
=$1; shift
1718 local sources
=("$@")
1721 if [ $is_blocked -eq 1 ]; then
1725 for src
in "${sources[@]}"; do
1726 bridge
-j -d -s mdb show dev br0 \
1727 | jq
-e ".[].mdb[] | \
1728 select(.grp == \"$TEST_GROUP\" and .source_list != null) |
1730 select(.address == \"$src\") |
1731 select(.timer == \"0.00\")" &>/dev
/null
1732 check_err_fail
$should_fail $?
"Entry $src has zero timer"
1734 bridge
-j -d -s mdb show dev br0 \
1735 | jq
-e ".[].mdb[] | \
1736 select(.grp == \"$TEST_GROUP\" and .src == \"$src\" and \
1737 .flags[] == \"blocked\")" &>/dev
/null
1738 check_err_fail
$should_fail $?
"Entry $src has blocked flag"
1746 local vrf_name
=$
(master_name_get
$if_name)
1748 # We don't care about actual reception, just about joining the
1749 # IP multicast group and adding the L2 address to the device's
1750 # MAC filtering table
1751 ip vrf
exec $vrf_name \
1752 mreceive
-g $group -I $if_name > /dev
/null
2>&1 &
1760 kill "$mreceive_pid" && wait "$mreceive_pid"
1767 local vrf_name
=$
(master_name_get
$if_name)
1769 ip vrf
exec $vrf_name \
1770 msend
-g $groups -I $if_name -c 1 > /dev
/null
2>&1
1775 local mtype
=$1; shift
1776 local ip
=${1-ip}; shift
1778 # start the monitor in the background
1779 tmpfile
=`mktemp /var/run/nexthoptestXXX`
1780 mpid
=`($ip monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
1782 echo "$mpid $tmpfile"
1787 local mpid
=$1; shift
1788 local tmpfile
=$1; shift
1790 local what
=$1; shift
1794 local lines
=`grep '^\w' $tmpfile | wc -l`
1796 check_err $?
"$what: $lines lines of events, expected $el"
1800 hw_stats_monitor_test
()
1803 local type=$1; shift
1804 local make_suitable
=$1; shift
1805 local make_unsuitable
=$1; shift
1806 local ip
=${1-ip}; shift
1810 # Expect a notification about enablement.
1811 local ipmout
=$
(start_ip_monitor stats
"$ip")
1812 $ip stats
set dev
$dev ${type}_stats on
1813 stop_ip_monitor
$ipmout 1 "${type}_stats enablement"
1815 # Expect a notification about offload.
1816 local ipmout
=$
(start_ip_monitor stats
"$ip")
1818 stop_ip_monitor
$ipmout 1 "${type}_stats installation"
1820 # Expect a notification about loss of offload.
1821 local ipmout
=$
(start_ip_monitor stats
"$ip")
1823 stop_ip_monitor
$ipmout 1 "${type}_stats deinstallation"
1825 # Expect a notification about disablement
1826 local ipmout
=$
(start_ip_monitor stats
"$ip")
1827 $ip stats
set dev
$dev ${type}_stats off
1828 stop_ip_monitor
$ipmout 1 "${type}_stats disablement"
1830 log_test
"${type}_stats notifications"
1837 printf '%02x:' ${IP//./ } |
1841 # Convert a given IPv6 address, `IP' such that the :: token, if present, is
1842 # expanded, and each 16-bit group is padded with zeroes to be 4 hexadecimal
1843 # digits. An optional `BYTESEP' parameter can be given to further separate
1844 # individual bytes of each 16-bit group.
1848 local bytesep
=$1; shift
1850 local cvt_ip
=${IP/::/_}
1851 local colons
=${cvt_ip//[^:]/}
1852 local allcol
=:::::::
1853 # IP where :: -> the appropriate number of colons:
1854 local allcol_ip
=${cvt_ip/_/${allcol:${#colons}}}
1856 echo $allcol_ip |
tr : '\n' |
1858 sed 's/.*\(..\)\(..\)/\1'"$bytesep"'\2/' |
1874 printf "%04x" $u16 |
sed 's/^/000/;s/^.*\(..\)\(..\)$/\1:\2/'
1877 # Given a mausezahn-formatted payload (colon-separated bytes given as %02x),
1878 # possibly with a keyword CHECKSUM stashed where a 16-bit checksum should be,
1879 # calculate checksum as per RFC 1071, assuming the CHECKSUM field (if any)
1881 payload_template_calc_checksum
()
1883 local payload
=$1; shift
1888 # Push zero for the initial checksum.
1891 # Pad the payload with a terminating 00: in case we get an odd
1893 echo "${payload%:}:00:" |
1894 sed 's/CHECKSUM/00:00/g' |
1895 tr '[:lower:]' '[:upper:]' |
1896 # Add the word to the checksum.
1897 sed 's/\(..\):\(..\):/\1\2+\n/g' |
1898 # Strip the extra odd byte we pushed if left unconverted.
1901 echo "10000 ~ +" # Calculate and add carry.
1902 echo "FFFF r - p" # Bit-flip and print.
1905 tr '[:upper:]' '[:lower:]'
1908 payload_template_expand_checksum
()
1910 local payload
=$1; shift
1911 local checksum
=$1; shift
1913 local ckbytes
=$
(u16_to_bytes
$checksum)
1915 echo "$payload" |
sed "s/CHECKSUM/$ckbytes/g"
1918 payload_template_nbytes
()
1920 local payload
=$1; shift
1922 payload_template_expand_checksum
"${payload%:}" 0 |
1923 sed 's/:/\n/g' |
wc -l
1929 local sources
=("$@")
1932 local nsources
=$
(u16_to_bytes
${#sources[@]})
1934 # IS_IN ( $sources )
1936 )"22:"$
( : Type
- Membership Report
1938 )"CHECKSUM:"$
( : Checksum
1939 )"00:00:"$
( : Reserved
1940 )"00:01:"$
( : Number of Group Records
1941 )"01:"$
( : Record Type
- IS_IN
1942 )"00:"$
( : Aux Data Len
1943 )"${nsources}:"$
( : Number of Sources
1944 )"$(ipv4_to_bytes $GRP):"$
( : Multicast Address
1945 )"$(for src in "${sources[@]}"; do
1948 done)"$
( : Source Addresses
1950 local checksum
=$
(payload_template_calc_checksum
"$igmpv3")
1952 payload_template_expand_checksum
"$igmpv3" $checksum
1960 )"17:"$
( : Type
- Leave Group
1961 )"00:"$
( : Max Resp Time
- not meaningful
1962 )"CHECKSUM:"$
( : Checksum
1963 )"$(ipv4_to_bytes $GRP)"$
( : Group Address
1965 local checksum
=$
(payload_template_calc_checksum
"$payload")
1967 payload_template_expand_checksum
"$payload" $checksum
1974 local sources
=("$@")
1978 local nsources
=$
(u16_to_bytes
${#sources[@]})
1981 )"3a:"$
( : Next Header
- ICMPv6
1982 )"00:"$
( : Hdr Ext Len
1983 )"00:00:00:00:00:00:"$
( : Options and Padding
1987 )"8f:"$
( : Type
- MLDv2 Report
1989 )"CHECKSUM:"$
( : Checksum
1990 )"00:00:"$
( : Reserved
1991 )"00:01:"$
( : Number of Group Records
1992 )"01:"$
( : Record Type
- IS_IN
1993 )"00:"$
( : Aux Data Len
1994 )"${nsources}:"$
( : Number of Sources
1995 )"$(ipv6_to_bytes $GRP):"$
( : Multicast address
1996 )"$(for src in "${sources[@]}"; do
1999 done)"$
( : Source Addresses
2002 local len
=$
(u16_to_bytes $
(payload_template_nbytes
$icmpv6))
2004 )"$(ipv6_to_bytes $SIP):"$
( : SIP
2005 )"$(ipv6_to_bytes $GRP):"$
( : DIP is multicast address
2006 )"${len}:"$
( : Upper-layer length
2007 )"00:3a:"$
( : Zero and next-header
2009 local checksum
=$
(payload_template_calc_checksum
${sudohdr}${icmpv6})
2011 payload_template_expand_checksum
"$hbh$icmpv6" $checksum
2023 )"3a:"$
( : Next Header
- ICMPv6
2024 )"00:"$
( : Hdr Ext Len
2025 )"00:00:00:00:00:00:"$
( : Options and Padding
2029 )"84:"$
( : Type
- MLDv1 Done
2031 )"CHECKSUM:"$
( : Checksum
2032 )"00:00:"$
( : Max Resp Delay
- not meaningful
2033 )"00:00:"$
( : Reserved
2034 )"$(ipv6_to_bytes $GRP):"$
( : Multicast address
2037 local len
=$
(u16_to_bytes $
(payload_template_nbytes
$icmpv6))
2039 )"$(ipv6_to_bytes $SIP):"$
( : SIP
2040 )"$(ipv6_to_bytes $GRP):"$
( : DIP is multicast address
2041 )"${len}:"$
( : Upper-layer length
2042 )"00:3a:"$
( : Zero and next-header
2044 local checksum
=$
(payload_template_calc_checksum
${sudohdr}${icmpv6})
2046 payload_template_expand_checksum
"$hbh$icmpv6" $checksum
2051 local reason1
="$1"; shift
2052 local reason2
="$1"; shift
2053 local caller
=${FUNCNAME[1]}
2054 local src
=${BASH_SOURCE[1]}
2056 if systemctl is-active
--quiet lldpad
; then
2058 cat >/dev
/stderr
<<-EOF
2059 WARNING: lldpad is running
2061 lldpad will likely $reason1, and this test will
2062 $reason2. Both are not supported at the same time,
2063 one of them is arbitrarily going to overwrite the
2064 other. That will cause spurious failures (or, unlikely,
2065 passes) of this test.
2068 if [[ -z $ALLOW_LLDPAD ]]; then
2069 cat >/dev
/stderr
<<-EOF
2071 If you want to run the test anyway, please set
2072 an environment variable ALLOW_LLDPAD to a
2075 log_test_skip
$src:$caller
2087 echo $
((v
> 0 ? v
: -v))
2093 local mac_addr
=$
(mac_get
$dev)
2094 local tmp
=$
(ether_addr_to_u64
$mac_addr)
2098 ip link add link
$dev name macvlan-tmp
type macvlan mode private
2099 ip link
set macvlan-tmp address $
(u64_to_ether_addr $
((tmp
+ 1)))
2100 ip link
set macvlan-tmp up
2102 promisc
=$
(ip
-j -d link show dev
$dev | jq
-r '.[].promiscuity')
2104 ip link del macvlan-tmp
2106 [[ $promisc == 1 ]] && echo "no" ||
echo "yes"