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