blob: d1f14f83979e07e3e09c4ba57f26a5a602922405 [file] [log] [blame]
Ido Schimmel73bae672018-02-28 12:25:06 +02001#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4##############################################################################
5# Defines
6
7# Can be overridden by the configuration file.
8PING=${PING:=ping}
9PING6=${PING6:=ping6}
Ido Schimmeld4deb012018-02-28 12:25:07 +020010MZ=${MZ:=mausezahn}
Ido Schimmel73bae672018-02-28 12:25:06 +020011WAIT_TIME=${WAIT_TIME:=5}
12PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
13PAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
Ido Schimmel59be45c2018-03-11 09:57:25 +020014NETIF_TYPE=${NETIF_TYPE:=veth}
15NETIF_CREATE=${NETIF_CREATE:=yes}
Ido Schimmel73bae672018-02-28 12:25:06 +020016
17if [[ -f forwarding.config ]]; then
18 source forwarding.config
19fi
20
21##############################################################################
22# Sanity checks
23
David Ahern198979b2018-03-01 13:49:30 -080024check_tc_version()
25{
26 tc -j &> /dev/null
27 if [[ $? -ne 0 ]]; then
28 echo "SKIP: iproute2 too old; tc is missing JSON support"
29 exit 1
30 fi
31
32 tc filter help 2>&1 | grep block &> /dev/null
33 if [[ $? -ne 0 ]]; then
34 echo "SKIP: iproute2 too old; tc is missing shared block support"
35 exit 1
36 fi
37}
38
Ido Schimmel73bae672018-02-28 12:25:06 +020039if [[ "$(id -u)" -ne 0 ]]; then
40 echo "SKIP: need root privileges"
41 exit 0
42fi
43
David Ahern198979b2018-03-01 13:49:30 -080044if [[ "$CHECK_TC" = "yes" ]]; then
45 check_tc_version
Jiri Pirko4908e242018-02-28 12:25:19 +020046fi
47
Ido Schimmel73bae672018-02-28 12:25:06 +020048if [[ ! -x "$(command -v jq)" ]]; then
49 echo "SKIP: jq not installed"
David Ahern198979b2018-03-01 13:49:30 -080050 exit 1
Ido Schimmel73bae672018-02-28 12:25:06 +020051fi
52
Ido Schimmeld4deb012018-02-28 12:25:07 +020053if [[ ! -x "$(command -v $MZ)" ]]; then
54 echo "SKIP: $MZ not installed"
Ido Schimmelff0162a2018-03-11 09:57:23 +020055 exit 1
Ido Schimmeld4deb012018-02-28 12:25:07 +020056fi
57
Ido Schimmel73bae672018-02-28 12:25:06 +020058if [[ ! -v NUM_NETIFS ]]; then
59 echo "SKIP: importer does not define \"NUM_NETIFS\""
Ido Schimmel231b85a2018-03-11 09:57:24 +020060 exit 1
Ido Schimmel73bae672018-02-28 12:25:06 +020061fi
62
63##############################################################################
Jiri Pirko781fe632018-02-28 12:25:15 +020064# Command line options handling
65
66count=0
67
68while [[ $# -gt 0 ]]; do
69 if [[ "$count" -eq "0" ]]; then
70 unset NETIFS
71 declare -A NETIFS
72 fi
73 count=$((count + 1))
74 NETIFS[p$count]="$1"
75 shift
76done
77
78##############################################################################
Ido Schimmel73bae672018-02-28 12:25:06 +020079# Network interfaces configuration
80
David Ahern190f8872018-03-04 17:37:47 -080081create_netif_veth()
82{
83 local i
84
85 for i in $(eval echo {1..$NUM_NETIFS}); do
86 local j=$((i+1))
87
88 ip link show dev ${NETIFS[p$i]} &> /dev/null
89 if [[ $? -ne 0 ]]; then
90 ip link add ${NETIFS[p$i]} type veth \
91 peer name ${NETIFS[p$j]}
92 if [[ $? -ne 0 ]]; then
93 echo "Failed to create netif"
94 exit 1
95 fi
96 fi
97 i=$j
98 done
99}
100
101create_netif()
102{
103 case "$NETIF_TYPE" in
104 veth) create_netif_veth
105 ;;
106 *) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
107 exit 1
108 ;;
109 esac
110}
111
112if [[ "$NETIF_CREATE" = "yes" ]]; then
113 create_netif
114fi
115
Ido Schimmel73bae672018-02-28 12:25:06 +0200116for i in $(eval echo {1..$NUM_NETIFS}); do
117 ip link show dev ${NETIFS[p$i]} &> /dev/null
118 if [[ $? -ne 0 ]]; then
119 echo "SKIP: could not find all required interfaces"
Ido Schimmel231b85a2018-03-11 09:57:24 +0200120 exit 1
Ido Schimmel73bae672018-02-28 12:25:06 +0200121 fi
122done
123
124##############################################################################
125# Helpers
126
127# Exit status to return at the end. Set in case one of the tests fails.
128EXIT_STATUS=0
129# Per-test return value. Clear at the beginning of each test.
130RET=0
131
132check_err()
133{
134 local err=$1
135 local msg=$2
136
137 if [[ $RET -eq 0 && $err -ne 0 ]]; then
138 RET=$err
139 retmsg=$msg
140 fi
141}
142
143check_fail()
144{
145 local err=$1
146 local msg=$2
147
148 if [[ $RET -eq 0 && $err -eq 0 ]]; then
149 RET=1
150 retmsg=$msg
151 fi
152}
153
154log_test()
155{
156 local test_name=$1
157 local opt_str=$2
158
159 if [[ $# -eq 2 ]]; then
160 opt_str="($opt_str)"
161 fi
162
163 if [[ $RET -ne 0 ]]; then
164 EXIT_STATUS=1
165 printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str"
166 if [[ ! -z "$retmsg" ]]; then
167 printf "\t%s\n" "$retmsg"
168 fi
169 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
170 echo "Hit enter to continue, 'q' to quit"
171 read a
172 [ "$a" = "q" ] && exit 1
173 fi
174 return 1
175 fi
176
177 printf "TEST: %-60s [PASS]\n" "$test_name $opt_str"
178 return 0
179}
180
Ido Schimmel3d578d82018-02-28 12:25:11 +0200181log_info()
182{
183 local msg=$1
184
185 echo "INFO: $msg"
186}
187
Petr Machata010079b2018-06-28 18:56:20 +0200188setup_wait_dev()
189{
190 local dev=$1; shift
191
192 while true; do
193 ip link show dev $dev up \
194 | grep 'state UP' &> /dev/null
195 if [[ $? -ne 0 ]]; then
196 sleep 1
197 else
198 break
199 fi
200 done
201}
202
Ido Schimmel73bae672018-02-28 12:25:06 +0200203setup_wait()
204{
205 for i in $(eval echo {1..$NUM_NETIFS}); do
Petr Machata010079b2018-06-28 18:56:20 +0200206 setup_wait_dev ${NETIFS[p$i]}
Ido Schimmel73bae672018-02-28 12:25:06 +0200207 done
208
209 # Make sure links are ready.
210 sleep $WAIT_TIME
211}
212
213pre_cleanup()
214{
215 if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
216 echo "Pausing before cleanup, hit any key to continue"
217 read
218 fi
219}
220
221vrf_prepare()
222{
223 ip -4 rule add pref 32765 table local
224 ip -4 rule del pref 0
225 ip -6 rule add pref 32765 table local
226 ip -6 rule del pref 0
227}
228
229vrf_cleanup()
230{
231 ip -6 rule add pref 0 table local
232 ip -6 rule del pref 32765
233 ip -4 rule add pref 0 table local
234 ip -4 rule del pref 32765
235}
236
237__last_tb_id=0
238declare -A __TB_IDS
239
240__vrf_td_id_assign()
241{
242 local vrf_name=$1
243
244 __last_tb_id=$((__last_tb_id + 1))
245 __TB_IDS[$vrf_name]=$__last_tb_id
246 return $__last_tb_id
247}
248
249__vrf_td_id_lookup()
250{
251 local vrf_name=$1
252
253 return ${__TB_IDS[$vrf_name]}
254}
255
256vrf_create()
257{
258 local vrf_name=$1
259 local tb_id
260
261 __vrf_td_id_assign $vrf_name
262 tb_id=$?
263
264 ip link add dev $vrf_name type vrf table $tb_id
265 ip -4 route add table $tb_id unreachable default metric 4278198272
266 ip -6 route add table $tb_id unreachable default metric 4278198272
267}
268
269vrf_destroy()
270{
271 local vrf_name=$1
272 local tb_id
273
274 __vrf_td_id_lookup $vrf_name
275 tb_id=$?
276
277 ip -6 route del table $tb_id unreachable default metric 4278198272
278 ip -4 route del table $tb_id unreachable default metric 4278198272
279 ip link del dev $vrf_name
280}
281
282__addr_add_del()
283{
284 local if_name=$1
285 local add_del=$2
286 local array
287
288 shift
289 shift
290 array=("${@}")
291
292 for addrstr in "${array[@]}"; do
293 ip address $add_del $addrstr dev $if_name
294 done
295}
296
Petr Machata3368b222018-06-26 02:08:00 +0200297__simple_if_init()
298{
299 local if_name=$1; shift
300 local vrf_name=$1; shift
301 local addrs=("${@}")
302
303 ip link set dev $if_name master $vrf_name
304 ip link set dev $if_name up
305
306 __addr_add_del $if_name add "${addrs[@]}"
307}
308
309__simple_if_fini()
310{
311 local if_name=$1; shift
312 local addrs=("${@}")
313
314 __addr_add_del $if_name del "${addrs[@]}"
315
316 ip link set dev $if_name down
317 ip link set dev $if_name nomaster
318}
319
Ido Schimmel73bae672018-02-28 12:25:06 +0200320simple_if_init()
321{
322 local if_name=$1
323 local vrf_name
324 local array
325
326 shift
327 vrf_name=v$if_name
328 array=("${@}")
329
330 vrf_create $vrf_name
Ido Schimmel73bae672018-02-28 12:25:06 +0200331 ip link set dev $vrf_name up
Petr Machata3368b222018-06-26 02:08:00 +0200332 __simple_if_init $if_name $vrf_name "${array[@]}"
Ido Schimmel73bae672018-02-28 12:25:06 +0200333}
334
335simple_if_fini()
336{
337 local if_name=$1
338 local vrf_name
339 local array
340
341 shift
342 vrf_name=v$if_name
343 array=("${@}")
344
Petr Machata3368b222018-06-26 02:08:00 +0200345 __simple_if_fini $if_name "${array[@]}"
Ido Schimmel73bae672018-02-28 12:25:06 +0200346 vrf_destroy $vrf_name
347}
348
Petr Machata7d4cbae2018-04-27 01:17:56 +0200349tunnel_create()
350{
351 local name=$1; shift
352 local type=$1; shift
353 local local=$1; shift
354 local remote=$1; shift
355
356 ip link add name $name type $type \
357 local $local remote $remote "$@"
358 ip link set dev $name up
359}
360
361tunnel_destroy()
362{
363 local name=$1; shift
364
365 ip link del dev $name
366}
367
Petr Machata0e7a5042018-05-24 16:27:26 +0200368vlan_create()
369{
370 local if_name=$1; shift
371 local vid=$1; shift
372 local vrf=$1; shift
373 local ips=("${@}")
374 local name=$if_name.$vid
375
376 ip link add name $name link $if_name type vlan id $vid
377 if [ "$vrf" != "" ]; then
378 ip link set dev $name master $vrf
379 fi
380 ip link set dev $name up
381 __addr_add_del $name add "${ips[@]}"
382}
383
384vlan_destroy()
385{
386 local if_name=$1; shift
387 local vid=$1; shift
388 local name=$if_name.$vid
389
390 ip link del dev $name
391}
392
Ido Schimmel73bae672018-02-28 12:25:06 +0200393master_name_get()
394{
395 local if_name=$1
396
397 ip -j link show dev $if_name | jq -r '.[]["master"]'
398}
399
Ido Schimmel3d578d82018-02-28 12:25:11 +0200400link_stats_tx_packets_get()
401{
402 local if_name=$1
403
404 ip -j -s link show dev $if_name | jq '.[]["stats64"]["tx"]["packets"]'
405}
406
Petr Machata7d4cbae2018-04-27 01:17:56 +0200407tc_rule_stats_get()
408{
409 local dev=$1; shift
410 local pref=$1; shift
Petr Machataa66d62d2018-06-26 02:07:45 +0200411 local dir=$1; shift
Petr Machata7d4cbae2018-04-27 01:17:56 +0200412
Petr Machataa66d62d2018-06-26 02:07:45 +0200413 tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
414 | jq '.[1].options.actions[].stats.packets'
Petr Machata7d4cbae2018-04-27 01:17:56 +0200415}
416
Jiri Pirko4e4272d2018-02-28 12:25:14 +0200417mac_get()
418{
419 local if_name=$1
420
421 ip -j link show dev $if_name | jq -r '.[]["address"]'
422}
423
Ido Schimmeld4deb012018-02-28 12:25:07 +0200424bridge_ageing_time_get()
425{
426 local bridge=$1
427 local ageing_time
428
429 # Need to divide by 100 to convert to seconds.
430 ageing_time=$(ip -j -d link show dev $bridge \
431 | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
432 echo $((ageing_time / 100))
433}
434
Petr Machataf5ae5772018-05-03 12:36:59 +0200435declare -A SYSCTL_ORIG
436sysctl_set()
437{
438 local key=$1; shift
439 local value=$1; shift
440
441 SYSCTL_ORIG[$key]=$(sysctl -n $key)
442 sysctl -qw $key=$value
443}
444
445sysctl_restore()
446{
447 local key=$1; shift
448
449 sysctl -qw $key=${SYSCTL_ORIG["$key"]}
450}
451
Ido Schimmel7b7bc872018-02-28 12:25:09 +0200452forwarding_enable()
453{
Petr Machatad51d10a2018-05-03 12:37:13 +0200454 sysctl_set net.ipv4.conf.all.forwarding 1
455 sysctl_set net.ipv6.conf.all.forwarding 1
Ido Schimmel7b7bc872018-02-28 12:25:09 +0200456}
457
458forwarding_restore()
459{
Petr Machatad51d10a2018-05-03 12:37:13 +0200460 sysctl_restore net.ipv6.conf.all.forwarding
461 sysctl_restore net.ipv4.conf.all.forwarding
Ido Schimmel7b7bc872018-02-28 12:25:09 +0200462}
463
Jiri Pirko2f19f212018-02-28 12:25:13 +0200464tc_offload_check()
465{
466 for i in $(eval echo {1..$NUM_NETIFS}); do
467 ethtool -k ${NETIFS[p$i]} \
468 | grep "hw-tc-offload: on" &> /dev/null
469 if [[ $? -ne 0 ]]; then
470 return 1
471 fi
472 done
473
474 return 0
475}
476
Petr Machata87c0c042018-05-24 16:27:35 +0200477trap_install()
Petr Machata7d4cbae2018-04-27 01:17:56 +0200478{
479 local dev=$1; shift
480 local direction=$1; shift
481
Petr Machataac0fcad2018-06-28 18:56:28 +0200482 # Some devices may not support or need in-hardware trapping of traffic
483 # (e.g. the veth pairs that this library creates for non-existent
484 # loopbacks). Use continue instead, so that there is a filter in there
485 # (some tests check counters), and so that other filters are still
486 # processed.
487 tc filter add dev $dev $direction pref 1 \
488 flower skip_sw action trap 2>/dev/null \
489 || tc filter add dev $dev $direction pref 1 \
490 flower action continue
Petr Machata87c0c042018-05-24 16:27:35 +0200491}
492
493trap_uninstall()
494{
495 local dev=$1; shift
496 local direction=$1; shift
497
Petr Machataac0fcad2018-06-28 18:56:28 +0200498 tc filter del dev $dev $direction pref 1 flower
Petr Machata87c0c042018-05-24 16:27:35 +0200499}
500
501slow_path_trap_install()
502{
Petr Machataac0fcad2018-06-28 18:56:28 +0200503 # For slow-path testing, we need to install a trap to get to
504 # slow path the packets that would otherwise be switched in HW.
Petr Machata7d4cbae2018-04-27 01:17:56 +0200505 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
Petr Machata87c0c042018-05-24 16:27:35 +0200506 trap_install "$@"
Petr Machata7d4cbae2018-04-27 01:17:56 +0200507 fi
508}
509
510slow_path_trap_uninstall()
511{
Petr Machata7d4cbae2018-04-27 01:17:56 +0200512 if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
Petr Machata87c0c042018-05-24 16:27:35 +0200513 trap_uninstall "$@"
Petr Machata7d4cbae2018-04-27 01:17:56 +0200514 fi
515}
516
517__icmp_capture_add_del()
518{
519 local add_del=$1; shift
520 local pref=$1; shift
521 local vsuf=$1; shift
522 local tundev=$1; shift
523 local filter=$1; shift
524
525 tc filter $add_del dev "$tundev" ingress \
526 proto ip$vsuf pref $pref \
527 flower ip_proto icmp$vsuf $filter \
528 action pass
529}
530
531icmp_capture_install()
532{
533 __icmp_capture_add_del add 100 "" "$@"
534}
535
536icmp_capture_uninstall()
537{
538 __icmp_capture_add_del del 100 "" "$@"
539}
540
541icmp6_capture_install()
542{
543 __icmp_capture_add_del add 100 v6 "$@"
544}
545
546icmp6_capture_uninstall()
547{
548 __icmp_capture_add_del del 100 v6 "$@"
549}
550
Petr Machata2004a9b2018-05-31 19:52:02 +0200551__vlan_capture_add_del()
552{
553 local add_del=$1; shift
554 local pref=$1; shift
555 local dev=$1; shift
556 local filter=$1; shift
557
558 tc filter $add_del dev "$dev" ingress \
559 proto 802.1q pref $pref \
560 flower $filter \
561 action pass
562}
563
564vlan_capture_install()
565{
566 __vlan_capture_add_del add 100 "$@"
567}
568
569vlan_capture_uninstall()
570{
571 __vlan_capture_add_del del 100 "$@"
572}
573
Petr Machata7d4cbae2018-04-27 01:17:56 +0200574matchall_sink_create()
575{
576 local dev=$1; shift
577
578 tc qdisc add dev $dev clsact
579 tc filter add dev $dev ingress \
580 pref 10000 \
581 matchall \
582 action drop
583}
584
Ido Schimmel0eb80532018-05-03 10:51:33 +0300585tests_run()
586{
587 local current_test
588
589 for current_test in ${TESTS:-$ALL_TESTS}; do
590 $current_test
591 done
592}
593
Petr Machatab2c47872018-06-26 02:06:06 +0200594multipath_eval()
595{
Petr Machata1b86fa32018-06-26 02:07:08 +0200596 local desc="$1"
597 local weight_rp12=$2
598 local weight_rp13=$3
599 local packets_rp12=$4
600 local packets_rp13=$5
601 local weights_ratio packets_ratio diff
Petr Machatab2c47872018-06-26 02:06:06 +0200602
Petr Machata1b86fa32018-06-26 02:07:08 +0200603 RET=0
Petr Machatab2c47872018-06-26 02:06:06 +0200604
Petr Machata1b86fa32018-06-26 02:07:08 +0200605 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
606 weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
607 | bc -l)
608 else
609 weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
610 | bc -l)
611 fi
Petr Machatab2c47872018-06-26 02:06:06 +0200612
Petr Machata1b86fa32018-06-26 02:07:08 +0200613 if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
614 check_err 1 "Packet difference is 0"
615 log_test "Multipath"
616 log_info "Expected ratio $weights_ratio"
617 return
618 fi
Petr Machatab2c47872018-06-26 02:06:06 +0200619
Petr Machata1b86fa32018-06-26 02:07:08 +0200620 if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
621 packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
622 | bc -l)
623 else
624 packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
625 | bc -l)
626 fi
Petr Machatab2c47872018-06-26 02:06:06 +0200627
Petr Machata1b86fa32018-06-26 02:07:08 +0200628 diff=$(echo $weights_ratio - $packets_ratio | bc -l)
629 diff=${diff#-}
630
631 test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
632 check_err $? "Too large discrepancy between expected and measured ratios"
633 log_test "$desc"
634 log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
Petr Machatab2c47872018-06-26 02:06:06 +0200635}
636
Ido Schimmel73bae672018-02-28 12:25:06 +0200637##############################################################################
638# Tests
639
640ping_test()
641{
642 local if_name=$1
643 local dip=$2
644 local vrf_name
645
646 RET=0
647
648 vrf_name=$(master_name_get $if_name)
649 ip vrf exec $vrf_name $PING $dip -c 10 -i 0.1 -w 2 &> /dev/null
650 check_err $?
651 log_test "ping"
652}
653
654ping6_test()
655{
656 local if_name=$1
657 local dip=$2
658 local vrf_name
659
660 RET=0
661
662 vrf_name=$(master_name_get $if_name)
663 ip vrf exec $vrf_name $PING6 $dip -c 10 -i 0.1 -w 2 &> /dev/null
664 check_err $?
665 log_test "ping6"
666}
Ido Schimmeld4deb012018-02-28 12:25:07 +0200667
668learning_test()
669{
670 local bridge=$1
671 local br_port1=$2 # Connected to `host1_if`.
672 local host1_if=$3
673 local host2_if=$4
674 local mac=de:ad:be:ef:13:37
675 local ageing_time
676
677 RET=0
678
679 bridge -j fdb show br $bridge brport $br_port1 \
680 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
681 check_fail $? "Found FDB record when should not"
682
683 # Disable unknown unicast flooding on `br_port1` to make sure
684 # packets are only forwarded through the port after a matching
685 # FDB entry was installed.
686 bridge link set dev $br_port1 flood off
687
688 tc qdisc add dev $host1_if ingress
689 tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
690 flower dst_mac $mac action drop
691
692 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
693 sleep 1
694
695 tc -j -s filter show dev $host1_if ingress \
696 | jq -e ".[] | select(.options.handle == 101) \
697 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
698 check_fail $? "Packet reached second host when should not"
699
700 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
701 sleep 1
702
703 bridge -j fdb show br $bridge brport $br_port1 \
704 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
705 check_err $? "Did not find FDB record when should"
706
707 $MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
708 sleep 1
709
710 tc -j -s filter show dev $host1_if ingress \
711 | jq -e ".[] | select(.options.handle == 101) \
712 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
713 check_err $? "Packet did not reach second host when should"
714
715 # Wait for 10 seconds after the ageing time to make sure FDB
716 # record was aged-out.
717 ageing_time=$(bridge_ageing_time_get $bridge)
718 sleep $((ageing_time + 10))
719
720 bridge -j fdb show br $bridge brport $br_port1 \
721 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
722 check_fail $? "Found FDB record when should not"
723
724 bridge link set dev $br_port1 learning off
725
726 $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
727 sleep 1
728
729 bridge -j fdb show br $bridge brport $br_port1 \
730 | jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
731 check_fail $? "Found FDB record when should not"
732
733 bridge link set dev $br_port1 learning on
734
735 tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
736 tc qdisc del dev $host1_if ingress
737
738 bridge link set dev $br_port1 flood on
739
740 log_test "FDB learning"
741}
Ido Schimmel236dd502018-02-28 12:25:08 +0200742
743flood_test_do()
744{
745 local should_flood=$1
746 local mac=$2
747 local ip=$3
748 local host1_if=$4
749 local host2_if=$5
750 local err=0
751
752 # Add an ACL on `host2_if` which will tell us whether the packet
753 # was flooded to it or not.
754 tc qdisc add dev $host2_if ingress
755 tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
756 flower dst_mac $mac action drop
757
758 $MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
759 sleep 1
760
761 tc -j -s filter show dev $host2_if ingress \
762 | jq -e ".[] | select(.options.handle == 101) \
763 | select(.options.actions[0].stats.packets == 1)" &> /dev/null
764 if [[ $? -ne 0 && $should_flood == "true" || \
765 $? -eq 0 && $should_flood == "false" ]]; then
766 err=1
767 fi
768
769 tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
770 tc qdisc del dev $host2_if ingress
771
772 return $err
773}
774
775flood_unicast_test()
776{
777 local br_port=$1
778 local host1_if=$2
779 local host2_if=$3
780 local mac=de:ad:be:ef:13:37
781 local ip=192.0.2.100
782
783 RET=0
784
785 bridge link set dev $br_port flood off
786
787 flood_test_do false $mac $ip $host1_if $host2_if
788 check_err $? "Packet flooded when should not"
789
790 bridge link set dev $br_port flood on
791
792 flood_test_do true $mac $ip $host1_if $host2_if
793 check_err $? "Packet was not flooded when should"
794
795 log_test "Unknown unicast flood"
796}
797
798flood_multicast_test()
799{
800 local br_port=$1
801 local host1_if=$2
802 local host2_if=$3
803 local mac=01:00:5e:00:00:01
804 local ip=239.0.0.1
805
806 RET=0
807
808 bridge link set dev $br_port mcast_flood off
809
810 flood_test_do false $mac $ip $host1_if $host2_if
811 check_err $? "Packet flooded when should not"
812
813 bridge link set dev $br_port mcast_flood on
814
815 flood_test_do true $mac $ip $host1_if $host2_if
816 check_err $? "Packet was not flooded when should"
817
818 log_test "Unregistered multicast flood"
819}
820
821flood_test()
822{
823 # `br_port` is connected to `host2_if`
824 local br_port=$1
825 local host1_if=$2
826 local host2_if=$3
827
828 flood_unicast_test $br_port $host1_if $host2_if
829 flood_multicast_test $br_port $host1_if $host2_if
830}