xref: /linux/tools/testing/selftests/net/fdb_flush.sh (revision 17271848c9a79cdbee49537cb9a73e7de0906962)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# This test is for checking functionality of flushing FDB entries.
5# Check that flush works as expected with all the supported arguments and verify
6# some combinations of arguments.
7
8source lib.sh
9ret=0
10
11FLUSH_BY_STATE_TESTS="
12	vxlan_test_flush_by_permanent
13	vxlan_test_flush_by_nopermanent
14	vxlan_test_flush_by_static
15	vxlan_test_flush_by_nostatic
16	vxlan_test_flush_by_dynamic
17	vxlan_test_flush_by_nodynamic
18"
19
20FLUSH_BY_FLAG_TESTS="
21	vxlan_test_flush_by_extern_learn
22	vxlan_test_flush_by_noextern_learn
23	vxlan_test_flush_by_router
24	vxlan_test_flush_by_norouter
25"
26
27TESTS="
28	vxlan_test_flush_by_dev
29	vxlan_test_flush_by_vni
30	vxlan_test_flush_by_src_vni
31	vxlan_test_flush_by_port
32	vxlan_test_flush_by_dst_ip
33	vxlan_test_flush_by_nhid
34	$FLUSH_BY_STATE_TESTS
35	$FLUSH_BY_FLAG_TESTS
36	vxlan_test_flush_by_several_args
37	vxlan_test_flush_by_remote_attributes
38	bridge_test_flush_by_dev
39	bridge_test_flush_by_vlan
40	bridge_vxlan_test_flush
41"
42
43: ${VERBOSE:=0}
44: ${PAUSE_ON_FAIL:=no}
45: ${PAUSE:=no}
46: ${VXPORT:=4789}
47
48run_cmd()
49{
50	local cmd="$1"
51	local out
52	local rc
53	local stderr="2>/dev/null"
54
55	if [ "$VERBOSE" = "1" ]; then
56		printf "COMMAND: $cmd\n"
57		stderr=
58	fi
59
60	out=$(eval $cmd $stderr)
61	rc=$?
62	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
63		echo "    $out"
64	fi
65
66	return $rc
67}
68
69log_test()
70{
71	log_test_expected "$1" "$2" "$3"
72}
73
74MAC_POOL_1="
75	de:ad:be:ef:13:10
76	de:ad:be:ef:13:11
77	de:ad:be:ef:13:12
78	de:ad:be:ef:13:13
79	de:ad:be:ef:13:14
80"
81mac_pool_1_len=$(echo "$MAC_POOL_1" | grep -c .)
82
83MAC_POOL_2="
84	ca:fe:be:ef:13:10
85	ca:fe:be:ef:13:11
86	ca:fe:be:ef:13:12
87	ca:fe:be:ef:13:13
88	ca:fe:be:ef:13:14
89"
90mac_pool_2_len=$(echo "$MAC_POOL_2" | grep -c .)
91
92fdb_add_mac_pool_1()
93{
94	local dev=$1; shift
95	local args="$@"
96
97	for mac in $MAC_POOL_1
98	do
99		$BRIDGE fdb add $mac dev $dev $args
100	done
101}
102
103fdb_add_mac_pool_2()
104{
105	local dev=$1; shift
106	local args="$@"
107
108	for mac in $MAC_POOL_2
109	do
110		$BRIDGE fdb add $mac dev $dev $args
111	done
112}
113
114fdb_check_n_entries_by_dev_filter()
115{
116	local dev=$1; shift
117	local exp_entries=$1; shift
118	local filter="$@"
119
120	local entries=$($BRIDGE fdb show dev $dev | grep "$filter" | wc -l)
121
122	[[ $entries -eq $exp_entries ]]
123	rc=$?
124
125	log_test $rc 0 "$dev: Expected $exp_entries FDB entries, got $entries"
126	return $rc
127}
128
129vxlan_test_flush_by_dev()
130{
131	local vni=3000
132	local dst_ip=192.0.2.1
133
134	fdb_add_mac_pool_1 vx10 vni $vni dst $dst_ip
135	fdb_add_mac_pool_2 vx20 vni $vni dst $dst_ip
136
137	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len
138	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
139
140	run_cmd "$BRIDGE fdb flush dev vx10"
141	log_test $? 0 "Flush FDB by dev vx10"
142
143	fdb_check_n_entries_by_dev_filter vx10 0
144	log_test $? 0 "Flush FDB by dev vx10 - test vx10 entries"
145
146	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
147	log_test $? 0 "Flush FDB by dev vx10 - test vx20 entries"
148}
149
150vxlan_test_flush_by_vni()
151{
152	local vni_1=3000
153	local vni_2=4000
154	local dst_ip=192.0.2.1
155
156	fdb_add_mac_pool_1 vx10 vni $vni_1 dst $dst_ip
157	fdb_add_mac_pool_2 vx10 vni $vni_2 dst $dst_ip
158
159	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
160	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len vni $vni_2
161
162	run_cmd "$BRIDGE fdb flush dev vx10 vni $vni_2"
163	log_test $? 0 "Flush FDB by dev vx10 and vni $vni_2"
164
165	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
166	log_test $? 0 "Test entries with vni $vni_1"
167
168	fdb_check_n_entries_by_dev_filter vx10 0 vni $vni_2
169	log_test $? 0 "Test entries with vni $vni_2"
170}
171
172vxlan_test_flush_by_src_vni()
173{
174	# Set some entries with {vni=x,src_vni=y} and some with the opposite -
175	# {vni=y,src_vni=x}, to verify that when we flush by src_vni=x, entries
176	# with vni=x are not flused.
177	local vni_1=3000
178	local vni_2=4000
179	local src_vni_1=4000
180	local src_vni_2=3000
181	local dst_ip=192.0.2.1
182
183	# Reconfigure vx10 with 'external' to get 'src_vni' details in
184	# 'bridge fdb' output
185	$IP link del dev vx10
186	$IP link add name vx10 type vxlan dstport "$VXPORT" external
187
188	fdb_add_mac_pool_1 vx10 vni $vni_1 src_vni $src_vni_1 dst $dst_ip
189	fdb_add_mac_pool_2 vx10 vni $vni_2 src_vni $src_vni_2 dst $dst_ip
190
191	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
192		src_vni $src_vni_1
193	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len \
194		src_vni $src_vni_2
195
196	run_cmd "$BRIDGE fdb flush dev vx10 src_vni $src_vni_2"
197	log_test $? 0 "Flush FDB by dev vx10 and src_vni $src_vni_2"
198
199	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
200		src_vni $src_vni_1
201	log_test $? 0 "Test entries with src_vni $src_vni_1"
202
203	fdb_check_n_entries_by_dev_filter vx10 0 src_vni $src_vni_2
204	log_test $? 0 "Test entries with src_vni $src_vni_2"
205}
206
207vxlan_test_flush_by_port()
208{
209	local port_1=1234
210	local port_2=4321
211	local dst_ip=192.0.2.1
212
213	fdb_add_mac_pool_1 vx10 port $port_1 dst $dst_ip
214	fdb_add_mac_pool_2 vx10 port $port_2 dst $dst_ip
215
216	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
217	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len port $port_2
218
219	run_cmd "$BRIDGE fdb flush dev vx10 port $port_2"
220	log_test $? 0 "Flush FDB by dev vx10 and port $port_2"
221
222	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
223	log_test $? 0 "Test entries with port $port_1"
224
225	fdb_check_n_entries_by_dev_filter vx10 0 port $port_2
226	log_test $? 0 "Test entries with port $port_2"
227}
228
229vxlan_test_flush_by_dst_ip()
230{
231	local dst_ip_1=192.0.2.1
232	local dst_ip_2=192.0.2.2
233
234	fdb_add_mac_pool_1 vx10 dst $dst_ip_1
235	fdb_add_mac_pool_2 vx10 dst $dst_ip_2
236
237	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
238	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
239
240	run_cmd "$BRIDGE fdb flush dev vx10 dst $dst_ip_2"
241	log_test $? 0 "Flush FDB by dev vx10 and dst $dst_ip_2"
242
243	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
244	log_test $? 0 "Test entries with dst $dst_ip_1"
245
246	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
247	log_test $? 0 "Test entries with dst $dst_ip_2"
248}
249
250nexthops_add()
251{
252	local nhid_1=$1; shift
253	local nhid_2=$1; shift
254
255	$IP nexthop add id 10 via 192.0.2.1 fdb
256	$IP nexthop add id $nhid_1 group 10 fdb
257
258	$IP nexthop add id 20 via 192.0.2.2 fdb
259	$IP nexthop add id $nhid_2 group 20 fdb
260}
261
262vxlan_test_flush_by_nhid()
263{
264	local nhid_1=100
265	local nhid_2=200
266
267	nexthops_add $nhid_1 $nhid_2
268
269	fdb_add_mac_pool_1 vx10 nhid $nhid_1
270	fdb_add_mac_pool_2 vx10 nhid $nhid_2
271
272	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
273	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len nhid $nhid_2
274
275	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_2"
276	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_2"
277
278	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
279	log_test $? 0 "Test entries with nhid $nhid_1"
280
281	fdb_check_n_entries_by_dev_filter vx10 0 nhid $nhid_2
282	log_test $? 0 "Test entries with nhid $nhid_2"
283
284	# Flush also entries with $nhid_1, and then verify that flushing by
285	# 'nhid' does not return an error when there are no entries with
286	# nexthops.
287	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
288	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_1"
289
290	fdb_check_n_entries_by_dev_filter vx10 0 nhid
291	log_test $? 0 "Test entries with 'nhid' keyword"
292
293	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
294	log_test $? 0 "Flush FDB by nhid when there are no entries with nexthop"
295}
296
297vxlan_test_flush_by_state()
298{
299	local flush_by_state=$1; shift
300	local state_1=$1; shift
301	local exp_state_1=$1; shift
302	local state_2=$1; shift
303	local exp_state_2=$1; shift
304
305	local dst_ip_1=192.0.2.1
306	local dst_ip_2=192.0.2.2
307
308	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $state_1
309	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $state_2
310
311	# Check the entries by dst_ip as not all states appear in 'bridge fdb'
312	# output.
313	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
314	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
315
316	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_state"
317	log_test $? 0 "Flush FDB by dev vx10 and state $flush_by_state"
318
319	fdb_check_n_entries_by_dev_filter vx10 $exp_state_1 dst $dst_ip_1
320	log_test $? 0 "Test entries with state $state_1"
321
322	fdb_check_n_entries_by_dev_filter vx10 $exp_state_2 dst $dst_ip_2
323	log_test $? 0 "Test entries with state $state_2"
324}
325
326vxlan_test_flush_by_permanent()
327{
328	# Entries that are added without state get 'permanent' state by
329	# default, add some entries with flag 'extern_learn' instead of state,
330	# so they will be added with 'permanent' and should be flushed also.
331	local flush_by_state="permanent"
332	local state_1="permanent"
333	local exp_state_1=0
334	local state_2="extern_learn"
335	local exp_state_2=0
336
337	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
338		$state_2 $exp_state_2
339}
340
341vxlan_test_flush_by_nopermanent()
342{
343	local flush_by_state="nopermanent"
344	local state_1="permanent"
345	local exp_state_1=$mac_pool_1_len
346	local state_2="static"
347	local exp_state_2=0
348
349	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
350		$state_2 $exp_state_2
351}
352
353vxlan_test_flush_by_static()
354{
355	local flush_by_state="static"
356	local state_1="static"
357	local exp_state_1=0
358	local state_2="dynamic"
359	local exp_state_2=$mac_pool_2_len
360
361	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
362		$state_2 $exp_state_2
363}
364
365vxlan_test_flush_by_nostatic()
366{
367	local flush_by_state="nostatic"
368	local state_1="permanent"
369	local exp_state_1=$mac_pool_1_len
370	local state_2="dynamic"
371	local exp_state_2=0
372
373	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
374		$state_2 $exp_state_2
375}
376
377vxlan_test_flush_by_dynamic()
378{
379	local flush_by_state="dynamic"
380	local state_1="dynamic"
381	local exp_state_1=0
382	local state_2="static"
383	local exp_state_2=$mac_pool_2_len
384
385	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
386		$state_2 $exp_state_2
387}
388
389vxlan_test_flush_by_nodynamic()
390{
391	local flush_by_state="nodynamic"
392	local state_1="permanent"
393	local exp_state_1=0
394	local state_2="dynamic"
395	local exp_state_2=$mac_pool_2_len
396
397	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
398		$state_2 $exp_state_2
399}
400
401vxlan_test_flush_by_flag()
402{
403	local flush_by_flag=$1; shift
404	local flag_1=$1; shift
405	local exp_flag_1=$1; shift
406	local flag_2=$1; shift
407	local exp_flag_2=$1; shift
408
409	local dst_ip_1=192.0.2.1
410	local dst_ip_2=192.0.2.2
411
412	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $flag_1
413	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $flag_2
414
415	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $flag_1
416	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $flag_2
417
418	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_flag"
419	log_test $? 0 "Flush FDB by dev vx10 and flag $flush_by_flag"
420
421	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_1 dst $dst_ip_1
422	log_test $? 0 "Test entries with flag $flag_1"
423
424	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_2 dst $dst_ip_2
425	log_test $? 0 "Test entries with flag $flag_2"
426}
427
428vxlan_test_flush_by_extern_learn()
429{
430	local flush_by_flag="extern_learn"
431	local flag_1="extern_learn"
432	local exp_flag_1=0
433	local flag_2="router"
434	local exp_flag_2=$mac_pool_2_len
435
436	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
437		$flag_2 $exp_flag_2
438}
439
440vxlan_test_flush_by_noextern_learn()
441{
442	local flush_by_flag="noextern_learn"
443	local flag_1="extern_learn"
444	local exp_flag_1=$mac_pool_1_len
445	local flag_2="router"
446	local exp_flag_2=0
447
448	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
449		$flag_2 $exp_flag_2
450}
451
452vxlan_test_flush_by_router()
453{
454	local flush_by_flag="router"
455	local flag_1="router"
456	local exp_flag_1=0
457	local flag_2="extern_learn"
458	local exp_flag_2=$mac_pool_2_len
459
460	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
461		$flag_2 $exp_flag_2
462}
463
464vxlan_test_flush_by_norouter()
465{
466
467	local flush_by_flag="norouter"
468	local flag_1="router"
469	local exp_flag_1=$mac_pool_1_len
470	local flag_2="extern_learn"
471	local exp_flag_2=0
472
473	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
474		$flag_2 $exp_flag_2
475}
476
477vxlan_test_flush_by_several_args()
478{
479	local dst_ip_1=192.0.2.1
480	local dst_ip_2=192.0.2.2
481	local state_1=permanent
482	local state_2=static
483	local vni=3000
484	local port=1234
485	local nhid=100
486	local flag=router
487	local flush_args
488
489	################### Flush by 2 args - nhid and flag ####################
490	$IP nexthop add id 10 via 192.0.2.1 fdb
491	$IP nexthop add id $nhid group 10 fdb
492
493	fdb_add_mac_pool_1 vx10 nhid $nhid $flag $state_1
494	fdb_add_mac_pool_2 vx10 nhid $nhid $flag $state_2
495
496	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $state_1
497	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $state_2
498
499	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid $flag"
500	log_test $? 0 "Flush FDB by dev vx10 nhid $nhid $flag"
501
502	# All entries should be flushed as 'state' is not an argument for flush
503	# filtering.
504	fdb_check_n_entries_by_dev_filter vx10 0 $state_1
505	log_test $? 0 "Test entries with state $state_1"
506
507	fdb_check_n_entries_by_dev_filter vx10 0 $state_2
508	log_test $? 0 "Test entries with state $state_2"
509
510	################ Flush by 3 args - VNI, port and dst_ip ################
511	fdb_add_mac_pool_1 vx10 vni $vni port $port dst $dst_ip_1
512	fdb_add_mac_pool_2 vx10 vni $vni port $port dst $dst_ip_2
513
514	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
515	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
516
517	flush_args="vni $vni port $port dst $dst_ip_2"
518	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
519	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
520
521	# Only entries with $dst_ip_2 should be flushed, even the rest arguments
522	# match the filter, the flush should be AND of all the arguments.
523	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
524	log_test $? 0 "Test entries with dst $dst_ip_1"
525
526	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
527	log_test $? 0 "Test entries with dst $dst_ip_2"
528}
529
530multicast_fdb_entries_add()
531{
532	mac=00:00:00:00:00:00
533	vnis=(2000 3000)
534
535	for vni in "${vnis[@]}"; do
536		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
537			src_vni 5000
538		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
539			port 1111
540		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.2 vni $vni \
541			port 2222
542	done
543}
544
545vxlan_test_flush_by_remote_attributes()
546{
547	local flush_args
548
549	# Reconfigure vx10 with 'external' to get 'src_vni' details in
550	# 'bridge fdb' output
551	$IP link del dev vx10
552	$IP link add name vx10 type vxlan dstport "$VXPORT" external
553
554	# For multicast FDB entries, the VXLAN driver stores a linked list of
555	# remotes for a given key. Verify that only the expected remotes are
556	# flushed.
557	multicast_fdb_entries_add
558
559	## Flush by 3 remote's attributes - destination IP, port and VNI ##
560	flush_args="dst 192.0.2.1 port 1111 vni 2000"
561	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
562
563	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
564	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
565	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
566
567	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
568
569	exp_n_entries=$((t0_n_entries - 1))
570	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
571	[[ $t1_n_entries -eq $exp_n_entries ]]
572	log_test $? 0 "Check how many entries were flushed"
573
574	## Flush by 2 remote's attributes - destination IP and port ##
575	flush_args="dst 192.0.2.2 port 2222"
576
577	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
578
579	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
580	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
581	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
582
583	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
584
585	exp_n_entries=$((t0_n_entries - 2))
586	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
587	[[ $t1_n_entries -eq $exp_n_entries ]]
588	log_test $? 0 "Check how many entries were flushed"
589
590	## Flush by source VNI, which is not remote's attribute and VNI ##
591	flush_args="vni 3000 src_vni 5000"
592
593	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
594
595	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
596	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
597	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
598
599	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
600
601	exp_n_entries=$((t0_n_entries -1))
602	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
603	[[ $t1_n_entries -eq $exp_n_entries ]]
604	log_test $? 0 "Check how many entries were flushed"
605
606	# Flush by 1 remote's attribute - destination IP ##
607	flush_args="dst 192.0.2.1"
608
609	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
610
611	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
612	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
613	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
614
615	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
616
617	exp_n_entries=$((t0_n_entries -2))
618	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
619	[[ $t1_n_entries -eq $exp_n_entries ]]
620	log_test $? 0 "Check how many entries were flushed"
621}
622
623bridge_test_flush_by_dev()
624{
625	local dst_ip=192.0.2.1
626	local br0_n_ent_t0=$($BRIDGE fdb show dev br0 | wc -l)
627	local br1_n_ent_t0=$($BRIDGE fdb show dev br1 | wc -l)
628
629	fdb_add_mac_pool_1 br0 dst $dst_ip
630	fdb_add_mac_pool_2 br1 dst $dst_ip
631
632	# Each 'fdb add' command adds one extra entry in the bridge with the
633	# default vlan.
634	local exp_br0_n_ent=$(($br0_n_ent_t0 + 2 * $mac_pool_1_len))
635	local exp_br1_n_ent=$(($br1_n_ent_t0 + 2 * $mac_pool_2_len))
636
637	fdb_check_n_entries_by_dev_filter br0 $exp_br0_n_ent
638	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
639
640	run_cmd "$BRIDGE fdb flush dev br0"
641	log_test $? 0 "Flush FDB by dev br0"
642
643	# The default entry should not be flushed
644	fdb_check_n_entries_by_dev_filter br0 1
645	log_test $? 0 "Flush FDB by dev br0 - test br0 entries"
646
647	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
648	log_test $? 0 "Flush FDB by dev br0 - test br1 entries"
649}
650
651bridge_test_flush_by_vlan()
652{
653	local vlan_1=10
654	local vlan_2=20
655	local vlan_1_ent_t0
656	local vlan_2_ent_t0
657
658	$BRIDGE vlan add vid $vlan_1 dev br0 self
659	$BRIDGE vlan add vid $vlan_2 dev br0 self
660
661	vlan_1_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_1" | wc -l)
662	vlan_2_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_2" | wc -l)
663
664	fdb_add_mac_pool_1 br0 vlan $vlan_1
665	fdb_add_mac_pool_2 br0 vlan $vlan_2
666
667	local exp_vlan_1_ent=$(($vlan_1_ent_t0 + $mac_pool_1_len))
668	local exp_vlan_2_ent=$(($vlan_2_ent_t0 + $mac_pool_2_len))
669
670	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_1_ent vlan $vlan_1
671	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
672
673	run_cmd "$BRIDGE fdb flush dev br0 vlan $vlan_1"
674	log_test $? 0 "Flush FDB by dev br0 and vlan $vlan_1"
675
676	fdb_check_n_entries_by_dev_filter br0 0 vlan $vlan_1
677	log_test $? 0 "Test entries with vlan $vlan_1"
678
679	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
680	log_test $? 0 "Test entries with vlan $vlan_2"
681}
682
683bridge_vxlan_test_flush()
684{
685	local vlan_1=10
686	local dst_ip=192.0.2.1
687
688	$IP link set dev vx10 master br0
689	$BRIDGE vlan add vid $vlan_1 dev br0 self
690	$BRIDGE vlan add vid $vlan_1 dev vx10
691
692	fdb_add_mac_pool_1 vx10 vni 3000 dst $dst_ip self master
693
694	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vlan $vlan_1
695	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni 3000
696
697	# Such command should fail in VXLAN driver as vlan is not supported,
698	# but the command should flush the entries in the bridge
699	run_cmd "$BRIDGE fdb flush dev vx10 vlan $vlan_1 master self"
700	log_test $? 255 \
701		"Flush FDB by dev vx10, vlan $vlan_1, master and self"
702
703	fdb_check_n_entries_by_dev_filter vx10 0 vlan $vlan_1
704	log_test $? 0 "Test entries with vlan $vlan_1"
705
706	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip
707	log_test $? 0 "Test entries with dst $dst_ip"
708}
709
710setup()
711{
712	setup_ns NS
713	IP="ip -netns ${NS}"
714	BRIDGE="bridge -netns ${NS}"
715
716	$IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
717	$IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
718
719	$IP link add br0 type bridge vlan_filtering 1
720	$IP link add br1 type bridge vlan_filtering 1
721}
722
723cleanup()
724{
725	$IP link del dev br1
726	$IP link del dev br0
727
728	$IP link del dev vx20
729	$IP link del dev vx10
730
731	cleanup_ns ${NS}
732}
733
734################################################################################
735# main
736
737while getopts :t:pPhvw: o
738do
739	case $o in
740		t) TESTS=$OPTARG;;
741		p) PAUSE_ON_FAIL=yes;;
742		P) PAUSE=yes;;
743		v) VERBOSE=$(($VERBOSE + 1));;
744		w) PING_TIMEOUT=$OPTARG;;
745		h) usage; exit 0;;
746		*) usage; exit 1;;
747	esac
748done
749
750# make sure we don't pause twice
751[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
752
753if [ "$(id -u)" -ne 0 ];then
754	echo "SKIP: Need root privileges"
755	exit $ksft_skip;
756fi
757
758if [ ! -x "$(command -v ip)" ]; then
759	echo "SKIP: Could not run test without ip tool"
760	exit $ksft_skip
761fi
762
763# Check a flag that is added to flush command as part of VXLAN flush support
764bridge fdb help 2>&1 | grep -q "\[no\]router"
765if [ $? -ne 0 ]; then
766	echo "SKIP: iproute2 too old, missing flush command for VXLAN"
767	exit $ksft_skip
768fi
769
770ip link add dev vx10 type vxlan id 1000 2> /dev/null
771out=$(bridge fdb flush dev vx10 2>&1 | grep -q "Operation not supported")
772if [ $? -eq 0 ]; then
773	echo "SKIP: kernel lacks vxlan flush support"
774	exit $ksft_skip
775fi
776ip link del dev vx10
777
778for t in $TESTS
779do
780	setup; $t; cleanup;
781done
782
783exit $ret
784