1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# This test is for checking bridge neighbor suppression functionality. The
5# topology consists of two bridges (VTEPs) connected using VXLAN. A single
6# host is connected to each bridge over multiple VLANs. The test checks that
7# ARP/NS messages from the first host are suppressed on the VXLAN port when
8# should.
9#
10# +-----------------------+              +------------------------+
11# | h1                    |              | h2                     |
12# |                       |              |                        |
13# | + eth0.10             |              | + eth0.10              |
14# | | 192.0.2.1/28        |              | | 192.0.2.2/28         |
15# | | 2001:db8:1::1/64    |              | | 2001:db8:1::2/64     |
16# | |                     |              | |                      |
17# | |  + eth0.20          |              | |  + eth0.20           |
18# | \  | 192.0.2.17/28    |              | \  | 192.0.2.18/28     |
19# |  \ | 2001:db8:2::1/64 |              |  \ | 2001:db8:2::2/64  |
20# |   \|                  |              |   \|                   |
21# |    + eth0             |              |    + eth0              |
22# +----|------------------+              +----|-------------------+
23#      |                                      |
24#      |                                      |
25# +----|-------------------------------+ +----|-------------------------------+
26# |    + swp1                   + vx0  | |    + swp1                   + vx0  |
27# |    |                        |      | |    |                        |      |
28# |    |           br0          |      | |    |                        |      |
29# |    +------------+-----------+      | |    +------------+-----------+      |
30# |                 |                  | |                 |                  |
31# |                 |                  | |                 |                  |
32# |             +---+---+              | |             +---+---+              |
33# |             |       |              | |             |       |              |
34# |             |       |              | |             |       |              |
35# |             +       +              | |             +       +              |
36# |          br0.10  br0.20            | |          br0.10  br0.20            |
37# |                                    | |                                    |
38# |                 192.0.2.33         | |                 192.0.2.34         |
39# |                 + lo               | |                 + lo               |
40# |                                    | |                                    |
41# |                                    | |                                    |
42# |                   192.0.2.49/28    | |    192.0.2.50/28                   |
43# |                           veth0 +-------+ veth0                           |
44# |                                    | |                                    |
45# | sw1                                | | sw2                                |
46# +------------------------------------+ +------------------------------------+
47
48source lib.sh
49ret=0
50
51# All tests in this script. Can be overridden with -t option.
52TESTS="
53	neigh_suppress_arp
54	neigh_suppress_ns
55	neigh_vlan_suppress_arp
56	neigh_vlan_suppress_ns
57"
58VERBOSE=0
59PAUSE_ON_FAIL=no
60PAUSE=no
61
62################################################################################
63# Utilities
64
65log_test()
66{
67	local rc=$1
68	local expected=$2
69	local msg="$3"
70
71	if [ ${rc} -eq ${expected} ]; then
72		printf "TEST: %-60s  [ OK ]\n" "${msg}"
73		nsuccess=$((nsuccess+1))
74	else
75		ret=1
76		nfail=$((nfail+1))
77		printf "TEST: %-60s  [FAIL]\n" "${msg}"
78		if [ "$VERBOSE" = "1" ]; then
79			echo "    rc=$rc, expected $expected"
80		fi
81
82		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
83		echo
84			echo "hit enter to continue, 'q' to quit"
85			read a
86			[ "$a" = "q" ] && exit 1
87		fi
88	fi
89
90	if [ "${PAUSE}" = "yes" ]; then
91		echo
92		echo "hit enter to continue, 'q' to quit"
93		read a
94		[ "$a" = "q" ] && exit 1
95	fi
96
97	[ "$VERBOSE" = "1" ] && echo
98}
99
100run_cmd()
101{
102	local cmd="$1"
103	local out
104	local stderr="2>/dev/null"
105
106	if [ "$VERBOSE" = "1" ]; then
107		printf "COMMAND: $cmd\n"
108		stderr=
109	fi
110
111	out=$(eval $cmd $stderr)
112	rc=$?
113	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
114		echo "    $out"
115	fi
116
117	return $rc
118}
119
120tc_check_packets()
121{
122	local ns=$1; shift
123	local id=$1; shift
124	local handle=$1; shift
125	local count=$1; shift
126	local pkts
127
128	sleep 0.1
129	pkts=$(tc -n $ns -j -s filter show $id \
130		| jq ".[] | select(.options.handle == $handle) | \
131		.options.actions[0].stats.packets")
132	[[ $pkts == $count ]]
133}
134
135################################################################################
136# Setup
137
138setup_topo_ns()
139{
140	local ns=$1; shift
141
142	ip netns exec $ns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
143	ip netns exec $ns sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
144	ip netns exec $ns sysctl -qw net.ipv6.conf.all.accept_dad=0
145	ip netns exec $ns sysctl -qw net.ipv6.conf.default.accept_dad=0
146}
147
148setup_topo()
149{
150	local ns
151
152	setup_ns h1 h2 sw1 sw2
153	for ns in $h1 $h2 $sw1 $sw2; do
154		setup_topo_ns $ns
155	done
156
157	ip -n $h1 link add name eth0 type veth peer name swp1 netns $sw1
158	ip -n $sw1 link add name veth0 type veth peer name veth0 netns $sw2
159	ip -n $h2 link add name eth0 type veth peer name swp1 netns $sw2
160}
161
162setup_host_common()
163{
164	local ns=$1; shift
165	local v4addr1=$1; shift
166	local v4addr2=$1; shift
167	local v6addr1=$1; shift
168	local v6addr2=$1; shift
169
170	ip -n $ns link set dev eth0 up
171	ip -n $ns link add link eth0 name eth0.10 up type vlan id 10
172	ip -n $ns link add link eth0 name eth0.20 up type vlan id 20
173
174	ip -n $ns address add $v4addr1 dev eth0.10
175	ip -n $ns address add $v4addr2 dev eth0.20
176	ip -n $ns address add $v6addr1 dev eth0.10
177	ip -n $ns address add $v6addr2 dev eth0.20
178}
179
180setup_h1()
181{
182	local ns=$h1
183	local v4addr1=192.0.2.1/28
184	local v4addr2=192.0.2.17/28
185	local v6addr1=2001:db8:1::1/64
186	local v6addr2=2001:db8:2::1/64
187
188	setup_host_common $ns $v4addr1 $v4addr2 $v6addr1 $v6addr2
189}
190
191setup_h2()
192{
193	local ns=$h2
194	local v4addr1=192.0.2.2/28
195	local v4addr2=192.0.2.18/28
196	local v6addr1=2001:db8:1::2/64
197	local v6addr2=2001:db8:2::2/64
198
199	setup_host_common $ns $v4addr1 $v4addr2 $v6addr1 $v6addr2
200}
201
202setup_sw_common()
203{
204	local ns=$1; shift
205	local local_addr=$1; shift
206	local remote_addr=$1; shift
207	local veth_addr=$1; shift
208	local gw_addr=$1; shift
209
210	ip -n $ns address add $local_addr/32 dev lo
211
212	ip -n $ns link set dev veth0 up
213	ip -n $ns address add $veth_addr/28 dev veth0
214	ip -n $ns route add default via $gw_addr
215
216	ip -n $ns link add name br0 up type bridge vlan_filtering 1 \
217		vlan_default_pvid 0 mcast_snooping 0
218
219	ip -n $ns link add link br0 name br0.10 up type vlan id 10
220	bridge -n $ns vlan add vid 10 dev br0 self
221
222	ip -n $ns link add link br0 name br0.20 up type vlan id 20
223	bridge -n $ns vlan add vid 20 dev br0 self
224
225	ip -n $ns link set dev swp1 up master br0
226	bridge -n $ns vlan add vid 10 dev swp1
227	bridge -n $ns vlan add vid 20 dev swp1
228
229	ip -n $ns link add name vx0 up master br0 type vxlan \
230		local $local_addr dstport 4789 nolearning external
231	bridge -n $ns fdb add 00:00:00:00:00:00 dev vx0 self static \
232		dst $remote_addr src_vni 10010
233	bridge -n $ns fdb add 00:00:00:00:00:00 dev vx0 self static \
234		dst $remote_addr src_vni 10020
235	bridge -n $ns link set dev vx0 vlan_tunnel on learning off
236
237	bridge -n $ns vlan add vid 10 dev vx0
238	bridge -n $ns vlan add vid 10 dev vx0 tunnel_info id 10010
239
240	bridge -n $ns vlan add vid 20 dev vx0
241	bridge -n $ns vlan add vid 20 dev vx0 tunnel_info id 10020
242}
243
244setup_sw1()
245{
246	local ns=$sw1
247	local local_addr=192.0.2.33
248	local remote_addr=192.0.2.34
249	local veth_addr=192.0.2.49
250	local gw_addr=192.0.2.50
251
252	setup_sw_common $ns $local_addr $remote_addr $veth_addr $gw_addr
253}
254
255setup_sw2()
256{
257	local ns=$sw2
258	local local_addr=192.0.2.34
259	local remote_addr=192.0.2.33
260	local veth_addr=192.0.2.50
261	local gw_addr=192.0.2.49
262
263	setup_sw_common $ns $local_addr $remote_addr $veth_addr $gw_addr
264}
265
266setup()
267{
268	set -e
269
270	setup_topo
271	setup_h1
272	setup_h2
273	setup_sw1
274	setup_sw2
275
276	sleep 5
277
278	set +e
279}
280
281cleanup()
282{
283	cleanup_ns $h1 $h2 $sw1 $sw2
284}
285
286################################################################################
287# Tests
288
289neigh_suppress_arp_common()
290{
291	local vid=$1; shift
292	local sip=$1; shift
293	local tip=$1; shift
294	local h2_mac
295
296	echo
297	echo "Per-port ARP suppression - VLAN $vid"
298	echo "----------------------------------"
299
300	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
301	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto 0x0806 flower indev swp1 arp_tip $tip arp_sip $sip arp_op request action pass"
302
303	# Initial state - check that ARP requests are not suppressed and that
304	# ARP replies are received.
305	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
306	log_test $? 0 "arping"
307	tc_check_packets $sw1 "dev vx0 egress" 101 1
308	log_test $? 0 "ARP suppression"
309
310	# Enable neighbor suppression and check that nothing changes compared
311	# to the initial state.
312	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
313	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
314	log_test $? 0 "\"neigh_suppress\" is on"
315
316	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
317	log_test $? 0 "arping"
318	tc_check_packets $sw1 "dev vx0 egress" 101 2
319	log_test $? 0 "ARP suppression"
320
321	# Install an FDB entry for the remote host and check that nothing
322	# changes compared to the initial state.
323	h2_mac=$(ip -n $h2 -j -p link show eth0.$vid | jq -r '.[]["address"]')
324	run_cmd "bridge -n $sw1 fdb replace $h2_mac dev vx0 master static vlan $vid"
325	log_test $? 0 "FDB entry installation"
326
327	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
328	log_test $? 0 "arping"
329	tc_check_packets $sw1 "dev vx0 egress" 101 3
330	log_test $? 0 "ARP suppression"
331
332	# Install a neighbor on the matching SVI interface and check that ARP
333	# requests are suppressed.
334	run_cmd "ip -n $sw1 neigh replace $tip lladdr $h2_mac nud permanent dev br0.$vid"
335	log_test $? 0 "Neighbor entry installation"
336
337	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
338	log_test $? 0 "arping"
339	tc_check_packets $sw1 "dev vx0 egress" 101 3
340	log_test $? 0 "ARP suppression"
341
342	# Take the second host down and check that ARP requests are suppressed
343	# and that ARP replies are received.
344	run_cmd "ip -n $h2 link set dev eth0.$vid down"
345	log_test $? 0 "H2 down"
346
347	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
348	log_test $? 0 "arping"
349	tc_check_packets $sw1 "dev vx0 egress" 101 3
350	log_test $? 0 "ARP suppression"
351
352	run_cmd "ip -n $h2 link set dev eth0.$vid up"
353	log_test $? 0 "H2 up"
354
355	# Disable neighbor suppression and check that ARP requests are no
356	# longer suppressed.
357	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off"
358	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\""
359	log_test $? 0 "\"neigh_suppress\" is off"
360
361	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
362	log_test $? 0 "arping"
363	tc_check_packets $sw1 "dev vx0 egress" 101 4
364	log_test $? 0 "ARP suppression"
365
366	# Take the second host down and check that ARP requests are not
367	# suppressed and that ARP replies are not received.
368	run_cmd "ip -n $h2 link set dev eth0.$vid down"
369	log_test $? 0 "H2 down"
370
371	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip"
372	log_test $? 1 "arping"
373	tc_check_packets $sw1 "dev vx0 egress" 101 5
374	log_test $? 0 "ARP suppression"
375}
376
377neigh_suppress_arp()
378{
379	local vid=10
380	local sip=192.0.2.1
381	local tip=192.0.2.2
382
383	neigh_suppress_arp_common $vid $sip $tip
384
385	vid=20
386	sip=192.0.2.17
387	tip=192.0.2.18
388	neigh_suppress_arp_common $vid $sip $tip
389}
390
391neigh_suppress_ns_common()
392{
393	local vid=$1; shift
394	local saddr=$1; shift
395	local daddr=$1; shift
396	local maddr=$1; shift
397	local h2_mac
398
399	echo
400	echo "Per-port NS suppression - VLAN $vid"
401	echo "---------------------------------"
402
403	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
404	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr type 135 code 0 action pass"
405
406	# Initial state - check that NS messages are not suppressed and that ND
407	# messages are received.
408	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
409	log_test $? 0 "ndisc6"
410	tc_check_packets $sw1 "dev vx0 egress" 101 1
411	log_test $? 0 "NS suppression"
412
413	# Enable neighbor suppression and check that nothing changes compared
414	# to the initial state.
415	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
416	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
417	log_test $? 0 "\"neigh_suppress\" is on"
418
419	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
420	log_test $? 0 "ndisc6"
421	tc_check_packets $sw1 "dev vx0 egress" 101 2
422	log_test $? 0 "NS suppression"
423
424	# Install an FDB entry for the remote host and check that nothing
425	# changes compared to the initial state.
426	h2_mac=$(ip -n $h2 -j -p link show eth0.$vid | jq -r '.[]["address"]')
427	run_cmd "bridge -n $sw1 fdb replace $h2_mac dev vx0 master static vlan $vid"
428	log_test $? 0 "FDB entry installation"
429
430	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
431	log_test $? 0 "ndisc6"
432	tc_check_packets $sw1 "dev vx0 egress" 101 3
433	log_test $? 0 "NS suppression"
434
435	# Install a neighbor on the matching SVI interface and check that NS
436	# messages are suppressed.
437	run_cmd "ip -n $sw1 neigh replace $daddr lladdr $h2_mac nud permanent dev br0.$vid"
438	log_test $? 0 "Neighbor entry installation"
439
440	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
441	log_test $? 0 "ndisc6"
442	tc_check_packets $sw1 "dev vx0 egress" 101 3
443	log_test $? 0 "NS suppression"
444
445	# Take the second host down and check that NS messages are suppressed
446	# and that ND messages are received.
447	run_cmd "ip -n $h2 link set dev eth0.$vid down"
448	log_test $? 0 "H2 down"
449
450	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
451	log_test $? 0 "ndisc6"
452	tc_check_packets $sw1 "dev vx0 egress" 101 3
453	log_test $? 0 "NS suppression"
454
455	run_cmd "ip -n $h2 link set dev eth0.$vid up"
456	log_test $? 0 "H2 up"
457
458	# Disable neighbor suppression and check that NS messages are no longer
459	# suppressed.
460	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off"
461	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\""
462	log_test $? 0 "\"neigh_suppress\" is off"
463
464	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
465	log_test $? 0 "ndisc6"
466	tc_check_packets $sw1 "dev vx0 egress" 101 4
467	log_test $? 0 "NS suppression"
468
469	# Take the second host down and check that NS messages are not
470	# suppressed and that ND messages are not received.
471	run_cmd "ip -n $h2 link set dev eth0.$vid down"
472	log_test $? 0 "H2 down"
473
474	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid"
475	log_test $? 2 "ndisc6"
476	tc_check_packets $sw1 "dev vx0 egress" 101 5
477	log_test $? 0 "NS suppression"
478}
479
480neigh_suppress_ns()
481{
482	local vid=10
483	local saddr=2001:db8:1::1
484	local daddr=2001:db8:1::2
485	local maddr=ff02::1:ff00:2
486
487	neigh_suppress_ns_common $vid $saddr $daddr $maddr
488
489	vid=20
490	saddr=2001:db8:2::1
491	daddr=2001:db8:2::2
492	maddr=ff02::1:ff00:2
493
494	neigh_suppress_ns_common $vid $saddr $daddr $maddr
495}
496
497neigh_vlan_suppress_arp()
498{
499	local vid1=10
500	local vid2=20
501	local sip1=192.0.2.1
502	local sip2=192.0.2.17
503	local tip1=192.0.2.2
504	local tip2=192.0.2.18
505	local h2_mac1
506	local h2_mac2
507
508	echo
509	echo "Per-{Port, VLAN} ARP suppression"
510	echo "--------------------------------"
511
512	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
513	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto 0x0806 flower indev swp1 arp_tip $tip1 arp_sip $sip1 arp_op request action pass"
514	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 102 proto 0x0806 flower indev swp1 arp_tip $tip2 arp_sip $sip2 arp_op request action pass"
515
516	h2_mac1=$(ip -n $h2 -j -p link show eth0.$vid1 | jq -r '.[]["address"]')
517	h2_mac2=$(ip -n $h2 -j -p link show eth0.$vid2 | jq -r '.[]["address"]')
518	run_cmd "bridge -n $sw1 fdb replace $h2_mac1 dev vx0 master static vlan $vid1"
519	run_cmd "bridge -n $sw1 fdb replace $h2_mac2 dev vx0 master static vlan $vid2"
520	run_cmd "ip -n $sw1 neigh replace $tip1 lladdr $h2_mac1 nud permanent dev br0.$vid1"
521	run_cmd "ip -n $sw1 neigh replace $tip2 lladdr $h2_mac2 nud permanent dev br0.$vid2"
522
523	# Enable per-{Port, VLAN} neighbor suppression and check that ARP
524	# requests are not suppressed and that ARP replies are received.
525	run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress on"
526	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress on\""
527	log_test $? 0 "\"neigh_vlan_suppress\" is on"
528
529	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1"
530	log_test $? 0 "arping (VLAN $vid1)"
531	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2"
532	log_test $? 0 "arping (VLAN $vid2)"
533
534	tc_check_packets $sw1 "dev vx0 egress" 101 1
535	log_test $? 0 "ARP suppression (VLAN $vid1)"
536	tc_check_packets $sw1 "dev vx0 egress" 102 1
537	log_test $? 0 "ARP suppression (VLAN $vid2)"
538
539	# Enable neighbor suppression on VLAN 10 and check that only on this
540	# VLAN ARP requests are suppressed.
541	run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress on"
542	run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress on\""
543	log_test $? 0 "\"neigh_suppress\" is on (VLAN $vid1)"
544	run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid2 | grep \"neigh_suppress off\""
545	log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid2)"
546
547	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1"
548	log_test $? 0 "arping (VLAN $vid1)"
549	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2"
550	log_test $? 0 "arping (VLAN $vid2)"
551
552	tc_check_packets $sw1 "dev vx0 egress" 101 1
553	log_test $? 0 "ARP suppression (VLAN $vid1)"
554	tc_check_packets $sw1 "dev vx0 egress" 102 2
555	log_test $? 0 "ARP suppression (VLAN $vid2)"
556
557	# Enable neighbor suppression on the port and check that it has no
558	# effect compared to previous state.
559	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
560	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
561	log_test $? 0 "\"neigh_suppress\" is on"
562
563	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1"
564	log_test $? 0 "arping (VLAN $vid1)"
565	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2"
566	log_test $? 0 "arping (VLAN $vid2)"
567
568	tc_check_packets $sw1 "dev vx0 egress" 101 1
569	log_test $? 0 "ARP suppression (VLAN $vid1)"
570	tc_check_packets $sw1 "dev vx0 egress" 102 3
571	log_test $? 0 "ARP suppression (VLAN $vid2)"
572
573	# Disable neighbor suppression on the port and check that it has no
574	# effect compared to previous state.
575	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off"
576	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\""
577	log_test $? 0 "\"neigh_suppress\" is off"
578
579	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1"
580	log_test $? 0 "arping (VLAN $vid1)"
581	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2"
582	log_test $? 0 "arping (VLAN $vid2)"
583
584	tc_check_packets $sw1 "dev vx0 egress" 101 1
585	log_test $? 0 "ARP suppression (VLAN $vid1)"
586	tc_check_packets $sw1 "dev vx0 egress" 102 4
587	log_test $? 0 "ARP suppression (VLAN $vid2)"
588
589	# Disable neighbor suppression on VLAN 10 and check that ARP requests
590	# are no longer suppressed on this VLAN.
591	run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress off"
592	run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress off\""
593	log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid1)"
594
595	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1"
596	log_test $? 0 "arping (VLAN $vid1)"
597	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2"
598	log_test $? 0 "arping (VLAN $vid2)"
599
600	tc_check_packets $sw1 "dev vx0 egress" 101 2
601	log_test $? 0 "ARP suppression (VLAN $vid1)"
602	tc_check_packets $sw1 "dev vx0 egress" 102 5
603	log_test $? 0 "ARP suppression (VLAN $vid2)"
604
605	# Disable per-{Port, VLAN} neighbor suppression, enable neighbor
606	# suppression on the port and check that on both VLANs ARP requests are
607	# suppressed.
608	run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress off"
609	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress off\""
610	log_test $? 0 "\"neigh_vlan_suppress\" is off"
611
612	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
613	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
614	log_test $? 0 "\"neigh_suppress\" is on"
615
616	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1"
617	log_test $? 0 "arping (VLAN $vid1)"
618	run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2"
619	log_test $? 0 "arping (VLAN $vid2)"
620
621	tc_check_packets $sw1 "dev vx0 egress" 101 2
622	log_test $? 0 "ARP suppression (VLAN $vid1)"
623	tc_check_packets $sw1 "dev vx0 egress" 102 5
624	log_test $? 0 "ARP suppression (VLAN $vid2)"
625}
626
627neigh_vlan_suppress_ns()
628{
629	local vid1=10
630	local vid2=20
631	local saddr1=2001:db8:1::1
632	local saddr2=2001:db8:2::1
633	local daddr1=2001:db8:1::2
634	local daddr2=2001:db8:2::2
635	local maddr=ff02::1:ff00:2
636	local h2_mac1
637	local h2_mac2
638
639	echo
640	echo "Per-{Port, VLAN} NS suppression"
641	echo "-------------------------------"
642
643	run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact"
644	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr1 type 135 code 0 action pass"
645	run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 102 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr2 type 135 code 0 action pass"
646
647	h2_mac1=$(ip -n $h2 -j -p link show eth0.$vid1 | jq -r '.[]["address"]')
648	h2_mac2=$(ip -n $h2 -j -p link show eth0.$vid2 | jq -r '.[]["address"]')
649	run_cmd "bridge -n $sw1 fdb replace $h2_mac1 dev vx0 master static vlan $vid1"
650	run_cmd "bridge -n $sw1 fdb replace $h2_mac2 dev vx0 master static vlan $vid2"
651	run_cmd "ip -n $sw1 neigh replace $daddr1 lladdr $h2_mac1 nud permanent dev br0.$vid1"
652	run_cmd "ip -n $sw1 neigh replace $daddr2 lladdr $h2_mac2 nud permanent dev br0.$vid2"
653
654	# Enable per-{Port, VLAN} neighbor suppression and check that NS
655	# messages are not suppressed and that ND messages are received.
656	run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress on"
657	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress on\""
658	log_test $? 0 "\"neigh_vlan_suppress\" is on"
659
660	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1"
661	log_test $? 0 "ndisc6 (VLAN $vid1)"
662	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2"
663	log_test $? 0 "ndisc6 (VLAN $vid2)"
664
665	tc_check_packets $sw1 "dev vx0 egress" 101 1
666	log_test $? 0 "NS suppression (VLAN $vid1)"
667	tc_check_packets $sw1 "dev vx0 egress" 102 1
668	log_test $? 0 "NS suppression (VLAN $vid2)"
669
670	# Enable neighbor suppression on VLAN 10 and check that only on this
671	# VLAN NS messages are suppressed.
672	run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress on"
673	run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress on\""
674	log_test $? 0 "\"neigh_suppress\" is on (VLAN $vid1)"
675	run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid2 | grep \"neigh_suppress off\""
676	log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid2)"
677
678	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1"
679	log_test $? 0 "ndisc6 (VLAN $vid1)"
680	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2"
681	log_test $? 0 "ndisc6 (VLAN $vid2)"
682
683	tc_check_packets $sw1 "dev vx0 egress" 101 1
684	log_test $? 0 "NS suppression (VLAN $vid1)"
685	tc_check_packets $sw1 "dev vx0 egress" 102 2
686	log_test $? 0 "NS suppression (VLAN $vid2)"
687
688	# Enable neighbor suppression on the port and check that it has no
689	# effect compared to previous state.
690	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
691	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
692	log_test $? 0 "\"neigh_suppress\" is on"
693
694	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1"
695	log_test $? 0 "ndisc6 (VLAN $vid1)"
696	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2"
697	log_test $? 0 "ndisc6 (VLAN $vid2)"
698
699	tc_check_packets $sw1 "dev vx0 egress" 101 1
700	log_test $? 0 "NS suppression (VLAN $vid1)"
701	tc_check_packets $sw1 "dev vx0 egress" 102 3
702	log_test $? 0 "NS suppression (VLAN $vid2)"
703
704	# Disable neighbor suppression on the port and check that it has no
705	# effect compared to previous state.
706	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off"
707	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\""
708	log_test $? 0 "\"neigh_suppress\" is off"
709
710	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1"
711	log_test $? 0 "ndisc6 (VLAN $vid1)"
712	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2"
713	log_test $? 0 "ndisc6 (VLAN $vid2)"
714
715	tc_check_packets $sw1 "dev vx0 egress" 101 1
716	log_test $? 0 "NS suppression (VLAN $vid1)"
717	tc_check_packets $sw1 "dev vx0 egress" 102 4
718	log_test $? 0 "NS suppression (VLAN $vid2)"
719
720	# Disable neighbor suppression on VLAN 10 and check that NS messages
721	# are no longer suppressed on this VLAN.
722	run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress off"
723	run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress off\""
724	log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid1)"
725
726	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1"
727	log_test $? 0 "ndisc6 (VLAN $vid1)"
728	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2"
729	log_test $? 0 "ndisc6 (VLAN $vid2)"
730
731	tc_check_packets $sw1 "dev vx0 egress" 101 2
732	log_test $? 0 "NS suppression (VLAN $vid1)"
733	tc_check_packets $sw1 "dev vx0 egress" 102 5
734	log_test $? 0 "NS suppression (VLAN $vid2)"
735
736	# Disable per-{Port, VLAN} neighbor suppression, enable neighbor
737	# suppression on the port and check that on both VLANs NS messages are
738	# suppressed.
739	run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress off"
740	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress off\""
741	log_test $? 0 "\"neigh_vlan_suppress\" is off"
742
743	run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
744	run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
745	log_test $? 0 "\"neigh_suppress\" is on"
746
747	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1"
748	log_test $? 0 "ndisc6 (VLAN $vid1)"
749	run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2"
750	log_test $? 0 "ndisc6 (VLAN $vid2)"
751
752	tc_check_packets $sw1 "dev vx0 egress" 101 2
753	log_test $? 0 "NS suppression (VLAN $vid1)"
754	tc_check_packets $sw1 "dev vx0 egress" 102 5
755	log_test $? 0 "NS suppression (VLAN $vid2)"
756}
757
758################################################################################
759# Usage
760
761usage()
762{
763	cat <<EOF
764usage: ${0##*/} OPTS
765
766        -t <test>   Test(s) to run (default: all)
767                    (options: $TESTS)
768        -p          Pause on fail
769        -P          Pause after each test before cleanup
770        -v          Verbose mode (show commands and output)
771EOF
772}
773
774################################################################################
775# Main
776
777trap cleanup EXIT
778
779while getopts ":t:pPvh" opt; do
780	case $opt in
781		t) TESTS=$OPTARG;;
782		p) PAUSE_ON_FAIL=yes;;
783		P) PAUSE=yes;;
784		v) VERBOSE=$(($VERBOSE + 1));;
785		h) usage; exit 0;;
786		*) usage; exit 1;;
787	esac
788done
789
790# Make sure we don't pause twice.
791[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
792
793if [ "$(id -u)" -ne 0 ];then
794	echo "SKIP: Need root privileges"
795	exit $ksft_skip;
796fi
797
798if [ ! -x "$(command -v ip)" ]; then
799	echo "SKIP: Could not run test without ip tool"
800	exit $ksft_skip
801fi
802
803if [ ! -x "$(command -v bridge)" ]; then
804	echo "SKIP: Could not run test without bridge tool"
805	exit $ksft_skip
806fi
807
808if [ ! -x "$(command -v tc)" ]; then
809	echo "SKIP: Could not run test without tc tool"
810	exit $ksft_skip
811fi
812
813if [ ! -x "$(command -v arping)" ]; then
814	echo "SKIP: Could not run test without arping tool"
815	exit $ksft_skip
816fi
817
818if [ ! -x "$(command -v ndisc6)" ]; then
819	echo "SKIP: Could not run test without ndisc6 tool"
820	exit $ksft_skip
821fi
822
823if [ ! -x "$(command -v jq)" ]; then
824	echo "SKIP: Could not run test without jq tool"
825	exit $ksft_skip
826fi
827
828bridge link help 2>&1 | grep -q "neigh_vlan_suppress"
829if [ $? -ne 0 ]; then
830   echo "SKIP: iproute2 bridge too old, missing per-VLAN neighbor suppression support"
831   exit $ksft_skip
832fi
833
834# Start clean.
835cleanup
836
837for t in $TESTS
838do
839	setup; $t; cleanup;
840done
841
842if [ "$TESTS" != "none" ]; then
843	printf "\nTests passed: %3d\n" ${nsuccess}
844	printf "Tests failed: %3d\n"   ${nfail}
845fi
846
847exit $ret
848