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