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