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