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