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"
18NUM_NETIFS=4
19source $lib_dir/tc_common.sh
20source $lib_dir/lib.sh
21source $lib_dir/devlink_lib.sh
22
23h1_create()
24{
25	simple_if_init $h1
26}
27
28h1_destroy()
29{
30	simple_if_fini $h1
31}
32
33h2_create()
34{
35	simple_if_init $h2
36}
37
38h2_destroy()
39{
40	simple_if_fini $h2
41}
42
43switch_create()
44{
45	ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0
46
47	ip link set dev $swp1 master br0
48	ip link set dev $swp2 master br0
49
50	ip link set dev br0 up
51	ip link set dev $swp1 up
52	ip link set dev $swp2 up
53
54	tc qdisc add dev $swp2 clsact
55}
56
57switch_destroy()
58{
59	tc qdisc del dev $swp2 clsact
60
61	ip link set dev $swp2 down
62	ip link set dev $swp1 down
63
64	ip link del dev br0
65}
66
67setup_prepare()
68{
69	h1=${NETIFS[p1]}
70	swp1=${NETIFS[p2]}
71
72	swp2=${NETIFS[p3]}
73	h2=${NETIFS[p4]}
74
75	vrf_prepare
76
77	h1_create
78	h2_create
79
80	switch_create
81}
82
83cleanup()
84{
85	pre_cleanup
86
87	switch_destroy
88
89	h2_destroy
90	h1_destroy
91
92	vrf_cleanup
93}
94
95source_mac_is_multicast_test()
96{
97	local trap_name="source_mac_is_multicast"
98	local smac=01:02:03:04:05:06
99	local mz_pid
100
101	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
102		flower src_mac $smac action drop
103
104	$MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -d 1msec -q &
105	mz_pid=$!
106
107	RET=0
108
109	devlink_trap_drop_test $trap_name $swp2 101
110
111	log_test "Source MAC is multicast"
112
113	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
114}
115
116__vlan_tag_mismatch_test()
117{
118	local trap_name="vlan_tag_mismatch"
119	local dmac=de:ad:be:ef:13:37
120	local opt=$1; shift
121	local mz_pid
122
123	# Remove PVID flag. This should prevent untagged and prio-tagged
124	# packets from entering the bridge.
125	bridge vlan add vid 1 dev $swp1 untagged master
126
127	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
128		flower dst_mac $dmac action drop
129
130	$MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
131	mz_pid=$!
132
133	devlink_trap_drop_test $trap_name $swp2 101
134
135	# Add PVID and make sure packets are no longer dropped.
136	bridge vlan add vid 1 dev $swp1 pvid untagged master
137	devlink_trap_action_set $trap_name "trap"
138
139	devlink_trap_stats_idle_test $trap_name
140	check_err $? "Trap stats not idle when packets should not be dropped"
141	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
142	check_err $? "Trap group stats not idle with when packets should not be dropped"
143
144	tc_check_packets "dev $swp2 egress" 101 0
145	check_fail $? "Packets not forwarded when should"
146
147	devlink_trap_action_set $trap_name "drop"
148
149	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
150}
151
152vlan_tag_mismatch_untagged_test()
153{
154	RET=0
155
156	__vlan_tag_mismatch_test
157
158	log_test "VLAN tag mismatch - untagged packets"
159}
160
161vlan_tag_mismatch_vid_0_test()
162{
163	RET=0
164
165	__vlan_tag_mismatch_test "-Q 0"
166
167	log_test "VLAN tag mismatch - prio-tagged packets"
168}
169
170vlan_tag_mismatch_test()
171{
172	vlan_tag_mismatch_untagged_test
173	vlan_tag_mismatch_vid_0_test
174}
175
176ingress_vlan_filter_test()
177{
178	local trap_name="ingress_vlan_filter"
179	local dmac=de:ad:be:ef:13:37
180	local mz_pid
181	local vid=10
182
183	bridge vlan add vid $vid dev $swp2 master
184
185	RET=0
186
187	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
188		flower dst_mac $dmac action drop
189
190	$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
191	mz_pid=$!
192
193	devlink_trap_drop_test $trap_name $swp2 101
194
195	# Add the VLAN on the bridge port and make sure packets are no longer
196	# dropped.
197	bridge vlan add vid $vid dev $swp1 master
198	devlink_trap_action_set $trap_name "trap"
199
200	devlink_trap_stats_idle_test $trap_name
201	check_err $? "Trap stats not idle when packets should not be dropped"
202	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
203	check_err $? "Trap group stats not idle with when packets should not be dropped"
204
205	tc_check_packets "dev $swp2 egress" 101 0
206	check_fail $? "Packets not forwarded when should"
207
208	devlink_trap_action_set $trap_name "drop"
209
210	log_test "Ingress VLAN filter"
211
212	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
213
214	bridge vlan del vid $vid dev $swp1 master
215	bridge vlan del vid $vid dev $swp2 master
216}
217
218__ingress_stp_filter_test()
219{
220	local trap_name="ingress_spanning_tree_filter"
221	local dmac=de:ad:be:ef:13:37
222	local state=$1; shift
223	local mz_pid
224	local vid=20
225
226	bridge vlan add vid $vid dev $swp2 master
227	bridge vlan add vid $vid dev $swp1 master
228	ip link set dev $swp1 type bridge_slave state $state
229
230	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
231		flower dst_mac $dmac action drop
232
233	$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
234	mz_pid=$!
235
236	devlink_trap_drop_test $trap_name $swp2 101
237
238	# Change STP state to forwarding and make sure packets are no longer
239	# dropped.
240	ip link set dev $swp1 type bridge_slave state 3
241	devlink_trap_action_set $trap_name "trap"
242
243	devlink_trap_stats_idle_test $trap_name
244	check_err $? "Trap stats not idle when packets should not be dropped"
245	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
246	check_err $? "Trap group stats not idle with when packets should not be dropped"
247
248	tc_check_packets "dev $swp2 egress" 101 0
249	check_fail $? "Packets not forwarded when should"
250
251	devlink_trap_action_set $trap_name "drop"
252
253	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
254
255	bridge vlan del vid $vid dev $swp1 master
256	bridge vlan del vid $vid dev $swp2 master
257}
258
259ingress_stp_filter_listening_test()
260{
261	local state=$1; shift
262
263	RET=0
264
265	__ingress_stp_filter_test $state
266
267	log_test "Ingress STP filter - listening state"
268}
269
270ingress_stp_filter_learning_test()
271{
272	local state=$1; shift
273
274	RET=0
275
276	__ingress_stp_filter_test $state
277
278	log_test "Ingress STP filter - learning state"
279}
280
281ingress_stp_filter_test()
282{
283	ingress_stp_filter_listening_test 1
284	ingress_stp_filter_learning_test 2
285}
286
287port_list_is_empty_uc_test()
288{
289	local trap_name="port_list_is_empty"
290	local dmac=de:ad:be:ef:13:37
291	local mz_pid
292
293	# Disable unicast flooding on both ports, so that packets cannot egress
294	# any port.
295	ip link set dev $swp1 type bridge_slave flood off
296	ip link set dev $swp2 type bridge_slave flood off
297
298	RET=0
299
300	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
301		flower dst_mac $dmac action drop
302
303	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
304	mz_pid=$!
305
306	devlink_trap_drop_test $trap_name $swp2 101
307
308	# Allow packets to be flooded to one port.
309	ip link set dev $swp2 type bridge_slave flood on
310	devlink_trap_action_set $trap_name "trap"
311
312	devlink_trap_stats_idle_test $trap_name
313	check_err $? "Trap stats not idle when packets should not be dropped"
314	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
315	check_err $? "Trap group stats not idle with when packets should not be dropped"
316
317	tc_check_packets "dev $swp2 egress" 101 0
318	check_fail $? "Packets not forwarded when should"
319
320	devlink_trap_action_set $trap_name "drop"
321
322	log_test "Port list is empty - unicast"
323
324	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
325
326	ip link set dev $swp1 type bridge_slave flood on
327}
328
329port_list_is_empty_mc_test()
330{
331	local trap_name="port_list_is_empty"
332	local dmac=01:00:5e:00:00:01
333	local dip=239.0.0.1
334	local mz_pid
335
336	# Disable multicast flooding on both ports, so that packets cannot
337	# egress any port. We also need to flush IP addresses from the bridge
338	# in order to prevent packets from being flooded to the router port.
339	ip link set dev $swp1 type bridge_slave mcast_flood off
340	ip link set dev $swp2 type bridge_slave mcast_flood off
341	ip address flush dev br0
342
343	RET=0
344
345	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
346		flower dst_mac $dmac action drop
347
348	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q &
349	mz_pid=$!
350
351	devlink_trap_drop_test $trap_name $swp2 101
352
353	# Allow packets to be flooded to one port.
354	ip link set dev $swp2 type bridge_slave mcast_flood on
355	devlink_trap_action_set $trap_name "trap"
356
357	devlink_trap_stats_idle_test $trap_name
358	check_err $? "Trap stats not idle when packets should not be dropped"
359	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
360	check_err $? "Trap group stats not idle with when packets should not be dropped"
361
362	tc_check_packets "dev $swp2 egress" 101 0
363	check_fail $? "Packets not forwarded when should"
364
365	devlink_trap_action_set $trap_name "drop"
366
367	log_test "Port list is empty - multicast"
368
369	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
370
371	ip link set dev $swp1 type bridge_slave mcast_flood on
372}
373
374port_list_is_empty_test()
375{
376	port_list_is_empty_uc_test
377	port_list_is_empty_mc_test
378}
379
380port_loopback_filter_uc_test()
381{
382	local trap_name="port_loopback_filter"
383	local dmac=de:ad:be:ef:13:37
384	local mz_pid
385
386	# Make sure packets can only egress the input port.
387	ip link set dev $swp2 type bridge_slave flood off
388
389	RET=0
390
391	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
392		flower dst_mac $dmac action drop
393
394	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
395	mz_pid=$!
396
397	devlink_trap_drop_test $trap_name $swp2 101
398
399	# Allow packets to be flooded.
400	ip link set dev $swp2 type bridge_slave flood on
401	devlink_trap_action_set $trap_name "trap"
402
403	devlink_trap_stats_idle_test $trap_name
404	check_err $? "Trap stats not idle when packets should not be dropped"
405	devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name)
406	check_err $? "Trap group stats not idle with when packets should not be dropped"
407
408	tc_check_packets "dev $swp2 egress" 101 0
409	check_fail $? "Packets not forwarded when should"
410
411	devlink_trap_action_set $trap_name "drop"
412
413	log_test "Port loopback filter - unicast"
414
415	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
416}
417
418port_loopback_filter_test()
419{
420	port_loopback_filter_uc_test
421}
422
423trap cleanup EXIT
424
425setup_prepare
426setup_wait
427
428tests_run
429
430exit $EXIT_STATUS
431