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