1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test devlink-trap L2 drops functionality over mlxsw. Each registered L2 drop
5# packet trap is tested to make sure it is triggered under the right
6# conditions.
7
8lib_dir=$(dirname $0)/../../../net/forwarding
9
10ALL_TESTS="
11	source_mac_is_multicast_test
12	vlan_tag_mismatch_test
13	ingress_vlan_filter_test
14	ingress_stp_filter_test
15	port_list_is_empty_test
16	port_loopback_filter_test
17	locked_port_test
18"
19NUM_NETIFS=4
20source $lib_dir/tc_common.sh
21source $lib_dir/lib.sh
22source $lib_dir/devlink_lib.sh
23
24h1_create()
25{
26	simple_if_init $h1
27}
28
29h1_destroy()
30{
31	simple_if_fini $h1
32}
33
34h2_create()
35{
36	simple_if_init $h2
37}
38
39h2_destroy()
40{
41	simple_if_fini $h2
42}
43
44switch_create()
45{
46	ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0
47
48	ip link set dev $swp1 master br0
49	ip link set dev $swp2 master br0
50
51	ip link set dev br0 up
52	ip link set dev $swp1 up
53	ip link set dev $swp2 up
54
55	tc qdisc add dev $swp2 clsact
56}
57
58switch_destroy()
59{
60	tc qdisc del dev $swp2 clsact
61
62	ip link set dev $swp2 down
63	ip link set dev $swp1 down
64
65	ip link del dev br0
66}
67
68setup_prepare()
69{
70	h1=${NETIFS[p1]}
71	swp1=${NETIFS[p2]}
72
73	swp2=${NETIFS[p3]}
74	h2=${NETIFS[p4]}
75
76	vrf_prepare
77
78	h1_create
79	h2_create
80
81	switch_create
82}
83
84cleanup()
85{
86	pre_cleanup
87
88	switch_destroy
89
90	h2_destroy
91	h1_destroy
92
93	vrf_cleanup
94}
95
96source_mac_is_multicast_test()
97{
98	local trap_name="source_mac_is_multicast"
99	local smac=01:02:03:04:05:06
100	local mz_pid
101
102	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
103		flower src_mac $smac action drop
104
105	$MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -d 1msec -q &
106	mz_pid=$!
107
108	RET=0
109
110	devlink_trap_drop_test $trap_name $swp2 101
111
112	log_test "Source MAC is multicast"
113
114	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
115}
116
117__vlan_tag_mismatch_test()
118{
119	local trap_name="vlan_tag_mismatch"
120	local dmac=de:ad:be:ef:13:37
121	local opt=$1; shift
122	local mz_pid
123
124	# Remove PVID flag. This should prevent untagged and prio-tagged
125	# packets from entering the bridge.
126	bridge vlan add vid 1 dev $swp1 untagged master
127
128	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
129		flower dst_mac $dmac action drop
130
131	$MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
132	mz_pid=$!
133
134	devlink_trap_drop_test $trap_name $swp2 101
135
136	# Add PVID and make sure packets are no longer dropped.
137	bridge vlan add vid 1 dev $swp1 pvid untagged master
138	devlink_trap_action_set $trap_name "trap"
139
140	devlink_trap_stats_idle_test $trap_name
141	check_err $? "Trap stats not idle when packets should not be dropped"
142	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
143	check_err $? "Trap group stats not idle with when packets should not be dropped"
144
145	tc_check_packets "dev $swp2 egress" 101 0
146	check_fail $? "Packets not forwarded when should"
147
148	devlink_trap_action_set $trap_name "drop"
149
150	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
151}
152
153vlan_tag_mismatch_untagged_test()
154{
155	RET=0
156
157	__vlan_tag_mismatch_test
158
159	log_test "VLAN tag mismatch - untagged packets"
160}
161
162vlan_tag_mismatch_vid_0_test()
163{
164	RET=0
165
166	__vlan_tag_mismatch_test "-Q 0"
167
168	log_test "VLAN tag mismatch - prio-tagged packets"
169}
170
171vlan_tag_mismatch_test()
172{
173	vlan_tag_mismatch_untagged_test
174	vlan_tag_mismatch_vid_0_test
175}
176
177ingress_vlan_filter_test()
178{
179	local trap_name="ingress_vlan_filter"
180	local dmac=de:ad:be:ef:13:37
181	local mz_pid
182	local vid=10
183
184	bridge vlan add vid $vid dev $swp2 master
185
186	RET=0
187
188	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
189		flower dst_mac $dmac action drop
190
191	$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
192	mz_pid=$!
193
194	devlink_trap_drop_test $trap_name $swp2 101
195
196	# Add the VLAN on the bridge port and make sure packets are no longer
197	# dropped.
198	bridge vlan add vid $vid dev $swp1 master
199	devlink_trap_action_set $trap_name "trap"
200
201	devlink_trap_stats_idle_test $trap_name
202	check_err $? "Trap stats not idle when packets should not be dropped"
203	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
204	check_err $? "Trap group stats not idle with when packets should not be dropped"
205
206	tc_check_packets "dev $swp2 egress" 101 0
207	check_fail $? "Packets not forwarded when should"
208
209	devlink_trap_action_set $trap_name "drop"
210
211	log_test "Ingress VLAN filter"
212
213	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
214
215	bridge vlan del vid $vid dev $swp1 master
216	bridge vlan del vid $vid dev $swp2 master
217}
218
219__ingress_stp_filter_test()
220{
221	local trap_name="ingress_spanning_tree_filter"
222	local dmac=de:ad:be:ef:13:37
223	local state=$1; shift
224	local mz_pid
225	local vid=20
226
227	bridge vlan add vid $vid dev $swp2 master
228	bridge vlan add vid $vid dev $swp1 master
229	ip link set dev $swp1 type bridge_slave state $state
230
231	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
232		flower dst_mac $dmac action drop
233
234	$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
235	mz_pid=$!
236
237	devlink_trap_drop_test $trap_name $swp2 101
238
239	# Change STP state to forwarding and make sure packets are no longer
240	# dropped.
241	ip link set dev $swp1 type bridge_slave state 3
242	devlink_trap_action_set $trap_name "trap"
243
244	devlink_trap_stats_idle_test $trap_name
245	check_err $? "Trap stats not idle when packets should not be dropped"
246	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
247	check_err $? "Trap group stats not idle with when packets should not be dropped"
248
249	tc_check_packets "dev $swp2 egress" 101 0
250	check_fail $? "Packets not forwarded when should"
251
252	devlink_trap_action_set $trap_name "drop"
253
254	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
255
256	bridge vlan del vid $vid dev $swp1 master
257	bridge vlan del vid $vid dev $swp2 master
258}
259
260ingress_stp_filter_listening_test()
261{
262	local state=$1; shift
263
264	RET=0
265
266	__ingress_stp_filter_test $state
267
268	log_test "Ingress STP filter - listening state"
269}
270
271ingress_stp_filter_learning_test()
272{
273	local state=$1; shift
274
275	RET=0
276
277	__ingress_stp_filter_test $state
278
279	log_test "Ingress STP filter - learning state"
280}
281
282ingress_stp_filter_test()
283{
284	ingress_stp_filter_listening_test 1
285	ingress_stp_filter_learning_test 2
286}
287
288port_list_is_empty_uc_test()
289{
290	local trap_name="port_list_is_empty"
291	local dmac=de:ad:be:ef:13:37
292	local mz_pid
293
294	# Disable unicast flooding on both ports, so that packets cannot egress
295	# any port.
296	ip link set dev $swp1 type bridge_slave flood off
297	ip link set dev $swp2 type bridge_slave flood off
298
299	RET=0
300
301	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
302		flower dst_mac $dmac action drop
303
304	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
305	mz_pid=$!
306
307	devlink_trap_drop_test $trap_name $swp2 101
308
309	# Allow packets to be flooded to one port.
310	ip link set dev $swp2 type bridge_slave flood on
311	devlink_trap_action_set $trap_name "trap"
312
313	devlink_trap_stats_idle_test $trap_name
314	check_err $? "Trap stats not idle when packets should not be dropped"
315	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
316	check_err $? "Trap group stats not idle with when packets should not be dropped"
317
318	tc_check_packets "dev $swp2 egress" 101 0
319	check_fail $? "Packets not forwarded when should"
320
321	devlink_trap_action_set $trap_name "drop"
322
323	log_test "Port list is empty - unicast"
324
325	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
326
327	ip link set dev $swp1 type bridge_slave flood on
328}
329
330port_list_is_empty_mc_test()
331{
332	local trap_name="port_list_is_empty"
333	local dmac=01:00:5e:00:00:01
334	local dip=239.0.0.1
335	local mz_pid
336
337	# Disable multicast flooding on both ports, so that packets cannot
338	# egress any port. We also need to flush IP addresses from the bridge
339	# in order to prevent packets from being flooded to the router port.
340	ip link set dev $swp1 type bridge_slave mcast_flood off
341	ip link set dev $swp2 type bridge_slave mcast_flood off
342	ip address flush dev br0
343
344	RET=0
345
346	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
347		flower dst_mac $dmac action drop
348
349	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q &
350	mz_pid=$!
351
352	devlink_trap_drop_test $trap_name $swp2 101
353
354	# Allow packets to be flooded to one port.
355	ip link set dev $swp2 type bridge_slave mcast_flood on
356	devlink_trap_action_set $trap_name "trap"
357
358	devlink_trap_stats_idle_test $trap_name
359	check_err $? "Trap stats not idle when packets should not be dropped"
360	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
361	check_err $? "Trap group stats not idle with when packets should not be dropped"
362
363	tc_check_packets "dev $swp2 egress" 101 0
364	check_fail $? "Packets not forwarded when should"
365
366	devlink_trap_action_set $trap_name "drop"
367
368	log_test "Port list is empty - multicast"
369
370	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
371
372	ip link set dev $swp1 type bridge_slave mcast_flood on
373}
374
375port_list_is_empty_test()
376{
377	port_list_is_empty_uc_test
378	port_list_is_empty_mc_test
379}
380
381port_loopback_filter_uc_test()
382{
383	local trap_name="port_loopback_filter"
384	local dmac=de:ad:be:ef:13:37
385	local mz_pid
386
387	# Make sure packets can only egress the input port.
388	ip link set dev $swp2 type bridge_slave flood off
389
390	RET=0
391
392	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
393		flower dst_mac $dmac action drop
394
395	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
396	mz_pid=$!
397
398	devlink_trap_drop_test $trap_name $swp2 101
399
400	# Allow packets to be flooded.
401	ip link set dev $swp2 type bridge_slave flood on
402	devlink_trap_action_set $trap_name "trap"
403
404	devlink_trap_stats_idle_test $trap_name
405	check_err $? "Trap stats not idle when packets should not be dropped"
406	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
407	check_err $? "Trap group stats not idle with when packets should not be dropped"
408
409	tc_check_packets "dev $swp2 egress" 101 0
410	check_fail $? "Packets not forwarded when should"
411
412	devlink_trap_action_set $trap_name "drop"
413
414	log_test "Port loopback filter - unicast"
415
416	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
417}
418
419port_loopback_filter_test()
420{
421	port_loopback_filter_uc_test
422}
423
424locked_port_miss_test()
425{
426	local trap_name="locked_port"
427	local smac=00:11:22:33:44:55
428
429	bridge link set dev $swp1 learning off
430	bridge link set dev $swp1 locked on
431
432	RET=0
433
434	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
435		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
436	check_fail $? "Trap stats increased before setting action to \"trap\""
437
438	devlink_trap_action_set $trap_name "trap"
439
440	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
441		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
442	check_err $? "Trap stats did not increase when should"
443
444	devlink_trap_action_set $trap_name "drop"
445
446	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
447		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
448	check_fail $? "Trap stats increased after setting action to \"drop\""
449
450	devlink_trap_action_set $trap_name "trap"
451
452	bridge fdb replace $smac dev $swp1 master static vlan 1
453
454	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
455		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
456	check_fail $? "Trap stats increased after adding an FDB entry"
457
458	bridge fdb del $smac dev $swp1 master static vlan 1
459	bridge link set dev $swp1 locked off
460
461	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
462		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
463	check_fail $? "Trap stats increased after unlocking port"
464
465	log_test "Locked port - FDB miss"
466
467	devlink_trap_action_set $trap_name "drop"
468	bridge link set dev $swp1 learning on
469}
470
471locked_port_mismatch_test()
472{
473	local trap_name="locked_port"
474	local smac=00:11:22:33:44:55
475
476	bridge link set dev $swp1 learning off
477	bridge link set dev $swp1 locked on
478
479	RET=0
480
481	bridge fdb replace $smac dev $swp2 master static vlan 1
482
483	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
484		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
485	check_fail $? "Trap stats increased before setting action to \"trap\""
486
487	devlink_trap_action_set $trap_name "trap"
488
489	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
490		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
491	check_err $? "Trap stats did not increase when should"
492
493	devlink_trap_action_set $trap_name "drop"
494
495	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
496		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
497	check_fail $? "Trap stats increased after setting action to \"drop\""
498
499	devlink_trap_action_set $trap_name "trap"
500	bridge link set dev $swp1 locked off
501
502	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
503		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
504	check_fail $? "Trap stats increased after unlocking port"
505
506	bridge link set dev $swp1 locked on
507	bridge fdb replace $smac dev $swp1 master static vlan 1
508
509	devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
510		-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
511	check_fail $? "Trap stats increased after replacing an FDB entry"
512
513	bridge fdb del $smac dev $swp1 master static vlan 1
514	devlink_trap_action_set $trap_name "drop"
515
516	log_test "Locked port - FDB mismatch"
517
518	bridge link set dev $swp1 locked off
519	bridge link set dev $swp1 learning on
520}
521
522locked_port_test()
523{
524	locked_port_miss_test
525	locked_port_mismatch_test
526}
527
528trap cleanup EXIT
529
530setup_prepare
531setup_wait
532
533tests_run
534
535exit $EXIT_STATUS
536