1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# +--------------------+                     +----------------------+
5# | H1                 |                     |                   H2 |
6# |                    |                     |                      |
7# |              $h1 + |                     | + $h2                |
8# |     192.0.2.2/24 | |                     | | 198.51.100.2/24    |
9# | 2001:db8:1::2/64 | |                     | | 2001:db8:2::2/64   |
10# |                  | |                     | |                    |
11# +------------------|-+                     +-|--------------------+
12#                    |                         |
13# +------------------|-------------------------|--------------------+
14# | SW               |                         |                    |
15# |                  |                         |                    |
16# |             $rp1 +                         + $rp2               |
17# |     192.0.2.1/24                             198.51.100.1/24    |
18# | 2001:db8:1::1/64                             2001:db8:2::1/64   |
19# |                                                                 |
20# +-----------------------------------------------------------------+
21
22ALL_TESTS="
23	ping_ipv4
24	ping_ipv6
25	sip_in_class_e
26	mc_mac_mismatch
27	ipv4_sip_equal_dip
28	ipv6_sip_equal_dip
29	ipv4_dip_link_local
30"
31
32NUM_NETIFS=4
33source lib.sh
34source tc_common.sh
35
36require_command $MCD
37require_command $MC_CLI
38table_name=selftests
39
40h1_create()
41{
42	vrf_create "vrf-h1"
43	ip link set dev $h1 master vrf-h1
44
45	ip link set dev vrf-h1 up
46	ip link set dev $h1 up
47
48	ip address add 192.0.2.2/24 dev $h1
49	ip address add 2001:db8:1::2/64 dev $h1
50
51	ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1
52	ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1
53}
54
55h1_destroy()
56{
57	ip route del 2001:db8:2::/64 vrf vrf-h1
58	ip route del 198.51.100.0/24 vrf vrf-h1
59
60	ip address del 2001:db8:1::2/64 dev $h1
61	ip address del 192.0.2.2/24 dev $h1
62
63	ip link set dev $h1 down
64	vrf_destroy "vrf-h1"
65}
66
67h2_create()
68{
69	vrf_create "vrf-h2"
70	ip link set dev $h2 master vrf-h2
71
72	ip link set dev vrf-h2 up
73	ip link set dev $h2 up
74
75	ip address add 198.51.100.2/24 dev $h2
76	ip address add 2001:db8:2::2/64 dev $h2
77
78	ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1
79	ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1
80}
81
82h2_destroy()
83{
84	ip route del 2001:db8:1::/64 vrf vrf-h2
85	ip route del 192.0.2.0/24 vrf vrf-h2
86
87	ip address del 2001:db8:2::2/64 dev $h2
88	ip address del 198.51.100.2/24 dev $h2
89
90	ip link set dev $h2 down
91	vrf_destroy "vrf-h2"
92}
93
94router_create()
95{
96	ip link set dev $rp1 up
97	ip link set dev $rp2 up
98
99	tc qdisc add dev $rp2 clsact
100
101	ip address add 192.0.2.1/24 dev $rp1
102	ip address add 2001:db8:1::1/64 dev $rp1
103
104	ip address add 198.51.100.1/24 dev $rp2
105	ip address add 2001:db8:2::1/64 dev $rp2
106}
107
108router_destroy()
109{
110	ip address del 2001:db8:2::1/64 dev $rp2
111	ip address del 198.51.100.1/24 dev $rp2
112
113	ip address del 2001:db8:1::1/64 dev $rp1
114	ip address del 192.0.2.1/24 dev $rp1
115
116	tc qdisc del dev $rp2 clsact
117
118	ip link set dev $rp2 down
119	ip link set dev $rp1 down
120}
121
122start_mcd()
123{
124	SMCROUTEDIR="$(mktemp -d)"
125
126	for ((i = 1; i <= $NUM_NETIFS; ++i)); do
127		echo "phyint ${NETIFS[p$i]} enable" >> \
128			$SMCROUTEDIR/$table_name.conf
129	done
130
131	$MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \
132		-P $SMCROUTEDIR/$table_name.pid
133}
134
135kill_mcd()
136{
137	pkill $MCD
138	rm -rf $SMCROUTEDIR
139}
140
141setup_prepare()
142{
143	h1=${NETIFS[p1]}
144	rp1=${NETIFS[p2]}
145
146	rp2=${NETIFS[p3]}
147	h2=${NETIFS[p4]}
148
149	rp1mac=$(mac_get $rp1)
150
151	start_mcd
152
153	vrf_prepare
154
155	h1_create
156	h2_create
157
158	router_create
159
160	forwarding_enable
161}
162
163cleanup()
164{
165	pre_cleanup
166
167	forwarding_restore
168
169	router_destroy
170
171	h2_destroy
172	h1_destroy
173
174	vrf_cleanup
175
176	kill_mcd
177}
178
179ping_ipv4()
180{
181	ping_test $h1 198.51.100.2
182}
183
184ping_ipv6()
185{
186	ping6_test $h1 2001:db8:2::2
187}
188
189sip_in_class_e()
190{
191	RET=0
192
193	# Disable rpfilter to prevent packets to be dropped because of it.
194	sysctl_set net.ipv4.conf.all.rp_filter 0
195	sysctl_set net.ipv4.conf.$rp1.rp_filter 0
196
197	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
198		flower src_ip 240.0.0.1 ip_proto udp action pass
199
200	$MZ $h1 -t udp "sp=54321,dp=12345" -c 5 -d 1msec \
201		-A 240.0.0.1 -b $rp1mac -B 198.51.100.2 -q
202
203	tc_check_packets "dev $rp2 egress" 101 5
204	check_err $? "Packets were dropped"
205
206	log_test "Source IP in class E"
207
208	tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
209	sysctl_restore net.ipv4.conf.$rp1.rp_filter
210	sysctl_restore net.ipv4.conf.all.rp_filter
211}
212
213create_mcast_sg()
214{
215	local if_name=$1; shift
216	local s_addr=$1; shift
217	local mcast=$1; shift
218	local dest_ifs=${@}
219
220	$MC_CLI -I $table_name add $if_name $s_addr $mcast $dest_ifs
221}
222
223delete_mcast_sg()
224{
225	local if_name=$1; shift
226	local s_addr=$1; shift
227	local mcast=$1; shift
228	local dest_ifs=${@}
229
230	$MC_CLI -I $table_name remove $if_name $s_addr $mcast $dest_ifs
231}
232
233__mc_mac_mismatch()
234{
235	local desc=$1; shift
236	local proto=$1; shift
237	local sip=$1; shift
238	local dip=$1; shift
239	local flags=${1:-""}; shift
240	local dmac=01:02:03:04:05:06
241
242	RET=0
243
244	tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
245		flower dst_ip $dip action pass
246
247	create_mcast_sg $rp1 $sip $dip $rp2
248
249	$MZ $flags $h1 -t udp "sp=54321,dp=12345" -c 5 -d 1msec -b $dmac \
250		-B $dip -q
251
252	tc_check_packets "dev $rp2 egress" 101 5
253	check_err $? "Packets were dropped"
254
255	log_test "Multicast MAC mismatch: $desc"
256
257	delete_mcast_sg $rp1 $sip $dip $rp2
258	tc filter del dev $rp2 egress protocol $proto pref 1 handle 101 flower
259}
260
261mc_mac_mismatch()
262{
263	__mc_mac_mismatch "IPv4" "ip" 192.0.2.2 225.1.2.3
264	__mc_mac_mismatch "IPv6" "ipv6" 2001:db8:1::2 ff0e::3 "-6"
265}
266
267ipv4_sip_equal_dip()
268{
269	RET=0
270
271	# Disable rpfilter to prevent packets to be dropped because of it.
272	sysctl_set net.ipv4.conf.all.rp_filter 0
273	sysctl_set net.ipv4.conf.$rp1.rp_filter 0
274
275	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
276		flower src_ip 198.51.100.2  action pass
277
278	$MZ $h1 -t udp "sp=54321,dp=12345" -c 5 -d 1msec \
279		-A 198.51.100.2 -b $rp1mac -B 198.51.100.2 -q
280
281	tc_check_packets "dev $rp2 egress" 101 5
282	check_err $? "Packets were dropped"
283
284	log_test "Source IP is equal to destination IP: IPv4"
285
286	tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
287	sysctl_restore net.ipv4.conf.$rp1.rp_filter
288	sysctl_restore net.ipv4.conf.all.rp_filter
289}
290
291ipv6_sip_equal_dip()
292{
293	RET=0
294
295	tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \
296		flower src_ip 2001:db8:2::2 action pass
297
298	$MZ -6 $h1 -t udp "sp=54321,dp=12345" -c 5 -d 1msec \
299		-A 2001:db8:2::2 -b $rp1mac -B 2001:db8:2::2 -q
300
301	tc_check_packets "dev $rp2 egress" 101 5
302	check_err $? "Packets were dropped"
303
304	log_test "Source IP is equal to destination IP: IPv6"
305
306	tc filter del dev $rp2 egress protocol ipv6 pref 1 handle 101 flower
307}
308
309ipv4_dip_link_local()
310{
311	local dip=169.254.1.1
312
313	RET=0
314
315	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
316		flower dst_ip $dip action pass
317
318	ip neigh add 169.254.1.1 lladdr 00:11:22:33:44:55 dev $rp2
319	ip route add 169.254.1.0/24 dev $rp2
320
321	$MZ $h1 -t udp "sp=54321,dp=12345" -c 5 -d 1msec -b $rp1mac -B $dip -q
322
323	tc_check_packets "dev $rp2 egress" 101 5
324	check_err $? "Packets were dropped"
325
326	log_test "IPv4 destination IP is link-local"
327
328	ip route del 169.254.1.0/24 dev $rp2
329	ip neigh del 169.254.1.1 lladdr 00:11:22:33:44:55 dev $rp2
330	tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
331}
332
333trap cleanup EXIT
334
335setup_prepare
336setup_wait
337
338tests_run
339
340exit $EXIT_STATUS
341