~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/net/forwarding/lib.sh

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/testing/selftests/net/forwarding/lib.sh (Architecture i386) and /tools/testing/selftests/net/forwarding/lib.sh (Architecture m68k)


  1 #!/bin/bash                                         1 #!/bin/bash
  2 # SPDX-License-Identifier: GPL-2.0                  2 # SPDX-License-Identifier: GPL-2.0
  3                                                     3 
  4 ##############################################      4 ##############################################################################
  5 # Topology description. p1 looped back to p2,       5 # Topology description. p1 looped back to p2, p3 to p4 and so on.
  6                                                     6 
  7 declare -A NETIFS=(                                 7 declare -A NETIFS=(
  8     [p1]=veth0                                      8     [p1]=veth0
  9     [p2]=veth1                                      9     [p2]=veth1
 10     [p3]=veth2                                     10     [p3]=veth2
 11     [p4]=veth3                                     11     [p4]=veth3
 12     [p5]=veth4                                     12     [p5]=veth4
 13     [p6]=veth5                                     13     [p6]=veth5
 14     [p7]=veth6                                     14     [p7]=veth6
 15     [p8]=veth7                                     15     [p8]=veth7
 16     [p9]=veth8                                     16     [p9]=veth8
 17     [p10]=veth9                                    17     [p10]=veth9
 18 )                                                  18 )
 19                                                    19 
 20 # Port that does not have a cable connected.       20 # Port that does not have a cable connected.
 21 : "${NETIF_NO_CABLE:=eth8}"                        21 : "${NETIF_NO_CABLE:=eth8}"
 22                                                    22 
 23 ##############################################     23 ##############################################################################
 24 # Defines                                          24 # Defines
 25                                                    25 
 26 # Networking utilities.                            26 # Networking utilities.
 27 : "${PING:=ping}"                                  27 : "${PING:=ping}"
 28 : "${PING6:=ping6}"     # Some distros just us     28 : "${PING6:=ping6}"     # Some distros just use ping.
 29 : "${ARPING:=arping}"                              29 : "${ARPING:=arping}"
 30 : "${TROUTE6:=traceroute6}"                        30 : "${TROUTE6:=traceroute6}"
 31                                                    31 
 32 # Packet generator.                                32 # Packet generator.
 33 : "${MZ:=mausezahn}"    # Some distributions u     33 : "${MZ:=mausezahn}"    # Some distributions use 'mz'.
 34 : "${MZ_DELAY:=0}"                                 34 : "${MZ_DELAY:=0}"
 35                                                    35 
 36 # Host configuration tools.                        36 # Host configuration tools.
 37 : "${TEAMD:=teamd}"                                37 : "${TEAMD:=teamd}"
 38 : "${MCD:=smcrouted}"                              38 : "${MCD:=smcrouted}"
 39 : "${MC_CLI:=smcroutectl}"                         39 : "${MC_CLI:=smcroutectl}"
 40                                                    40 
 41 # Constants for netdevice bring-up:                41 # Constants for netdevice bring-up:
 42 # Default time in seconds to wait for an inter     42 # Default time in seconds to wait for an interface to come up before giving up
 43 # and bailing out. Used during initial setup.      43 # and bailing out. Used during initial setup.
 44 : "${INTERFACE_TIMEOUT:=600}"                      44 : "${INTERFACE_TIMEOUT:=600}"
 45 # Like INTERFACE_TIMEOUT, but default for ad-h     45 # Like INTERFACE_TIMEOUT, but default for ad-hoc waiting in testing scripts.
 46 : "${WAIT_TIMEOUT:=20}"                            46 : "${WAIT_TIMEOUT:=20}"
 47 # Time to wait after interfaces participating      47 # Time to wait after interfaces participating in the test are all UP.
 48 : "${WAIT_TIME:=5}"                                48 : "${WAIT_TIME:=5}"
 49                                                    49 
 50 # Whether to pause on, respectively, after a f     50 # Whether to pause on, respectively, after a failure and before cleanup.
 51 : "${PAUSE_ON_FAIL:=no}"                           51 : "${PAUSE_ON_FAIL:=no}"
 52 : "${PAUSE_ON_CLEANUP:=no}"                        52 : "${PAUSE_ON_CLEANUP:=no}"
 53                                                    53 
 54 # Whether to create virtual interfaces, and wh     54 # Whether to create virtual interfaces, and what netdevice type they should be.
 55 : "${NETIF_CREATE:=yes}"                           55 : "${NETIF_CREATE:=yes}"
 56 : "${NETIF_TYPE:=veth}"                            56 : "${NETIF_TYPE:=veth}"
 57                                                    57 
 58 # Constants for ping tests:                        58 # Constants for ping tests:
 59 # How many packets should be sent.                 59 # How many packets should be sent.
 60 : "${PING_COUNT:=10}"                              60 : "${PING_COUNT:=10}"
 61 # Timeout (in seconds) before ping exits regar     61 # Timeout (in seconds) before ping exits regardless of how many packets have
 62 # been sent or received                            62 # been sent or received
 63 : "${PING_TIMEOUT:=5}"                             63 : "${PING_TIMEOUT:=5}"
 64                                                    64 
 65 # Minimum ageing_time (in centiseconds) suppor     65 # Minimum ageing_time (in centiseconds) supported by hardware
 66 : "${LOW_AGEING_TIME:=1000}"                       66 : "${LOW_AGEING_TIME:=1000}"
 67                                                    67 
 68 # Whether to check for availability of certain     68 # Whether to check for availability of certain tools.
 69 : "${REQUIRE_JQ:=yes}"                             69 : "${REQUIRE_JQ:=yes}"
 70 : "${REQUIRE_MZ:=yes}"                             70 : "${REQUIRE_MZ:=yes}"
 71 : "${REQUIRE_MTOOLS:=no}"                          71 : "${REQUIRE_MTOOLS:=no}"
 72                                                    72 
 73 # Whether to override MAC addresses on interfa     73 # Whether to override MAC addresses on interfaces participating in the test.
 74 : "${STABLE_MAC_ADDRS:=no}"                        74 : "${STABLE_MAC_ADDRS:=no}"
 75                                                    75 
 76 # Flags for tcpdump                                76 # Flags for tcpdump
 77 : "${TCPDUMP_EXTRA_FLAGS:=}"                       77 : "${TCPDUMP_EXTRA_FLAGS:=}"
 78                                                    78 
 79 # Flags for TC filters.                            79 # Flags for TC filters.
 80 : "${TC_FLAG:=skip_hw}"                            80 : "${TC_FLAG:=skip_hw}"
 81                                                    81 
 82 # Whether the machine is "slow" -- i.e. might      82 # Whether the machine is "slow" -- i.e. might be incapable of running tests
 83 # involving heavy traffic. This might be the c     83 # involving heavy traffic. This might be the case on a debug kernel, a VM, or
 84 # e.g. a low-power board.                          84 # e.g. a low-power board.
 85 : "${KSFT_MACHINE_SLOW:=no}"                       85 : "${KSFT_MACHINE_SLOW:=no}"
 86                                                    86 
 87 ##############################################     87 ##############################################################################
 88 # Find netifs by test-specified driver name        88 # Find netifs by test-specified driver name
 89                                                    89 
 90 driver_name_get()                                  90 driver_name_get()
 91 {                                                  91 {
 92         local dev=$1; shift                        92         local dev=$1; shift
 93         local driver_path="/sys/class/net/$dev     93         local driver_path="/sys/class/net/$dev/device/driver"
 94                                                    94 
 95         if [[ -L $driver_path ]]; then             95         if [[ -L $driver_path ]]; then
 96                 basename `realpath $driver_pat     96                 basename `realpath $driver_path`
 97         fi                                         97         fi
 98 }                                                  98 }
 99                                                    99 
100 netif_find_driver()                               100 netif_find_driver()
101 {                                                 101 {
102         local ifnames=`ip -j link show | jq -r    102         local ifnames=`ip -j link show | jq -r ".[].ifname"`
103         local count=0                             103         local count=0
104                                                   104 
105         for ifname in $ifnames                    105         for ifname in $ifnames
106         do                                        106         do
107                 local driver_name=`driver_name    107                 local driver_name=`driver_name_get $ifname`
108                 if [[ ! -z $driver_name && $dr    108                 if [[ ! -z $driver_name && $driver_name == $NETIF_FIND_DRIVER ]]; then
109                         count=$((count + 1))      109                         count=$((count + 1))
110                         NETIFS[p$count]="$ifna    110                         NETIFS[p$count]="$ifname"
111                 fi                                111                 fi
112         done                                      112         done
113 }                                                 113 }
114                                                   114 
115 # Whether to find netdevice according to the d    115 # Whether to find netdevice according to the driver speficied by the importer
116 : "${NETIF_FIND_DRIVER:=}"                        116 : "${NETIF_FIND_DRIVER:=}"
117                                                   117 
118 if [[ $NETIF_FIND_DRIVER ]]; then                 118 if [[ $NETIF_FIND_DRIVER ]]; then
119         unset NETIFS                              119         unset NETIFS
120         declare -A NETIFS                         120         declare -A NETIFS
121         netif_find_driver                         121         netif_find_driver
122 fi                                                122 fi
123                                                   123 
124 net_forwarding_dir=$(dirname "$(readlink -e "$    124 net_forwarding_dir=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
125                                                   125 
126 if [[ -f $net_forwarding_dir/forwarding.config    126 if [[ -f $net_forwarding_dir/forwarding.config ]]; then
127         source "$net_forwarding_dir/forwarding    127         source "$net_forwarding_dir/forwarding.config"
128 fi                                                128 fi
129                                                   129 
130 source "$net_forwarding_dir/../lib.sh"            130 source "$net_forwarding_dir/../lib.sh"
131                                                   131 
132 ##############################################    132 ##############################################################################
133 # Sanity checks                                   133 # Sanity checks
134                                                   134 
135 check_tc_version()                                135 check_tc_version()
136 {                                                 136 {
137         tc -j &> /dev/null                        137         tc -j &> /dev/null
138         if [[ $? -ne 0 ]]; then                   138         if [[ $? -ne 0 ]]; then
139                 echo "SKIP: iproute2 too old;     139                 echo "SKIP: iproute2 too old; tc is missing JSON support"
140                 exit $ksft_skip                   140                 exit $ksft_skip
141         fi                                        141         fi
142 }                                                 142 }
143                                                   143 
144 # Old versions of tc don't understand "mpls_uc    144 # Old versions of tc don't understand "mpls_uc"
145 check_tc_mpls_support()                           145 check_tc_mpls_support()
146 {                                                 146 {
147         local dev=$1; shift                       147         local dev=$1; shift
148                                                   148 
149         tc filter add dev $dev ingress protoco    149         tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
150                 matchall action pipe &> /dev/n    150                 matchall action pipe &> /dev/null
151         if [[ $? -ne 0 ]]; then                   151         if [[ $? -ne 0 ]]; then
152                 echo "SKIP: iproute2 too old;     152                 echo "SKIP: iproute2 too old; tc is missing MPLS support"
153                 return $ksft_skip                 153                 return $ksft_skip
154         fi                                        154         fi
155         tc filter del dev $dev ingress protoco    155         tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
156                 matchall                          156                 matchall
157 }                                                 157 }
158                                                   158 
159 # Old versions of tc produce invalid json outp    159 # Old versions of tc produce invalid json output for mpls lse statistics
160 check_tc_mpls_lse_stats()                         160 check_tc_mpls_lse_stats()
161 {                                                 161 {
162         local dev=$1; shift                       162         local dev=$1; shift
163         local ret;                                163         local ret;
164                                                   164 
165         tc filter add dev $dev ingress protoco    165         tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
166                 flower mpls lse depth 2           166                 flower mpls lse depth 2                                 \
167                 action continue &> /dev/null      167                 action continue &> /dev/null
168                                                   168 
169         if [[ $? -ne 0 ]]; then                   169         if [[ $? -ne 0 ]]; then
170                 echo "SKIP: iproute2 too old;     170                 echo "SKIP: iproute2 too old; tc-flower is missing extended MPLS support"
171                 return $ksft_skip                 171                 return $ksft_skip
172         fi                                        172         fi
173                                                   173 
174         tc -j filter show dev $dev ingress pro    174         tc -j filter show dev $dev ingress protocol mpls_uc | jq . &> /dev/null
175         ret=$?                                    175         ret=$?
176         tc filter del dev $dev ingress protoco    176         tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
177                 flower                            177                 flower
178                                                   178 
179         if [[ $ret -ne 0 ]]; then                 179         if [[ $ret -ne 0 ]]; then
180                 echo "SKIP: iproute2 too old;     180                 echo "SKIP: iproute2 too old; tc-flower produces invalid json output for extended MPLS filters"
181                 return $ksft_skip                 181                 return $ksft_skip
182         fi                                        182         fi
183 }                                                 183 }
184                                                   184 
185 check_tc_shblock_support()                        185 check_tc_shblock_support()
186 {                                                 186 {
187         tc filter help 2>&1 | grep block &> /d    187         tc filter help 2>&1 | grep block &> /dev/null
188         if [[ $? -ne 0 ]]; then                   188         if [[ $? -ne 0 ]]; then
189                 echo "SKIP: iproute2 too old;     189                 echo "SKIP: iproute2 too old; tc is missing shared block support"
190                 exit $ksft_skip                   190                 exit $ksft_skip
191         fi                                        191         fi
192 }                                                 192 }
193                                                   193 
194 check_tc_chain_support()                          194 check_tc_chain_support()
195 {                                                 195 {
196         tc help 2>&1|grep chain &> /dev/null      196         tc help 2>&1|grep chain &> /dev/null
197         if [[ $? -ne 0 ]]; then                   197         if [[ $? -ne 0 ]]; then
198                 echo "SKIP: iproute2 too old;     198                 echo "SKIP: iproute2 too old; tc is missing chain support"
199                 exit $ksft_skip                   199                 exit $ksft_skip
200         fi                                        200         fi
201 }                                                 201 }
202                                                   202 
203 check_tc_action_hw_stats_support()                203 check_tc_action_hw_stats_support()
204 {                                                 204 {
205         tc actions help 2>&1 | grep -q hw_stat    205         tc actions help 2>&1 | grep -q hw_stats
206         if [[ $? -ne 0 ]]; then                   206         if [[ $? -ne 0 ]]; then
207                 echo "SKIP: iproute2 too old;     207                 echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
208                 exit $ksft_skip                   208                 exit $ksft_skip
209         fi                                        209         fi
210 }                                                 210 }
211                                                   211 
212 check_tc_fp_support()                             212 check_tc_fp_support()
213 {                                                 213 {
214         tc qdisc add dev lo mqprio help 2>&1 |    214         tc qdisc add dev lo mqprio help 2>&1 | grep -q "fp "
215         if [[ $? -ne 0 ]]; then                   215         if [[ $? -ne 0 ]]; then
216                 echo "SKIP: iproute2 too old;     216                 echo "SKIP: iproute2 too old; tc is missing frame preemption support"
217                 exit $ksft_skip                   217                 exit $ksft_skip
218         fi                                        218         fi
219 }                                                 219 }
220                                                   220 
221 check_ethtool_lanes_support()                     221 check_ethtool_lanes_support()
222 {                                                 222 {
223         ethtool --help 2>&1| grep lanes &> /de    223         ethtool --help 2>&1| grep lanes &> /dev/null
224         if [[ $? -ne 0 ]]; then                   224         if [[ $? -ne 0 ]]; then
225                 echo "SKIP: ethtool too old; i    225                 echo "SKIP: ethtool too old; it is missing lanes support"
226                 exit $ksft_skip                   226                 exit $ksft_skip
227         fi                                        227         fi
228 }                                                 228 }
229                                                   229 
230 check_ethtool_mm_support()                        230 check_ethtool_mm_support()
231 {                                                 231 {
232         ethtool --help 2>&1| grep -- '--show-m    232         ethtool --help 2>&1| grep -- '--show-mm' &> /dev/null
233         if [[ $? -ne 0 ]]; then                   233         if [[ $? -ne 0 ]]; then
234                 echo "SKIP: ethtool too old; i    234                 echo "SKIP: ethtool too old; it is missing MAC Merge layer support"
235                 exit $ksft_skip                   235                 exit $ksft_skip
236         fi                                        236         fi
237 }                                                 237 }
238                                                   238 
239 check_ethtool_counter_group_support()             239 check_ethtool_counter_group_support()
240 {                                                 240 {
241         ethtool --help 2>&1| grep -- '--all-gr    241         ethtool --help 2>&1| grep -- '--all-groups' &> /dev/null
242         if [[ $? -ne 0 ]]; then                   242         if [[ $? -ne 0 ]]; then
243                 echo "SKIP: ethtool too old; i    243                 echo "SKIP: ethtool too old; it is missing standard counter group support"
244                 exit $ksft_skip                   244                 exit $ksft_skip
245         fi                                        245         fi
246 }                                                 246 }
247                                                   247 
248 check_ethtool_pmac_std_stats_support()            248 check_ethtool_pmac_std_stats_support()
249 {                                                 249 {
250         local dev=$1; shift                       250         local dev=$1; shift
251         local grp=$1; shift                       251         local grp=$1; shift
252                                                   252 
253         [ 0 -ne $(ethtool --json -S $dev --all    253         [ 0 -ne $(ethtool --json -S $dev --all-groups --src pmac 2>/dev/null \
254                 | jq ".[].\"$grp\" | length")     254                 | jq ".[].\"$grp\" | length") ]
255 }                                                 255 }
256                                                   256 
257 check_locked_port_support()                       257 check_locked_port_support()
258 {                                                 258 {
259         if ! bridge -d link show | grep -q " l    259         if ! bridge -d link show | grep -q " locked"; then
260                 echo "SKIP: iproute2 too old;     260                 echo "SKIP: iproute2 too old; Locked port feature not supported."
261                 return $ksft_skip                 261                 return $ksft_skip
262         fi                                        262         fi
263 }                                                 263 }
264                                                   264 
265 check_port_mab_support()                          265 check_port_mab_support()
266 {                                                 266 {
267         if ! bridge -d link show | grep -q "ma    267         if ! bridge -d link show | grep -q "mab"; then
268                 echo "SKIP: iproute2 too old;     268                 echo "SKIP: iproute2 too old; MacAuth feature not supported."
269                 return $ksft_skip                 269                 return $ksft_skip
270         fi                                        270         fi
271 }                                                 271 }
272                                                   272 
273 if [[ "$(id -u)" -ne 0 ]]; then                   273 if [[ "$(id -u)" -ne 0 ]]; then
274         echo "SKIP: need root privileges"         274         echo "SKIP: need root privileges"
275         exit $ksft_skip                           275         exit $ksft_skip
276 fi                                                276 fi
277                                                   277 
278 check_driver()                                    278 check_driver()
279 {                                                 279 {
280         local dev=$1; shift                       280         local dev=$1; shift
281         local expected=$1; shift                  281         local expected=$1; shift
282         local driver_name=`driver_name_get $de    282         local driver_name=`driver_name_get $dev`
283                                                   283 
284         if [[ $driver_name != $expected ]]; th    284         if [[ $driver_name != $expected ]]; then
285                 echo "SKIP: expected driver $e    285                 echo "SKIP: expected driver $expected for $dev, got $driver_name instead"
286                 exit $ksft_skip                   286                 exit $ksft_skip
287         fi                                        287         fi
288 }                                                 288 }
289                                                   289 
290 if [[ "$CHECK_TC" = "yes" ]]; then                290 if [[ "$CHECK_TC" = "yes" ]]; then
291         check_tc_version                          291         check_tc_version
292 fi                                                292 fi
293                                                   293 
294 require_command()                                 294 require_command()
295 {                                                 295 {
296         local cmd=$1; shift                       296         local cmd=$1; shift
297                                                   297 
298         if [[ ! -x "$(command -v "$cmd")" ]];     298         if [[ ! -x "$(command -v "$cmd")" ]]; then
299                 echo "SKIP: $cmd not installed    299                 echo "SKIP: $cmd not installed"
300                 exit $ksft_skip                   300                 exit $ksft_skip
301         fi                                        301         fi
302 }                                                 302 }
303                                                   303 
304 # IPv6 support was added in v3.0                  304 # IPv6 support was added in v3.0
305 check_mtools_version()                            305 check_mtools_version()
306 {                                                 306 {
307         local version="$(msend -v)"               307         local version="$(msend -v)"
308         local major                               308         local major
309                                                   309 
310         version=${version##msend version }        310         version=${version##msend version }
311         major=$(echo $version | cut -d. -f1)      311         major=$(echo $version | cut -d. -f1)
312                                                   312 
313         if [ $major -lt 3 ]; then                 313         if [ $major -lt 3 ]; then
314                 echo "SKIP: expected mtools ve    314                 echo "SKIP: expected mtools version 3.0, got $version"
315                 exit $ksft_skip                   315                 exit $ksft_skip
316         fi                                        316         fi
317 }                                                 317 }
318                                                   318 
319 if [[ "$REQUIRE_JQ" = "yes" ]]; then              319 if [[ "$REQUIRE_JQ" = "yes" ]]; then
320         require_command jq                        320         require_command jq
321 fi                                                321 fi
322 if [[ "$REQUIRE_MZ" = "yes" ]]; then              322 if [[ "$REQUIRE_MZ" = "yes" ]]; then
323         require_command $MZ                       323         require_command $MZ
324 fi                                                324 fi
325 if [[ "$REQUIRE_MTOOLS" = "yes" ]]; then          325 if [[ "$REQUIRE_MTOOLS" = "yes" ]]; then
326         # https://github.com/troglobit/mtools     326         # https://github.com/troglobit/mtools
327         require_command msend                     327         require_command msend
328         require_command mreceive                  328         require_command mreceive
329         check_mtools_version                      329         check_mtools_version
330 fi                                                330 fi
331                                                   331 
332 ##############################################    332 ##############################################################################
333 # Command line options handling                   333 # Command line options handling
334                                                   334 
335 count=0                                           335 count=0
336                                                   336 
337 while [[ $# -gt 0 ]]; do                          337 while [[ $# -gt 0 ]]; do
338         if [[ "$count" -eq "0" ]]; then           338         if [[ "$count" -eq "0" ]]; then
339                 unset NETIFS                      339                 unset NETIFS
340                 declare -A NETIFS                 340                 declare -A NETIFS
341         fi                                        341         fi
342         count=$((count + 1))                      342         count=$((count + 1))
343         NETIFS[p$count]="$1"                      343         NETIFS[p$count]="$1"
344         shift                                     344         shift
345 done                                              345 done
346                                                   346 
347 ##############################################    347 ##############################################################################
348 # Network interfaces configuration                348 # Network interfaces configuration
349                                                   349 
350 if [[ ! -v NUM_NETIFS ]]; then                    350 if [[ ! -v NUM_NETIFS ]]; then
351         echo "SKIP: importer does not define \    351         echo "SKIP: importer does not define \"NUM_NETIFS\""
352         exit $ksft_skip                           352         exit $ksft_skip
353 fi                                                353 fi
354                                                   354 
355 if (( NUM_NETIFS > ${#NETIFS[@]} )); then         355 if (( NUM_NETIFS > ${#NETIFS[@]} )); then
356         echo "SKIP: Importer requires $NUM_NET    356         echo "SKIP: Importer requires $NUM_NETIFS NETIFS, but only ${#NETIFS[@]} are defined (${NETIFS[@]})"
357         exit $ksft_skip                           357         exit $ksft_skip
358 fi                                                358 fi
359                                                   359 
360 for i in $(seq ${#NETIFS[@]}); do                 360 for i in $(seq ${#NETIFS[@]}); do
361         if [[ ! ${NETIFS[p$i]} ]]; then           361         if [[ ! ${NETIFS[p$i]} ]]; then
362                 echo "SKIP: NETIFS[p$i] not gi    362                 echo "SKIP: NETIFS[p$i] not given"
363                 exit $ksft_skip                   363                 exit $ksft_skip
364         fi                                        364         fi
365 done                                              365 done
366                                                   366 
367 create_netif_veth()                               367 create_netif_veth()
368 {                                                 368 {
369         local i                                   369         local i
370                                                   370 
371         for ((i = 1; i <= NUM_NETIFS; ++i)); d    371         for ((i = 1; i <= NUM_NETIFS; ++i)); do
372                 local j=$((i+1))                  372                 local j=$((i+1))
373                                                   373 
374                 if [ -z ${NETIFS[p$i]} ]; then    374                 if [ -z ${NETIFS[p$i]} ]; then
375                         echo "SKIP: Cannot cre    375                         echo "SKIP: Cannot create interface. Name not specified"
376                         exit $ksft_skip           376                         exit $ksft_skip
377                 fi                                377                 fi
378                                                   378 
379                 ip link show dev ${NETIFS[p$i]    379                 ip link show dev ${NETIFS[p$i]} &> /dev/null
380                 if [[ $? -ne 0 ]]; then           380                 if [[ $? -ne 0 ]]; then
381                         ip link add ${NETIFS[p    381                         ip link add ${NETIFS[p$i]} type veth \
382                                 peer name ${NE    382                                 peer name ${NETIFS[p$j]}
383                         if [[ $? -ne 0 ]]; the    383                         if [[ $? -ne 0 ]]; then
384                                 echo "Failed t    384                                 echo "Failed to create netif"
385                                 exit 1            385                                 exit 1
386                         fi                        386                         fi
387                 fi                                387                 fi
388                 i=$j                              388                 i=$j
389         done                                      389         done
390 }                                                 390 }
391                                                   391 
392 create_netif()                                    392 create_netif()
393 {                                                 393 {
394         case "$NETIF_TYPE" in                     394         case "$NETIF_TYPE" in
395         veth) create_netif_veth                   395         veth) create_netif_veth
396               ;;                                  396               ;;
397         *) echo "Can not create interfaces of     397         *) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
398            exit 1                                 398            exit 1
399            ;;                                     399            ;;
400         esac                                      400         esac
401 }                                                 401 }
402                                                   402 
403 declare -A MAC_ADDR_ORIG                          403 declare -A MAC_ADDR_ORIG
404 mac_addr_prepare()                                404 mac_addr_prepare()
405 {                                                 405 {
406         local new_addr=                           406         local new_addr=
407         local dev=                                407         local dev=
408                                                   408 
409         for ((i = 1; i <= NUM_NETIFS; ++i)); d    409         for ((i = 1; i <= NUM_NETIFS; ++i)); do
410                 dev=${NETIFS[p$i]}                410                 dev=${NETIFS[p$i]}
411                 new_addr=$(printf "00:01:02:03    411                 new_addr=$(printf "00:01:02:03:04:%02x" $i)
412                                                   412 
413                 MAC_ADDR_ORIG["$dev"]=$(ip -j     413                 MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
414                 # Strip quotes                    414                 # Strip quotes
415                 MAC_ADDR_ORIG["$dev"]=${MAC_AD    415                 MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
416                 ip link set dev $dev address $    416                 ip link set dev $dev address $new_addr
417         done                                      417         done
418 }                                                 418 }
419                                                   419 
420 mac_addr_restore()                                420 mac_addr_restore()
421 {                                                 421 {
422         local dev=                                422         local dev=
423                                                   423 
424         for ((i = 1; i <= NUM_NETIFS; ++i)); d    424         for ((i = 1; i <= NUM_NETIFS; ++i)); do
425                 dev=${NETIFS[p$i]}                425                 dev=${NETIFS[p$i]}
426                 ip link set dev $dev address $    426                 ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
427         done                                      427         done
428 }                                                 428 }
429                                                   429 
430 if [[ "$NETIF_CREATE" = "yes" ]]; then            430 if [[ "$NETIF_CREATE" = "yes" ]]; then
431         create_netif                              431         create_netif
432 fi                                                432 fi
433                                                   433 
434 if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then        434 if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
435         mac_addr_prepare                          435         mac_addr_prepare
436 fi                                                436 fi
437                                                   437 
438 for ((i = 1; i <= NUM_NETIFS; ++i)); do           438 for ((i = 1; i <= NUM_NETIFS; ++i)); do
439         ip link show dev ${NETIFS[p$i]} &> /de    439         ip link show dev ${NETIFS[p$i]} &> /dev/null
440         if [[ $? -ne 0 ]]; then                   440         if [[ $? -ne 0 ]]; then
441                 echo "SKIP: could not find all    441                 echo "SKIP: could not find all required interfaces"
442                 exit $ksft_skip                   442                 exit $ksft_skip
443         fi                                        443         fi
444 done                                              444 done
445                                                   445 
446 ##############################################    446 ##############################################################################
447 # Helpers                                         447 # Helpers
448                                                   448 
449 # Exit status to return at the end. Set in cas    449 # Exit status to return at the end. Set in case one of the tests fails.
450 EXIT_STATUS=0                                     450 EXIT_STATUS=0
451 # Per-test return value. Clear at the beginnin    451 # Per-test return value. Clear at the beginning of each test.
452 RET=0                                             452 RET=0
453                                                   453 
454 ret_set_ksft_status()                             454 ret_set_ksft_status()
455 {                                                 455 {
456         local ksft_status=$1; shift               456         local ksft_status=$1; shift
457         local msg=$1; shift                       457         local msg=$1; shift
458                                                   458 
459         RET=$(ksft_status_merge $RET $ksft_sta    459         RET=$(ksft_status_merge $RET $ksft_status)
460         if (( $? )); then                         460         if (( $? )); then
461                 retmsg=$msg                       461                 retmsg=$msg
462         fi                                        462         fi
463 }                                                 463 }
464                                                   464 
465 # Whether FAILs should be interpreted as XFAIL    465 # Whether FAILs should be interpreted as XFAILs. Internal.
466 FAIL_TO_XFAIL=                                    466 FAIL_TO_XFAIL=
467                                                   467 
468 check_err()                                       468 check_err()
469 {                                                 469 {
470         local err=$1                              470         local err=$1
471         local msg=$2                              471         local msg=$2
472                                                   472 
473         if ((err)); then                          473         if ((err)); then
474                 if [[ $FAIL_TO_XFAIL = yes ]];    474                 if [[ $FAIL_TO_XFAIL = yes ]]; then
475                         ret_set_ksft_status $k    475                         ret_set_ksft_status $ksft_xfail "$msg"
476                 else                              476                 else
477                         ret_set_ksft_status $k    477                         ret_set_ksft_status $ksft_fail "$msg"
478                 fi                                478                 fi
479         fi                                        479         fi
480 }                                                 480 }
481                                                   481 
482 check_fail()                                      482 check_fail()
483 {                                                 483 {
484         local err=$1                              484         local err=$1
485         local msg=$2                              485         local msg=$2
486                                                   486 
487         check_err $((!err)) "$msg"                487         check_err $((!err)) "$msg"
488 }                                                 488 }
489                                                   489 
490 check_err_fail()                                  490 check_err_fail()
491 {                                                 491 {
492         local should_fail=$1; shift               492         local should_fail=$1; shift
493         local err=$1; shift                       493         local err=$1; shift
494         local what=$1; shift                      494         local what=$1; shift
495                                                   495 
496         if ((should_fail)); then                  496         if ((should_fail)); then
497                 check_fail $err "$what succeed    497                 check_fail $err "$what succeeded, but should have failed"
498         else                                      498         else
499                 check_err $err "$what failed"     499                 check_err $err "$what failed"
500         fi                                        500         fi
501 }                                                 501 }
502                                                   502 
503 xfail()                                           503 xfail()
504 {                                                 504 {
505         FAIL_TO_XFAIL=yes "$@"                    505         FAIL_TO_XFAIL=yes "$@"
506 }                                                 506 }
507                                                   507 
508 xfail_on_slow()                                   508 xfail_on_slow()
509 {                                                 509 {
510         if [[ $KSFT_MACHINE_SLOW = yes ]]; the    510         if [[ $KSFT_MACHINE_SLOW = yes ]]; then
511                 FAIL_TO_XFAIL=yes "$@"            511                 FAIL_TO_XFAIL=yes "$@"
512         else                                      512         else
513                 "$@"                              513                 "$@"
514         fi                                        514         fi
515 }                                                 515 }
516                                                   516 
517 omit_on_slow()                                    517 omit_on_slow()
518 {                                                 518 {
519         if [[ $KSFT_MACHINE_SLOW != yes ]]; th    519         if [[ $KSFT_MACHINE_SLOW != yes ]]; then
520                 "$@"                              520                 "$@"
521         fi                                        521         fi
522 }                                                 522 }
523                                                   523 
524 xfail_on_veth()                                   524 xfail_on_veth()
525 {                                                 525 {
526         local dev=$1; shift                       526         local dev=$1; shift
527         local kind                                527         local kind
528                                                   528 
529         kind=$(ip -j -d link show dev $dev |      529         kind=$(ip -j -d link show dev $dev |
530                         jq -r '.[].linkinfo.in    530                         jq -r '.[].linkinfo.info_kind')
531         if [[ $kind = veth ]]; then               531         if [[ $kind = veth ]]; then
532                 FAIL_TO_XFAIL=yes "$@"            532                 FAIL_TO_XFAIL=yes "$@"
533         else                                      533         else
534                 "$@"                              534                 "$@"
535         fi                                        535         fi
536 }                                                 536 }
537                                                   537 
538 log_test_result()                                 538 log_test_result()
539 {                                                 539 {
540         local test_name=$1; shift                 540         local test_name=$1; shift
541         local opt_str=$1; shift                   541         local opt_str=$1; shift
542         local result=$1; shift                    542         local result=$1; shift
543         local retmsg=$1; shift                    543         local retmsg=$1; shift
544                                                   544 
545         printf "TEST: %-60s  [%s]\n" "$test_na    545         printf "TEST: %-60s  [%s]\n" "$test_name $opt_str" "$result"
546         if [[ $retmsg ]]; then                    546         if [[ $retmsg ]]; then
547                 printf "\t%s\n" "$retmsg"         547                 printf "\t%s\n" "$retmsg"
548         fi                                        548         fi
549 }                                                 549 }
550                                                   550 
551 pause_on_fail()                                   551 pause_on_fail()
552 {                                                 552 {
553         if [[ $PAUSE_ON_FAIL == yes ]]; then      553         if [[ $PAUSE_ON_FAIL == yes ]]; then
554                 echo "Hit enter to continue, '    554                 echo "Hit enter to continue, 'q' to quit"
555                 read a                            555                 read a
556                 [[ $a == q ]] && exit 1           556                 [[ $a == q ]] && exit 1
557         fi                                        557         fi
558 }                                                 558 }
559                                                   559 
560 handle_test_result_pass()                         560 handle_test_result_pass()
561 {                                                 561 {
562         local test_name=$1; shift                 562         local test_name=$1; shift
563         local opt_str=$1; shift                   563         local opt_str=$1; shift
564                                                   564 
565         log_test_result "$test_name" "$opt_str    565         log_test_result "$test_name" "$opt_str" " OK "
566 }                                                 566 }
567                                                   567 
568 handle_test_result_fail()                         568 handle_test_result_fail()
569 {                                                 569 {
570         local test_name=$1; shift                 570         local test_name=$1; shift
571         local opt_str=$1; shift                   571         local opt_str=$1; shift
572                                                   572 
573         log_test_result "$test_name" "$opt_str    573         log_test_result "$test_name" "$opt_str" FAIL "$retmsg"
574         pause_on_fail                             574         pause_on_fail
575 }                                                 575 }
576                                                   576 
577 handle_test_result_xfail()                        577 handle_test_result_xfail()
578 {                                                 578 {
579         local test_name=$1; shift                 579         local test_name=$1; shift
580         local opt_str=$1; shift                   580         local opt_str=$1; shift
581                                                   581 
582         log_test_result "$test_name" "$opt_str    582         log_test_result "$test_name" "$opt_str" XFAIL "$retmsg"
583         pause_on_fail                             583         pause_on_fail
584 }                                                 584 }
585                                                   585 
586 handle_test_result_skip()                         586 handle_test_result_skip()
587 {                                                 587 {
588         local test_name=$1; shift                 588         local test_name=$1; shift
589         local opt_str=$1; shift                   589         local opt_str=$1; shift
590                                                   590 
591         log_test_result "$test_name" "$opt_str    591         log_test_result "$test_name" "$opt_str" SKIP "$retmsg"
592 }                                                 592 }
593                                                   593 
594 log_test()                                        594 log_test()
595 {                                                 595 {
596         local test_name=$1                        596         local test_name=$1
597         local opt_str=$2                          597         local opt_str=$2
598                                                   598 
599         if [[ $# -eq 2 ]]; then                   599         if [[ $# -eq 2 ]]; then
600                 opt_str="($opt_str)"              600                 opt_str="($opt_str)"
601         fi                                        601         fi
602                                                   602 
603         if ((RET == ksft_pass)); then             603         if ((RET == ksft_pass)); then
604                 handle_test_result_pass "$test    604                 handle_test_result_pass "$test_name" "$opt_str"
605         elif ((RET == ksft_xfail)); then          605         elif ((RET == ksft_xfail)); then
606                 handle_test_result_xfail "$tes    606                 handle_test_result_xfail "$test_name" "$opt_str"
607         elif ((RET == ksft_skip)); then           607         elif ((RET == ksft_skip)); then
608                 handle_test_result_skip "$test    608                 handle_test_result_skip "$test_name" "$opt_str"
609         else                                      609         else
610                 handle_test_result_fail "$test    610                 handle_test_result_fail "$test_name" "$opt_str"
611         fi                                        611         fi
612                                                   612 
613         EXIT_STATUS=$(ksft_exit_status_merge $    613         EXIT_STATUS=$(ksft_exit_status_merge $EXIT_STATUS $RET)
614         return $RET                               614         return $RET
615 }                                                 615 }
616                                                   616 
617 log_test_skip()                                   617 log_test_skip()
618 {                                                 618 {
619         RET=$ksft_skip retmsg= log_test "$@"      619         RET=$ksft_skip retmsg= log_test "$@"
620 }                                                 620 }
621                                                   621 
622 log_test_xfail()                                  622 log_test_xfail()
623 {                                                 623 {
624         RET=$ksft_xfail retmsg= log_test "$@"     624         RET=$ksft_xfail retmsg= log_test "$@"
625 }                                                 625 }
626                                                   626 
627 log_info()                                        627 log_info()
628 {                                                 628 {
629         local msg=$1                              629         local msg=$1
630                                                   630 
631         echo "INFO: $msg"                         631         echo "INFO: $msg"
632 }                                                 632 }
633                                                   633 
634 not()                                             634 not()
635 {                                                 635 {
636         "$@"                                      636         "$@"
637         [[ $? != 0 ]]                             637         [[ $? != 0 ]]
638 }                                                 638 }
639                                                   639 
640 get_max()                                         640 get_max()
641 {                                                 641 {
642         local arr=("$@")                          642         local arr=("$@")
643                                                   643 
644         max=${arr[0]}                             644         max=${arr[0]}
645         for cur in ${arr[@]}; do                  645         for cur in ${arr[@]}; do
646                 if [[ $cur -gt $max ]]; then      646                 if [[ $cur -gt $max ]]; then
647                         max=$cur                  647                         max=$cur
648                 fi                                648                 fi
649         done                                      649         done
650                                                   650 
651         echo $max                                 651         echo $max
652 }                                                 652 }
653                                                   653 
654 grep_bridge_fdb()                                 654 grep_bridge_fdb()
655 {                                                 655 {
656         local addr=$1; shift                      656         local addr=$1; shift
657         local word                                657         local word
658         local flag                                658         local flag
659                                                   659 
660         if [ "$1" == "self" ] || [ "$1" == "ma    660         if [ "$1" == "self" ] || [ "$1" == "master" ]; then
661                 word=$1; shift                    661                 word=$1; shift
662                 if [ "$1" == "-v" ]; then         662                 if [ "$1" == "-v" ]; then
663                         flag=$1; shift            663                         flag=$1; shift
664                 fi                                664                 fi
665         fi                                        665         fi
666                                                   666 
667         $@ | grep $addr | grep $flag "$word"      667         $@ | grep $addr | grep $flag "$word"
668 }                                                 668 }
669                                                   669 
670 wait_for_port_up()                                670 wait_for_port_up()
671 {                                                 671 {
672         "$@" | grep -q "Link detected: yes"       672         "$@" | grep -q "Link detected: yes"
673 }                                                 673 }
674                                                   674 
675 wait_for_offload()                                675 wait_for_offload()
676 {                                                 676 {
677         "$@" | grep -q offload                    677         "$@" | grep -q offload
678 }                                                 678 }
679                                                   679 
680 wait_for_trap()                                   680 wait_for_trap()
681 {                                                 681 {
682         "$@" | grep -q trap                       682         "$@" | grep -q trap
683 }                                                 683 }
684                                                   684 
685 setup_wait_dev()                                  685 setup_wait_dev()
686 {                                                 686 {
687         local dev=$1; shift                       687         local dev=$1; shift
688         local wait_time=${1:-$WAIT_TIME}; shif    688         local wait_time=${1:-$WAIT_TIME}; shift
689                                                   689 
690         setup_wait_dev_with_timeout "$dev" $IN    690         setup_wait_dev_with_timeout "$dev" $INTERFACE_TIMEOUT $wait_time
691                                                   691 
692         if (($?)); then                           692         if (($?)); then
693                 check_err 1                       693                 check_err 1
694                 log_test setup_wait_dev ": Int    694                 log_test setup_wait_dev ": Interface $dev does not come up."
695                 exit 1                            695                 exit 1
696         fi                                        696         fi
697 }                                                 697 }
698                                                   698 
699 setup_wait_dev_with_timeout()                     699 setup_wait_dev_with_timeout()
700 {                                                 700 {
701         local dev=$1; shift                       701         local dev=$1; shift
702         local max_iterations=${1:-$WAIT_TIMEOU    702         local max_iterations=${1:-$WAIT_TIMEOUT}; shift
703         local wait_time=${1:-$WAIT_TIME}; shif    703         local wait_time=${1:-$WAIT_TIME}; shift
704         local i                                   704         local i
705                                                   705 
706         for ((i = 1; i <= $max_iterations; ++i    706         for ((i = 1; i <= $max_iterations; ++i)); do
707                 ip link show dev $dev up \        707                 ip link show dev $dev up \
708                         | grep 'state UP' &> /    708                         | grep 'state UP' &> /dev/null
709                 if [[ $? -ne 0 ]]; then           709                 if [[ $? -ne 0 ]]; then
710                         sleep 1                   710                         sleep 1
711                 else                              711                 else
712                         sleep $wait_time          712                         sleep $wait_time
713                         return 0                  713                         return 0
714                 fi                                714                 fi
715         done                                      715         done
716                                                   716 
717         return 1                                  717         return 1
718 }                                                 718 }
719                                                   719 
720 setup_wait()                                      720 setup_wait()
721 {                                                 721 {
722         local num_netifs=${1:-$NUM_NETIFS}        722         local num_netifs=${1:-$NUM_NETIFS}
723         local i                                   723         local i
724                                                   724 
725         for ((i = 1; i <= num_netifs; ++i)); d    725         for ((i = 1; i <= num_netifs; ++i)); do
726                 setup_wait_dev ${NETIFS[p$i]}     726                 setup_wait_dev ${NETIFS[p$i]} 0
727         done                                      727         done
728                                                   728 
729         # Make sure links are ready.              729         # Make sure links are ready.
730         sleep $WAIT_TIME                          730         sleep $WAIT_TIME
731 }                                                 731 }
732                                                   732 
733 wait_for_dev()                                    733 wait_for_dev()
734 {                                                 734 {
735         local dev=$1; shift                       735         local dev=$1; shift
736         local timeout=${1:-$WAIT_TIMEOUT}; shi    736         local timeout=${1:-$WAIT_TIMEOUT}; shift
737                                                   737 
738         slowwait $timeout ip link show dev $de    738         slowwait $timeout ip link show dev $dev &> /dev/null
739         if (( $? )); then                         739         if (( $? )); then
740                 check_err 1                       740                 check_err 1
741                 log_test wait_for_dev "Interfa    741                 log_test wait_for_dev "Interface $dev did not appear."
742                 exit $EXIT_STATUS                 742                 exit $EXIT_STATUS
743         fi                                        743         fi
744 }                                                 744 }
745                                                   745 
746 cmd_jq()                                          746 cmd_jq()
747 {                                                 747 {
748         local cmd=$1                              748         local cmd=$1
749         local jq_exp=$2                           749         local jq_exp=$2
750         local jq_opts=$3                          750         local jq_opts=$3
751         local ret                                 751         local ret
752         local output                              752         local output
753                                                   753 
754         output="$($cmd)"                          754         output="$($cmd)"
755         # it the command fails, return error r    755         # it the command fails, return error right away
756         ret=$?                                    756         ret=$?
757         if [[ $ret -ne 0 ]]; then                 757         if [[ $ret -ne 0 ]]; then
758                 return $ret                       758                 return $ret
759         fi                                        759         fi
760         output=$(echo $output | jq -r $jq_opts    760         output=$(echo $output | jq -r $jq_opts "$jq_exp")
761         ret=$?                                    761         ret=$?
762         if [[ $ret -ne 0 ]]; then                 762         if [[ $ret -ne 0 ]]; then
763                 return $ret                       763                 return $ret
764         fi                                        764         fi
765         echo $output                              765         echo $output
766         # return success only in case of non-e    766         # return success only in case of non-empty output
767         [ ! -z "$output" ]                        767         [ ! -z "$output" ]
768 }                                                 768 }
769                                                   769 
770 pre_cleanup()                                     770 pre_cleanup()
771 {                                                 771 {
772         if [ "${PAUSE_ON_CLEANUP}" = "yes" ];     772         if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
773                 echo "Pausing before cleanup,     773                 echo "Pausing before cleanup, hit any key to continue"
774                 read                              774                 read
775         fi                                        775         fi
776                                                   776 
777         if [[ "$STABLE_MAC_ADDRS" = "yes" ]];     777         if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
778                 mac_addr_restore                  778                 mac_addr_restore
779         fi                                        779         fi
780 }                                                 780 }
781                                                   781 
782 vrf_prepare()                                     782 vrf_prepare()
783 {                                                 783 {
784         ip -4 rule add pref 32765 table local     784         ip -4 rule add pref 32765 table local
785         ip -4 rule del pref 0                     785         ip -4 rule del pref 0
786         ip -6 rule add pref 32765 table local     786         ip -6 rule add pref 32765 table local
787         ip -6 rule del pref 0                     787         ip -6 rule del pref 0
788 }                                                 788 }
789                                                   789 
790 vrf_cleanup()                                     790 vrf_cleanup()
791 {                                                 791 {
792         ip -6 rule add pref 0 table local         792         ip -6 rule add pref 0 table local
793         ip -6 rule del pref 32765                 793         ip -6 rule del pref 32765
794         ip -4 rule add pref 0 table local         794         ip -4 rule add pref 0 table local
795         ip -4 rule del pref 32765                 795         ip -4 rule del pref 32765
796 }                                                 796 }
797                                                   797 
798 __last_tb_id=0                                    798 __last_tb_id=0
799 declare -A __TB_IDS                               799 declare -A __TB_IDS
800                                                   800 
801 __vrf_td_id_assign()                              801 __vrf_td_id_assign()
802 {                                                 802 {
803         local vrf_name=$1                         803         local vrf_name=$1
804                                                   804 
805         __last_tb_id=$((__last_tb_id + 1))        805         __last_tb_id=$((__last_tb_id + 1))
806         __TB_IDS[$vrf_name]=$__last_tb_id         806         __TB_IDS[$vrf_name]=$__last_tb_id
807         return $__last_tb_id                      807         return $__last_tb_id
808 }                                                 808 }
809                                                   809 
810 __vrf_td_id_lookup()                              810 __vrf_td_id_lookup()
811 {                                                 811 {
812         local vrf_name=$1                         812         local vrf_name=$1
813                                                   813 
814         return ${__TB_IDS[$vrf_name]}             814         return ${__TB_IDS[$vrf_name]}
815 }                                                 815 }
816                                                   816 
817 vrf_create()                                      817 vrf_create()
818 {                                                 818 {
819         local vrf_name=$1                         819         local vrf_name=$1
820         local tb_id                               820         local tb_id
821                                                   821 
822         __vrf_td_id_assign $vrf_name              822         __vrf_td_id_assign $vrf_name
823         tb_id=$?                                  823         tb_id=$?
824                                                   824 
825         ip link add dev $vrf_name type vrf tab    825         ip link add dev $vrf_name type vrf table $tb_id
826         ip -4 route add table $tb_id unreachab    826         ip -4 route add table $tb_id unreachable default metric 4278198272
827         ip -6 route add table $tb_id unreachab    827         ip -6 route add table $tb_id unreachable default metric 4278198272
828 }                                                 828 }
829                                                   829 
830 vrf_destroy()                                     830 vrf_destroy()
831 {                                                 831 {
832         local vrf_name=$1                         832         local vrf_name=$1
833         local tb_id                               833         local tb_id
834                                                   834 
835         __vrf_td_id_lookup $vrf_name              835         __vrf_td_id_lookup $vrf_name
836         tb_id=$?                                  836         tb_id=$?
837                                                   837 
838         ip -6 route del table $tb_id unreachab    838         ip -6 route del table $tb_id unreachable default metric 4278198272
839         ip -4 route del table $tb_id unreachab    839         ip -4 route del table $tb_id unreachable default metric 4278198272
840         ip link del dev $vrf_name                 840         ip link del dev $vrf_name
841 }                                                 841 }
842                                                   842 
843 __addr_add_del()                                  843 __addr_add_del()
844 {                                                 844 {
845         local if_name=$1                          845         local if_name=$1
846         local add_del=$2                          846         local add_del=$2
847         local array                               847         local array
848                                                   848 
849         shift                                     849         shift
850         shift                                     850         shift
851         array=("${@}")                            851         array=("${@}")
852                                                   852 
853         for addrstr in "${array[@]}"; do          853         for addrstr in "${array[@]}"; do
854                 ip address $add_del $addrstr d    854                 ip address $add_del $addrstr dev $if_name
855         done                                      855         done
856 }                                                 856 }
857                                                   857 
858 __simple_if_init()                                858 __simple_if_init()
859 {                                                 859 {
860         local if_name=$1; shift                   860         local if_name=$1; shift
861         local vrf_name=$1; shift                  861         local vrf_name=$1; shift
862         local addrs=("${@}")                      862         local addrs=("${@}")
863                                                   863 
864         ip link set dev $if_name master $vrf_n    864         ip link set dev $if_name master $vrf_name
865         ip link set dev $if_name up               865         ip link set dev $if_name up
866                                                   866 
867         __addr_add_del $if_name add "${addrs[@    867         __addr_add_del $if_name add "${addrs[@]}"
868 }                                                 868 }
869                                                   869 
870 __simple_if_fini()                                870 __simple_if_fini()
871 {                                                 871 {
872         local if_name=$1; shift                   872         local if_name=$1; shift
873         local addrs=("${@}")                      873         local addrs=("${@}")
874                                                   874 
875         __addr_add_del $if_name del "${addrs[@    875         __addr_add_del $if_name del "${addrs[@]}"
876                                                   876 
877         ip link set dev $if_name down             877         ip link set dev $if_name down
878         ip link set dev $if_name nomaster         878         ip link set dev $if_name nomaster
879 }                                                 879 }
880                                                   880 
881 simple_if_init()                                  881 simple_if_init()
882 {                                                 882 {
883         local if_name=$1                          883         local if_name=$1
884         local vrf_name                            884         local vrf_name
885         local array                               885         local array
886                                                   886 
887         shift                                     887         shift
888         vrf_name=v$if_name                        888         vrf_name=v$if_name
889         array=("${@}")                            889         array=("${@}")
890                                                   890 
891         vrf_create $vrf_name                      891         vrf_create $vrf_name
892         ip link set dev $vrf_name up              892         ip link set dev $vrf_name up
893         __simple_if_init $if_name $vrf_name "$    893         __simple_if_init $if_name $vrf_name "${array[@]}"
894 }                                                 894 }
895                                                   895 
896 simple_if_fini()                                  896 simple_if_fini()
897 {                                                 897 {
898         local if_name=$1                          898         local if_name=$1
899         local vrf_name                            899         local vrf_name
900         local array                               900         local array
901                                                   901 
902         shift                                     902         shift
903         vrf_name=v$if_name                        903         vrf_name=v$if_name
904         array=("${@}")                            904         array=("${@}")
905                                                   905 
906         __simple_if_fini $if_name "${array[@]}    906         __simple_if_fini $if_name "${array[@]}"
907         vrf_destroy $vrf_name                     907         vrf_destroy $vrf_name
908 }                                                 908 }
909                                                   909 
910 tunnel_create()                                   910 tunnel_create()
911 {                                                 911 {
912         local name=$1; shift                      912         local name=$1; shift
913         local type=$1; shift                      913         local type=$1; shift
914         local local=$1; shift                     914         local local=$1; shift
915         local remote=$1; shift                    915         local remote=$1; shift
916                                                   916 
917         ip link add name $name type $type \       917         ip link add name $name type $type \
918            local $local remote $remote "$@"       918            local $local remote $remote "$@"
919         ip link set dev $name up                  919         ip link set dev $name up
920 }                                                 920 }
921                                                   921 
922 tunnel_destroy()                                  922 tunnel_destroy()
923 {                                                 923 {
924         local name=$1; shift                      924         local name=$1; shift
925                                                   925 
926         ip link del dev $name                     926         ip link del dev $name
927 }                                                 927 }
928                                                   928 
929 vlan_create()                                     929 vlan_create()
930 {                                                 930 {
931         local if_name=$1; shift                   931         local if_name=$1; shift
932         local vid=$1; shift                       932         local vid=$1; shift
933         local vrf=$1; shift                       933         local vrf=$1; shift
934         local ips=("${@}")                        934         local ips=("${@}")
935         local name=$if_name.$vid                  935         local name=$if_name.$vid
936                                                   936 
937         ip link add name $name link $if_name t    937         ip link add name $name link $if_name type vlan id $vid
938         if [ "$vrf" != "" ]; then                 938         if [ "$vrf" != "" ]; then
939                 ip link set dev $name master $    939                 ip link set dev $name master $vrf
940         fi                                        940         fi
941         ip link set dev $name up                  941         ip link set dev $name up
942         __addr_add_del $name add "${ips[@]}"      942         __addr_add_del $name add "${ips[@]}"
943 }                                                 943 }
944                                                   944 
945 vlan_destroy()                                    945 vlan_destroy()
946 {                                                 946 {
947         local if_name=$1; shift                   947         local if_name=$1; shift
948         local vid=$1; shift                       948         local vid=$1; shift
949         local name=$if_name.$vid                  949         local name=$if_name.$vid
950                                                   950 
951         ip link del dev $name                     951         ip link del dev $name
952 }                                                 952 }
953                                                   953 
954 team_create()                                     954 team_create()
955 {                                                 955 {
956         local if_name=$1; shift                   956         local if_name=$1; shift
957         local mode=$1; shift                      957         local mode=$1; shift
958                                                   958 
959         require_command $TEAMD                    959         require_command $TEAMD
960         $TEAMD -t $if_name -d -c '{"runner": {    960         $TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
961         for slave in "$@"; do                     961         for slave in "$@"; do
962                 ip link set dev $slave down       962                 ip link set dev $slave down
963                 ip link set dev $slave master     963                 ip link set dev $slave master $if_name
964                 ip link set dev $slave up         964                 ip link set dev $slave up
965         done                                      965         done
966         ip link set dev $if_name up               966         ip link set dev $if_name up
967 }                                                 967 }
968                                                   968 
969 team_destroy()                                    969 team_destroy()
970 {                                                 970 {
971         local if_name=$1; shift                   971         local if_name=$1; shift
972                                                   972 
973         $TEAMD -t $if_name -k                     973         $TEAMD -t $if_name -k
974 }                                                 974 }
975                                                   975 
976 master_name_get()                                 976 master_name_get()
977 {                                                 977 {
978         local if_name=$1                          978         local if_name=$1
979                                                   979 
980         ip -j link show dev $if_name | jq -r '    980         ip -j link show dev $if_name | jq -r '.[]["master"]'
981 }                                                 981 }
982                                                   982 
983 link_stats_get()                                  983 link_stats_get()
984 {                                                 984 {
985         local if_name=$1; shift                   985         local if_name=$1; shift
986         local dir=$1; shift                       986         local dir=$1; shift
987         local stat=$1; shift                      987         local stat=$1; shift
988                                                   988 
989         ip -j -s link show dev $if_name \         989         ip -j -s link show dev $if_name \
990                 | jq '.[]["stats64"]["'$dir'"]    990                 | jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
991 }                                                 991 }
992                                                   992 
993 link_stats_tx_packets_get()                       993 link_stats_tx_packets_get()
994 {                                                 994 {
995         link_stats_get $1 tx packets              995         link_stats_get $1 tx packets
996 }                                                 996 }
997                                                   997 
998 link_stats_rx_errors_get()                        998 link_stats_rx_errors_get()
999 {                                                 999 {
1000         link_stats_get $1 rx errors              1000         link_stats_get $1 rx errors
1001 }                                                1001 }
1002                                                  1002 
1003 ethtool_stats_get()                              1003 ethtool_stats_get()
1004 {                                                1004 {
1005         local dev=$1; shift                      1005         local dev=$1; shift
1006         local stat=$1; shift                     1006         local stat=$1; shift
1007                                                  1007 
1008         ethtool -S $dev | grep "^ *$stat:" |     1008         ethtool -S $dev | grep "^ *$stat:" | head -n 1 | cut -d: -f2
1009 }                                                1009 }
1010                                                  1010 
1011 ethtool_std_stats_get()                          1011 ethtool_std_stats_get()
1012 {                                                1012 {
1013         local dev=$1; shift                      1013         local dev=$1; shift
1014         local grp=$1; shift                      1014         local grp=$1; shift
1015         local name=$1; shift                     1015         local name=$1; shift
1016         local src=$1; shift                      1016         local src=$1; shift
1017                                                  1017 
1018         ethtool --json -S $dev --groups $grp     1018         ethtool --json -S $dev --groups $grp -- --src $src | \
1019                 jq '.[]."'"$grp"'"."'$name'"'    1019                 jq '.[]."'"$grp"'"."'$name'"'
1020 }                                                1020 }
1021                                                  1021 
1022 qdisc_stats_get()                                1022 qdisc_stats_get()
1023 {                                                1023 {
1024         local dev=$1; shift                      1024         local dev=$1; shift
1025         local handle=$1; shift                   1025         local handle=$1; shift
1026         local selector=$1; shift                 1026         local selector=$1; shift
1027                                                  1027 
1028         tc -j -s qdisc show dev "$dev" \         1028         tc -j -s qdisc show dev "$dev" \
1029             | jq '.[] | select(.handle == "'"    1029             | jq '.[] | select(.handle == "'"$handle"'") | '"$selector"
1030 }                                                1030 }
1031                                                  1031 
1032 qdisc_parent_stats_get()                         1032 qdisc_parent_stats_get()
1033 {                                                1033 {
1034         local dev=$1; shift                      1034         local dev=$1; shift
1035         local parent=$1; shift                   1035         local parent=$1; shift
1036         local selector=$1; shift                 1036         local selector=$1; shift
1037                                                  1037 
1038         tc -j -s qdisc show dev "$dev" invisi    1038         tc -j -s qdisc show dev "$dev" invisible \
1039             | jq '.[] | select(.parent == "'"    1039             | jq '.[] | select(.parent == "'"$parent"'") | '"$selector"
1040 }                                                1040 }
1041                                                  1041 
1042 ipv6_stats_get()                                 1042 ipv6_stats_get()
1043 {                                                1043 {
1044         local dev=$1; shift                      1044         local dev=$1; shift
1045         local stat=$1; shift                     1045         local stat=$1; shift
1046                                                  1046 
1047         cat /proc/net/dev_snmp6/$dev | grep "    1047         cat /proc/net/dev_snmp6/$dev | grep "^$stat" | cut -f2
1048 }                                                1048 }
1049                                                  1049 
1050 hw_stats_get()                                   1050 hw_stats_get()
1051 {                                                1051 {
1052         local suite=$1; shift                    1052         local suite=$1; shift
1053         local if_name=$1; shift                  1053         local if_name=$1; shift
1054         local dir=$1; shift                      1054         local dir=$1; shift
1055         local stat=$1; shift                     1055         local stat=$1; shift
1056                                                  1056 
1057         ip -j stats show dev $if_name group o    1057         ip -j stats show dev $if_name group offload subgroup $suite |
1058                 jq ".[0].stats64.$dir.$stat"     1058                 jq ".[0].stats64.$dir.$stat"
1059 }                                                1059 }
1060                                                  1060 
1061 __nh_stats_get()                                 1061 __nh_stats_get()
1062 {                                                1062 {
1063         local key=$1; shift                      1063         local key=$1; shift
1064         local group_id=$1; shift                 1064         local group_id=$1; shift
1065         local member_id=$1; shift                1065         local member_id=$1; shift
1066                                                  1066 
1067         ip -j -s -s nexthop show id $group_id    1067         ip -j -s -s nexthop show id $group_id |
1068             jq --argjson member_id "$member_i    1068             jq --argjson member_id "$member_id" --arg key "$key" \
1069                '.[].group_stats[] | select(.i    1069                '.[].group_stats[] | select(.id == $member_id) | .[$key]'
1070 }                                                1070 }
1071                                                  1071 
1072 nh_stats_get()                                   1072 nh_stats_get()
1073 {                                                1073 {
1074         local group_id=$1; shift                 1074         local group_id=$1; shift
1075         local member_id=$1; shift                1075         local member_id=$1; shift
1076                                                  1076 
1077         __nh_stats_get packets "$group_id" "$    1077         __nh_stats_get packets "$group_id" "$member_id"
1078 }                                                1078 }
1079                                                  1079 
1080 nh_stats_get_hw()                                1080 nh_stats_get_hw()
1081 {                                                1081 {
1082         local group_id=$1; shift                 1082         local group_id=$1; shift
1083         local member_id=$1; shift                1083         local member_id=$1; shift
1084                                                  1084 
1085         __nh_stats_get packets_hw "$group_id"    1085         __nh_stats_get packets_hw "$group_id" "$member_id"
1086 }                                                1086 }
1087                                                  1087 
1088 humanize()                                       1088 humanize()
1089 {                                                1089 {
1090         local speed=$1; shift                    1090         local speed=$1; shift
1091                                                  1091 
1092         for unit in bps Kbps Mbps Gbps; do       1092         for unit in bps Kbps Mbps Gbps; do
1093                 if (($(echo "$speed < 1024" |    1093                 if (($(echo "$speed < 1024" | bc))); then
1094                         break                    1094                         break
1095                 fi                               1095                 fi
1096                                                  1096 
1097                 speed=$(echo "scale=1; $speed    1097                 speed=$(echo "scale=1; $speed / 1024" | bc)
1098         done                                     1098         done
1099                                                  1099 
1100         echo "$speed${unit}"                     1100         echo "$speed${unit}"
1101 }                                                1101 }
1102                                                  1102 
1103 rate()                                           1103 rate()
1104 {                                                1104 {
1105         local t0=$1; shift                       1105         local t0=$1; shift
1106         local t1=$1; shift                       1106         local t1=$1; shift
1107         local interval=$1; shift                 1107         local interval=$1; shift
1108                                                  1108 
1109         echo $((8 * (t1 - t0) / interval))       1109         echo $((8 * (t1 - t0) / interval))
1110 }                                                1110 }
1111                                                  1111 
1112 packets_rate()                                   1112 packets_rate()
1113 {                                                1113 {
1114         local t0=$1; shift                       1114         local t0=$1; shift
1115         local t1=$1; shift                       1115         local t1=$1; shift
1116         local interval=$1; shift                 1116         local interval=$1; shift
1117                                                  1117 
1118         echo $(((t1 - t0) / interval))           1118         echo $(((t1 - t0) / interval))
1119 }                                                1119 }
1120                                                  1120 
1121 mac_get()                                        1121 mac_get()
1122 {                                                1122 {
1123         local if_name=$1                         1123         local if_name=$1
1124                                                  1124 
1125         ip -j link show dev $if_name | jq -r     1125         ip -j link show dev $if_name | jq -r '.[]["address"]'
1126 }                                                1126 }
1127                                                  1127 
1128 ether_addr_to_u64()                              1128 ether_addr_to_u64()
1129 {                                                1129 {
1130         local addr="$1"                          1130         local addr="$1"
1131         local order="$((1 << 40))"               1131         local order="$((1 << 40))"
1132         local val=0                              1132         local val=0
1133         local byte                               1133         local byte
1134                                                  1134 
1135         addr="${addr//:/ }"                      1135         addr="${addr//:/ }"
1136                                                  1136 
1137         for byte in $addr; do                    1137         for byte in $addr; do
1138                 byte="0x$byte"                   1138                 byte="0x$byte"
1139                 val=$((val + order * byte))      1139                 val=$((val + order * byte))
1140                 order=$((order >> 8))            1140                 order=$((order >> 8))
1141         done                                     1141         done
1142                                                  1142 
1143         printf "0x%x" $val                       1143         printf "0x%x" $val
1144 }                                                1144 }
1145                                                  1145 
1146 u64_to_ether_addr()                              1146 u64_to_ether_addr()
1147 {                                                1147 {
1148         local val=$1                             1148         local val=$1
1149         local byte                               1149         local byte
1150         local i                                  1150         local i
1151                                                  1151 
1152         for ((i = 40; i >= 0; i -= 8)); do       1152         for ((i = 40; i >= 0; i -= 8)); do
1153                 byte=$(((val & (0xff << i)) >    1153                 byte=$(((val & (0xff << i)) >> i))
1154                 printf "%02x" $byte              1154                 printf "%02x" $byte
1155                 if [ $i -ne 0 ]; then            1155                 if [ $i -ne 0 ]; then
1156                         printf ":"               1156                         printf ":"
1157                 fi                               1157                 fi
1158         done                                     1158         done
1159 }                                                1159 }
1160                                                  1160 
1161 ipv6_lladdr_get()                                1161 ipv6_lladdr_get()
1162 {                                                1162 {
1163         local if_name=$1                         1163         local if_name=$1
1164                                                  1164 
1165         ip -j addr show dev $if_name | \         1165         ip -j addr show dev $if_name | \
1166                 jq -r '.[]["addr_info"][] | s    1166                 jq -r '.[]["addr_info"][] | select(.scope == "link").local' | \
1167                 head -1                          1167                 head -1
1168 }                                                1168 }
1169                                                  1169 
1170 bridge_ageing_time_get()                         1170 bridge_ageing_time_get()
1171 {                                                1171 {
1172         local bridge=$1                          1172         local bridge=$1
1173         local ageing_time                        1173         local ageing_time
1174                                                  1174 
1175         # Need to divide by 100 to convert to    1175         # Need to divide by 100 to convert to seconds.
1176         ageing_time=$(ip -j -d link show dev     1176         ageing_time=$(ip -j -d link show dev $bridge \
1177                       | jq '.[]["linkinfo"]["    1177                       | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
1178         echo $((ageing_time / 100))              1178         echo $((ageing_time / 100))
1179 }                                                1179 }
1180                                                  1180 
1181 declare -A SYSCTL_ORIG                           1181 declare -A SYSCTL_ORIG
1182 sysctl_save()                                    1182 sysctl_save()
1183 {                                                1183 {
1184         local key=$1; shift                      1184         local key=$1; shift
1185                                                  1185 
1186         SYSCTL_ORIG[$key]=$(sysctl -n $key)      1186         SYSCTL_ORIG[$key]=$(sysctl -n $key)
1187 }                                                1187 }
1188                                                  1188 
1189 sysctl_set()                                     1189 sysctl_set()
1190 {                                                1190 {
1191         local key=$1; shift                      1191         local key=$1; shift
1192         local value=$1; shift                    1192         local value=$1; shift
1193                                                  1193 
1194         sysctl_save "$key"                       1194         sysctl_save "$key"
1195         sysctl -qw $key="$value"                 1195         sysctl -qw $key="$value"
1196 }                                                1196 }
1197                                                  1197 
1198 sysctl_restore()                                 1198 sysctl_restore()
1199 {                                                1199 {
1200         local key=$1; shift                      1200         local key=$1; shift
1201                                                  1201 
1202         sysctl -qw $key="${SYSCTL_ORIG[$key]}    1202         sysctl -qw $key="${SYSCTL_ORIG[$key]}"
1203 }                                                1203 }
1204                                                  1204 
1205 forwarding_enable()                              1205 forwarding_enable()
1206 {                                                1206 {
1207         sysctl_set net.ipv4.conf.all.forwardi    1207         sysctl_set net.ipv4.conf.all.forwarding 1
1208         sysctl_set net.ipv6.conf.all.forwardi    1208         sysctl_set net.ipv6.conf.all.forwarding 1
1209 }                                                1209 }
1210                                                  1210 
1211 forwarding_restore()                             1211 forwarding_restore()
1212 {                                                1212 {
1213         sysctl_restore net.ipv6.conf.all.forw    1213         sysctl_restore net.ipv6.conf.all.forwarding
1214         sysctl_restore net.ipv4.conf.all.forw    1214         sysctl_restore net.ipv4.conf.all.forwarding
1215 }                                                1215 }
1216                                                  1216 
1217 declare -A MTU_ORIG                              1217 declare -A MTU_ORIG
1218 mtu_set()                                        1218 mtu_set()
1219 {                                                1219 {
1220         local dev=$1; shift                      1220         local dev=$1; shift
1221         local mtu=$1; shift                      1221         local mtu=$1; shift
1222                                                  1222 
1223         MTU_ORIG["$dev"]=$(ip -j link show de    1223         MTU_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].mtu')
1224         ip link set dev $dev mtu $mtu            1224         ip link set dev $dev mtu $mtu
1225 }                                                1225 }
1226                                                  1226 
1227 mtu_restore()                                    1227 mtu_restore()
1228 {                                                1228 {
1229         local dev=$1; shift                      1229         local dev=$1; shift
1230                                                  1230 
1231         ip link set dev $dev mtu ${MTU_ORIG["    1231         ip link set dev $dev mtu ${MTU_ORIG["$dev"]}
1232 }                                                1232 }
1233                                                  1233 
1234 tc_offload_check()                               1234 tc_offload_check()
1235 {                                                1235 {
1236         local num_netifs=${1:-$NUM_NETIFS}       1236         local num_netifs=${1:-$NUM_NETIFS}
1237                                                  1237 
1238         for ((i = 1; i <= num_netifs; ++i));     1238         for ((i = 1; i <= num_netifs; ++i)); do
1239                 ethtool -k ${NETIFS[p$i]} \      1239                 ethtool -k ${NETIFS[p$i]} \
1240                         | grep "hw-tc-offload    1240                         | grep "hw-tc-offload: on" &> /dev/null
1241                 if [[ $? -ne 0 ]]; then          1241                 if [[ $? -ne 0 ]]; then
1242                         return 1                 1242                         return 1
1243                 fi                               1243                 fi
1244         done                                     1244         done
1245                                                  1245 
1246         return 0                                 1246         return 0
1247 }                                                1247 }
1248                                                  1248 
1249 trap_install()                                   1249 trap_install()
1250 {                                                1250 {
1251         local dev=$1; shift                      1251         local dev=$1; shift
1252         local direction=$1; shift                1252         local direction=$1; shift
1253                                                  1253 
1254         # Some devices may not support or nee    1254         # Some devices may not support or need in-hardware trapping of traffic
1255         # (e.g. the veth pairs that this libr    1255         # (e.g. the veth pairs that this library creates for non-existent
1256         # loopbacks). Use continue instead, s    1256         # loopbacks). Use continue instead, so that there is a filter in there
1257         # (some tests check counters), and so    1257         # (some tests check counters), and so that other filters are still
1258         # processed.                             1258         # processed.
1259         tc filter add dev $dev $direction pre    1259         tc filter add dev $dev $direction pref 1 \
1260                 flower skip_sw action trap 2>    1260                 flower skip_sw action trap 2>/dev/null \
1261             || tc filter add dev $dev $direct    1261             || tc filter add dev $dev $direction pref 1 \
1262                        flower action continue    1262                        flower action continue
1263 }                                                1263 }
1264                                                  1264 
1265 trap_uninstall()                                 1265 trap_uninstall()
1266 {                                                1266 {
1267         local dev=$1; shift                      1267         local dev=$1; shift
1268         local direction=$1; shift                1268         local direction=$1; shift
1269                                                  1269 
1270         tc filter del dev $dev $direction pre    1270         tc filter del dev $dev $direction pref 1 flower
1271 }                                                1271 }
1272                                                  1272 
1273 __icmp_capture_add_del()                         1273 __icmp_capture_add_del()
1274 {                                                1274 {
1275         local add_del=$1; shift                  1275         local add_del=$1; shift
1276         local pref=$1; shift                     1276         local pref=$1; shift
1277         local vsuf=$1; shift                     1277         local vsuf=$1; shift
1278         local tundev=$1; shift                   1278         local tundev=$1; shift
1279         local filter=$1; shift                   1279         local filter=$1; shift
1280                                                  1280 
1281         tc filter $add_del dev "$tundev" ingr    1281         tc filter $add_del dev "$tundev" ingress \
1282            proto ip$vsuf pref $pref \            1282            proto ip$vsuf pref $pref \
1283            flower ip_proto icmp$vsuf $filter     1283            flower ip_proto icmp$vsuf $filter \
1284            action pass                           1284            action pass
1285 }                                                1285 }
1286                                                  1286 
1287 icmp_capture_install()                           1287 icmp_capture_install()
1288 {                                                1288 {
1289         local tundev=$1; shift                   1289         local tundev=$1; shift
1290         local filter=$1; shift                   1290         local filter=$1; shift
1291                                                  1291 
1292         __icmp_capture_add_del add 100 "" "$t    1292         __icmp_capture_add_del add 100 "" "$tundev" "$filter"
1293 }                                                1293 }
1294                                                  1294 
1295 icmp_capture_uninstall()                         1295 icmp_capture_uninstall()
1296 {                                                1296 {
1297         local tundev=$1; shift                   1297         local tundev=$1; shift
1298         local filter=$1; shift                   1298         local filter=$1; shift
1299                                                  1299 
1300         __icmp_capture_add_del del 100 "" "$t    1300         __icmp_capture_add_del del 100 "" "$tundev" "$filter"
1301 }                                                1301 }
1302                                                  1302 
1303 icmp6_capture_install()                          1303 icmp6_capture_install()
1304 {                                                1304 {
1305         local tundev=$1; shift                   1305         local tundev=$1; shift
1306         local filter=$1; shift                   1306         local filter=$1; shift
1307                                                  1307 
1308         __icmp_capture_add_del add 100 v6 "$t    1308         __icmp_capture_add_del add 100 v6 "$tundev" "$filter"
1309 }                                                1309 }
1310                                                  1310 
1311 icmp6_capture_uninstall()                        1311 icmp6_capture_uninstall()
1312 {                                                1312 {
1313         local tundev=$1; shift                   1313         local tundev=$1; shift
1314         local filter=$1; shift                   1314         local filter=$1; shift
1315                                                  1315 
1316         __icmp_capture_add_del del 100 v6 "$t    1316         __icmp_capture_add_del del 100 v6 "$tundev" "$filter"
1317 }                                                1317 }
1318                                                  1318 
1319 __vlan_capture_add_del()                         1319 __vlan_capture_add_del()
1320 {                                                1320 {
1321         local add_del=$1; shift                  1321         local add_del=$1; shift
1322         local pref=$1; shift                     1322         local pref=$1; shift
1323         local dev=$1; shift                      1323         local dev=$1; shift
1324         local filter=$1; shift                   1324         local filter=$1; shift
1325                                                  1325 
1326         tc filter $add_del dev "$dev" ingress    1326         tc filter $add_del dev "$dev" ingress \
1327            proto 802.1q pref $pref \             1327            proto 802.1q pref $pref \
1328            flower $filter \                      1328            flower $filter \
1329            action pass                           1329            action pass
1330 }                                                1330 }
1331                                                  1331 
1332 vlan_capture_install()                           1332 vlan_capture_install()
1333 {                                                1333 {
1334         local dev=$1; shift                      1334         local dev=$1; shift
1335         local filter=$1; shift                   1335         local filter=$1; shift
1336                                                  1336 
1337         __vlan_capture_add_del add 100 "$dev"    1337         __vlan_capture_add_del add 100 "$dev" "$filter"
1338 }                                                1338 }
1339                                                  1339 
1340 vlan_capture_uninstall()                         1340 vlan_capture_uninstall()
1341 {                                                1341 {
1342         local dev=$1; shift                      1342         local dev=$1; shift
1343         local filter=$1; shift                   1343         local filter=$1; shift
1344                                                  1344 
1345         __vlan_capture_add_del del 100 "$dev"    1345         __vlan_capture_add_del del 100 "$dev" "$filter"
1346 }                                                1346 }
1347                                                  1347 
1348 __dscp_capture_add_del()                         1348 __dscp_capture_add_del()
1349 {                                                1349 {
1350         local add_del=$1; shift                  1350         local add_del=$1; shift
1351         local dev=$1; shift                      1351         local dev=$1; shift
1352         local base=$1; shift                     1352         local base=$1; shift
1353         local dscp;                              1353         local dscp;
1354                                                  1354 
1355         for prio in {0..7}; do                   1355         for prio in {0..7}; do
1356                 dscp=$((base + prio))            1356                 dscp=$((base + prio))
1357                 __icmp_capture_add_del $add_d    1357                 __icmp_capture_add_del $add_del $((dscp + 100)) "" $dev \
1358                                        "skip_    1358                                        "skip_hw ip_tos $((dscp << 2))"
1359         done                                     1359         done
1360 }                                                1360 }
1361                                                  1361 
1362 dscp_capture_install()                           1362 dscp_capture_install()
1363 {                                                1363 {
1364         local dev=$1; shift                      1364         local dev=$1; shift
1365         local base=$1; shift                     1365         local base=$1; shift
1366                                                  1366 
1367         __dscp_capture_add_del add $dev $base    1367         __dscp_capture_add_del add $dev $base
1368 }                                                1368 }
1369                                                  1369 
1370 dscp_capture_uninstall()                         1370 dscp_capture_uninstall()
1371 {                                                1371 {
1372         local dev=$1; shift                      1372         local dev=$1; shift
1373         local base=$1; shift                     1373         local base=$1; shift
1374                                                  1374 
1375         __dscp_capture_add_del del $dev $base    1375         __dscp_capture_add_del del $dev $base
1376 }                                                1376 }
1377                                                  1377 
1378 dscp_fetch_stats()                               1378 dscp_fetch_stats()
1379 {                                                1379 {
1380         local dev=$1; shift                      1380         local dev=$1; shift
1381         local base=$1; shift                     1381         local base=$1; shift
1382                                                  1382 
1383         for prio in {0..7}; do                   1383         for prio in {0..7}; do
1384                 local dscp=$((base + prio))      1384                 local dscp=$((base + prio))
1385                 local t=$(tc_rule_stats_get $    1385                 local t=$(tc_rule_stats_get $dev $((dscp + 100)))
1386                 echo "[$dscp]=$t "               1386                 echo "[$dscp]=$t "
1387         done                                     1387         done
1388 }                                                1388 }
1389                                                  1389 
1390 matchall_sink_create()                           1390 matchall_sink_create()
1391 {                                                1391 {
1392         local dev=$1; shift                      1392         local dev=$1; shift
1393                                                  1393 
1394         tc qdisc add dev $dev clsact             1394         tc qdisc add dev $dev clsact
1395         tc filter add dev $dev ingress \         1395         tc filter add dev $dev ingress \
1396            pref 10000 \                          1396            pref 10000 \
1397            matchall \                            1397            matchall \
1398            action drop                           1398            action drop
1399 }                                                1399 }
1400                                                  1400 
1401 tests_run()                                      1401 tests_run()
1402 {                                                1402 {
1403         local current_test                       1403         local current_test
1404                                                  1404 
1405         for current_test in ${TESTS:-$ALL_TES    1405         for current_test in ${TESTS:-$ALL_TESTS}; do
1406                 $current_test                    1406                 $current_test
1407         done                                     1407         done
1408 }                                                1408 }
1409                                                  1409 
1410 multipath_eval()                                 1410 multipath_eval()
1411 {                                                1411 {
1412         local desc="$1"                          1412         local desc="$1"
1413         local weight_rp12=$2                     1413         local weight_rp12=$2
1414         local weight_rp13=$3                     1414         local weight_rp13=$3
1415         local packets_rp12=$4                    1415         local packets_rp12=$4
1416         local packets_rp13=$5                    1416         local packets_rp13=$5
1417         local weights_ratio packets_ratio dif    1417         local weights_ratio packets_ratio diff
1418                                                  1418 
1419         RET=0                                    1419         RET=0
1420                                                  1420 
1421         if [[ "$weight_rp12" -gt "$weight_rp1    1421         if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1422                 weights_ratio=$(echo "scale=2    1422                 weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
1423                                 | bc -l)         1423                                 | bc -l)
1424         else                                     1424         else
1425                 weights_ratio=$(echo "scale=2    1425                 weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
1426                                 | bc -l)         1426                                 | bc -l)
1427         fi                                       1427         fi
1428                                                  1428 
1429         if [[ "$packets_rp12" -eq "0" || "$pa    1429         if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
1430                check_err 1 "Packet difference    1430                check_err 1 "Packet difference is 0"
1431                log_test "Multipath"              1431                log_test "Multipath"
1432                log_info "Expected ratio $weig    1432                log_info "Expected ratio $weights_ratio"
1433                return                            1433                return
1434         fi                                       1434         fi
1435                                                  1435 
1436         if [[ "$weight_rp12" -gt "$weight_rp1    1436         if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1437                 packets_ratio=$(echo "scale=2    1437                 packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
1438                                 | bc -l)         1438                                 | bc -l)
1439         else                                     1439         else
1440                 packets_ratio=$(echo "scale=2    1440                 packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
1441                                 | bc -l)         1441                                 | bc -l)
1442         fi                                       1442         fi
1443                                                  1443 
1444         diff=$(echo $weights_ratio - $packets    1444         diff=$(echo $weights_ratio - $packets_ratio | bc -l)
1445         diff=${diff#-}                           1445         diff=${diff#-}
1446                                                  1446 
1447         test "$(echo "$diff / $weights_ratio     1447         test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
1448         check_err $? "Too large discrepancy b    1448         check_err $? "Too large discrepancy between expected and measured ratios"
1449         log_test "$desc"                         1449         log_test "$desc"
1450         log_info "Expected ratio $weights_rat    1450         log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
1451 }                                                1451 }
1452                                                  1452 
1453 in_ns()                                          1453 in_ns()
1454 {                                                1454 {
1455         local name=$1; shift                     1455         local name=$1; shift
1456                                                  1456 
1457         ip netns exec $name bash <<-EOF          1457         ip netns exec $name bash <<-EOF
1458                 NUM_NETIFS=0                     1458                 NUM_NETIFS=0
1459                 source lib.sh                    1459                 source lib.sh
1460                 $(for a in "$@"; do printf "%    1460                 $(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
1461         EOF                                      1461         EOF
1462 }                                                1462 }
1463                                                  1463 
1464 #############################################    1464 ##############################################################################
1465 # Tests                                          1465 # Tests
1466                                                  1466 
1467 ping_do()                                        1467 ping_do()
1468 {                                                1468 {
1469         local if_name=$1                         1469         local if_name=$1
1470         local dip=$2                             1470         local dip=$2
1471         local args=$3                            1471         local args=$3
1472         local vrf_name                           1472         local vrf_name
1473                                                  1473 
1474         vrf_name=$(master_name_get $if_name)     1474         vrf_name=$(master_name_get $if_name)
1475         ip vrf exec $vrf_name \                  1475         ip vrf exec $vrf_name \
1476                 $PING $args $dip -c $PING_COU    1476                 $PING $args $dip -c $PING_COUNT -i 0.1 \
1477                 -w $PING_TIMEOUT &> /dev/null    1477                 -w $PING_TIMEOUT &> /dev/null
1478 }                                                1478 }
1479                                                  1479 
1480 ping_test()                                      1480 ping_test()
1481 {                                                1481 {
1482         RET=0                                    1482         RET=0
1483                                                  1483 
1484         ping_do $1 $2                            1484         ping_do $1 $2
1485         check_err $?                             1485         check_err $?
1486         log_test "ping$3"                        1486         log_test "ping$3"
1487 }                                                1487 }
1488                                                  1488 
1489 ping_test_fails()                                1489 ping_test_fails()
1490 {                                                1490 {
1491         RET=0                                    1491         RET=0
1492                                                  1492 
1493         ping_do $1 $2                            1493         ping_do $1 $2
1494         check_fail $?                            1494         check_fail $?
1495         log_test "ping fails$3"                  1495         log_test "ping fails$3"
1496 }                                                1496 }
1497                                                  1497 
1498 ping6_do()                                       1498 ping6_do()
1499 {                                                1499 {
1500         local if_name=$1                         1500         local if_name=$1
1501         local dip=$2                             1501         local dip=$2
1502         local args=$3                            1502         local args=$3
1503         local vrf_name                           1503         local vrf_name
1504                                                  1504 
1505         vrf_name=$(master_name_get $if_name)     1505         vrf_name=$(master_name_get $if_name)
1506         ip vrf exec $vrf_name \                  1506         ip vrf exec $vrf_name \
1507                 $PING6 $args $dip -c $PING_CO    1507                 $PING6 $args $dip -c $PING_COUNT -i 0.1 \
1508                 -w $PING_TIMEOUT &> /dev/null    1508                 -w $PING_TIMEOUT &> /dev/null
1509 }                                                1509 }
1510                                                  1510 
1511 ping6_test()                                     1511 ping6_test()
1512 {                                                1512 {
1513         RET=0                                    1513         RET=0
1514                                                  1514 
1515         ping6_do $1 $2                           1515         ping6_do $1 $2
1516         check_err $?                             1516         check_err $?
1517         log_test "ping6$3"                       1517         log_test "ping6$3"
1518 }                                                1518 }
1519                                                  1519 
1520 ping6_test_fails()                               1520 ping6_test_fails()
1521 {                                                1521 {
1522         RET=0                                    1522         RET=0
1523                                                  1523 
1524         ping6_do $1 $2                           1524         ping6_do $1 $2
1525         check_fail $?                            1525         check_fail $?
1526         log_test "ping6 fails$3"                 1526         log_test "ping6 fails$3"
1527 }                                                1527 }
1528                                                  1528 
1529 learning_test()                                  1529 learning_test()
1530 {                                                1530 {
1531         local bridge=$1                          1531         local bridge=$1
1532         local br_port1=$2       # Connected t    1532         local br_port1=$2       # Connected to `host1_if`.
1533         local host1_if=$3                        1533         local host1_if=$3
1534         local host2_if=$4                        1534         local host2_if=$4
1535         local mac=de:ad:be:ef:13:37              1535         local mac=de:ad:be:ef:13:37
1536         local ageing_time                        1536         local ageing_time
1537                                                  1537 
1538         RET=0                                    1538         RET=0
1539                                                  1539 
1540         bridge -j fdb show br $bridge brport     1540         bridge -j fdb show br $bridge brport $br_port1 \
1541                 | jq -e ".[] | select(.mac ==    1541                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1542         check_fail $? "Found FDB record when     1542         check_fail $? "Found FDB record when should not"
1543                                                  1543 
1544         # Disable unknown unicast flooding on    1544         # Disable unknown unicast flooding on `br_port1` to make sure
1545         # packets are only forwarded through     1545         # packets are only forwarded through the port after a matching
1546         # FDB entry was installed.               1546         # FDB entry was installed.
1547         bridge link set dev $br_port1 flood o    1547         bridge link set dev $br_port1 flood off
1548                                                  1548 
1549         ip link set $host1_if promisc on         1549         ip link set $host1_if promisc on
1550         tc qdisc add dev $host1_if ingress       1550         tc qdisc add dev $host1_if ingress
1551         tc filter add dev $host1_if ingress p    1551         tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
1552                 flower dst_mac $mac action dr    1552                 flower dst_mac $mac action drop
1553                                                  1553 
1554         $MZ $host2_if -c 1 -p 64 -b $mac -t i    1554         $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
1555         sleep 1                                  1555         sleep 1
1556                                                  1556 
1557         tc -j -s filter show dev $host1_if in    1557         tc -j -s filter show dev $host1_if ingress \
1558                 | jq -e ".[] | select(.option    1558                 | jq -e ".[] | select(.options.handle == 101) \
1559                 | select(.options.actions[0].    1559                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1560         check_fail $? "Packet reached first h    1560         check_fail $? "Packet reached first host when should not"
1561                                                  1561 
1562         $MZ $host1_if -c 1 -p 64 -a $mac -t i    1562         $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
1563         sleep 1                                  1563         sleep 1
1564                                                  1564 
1565         bridge -j fdb show br $bridge brport     1565         bridge -j fdb show br $bridge brport $br_port1 \
1566                 | jq -e ".[] | select(.mac ==    1566                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1567         check_err $? "Did not find FDB record    1567         check_err $? "Did not find FDB record when should"
1568                                                  1568 
1569         $MZ $host2_if -c 1 -p 64 -b $mac -t i    1569         $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
1570         sleep 1                                  1570         sleep 1
1571                                                  1571 
1572         tc -j -s filter show dev $host1_if in    1572         tc -j -s filter show dev $host1_if ingress \
1573                 | jq -e ".[] | select(.option    1573                 | jq -e ".[] | select(.options.handle == 101) \
1574                 | select(.options.actions[0].    1574                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1575         check_err $? "Packet did not reach se    1575         check_err $? "Packet did not reach second host when should"
1576                                                  1576 
1577         # Wait for 10 seconds after the agein    1577         # Wait for 10 seconds after the ageing time to make sure FDB
1578         # record was aged-out.                   1578         # record was aged-out.
1579         ageing_time=$(bridge_ageing_time_get     1579         ageing_time=$(bridge_ageing_time_get $bridge)
1580         sleep $((ageing_time + 10))              1580         sleep $((ageing_time + 10))
1581                                                  1581 
1582         bridge -j fdb show br $bridge brport     1582         bridge -j fdb show br $bridge brport $br_port1 \
1583                 | jq -e ".[] | select(.mac ==    1583                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1584         check_fail $? "Found FDB record when     1584         check_fail $? "Found FDB record when should not"
1585                                                  1585 
1586         bridge link set dev $br_port1 learnin    1586         bridge link set dev $br_port1 learning off
1587                                                  1587 
1588         $MZ $host1_if -c 1 -p 64 -a $mac -t i    1588         $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
1589         sleep 1                                  1589         sleep 1
1590                                                  1590 
1591         bridge -j fdb show br $bridge brport     1591         bridge -j fdb show br $bridge brport $br_port1 \
1592                 | jq -e ".[] | select(.mac ==    1592                 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1593         check_fail $? "Found FDB record when     1593         check_fail $? "Found FDB record when should not"
1594                                                  1594 
1595         bridge link set dev $br_port1 learnin    1595         bridge link set dev $br_port1 learning on
1596                                                  1596 
1597         tc filter del dev $host1_if ingress p    1597         tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
1598         tc qdisc del dev $host1_if ingress       1598         tc qdisc del dev $host1_if ingress
1599         ip link set $host1_if promisc off        1599         ip link set $host1_if promisc off
1600                                                  1600 
1601         bridge link set dev $br_port1 flood o    1601         bridge link set dev $br_port1 flood on
1602                                                  1602 
1603         log_test "FDB learning"                  1603         log_test "FDB learning"
1604 }                                                1604 }
1605                                                  1605 
1606 flood_test_do()                                  1606 flood_test_do()
1607 {                                                1607 {
1608         local should_flood=$1                    1608         local should_flood=$1
1609         local mac=$2                             1609         local mac=$2
1610         local ip=$3                              1610         local ip=$3
1611         local host1_if=$4                        1611         local host1_if=$4
1612         local host2_if=$5                        1612         local host2_if=$5
1613         local err=0                              1613         local err=0
1614                                                  1614 
1615         # Add an ACL on `host2_if` which will    1615         # Add an ACL on `host2_if` which will tell us whether the packet
1616         # was flooded to it or not.              1616         # was flooded to it or not.
1617         ip link set $host2_if promisc on         1617         ip link set $host2_if promisc on
1618         tc qdisc add dev $host2_if ingress       1618         tc qdisc add dev $host2_if ingress
1619         tc filter add dev $host2_if ingress p    1619         tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
1620                 flower dst_mac $mac action dr    1620                 flower dst_mac $mac action drop
1621                                                  1621 
1622         $MZ $host1_if -c 1 -p 64 -b $mac -B $    1622         $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
1623         sleep 1                                  1623         sleep 1
1624                                                  1624 
1625         tc -j -s filter show dev $host2_if in    1625         tc -j -s filter show dev $host2_if ingress \
1626                 | jq -e ".[] | select(.option    1626                 | jq -e ".[] | select(.options.handle == 101) \
1627                 | select(.options.actions[0].    1627                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1628         if [[ $? -ne 0 && $should_flood == "t    1628         if [[ $? -ne 0 && $should_flood == "true" || \
1629               $? -eq 0 && $should_flood == "f    1629               $? -eq 0 && $should_flood == "false" ]]; then
1630                 err=1                            1630                 err=1
1631         fi                                       1631         fi
1632                                                  1632 
1633         tc filter del dev $host2_if ingress p    1633         tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
1634         tc qdisc del dev $host2_if ingress       1634         tc qdisc del dev $host2_if ingress
1635         ip link set $host2_if promisc off        1635         ip link set $host2_if promisc off
1636                                                  1636 
1637         return $err                              1637         return $err
1638 }                                                1638 }
1639                                                  1639 
1640 flood_unicast_test()                             1640 flood_unicast_test()
1641 {                                                1641 {
1642         local br_port=$1                         1642         local br_port=$1
1643         local host1_if=$2                        1643         local host1_if=$2
1644         local host2_if=$3                        1644         local host2_if=$3
1645         local mac=de:ad:be:ef:13:37              1645         local mac=de:ad:be:ef:13:37
1646         local ip=192.0.2.100                     1646         local ip=192.0.2.100
1647                                                  1647 
1648         RET=0                                    1648         RET=0
1649                                                  1649 
1650         bridge link set dev $br_port flood of    1650         bridge link set dev $br_port flood off
1651                                                  1651 
1652         flood_test_do false $mac $ip $host1_i    1652         flood_test_do false $mac $ip $host1_if $host2_if
1653         check_err $? "Packet flooded when sho    1653         check_err $? "Packet flooded when should not"
1654                                                  1654 
1655         bridge link set dev $br_port flood on    1655         bridge link set dev $br_port flood on
1656                                                  1656 
1657         flood_test_do true $mac $ip $host1_if    1657         flood_test_do true $mac $ip $host1_if $host2_if
1658         check_err $? "Packet was not flooded     1658         check_err $? "Packet was not flooded when should"
1659                                                  1659 
1660         log_test "Unknown unicast flood"         1660         log_test "Unknown unicast flood"
1661 }                                                1661 }
1662                                                  1662 
1663 flood_multicast_test()                           1663 flood_multicast_test()
1664 {                                                1664 {
1665         local br_port=$1                         1665         local br_port=$1
1666         local host1_if=$2                        1666         local host1_if=$2
1667         local host2_if=$3                        1667         local host2_if=$3
1668         local mac=01:00:5e:00:00:01              1668         local mac=01:00:5e:00:00:01
1669         local ip=239.0.0.1                       1669         local ip=239.0.0.1
1670                                                  1670 
1671         RET=0                                    1671         RET=0
1672                                                  1672 
1673         bridge link set dev $br_port mcast_fl    1673         bridge link set dev $br_port mcast_flood off
1674                                                  1674 
1675         flood_test_do false $mac $ip $host1_i    1675         flood_test_do false $mac $ip $host1_if $host2_if
1676         check_err $? "Packet flooded when sho    1676         check_err $? "Packet flooded when should not"
1677                                                  1677 
1678         bridge link set dev $br_port mcast_fl    1678         bridge link set dev $br_port mcast_flood on
1679                                                  1679 
1680         flood_test_do true $mac $ip $host1_if    1680         flood_test_do true $mac $ip $host1_if $host2_if
1681         check_err $? "Packet was not flooded     1681         check_err $? "Packet was not flooded when should"
1682                                                  1682 
1683         log_test "Unregistered multicast floo    1683         log_test "Unregistered multicast flood"
1684 }                                                1684 }
1685                                                  1685 
1686 flood_test()                                     1686 flood_test()
1687 {                                                1687 {
1688         # `br_port` is connected to `host2_if    1688         # `br_port` is connected to `host2_if`
1689         local br_port=$1                         1689         local br_port=$1
1690         local host1_if=$2                        1690         local host1_if=$2
1691         local host2_if=$3                        1691         local host2_if=$3
1692                                                  1692 
1693         flood_unicast_test $br_port $host1_if    1693         flood_unicast_test $br_port $host1_if $host2_if
1694         flood_multicast_test $br_port $host1_    1694         flood_multicast_test $br_port $host1_if $host2_if
1695 }                                                1695 }
1696                                                  1696 
1697 __start_traffic()                                1697 __start_traffic()
1698 {                                                1698 {
1699         local pktsize=$1; shift                  1699         local pktsize=$1; shift
1700         local proto=$1; shift                    1700         local proto=$1; shift
1701         local h_in=$1; shift    # Where the t    1701         local h_in=$1; shift    # Where the traffic egresses the host
1702         local sip=$1; shift                      1702         local sip=$1; shift
1703         local dip=$1; shift                      1703         local dip=$1; shift
1704         local dmac=$1; shift                     1704         local dmac=$1; shift
1705         local -a mz_args=("$@")                  1705         local -a mz_args=("$@")
1706                                                  1706 
1707         $MZ $h_in -p $pktsize -A $sip -B $dip    1707         $MZ $h_in -p $pktsize -A $sip -B $dip -c 0 \
1708                 -a own -b $dmac -t "$proto" -    1708                 -a own -b $dmac -t "$proto" -q "${mz_args[@]}" &
1709         sleep 1                                  1709         sleep 1
1710 }                                                1710 }
1711                                                  1711 
1712 start_traffic_pktsize()                          1712 start_traffic_pktsize()
1713 {                                                1713 {
1714         local pktsize=$1; shift                  1714         local pktsize=$1; shift
1715         local h_in=$1; shift                     1715         local h_in=$1; shift
1716         local sip=$1; shift                      1716         local sip=$1; shift
1717         local dip=$1; shift                      1717         local dip=$1; shift
1718         local dmac=$1; shift                     1718         local dmac=$1; shift
1719         local -a mz_args=("$@")                  1719         local -a mz_args=("$@")
1720                                                  1720 
1721         __start_traffic $pktsize udp "$h_in"     1721         __start_traffic $pktsize udp "$h_in" "$sip" "$dip" "$dmac" \
1722                         "${mz_args[@]}"          1722                         "${mz_args[@]}"
1723 }                                                1723 }
1724                                                  1724 
1725 start_tcp_traffic_pktsize()                      1725 start_tcp_traffic_pktsize()
1726 {                                                1726 {
1727         local pktsize=$1; shift                  1727         local pktsize=$1; shift
1728         local h_in=$1; shift                     1728         local h_in=$1; shift
1729         local sip=$1; shift                      1729         local sip=$1; shift
1730         local dip=$1; shift                      1730         local dip=$1; shift
1731         local dmac=$1; shift                     1731         local dmac=$1; shift
1732         local -a mz_args=("$@")                  1732         local -a mz_args=("$@")
1733                                                  1733 
1734         __start_traffic $pktsize tcp "$h_in"     1734         __start_traffic $pktsize tcp "$h_in" "$sip" "$dip" "$dmac" \
1735                         "${mz_args[@]}"          1735                         "${mz_args[@]}"
1736 }                                                1736 }
1737                                                  1737 
1738 start_traffic()                                  1738 start_traffic()
1739 {                                                1739 {
1740         local h_in=$1; shift                     1740         local h_in=$1; shift
1741         local sip=$1; shift                      1741         local sip=$1; shift
1742         local dip=$1; shift                      1742         local dip=$1; shift
1743         local dmac=$1; shift                     1743         local dmac=$1; shift
1744         local -a mz_args=("$@")                  1744         local -a mz_args=("$@")
1745                                                  1745 
1746         start_traffic_pktsize 8000 "$h_in" "$    1746         start_traffic_pktsize 8000 "$h_in" "$sip" "$dip" "$dmac" \
1747                               "${mz_args[@]}"    1747                               "${mz_args[@]}"
1748 }                                                1748 }
1749                                                  1749 
1750 start_tcp_traffic()                              1750 start_tcp_traffic()
1751 {                                                1751 {
1752         local h_in=$1; shift                     1752         local h_in=$1; shift
1753         local sip=$1; shift                      1753         local sip=$1; shift
1754         local dip=$1; shift                      1754         local dip=$1; shift
1755         local dmac=$1; shift                     1755         local dmac=$1; shift
1756         local -a mz_args=("$@")                  1756         local -a mz_args=("$@")
1757                                                  1757 
1758         start_tcp_traffic_pktsize 8000 "$h_in    1758         start_tcp_traffic_pktsize 8000 "$h_in" "$sip" "$dip" "$dmac" \
1759                                   "${mz_args[    1759                                   "${mz_args[@]}"
1760 }                                                1760 }
1761                                                  1761 
1762 stop_traffic()                                   1762 stop_traffic()
1763 {                                                1763 {
1764         # Suppress noise from killing mauseza    1764         # Suppress noise from killing mausezahn.
1765         { kill %% && wait %%; } 2>/dev/null      1765         { kill %% && wait %%; } 2>/dev/null
1766 }                                                1766 }
1767                                                  1767 
1768 declare -A cappid                                1768 declare -A cappid
1769 declare -A capfile                               1769 declare -A capfile
1770 declare -A capout                                1770 declare -A capout
1771                                                  1771 
1772 tcpdump_start()                                  1772 tcpdump_start()
1773 {                                                1773 {
1774         local if_name=$1; shift                  1774         local if_name=$1; shift
1775         local ns=$1; shift                       1775         local ns=$1; shift
1776                                                  1776 
1777         capfile[$if_name]=$(mktemp)              1777         capfile[$if_name]=$(mktemp)
1778         capout[$if_name]=$(mktemp)               1778         capout[$if_name]=$(mktemp)
1779                                                  1779 
1780         if [ -z $ns ]; then                      1780         if [ -z $ns ]; then
1781                 ns_cmd=""                        1781                 ns_cmd=""
1782         else                                     1782         else
1783                 ns_cmd="ip netns exec ${ns}"     1783                 ns_cmd="ip netns exec ${ns}"
1784         fi                                       1784         fi
1785                                                  1785 
1786         if [ -z $SUDO_USER ] ; then              1786         if [ -z $SUDO_USER ] ; then
1787                 capuser=""                       1787                 capuser=""
1788         else                                     1788         else
1789                 capuser="-Z $SUDO_USER"          1789                 capuser="-Z $SUDO_USER"
1790         fi                                       1790         fi
1791                                                  1791 
1792         $ns_cmd tcpdump $TCPDUMP_EXTRA_FLAGS     1792         $ns_cmd tcpdump $TCPDUMP_EXTRA_FLAGS -e -n -Q in -i $if_name \
1793                 -s 65535 -B 32768 $capuser -w    1793                 -s 65535 -B 32768 $capuser -w ${capfile[$if_name]} \
1794                 > "${capout[$if_name]}" 2>&1     1794                 > "${capout[$if_name]}" 2>&1 &
1795         cappid[$if_name]=$!                      1795         cappid[$if_name]=$!
1796                                                  1796 
1797         sleep 1                                  1797         sleep 1
1798 }                                                1798 }
1799                                                  1799 
1800 tcpdump_stop()                                   1800 tcpdump_stop()
1801 {                                                1801 {
1802         local if_name=$1                         1802         local if_name=$1
1803         local pid=${cappid[$if_name]}            1803         local pid=${cappid[$if_name]}
1804                                                  1804 
1805         $ns_cmd kill "$pid" && wait "$pid"       1805         $ns_cmd kill "$pid" && wait "$pid"
1806         sleep 1                                  1806         sleep 1
1807 }                                                1807 }
1808                                                  1808 
1809 tcpdump_cleanup()                                1809 tcpdump_cleanup()
1810 {                                                1810 {
1811         local if_name=$1                         1811         local if_name=$1
1812                                                  1812 
1813         rm ${capfile[$if_name]} ${capout[$if_    1813         rm ${capfile[$if_name]} ${capout[$if_name]}
1814 }                                                1814 }
1815                                                  1815 
1816 tcpdump_show()                                   1816 tcpdump_show()
1817 {                                                1817 {
1818         local if_name=$1                         1818         local if_name=$1
1819                                                  1819 
1820         tcpdump -e -n -r ${capfile[$if_name]}    1820         tcpdump -e -n -r ${capfile[$if_name]} 2>&1
1821 }                                                1821 }
1822                                                  1822 
1823 # return 0 if the packet wasn't seen on host2    1823 # return 0 if the packet wasn't seen on host2_if or 1 if it was
1824 mcast_packet_test()                              1824 mcast_packet_test()
1825 {                                                1825 {
1826         local mac=$1                             1826         local mac=$1
1827         local src_ip=$2                          1827         local src_ip=$2
1828         local ip=$3                              1828         local ip=$3
1829         local host1_if=$4                        1829         local host1_if=$4
1830         local host2_if=$5                        1830         local host2_if=$5
1831         local seen=0                             1831         local seen=0
1832         local tc_proto="ip"                      1832         local tc_proto="ip"
1833         local mz_v6arg=""                        1833         local mz_v6arg=""
1834                                                  1834 
1835         # basic check to see if we were passe    1835         # basic check to see if we were passed an IPv4 address, if not assume IPv6
1836         if [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3    1836         if [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
1837                 tc_proto="ipv6"                  1837                 tc_proto="ipv6"
1838                 mz_v6arg="-6"                    1838                 mz_v6arg="-6"
1839         fi                                       1839         fi
1840                                                  1840 
1841         # Add an ACL on `host2_if` which will    1841         # Add an ACL on `host2_if` which will tell us whether the packet
1842         # was received by it or not.             1842         # was received by it or not.
1843         tc qdisc add dev $host2_if ingress       1843         tc qdisc add dev $host2_if ingress
1844         tc filter add dev $host2_if ingress p    1844         tc filter add dev $host2_if ingress protocol $tc_proto pref 1 handle 101 \
1845                 flower ip_proto udp dst_mac $    1845                 flower ip_proto udp dst_mac $mac action drop
1846                                                  1846 
1847         $MZ $host1_if $mz_v6arg -c 1 -p 64 -b    1847         $MZ $host1_if $mz_v6arg -c 1 -p 64 -b $mac -A $src_ip -B $ip -t udp "dp=4096,sp=2048" -q
1848         sleep 1                                  1848         sleep 1
1849                                                  1849 
1850         tc -j -s filter show dev $host2_if in    1850         tc -j -s filter show dev $host2_if ingress \
1851                 | jq -e ".[] | select(.option    1851                 | jq -e ".[] | select(.options.handle == 101) \
1852                 | select(.options.actions[0].    1852                 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
1853         if [[ $? -eq 0 ]]; then                  1853         if [[ $? -eq 0 ]]; then
1854                 seen=1                           1854                 seen=1
1855         fi                                       1855         fi
1856                                                  1856 
1857         tc filter del dev $host2_if ingress p    1857         tc filter del dev $host2_if ingress protocol $tc_proto pref 1 handle 101 flower
1858         tc qdisc del dev $host2_if ingress       1858         tc qdisc del dev $host2_if ingress
1859                                                  1859 
1860         return $seen                             1860         return $seen
1861 }                                                1861 }
1862                                                  1862 
1863 brmcast_check_sg_entries()                       1863 brmcast_check_sg_entries()
1864 {                                                1864 {
1865         local report=$1; shift                   1865         local report=$1; shift
1866         local slist=("$@")                       1866         local slist=("$@")
1867         local sarg=""                            1867         local sarg=""
1868                                                  1868 
1869         for src in "${slist[@]}"; do             1869         for src in "${slist[@]}"; do
1870                 sarg="${sarg} and .source_lis    1870                 sarg="${sarg} and .source_list[].address == \"$src\""
1871         done                                     1871         done
1872         bridge -j -d -s mdb show dev br0 \       1872         bridge -j -d -s mdb show dev br0 \
1873                 | jq -e ".[].mdb[] | \           1873                 | jq -e ".[].mdb[] | \
1874                          select(.grp == \"$TE    1874                          select(.grp == \"$TEST_GROUP\" and .source_list != null $sarg)" &>/dev/null
1875         check_err $? "Wrong *,G entry source     1875         check_err $? "Wrong *,G entry source list after $report report"
1876                                                  1876 
1877         for sgent in "${slist[@]}"; do           1877         for sgent in "${slist[@]}"; do
1878                 bridge -j -d -s mdb show dev     1878                 bridge -j -d -s mdb show dev br0 \
1879                         | jq -e ".[].mdb[] |     1879                         | jq -e ".[].mdb[] | \
1880                                  select(.grp     1880                                  select(.grp == \"$TEST_GROUP\" and .src == \"$sgent\")" &>/dev/null
1881                 check_err $? "Missing S,G ent    1881                 check_err $? "Missing S,G entry ($sgent, $TEST_GROUP)"
1882         done                                     1882         done
1883 }                                                1883 }
1884                                                  1884 
1885 brmcast_check_sg_fwding()                        1885 brmcast_check_sg_fwding()
1886 {                                                1886 {
1887         local should_fwd=$1; shift               1887         local should_fwd=$1; shift
1888         local sources=("$@")                     1888         local sources=("$@")
1889                                                  1889 
1890         for src in "${sources[@]}"; do           1890         for src in "${sources[@]}"; do
1891                 local retval=0                   1891                 local retval=0
1892                                                  1892 
1893                 mcast_packet_test $TEST_GROUP    1893                 mcast_packet_test $TEST_GROUP_MAC $src $TEST_GROUP $h2 $h1
1894                 retval=$?                        1894                 retval=$?
1895                 if [ $should_fwd -eq 1 ]; the    1895                 if [ $should_fwd -eq 1 ]; then
1896                         check_fail $retval "D    1896                         check_fail $retval "Didn't forward traffic from S,G ($src, $TEST_GROUP)"
1897                 else                             1897                 else
1898                         check_err $retval "Fo    1898                         check_err $retval "Forwarded traffic for blocked S,G ($src, $TEST_GROUP)"
1899                 fi                               1899                 fi
1900         done                                     1900         done
1901 }                                                1901 }
1902                                                  1902 
1903 brmcast_check_sg_state()                         1903 brmcast_check_sg_state()
1904 {                                                1904 {
1905         local is_blocked=$1; shift               1905         local is_blocked=$1; shift
1906         local sources=("$@")                     1906         local sources=("$@")
1907         local should_fail=1                      1907         local should_fail=1
1908                                                  1908 
1909         if [ $is_blocked -eq 1 ]; then           1909         if [ $is_blocked -eq 1 ]; then
1910                 should_fail=0                    1910                 should_fail=0
1911         fi                                       1911         fi
1912                                                  1912 
1913         for src in "${sources[@]}"; do           1913         for src in "${sources[@]}"; do
1914                 bridge -j -d -s mdb show dev     1914                 bridge -j -d -s mdb show dev br0 \
1915                         | jq -e ".[].mdb[] |     1915                         | jq -e ".[].mdb[] | \
1916                                  select(.grp     1916                                  select(.grp == \"$TEST_GROUP\" and .source_list != null) |
1917                                  .source_list    1917                                  .source_list[] |
1918                                  select(.addr    1918                                  select(.address == \"$src\") |
1919                                  select(.time    1919                                  select(.timer == \"0.00\")" &>/dev/null
1920                 check_err_fail $should_fail $    1920                 check_err_fail $should_fail $? "Entry $src has zero timer"
1921                                                  1921 
1922                 bridge -j -d -s mdb show dev     1922                 bridge -j -d -s mdb show dev br0 \
1923                         | jq -e ".[].mdb[] |     1923                         | jq -e ".[].mdb[] | \
1924                                  select(.grp     1924                                  select(.grp == \"$TEST_GROUP\" and .src == \"$src\" and \
1925                                  .flags[] ==     1925                                  .flags[] == \"blocked\")" &>/dev/null
1926                 check_err_fail $should_fail $    1926                 check_err_fail $should_fail $? "Entry $src has blocked flag"
1927         done                                     1927         done
1928 }                                                1928 }
1929                                                  1929 
1930 mc_join()                                        1930 mc_join()
1931 {                                                1931 {
1932         local if_name=$1                         1932         local if_name=$1
1933         local group=$2                           1933         local group=$2
1934         local vrf_name=$(master_name_get $if_    1934         local vrf_name=$(master_name_get $if_name)
1935                                                  1935 
1936         # We don't care about actual receptio    1936         # We don't care about actual reception, just about joining the
1937         # IP multicast group and adding the L    1937         # IP multicast group and adding the L2 address to the device's
1938         # MAC filtering table                    1938         # MAC filtering table
1939         ip vrf exec $vrf_name \                  1939         ip vrf exec $vrf_name \
1940                 mreceive -g $group -I $if_nam    1940                 mreceive -g $group -I $if_name > /dev/null 2>&1 &
1941         mreceive_pid=$!                          1941         mreceive_pid=$!
1942                                                  1942 
1943         sleep 1                                  1943         sleep 1
1944 }                                                1944 }
1945                                                  1945 
1946 mc_leave()                                       1946 mc_leave()
1947 {                                                1947 {
1948         kill "$mreceive_pid" && wait "$mrecei    1948         kill "$mreceive_pid" && wait "$mreceive_pid"
1949 }                                                1949 }
1950                                                  1950 
1951 mc_send()                                        1951 mc_send()
1952 {                                                1952 {
1953         local if_name=$1                         1953         local if_name=$1
1954         local groups=$2                          1954         local groups=$2
1955         local vrf_name=$(master_name_get $if_    1955         local vrf_name=$(master_name_get $if_name)
1956                                                  1956 
1957         ip vrf exec $vrf_name \                  1957         ip vrf exec $vrf_name \
1958                 msend -g $groups -I $if_name     1958                 msend -g $groups -I $if_name -c 1 > /dev/null 2>&1
1959 }                                                1959 }
1960                                                  1960 
1961 start_ip_monitor()                               1961 start_ip_monitor()
1962 {                                                1962 {
1963         local mtype=$1; shift                    1963         local mtype=$1; shift
1964         local ip=${1-ip}; shift                  1964         local ip=${1-ip}; shift
1965                                                  1965 
1966         # start the monitor in the background    1966         # start the monitor in the background
1967         tmpfile=`mktemp /var/run/nexthoptestX    1967         tmpfile=`mktemp /var/run/nexthoptestXXX`
1968         mpid=`($ip monitor $mtype > $tmpfile     1968         mpid=`($ip monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
1969         sleep 0.2                                1969         sleep 0.2
1970         echo "$mpid $tmpfile"                    1970         echo "$mpid $tmpfile"
1971 }                                                1971 }
1972                                                  1972 
1973 stop_ip_monitor()                                1973 stop_ip_monitor()
1974 {                                                1974 {
1975         local mpid=$1; shift                     1975         local mpid=$1; shift
1976         local tmpfile=$1; shift                  1976         local tmpfile=$1; shift
1977         local el=$1; shift                       1977         local el=$1; shift
1978         local what=$1; shift                     1978         local what=$1; shift
1979                                                  1979 
1980         sleep 0.2                                1980         sleep 0.2
1981         kill $mpid                               1981         kill $mpid
1982         local lines=`grep '^\w' $tmpfile | wc    1982         local lines=`grep '^\w' $tmpfile | wc -l`
1983         test $lines -eq $el                      1983         test $lines -eq $el
1984         check_err $? "$what: $lines lines of     1984         check_err $? "$what: $lines lines of events, expected $el"
1985         rm -rf $tmpfile                          1985         rm -rf $tmpfile
1986 }                                                1986 }
1987                                                  1987 
1988 hw_stats_monitor_test()                          1988 hw_stats_monitor_test()
1989 {                                                1989 {
1990         local dev=$1; shift                      1990         local dev=$1; shift
1991         local type=$1; shift                     1991         local type=$1; shift
1992         local make_suitable=$1; shift            1992         local make_suitable=$1; shift
1993         local make_unsuitable=$1; shift          1993         local make_unsuitable=$1; shift
1994         local ip=${1-ip}; shift                  1994         local ip=${1-ip}; shift
1995                                                  1995 
1996         RET=0                                    1996         RET=0
1997                                                  1997 
1998         # Expect a notification about enablem    1998         # Expect a notification about enablement.
1999         local ipmout=$(start_ip_monitor stats    1999         local ipmout=$(start_ip_monitor stats "$ip")
2000         $ip stats set dev $dev ${type}_stats     2000         $ip stats set dev $dev ${type}_stats on
2001         stop_ip_monitor $ipmout 1 "${type}_st    2001         stop_ip_monitor $ipmout 1 "${type}_stats enablement"
2002                                                  2002 
2003         # Expect a notification about offload    2003         # Expect a notification about offload.
2004         local ipmout=$(start_ip_monitor stats    2004         local ipmout=$(start_ip_monitor stats "$ip")
2005         $make_suitable                           2005         $make_suitable
2006         stop_ip_monitor $ipmout 1 "${type}_st    2006         stop_ip_monitor $ipmout 1 "${type}_stats installation"
2007                                                  2007 
2008         # Expect a notification about loss of    2008         # Expect a notification about loss of offload.
2009         local ipmout=$(start_ip_monitor stats    2009         local ipmout=$(start_ip_monitor stats "$ip")
2010         $make_unsuitable                         2010         $make_unsuitable
2011         stop_ip_monitor $ipmout 1 "${type}_st    2011         stop_ip_monitor $ipmout 1 "${type}_stats deinstallation"
2012                                                  2012 
2013         # Expect a notification about disable    2013         # Expect a notification about disablement
2014         local ipmout=$(start_ip_monitor stats    2014         local ipmout=$(start_ip_monitor stats "$ip")
2015         $ip stats set dev $dev ${type}_stats     2015         $ip stats set dev $dev ${type}_stats off
2016         stop_ip_monitor $ipmout 1 "${type}_st    2016         stop_ip_monitor $ipmout 1 "${type}_stats disablement"
2017                                                  2017 
2018         log_test "${type}_stats notifications    2018         log_test "${type}_stats notifications"
2019 }                                                2019 }
2020                                                  2020 
2021 ipv4_to_bytes()                                  2021 ipv4_to_bytes()
2022 {                                                2022 {
2023         local IP=$1; shift                       2023         local IP=$1; shift
2024                                                  2024 
2025         printf '%02x:' ${IP//./ } |              2025         printf '%02x:' ${IP//./ } |
2026             sed 's/:$//'                         2026             sed 's/:$//'
2027 }                                                2027 }
2028                                                  2028 
2029 # Convert a given IPv6 address, `IP' such tha    2029 # Convert a given IPv6 address, `IP' such that the :: token, if present, is
2030 # expanded, and each 16-bit group is padded w    2030 # expanded, and each 16-bit group is padded with zeroes to be 4 hexadecimal
2031 # digits. An optional `BYTESEP' parameter can    2031 # digits. An optional `BYTESEP' parameter can be given to further separate
2032 # individual bytes of each 16-bit group.         2032 # individual bytes of each 16-bit group.
2033 expand_ipv6()                                    2033 expand_ipv6()
2034 {                                                2034 {
2035         local IP=$1; shift                       2035         local IP=$1; shift
2036         local bytesep=$1; shift                  2036         local bytesep=$1; shift
2037                                                  2037 
2038         local cvt_ip=${IP/::/_}                  2038         local cvt_ip=${IP/::/_}
2039         local colons=${cvt_ip//[^:]/}            2039         local colons=${cvt_ip//[^:]/}
2040         local allcol=:::::::                     2040         local allcol=:::::::
2041         # IP where :: -> the appropriate numb    2041         # IP where :: -> the appropriate number of colons:
2042         local allcol_ip=${cvt_ip/_/${allcol:$    2042         local allcol_ip=${cvt_ip/_/${allcol:${#colons}}}
2043                                                  2043 
2044         echo $allcol_ip | tr : '\n' |            2044         echo $allcol_ip | tr : '\n' |
2045             sed s/^/0000/ |                      2045             sed s/^/0000/ |
2046             sed 's/.*\(..\)\(..\)/\1'"$bytese    2046             sed 's/.*\(..\)\(..\)/\1'"$bytesep"'\2/' |
2047             tr '\n' : |                          2047             tr '\n' : |
2048             sed 's/:$//'                         2048             sed 's/:$//'
2049 }                                                2049 }
2050                                                  2050 
2051 ipv6_to_bytes()                                  2051 ipv6_to_bytes()
2052 {                                                2052 {
2053         local IP=$1; shift                       2053         local IP=$1; shift
2054                                                  2054 
2055         expand_ipv6 "$IP" :                      2055         expand_ipv6 "$IP" :
2056 }                                                2056 }
2057                                                  2057 
2058 u16_to_bytes()                                   2058 u16_to_bytes()
2059 {                                                2059 {
2060         local u16=$1; shift                      2060         local u16=$1; shift
2061                                                  2061 
2062         printf "%04x" $u16 | sed 's/^/000/;s/    2062         printf "%04x" $u16 | sed 's/^/000/;s/^.*\(..\)\(..\)$/\1:\2/'
2063 }                                                2063 }
2064                                                  2064 
2065 # Given a mausezahn-formatted payload (colon-    2065 # Given a mausezahn-formatted payload (colon-separated bytes given as %02x),
2066 # possibly with a keyword CHECKSUM stashed wh    2066 # possibly with a keyword CHECKSUM stashed where a 16-bit checksum should be,
2067 # calculate checksum as per RFC 1071, assumin    2067 # calculate checksum as per RFC 1071, assuming the CHECKSUM field (if any)
2068 # stands for 00:00.                              2068 # stands for 00:00.
2069 payload_template_calc_checksum()                 2069 payload_template_calc_checksum()
2070 {                                                2070 {
2071         local payload=$1; shift                  2071         local payload=$1; shift
2072                                                  2072 
2073         (                                        2073         (
2074             # Set input radix.                   2074             # Set input radix.
2075             echo "16i"                           2075             echo "16i"
2076             # Push zero for the initial check    2076             # Push zero for the initial checksum.
2077             echo 0                               2077             echo 0
2078                                                  2078 
2079             # Pad the payload with a terminat    2079             # Pad the payload with a terminating 00: in case we get an odd
2080             # number of bytes.                   2080             # number of bytes.
2081             echo "${payload%:}:00:" |            2081             echo "${payload%:}:00:" |
2082                 sed 's/CHECKSUM/00:00/g' |       2082                 sed 's/CHECKSUM/00:00/g' |
2083                 tr '[:lower:]' '[:upper:]' |     2083                 tr '[:lower:]' '[:upper:]' |
2084                 # Add the word to the checksu    2084                 # Add the word to the checksum.
2085                 sed 's/\(..\):\(..\):/\1\2+\n    2085                 sed 's/\(..\):\(..\):/\1\2+\n/g' |
2086                 # Strip the extra odd byte we    2086                 # Strip the extra odd byte we pushed if left unconverted.
2087                 sed 's/\(..\):$//'               2087                 sed 's/\(..\):$//'
2088                                                  2088 
2089             echo "10000 ~ +"    # Calculate a    2089             echo "10000 ~ +"    # Calculate and add carry.
2090             echo "FFFF r - p"   # Bit-flip an    2090             echo "FFFF r - p"   # Bit-flip and print.
2091         ) |                                      2091         ) |
2092             dc |                                 2092             dc |
2093             tr '[:upper:]' '[:lower:]'           2093             tr '[:upper:]' '[:lower:]'
2094 }                                                2094 }
2095                                                  2095 
2096 payload_template_expand_checksum()               2096 payload_template_expand_checksum()
2097 {                                                2097 {
2098         local payload=$1; shift                  2098         local payload=$1; shift
2099         local checksum=$1; shift                 2099         local checksum=$1; shift
2100                                                  2100 
2101         local ckbytes=$(u16_to_bytes $checksu    2101         local ckbytes=$(u16_to_bytes $checksum)
2102                                                  2102 
2103         echo "$payload" | sed "s/CHECKSUM/$ck    2103         echo "$payload" | sed "s/CHECKSUM/$ckbytes/g"
2104 }                                                2104 }
2105                                                  2105 
2106 payload_template_nbytes()                        2106 payload_template_nbytes()
2107 {                                                2107 {
2108         local payload=$1; shift                  2108         local payload=$1; shift
2109                                                  2109 
2110         payload_template_expand_checksum "${p    2110         payload_template_expand_checksum "${payload%:}" 0 |
2111                 sed 's/:/\n/g' | wc -l           2111                 sed 's/:/\n/g' | wc -l
2112 }                                                2112 }
2113                                                  2113 
2114 igmpv3_is_in_get()                               2114 igmpv3_is_in_get()
2115 {                                                2115 {
2116         local GRP=$1; shift                      2116         local GRP=$1; shift
2117         local sources=("$@")                     2117         local sources=("$@")
2118                                                  2118 
2119         local igmpv3                             2119         local igmpv3
2120         local nsources=$(u16_to_bytes ${#sour    2120         local nsources=$(u16_to_bytes ${#sources[@]})
2121                                                  2121 
2122         # IS_IN ( $sources )                     2122         # IS_IN ( $sources )
2123         igmpv3=$(:                               2123         igmpv3=$(:
2124                 )"22:"$(                         2124                 )"22:"$(                        : Type - Membership Report
2125                 )"00:"$(                         2125                 )"00:"$(                        : Reserved
2126                 )"CHECKSUM:"$(                   2126                 )"CHECKSUM:"$(                  : Checksum
2127                 )"00:00:"$(                      2127                 )"00:00:"$(                     : Reserved
2128                 )"00:01:"$(                      2128                 )"00:01:"$(                     : Number of Group Records
2129                 )"01:"$(                         2129                 )"01:"$(                        : Record Type - IS_IN
2130                 )"00:"$(                         2130                 )"00:"$(                        : Aux Data Len
2131                 )"${nsources}:"$(                2131                 )"${nsources}:"$(               : Number of Sources
2132                 )"$(ipv4_to_bytes $GRP):"$(      2132                 )"$(ipv4_to_bytes $GRP):"$(     : Multicast Address
2133                 )"$(for src in "${sources[@]}    2133                 )"$(for src in "${sources[@]}"; do
2134                         ipv4_to_bytes $src       2134                         ipv4_to_bytes $src
2135                         echo -n :                2135                         echo -n :
2136                     done)"$(                     2136                     done)"$(                    : Source Addresses
2137                 )                                2137                 )
2138         local checksum=$(payload_template_cal    2138         local checksum=$(payload_template_calc_checksum "$igmpv3")
2139                                                  2139 
2140         payload_template_expand_checksum "$ig    2140         payload_template_expand_checksum "$igmpv3" $checksum
2141 }                                                2141 }
2142                                                  2142 
2143 igmpv2_leave_get()                               2143 igmpv2_leave_get()
2144 {                                                2144 {
2145         local GRP=$1; shift                      2145         local GRP=$1; shift
2146                                                  2146 
2147         local payload=$(:                        2147         local payload=$(:
2148                 )"17:"$(                         2148                 )"17:"$(                        : Type - Leave Group
2149                 )"00:"$(                         2149                 )"00:"$(                        : Max Resp Time - not meaningful
2150                 )"CHECKSUM:"$(                   2150                 )"CHECKSUM:"$(                  : Checksum
2151                 )"$(ipv4_to_bytes $GRP)"$(       2151                 )"$(ipv4_to_bytes $GRP)"$(      : Group Address
2152                 )                                2152                 )
2153         local checksum=$(payload_template_cal    2153         local checksum=$(payload_template_calc_checksum "$payload")
2154                                                  2154 
2155         payload_template_expand_checksum "$pa    2155         payload_template_expand_checksum "$payload" $checksum
2156 }                                                2156 }
2157                                                  2157 
2158 mldv2_is_in_get()                                2158 mldv2_is_in_get()
2159 {                                                2159 {
2160         local SIP=$1; shift                      2160         local SIP=$1; shift
2161         local GRP=$1; shift                      2161         local GRP=$1; shift
2162         local sources=("$@")                     2162         local sources=("$@")
2163                                                  2163 
2164         local hbh                                2164         local hbh
2165         local icmpv6                             2165         local icmpv6
2166         local nsources=$(u16_to_bytes ${#sour    2166         local nsources=$(u16_to_bytes ${#sources[@]})
2167                                                  2167 
2168         hbh=$(:                                  2168         hbh=$(:
2169                 )"3a:"$(                         2169                 )"3a:"$(                        : Next Header - ICMPv6
2170                 )"00:"$(                         2170                 )"00:"$(                        : Hdr Ext Len
2171                 )"00:00:00:00:00:00:"$(          2171                 )"00:00:00:00:00:00:"$(         : Options and Padding
2172                 )                                2172                 )
2173                                                  2173 
2174         icmpv6=$(:                               2174         icmpv6=$(:
2175                 )"8f:"$(                         2175                 )"8f:"$(                        : Type - MLDv2 Report
2176                 )"00:"$(                         2176                 )"00:"$(                        : Code
2177                 )"CHECKSUM:"$(                   2177                 )"CHECKSUM:"$(                  : Checksum
2178                 )"00:00:"$(                      2178                 )"00:00:"$(                     : Reserved
2179                 )"00:01:"$(                      2179                 )"00:01:"$(                     : Number of Group Records
2180                 )"01:"$(                         2180                 )"01:"$(                        : Record Type - IS_IN
2181                 )"00:"$(                         2181                 )"00:"$(                        : Aux Data Len
2182                 )"${nsources}:"$(                2182                 )"${nsources}:"$(               : Number of Sources
2183                 )"$(ipv6_to_bytes $GRP):"$(      2183                 )"$(ipv6_to_bytes $GRP):"$(     : Multicast address
2184                 )"$(for src in "${sources[@]}    2184                 )"$(for src in "${sources[@]}"; do
2185                         ipv6_to_bytes $src       2185                         ipv6_to_bytes $src
2186                         echo -n :                2186                         echo -n :
2187                     done)"$(                     2187                     done)"$(                    : Source Addresses
2188                 )                                2188                 )
2189                                                  2189 
2190         local len=$(u16_to_bytes $(payload_te    2190         local len=$(u16_to_bytes $(payload_template_nbytes $icmpv6))
2191         local sudohdr=$(:                        2191         local sudohdr=$(:
2192                 )"$(ipv6_to_bytes $SIP):"$(      2192                 )"$(ipv6_to_bytes $SIP):"$(     : SIP
2193                 )"$(ipv6_to_bytes $GRP):"$(      2193                 )"$(ipv6_to_bytes $GRP):"$(     : DIP is multicast address
2194                 )"${len}:"$(                     2194                 )"${len}:"$(                    : Upper-layer length
2195                 )"00:3a:"$(                      2195                 )"00:3a:"$(                     : Zero and next-header
2196                 )                                2196                 )
2197         local checksum=$(payload_template_cal    2197         local checksum=$(payload_template_calc_checksum ${sudohdr}${icmpv6})
2198                                                  2198 
2199         payload_template_expand_checksum "$hb    2199         payload_template_expand_checksum "$hbh$icmpv6" $checksum
2200 }                                                2200 }
2201                                                  2201 
2202 mldv1_done_get()                                 2202 mldv1_done_get()
2203 {                                                2203 {
2204         local SIP=$1; shift                      2204         local SIP=$1; shift
2205         local GRP=$1; shift                      2205         local GRP=$1; shift
2206                                                  2206 
2207         local hbh                                2207         local hbh
2208         local icmpv6                             2208         local icmpv6
2209                                                  2209 
2210         hbh=$(:                                  2210         hbh=$(:
2211                 )"3a:"$(                         2211                 )"3a:"$(                        : Next Header - ICMPv6
2212                 )"00:"$(                         2212                 )"00:"$(                        : Hdr Ext Len
2213                 )"00:00:00:00:00:00:"$(          2213                 )"00:00:00:00:00:00:"$(         : Options and Padding
2214                 )                                2214                 )
2215                                                  2215 
2216         icmpv6=$(:                               2216         icmpv6=$(:
2217                 )"84:"$(                         2217                 )"84:"$(                        : Type - MLDv1 Done
2218                 )"00:"$(                         2218                 )"00:"$(                        : Code
2219                 )"CHECKSUM:"$(                   2219                 )"CHECKSUM:"$(                  : Checksum
2220                 )"00:00:"$(                      2220                 )"00:00:"$(                     : Max Resp Delay - not meaningful
2221                 )"00:00:"$(                      2221                 )"00:00:"$(                     : Reserved
2222                 )"$(ipv6_to_bytes $GRP):"$(      2222                 )"$(ipv6_to_bytes $GRP):"$(     : Multicast address
2223                 )                                2223                 )
2224                                                  2224 
2225         local len=$(u16_to_bytes $(payload_te    2225         local len=$(u16_to_bytes $(payload_template_nbytes $icmpv6))
2226         local sudohdr=$(:                        2226         local sudohdr=$(:
2227                 )"$(ipv6_to_bytes $SIP):"$(      2227                 )"$(ipv6_to_bytes $SIP):"$(     : SIP
2228                 )"$(ipv6_to_bytes $GRP):"$(      2228                 )"$(ipv6_to_bytes $GRP):"$(     : DIP is multicast address
2229                 )"${len}:"$(                     2229                 )"${len}:"$(                    : Upper-layer length
2230                 )"00:3a:"$(                      2230                 )"00:3a:"$(                     : Zero and next-header
2231                 )                                2231                 )
2232         local checksum=$(payload_template_cal    2232         local checksum=$(payload_template_calc_checksum ${sudohdr}${icmpv6})
2233                                                  2233 
2234         payload_template_expand_checksum "$hb    2234         payload_template_expand_checksum "$hbh$icmpv6" $checksum
2235 }                                                2235 }
2236                                                  2236 
2237 bail_on_lldpad()                                 2237 bail_on_lldpad()
2238 {                                                2238 {
2239         local reason1="$1"; shift                2239         local reason1="$1"; shift
2240         local reason2="$1"; shift                2240         local reason2="$1"; shift
2241         local caller=${FUNCNAME[1]}              2241         local caller=${FUNCNAME[1]}
2242         local src=${BASH_SOURCE[1]}              2242         local src=${BASH_SOURCE[1]}
2243                                                  2243 
2244         if systemctl is-active --quiet lldpad    2244         if systemctl is-active --quiet lldpad; then
2245                                                  2245 
2246                 cat >/dev/stderr <<-EOF          2246                 cat >/dev/stderr <<-EOF
2247                 WARNING: lldpad is running       2247                 WARNING: lldpad is running
2248                                                  2248 
2249                         lldpad will likely $r    2249                         lldpad will likely $reason1, and this test will
2250                         $reason2. Both are no    2250                         $reason2. Both are not supported at the same time,
2251                         one of them is arbitr    2251                         one of them is arbitrarily going to overwrite the
2252                         other. That will caus    2252                         other. That will cause spurious failures (or, unlikely,
2253                         passes) of this test.    2253                         passes) of this test.
2254                 EOF                              2254                 EOF
2255                                                  2255 
2256                 if [[ -z $ALLOW_LLDPAD ]]; th    2256                 if [[ -z $ALLOW_LLDPAD ]]; then
2257                         cat >/dev/stderr <<-E    2257                         cat >/dev/stderr <<-EOF
2258                                                  2258 
2259                                 If you want t    2259                                 If you want to run the test anyway, please set
2260                                 an environmen    2260                                 an environment variable ALLOW_LLDPAD to a
2261                                 non-empty str    2261                                 non-empty string.
2262                         EOF                      2262                         EOF
2263                         log_test_skip $src:$c    2263                         log_test_skip $src:$caller
2264                         exit $EXIT_STATUS        2264                         exit $EXIT_STATUS
2265                 else                             2265                 else
2266                         return                   2266                         return
2267                 fi                               2267                 fi
2268         fi                                       2268         fi
2269 }                                                2269 }
2270                                                  2270 
2271 absval()                                         2271 absval()
2272 {                                                2272 {
2273         local v=$1; shift                        2273         local v=$1; shift
2274                                                  2274 
2275         echo $((v > 0 ? v : -v))                 2275         echo $((v > 0 ? v : -v))
2276 }                                                2276 }
2277                                                  2277 
2278 has_unicast_flt()                                2278 has_unicast_flt()
2279 {                                                2279 {
2280         local dev=$1; shift                      2280         local dev=$1; shift
2281         local mac_addr=$(mac_get $dev)           2281         local mac_addr=$(mac_get $dev)
2282         local tmp=$(ether_addr_to_u64 $mac_ad    2282         local tmp=$(ether_addr_to_u64 $mac_addr)
2283         local promisc                            2283         local promisc
2284                                                  2284 
2285         ip link set $dev up                      2285         ip link set $dev up
2286         ip link add link $dev name macvlan-tm    2286         ip link add link $dev name macvlan-tmp type macvlan mode private
2287         ip link set macvlan-tmp address $(u64    2287         ip link set macvlan-tmp address $(u64_to_ether_addr $((tmp + 1)))
2288         ip link set macvlan-tmp up               2288         ip link set macvlan-tmp up
2289                                                  2289 
2290         promisc=$(ip -j -d link show dev $dev    2290         promisc=$(ip -j -d link show dev $dev | jq -r '.[].promiscuity')
2291                                                  2291 
2292         ip link del macvlan-tmp                  2292         ip link del macvlan-tmp
2293                                                  2293 
2294         [[ $promisc == 1 ]] && echo "no" || e    2294         [[ $promisc == 1 ]] && echo "no" || echo "yes"
2295 }                                                2295 }
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php