1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# +-----------------------+                             +----------------------+
5# | H1 (vrf)              |                             | H2 (vrf)             |
6# |    + $h1              |                             |              $h2 +   |
7# |    | 192.0.2.1/28     |                             |     192.0.2.2/28 |   |
8# |    | 2001:db8:1::1/64 |                             | 2001:db8:1::2/64 |   |
9# +----|------------------+                             +------------------|---+
10#      |                                                                   |
11# +----|-------------------------------------------------------------------|---+
12# | SW |                                                                   |   |
13# |  +-|-------------------------------------------------------------------|-+ |
14# |  | + $swp1                       BR                              $swp2 + | |
15# |  +-----------------------------------------------------------------------+ |
16# +----------------------------------------------------------------------------+
17
18ALL_TESTS="
19	test_l2_miss_unicast
20	test_l2_miss_multicast
21	test_l2_miss_ll_multicast
22	test_l2_miss_broadcast
23"
24
25NUM_NETIFS=4
26source lib.sh
27source tc_common.sh
28
29h1_create()
30{
31	simple_if_init $h1 192.0.2.1/28 2001:db8:1::1/64
32}
33
34h1_destroy()
35{
36	simple_if_fini $h1 192.0.2.1/28 2001:db8:1::1/64
37}
38
39h2_create()
40{
41	simple_if_init $h2 192.0.2.2/28 2001:db8:1::2/64
42}
43
44h2_destroy()
45{
46	simple_if_fini $h2 192.0.2.2/28 2001:db8:1::2/64
47}
48
49switch_create()
50{
51	ip link add name br1 up type bridge
52	ip link set dev $swp1 master br1
53	ip link set dev $swp1 up
54	ip link set dev $swp2 master br1
55	ip link set dev $swp2 up
56
57	tc qdisc add dev $swp2 clsact
58}
59
60switch_destroy()
61{
62	tc qdisc del dev $swp2 clsact
63
64	ip link set dev $swp2 down
65	ip link set dev $swp2 nomaster
66	ip link set dev $swp1 down
67	ip link set dev $swp1 nomaster
68	ip link del dev br1
69}
70
71test_l2_miss_unicast()
72{
73	local dmac=00:01:02:03:04:05
74	local dip=192.0.2.2
75	local sip=192.0.2.1
76
77	RET=0
78
79	# Unknown unicast.
80	tc filter add dev $swp2 egress protocol ipv4 handle 101 pref 1 \
81	   flower indev $swp1 l2_miss 1 dst_mac $dmac src_ip $sip \
82	   dst_ip $dip action pass
83	# Known unicast.
84	tc filter add dev $swp2 egress protocol ipv4 handle 102 pref 1 \
85	   flower indev $swp1 l2_miss 0 dst_mac $dmac src_ip $sip \
86	   dst_ip $dip action pass
87
88	# Before adding FDB entry.
89	$MZ $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
90
91	tc_check_packets "dev $swp2 egress" 101 1
92	check_err $? "Unknown unicast filter was not hit before adding FDB entry"
93
94	tc_check_packets "dev $swp2 egress" 102 0
95	check_err $? "Known unicast filter was hit before adding FDB entry"
96
97	# Adding FDB entry.
98	bridge fdb replace $dmac dev $swp2 master static
99
100	$MZ $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
101
102	tc_check_packets "dev $swp2 egress" 101 1
103	check_err $? "Unknown unicast filter was hit after adding FDB entry"
104
105	tc_check_packets "dev $swp2 egress" 102 1
106	check_err $? "Known unicast filter was not hit after adding FDB entry"
107
108	# Deleting FDB entry.
109	bridge fdb del $dmac dev $swp2 master static
110
111	$MZ $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
112
113	tc_check_packets "dev $swp2 egress" 101 2
114	check_err $? "Unknown unicast filter was not hit after deleting FDB entry"
115
116	tc_check_packets "dev $swp2 egress" 102 1
117	check_err $? "Known unicast filter was hit after deleting FDB entry"
118
119	tc filter del dev $swp2 egress protocol ipv4 pref 1 handle 102 flower
120	tc filter del dev $swp2 egress protocol ipv4 pref 1 handle 101 flower
121
122	log_test "L2 miss - Unicast"
123}
124
125test_l2_miss_multicast_common()
126{
127	local proto=$1; shift
128	local sip=$1; shift
129	local dip=$1; shift
130	local mode=$1; shift
131	local name=$1; shift
132
133	RET=0
134
135	# Unregistered multicast.
136	tc filter add dev $swp2 egress protocol $proto handle 101 pref 1 \
137	   flower indev $swp1 l2_miss 1 src_ip $sip dst_ip $dip \
138	   action pass
139	# Registered multicast.
140	tc filter add dev $swp2 egress protocol $proto handle 102 pref 1 \
141	   flower indev $swp1 l2_miss 0 src_ip $sip dst_ip $dip \
142	   action pass
143
144	# Before adding MDB entry.
145	$MZ $mode $h1 -t ip -A $sip -B $dip -c 1 -p 100 -q
146
147	tc_check_packets "dev $swp2 egress" 101 1
148	check_err $? "Unregistered multicast filter was not hit before adding MDB entry"
149
150	tc_check_packets "dev $swp2 egress" 102 0
151	check_err $? "Registered multicast filter was hit before adding MDB entry"
152
153	# Adding MDB entry.
154	bridge mdb replace dev br1 port $swp2 grp $dip permanent
155
156	$MZ $mode $h1 -t ip -A $sip -B $dip -c 1 -p 100 -q
157
158	tc_check_packets "dev $swp2 egress" 101 1
159	check_err $? "Unregistered multicast filter was hit after adding MDB entry"
160
161	tc_check_packets "dev $swp2 egress" 102 1
162	check_err $? "Registered multicast filter was not hit after adding MDB entry"
163
164	# Deleting MDB entry.
165	bridge mdb del dev br1 port $swp2 grp $dip
166
167	$MZ $mode $h1 -t ip -A $sip -B $dip -c 1 -p 100 -q
168
169	tc_check_packets "dev $swp2 egress" 101 2
170	check_err $? "Unregistered multicast filter was not hit after deleting MDB entry"
171
172	tc_check_packets "dev $swp2 egress" 102 1
173	check_err $? "Registered multicast filter was hit after deleting MDB entry"
174
175	tc filter del dev $swp2 egress protocol $proto pref 1 handle 102 flower
176	tc filter del dev $swp2 egress protocol $proto pref 1 handle 101 flower
177
178	log_test "L2 miss - Multicast ($name)"
179}
180
181test_l2_miss_multicast_ipv4()
182{
183	local proto="ipv4"
184	local sip=192.0.2.1
185	local dip=239.1.1.1
186	local mode="-4"
187	local name="IPv4"
188
189	test_l2_miss_multicast_common $proto $sip $dip $mode $name
190}
191
192test_l2_miss_multicast_ipv6()
193{
194	local proto="ipv6"
195	local sip=2001:db8:1::1
196	local dip=ff0e::1
197	local mode="-6"
198	local name="IPv6"
199
200	test_l2_miss_multicast_common $proto $sip $dip $mode $name
201}
202
203test_l2_miss_multicast()
204{
205	# Configure $swp2 as a multicast router port so that it will forward
206	# both registered and unregistered multicast traffic.
207	bridge link set dev $swp2 mcast_router 2
208
209	# Forwarding according to MDB entries only takes place when the bridge
210	# detects that there is a valid querier in the network. Set the bridge
211	# as the querier and assign it a valid IPv6 link-local address to be
212	# used as the source address for MLD queries.
213	ip link set dev br1 type bridge mcast_querier 1
214	ip -6 address add fe80::1/64 nodad dev br1
215	# Wait the default Query Response Interval (10 seconds) for the bridge
216	# to determine that there are no other queriers in the network.
217	sleep 10
218
219	test_l2_miss_multicast_ipv4
220	test_l2_miss_multicast_ipv6
221
222	ip -6 address del fe80::1/64 dev br1
223	ip link set dev br1 type bridge mcast_querier 0
224	bridge link set dev $swp2 mcast_router 1
225}
226
227test_l2_miss_multicast_common2()
228{
229	local name=$1; shift
230	local dmac=$1; shift
231	local dip=224.0.0.1
232	local sip=192.0.2.1
233
234}
235
236test_l2_miss_ll_multicast_common()
237{
238	local proto=$1; shift
239	local dmac=$1; shift
240	local sip=$1; shift
241	local dip=$1; shift
242	local mode=$1; shift
243	local name=$1; shift
244
245	RET=0
246
247	tc filter add dev $swp2 egress protocol $proto handle 101 pref 1 \
248	   flower indev $swp1 l2_miss 1 dst_mac $dmac src_ip $sip \
249	   dst_ip $dip action pass
250
251	$MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
252
253	tc_check_packets "dev $swp2 egress" 101 1
254	check_err $? "Filter was not hit"
255
256	tc filter del dev $swp2 egress protocol $proto pref 1 handle 101 flower
257
258	log_test "L2 miss - Link-local multicast ($name)"
259}
260
261test_l2_miss_ll_multicast_ipv4()
262{
263	local proto=ipv4
264	local dmac=01:00:5e:00:00:01
265	local sip=192.0.2.1
266	local dip=224.0.0.1
267	local mode="-4"
268	local name="IPv4"
269
270	test_l2_miss_ll_multicast_common $proto $dmac $sip $dip $mode $name
271}
272
273test_l2_miss_ll_multicast_ipv6()
274{
275	local proto=ipv6
276	local dmac=33:33:00:00:00:01
277	local sip=2001:db8:1::1
278	local dip=ff02::1
279	local mode="-6"
280	local name="IPv6"
281
282	test_l2_miss_ll_multicast_common $proto $dmac $sip $dip $mode $name
283}
284
285test_l2_miss_ll_multicast()
286{
287	test_l2_miss_ll_multicast_ipv4
288	test_l2_miss_ll_multicast_ipv6
289}
290
291test_l2_miss_broadcast()
292{
293	local dmac=ff:ff:ff:ff:ff:ff
294	local smac=00:01:02:03:04:05
295
296	RET=0
297
298	tc filter add dev $swp2 egress protocol all handle 101 pref 1 \
299	   flower l2_miss 1 dst_mac $dmac src_mac $smac \
300	   action pass
301	tc filter add dev $swp2 egress protocol all handle 102 pref 1 \
302	   flower l2_miss 0 dst_mac $dmac src_mac $smac \
303	   action pass
304
305	$MZ $h1 -a $smac -b $dmac -c 1 -p 100 -q
306
307	tc_check_packets "dev $swp2 egress" 101 0
308	check_err $? "L2 miss filter was hit when should not"
309
310	tc_check_packets "dev $swp2 egress" 102 1
311	check_err $? "L2 no miss filter was not hit when should"
312
313	tc filter del dev $swp2 egress protocol all pref 1 handle 102 flower
314	tc filter del dev $swp2 egress protocol all pref 1 handle 101 flower
315
316	log_test "L2 miss - Broadcast"
317}
318
319setup_prepare()
320{
321	h1=${NETIFS[p1]}
322	swp1=${NETIFS[p2]}
323
324	swp2=${NETIFS[p3]}
325	h2=${NETIFS[p4]}
326
327	vrf_prepare
328	h1_create
329	h2_create
330	switch_create
331}
332
333cleanup()
334{
335	pre_cleanup
336
337	switch_destroy
338	h2_destroy
339	h1_destroy
340	vrf_cleanup
341}
342
343trap cleanup EXIT
344
345setup_prepare
346setup_wait
347
348tests_run
349
350exit $EXIT_STATUS
351