1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Test traffic distribution when there are multiple routes between an IPv4
5# GRE tunnel. The tunnel carries IPv4 traffic between multiple hosts.
6# Multiple routes are in the underlay network. With the default multipath
7# policy, SW2 will only look at the outer IP addresses, hence only a single
8# route would be used.
9#
10# +-------------------------+
11# | H1                      |
12# |               $h1 +     |
13# | 192.0.3.{2-62}/24 |     |
14# +-------------------|-----+
15#                     |
16# +-------------------|------------------------+
17# | SW1               |                        |
18# |              $ol1 +                        |
19# |      192.0.3.1/24                          |
20# |                                            |
21# |  + g1 (gre)                                |
22# |    loc=192.0.2.65                          |
23# |    rem=192.0.2.66 --.                      |
24# |    tos=inherit      |                      |
25# |                     v                      |
26# |                     + $ul1                 |
27# |                     | 192.0.2.129/28       |
28# +---------------------|----------------------+
29#                       |
30# +---------------------|----------------------+
31# | SW2                 |                      |
32# |               $ul21 +                      |
33# |      192.0.2.130/28                        |
34# |                   |                        |
35# !   ________________|_____                   |
36# |  /                      \                  |
37# |  |                      |                  |
38# |  + $ul22.111 (vlan)     + $ul22.222 (vlan) |
39# |  | 192.0.2.145/28       | 192.0.2.161/28   |
40# |  |                      |                  |
41# +--|----------------------|------------------+
42#    |                      |
43# +--|----------------------|------------------+
44# |  |                      |                  |
45# |  + $ul32.111 (vlan)     + $ul32.222 (vlan) |
46# |  | 192.0.2.146/28       | 192.0.2.162/28   |
47# |  |                      |                  |
48# |  \______________________/                  |
49# |                   |                        |
50# |                   |                        |
51# |               $ul31 +                      |
52# |      192.0.2.177/28 |                  SW3 |
53# +---------------------|----------------------+
54#                       |
55# +---------------------|----------------------+
56# |                     + $ul4                 |
57# |                     ^ 192.0.2.178/28       |
58# |                     |                      |
59# |  + g2 (gre)         |                      |
60# |    loc=192.0.2.66   |                      |
61# |    rem=192.0.2.65 --'                      |
62# |    tos=inherit                             |
63# |                                            |
64# |               $ol4 +                       |
65# |       192.0.4.1/24 |                   SW4 |
66# +--------------------|-----------------------+
67#                      |
68# +--------------------|---------+
69# |                    |         |
70# |                $h2 +         |
71# |  192.0.4.{2-62}/24        H2 |
72# +------------------------------+
73
74ALL_TESTS="
75	ping_ipv4
76	multipath_ipv4
77"
78
79NUM_NETIFS=10
80source lib.sh
81
82h1_create()
83{
84	simple_if_init $h1 192.0.3.2/24
85	ip route add vrf v$h1 192.0.4.0/24 via 192.0.3.1
86}
87
88h1_destroy()
89{
90	ip route del vrf v$h1 192.0.4.0/24 via 192.0.3.1
91	simple_if_fini $h1 192.0.3.2/24
92}
93
94sw1_create()
95{
96	simple_if_init $ol1 192.0.3.1/24
97	__simple_if_init $ul1 v$ol1 192.0.2.129/28
98
99	tunnel_create g1 gre 192.0.2.65 192.0.2.66 tos inherit dev v$ol1
100	__simple_if_init g1 v$ol1 192.0.2.65/32
101	ip route add vrf v$ol1 192.0.2.66/32 via 192.0.2.130
102
103	ip route add vrf v$ol1 192.0.4.0/24 nexthop dev g1
104}
105
106sw1_destroy()
107{
108	ip route del vrf v$ol1 192.0.4.0/24
109
110	ip route del vrf v$ol1 192.0.2.66/32
111	__simple_if_fini g1 192.0.2.65/32
112	tunnel_destroy g1
113
114	__simple_if_fini $ul1 192.0.2.129/28
115	simple_if_fini $ol1 192.0.3.1/24
116}
117
118sw2_create()
119{
120	simple_if_init $ul21 192.0.2.130/28
121	__simple_if_init $ul22 v$ul21
122	vlan_create $ul22 111 v$ul21 192.0.2.145/28
123	vlan_create $ul22 222 v$ul21 192.0.2.161/28
124
125	ip route add vrf v$ul21 192.0.2.65/32 via 192.0.2.129
126	ip route add vrf v$ul21 192.0.2.66/32 \
127	   nexthop via 192.0.2.146 \
128	   nexthop via 192.0.2.162
129}
130
131sw2_destroy()
132{
133	ip route del vrf v$ul21 192.0.2.66/32
134	ip route del vrf v$ul21 192.0.2.65/32
135
136	vlan_destroy $ul22 222
137	vlan_destroy $ul22 111
138	__simple_if_fini $ul22
139	simple_if_fini $ul21 192.0.2.130/28
140}
141
142sw3_create()
143{
144	simple_if_init $ul31 192.0.2.177/28
145	__simple_if_init $ul32 v$ul31
146	vlan_create $ul32 111 v$ul31 192.0.2.146/28
147	vlan_create $ul32 222 v$ul31 192.0.2.162/28
148
149	ip route add vrf v$ul31 192.0.2.66/32 via 192.0.2.178
150	ip route add vrf v$ul31 192.0.2.65/32 \
151	   nexthop via 192.0.2.145 \
152	   nexthop via 192.0.2.161
153
154	tc qdisc add dev $ul32 clsact
155	tc filter add dev $ul32 ingress pref 111 prot 802.1Q \
156	   flower vlan_id 111 action pass
157	tc filter add dev $ul32 ingress pref 222 prot 802.1Q \
158	   flower vlan_id 222 action pass
159}
160
161sw3_destroy()
162{
163	tc qdisc del dev $ul32 clsact
164
165	ip route del vrf v$ul31 192.0.2.65/32
166	ip route del vrf v$ul31 192.0.2.66/32
167
168	vlan_destroy $ul32 222
169	vlan_destroy $ul32 111
170	__simple_if_fini $ul32
171	simple_if_fini $ul31 192.0.2.177/28
172}
173
174sw4_create()
175{
176	simple_if_init $ol4 192.0.4.1/24
177	__simple_if_init $ul4 v$ol4 192.0.2.178/28
178
179	tunnel_create g2 gre 192.0.2.66 192.0.2.65 tos inherit dev v$ol4
180	__simple_if_init g2 v$ol4 192.0.2.66/32
181	ip route add vrf v$ol4 192.0.2.65/32 via 192.0.2.177
182
183	ip route add vrf v$ol4 192.0.3.0/24 nexthop dev g2
184}
185
186sw4_destroy()
187{
188	ip route del vrf v$ol4 192.0.3.0/24
189
190	ip route del vrf v$ol4 192.0.2.65/32
191	__simple_if_fini g2 192.0.2.66/32
192	tunnel_destroy g2
193
194	__simple_if_fini $ul4 192.0.2.178/28
195	simple_if_fini $ol4 192.0.4.1/24
196}
197
198h2_create()
199{
200	simple_if_init $h2 192.0.4.2/24
201	ip route add vrf v$h2 192.0.3.0/24 via 192.0.4.1
202}
203
204h2_destroy()
205{
206	ip route del vrf v$h2 192.0.3.0/24 via 192.0.4.1
207	simple_if_fini $h2 192.0.4.2/24
208}
209
210setup_prepare()
211{
212	h1=${NETIFS[p1]}
213
214	ol1=${NETIFS[p2]}
215	ul1=${NETIFS[p3]}
216
217	ul21=${NETIFS[p4]}
218	ul22=${NETIFS[p5]}
219
220	ul32=${NETIFS[p6]}
221	ul31=${NETIFS[p7]}
222
223	ul4=${NETIFS[p8]}
224	ol4=${NETIFS[p9]}
225
226	h2=${NETIFS[p10]}
227
228	vrf_prepare
229	h1_create
230	sw1_create
231	sw2_create
232	sw3_create
233	sw4_create
234	h2_create
235
236	forwarding_enable
237}
238
239cleanup()
240{
241	pre_cleanup
242
243	forwarding_restore
244
245	h2_destroy
246	sw4_destroy
247	sw3_destroy
248	sw2_destroy
249	sw1_destroy
250	h1_destroy
251	vrf_cleanup
252}
253
254multipath4_test()
255{
256	local what=$1; shift
257	local weight1=$1; shift
258	local weight2=$1; shift
259
260	sysctl_set net.ipv4.fib_multipath_hash_policy 2
261	ip route replace vrf v$ul21 192.0.2.66/32 \
262	   nexthop via 192.0.2.146 weight $weight1 \
263	   nexthop via 192.0.2.162 weight $weight2
264
265	local t0_111=$(tc_rule_stats_get $ul32 111 ingress)
266	local t0_222=$(tc_rule_stats_get $ul32 222 ingress)
267
268	ip vrf exec v$h1 \
269	   $MZ $h1 -q -p 64 -A "192.0.3.2-192.0.3.62" -B "192.0.4.2-192.0.4.62" \
270	       -d $MZ_DELAY -c 50 -t udp "sp=1024,dp=1024"
271	sleep 1
272
273	local t1_111=$(tc_rule_stats_get $ul32 111 ingress)
274	local t1_222=$(tc_rule_stats_get $ul32 222 ingress)
275
276	local d111=$((t1_111 - t0_111))
277	local d222=$((t1_222 - t0_222))
278	multipath_eval "$what" $weight1 $weight2 $d111 $d222
279
280	ip route replace vrf v$ul21 192.0.2.66/32 \
281	   nexthop via 192.0.2.146 \
282	   nexthop via 192.0.2.162
283	sysctl_restore net.ipv4.fib_multipath_hash_policy
284}
285
286ping_ipv4()
287{
288	ping_test $h1 192.0.4.2
289}
290
291multipath_ipv4()
292{
293	log_info "Running IPv4 over GRE over IPv4 multipath tests"
294	multipath4_test "ECMP" 1 1
295	multipath4_test "Weighted MP 2:1" 2 1
296	multipath4_test "Weighted MP 11:45" 11 45
297}
298
299trap cleanup EXIT
300
301setup_prepare
302setup_wait
303tests_run
304
305exit $EXIT_STATUS
306