1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# +-----------------------+                          +------------------------+
5# | H1 (vrf)              |                          | H2 (vrf)               |
6# | + $h1.10              |                          | + $h2.10               |
7# | | 192.0.2.1/28        |                          | | 192.0.2.2/28         |
8# | | 2001:db8:1::1/64    |                          | | 2001:db8:1::2/64     |
9# | |                     |                          | |                      |
10# | |  + $h1.20           |                          | |  + $h2.20            |
11# | \  | 198.51.100.1/24  |                          | \  | 198.51.100.2/24   |
12# |  \ | 2001:db8:2::1/64 |                          |  \ | 2001:db8:2::2/64  |
13# |   \|                  |                          |   \|                   |
14# |    + $h1              |                          |    + $h2               |
15# +----|------------------+                          +----|-------------------+
16#      |                                                  |
17# +----|--------------------------------------------------|-------------------+
18# | SW |                                                  |                   |
19# | +--|--------------------------------------------------|-----------------+ |
20# | |  + $swp1                   BR1 (802.1q)             + $swp2           | |
21# | |     vid 10                                             vid 10         | |
22# | |     vid 20                                             vid 20         | |
23# | |                                                                       | |
24# | |  + vx10 (vxlan)                        + vx20 (vxlan)                 | |
25# | |    local:                                local:                       | |
26# | |    2001:db8:3::1                         2001:db8:3::1                | |
27# | |    remote:                               remote:                      | |
28# | |    2001:db8:4::1 2001:db8:5::1           2001:db8:4::1 2001:db8:5::1  | |
29# | |    id 1000 dstport $VXPORT               id 2000 dstport $VXPORT      | |
30# | |    vid 10 pvid untagged                  vid 20 pvid untagged         | |
31# | +-----------------------------------------------------------------------+ |
32# |                                                                           |
33# |  2001:db8:4::0/64 via 2001:db8:3::2                                       |
34# |  2001:db8:5::0/64 via 2001:db8:3::2                                       |
35# |                                                                           |
36# |    + $rp1                                                                 |
37# |    | 2001:db8:3::1/64                                                     |
38# +----|----------------------------------------------------------------------+
39#      |
40# +----|----------------------------------------------------------+
41# |    |                                             VRP2 (vrf)   |
42# |    + $rp2                                                     |
43# |      2001:db8:3::2/64                                         |
44# |                                                               |  (maybe) HW
45# =============================================================================
46# |                                                               |  (likely) SW
47# |    + v1 (veth)                             + v3 (veth)        |
48# |    | 2001:db8:4::2/64                      | 2001:db8:5::2/64 |
49# +----|---------------------------------------|------------------+
50#      |                                       |
51# +----|--------------------------------+ +----|-------------------------------+
52# |    + v2 (veth)        NS1 (netns)   | |    + v4 (veth)        NS2 (netns)  |
53# |      2001:db8:4::1/64               | |      2001:db8:5::1/64              |
54# |                                     | |                                    |
55# | 2001:db8:3::0/64 via 2001:db8:4::2  | | 2001:db8:3::0/64 via 2001:db8:5::2 |
56# | 2001:db8:5::1/128 via 2001:db8:4::2 | | 2001:db8:4::1/128 via              |
57# |                                     | |         2001:db8:5::2              |
58# |                                     | |                                    |
59# | +-------------------------------+   | | +-------------------------------+  |
60# | |                  BR2 (802.1q) |   | | |                  BR2 (802.1q) |  |
61# | |  + vx10 (vxlan)               |   | | |  + vx10 (vxlan)               |  |
62# | |    local 2001:db8:4::1        |   | | |    local 2001:db8:5::1        |  |
63# | |    remote 2001:db8:3::1       |   | | |    remote 2001:db8:3::1       |  |
64# | |    remote 2001:db8:5::1       |   | | |    remote 2001:db8:4::1       |  |
65# | |    id 1000 dstport $VXPORT    |   | | |    id 1000 dstport $VXPORT    |  |
66# | |    vid 10 pvid untagged       |   | | |    vid 10 pvid untagged       |  |
67# | |                               |   | | |                               |  |
68# | |  + vx20 (vxlan)               |   | | |  + vx20 (vxlan)               |  |
69# | |    local 2001:db8:4::1        |   | | |    local 2001:db8:5::1        |  |
70# | |    remote 2001:db8:3::1       |   | | |    remote 2001:db8:3::1       |  |
71# | |    remote 2001:db8:5::1       |   | | |    remote 2001:db8:4::1       |  |
72# | |    id 2000 dstport $VXPORT    |   | | |    id 2000 dstport $VXPORT    |  |
73# | |    vid 20 pvid untagged       |   | | |    vid 20 pvid untagged       |  |
74# | |                               |   | | |                               |  |
75# | |  + w1 (veth)                  |   | | |  + w1 (veth)                  |  |
76# | |  | vid 10                     |   | | |  | vid 10                     |  |
77# | |  | vid 20                     |   | | |  | vid 20                     |  |
78# | +--|----------------------------+   | | +--|----------------------------+  |
79# |    |                                | |    |                               |
80# | +--|----------------------------+   | | +--|----------------------------+  |
81# | |  + w2 (veth)        VW2 (vrf) |   | | |  + w2 (veth)        VW2 (vrf) |  |
82# | |  |\                           |   | | |  |\                           |  |
83# | |  | + w2.10                    |   | | |  | + w2.10                    |  |
84# | |  |   192.0.2.3/28             |   | | |  |   192.0.2.4/28             |  |
85# | |  |   2001:db8:1::3/64         |   | | |  |   2001:db8:1::4/64         |  |
86# | |  |                            |   | | |  |                            |  |
87# | |  + w2.20                      |   | | |  + w2.20                      |  |
88# | |    198.51.100.3/24            |   | | |    198.51.100.4/24            |  |
89# | |    2001:db8:2::3/64           |   | | |    2001:db8:2::4/64           |  |
90# | +-------------------------------+   | | +-------------------------------+  |
91# +-------------------------------------+ +------------------------------------+
92
93: ${VXPORT:=4789}
94export VXPORT
95
96: ${ALL_TESTS:="
97	ping_ipv4
98	ping_ipv6
99	test_flood
100	test_unicast
101	reapply_config
102	ping_ipv4
103	ping_ipv6
104	test_flood
105	test_unicast
106	test_pvid
107	ping_ipv4
108	ping_ipv6
109	test_flood
110	test_pvid
111"}
112
113NUM_NETIFS=6
114source lib.sh
115source tc_common.sh
116
117h1_create()
118{
119	simple_if_init $h1
120	tc qdisc add dev $h1 clsact
121	vlan_create $h1 10 v$h1 192.0.2.1/28 2001:db8:1::1/64
122	vlan_create $h1 20 v$h1 198.51.100.1/24 2001:db8:2::1/64
123}
124
125h1_destroy()
126{
127	vlan_destroy $h1 20
128	vlan_destroy $h1 10
129	tc qdisc del dev $h1 clsact
130	simple_if_fini $h1
131}
132
133h2_create()
134{
135	simple_if_init $h2
136	tc qdisc add dev $h2 clsact
137	vlan_create $h2 10 v$h2 192.0.2.2/28 2001:db8:1::2/64
138	vlan_create $h2 20 v$h2 198.51.100.2/24 2001:db8:2::2/64
139}
140
141h2_destroy()
142{
143	vlan_destroy $h2 20
144	vlan_destroy $h2 10
145	tc qdisc del dev $h2 clsact
146	simple_if_fini $h2
147}
148
149rp1_set_addr()
150{
151	ip address add dev $rp1 2001:db8:3::1/64
152
153	ip route add 2001:db8:4::0/64 nexthop via 2001:db8:3::2
154	ip route add 2001:db8:5::0/64 nexthop via 2001:db8:3::2
155}
156
157rp1_unset_addr()
158{
159	ip route del 2001:db8:5::0/64 nexthop via 2001:db8:3::2
160	ip route del 2001:db8:4::0/64 nexthop via 2001:db8:3::2
161
162	ip address del dev $rp1 2001:db8:3::1/64
163}
164
165switch_create()
166{
167	ip link add name br1 type bridge vlan_filtering 1 vlan_default_pvid 0 \
168		mcast_snooping 0
169	# Make sure the bridge uses the MAC address of the local port and not
170	# that of the VxLAN's device.
171	ip link set dev br1 address $(mac_get $swp1)
172	ip link set dev br1 up
173
174	ip link set dev $rp1 up
175	rp1_set_addr
176	tc qdisc add dev $rp1 clsact
177
178	ip link add name vx10 type vxlan id 1000 local 2001:db8:3::1 \
179		dstport "$VXPORT" nolearning udp6zerocsumrx udp6zerocsumtx \
180		tos inherit ttl 100
181	ip link set dev vx10 up
182
183	ip link set dev vx10 master br1
184	bridge vlan add vid 10 dev vx10 pvid untagged
185
186	ip link add name vx20 type vxlan id 2000 local 2001:db8:3::1 \
187		dstport "$VXPORT" nolearning udp6zerocsumrx udp6zerocsumtx \
188		tos inherit ttl 100
189	ip link set dev vx20 up
190
191	ip link set dev vx20 master br1
192	bridge vlan add vid 20 dev vx20 pvid untagged
193
194	ip link set dev $swp1 master br1
195	ip link set dev $swp1 up
196	tc qdisc add dev $swp1 clsact
197	bridge vlan add vid 10 dev $swp1
198	bridge vlan add vid 20 dev $swp1
199
200	ip link set dev $swp2 master br1
201	ip link set dev $swp2 up
202	bridge vlan add vid 10 dev $swp2
203	bridge vlan add vid 20 dev $swp2
204
205	bridge fdb append dev vx10 00:00:00:00:00:00 dst 2001:db8:4::1 self
206	bridge fdb append dev vx10 00:00:00:00:00:00 dst 2001:db8:5::1 self
207
208	bridge fdb append dev vx20 00:00:00:00:00:00 dst 2001:db8:4::1 self
209	bridge fdb append dev vx20 00:00:00:00:00:00 dst 2001:db8:5::1 self
210}
211
212switch_destroy()
213{
214	bridge fdb del dev vx20 00:00:00:00:00:00 dst 2001:db8:5::1 self
215	bridge fdb del dev vx20 00:00:00:00:00:00 dst 2001:db8:4::1 self
216
217	bridge fdb del dev vx10 00:00:00:00:00:00 dst 2001:db8:5::1 self
218	bridge fdb del dev vx10 00:00:00:00:00:00 dst 2001:db8:4::1 self
219
220	bridge vlan del vid 20 dev $swp2
221	bridge vlan del vid 10 dev $swp2
222	ip link set dev $swp2 down
223	ip link set dev $swp2 nomaster
224
225	bridge vlan del vid 20 dev $swp1
226	bridge vlan del vid 10 dev $swp1
227	tc qdisc del dev $swp1 clsact
228	ip link set dev $swp1 down
229	ip link set dev $swp1 nomaster
230
231	bridge vlan del vid 20 dev vx20
232	ip link set dev vx20 nomaster
233
234	ip link set dev vx20 down
235	ip link del dev vx20
236
237	bridge vlan del vid 10 dev vx10
238	ip link set dev vx10 nomaster
239
240	ip link set dev vx10 down
241	ip link del dev vx10
242
243	tc qdisc del dev $rp1 clsact
244	rp1_unset_addr
245	ip link set dev $rp1 down
246
247	ip link set dev br1 down
248	ip link del dev br1
249}
250
251vrp2_create()
252{
253	simple_if_init $rp2 2001:db8:3::2/64
254	__simple_if_init v1 v$rp2 2001:db8:4::2/64
255	__simple_if_init v3 v$rp2 2001:db8:5::2/64
256	tc qdisc add dev v1 clsact
257}
258
259vrp2_destroy()
260{
261	tc qdisc del dev v1 clsact
262	__simple_if_fini v3 2001:db8:5::2/64
263	__simple_if_fini v1 2001:db8:4::2/64
264	simple_if_fini $rp2 2001:db8:3::2/64
265}
266
267ns_init_common()
268{
269	local in_if=$1; shift
270	local in_addr=$1; shift
271	local other_in_addr=$1; shift
272	local nh_addr=$1; shift
273	local host_addr1_ipv4=$1; shift
274	local host_addr1_ipv6=$1; shift
275	local host_addr2_ipv4=$1; shift
276	local host_addr2_ipv6=$1; shift
277
278	ip link set dev $in_if up
279	ip address add dev $in_if $in_addr/64
280	tc qdisc add dev $in_if clsact
281
282	ip link add name br2 type bridge vlan_filtering 1 vlan_default_pvid 0
283	ip link set dev br2 up
284
285	ip link add name w1 type veth peer name w2
286
287	ip link set dev w1 master br2
288	ip link set dev w1 up
289
290	bridge vlan add vid 10 dev w1
291	bridge vlan add vid 20 dev w1
292
293	ip link add name vx10 type vxlan id 1000 local $in_addr \
294		dstport "$VXPORT" udp6zerocsumrx
295	ip link set dev vx10 up
296	bridge fdb append dev vx10 00:00:00:00:00:00 dst 2001:db8:3::1 self
297	bridge fdb append dev vx10 00:00:00:00:00:00 dst $other_in_addr self
298
299	ip link set dev vx10 master br2
300	tc qdisc add dev vx10 clsact
301
302	bridge vlan add vid 10 dev vx10 pvid untagged
303
304	ip link add name vx20 type vxlan id 2000 local $in_addr \
305		dstport "$VXPORT" udp6zerocsumrx
306	ip link set dev vx20 up
307	bridge fdb append dev vx20 00:00:00:00:00:00 dst 2001:db8:3::1 self
308	bridge fdb append dev vx20 00:00:00:00:00:00 dst $other_in_addr self
309
310	ip link set dev vx20 master br2
311	tc qdisc add dev vx20 clsact
312
313	bridge vlan add vid 20 dev vx20 pvid untagged
314
315	simple_if_init w2
316        vlan_create w2 10 vw2 $host_addr1_ipv4/28 $host_addr1_ipv6/64
317        vlan_create w2 20 vw2 $host_addr2_ipv4/24 $host_addr2_ipv6/64
318
319	ip route add 2001:db8:3::0/64 nexthop via $nh_addr
320	ip route add $other_in_addr/128 nexthop via $nh_addr
321}
322export -f ns_init_common
323
324ns1_create()
325{
326	ip netns add ns1
327	ip link set dev v2 netns ns1
328	in_ns ns1 \
329	      ns_init_common v2 2001:db8:4::1 2001:db8:5::1 2001:db8:4::2 \
330	      192.0.2.3 2001:db8:1::3 198.51.100.3 2001:db8:2::3
331}
332
333ns1_destroy()
334{
335	ip netns exec ns1 ip link set dev v2 netns 1
336	ip netns del ns1
337}
338
339ns2_create()
340{
341	ip netns add ns2
342	ip link set dev v4 netns ns2
343	in_ns ns2 \
344	      ns_init_common v4 2001:db8:5::1 2001:db8:4::1 2001:db8:5::2 \
345	      192.0.2.4 2001:db8:1::4 198.51.100.4 2001:db8:2::4
346}
347
348ns2_destroy()
349{
350	ip netns exec ns2 ip link set dev v4 netns 1
351	ip netns del ns2
352}
353
354setup_prepare()
355{
356	h1=${NETIFS[p1]}
357	swp1=${NETIFS[p2]}
358
359	swp2=${NETIFS[p3]}
360	h2=${NETIFS[p4]}
361
362	rp1=${NETIFS[p5]}
363	rp2=${NETIFS[p6]}
364
365	vrf_prepare
366	forwarding_enable
367
368	h1_create
369	h2_create
370	switch_create
371
372	ip link add name v1 type veth peer name v2
373	ip link add name v3 type veth peer name v4
374	vrp2_create
375	ns1_create
376	ns2_create
377
378	r1_mac=$(in_ns ns1 mac_get w2)
379	r2_mac=$(in_ns ns2 mac_get w2)
380	h2_mac=$(mac_get $h2)
381}
382
383cleanup()
384{
385	pre_cleanup
386
387	ns2_destroy
388	ns1_destroy
389	vrp2_destroy
390	ip link del dev v3
391	ip link del dev v1
392
393	switch_destroy
394	h2_destroy
395	h1_destroy
396
397	forwarding_restore
398	vrf_cleanup
399}
400
401# For the first round of tests, vx10 and vx20 were the first devices to get
402# attached to the bridge, and at that point the local IP is already
403# configured. Try the other scenario of attaching these devices to a bridge
404# that already has local ports members, and only then assign the local IP.
405reapply_config()
406{
407	log_info "Reapplying configuration"
408
409	bridge fdb del dev vx20 00:00:00:00:00:00 dst 2001:db8:5::1 self
410	bridge fdb del dev vx20 00:00:00:00:00:00 dst 2001:db8:4::1 self
411
412	bridge fdb del dev vx10 00:00:00:00:00:00 dst 2001:db8:5::1 self
413	bridge fdb del dev vx10 00:00:00:00:00:00 dst 2001:db8:4::1 self
414
415	ip link set dev vx20 nomaster
416	ip link set dev vx10 nomaster
417
418	rp1_unset_addr
419	sleep 5
420
421	ip link set dev vx10 master br1
422	bridge vlan add vid 10 dev vx10 pvid untagged
423
424	ip link set dev vx20 master br1
425	bridge vlan add vid 20 dev vx20 pvid untagged
426
427	bridge fdb append dev vx10 00:00:00:00:00:00 dst 2001:db8:4::1 self
428	bridge fdb append dev vx10 00:00:00:00:00:00 dst 2001:db8:5::1 self
429
430	bridge fdb append dev vx20 00:00:00:00:00:00 dst 2001:db8:4::1 self
431	bridge fdb append dev vx20 00:00:00:00:00:00 dst 2001:db8:5::1 self
432
433	rp1_set_addr
434	sleep 5
435}
436
437__ping_ipv4()
438{
439	local vxlan_local_ip=$1; shift
440	local vxlan_remote_ip=$1; shift
441	local src_ip=$1; shift
442	local dst_ip=$1; shift
443	local dev=$1; shift
444	local info=$1; shift
445
446	RET=0
447
448	tc filter add dev $rp1 egress protocol ipv6 pref 1 handle 101 \
449		flower ip_proto udp src_ip $vxlan_local_ip \
450		dst_ip $vxlan_remote_ip dst_port $VXPORT $TC_FLAG action pass
451	# Match ICMP-reply packets after decapsulation, so source IP is
452	# destination IP of the ping and destination IP is source IP of the
453	# ping.
454	tc filter add dev $swp1 egress protocol 802.1q pref 1 handle 101 \
455		flower vlan_ethtype ipv4 src_ip $dst_ip dst_ip $src_ip \
456		$TC_FLAG action pass
457
458	# Send 100 packets and verify that at least 100 packets hit the rule,
459	# to overcome ARP noise.
460	PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip
461	check_err $? "Ping failed"
462
463	tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100
464	check_err $? "Encapsulated packets did not go through router"
465
466	tc_check_at_least_x_packets "dev $swp1 egress" 101 10 100
467	check_err $? "Decapsulated packets did not go through switch"
468
469	log_test "ping: $info"
470
471	tc filter del dev $swp1 egress
472	tc filter del dev $rp1 egress
473}
474
475ping_ipv4()
476{
477	RET=0
478
479	local local_sw_ip=2001:db8:3::1
480	local remote_ns1_ip=2001:db8:4::1
481	local remote_ns2_ip=2001:db8:5::1
482	local h1_10_ip=192.0.2.1
483	local h1_20_ip=198.51.100.1
484	local w2_10_ns1_ip=192.0.2.3
485	local w2_10_ns2_ip=192.0.2.4
486	local w2_20_ns1_ip=198.51.100.3
487	local w2_20_ns2_ip=198.51.100.4
488
489	ping_test $h1.10 192.0.2.2 ": local->local vid 10"
490	ping_test $h1.20 198.51.100.2 ": local->local vid 20"
491
492	__ping_ipv4 $local_sw_ip $remote_ns1_ip $h1_10_ip $w2_10_ns1_ip $h1.10 \
493		"local->remote 1 vid 10"
494	__ping_ipv4 $local_sw_ip $remote_ns2_ip $h1_10_ip $w2_10_ns2_ip $h1.10 \
495		"local->remote 2 vid 10"
496	__ping_ipv4 $local_sw_ip $remote_ns1_ip $h1_20_ip $w2_20_ns1_ip $h1.20 \
497		"local->remote 1 vid 20"
498	__ping_ipv4 $local_sw_ip $remote_ns2_ip $h1_20_ip $w2_20_ns2_ip $h1.20 \
499		"local->remote 2 vid 20"
500}
501
502__ping_ipv6()
503{
504	local vxlan_local_ip=$1; shift
505	local vxlan_remote_ip=$1; shift
506	local src_ip=$1; shift
507	local dst_ip=$1; shift
508	local dev=$1; shift
509	local info=$1; shift
510
511	RET=0
512
513	tc filter add dev $rp1 egress protocol ipv6 pref 1 handle 101 \
514		flower ip_proto udp src_ip $vxlan_local_ip \
515		dst_ip $vxlan_remote_ip dst_port $VXPORT $TC_FLAG action pass
516	# Match ICMP-reply packets after decapsulation, so source IP is
517	# destination IP of the ping and destination IP is source IP of the
518	# ping.
519	tc filter add dev $swp1 egress protocol 802.1q pref 1 handle 101 \
520		flower vlan_ethtype ipv6 src_ip $dst_ip dst_ip $src_ip \
521		$TC_FLAG action pass
522
523	# Send 100 packets and verify that at least 100 packets hit the rule,
524	# to overcome neighbor discovery noise.
525	PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip
526	check_err $? "Ping failed"
527
528	tc_check_at_least_x_packets "dev $rp1 egress" 101 100
529	check_err $? "Encapsulated packets did not go through router"
530
531	tc_check_at_least_x_packets "dev $swp1 egress" 101 100
532	check_err $? "Decapsulated packets did not go through switch"
533
534	log_test "ping6: $info"
535
536	tc filter del dev $swp1 egress
537	tc filter del dev $rp1 egress
538}
539
540ping_ipv6()
541{
542	RET=0
543
544	local local_sw_ip=2001:db8:3::1
545	local remote_ns1_ip=2001:db8:4::1
546	local remote_ns2_ip=2001:db8:5::1
547	local h1_10_ip=2001:db8:1::1
548	local h1_20_ip=2001:db8:2::1
549	local w2_10_ns1_ip=2001:db8:1::3
550	local w2_10_ns2_ip=2001:db8:1::4
551	local w2_20_ns1_ip=2001:db8:2::3
552	local w2_20_ns2_ip=2001:db8:2::4
553
554	ping6_test $h1.10 2001:db8:1::2 ": local->local vid 10"
555	ping6_test $h1.20 2001:db8:2::2 ": local->local vid 20"
556
557	__ping_ipv6 $local_sw_ip $remote_ns1_ip $h1_10_ip $w2_10_ns1_ip $h1.10 \
558		"local->remote 1 vid 10"
559	__ping_ipv6 $local_sw_ip $remote_ns2_ip $h1_10_ip $w2_10_ns2_ip $h1.10 \
560		"local->remote 2 vid 10"
561	__ping_ipv6 $local_sw_ip $remote_ns1_ip $h1_20_ip $w2_20_ns1_ip $h1.20 \
562		"local->remote 1 vid 20"
563	__ping_ipv6 $local_sw_ip $remote_ns2_ip $h1_20_ip $w2_20_ns2_ip $h1.20 \
564		"local->remote 2 vid 20"
565}
566
567maybe_in_ns()
568{
569	echo ${1:+in_ns} $1
570}
571
572__flood_counter_add_del()
573{
574	local add_del=$1; shift
575	local dst_ip=$1; shift
576	local dev=$1; shift
577	local ns=$1; shift
578
579	# Putting the ICMP capture both to HW and to SW will end up
580	# double-counting the packets that are trapped to slow path, such as for
581	# the unicast test. Adding either skip_hw or skip_sw fixes this problem,
582	# but with skip_hw, the flooded packets are not counted at all, because
583	# those are dropped due to MAC address mismatch; and skip_sw is a no-go
584	# for veth-based topologies.
585	#
586	# So try to install with skip_sw and fall back to skip_sw if that fails.
587
588	$(maybe_in_ns $ns) tc filter $add_del dev "$dev" ingress \
589	   proto ipv6 pref 100 flower dst_ip $dst_ip ip_proto \
590	   icmpv6 skip_sw action pass 2>/dev/null || \
591	$(maybe_in_ns $ns) tc filter $add_del dev "$dev" ingress \
592	   proto ipv6 pref 100 flower dst_ip $dst_ip ip_proto \
593	   icmpv6 skip_hw action pass
594}
595
596flood_counter_install()
597{
598	__flood_counter_add_del add "$@"
599}
600
601flood_counter_uninstall()
602{
603	__flood_counter_add_del del "$@"
604}
605
606flood_fetch_stat()
607{
608	local dev=$1; shift
609	local ns=$1; shift
610
611	$(maybe_in_ns $ns) tc_rule_stats_get $dev 100 ingress
612}
613
614flood_fetch_stats()
615{
616	local counters=("${@}")
617	local counter
618
619	for counter in "${counters[@]}"; do
620		flood_fetch_stat $counter
621	done
622}
623
624vxlan_flood_test()
625{
626	local mac=$1; shift
627	local dst=$1; shift
628	local vid=$1; shift
629	local -a expects=("${@}")
630
631	local -a counters=($h2 "vx10 ns1" "vx20 ns1" "vx10 ns2" "vx20 ns2")
632	local counter
633	local key
634
635	# Packets reach the local host tagged whereas they reach the VxLAN
636	# devices untagged. In order to be able to use the same filter for
637	# all counters, make sure the packets also reach the local host
638	# untagged
639	bridge vlan add vid $vid dev $swp2 untagged
640	for counter in "${counters[@]}"; do
641		flood_counter_install $dst $counter
642	done
643
644	local -a t0s=($(flood_fetch_stats "${counters[@]}"))
645	$MZ -6 $h1 -Q $vid -c 10 -d 100msec -p 64 -b $mac -B $dst -t icmp6 type=128 -q
646	sleep 1
647	local -a t1s=($(flood_fetch_stats "${counters[@]}"))
648
649	for key in ${!t0s[@]}; do
650		local delta=$((t1s[$key] - t0s[$key]))
651		local expect=${expects[$key]}
652
653		((expect == delta))
654		check_err $? "${counters[$key]}: Expected to capture $expect packets, got $delta."
655	done
656
657	for counter in "${counters[@]}"; do
658		flood_counter_uninstall $dst $counter
659	done
660	bridge vlan add vid $vid dev $swp2
661}
662
663__test_flood()
664{
665	local mac=$1; shift
666	local dst=$1; shift
667	local vid=$1; shift
668	local what=$1; shift
669	local -a expects=("${@}")
670
671	RET=0
672
673	vxlan_flood_test $mac $dst $vid "${expects[@]}"
674
675	log_test "VXLAN: $what"
676}
677
678test_flood()
679{
680	__test_flood de:ad:be:ef:13:37 2001:db8:1::100 10 "flood vlan 10" \
681		10 10 0 10 0
682	__test_flood ca:fe:be:ef:13:37 2001:db8:2::100 20 "flood vlan 20" \
683		10 0 10 0 10
684}
685
686vxlan_fdb_add_del()
687{
688	local add_del=$1; shift
689	local vid=$1; shift
690	local mac=$1; shift
691	local dev=$1; shift
692	local dst=$1; shift
693
694	bridge fdb $add_del dev $dev $mac self static permanent \
695		${dst:+dst} $dst 2>/dev/null
696	bridge fdb $add_del dev $dev $mac master static vlan $vid 2>/dev/null
697}
698
699__test_unicast()
700{
701	local mac=$1; shift
702	local dst=$1; shift
703	local hit_idx=$1; shift
704	local vid=$1; shift
705	local what=$1; shift
706
707	RET=0
708
709	local -a expects=(0 0 0 0 0)
710	expects[$hit_idx]=10
711
712	vxlan_flood_test $mac $dst $vid "${expects[@]}"
713
714	log_test "VXLAN: $what"
715}
716
717test_unicast()
718{
719	local -a targets=("$h2_mac $h2"
720			  "$r1_mac vx10 2001:db8:4::1"
721			  "$r2_mac vx10 2001:db8:5::1")
722	local target
723
724	log_info "unicast vlan 10"
725
726	for target in "${targets[@]}"; do
727		vxlan_fdb_add_del add 10 $target
728	done
729
730	__test_unicast $h2_mac 2001:db8:1::2 0 10 "local MAC unicast"
731	__test_unicast $r1_mac 2001:db8:1::3 1 10 "remote MAC 1 unicast"
732	__test_unicast $r2_mac 2001:db8:1::4 3 10 "remote MAC 2 unicast"
733
734	for target in "${targets[@]}"; do
735		vxlan_fdb_add_del del 10 $target
736	done
737
738	log_info "unicast vlan 20"
739
740	targets=("$h2_mac $h2" "$r1_mac vx20 2001:db8:4::1" \
741		 "$r2_mac vx20 2001:db8:5::1")
742
743	for target in "${targets[@]}"; do
744		vxlan_fdb_add_del add 20 $target
745	done
746
747	__test_unicast $h2_mac 2001:db8:2::2 0 20 "local MAC unicast"
748	__test_unicast $r1_mac 2001:db8:2::3 2 20 "remote MAC 1 unicast"
749	__test_unicast $r2_mac 2001:db8:2::4 4 20 "remote MAC 2 unicast"
750
751	for target in "${targets[@]}"; do
752		vxlan_fdb_add_del del 20 $target
753	done
754}
755
756test_pvid()
757{
758	local -a expects=(0 0 0 0 0)
759	local mac=de:ad:be:ef:13:37
760	local dst=2001:db8:1::100
761	local vid=10
762
763	# Check that flooding works
764	RET=0
765
766	expects[0]=10; expects[1]=10; expects[3]=10
767	vxlan_flood_test $mac $dst $vid "${expects[@]}"
768
769	log_test "VXLAN: flood before pvid off"
770
771	# Toggle PVID off and test that flood to remote hosts does not work
772	RET=0
773
774	bridge vlan add vid 10 dev vx10
775
776	expects[0]=10; expects[1]=0; expects[3]=0
777	vxlan_flood_test $mac $dst $vid "${expects[@]}"
778
779	log_test "VXLAN: flood after pvid off"
780
781	# Toggle PVID on and test that flood to remote hosts does work
782	RET=0
783
784	bridge vlan add vid 10 dev vx10 pvid untagged
785
786	expects[0]=10; expects[1]=10; expects[3]=10
787	vxlan_flood_test $mac $dst $vid "${expects[@]}"
788
789	log_test "VXLAN: flood after pvid on"
790
791	# Add a new VLAN and test that it does not affect flooding
792	RET=0
793
794	bridge vlan add vid 30 dev vx10
795
796	expects[0]=10; expects[1]=10; expects[3]=10
797	vxlan_flood_test $mac $dst $vid "${expects[@]}"
798
799	bridge vlan del vid 30 dev vx10
800
801	log_test "VXLAN: flood after vlan add"
802
803	# Remove currently mapped VLAN and test that flood to remote hosts does
804	# not work
805	RET=0
806
807	bridge vlan del vid 10 dev vx10
808
809	expects[0]=10; expects[1]=0; expects[3]=0
810	vxlan_flood_test $mac $dst $vid "${expects[@]}"
811
812	log_test "VXLAN: flood after vlan delete"
813
814	# Re-add the VLAN and test that flood to remote hosts does work
815	RET=0
816
817	bridge vlan add vid 10 dev vx10 pvid untagged
818
819	expects[0]=10; expects[1]=10; expects[3]=10
820	vxlan_flood_test $mac $dst $vid "${expects[@]}"
821
822	log_test "VXLAN: flood after vlan re-add"
823}
824
825test_all()
826{
827	log_info "Running tests with UDP port $VXPORT"
828	tests_run
829}
830
831trap cleanup EXIT
832
833setup_prepare
834setup_wait
835test_all
836
837exit $EXIT_STATUS
838