1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# +---------------------------+                +------------------------------+
5# |                    vrf-h1 |                |                       vrf-h2 |
6# |    + $h1                  |                |    + $h2                     |
7# |    | 10.1.1.101/24        |                |    | 10.1.2.101/24           |
8# |    | default via 10.1.1.1 |                |    | default via 10.1.2.1    |
9# +----|----------------------+                +----|-------------------------+
10#      |                                            |
11# +----|--------------------------------------------|-------------------------+
12# | SW |                                            |                         |
13# | +--|--------------------------------------------|-----------------------+ |
14# | |  + $swp1                         br1          + $swp2                 | |
15# | |     vid 10 pvid untagged                         vid 20 pvid untagged | |
16# | |                                                                       | |
17# | |  + vx10                                       + vx20                  | |
18# | |    local 10.0.0.1                               local 10.0.0.1        | |
19# | |    remote 10.0.0.2                              remote 10.0.0.2       | |
20# | |    id 1000                                      id 2000               | |
21# | |    dstport 4789                                 dstport 4789          | |
22# | |    vid 10 pvid untagged                         vid 20 pvid untagged  | |
23# | |                                                                       | |
24# | +-----------------------------------+-----------------------------------+ |
25# |                                     |                                     |
26# | +-----------------------------------|-----------------------------------+ |
27# | |                                   |                                   | |
28# | |  +--------------------------------+--------------------------------+  | |
29# | |  |                                                                 |  | |
30# | |  + vlan10                                                   vlan20 +  | |
31# | |  | 10.1.1.11/24                                       10.1.2.11/24 |  | |
32# | |  |                                                                 |  | |
33# | |  + vlan10-v (macvlan)                           vlan20-v (macvlan) +  | |
34# | |    10.1.1.1/24                                         10.1.2.1/24    | |
35# | |    00:00:5e:00:01:01                             00:00:5e:00:01:01    | |
36# | |                               vrf-green                               | |
37# | +-----------------------------------------------------------------------+ |
38# |                                                                           |
39# |    + $rp1                                       +lo                       |
40# |    | 192.0.2.1/24                                10.0.0.1/32              |
41# +----|----------------------------------------------------------------------+
42#      |
43# +----|--------------------------------------------------------+
44# |    |                            vrf-spine                   |
45# |    + $rp2                                                   |
46# |      192.0.2.2/24                                           |
47# |                                                             |   (maybe) HW
48# =============================================================================
49# |                                                             |  (likely) SW
50# |                                                             |
51# |    + v1 (veth)                                              |
52# |    | 192.0.3.2/24                                           |
53# +----|--------------------------------------------------------+
54#      |
55# +----|----------------------------------------------------------------------+
56# |    + v2 (veth)                                  +lo           NS1 (netns) |
57# |      192.0.3.1/24                                10.0.0.2/32              |
58# |                                                                           |
59# | +-----------------------------------------------------------------------+ |
60# | |                               vrf-green                               | |
61# | |  + vlan10-v (macvlan)                           vlan20-v (macvlan) +  | |
62# | |  | 10.1.1.1/24                                         10.1.2.1/24 |  | |
63# | |  | 00:00:5e:00:01:01                             00:00:5e:00:01:01 |  | |
64# | |  |                                                                 |  | |
65# | |  + vlan10                                                   vlan20 +  | |
66# | |  | 10.1.1.12/24                                       10.1.2.12/24 |  | |
67# | |  |                                                                 |  | |
68# | |  +--------------------------------+--------------------------------+  | |
69# | |                                   |                                   | |
70# | +-----------------------------------|-----------------------------------+ |
71# |                                     |                                     |
72# | +-----------------------------------+-----------------------------------+ |
73# | |                                                                       | |
74# | |  + vx10                                     + vx20                    | |
75# | |    local 10.0.0.2                             local 10.0.0.2          | |
76# | |    remote 10.0.0.1                            remote 10.0.0.1         | |
77# | |    id 1000                                    id 2000                 | |
78# | |    dstport 4789                               dstport 4789            | |
79# | |    vid 10 pvid untagged                       vid 20 pvid untagged    | |
80# | |                                                                       | |
81# | |  + w1 (veth)                                + w3 (veth)               | |
82# | |  | vid 10 pvid untagged          br1        | vid 20 pvid untagged    | |
83# | +--|------------------------------------------|-------------------------+ |
84# |    |                                          |                           |
85# |    |                                          |                           |
86# | +--|----------------------+                +--|-------------------------+ |
87# | |  |               vrf-h1 |                |  |                  vrf-h2 | |
88# | |  + w2 (veth)            |                |  + w4 (veth)               | |
89# | |    10.1.1.102/24        |                |    10.1.2.102/24           | |
90# | |    default via 10.1.1.1 |                |    default via 10.1.2.1    | |
91# | +-------------------------+                +----------------------------+ |
92# +---------------------------------------------------------------------------+
93
94ALL_TESTS="
95	ping_ipv4
96	arp_decap
97	arp_suppression
98"
99NUM_NETIFS=6
100source lib.sh
101
102require_command $ARPING
103
104hx_create()
105{
106	local vrf_name=$1; shift
107	local if_name=$1; shift
108	local ip_addr=$1; shift
109	local gw_ip=$1; shift
110
111	vrf_create $vrf_name
112	ip link set dev $if_name master $vrf_name
113	ip link set dev $vrf_name up
114	ip link set dev $if_name up
115
116	ip address add $ip_addr/24 dev $if_name
117	ip neigh replace $gw_ip lladdr 00:00:5e:00:01:01 nud permanent \
118		dev $if_name
119	ip route add default vrf $vrf_name nexthop via $gw_ip
120}
121export -f hx_create
122
123hx_destroy()
124{
125	local vrf_name=$1; shift
126	local if_name=$1; shift
127	local ip_addr=$1; shift
128	local gw_ip=$1; shift
129
130	ip route del default vrf $vrf_name nexthop via $gw_ip
131	ip neigh del $gw_ip dev $if_name
132	ip address del $ip_addr/24 dev $if_name
133
134	ip link set dev $if_name down
135	vrf_destroy $vrf_name
136}
137
138h1_create()
139{
140	hx_create "vrf-h1" $h1 10.1.1.101 10.1.1.1
141}
142
143h1_destroy()
144{
145	hx_destroy "vrf-h1" $h1 10.1.1.101 10.1.1.1
146}
147
148h2_create()
149{
150	hx_create "vrf-h2" $h2 10.1.2.101 10.1.2.1
151}
152
153h2_destroy()
154{
155	hx_destroy "vrf-h2" $h2 10.1.2.101 10.1.2.1
156}
157
158switch_create()
159{
160	ip link add name br1 type bridge vlan_filtering 1 vlan_default_pvid 0 \
161		mcast_snooping 0
162	# Make sure the bridge uses the MAC address of the local port and not
163	# that of the VxLAN's device.
164	ip link set dev br1 address $(mac_get $swp1)
165	ip link set dev br1 up
166
167	ip link set dev $rp1 up
168	ip address add dev $rp1 192.0.2.1/24
169	ip route add 10.0.0.2/32 nexthop via 192.0.2.2
170
171	ip link add name vx10 type vxlan id 1000		\
172		local 10.0.0.1 remote 10.0.0.2 dstport 4789	\
173		nolearning noudpcsum tos inherit ttl 100
174	ip link set dev vx10 up
175
176	ip link set dev vx10 master br1
177	bridge vlan add vid 10 dev vx10 pvid untagged
178
179	ip link add name vx20 type vxlan id 2000		\
180		local 10.0.0.1 remote 10.0.0.2 dstport 4789	\
181		nolearning noudpcsum tos inherit ttl 100
182	ip link set dev vx20 up
183
184	ip link set dev vx20 master br1
185	bridge vlan add vid 20 dev vx20 pvid untagged
186
187	ip link set dev $swp1 master br1
188	ip link set dev $swp1 up
189	bridge vlan add vid 10 dev $swp1 pvid untagged
190
191	ip link set dev $swp2 master br1
192	ip link set dev $swp2 up
193	bridge vlan add vid 20 dev $swp2 pvid untagged
194
195	ip address add 10.0.0.1/32 dev lo
196
197	# Create SVIs
198	vrf_create "vrf-green"
199	ip link set dev vrf-green up
200
201	ip link add link br1 name vlan10 up master vrf-green type vlan id 10
202	ip address add 10.1.1.11/24 dev vlan10
203	ip link add link vlan10 name vlan10-v up master vrf-green \
204		address 00:00:5e:00:01:01 type macvlan mode private
205	ip address add 10.1.1.1/24 dev vlan10-v
206
207	ip link add link br1 name vlan20 up master vrf-green type vlan id 20
208	ip address add 10.1.2.11/24 dev vlan20
209	ip link add link vlan20 name vlan20-v up master vrf-green \
210		address 00:00:5e:00:01:01 type macvlan mode private
211	ip address add 10.1.2.1/24 dev vlan20-v
212
213	bridge vlan add vid 10 dev br1 self
214	bridge vlan add vid 20 dev br1 self
215
216	bridge fdb add 00:00:5e:00:01:01 dev br1 self local vlan 10
217	bridge fdb add 00:00:5e:00:01:01 dev br1 self local vlan 20
218}
219
220switch_destroy()
221{
222	bridge fdb del 00:00:5e:00:01:01 dev br1 self local vlan 20
223	bridge fdb del 00:00:5e:00:01:01 dev br1 self local vlan 10
224
225	bridge vlan del vid 20 dev br1 self
226	bridge vlan del vid 10 dev br1 self
227
228	ip link del dev vlan20
229
230	ip link del dev vlan10
231
232	vrf_destroy "vrf-green"
233
234	ip address del 10.0.0.1/32 dev lo
235
236	bridge vlan del vid 20 dev $swp2
237	ip link set dev $swp2 down
238	ip link set dev $swp2 nomaster
239
240	bridge vlan del vid 10 dev $swp1
241	ip link set dev $swp1 down
242	ip link set dev $swp1 nomaster
243
244	bridge vlan del vid 20 dev vx20
245	ip link set dev vx20 nomaster
246
247	ip link set dev vx20 down
248	ip link del dev vx20
249
250	bridge vlan del vid 10 dev vx10
251	ip link set dev vx10 nomaster
252
253	ip link set dev vx10 down
254	ip link del dev vx10
255
256	ip route del 10.0.0.2/32 nexthop via 192.0.2.2
257	ip address del dev $rp1 192.0.2.1/24
258	ip link set dev $rp1 down
259
260	ip link set dev br1 down
261	ip link del dev br1
262}
263
264spine_create()
265{
266	vrf_create "vrf-spine"
267	ip link set dev $rp2 master vrf-spine
268	ip link set dev v1 master vrf-spine
269	ip link set dev vrf-spine up
270	ip link set dev $rp2 up
271	ip link set dev v1 up
272
273	ip address add 192.0.2.2/24 dev $rp2
274	ip address add 192.0.3.2/24 dev v1
275
276	ip route add 10.0.0.1/32 vrf vrf-spine nexthop via 192.0.2.1
277	ip route add 10.0.0.2/32 vrf vrf-spine nexthop via 192.0.3.1
278}
279
280spine_destroy()
281{
282	ip route del 10.0.0.2/32 vrf vrf-spine nexthop via 192.0.3.1
283	ip route del 10.0.0.1/32 vrf vrf-spine nexthop via 192.0.2.1
284
285	ip address del 192.0.3.2/24 dev v1
286	ip address del 192.0.2.2/24 dev $rp2
287
288	ip link set dev v1 down
289	ip link set dev $rp2 down
290	vrf_destroy "vrf-spine"
291}
292
293ns_h1_create()
294{
295	hx_create "vrf-h1" w2 10.1.1.102 10.1.1.1
296}
297export -f ns_h1_create
298
299ns_h2_create()
300{
301	hx_create "vrf-h2" w4 10.1.2.102 10.1.2.1
302}
303export -f ns_h2_create
304
305ns_switch_create()
306{
307	ip link add name br1 type bridge vlan_filtering 1 vlan_default_pvid 0 \
308		mcast_snooping 0
309	ip link set dev br1 up
310
311	ip link set dev v2 up
312	ip address add dev v2 192.0.3.1/24
313	ip route add 10.0.0.1/32 nexthop via 192.0.3.2
314
315	ip link add name vx10 type vxlan id 1000		\
316		local 10.0.0.2 remote 10.0.0.1 dstport 4789	\
317		nolearning noudpcsum tos inherit ttl 100
318	ip link set dev vx10 up
319
320	ip link set dev vx10 master br1
321	bridge vlan add vid 10 dev vx10 pvid untagged
322
323	ip link add name vx20 type vxlan id 2000		\
324		local 10.0.0.2 remote 10.0.0.1 dstport 4789	\
325		nolearning noudpcsum tos inherit ttl 100
326	ip link set dev vx20 up
327
328	ip link set dev vx20 master br1
329	bridge vlan add vid 20 dev vx20 pvid untagged
330
331	ip link set dev w1 master br1
332	ip link set dev w1 up
333	bridge vlan add vid 10 dev w1 pvid untagged
334
335	ip link set dev w3 master br1
336	ip link set dev w3 up
337	bridge vlan add vid 20 dev w3 pvid untagged
338
339	ip address add 10.0.0.2/32 dev lo
340
341	# Create SVIs
342	vrf_create "vrf-green"
343	ip link set dev vrf-green up
344
345	ip link add link br1 name vlan10 up master vrf-green type vlan id 10
346	ip address add 10.1.1.12/24 dev vlan10
347	ip link add link vlan10 name vlan10-v up master vrf-green \
348		address 00:00:5e:00:01:01 type macvlan mode private
349	ip address add 10.1.1.1/24 dev vlan10-v
350
351	ip link add link br1 name vlan20 up master vrf-green type vlan id 20
352	ip address add 10.1.2.12/24 dev vlan20
353	ip link add link vlan20 name vlan20-v up master vrf-green \
354		address 00:00:5e:00:01:01 type macvlan mode private
355	ip address add 10.1.2.1/24 dev vlan20-v
356
357	bridge vlan add vid 10 dev br1 self
358	bridge vlan add vid 20 dev br1 self
359
360	bridge fdb add 00:00:5e:00:01:01 dev br1 self local vlan 10
361	bridge fdb add 00:00:5e:00:01:01 dev br1 self local vlan 20
362}
363export -f ns_switch_create
364
365ns_init()
366{
367	ip link add name w1 type veth peer name w2
368	ip link add name w3 type veth peer name w4
369
370	ip link set dev lo up
371
372	ns_h1_create
373	ns_h2_create
374	ns_switch_create
375}
376export -f ns_init
377
378ns1_create()
379{
380	ip netns add ns1
381	ip link set dev v2 netns ns1
382	in_ns ns1 ns_init
383}
384
385ns1_destroy()
386{
387	ip netns exec ns1 ip link set dev v2 netns 1
388	ip netns del ns1
389}
390
391macs_populate()
392{
393	local mac1=$1; shift
394	local mac2=$1; shift
395	local ip1=$1; shift
396	local ip2=$1; shift
397	local dst=$1; shift
398
399	bridge fdb add $mac1 dev vx10 self master extern_learn static \
400		dst $dst vlan 10
401	bridge fdb add $mac2 dev vx20 self master extern_learn static \
402		dst $dst vlan 20
403
404	ip neigh add $ip1 lladdr $mac1 nud noarp dev vlan10 \
405		extern_learn
406	ip neigh add $ip2 lladdr $mac2 nud noarp dev vlan20 \
407		extern_learn
408}
409export -f macs_populate
410
411macs_initialize()
412{
413	local h1_ns_mac=$(in_ns ns1 mac_get w2)
414	local h2_ns_mac=$(in_ns ns1 mac_get w4)
415	local h1_mac=$(mac_get $h1)
416	local h2_mac=$(mac_get $h2)
417
418	macs_populate $h1_ns_mac $h2_ns_mac 10.1.1.102 10.1.2.102 10.0.0.2
419	in_ns ns1 macs_populate $h1_mac $h2_mac 10.1.1.101 10.1.2.101 10.0.0.1
420}
421
422setup_prepare()
423{
424	h1=${NETIFS[p1]}
425	swp1=${NETIFS[p2]}
426
427	swp2=${NETIFS[p3]}
428	h2=${NETIFS[p4]}
429
430	rp1=${NETIFS[p5]}
431	rp2=${NETIFS[p6]}
432
433	vrf_prepare
434	forwarding_enable
435
436	h1_create
437	h2_create
438	switch_create
439
440	ip link add name v1 type veth peer name v2
441	spine_create
442	ns1_create
443
444	macs_initialize
445}
446
447cleanup()
448{
449	pre_cleanup
450
451	ns1_destroy
452	spine_destroy
453	ip link del dev v1
454
455	switch_destroy
456	h2_destroy
457	h1_destroy
458
459	forwarding_restore
460	vrf_cleanup
461}
462
463ping_ipv4()
464{
465	ping_test $h1 10.1.2.101 ": local->local vid 10->vid 20"
466	ping_test $h1 10.1.1.102 ": local->remote vid 10->vid 10"
467	ping_test $h2 10.1.2.102 ": local->remote vid 20->vid 20"
468	ping_test $h1 10.1.2.102 ": local->remote vid 10->vid 20"
469	ping_test $h2 10.1.1.102 ": local->remote vid 20->vid 10"
470}
471
472arp_decap()
473{
474	# Repeat the ping tests, but without populating the neighbours. This
475	# makes sure we correctly decapsulate ARP packets
476	log_info "deleting neighbours from vlan interfaces"
477
478	ip neigh del 10.1.1.102 dev vlan10
479	ip neigh del 10.1.2.102 dev vlan20
480
481	ping_ipv4
482
483	ip neigh replace 10.1.1.102 lladdr $(in_ns ns1 mac_get w2) nud noarp \
484		dev vlan10 extern_learn
485	ip neigh replace 10.1.2.102 lladdr $(in_ns ns1 mac_get w4) nud noarp \
486		dev vlan20 extern_learn
487}
488
489arp_suppression_compare()
490{
491	local expect=$1; shift
492	local actual=$(in_ns ns1 tc_rule_stats_get vx10 1 ingress)
493
494	(( expect == actual ))
495	check_err $? "expected $expect arps got $actual"
496}
497
498arp_suppression()
499{
500	ip link set dev vx10 type bridge_slave neigh_suppress on
501
502	in_ns ns1 tc qdisc add dev vx10 clsact
503	in_ns ns1 tc filter add dev vx10 ingress proto arp pref 1 handle 101 \
504		flower dst_mac ff:ff:ff:ff:ff:ff arp_tip 10.1.1.102 arp_op \
505		request action pass
506
507	# The neighbour is configured on the SVI and ARP suppression is on, so
508	# the ARP request should be suppressed
509	RET=0
510
511	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
512	check_err $? "arping failed"
513
514	arp_suppression_compare 0
515
516	log_test "neigh_suppress: on / neigh exists: yes"
517
518	# Delete the neighbour from the the SVI. A single ARP request should be
519	# received by the remote VTEP
520	RET=0
521
522	ip neigh del 10.1.1.102 dev vlan10
523
524	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
525	check_err $? "arping failed"
526
527	arp_suppression_compare 1
528
529	log_test "neigh_suppress: on / neigh exists: no"
530
531	# Turn off ARP suppression and make sure ARP is not suppressed,
532	# regardless of neighbour existence on the SVI
533	RET=0
534
535	ip neigh del 10.1.1.102 dev vlan10 &> /dev/null
536	ip link set dev vx10 type bridge_slave neigh_suppress off
537
538	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
539	check_err $? "arping failed"
540
541	arp_suppression_compare 2
542
543	log_test "neigh_suppress: off / neigh exists: no"
544
545	RET=0
546
547	ip neigh add 10.1.1.102 lladdr $(in_ns ns1 mac_get w2) nud noarp \
548		dev vlan10 extern_learn
549
550	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
551	check_err $? "arping failed"
552
553	arp_suppression_compare 3
554
555	log_test "neigh_suppress: off / neigh exists: yes"
556
557	in_ns ns1 tc qdisc del dev vx10 clsact
558}
559
560trap cleanup EXIT
561
562setup_prepare
563setup_wait
564
565tests_run
566
567exit $EXIT_STATUS
568