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