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	sysctl_set net.ipv4.conf.all.rp_filter 0
220	sysctl_set net.ipv4.conf.vlan10-v.rp_filter 0
221	sysctl_set net.ipv4.conf.vlan20-v.rp_filter 0
222}
223
224switch_destroy()
225{
226	sysctl_restore net.ipv4.conf.all.rp_filter
227
228	bridge fdb del 00:00:5e:00:01:01 dev br1 self local vlan 20
229	bridge fdb del 00:00:5e:00:01:01 dev br1 self local vlan 10
230
231	bridge vlan del vid 20 dev br1 self
232	bridge vlan del vid 10 dev br1 self
233
234	ip link del dev vlan20
235
236	ip link del dev vlan10
237
238	vrf_destroy "vrf-green"
239
240	ip address del 10.0.0.1/32 dev lo
241
242	bridge vlan del vid 20 dev $swp2
243	ip link set dev $swp2 down
244	ip link set dev $swp2 nomaster
245
246	bridge vlan del vid 10 dev $swp1
247	ip link set dev $swp1 down
248	ip link set dev $swp1 nomaster
249
250	bridge vlan del vid 20 dev vx20
251	ip link set dev vx20 nomaster
252
253	ip link set dev vx20 down
254	ip link del dev vx20
255
256	bridge vlan del vid 10 dev vx10
257	ip link set dev vx10 nomaster
258
259	ip link set dev vx10 down
260	ip link del dev vx10
261
262	ip route del 10.0.0.2/32 nexthop via 192.0.2.2
263	ip address del dev $rp1 192.0.2.1/24
264	ip link set dev $rp1 down
265
266	ip link set dev br1 down
267	ip link del dev br1
268}
269
270spine_create()
271{
272	vrf_create "vrf-spine"
273	ip link set dev $rp2 master vrf-spine
274	ip link set dev v1 master vrf-spine
275	ip link set dev vrf-spine up
276	ip link set dev $rp2 up
277	ip link set dev v1 up
278
279	ip address add 192.0.2.2/24 dev $rp2
280	ip address add 192.0.3.2/24 dev v1
281
282	ip route add 10.0.0.1/32 vrf vrf-spine nexthop via 192.0.2.1
283	ip route add 10.0.0.2/32 vrf vrf-spine nexthop via 192.0.3.1
284}
285
286spine_destroy()
287{
288	ip route del 10.0.0.2/32 vrf vrf-spine nexthop via 192.0.3.1
289	ip route del 10.0.0.1/32 vrf vrf-spine nexthop via 192.0.2.1
290
291	ip address del 192.0.3.2/24 dev v1
292	ip address del 192.0.2.2/24 dev $rp2
293
294	ip link set dev v1 down
295	ip link set dev $rp2 down
296	vrf_destroy "vrf-spine"
297}
298
299ns_h1_create()
300{
301	hx_create "vrf-h1" w2 10.1.1.102 10.1.1.1
302}
303export -f ns_h1_create
304
305ns_h2_create()
306{
307	hx_create "vrf-h2" w4 10.1.2.102 10.1.2.1
308}
309export -f ns_h2_create
310
311ns_switch_create()
312{
313	ip link add name br1 type bridge vlan_filtering 1 vlan_default_pvid 0 \
314		mcast_snooping 0
315	ip link set dev br1 up
316
317	ip link set dev v2 up
318	ip address add dev v2 192.0.3.1/24
319	ip route add 10.0.0.1/32 nexthop via 192.0.3.2
320
321	ip link add name vx10 type vxlan id 1000		\
322		local 10.0.0.2 remote 10.0.0.1 dstport 4789	\
323		nolearning noudpcsum tos inherit ttl 100
324	ip link set dev vx10 up
325
326	ip link set dev vx10 master br1
327	bridge vlan add vid 10 dev vx10 pvid untagged
328
329	ip link add name vx20 type vxlan id 2000		\
330		local 10.0.0.2 remote 10.0.0.1 dstport 4789	\
331		nolearning noudpcsum tos inherit ttl 100
332	ip link set dev vx20 up
333
334	ip link set dev vx20 master br1
335	bridge vlan add vid 20 dev vx20 pvid untagged
336
337	ip link set dev w1 master br1
338	ip link set dev w1 up
339	bridge vlan add vid 10 dev w1 pvid untagged
340
341	ip link set dev w3 master br1
342	ip link set dev w3 up
343	bridge vlan add vid 20 dev w3 pvid untagged
344
345	ip address add 10.0.0.2/32 dev lo
346
347	# Create SVIs
348	vrf_create "vrf-green"
349	ip link set dev vrf-green up
350
351	ip link add link br1 name vlan10 up master vrf-green type vlan id 10
352	ip address add 10.1.1.12/24 dev vlan10
353	ip link add link vlan10 name vlan10-v up master vrf-green \
354		address 00:00:5e:00:01:01 type macvlan mode private
355	ip address add 10.1.1.1/24 dev vlan10-v
356
357	ip link add link br1 name vlan20 up master vrf-green type vlan id 20
358	ip address add 10.1.2.12/24 dev vlan20
359	ip link add link vlan20 name vlan20-v up master vrf-green \
360		address 00:00:5e:00:01:01 type macvlan mode private
361	ip address add 10.1.2.1/24 dev vlan20-v
362
363	bridge vlan add vid 10 dev br1 self
364	bridge vlan add vid 20 dev br1 self
365
366	bridge fdb add 00:00:5e:00:01:01 dev br1 self local vlan 10
367	bridge fdb add 00:00:5e:00:01:01 dev br1 self local vlan 20
368
369	sysctl_set net.ipv4.conf.all.rp_filter 0
370	sysctl_set net.ipv4.conf.vlan10-v.rp_filter 0
371	sysctl_set net.ipv4.conf.vlan20-v.rp_filter 0
372}
373export -f ns_switch_create
374
375ns_init()
376{
377	ip link add name w1 type veth peer name w2
378	ip link add name w3 type veth peer name w4
379
380	ip link set dev lo up
381
382	ns_h1_create
383	ns_h2_create
384	ns_switch_create
385}
386export -f ns_init
387
388ns1_create()
389{
390	ip netns add ns1
391	ip link set dev v2 netns ns1
392	in_ns ns1 ns_init
393}
394
395ns1_destroy()
396{
397	ip netns exec ns1 ip link set dev v2 netns 1
398	ip netns del ns1
399}
400
401macs_populate()
402{
403	local mac1=$1; shift
404	local mac2=$1; shift
405	local ip1=$1; shift
406	local ip2=$1; shift
407	local dst=$1; shift
408
409	bridge fdb add $mac1 dev vx10 self master extern_learn static \
410		dst $dst vlan 10
411	bridge fdb add $mac2 dev vx20 self master extern_learn static \
412		dst $dst vlan 20
413
414	ip neigh add $ip1 lladdr $mac1 nud noarp dev vlan10 \
415		extern_learn
416	ip neigh add $ip2 lladdr $mac2 nud noarp dev vlan20 \
417		extern_learn
418}
419export -f macs_populate
420
421macs_initialize()
422{
423	local h1_ns_mac=$(in_ns ns1 mac_get w2)
424	local h2_ns_mac=$(in_ns ns1 mac_get w4)
425	local h1_mac=$(mac_get $h1)
426	local h2_mac=$(mac_get $h2)
427
428	macs_populate $h1_ns_mac $h2_ns_mac 10.1.1.102 10.1.2.102 10.0.0.2
429	in_ns ns1 macs_populate $h1_mac $h2_mac 10.1.1.101 10.1.2.101 10.0.0.1
430}
431
432setup_prepare()
433{
434	h1=${NETIFS[p1]}
435	swp1=${NETIFS[p2]}
436
437	swp2=${NETIFS[p3]}
438	h2=${NETIFS[p4]}
439
440	rp1=${NETIFS[p5]}
441	rp2=${NETIFS[p6]}
442
443	vrf_prepare
444	forwarding_enable
445
446	h1_create
447	h2_create
448	switch_create
449
450	ip link add name v1 type veth peer name v2
451	spine_create
452	ns1_create
453
454	macs_initialize
455}
456
457cleanup()
458{
459	pre_cleanup
460
461	ns1_destroy
462	spine_destroy
463	ip link del dev v1
464
465	switch_destroy
466	h2_destroy
467	h1_destroy
468
469	forwarding_restore
470	vrf_cleanup
471}
472
473ping_ipv4()
474{
475	ping_test $h1 10.1.2.101 ": local->local vid 10->vid 20"
476	ping_test $h1 10.1.1.102 ": local->remote vid 10->vid 10"
477	ping_test $h2 10.1.2.102 ": local->remote vid 20->vid 20"
478	ping_test $h1 10.1.2.102 ": local->remote vid 10->vid 20"
479	ping_test $h2 10.1.1.102 ": local->remote vid 20->vid 10"
480}
481
482arp_decap()
483{
484	# Repeat the ping tests, but without populating the neighbours. This
485	# makes sure we correctly decapsulate ARP packets
486	log_info "deleting neighbours from vlan interfaces"
487
488	ip neigh del 10.1.1.102 dev vlan10
489	ip neigh del 10.1.2.102 dev vlan20
490
491	ping_ipv4
492
493	ip neigh replace 10.1.1.102 lladdr $(in_ns ns1 mac_get w2) nud noarp \
494		dev vlan10 extern_learn
495	ip neigh replace 10.1.2.102 lladdr $(in_ns ns1 mac_get w4) nud noarp \
496		dev vlan20 extern_learn
497}
498
499arp_suppression_compare()
500{
501	local expect=$1; shift
502	local actual=$(in_ns ns1 tc_rule_stats_get vx10 1 ingress)
503
504	(( expect == actual ))
505	check_err $? "expected $expect arps got $actual"
506}
507
508arp_suppression()
509{
510	ip link set dev vx10 type bridge_slave neigh_suppress on
511
512	in_ns ns1 tc qdisc add dev vx10 clsact
513	in_ns ns1 tc filter add dev vx10 ingress proto arp pref 1 handle 101 \
514		flower dst_mac ff:ff:ff:ff:ff:ff arp_tip 10.1.1.102 arp_op \
515		request action pass
516
517	# The neighbour is configured on the SVI and ARP suppression is on, so
518	# the ARP request should be suppressed
519	RET=0
520
521	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
522	check_err $? "arping failed"
523
524	arp_suppression_compare 0
525
526	log_test "neigh_suppress: on / neigh exists: yes"
527
528	# Delete the neighbour from the SVI. A single ARP request should be
529	# received by the remote VTEP
530	RET=0
531
532	ip neigh del 10.1.1.102 dev vlan10
533
534	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
535	check_err $? "arping failed"
536
537	arp_suppression_compare 1
538
539	log_test "neigh_suppress: on / neigh exists: no"
540
541	# Turn off ARP suppression and make sure ARP is not suppressed,
542	# regardless of neighbour existence on the SVI
543	RET=0
544
545	ip neigh del 10.1.1.102 dev vlan10 &> /dev/null
546	ip link set dev vx10 type bridge_slave neigh_suppress off
547
548	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
549	check_err $? "arping failed"
550
551	arp_suppression_compare 2
552
553	log_test "neigh_suppress: off / neigh exists: no"
554
555	RET=0
556
557	ip neigh add 10.1.1.102 lladdr $(in_ns ns1 mac_get w2) nud noarp \
558		dev vlan10 extern_learn
559
560	$ARPING -I $h1 -fqb -c 1 -w 1 10.1.1.102
561	check_err $? "arping failed"
562
563	arp_suppression_compare 3
564
565	log_test "neigh_suppress: off / neigh exists: yes"
566
567	in_ns ns1 tc qdisc del dev vx10 clsact
568}
569
570trap cleanup EXIT
571
572setup_prepare
573setup_wait
574
575tests_run
576
577exit $EXIT_STATUS
578