xref: /linux/tools/testing/selftests/net/test_bridge_backup_port.sh (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# This test is for checking bridge backup port and backup nexthop ID
5# functionality. The topology consists of two bridge (VTEPs) connected using
6# VXLAN. The test checks that when the switch port (swp1) is down, traffic is
7# redirected to the VXLAN port (vx0). When a backup nexthop ID is configured,
8# the test checks that traffic is redirected with the correct nexthop
9# information.
10#
11# +------------------------------------+ +------------------------------------+
12# |    + swp1                   + vx0  | |    + swp1                   + vx0  |
13# |    |                        |      | |    |                        |      |
14# |    |           br0          |      | |    |                        |      |
15# |    +------------+-----------+      | |    +------------+-----------+      |
16# |                 |                  | |                 |                  |
17# |                 |                  | |                 |                  |
18# |                 +                  | |                 +                  |
19# |                br0                 | |                br0                 |
20# |                 +                  | |                 +                  |
21# |                 |                  | |                 |                  |
22# |                 |                  | |                 |                  |
23# |                 +                  | |                 +                  |
24# |              br0.10                | |              br0.10                |
25# |           192.0.2.65/28            | |            192.0.2.66/28           |
26# |                                    | |                                    |
27# |                                    | |                                    |
28# |                 192.0.2.33         | |                 192.0.2.34         |
29# |                 + lo               | |                 + lo               |
30# |                                    | |                                    |
31# |                                    | |                                    |
32# |                   192.0.2.49/28    | |    192.0.2.50/28                   |
33# |                           veth0 +-------+ veth0                           |
34# |                                    | |                                    |
35# | sw1                                | | sw2                                |
36# +------------------------------------+ +------------------------------------+
37
38source lib.sh
39ret=0
40
41# All tests in this script. Can be overridden with -t option.
42TESTS="
43	backup_port
44	backup_nhid
45	backup_nhid_invalid
46	backup_nhid_ping
47	backup_nhid_torture
48"
49VERBOSE=0
50PAUSE_ON_FAIL=no
51PAUSE=no
52PING_TIMEOUT=5
53
54################################################################################
55# Utilities
56
57log_test()
58{
59	local rc=$1
60	local expected=$2
61	local msg="$3"
62
63	if [ ${rc} -eq ${expected} ]; then
64		printf "TEST: %-60s  [ OK ]\n" "${msg}"
65		nsuccess=$((nsuccess+1))
66	else
67		ret=1
68		nfail=$((nfail+1))
69		printf "TEST: %-60s  [FAIL]\n" "${msg}"
70		if [ "$VERBOSE" = "1" ]; then
71			echo "    rc=$rc, expected $expected"
72		fi
73
74		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
75		echo
76			echo "hit enter to continue, 'q' to quit"
77			read a
78			[ "$a" = "q" ] && exit 1
79		fi
80	fi
81
82	if [ "${PAUSE}" = "yes" ]; then
83		echo
84		echo "hit enter to continue, 'q' to quit"
85		read a
86		[ "$a" = "q" ] && exit 1
87	fi
88
89	[ "$VERBOSE" = "1" ] && echo
90}
91
92run_cmd()
93{
94	local cmd="$1"
95	local out
96	local stderr="2>/dev/null"
97
98	if [ "$VERBOSE" = "1" ]; then
99		printf "COMMAND: $cmd\n"
100		stderr=
101	fi
102
103	out=$(eval $cmd $stderr)
104	rc=$?
105	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
106		echo "    $out"
107	fi
108
109	return $rc
110}
111
112tc_check_packets()
113{
114	local ns=$1; shift
115	local id=$1; shift
116	local handle=$1; shift
117	local count=$1; shift
118	local pkts
119
120	sleep 0.1
121	pkts=$(tc -n $ns -j -s filter show $id \
122		| jq ".[] | select(.options.handle == $handle) | \
123		.options.actions[0].stats.packets")
124	[[ $pkts == $count ]]
125}
126
127bridge_link_check()
128{
129	local ns=$1; shift
130	local dev=$1; shift
131	local state=$1; shift
132
133	bridge -n $ns -d -j link show dev $dev | \
134		jq -e ".[][\"state\"] == \"$state\"" &> /dev/null
135}
136
137################################################################################
138# Setup
139
140setup_topo_ns()
141{
142	local ns=$1; shift
143
144	ip netns exec $ns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
145	ip netns exec $ns sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
146	ip netns exec $ns sysctl -qw net.ipv6.conf.all.accept_dad=0
147	ip netns exec $ns sysctl -qw net.ipv6.conf.default.accept_dad=0
148}
149
150setup_topo()
151{
152	local ns
153
154	setup_ns sw1 sw2
155	for ns in $sw1 $sw2; do
156		setup_topo_ns $ns
157	done
158
159	ip link add name veth0 type veth peer name veth1
160	ip link set dev veth0 netns $sw1 name veth0
161	ip link set dev veth1 netns $sw2 name veth0
162}
163
164setup_sw_common()
165{
166	local ns=$1; shift
167	local local_addr=$1; shift
168	local remote_addr=$1; shift
169	local veth_addr=$1; shift
170	local gw_addr=$1; shift
171	local br_addr=$1; shift
172
173	ip -n $ns address add $local_addr/32 dev lo
174
175	ip -n $ns link set dev veth0 up
176	ip -n $ns address add $veth_addr/28 dev veth0
177	ip -n $ns route add default via $gw_addr
178
179	ip -n $ns link add name br0 up type bridge vlan_filtering 1 \
180		vlan_default_pvid 0 mcast_snooping 0
181
182	ip -n $ns link add link br0 name br0.10 up type vlan id 10
183	bridge -n $ns vlan add vid 10 dev br0 self
184	ip -n $ns address add $br_addr/28 dev br0.10
185
186	ip -n $ns link add name swp1 up type dummy
187	ip -n $ns link set dev swp1 master br0
188	bridge -n $ns vlan add vid 10 dev swp1 untagged
189
190	ip -n $ns link add name vx0 up master br0 type vxlan \
191		local $local_addr dstport 4789 nolearning external
192	bridge -n $ns link set dev vx0 vlan_tunnel on learning off
193
194	bridge -n $ns vlan add vid 10 dev vx0
195	bridge -n $ns vlan add vid 10 dev vx0 tunnel_info id 10010
196}
197
198setup_sw1()
199{
200	local ns=$sw1
201	local local_addr=192.0.2.33
202	local remote_addr=192.0.2.34
203	local veth_addr=192.0.2.49
204	local gw_addr=192.0.2.50
205	local br_addr=192.0.2.65
206
207	setup_sw_common $ns $local_addr $remote_addr $veth_addr $gw_addr \
208		$br_addr
209}
210
211setup_sw2()
212{
213	local ns=$sw2
214	local local_addr=192.0.2.34
215	local remote_addr=192.0.2.33
216	local veth_addr=192.0.2.50
217	local gw_addr=192.0.2.49
218	local br_addr=192.0.2.66
219
220	setup_sw_common $ns $local_addr $remote_addr $veth_addr $gw_addr \
221		$br_addr
222}
223
224setup()
225{
226	set -e
227
228	setup_topo
229	setup_sw1
230	setup_sw2
231
232	sleep 5
233
234	set +e
235}
236
237cleanup()
238{
239	cleanup_ns $sw1 $sw2
240}
241
242################################################################################
243# Tests
244
245backup_port()
246{
247	local dmac=00:11:22:33:44:55
248	local smac=00:aa:bb:cc:dd:ee
249
250	echo
251	echo "Backup port"
252	echo "-----------"
253
254	run_cmd "tc -n $sw1 qdisc replace dev swp1 clsact"
255	run_cmd "tc -n $sw1 filter replace dev swp1 egress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac action pass"
256
257	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
258	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac action pass"
259
260	run_cmd "bridge -n $sw1 fdb replace $dmac dev swp1 master static vlan 10"
261
262	# Initial state - check that packets are forwarded out of swp1 when it
263	# has a carrier and not forwarded out of any port when it does not have
264	# a carrier.
265	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
266	tc_check_packets $sw1 "dev swp1 egress" 101 1
267	log_test $? 0 "Forwarding out of swp1"
268	tc_check_packets $sw1 "dev vx0 egress" 101 0
269	log_test $? 0 "No forwarding out of vx0"
270
271	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
272	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
273	log_test $? 0 "swp1 carrier off"
274
275	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
276	tc_check_packets $sw1 "dev swp1 egress" 101 1
277	log_test $? 0 "No forwarding out of swp1"
278	tc_check_packets $sw1 "dev vx0 egress" 101 0
279	log_test $? 0 "No forwarding out of vx0"
280
281	run_cmd "ip -n $sw1 link set dev swp1 carrier on"
282	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
283	log_test $? 0 "swp1 carrier on"
284
285	# Configure vx0 as the backup port of swp1 and check that packets are
286	# forwarded out of swp1 when it has a carrier and out of vx0 when swp1
287	# does not have a carrier.
288	run_cmd "bridge -n $sw1 link set dev swp1 backup_port vx0"
289	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_port vx0\""
290	log_test $? 0 "vx0 configured as backup port of swp1"
291
292	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
293	tc_check_packets $sw1 "dev swp1 egress" 101 2
294	log_test $? 0 "Forwarding out of swp1"
295	tc_check_packets $sw1 "dev vx0 egress" 101 0
296	log_test $? 0 "No forwarding out of vx0"
297
298	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
299	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
300	log_test $? 0 "swp1 carrier off"
301
302	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
303	tc_check_packets $sw1 "dev swp1 egress" 101 2
304	log_test $? 0 "No forwarding out of swp1"
305	tc_check_packets $sw1 "dev vx0 egress" 101 1
306	log_test $? 0 "Forwarding out of vx0"
307
308	run_cmd "ip -n $sw1 link set dev swp1 carrier on"
309	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
310	log_test $? 0 "swp1 carrier on"
311
312	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
313	tc_check_packets $sw1 "dev swp1 egress" 101 3
314	log_test $? 0 "Forwarding out of swp1"
315	tc_check_packets $sw1 "dev vx0 egress" 101 1
316	log_test $? 0 "No forwarding out of vx0"
317
318	# Check that packets are forwarded out of vx0 when swp1 is
319	# administratively down and out of swp1 when it is administratively up
320	# again.
321	run_cmd "ip -n $sw1 link set dev swp1 down"
322	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
323	log_test $? 0 "swp1 administratively down"
324
325	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
326	tc_check_packets $sw1 "dev swp1 egress" 101 3
327	log_test $? 0 "No forwarding out of swp1"
328	tc_check_packets $sw1 "dev vx0 egress" 101 2
329	log_test $? 0 "Forwarding out of vx0"
330
331	run_cmd "ip -n $sw1 link set dev swp1 up"
332	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
333	log_test $? 0 "swp1 administratively up"
334
335	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
336	tc_check_packets $sw1 "dev swp1 egress" 101 4
337	log_test $? 0 "Forwarding out of swp1"
338	tc_check_packets $sw1 "dev vx0 egress" 101 2
339	log_test $? 0 "No forwarding out of vx0"
340
341	# Remove vx0 as the backup port of swp1 and check that packets are no
342	# longer forwarded out of vx0 when swp1 does not have a carrier.
343	run_cmd "bridge -n $sw1 link set dev swp1 nobackup_port"
344	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_port vx0\""
345	log_test $? 1 "vx0 not configured as backup port of swp1"
346
347	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
348	tc_check_packets $sw1 "dev swp1 egress" 101 5
349	log_test $? 0 "Forwarding out of swp1"
350	tc_check_packets $sw1 "dev vx0 egress" 101 2
351	log_test $? 0 "No forwarding out of vx0"
352
353	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
354	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
355	log_test $? 0 "swp1 carrier off"
356
357	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
358	tc_check_packets $sw1 "dev swp1 egress" 101 5
359	log_test $? 0 "No forwarding out of swp1"
360	tc_check_packets $sw1 "dev vx0 egress" 101 2
361	log_test $? 0 "No forwarding out of vx0"
362}
363
364backup_nhid()
365{
366	local dmac=00:11:22:33:44:55
367	local smac=00:aa:bb:cc:dd:ee
368
369	echo
370	echo "Backup nexthop ID"
371	echo "-----------------"
372
373	run_cmd "tc -n $sw1 qdisc replace dev swp1 clsact"
374	run_cmd "tc -n $sw1 filter replace dev swp1 egress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac action pass"
375
376	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
377	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac action pass"
378
379	run_cmd "ip -n $sw1 nexthop replace id 1 via 192.0.2.34 fdb"
380	run_cmd "ip -n $sw1 nexthop replace id 2 via 192.0.2.34 fdb"
381	run_cmd "ip -n $sw1 nexthop replace id 10 group 1/2 fdb"
382
383	run_cmd "bridge -n $sw1 fdb replace $dmac dev swp1 master static vlan 10"
384	run_cmd "bridge -n $sw1 fdb replace $dmac dev vx0 self static dst 192.0.2.36 src_vni 10010"
385
386	run_cmd "ip -n $sw2 address replace 192.0.2.36/32 dev lo"
387
388	# The first filter matches on packets forwarded using the backup
389	# nexthop ID and the second filter matches on packets forwarded using a
390	# regular VXLAN FDB entry.
391	run_cmd "tc -n $sw2 qdisc replace dev vx0 clsact"
392	run_cmd "tc -n $sw2 filter replace dev vx0 ingress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac enc_key_id 10010 enc_dst_ip 192.0.2.34 action pass"
393	run_cmd "tc -n $sw2 filter replace dev vx0 ingress pref 1 handle 102 proto ip flower src_mac $smac dst_mac $dmac enc_key_id 10010 enc_dst_ip 192.0.2.36 action pass"
394
395	# Configure vx0 as the backup port of swp1 and check that packets are
396	# forwarded out of swp1 when it has a carrier and out of vx0 when swp1
397	# does not have a carrier. When packets are forwarded out of vx0, check
398	# that they are forwarded by the VXLAN FDB entry.
399	run_cmd "bridge -n $sw1 link set dev swp1 backup_port vx0"
400	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_port vx0\""
401	log_test $? 0 "vx0 configured as backup port of swp1"
402
403	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
404	tc_check_packets $sw1 "dev swp1 egress" 101 1
405	log_test $? 0 "Forwarding out of swp1"
406	tc_check_packets $sw1 "dev vx0 egress" 101 0
407	log_test $? 0 "No forwarding out of vx0"
408
409	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
410	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
411	log_test $? 0 "swp1 carrier off"
412
413	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
414	tc_check_packets $sw1 "dev swp1 egress" 101 1
415	log_test $? 0 "No forwarding out of swp1"
416	tc_check_packets $sw1 "dev vx0 egress" 101 1
417	log_test $? 0 "Forwarding out of vx0"
418	tc_check_packets $sw2 "dev vx0 ingress" 101 0
419	log_test $? 0 "No forwarding using backup nexthop ID"
420	tc_check_packets $sw2 "dev vx0 ingress" 102 1
421	log_test $? 0 "Forwarding using VXLAN FDB entry"
422
423	run_cmd "ip -n $sw1 link set dev swp1 carrier on"
424	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
425	log_test $? 0 "swp1 carrier on"
426
427	# Configure nexthop ID 10 as the backup nexthop ID of swp1 and check
428	# that when packets are forwarded out of vx0, they are forwarded using
429	# the backup nexthop ID.
430	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 10"
431	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid 10\""
432	log_test $? 0 "nexthop ID 10 configured as backup nexthop ID of swp1"
433
434	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
435	tc_check_packets $sw1 "dev swp1 egress" 101 2
436	log_test $? 0 "Forwarding out of swp1"
437	tc_check_packets $sw1 "dev vx0 egress" 101 1
438	log_test $? 0 "No forwarding out of vx0"
439
440	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
441	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
442	log_test $? 0 "swp1 carrier off"
443
444	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
445	tc_check_packets $sw1 "dev swp1 egress" 101 2
446	log_test $? 0 "No forwarding out of swp1"
447	tc_check_packets $sw1 "dev vx0 egress" 101 2
448	log_test $? 0 "Forwarding out of vx0"
449	tc_check_packets $sw2 "dev vx0 ingress" 101 1
450	log_test $? 0 "Forwarding using backup nexthop ID"
451	tc_check_packets $sw2 "dev vx0 ingress" 102 1
452	log_test $? 0 "No forwarding using VXLAN FDB entry"
453
454	run_cmd "ip -n $sw1 link set dev swp1 carrier on"
455	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 forwarding
456	log_test $? 0 "swp1 carrier on"
457
458	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
459	tc_check_packets $sw1 "dev swp1 egress" 101 3
460	log_test $? 0 "Forwarding out of swp1"
461	tc_check_packets $sw1 "dev vx0 egress" 101 2
462	log_test $? 0 "No forwarding out of vx0"
463	tc_check_packets $sw2 "dev vx0 ingress" 101 1
464	log_test $? 0 "No forwarding using backup nexthop ID"
465	tc_check_packets $sw2 "dev vx0 ingress" 102 1
466	log_test $? 0 "No forwarding using VXLAN FDB entry"
467
468	# Reset the backup nexthop ID to 0 and check that packets are no longer
469	# forwarded using the backup nexthop ID when swp1 does not have a
470	# carrier and are instead forwarded by the VXLAN FDB.
471	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 0"
472	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid\""
473	log_test $? 1 "No backup nexthop ID configured for swp1"
474
475	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
476	tc_check_packets $sw1 "dev swp1 egress" 101 4
477	log_test $? 0 "Forwarding out of swp1"
478	tc_check_packets $sw1 "dev vx0 egress" 101 2
479	log_test $? 0 "No forwarding out of vx0"
480	tc_check_packets $sw2 "dev vx0 ingress" 101 1
481	log_test $? 0 "No forwarding using backup nexthop ID"
482	tc_check_packets $sw2 "dev vx0 ingress" 102 1
483	log_test $? 0 "No forwarding using VXLAN FDB entry"
484
485	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
486	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
487	log_test $? 0 "swp1 carrier off"
488
489	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
490	tc_check_packets $sw1 "dev swp1 egress" 101 4
491	log_test $? 0 "No forwarding out of swp1"
492	tc_check_packets $sw1 "dev vx0 egress" 101 3
493	log_test $? 0 "Forwarding out of vx0"
494	tc_check_packets $sw2 "dev vx0 ingress" 101 1
495	log_test $? 0 "No forwarding using backup nexthop ID"
496	tc_check_packets $sw2 "dev vx0 ingress" 102 2
497	log_test $? 0 "Forwarding using VXLAN FDB entry"
498}
499
500backup_nhid_invalid()
501{
502	local dmac=00:11:22:33:44:55
503	local smac=00:aa:bb:cc:dd:ee
504	local tx_drop
505
506	echo
507	echo "Backup nexthop ID - invalid IDs"
508	echo "-------------------------------"
509
510	# Check that when traffic is redirected with an invalid nexthop ID, it
511	# is forwarded out of the VXLAN port, but dropped by the VXLAN driver
512	# and does not crash the host.
513
514	run_cmd "tc -n $sw1 qdisc replace dev swp1 clsact"
515	run_cmd "tc -n $sw1 filter replace dev swp1 egress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac action pass"
516
517	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
518	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac action pass"
519	# Drop all other Tx traffic to avoid changes to Tx drop counter.
520	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 2 handle 102 proto all matchall action drop"
521
522	tx_drop=$(ip -n $sw1 -s -j link show dev vx0 | jq '.[]["stats64"]["tx"]["dropped"]')
523
524	run_cmd "ip -n $sw1 nexthop replace id 1 via 192.0.2.34 fdb"
525	run_cmd "ip -n $sw1 nexthop replace id 2 via 192.0.2.34 fdb"
526	run_cmd "ip -n $sw1 nexthop replace id 10 group 1/2 fdb"
527
528	run_cmd "bridge -n $sw1 fdb replace $dmac dev swp1 master static vlan 10"
529
530	run_cmd "tc -n $sw2 qdisc replace dev vx0 clsact"
531	run_cmd "tc -n $sw2 filter replace dev vx0 ingress pref 1 handle 101 proto ip flower src_mac $smac dst_mac $dmac enc_key_id 10010 enc_dst_ip 192.0.2.34 action pass"
532
533	# First, check that redirection works.
534	run_cmd "bridge -n $sw1 link set dev swp1 backup_port vx0"
535	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_port vx0\""
536	log_test $? 0 "vx0 configured as backup port of swp1"
537
538	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 10"
539	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid 10\""
540	log_test $? 0 "Valid nexthop as backup nexthop"
541
542	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
543	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
544	log_test $? 0 "swp1 carrier off"
545
546	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
547	tc_check_packets $sw1 "dev swp1 egress" 101 0
548	log_test $? 0 "No forwarding out of swp1"
549	tc_check_packets $sw1 "dev vx0 egress" 101 1
550	log_test $? 0 "Forwarding out of vx0"
551	tc_check_packets $sw2 "dev vx0 ingress" 101 1
552	log_test $? 0 "Forwarding using backup nexthop ID"
553	run_cmd "ip -n $sw1 -s -j link show dev vx0 | jq -e '.[][\"stats64\"][\"tx\"][\"dropped\"] == $tx_drop'"
554	log_test $? 0 "No Tx drop increase"
555
556	# Use a non-existent nexthop ID.
557	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 20"
558	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid 20\""
559	log_test $? 0 "Non-existent nexthop as backup nexthop"
560
561	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
562	tc_check_packets $sw1 "dev swp1 egress" 101 0
563	log_test $? 0 "No forwarding out of swp1"
564	tc_check_packets $sw1 "dev vx0 egress" 101 2
565	log_test $? 0 "Forwarding out of vx0"
566	tc_check_packets $sw2 "dev vx0 ingress" 101 1
567	log_test $? 0 "No forwarding using backup nexthop ID"
568	run_cmd "ip -n $sw1 -s -j link show dev vx0 | jq -e '.[][\"stats64\"][\"tx\"][\"dropped\"] == $((tx_drop + 1))'"
569	log_test $? 0 "Tx drop increased"
570
571	# Use a blckhole nexthop.
572	run_cmd "ip -n $sw1 nexthop replace id 30 blackhole"
573	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 30"
574	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid 30\""
575	log_test $? 0 "Blackhole nexthop as backup nexthop"
576
577	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
578	tc_check_packets $sw1 "dev swp1 egress" 101 0
579	log_test $? 0 "No forwarding out of swp1"
580	tc_check_packets $sw1 "dev vx0 egress" 101 3
581	log_test $? 0 "Forwarding out of vx0"
582	tc_check_packets $sw2 "dev vx0 ingress" 101 1
583	log_test $? 0 "No forwarding using backup nexthop ID"
584	run_cmd "ip -n $sw1 -s -j link show dev vx0 | jq -e '.[][\"stats64\"][\"tx\"][\"dropped\"] == $((tx_drop + 2))'"
585	log_test $? 0 "Tx drop increased"
586
587	# Non-group FDB nexthop.
588	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 1"
589	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid 1\""
590	log_test $? 0 "Non-group FDB nexthop as backup nexthop"
591
592	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
593	tc_check_packets $sw1 "dev swp1 egress" 101 0
594	log_test $? 0 "No forwarding out of swp1"
595	tc_check_packets $sw1 "dev vx0 egress" 101 4
596	log_test $? 0 "Forwarding out of vx0"
597	tc_check_packets $sw2 "dev vx0 ingress" 101 1
598	log_test $? 0 "No forwarding using backup nexthop ID"
599	run_cmd "ip -n $sw1 -s -j link show dev vx0 | jq -e '.[][\"stats64\"][\"tx\"][\"dropped\"] == $((tx_drop + 3))'"
600	log_test $? 0 "Tx drop increased"
601
602	# IPv6 address family nexthop.
603	run_cmd "ip -n $sw1 nexthop replace id 100 via 2001:db8:100::1 fdb"
604	run_cmd "ip -n $sw1 nexthop replace id 200 via 2001:db8:100::1 fdb"
605	run_cmd "ip -n $sw1 nexthop replace id 300 group 100/200 fdb"
606	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 300"
607	run_cmd "bridge -n $sw1 -d link show dev swp1 | grep \"backup_nhid 300\""
608	log_test $? 0 "IPv6 address family nexthop as backup nexthop"
609
610	run_cmd "ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 1"
611	tc_check_packets $sw1 "dev swp1 egress" 101 0
612	log_test $? 0 "No forwarding out of swp1"
613	tc_check_packets $sw1 "dev vx0 egress" 101 5
614	log_test $? 0 "Forwarding out of vx0"
615	tc_check_packets $sw2 "dev vx0 ingress" 101 1
616	log_test $? 0 "No forwarding using backup nexthop ID"
617	run_cmd "ip -n $sw1 -s -j link show dev vx0 | jq -e '.[][\"stats64\"][\"tx\"][\"dropped\"] == $((tx_drop + 4))'"
618	log_test $? 0 "Tx drop increased"
619}
620
621backup_nhid_ping()
622{
623	local sw1_mac
624	local sw2_mac
625
626	echo
627	echo "Backup nexthop ID - ping"
628	echo "------------------------"
629
630	# Test bidirectional traffic when traffic is redirected in both VTEPs.
631	sw1_mac=$(ip -n $sw1 -j -p link show br0.10 | jq -r '.[]["address"]')
632	sw2_mac=$(ip -n $sw2 -j -p link show br0.10 | jq -r '.[]["address"]')
633
634	run_cmd "bridge -n $sw1 fdb replace $sw2_mac dev swp1 master static vlan 10"
635	run_cmd "bridge -n $sw2 fdb replace $sw1_mac dev swp1 master static vlan 10"
636
637	run_cmd "ip -n $sw1 neigh replace 192.0.2.66 lladdr $sw2_mac nud perm dev br0.10"
638	run_cmd "ip -n $sw2 neigh replace 192.0.2.65 lladdr $sw1_mac nud perm dev br0.10"
639
640	run_cmd "ip -n $sw1 nexthop replace id 1 via 192.0.2.34 fdb"
641	run_cmd "ip -n $sw2 nexthop replace id 1 via 192.0.2.33 fdb"
642	run_cmd "ip -n $sw1 nexthop replace id 10 group 1 fdb"
643	run_cmd "ip -n $sw2 nexthop replace id 10 group 1 fdb"
644
645	run_cmd "bridge -n $sw1 link set dev swp1 backup_port vx0"
646	run_cmd "bridge -n $sw2 link set dev swp1 backup_port vx0"
647	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 10"
648	run_cmd "bridge -n $sw2 link set dev swp1 backup_nhid 10"
649
650	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
651	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw1 swp1 disabled
652	run_cmd "ip -n $sw2 link set dev swp1 carrier off"
653	busywait $BUSYWAIT_TIMEOUT bridge_link_check $sw2 swp1 disabled
654
655	run_cmd "ip netns exec $sw1 ping -i 0.1 -c 10 -w $PING_TIMEOUT 192.0.2.66"
656	log_test $? 0 "Ping with backup nexthop ID"
657
658	# Reset the backup nexthop ID to 0 and check that ping fails.
659	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 0"
660	run_cmd "bridge -n $sw2 link set dev swp1 backup_nhid 0"
661
662	run_cmd "ip netns exec $sw1 ping -i 0.1 -c 10 -w $PING_TIMEOUT 192.0.2.66"
663	log_test $? 1 "Ping after disabling backup nexthop ID"
664}
665
666backup_nhid_add_del_loop()
667{
668	while true; do
669		ip -n $sw1 nexthop del id 10
670		ip -n $sw1 nexthop replace id 10 group 1/2 fdb
671	done >/dev/null 2>&1
672}
673
674backup_nhid_torture()
675{
676	local dmac=00:11:22:33:44:55
677	local smac=00:aa:bb:cc:dd:ee
678	local pid1
679	local pid2
680	local pid3
681
682	echo
683	echo "Backup nexthop ID - torture test"
684	echo "--------------------------------"
685
686	# Continuously send traffic through the backup nexthop while adding and
687	# deleting the group. The test is considered successful if nothing
688	# crashed.
689
690	run_cmd "ip -n $sw1 nexthop replace id 1 via 192.0.2.34 fdb"
691	run_cmd "ip -n $sw1 nexthop replace id 2 via 192.0.2.34 fdb"
692	run_cmd "ip -n $sw1 nexthop replace id 10 group 1/2 fdb"
693
694	run_cmd "bridge -n $sw1 fdb replace $dmac dev swp1 master static vlan 10"
695
696	run_cmd "bridge -n $sw1 link set dev swp1 backup_port vx0"
697	run_cmd "bridge -n $sw1 link set dev swp1 backup_nhid 10"
698	run_cmd "ip -n $sw1 link set dev swp1 carrier off"
699
700	backup_nhid_add_del_loop &
701	pid1=$!
702	ip netns exec $sw1 mausezahn br0.10 -a $smac -b $dmac -A 198.51.100.1 -B 198.51.100.2 -t ip -p 100 -q -c 0 &
703	pid2=$!
704
705	sleep 30
706	kill -9 $pid1 $pid2
707	wait $pid1 $pid2 2>/dev/null
708
709	log_test 0 0 "Torture test"
710}
711
712################################################################################
713# Usage
714
715usage()
716{
717	cat <<EOF
718usage: ${0##*/} OPTS
719
720        -t <test>   Test(s) to run (default: all)
721                    (options: $TESTS)
722        -p          Pause on fail
723        -P          Pause after each test before cleanup
724        -v          Verbose mode (show commands and output)
725        -w          Timeout for ping
726EOF
727}
728
729################################################################################
730# Main
731
732trap cleanup EXIT
733
734while getopts ":t:pPvhw:" opt; do
735	case $opt in
736		t) TESTS=$OPTARG;;
737		p) PAUSE_ON_FAIL=yes;;
738		P) PAUSE=yes;;
739		v) VERBOSE=$(($VERBOSE + 1));;
740		w) PING_TIMEOUT=$OPTARG;;
741		h) usage; exit 0;;
742		*) usage; exit 1;;
743	esac
744done
745
746# Make sure we don't pause twice.
747[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
748
749if [ "$(id -u)" -ne 0 ];then
750	echo "SKIP: Need root privileges"
751	exit $ksft_skip;
752fi
753
754if [ ! -x "$(command -v ip)" ]; then
755	echo "SKIP: Could not run test without ip tool"
756	exit $ksft_skip
757fi
758
759if [ ! -x "$(command -v bridge)" ]; then
760	echo "SKIP: Could not run test without bridge tool"
761	exit $ksft_skip
762fi
763
764if [ ! -x "$(command -v tc)" ]; then
765	echo "SKIP: Could not run test without tc tool"
766	exit $ksft_skip
767fi
768
769if [ ! -x "$(command -v mausezahn)" ]; then
770	echo "SKIP: Could not run test without mausezahn tool"
771	exit $ksft_skip
772fi
773
774if [ ! -x "$(command -v jq)" ]; then
775	echo "SKIP: Could not run test without jq tool"
776	exit $ksft_skip
777fi
778
779bridge link help 2>&1 | grep -q "backup_nhid"
780if [ $? -ne 0 ]; then
781   echo "SKIP: iproute2 bridge too old, missing backup nexthop ID support"
782   exit $ksft_skip
783fi
784
785# Start clean.
786cleanup
787
788for t in $TESTS
789do
790	setup; $t; cleanup;
791done
792
793if [ "$TESTS" != "none" ]; then
794	printf "\nTests passed: %3d\n" ${nsuccess}
795	printf "Tests failed: %3d\n"   ${nfail}
796fi
797
798exit $ret
799