1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="
5	locked_port_ipv4
6	locked_port_ipv6
7	locked_port_vlan
8	locked_port_mab
9	locked_port_mab_roam
10	locked_port_mab_config
11	locked_port_mab_flush
12	locked_port_mab_redirect
13"
14
15NUM_NETIFS=4
16CHECK_TC="no"
17source lib.sh
18
19h1_create()
20{
21	simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
22	vlan_create $h1 100 v$h1 198.51.100.1/24
23}
24
25h1_destroy()
26{
27	vlan_destroy $h1 100
28	simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
29}
30
31h2_create()
32{
33	simple_if_init $h2 192.0.2.2/24 2001:db8:1::2/64
34	vlan_create $h2 100 v$h2 198.51.100.2/24
35}
36
37h2_destroy()
38{
39	vlan_destroy $h2 100
40	simple_if_fini $h2 192.0.2.2/24 2001:db8:1::2/64
41}
42
43switch_create()
44{
45	ip link add dev br0 type bridge vlan_filtering 1
46
47	ip link set dev $swp1 master br0
48	ip link set dev $swp2 master br0
49
50	bridge link set dev $swp1 learning off
51
52	ip link set dev br0 up
53	ip link set dev $swp1 up
54	ip link set dev $swp2 up
55}
56
57switch_destroy()
58{
59	ip link set dev $swp2 down
60	ip link set dev $swp1 down
61
62	ip link del dev br0
63}
64
65setup_prepare()
66{
67	h1=${NETIFS[p1]}
68	swp1=${NETIFS[p2]}
69
70	swp2=${NETIFS[p3]}
71	h2=${NETIFS[p4]}
72
73	vrf_prepare
74
75	h1_create
76	h2_create
77
78	switch_create
79}
80
81cleanup()
82{
83	pre_cleanup
84
85	switch_destroy
86
87	h2_destroy
88	h1_destroy
89
90	vrf_cleanup
91}
92
93locked_port_ipv4()
94{
95	RET=0
96
97	check_locked_port_support || return 0
98
99	ping_do $h1 192.0.2.2
100	check_err $? "Ping did not work before locking port"
101
102	bridge link set dev $swp1 locked on
103
104	ping_do $h1 192.0.2.2
105	check_fail $? "Ping worked after locking port, but before adding FDB entry"
106
107	bridge fdb add `mac_get $h1` dev $swp1 master static
108
109	ping_do $h1 192.0.2.2
110	check_err $? "Ping did not work after locking port and adding FDB entry"
111
112	bridge link set dev $swp1 locked off
113	bridge fdb del `mac_get $h1` dev $swp1 master static
114
115	ping_do $h1 192.0.2.2
116	check_err $? "Ping did not work after unlocking port and removing FDB entry."
117
118	log_test "Locked port ipv4"
119}
120
121locked_port_vlan()
122{
123	RET=0
124
125	check_locked_port_support || return 0
126
127	bridge vlan add vid 100 dev $swp1
128	bridge vlan add vid 100 dev $swp2
129
130	ping_do $h1.100 198.51.100.2
131	check_err $? "Ping through vlan did not work before locking port"
132
133	bridge link set dev $swp1 locked on
134	ping_do $h1.100 198.51.100.2
135	check_fail $? "Ping through vlan worked after locking port, but before adding FDB entry"
136
137	bridge fdb add `mac_get $h1` dev $swp1 vlan 100 master static
138
139	ping_do $h1.100 198.51.100.2
140	check_err $? "Ping through vlan did not work after locking port and adding FDB entry"
141
142	bridge link set dev $swp1 locked off
143	bridge fdb del `mac_get $h1` dev $swp1 vlan 100 master static
144
145	ping_do $h1.100 198.51.100.2
146	check_err $? "Ping through vlan did not work after unlocking port and removing FDB entry"
147
148	bridge vlan del vid 100 dev $swp1
149	bridge vlan del vid 100 dev $swp2
150	log_test "Locked port vlan"
151}
152
153locked_port_ipv6()
154{
155	RET=0
156	check_locked_port_support || return 0
157
158	ping6_do $h1 2001:db8:1::2
159	check_err $? "Ping6 did not work before locking port"
160
161	bridge link set dev $swp1 locked on
162
163	ping6_do $h1 2001:db8:1::2
164	check_fail $? "Ping6 worked after locking port, but before adding FDB entry"
165
166	bridge fdb add `mac_get $h1` dev $swp1 master static
167	ping6_do $h1 2001:db8:1::2
168	check_err $? "Ping6 did not work after locking port and adding FDB entry"
169
170	bridge link set dev $swp1 locked off
171	bridge fdb del `mac_get $h1` dev $swp1 master static
172
173	ping6_do $h1 2001:db8:1::2
174	check_err $? "Ping6 did not work after unlocking port and removing FDB entry"
175
176	log_test "Locked port ipv6"
177}
178
179locked_port_mab()
180{
181	RET=0
182	check_port_mab_support || return 0
183
184	ping_do $h1 192.0.2.2
185	check_err $? "Ping did not work before locking port"
186
187	bridge link set dev $swp1 learning on locked on
188
189	ping_do $h1 192.0.2.2
190	check_fail $? "Ping worked on a locked port without an FDB entry"
191
192	bridge fdb get `mac_get $h1` br br0 vlan 1 &> /dev/null
193	check_fail $? "FDB entry created before enabling MAB"
194
195	bridge link set dev $swp1 learning on locked on mab on
196
197	ping_do $h1 192.0.2.2
198	check_fail $? "Ping worked on MAB enabled port without an FDB entry"
199
200	bridge fdb get `mac_get $h1` br br0 vlan 1 | grep "dev $swp1" | grep -q "locked"
201	check_err $? "Locked FDB entry not created"
202
203	bridge fdb replace `mac_get $h1` dev $swp1 master static
204
205	ping_do $h1 192.0.2.2
206	check_err $? "Ping did not work after replacing FDB entry"
207
208	bridge fdb get `mac_get $h1` br br0 vlan 1 | grep "dev $swp1" | grep -q "locked"
209	check_fail $? "FDB entry marked as locked after replacement"
210
211	bridge fdb del `mac_get $h1` dev $swp1 master
212	bridge link set dev $swp1 learning off locked off mab off
213
214	log_test "Locked port MAB"
215}
216
217# Check that entries cannot roam to a locked port, but that entries can roam
218# to an unlocked port.
219locked_port_mab_roam()
220{
221	local mac=a0:b0:c0:c0:b0:a0
222
223	RET=0
224	check_port_mab_support || return 0
225
226	bridge link set dev $swp1 learning on locked on mab on
227
228	$MZ $h1 -q -c 5 -d 100msec -t udp -a $mac -b rand
229	bridge fdb get $mac br br0 vlan 1 | grep "dev $swp1" | grep -q "locked"
230	check_err $? "No locked entry on first injection"
231
232	$MZ $h2 -q -c 5 -d 100msec -t udp -a $mac -b rand
233	bridge fdb get $mac br br0 vlan 1 | grep -q "dev $swp2"
234	check_err $? "Entry did not roam to an unlocked port"
235
236	bridge fdb get $mac br br0 vlan 1 | grep -q "locked"
237	check_fail $? "Entry roamed with locked flag on"
238
239	$MZ $h1 -q -c 5 -d 100msec -t udp -a $mac -b rand
240	bridge fdb get $mac br br0 vlan 1 | grep -q "dev $swp1"
241	check_fail $? "Entry roamed back to locked port"
242
243	bridge fdb del $mac vlan 1 dev $swp2 master
244	bridge link set dev $swp1 learning off locked off mab off
245
246	log_test "Locked port MAB roam"
247}
248
249# Check that MAB can only be enabled on a port that is both locked and has
250# learning enabled.
251locked_port_mab_config()
252{
253	RET=0
254	check_port_mab_support || return 0
255
256	bridge link set dev $swp1 learning on locked off mab on &> /dev/null
257	check_fail $? "MAB enabled while port is unlocked"
258
259	bridge link set dev $swp1 learning off locked on mab on &> /dev/null
260	check_fail $? "MAB enabled while port has learning disabled"
261
262	bridge link set dev $swp1 learning on locked on mab on
263	check_err $? "Failed to enable MAB when port is locked and has learning enabled"
264
265	bridge link set dev $swp1 learning off locked off mab off
266
267	log_test "Locked port MAB configuration"
268}
269
270# Check that locked FDB entries are flushed from a port when MAB is disabled.
271locked_port_mab_flush()
272{
273	local locked_mac1=00:01:02:03:04:05
274	local unlocked_mac1=00:01:02:03:04:06
275	local locked_mac2=00:01:02:03:04:07
276	local unlocked_mac2=00:01:02:03:04:08
277
278	RET=0
279	check_port_mab_support || return 0
280
281	bridge link set dev $swp1 learning on locked on mab on
282	bridge link set dev $swp2 learning on locked on mab on
283
284	# Create regular and locked FDB entries on each port.
285	bridge fdb add $unlocked_mac1 dev $swp1 vlan 1 master static
286	bridge fdb add $unlocked_mac2 dev $swp2 vlan 1 master static
287
288	$MZ $h1 -q -c 5 -d 100msec -t udp -a $locked_mac1 -b rand
289	bridge fdb get $locked_mac1 br br0 vlan 1 | grep "dev $swp1" | \
290		grep -q "locked"
291	check_err $? "Failed to create locked FDB entry on first port"
292
293	$MZ $h2 -q -c 5 -d 100msec -t udp -a $locked_mac2 -b rand
294	bridge fdb get $locked_mac2 br br0 vlan 1 | grep "dev $swp2" | \
295		grep -q "locked"
296	check_err $? "Failed to create locked FDB entry on second port"
297
298	# Disable MAB on the first port and check that only the first locked
299	# FDB entry was flushed.
300	bridge link set dev $swp1 mab off
301
302	bridge fdb get $unlocked_mac1 br br0 vlan 1 &> /dev/null
303	check_err $? "Regular FDB entry on first port was flushed after disabling MAB"
304
305	bridge fdb get $unlocked_mac2 br br0 vlan 1 &> /dev/null
306	check_err $? "Regular FDB entry on second port was flushed after disabling MAB"
307
308	bridge fdb get $locked_mac1 br br0 vlan 1 &> /dev/null
309	check_fail $? "Locked FDB entry on first port was not flushed after disabling MAB"
310
311	bridge fdb get $locked_mac2 br br0 vlan 1 &> /dev/null
312	check_err $? "Locked FDB entry on second port was flushed after disabling MAB"
313
314	bridge fdb del $unlocked_mac2 dev $swp2 vlan 1 master static
315	bridge fdb del $unlocked_mac1 dev $swp1 vlan 1 master static
316
317	bridge link set dev $swp2 learning on locked off mab off
318	bridge link set dev $swp1 learning off locked off mab off
319
320	log_test "Locked port MAB FDB flush"
321}
322
323# Check that traffic can be redirected from a locked bridge port and that it
324# does not create locked FDB entries.
325locked_port_mab_redirect()
326{
327	RET=0
328	check_port_mab_support || return 0
329
330	tc qdisc add dev $swp1 clsact
331	tc filter add dev $swp1 ingress protocol all pref 1 handle 101 flower \
332		action mirred egress redirect dev $swp2
333	bridge link set dev $swp1 learning on locked on mab on
334
335	ping_do $h1 192.0.2.2
336	check_err $? "Ping did not work with redirection"
337
338	bridge fdb get `mac_get $h1` br br0 vlan 1 2> /dev/null | \
339		grep "dev $swp1" | grep -q "locked"
340	check_fail $? "Locked entry created for redirected traffic"
341
342	tc filter del dev $swp1 ingress protocol all pref 1 handle 101 flower
343
344	ping_do $h1 192.0.2.2
345	check_fail $? "Ping worked without redirection"
346
347	bridge fdb get `mac_get $h1` br br0 vlan 1 2> /dev/null | \
348		grep "dev $swp1" | grep -q "locked"
349	check_err $? "Locked entry not created after deleting filter"
350
351	bridge fdb del `mac_get $h1` vlan 1 dev $swp1 master
352	bridge link set dev $swp1 learning off locked off mab off
353	tc qdisc del dev $swp1 clsact
354
355	log_test "Locked port MAB redirect"
356}
357
358trap cleanup EXIT
359
360setup_prepare
361setup_wait
362
363tests_run
364
365exit $EXIT_STATUS
366