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