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