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