1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="
5	ping_ipv4
6	ping_ipv6
7	multipath_test
8	ping_ipv4_blackhole
9	ping_ipv6_blackhole
10"
11NUM_NETIFS=8
12source lib.sh
13
14h1_create()
15{
16	vrf_create "vrf-h1"
17	ip link set dev $h1 master vrf-h1
18
19	ip link set dev vrf-h1 up
20	ip link set dev $h1 up
21
22	ip address add 192.0.2.2/24 dev $h1
23	ip address add 2001:db8:1::2/64 dev $h1
24
25	ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1
26	ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1
27}
28
29h1_destroy()
30{
31	ip route del 2001:db8:2::/64 vrf vrf-h1
32	ip route del 198.51.100.0/24 vrf vrf-h1
33
34	ip address del 2001:db8:1::2/64 dev $h1
35	ip address del 192.0.2.2/24 dev $h1
36
37	ip link set dev $h1 down
38	vrf_destroy "vrf-h1"
39}
40
41h2_create()
42{
43	vrf_create "vrf-h2"
44	ip link set dev $h2 master vrf-h2
45
46	ip link set dev vrf-h2 up
47	ip link set dev $h2 up
48
49	ip address add 198.51.100.2/24 dev $h2
50	ip address add 2001:db8:2::2/64 dev $h2
51
52	ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1
53	ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1
54}
55
56h2_destroy()
57{
58	ip route del 2001:db8:1::/64 vrf vrf-h2
59	ip route del 192.0.2.0/24 vrf vrf-h2
60
61	ip address del 2001:db8:2::2/64 dev $h2
62	ip address del 198.51.100.2/24 dev $h2
63
64	ip link set dev $h2 down
65	vrf_destroy "vrf-h2"
66}
67
68router1_create()
69{
70	vrf_create "vrf-r1"
71	ip link set dev $rp11 master vrf-r1
72	ip link set dev $rp12 master vrf-r1
73	ip link set dev $rp13 master vrf-r1
74
75	ip link set dev vrf-r1 up
76	ip link set dev $rp11 up
77	ip link set dev $rp12 up
78	ip link set dev $rp13 up
79
80	ip address add 192.0.2.1/24 dev $rp11
81	ip address add 2001:db8:1::1/64 dev $rp11
82
83	ip address add 169.254.2.12/24 dev $rp12
84	ip address add fe80:2::12/64 dev $rp12
85
86	ip address add 169.254.3.13/24 dev $rp13
87	ip address add fe80:3::13/64 dev $rp13
88}
89
90router1_destroy()
91{
92	ip route del 2001:db8:2::/64 vrf vrf-r1
93	ip route del 198.51.100.0/24 vrf vrf-r1
94
95	ip address del fe80:3::13/64 dev $rp13
96	ip address del 169.254.3.13/24 dev $rp13
97
98	ip address del fe80:2::12/64 dev $rp12
99	ip address del 169.254.2.12/24 dev $rp12
100
101	ip address del 2001:db8:1::1/64 dev $rp11
102	ip address del 192.0.2.1/24 dev $rp11
103
104	ip nexthop del id 103
105	ip nexthop del id 101
106	ip nexthop del id 102
107	ip nexthop del id 106
108	ip nexthop del id 104
109	ip nexthop del id 105
110
111	ip link set dev $rp13 down
112	ip link set dev $rp12 down
113	ip link set dev $rp11 down
114
115	vrf_destroy "vrf-r1"
116}
117
118router2_create()
119{
120	vrf_create "vrf-r2"
121	ip link set dev $rp21 master vrf-r2
122	ip link set dev $rp22 master vrf-r2
123	ip link set dev $rp23 master vrf-r2
124
125	ip link set dev vrf-r2 up
126	ip link set dev $rp21 up
127	ip link set dev $rp22 up
128	ip link set dev $rp23 up
129
130	ip address add 198.51.100.1/24 dev $rp21
131	ip address add 2001:db8:2::1/64 dev $rp21
132
133	ip address add 169.254.2.22/24 dev $rp22
134	ip address add fe80:2::22/64 dev $rp22
135
136	ip address add 169.254.3.23/24 dev $rp23
137	ip address add fe80:3::23/64 dev $rp23
138}
139
140router2_destroy()
141{
142	ip route del 2001:db8:1::/64 vrf vrf-r2
143	ip route del 192.0.2.0/24 vrf vrf-r2
144
145	ip address del fe80:3::23/64 dev $rp23
146	ip address del 169.254.3.23/24 dev $rp23
147
148	ip address del fe80:2::22/64 dev $rp22
149	ip address del 169.254.2.22/24 dev $rp22
150
151	ip address del 2001:db8:2::1/64 dev $rp21
152	ip address del 198.51.100.1/24 dev $rp21
153
154	ip nexthop del id 201
155	ip nexthop del id 202
156	ip nexthop del id 204
157	ip nexthop del id 205
158
159	ip link set dev $rp23 down
160	ip link set dev $rp22 down
161	ip link set dev $rp21 down
162
163	vrf_destroy "vrf-r2"
164}
165
166routing_nh_obj()
167{
168	ip nexthop add id 101 via 169.254.2.22 dev $rp12
169	ip nexthop add id 102 via 169.254.3.23 dev $rp13
170	ip nexthop add id 103 group 101/102
171	ip route add 198.51.100.0/24 vrf vrf-r1 nhid 103
172
173	ip nexthop add id 104 via fe80:2::22 dev $rp12
174	ip nexthop add id 105 via fe80:3::23 dev $rp13
175	ip nexthop add id 106 group 104/105
176	ip route add 2001:db8:2::/64 vrf vrf-r1 nhid 106
177
178	ip nexthop add id 201 via 169.254.2.12 dev $rp22
179	ip nexthop add id 202 via 169.254.3.13 dev $rp23
180	ip nexthop add id 203 group 201/202
181	ip route add 192.0.2.0/24 vrf vrf-r2 nhid 203
182
183	ip nexthop add id 204 via fe80:2::12 dev $rp22
184	ip nexthop add id 205 via fe80:3::13 dev $rp23
185	ip nexthop add id 206 group 204/205
186	ip route add 2001:db8:1::/64 vrf vrf-r2 nhid 206
187}
188
189multipath4_test()
190{
191	local desc="$1"
192	local weight_rp12=$2
193	local weight_rp13=$3
194	local t0_rp12 t0_rp13 t1_rp12 t1_rp13
195	local packets_rp12 packets_rp13
196
197	# Transmit multiple flows from h1 to h2 and make sure they are
198	# distributed between both multipath links (rp12 and rp13)
199	# according to the configured weights.
200	sysctl_set net.ipv4.fib_multipath_hash_policy 1
201	ip nexthop replace id 103 group 101,$weight_rp12/102,$weight_rp13
202
203	t0_rp12=$(link_stats_tx_packets_get $rp12)
204	t0_rp13=$(link_stats_tx_packets_get $rp13)
205
206	ip vrf exec vrf-h1 $MZ -q -p 64 -A 192.0.2.2 -B 198.51.100.2 \
207		-d 1msec -t udp "sp=1024,dp=0-32768"
208
209	t1_rp12=$(link_stats_tx_packets_get $rp12)
210	t1_rp13=$(link_stats_tx_packets_get $rp13)
211
212	let "packets_rp12 = $t1_rp12 - $t0_rp12"
213	let "packets_rp13 = $t1_rp13 - $t0_rp13"
214	multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
215
216	# Restore settings.
217	ip nexthop replace id 103 group 101/102
218	sysctl_restore net.ipv4.fib_multipath_hash_policy
219}
220
221multipath6_l4_test()
222{
223	local desc="$1"
224	local weight_rp12=$2
225	local weight_rp13=$3
226	local t0_rp12 t0_rp13 t1_rp12 t1_rp13
227	local packets_rp12 packets_rp13
228
229	# Transmit multiple flows from h1 to h2 and make sure they are
230	# distributed between both multipath links (rp12 and rp13)
231	# according to the configured weights.
232	sysctl_set net.ipv6.fib_multipath_hash_policy 1
233
234	ip nexthop replace id 106 group 104,$weight_rp12/105,$weight_rp13
235
236	t0_rp12=$(link_stats_tx_packets_get $rp12)
237	t0_rp13=$(link_stats_tx_packets_get $rp13)
238
239	$MZ $h1 -6 -q -p 64 -A 2001:db8:1::2 -B 2001:db8:2::2 \
240		-d 1msec -t udp "sp=1024,dp=0-32768"
241
242	t1_rp12=$(link_stats_tx_packets_get $rp12)
243	t1_rp13=$(link_stats_tx_packets_get $rp13)
244
245	let "packets_rp12 = $t1_rp12 - $t0_rp12"
246	let "packets_rp13 = $t1_rp13 - $t0_rp13"
247	multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
248
249	ip nexthop replace id 106 group 104/105
250
251	sysctl_restore net.ipv6.fib_multipath_hash_policy
252}
253
254multipath6_test()
255{
256	local desc="$1"
257	local weight_rp12=$2
258	local weight_rp13=$3
259	local t0_rp12 t0_rp13 t1_rp12 t1_rp13
260	local packets_rp12 packets_rp13
261
262	ip nexthop replace id 106 group 104,$weight_rp12/105,$weight_rp13
263
264	t0_rp12=$(link_stats_tx_packets_get $rp12)
265	t0_rp13=$(link_stats_tx_packets_get $rp13)
266
267	# Generate 16384 echo requests, each with a random flow label.
268	for _ in $(seq 1 16384); do
269		ip vrf exec vrf-h1 $PING6 2001:db8:2::2 -F 0 -c 1 -q >/dev/null 2>&1
270	done
271
272	t1_rp12=$(link_stats_tx_packets_get $rp12)
273	t1_rp13=$(link_stats_tx_packets_get $rp13)
274
275	let "packets_rp12 = $t1_rp12 - $t0_rp12"
276	let "packets_rp13 = $t1_rp13 - $t0_rp13"
277	multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
278
279	ip nexthop replace id 106 group 104/105
280}
281
282multipath_test()
283{
284	log_info "Running IPv4 multipath tests"
285	multipath4_test "ECMP" 1 1
286	multipath4_test "Weighted MP 2:1" 2 1
287	multipath4_test "Weighted MP 11:45" 11 45
288
289	log_info "Running IPv4 multipath tests with IPv6 link-local nexthops"
290	ip nexthop replace id 101 via fe80:2::22 dev $rp12
291	ip nexthop replace id 102 via fe80:3::23 dev $rp13
292
293	multipath4_test "ECMP" 1 1
294	multipath4_test "Weighted MP 2:1" 2 1
295	multipath4_test "Weighted MP 11:45" 11 45
296
297	ip nexthop replace id 102 via 169.254.3.23 dev $rp13
298	ip nexthop replace id 101 via 169.254.2.22 dev $rp12
299
300	log_info "Running IPv6 multipath tests"
301	multipath6_test "ECMP" 1 1
302	multipath6_test "Weighted MP 2:1" 2 1
303	multipath6_test "Weighted MP 11:45" 11 45
304
305	log_info "Running IPv6 L4 hash multipath tests"
306	multipath6_l4_test "ECMP" 1 1
307	multipath6_l4_test "Weighted MP 2:1" 2 1
308	multipath6_l4_test "Weighted MP 11:45" 11 45
309}
310
311ping_ipv4_blackhole()
312{
313	RET=0
314
315	ip nexthop add id 1001 blackhole
316	ip nexthop add id 1002 group 1001
317
318	ip route replace 198.51.100.0/24 vrf vrf-r1 nhid 1001
319	ping_do $h1 198.51.100.2
320	check_fail $? "ping did not fail when using a blackhole nexthop"
321
322	ip route replace 198.51.100.0/24 vrf vrf-r1 nhid 1002
323	ping_do $h1 198.51.100.2
324	check_fail $? "ping did not fail when using a blackhole nexthop group"
325
326	ip route replace 198.51.100.0/24 vrf vrf-r1 nhid 103
327	ping_do $h1 198.51.100.2
328	check_err $? "ping failed with a valid nexthop"
329
330	log_test "IPv4 blackhole ping"
331
332	ip nexthop del id 1002
333	ip nexthop del id 1001
334}
335
336ping_ipv6_blackhole()
337{
338	RET=0
339
340	ip -6 nexthop add id 1001 blackhole
341	ip nexthop add id 1002 group 1001
342
343	ip route replace 2001:db8:2::/64 vrf vrf-r1 nhid 1001
344	ping6_do $h1 2001:db8:2::2
345	check_fail $? "ping did not fail when using a blackhole nexthop"
346
347	ip route replace 2001:db8:2::/64 vrf vrf-r1 nhid 1002
348	ping6_do $h1 2001:db8:2::2
349	check_fail $? "ping did not fail when using a blackhole nexthop group"
350
351	ip route replace 2001:db8:2::/64 vrf vrf-r1 nhid 106
352	ping6_do $h1 2001:db8:2::2
353	check_err $? "ping failed with a valid nexthop"
354
355	log_test "IPv6 blackhole ping"
356
357	ip nexthop del id 1002
358	ip -6 nexthop del id 1001
359}
360
361setup_prepare()
362{
363	h1=${NETIFS[p1]}
364	rp11=${NETIFS[p2]}
365
366	rp12=${NETIFS[p3]}
367	rp22=${NETIFS[p4]}
368
369	rp13=${NETIFS[p5]}
370	rp23=${NETIFS[p6]}
371
372	rp21=${NETIFS[p7]}
373	h2=${NETIFS[p8]}
374
375	vrf_prepare
376
377	h1_create
378	h2_create
379
380	router1_create
381	router2_create
382
383	forwarding_enable
384}
385
386cleanup()
387{
388	pre_cleanup
389
390	forwarding_restore
391
392	router2_destroy
393	router1_destroy
394
395	h2_destroy
396	h1_destroy
397
398	vrf_cleanup
399}
400
401ping_ipv4()
402{
403	ping_test $h1 198.51.100.2
404}
405
406ping_ipv6()
407{
408	ping6_test $h1 2001:db8:2::2
409}
410
411ip nexthop ls >/dev/null 2>&1
412if [ $? -ne 0 ]; then
413	echo "Nexthop objects not supported; skipping tests"
414	exit 0
415fi
416
417trap cleanup EXIT
418
419setup_prepare
420setup_wait
421routing_nh_obj
422
423tests_run
424
425exit $EXIT_STATUS
426