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