1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Test traffic distribution when a wECMP route forwards traffic to two GRE
5# tunnels.
6#
7# +-------------------------+
8# | H1                      |
9# |               $h1 +     |
10# |      192.0.2.1/28 |     |
11# +-------------------|-----+
12#                     |
13# +-------------------|------------------------+
14# | SW1               |                        |
15# |              $ol1 +                        |
16# |      192.0.2.2/28                          |
17# |                                            |
18# |  + g1a (gre)          + g1b (gre)          |
19# |    loc=192.0.2.65       loc=192.0.2.81     |
20# |    rem=192.0.2.66 --.   rem=192.0.2.82 --. |
21# |    tos=inherit      |   tos=inherit      | |
22# |  .------------------'                    | |
23# |  |                    .------------------' |
24# |  v                    v                    |
25# |  + $ul1.111 (vlan)    + $ul1.222 (vlan)    |
26# |  | 192.0.2.129/28     | 192.0.2.145/28     |
27# |   \                  /                     |
28# |    \________________/                      |
29# |            |                               |
30# |            + $ul1                          |
31# +------------|-------------------------------+
32#              |
33# +------------|-------------------------------+
34# | SW2        + $ul2                          |
35# |     _______|________                       |
36# |    /                \                      |
37# |   /                  \                     |
38# |  + $ul2.111 (vlan)    + $ul2.222 (vlan)    |
39# |  ^ 192.0.2.130/28     ^ 192.0.2.146/28     |
40# |  |                    |                    |
41# |  |                    '------------------. |
42# |  '------------------.                    | |
43# |  + g2a (gre)        | + g2b (gre)        | |
44# |    loc=192.0.2.66   |   loc=192.0.2.82   | |
45# |    rem=192.0.2.65 --'   rem=192.0.2.81 --' |
46# |    tos=inherit          tos=inherit        |
47# |                                            |
48# |              $ol2 +                        |
49# |     192.0.2.17/28 |                        |
50# +-------------------|------------------------+
51#                     |
52# +-------------------|-----+
53# | H2                |     |
54# |               $h2 +     |
55# |     192.0.2.18/28       |
56# +-------------------------+
57
58ALL_TESTS="
59	ping_ipv4
60	multipath_ipv4
61"
62
63NUM_NETIFS=6
64source lib.sh
65
66h1_create()
67{
68	simple_if_init $h1 192.0.2.1/28 2001:db8:1::1/64
69	ip route add vrf v$h1 192.0.2.16/28 via 192.0.2.2
70}
71
72h1_destroy()
73{
74	ip route del vrf v$h1 192.0.2.16/28 via 192.0.2.2
75	simple_if_fini $h1 192.0.2.1/28
76}
77
78sw1_create()
79{
80	simple_if_init $ol1 192.0.2.2/28
81	__simple_if_init $ul1 v$ol1
82	vlan_create $ul1 111 v$ol1 192.0.2.129/28
83	vlan_create $ul1 222 v$ol1 192.0.2.145/28
84
85	tunnel_create g1a gre 192.0.2.65 192.0.2.66 tos inherit dev v$ol1
86	__simple_if_init g1a v$ol1 192.0.2.65/32
87	ip route add vrf v$ol1 192.0.2.66/32 via 192.0.2.130
88
89	tunnel_create g1b gre 192.0.2.81 192.0.2.82 tos inherit dev v$ol1
90	__simple_if_init g1b v$ol1 192.0.2.81/32
91	ip route add vrf v$ol1 192.0.2.82/32 via 192.0.2.146
92
93	ip route add vrf v$ol1 192.0.2.16/28 \
94	   nexthop dev g1a \
95	   nexthop dev g1b
96}
97
98sw1_destroy()
99{
100	ip route del vrf v$ol1 192.0.2.16/28
101
102	ip route del vrf v$ol1 192.0.2.82/32 via 192.0.2.146
103	__simple_if_fini g1b 192.0.2.81/32
104	tunnel_destroy g1b
105
106	ip route del vrf v$ol1 192.0.2.66/32 via 192.0.2.130
107	__simple_if_fini g1a 192.0.2.65/32
108	tunnel_destroy g1a
109
110	vlan_destroy $ul1 222
111	vlan_destroy $ul1 111
112	__simple_if_fini $ul1
113	simple_if_fini $ol1 192.0.2.2/28
114}
115
116sw2_create()
117{
118	simple_if_init $ol2 192.0.2.17/28
119	__simple_if_init $ul2 v$ol2
120	vlan_create $ul2 111 v$ol2 192.0.2.130/28
121	vlan_create $ul2 222 v$ol2 192.0.2.146/28
122
123	tunnel_create g2a gre 192.0.2.66 192.0.2.65 tos inherit dev v$ol2
124	__simple_if_init g2a v$ol2 192.0.2.66/32
125	ip route add vrf v$ol2 192.0.2.65/32 via 192.0.2.129
126
127	tunnel_create g2b gre 192.0.2.82 192.0.2.81 tos inherit dev v$ol2
128	__simple_if_init g2b v$ol2 192.0.2.82/32
129	ip route add vrf v$ol2 192.0.2.81/32 via 192.0.2.145
130
131	ip route add vrf v$ol2 192.0.2.0/28 \
132	   nexthop dev g2a \
133	   nexthop dev g2b
134
135	tc qdisc add dev $ul2 clsact
136	tc filter add dev $ul2 ingress pref 111 prot 802.1Q \
137	   flower vlan_id 111 action pass
138	tc filter add dev $ul2 ingress pref 222 prot 802.1Q \
139	   flower vlan_id 222 action pass
140}
141
142sw2_destroy()
143{
144	tc qdisc del dev $ul2 clsact
145
146	ip route del vrf v$ol2 192.0.2.0/28
147
148	ip route del vrf v$ol2 192.0.2.81/32 via 192.0.2.145
149	__simple_if_fini g2b 192.0.2.82/32
150	tunnel_destroy g2b
151
152	ip route del vrf v$ol2 192.0.2.65/32 via 192.0.2.129
153	__simple_if_fini g2a 192.0.2.66/32
154	tunnel_destroy g2a
155
156	vlan_destroy $ul2 222
157	vlan_destroy $ul2 111
158	__simple_if_fini $ul2
159	simple_if_fini $ol2 192.0.2.17/28
160}
161
162h2_create()
163{
164	simple_if_init $h2 192.0.2.18/28
165	ip route add vrf v$h2 192.0.2.0/28 via 192.0.2.17
166}
167
168h2_destroy()
169{
170	ip route del vrf v$h2 192.0.2.0/28 via 192.0.2.17
171	simple_if_fini $h2 192.0.2.18/28
172}
173
174setup_prepare()
175{
176	h1=${NETIFS[p1]}
177	ol1=${NETIFS[p2]}
178
179	ul1=${NETIFS[p3]}
180	ul2=${NETIFS[p4]}
181
182	ol2=${NETIFS[p5]}
183	h2=${NETIFS[p6]}
184
185	vrf_prepare
186	h1_create
187	sw1_create
188	sw2_create
189	h2_create
190
191	forwarding_enable
192}
193
194cleanup()
195{
196	pre_cleanup
197
198	forwarding_restore
199
200	h2_destroy
201	sw2_destroy
202	sw1_destroy
203	h1_destroy
204	vrf_cleanup
205}
206
207multipath4_test()
208{
209	local what=$1; shift
210	local weight1=$1; shift
211	local weight2=$1; shift
212
213	sysctl_set net.ipv4.fib_multipath_hash_policy 1
214	ip route replace vrf v$ol1 192.0.2.16/28 \
215	   nexthop dev g1a weight $weight1 \
216	   nexthop dev g1b weight $weight2
217
218	local t0_111=$(tc_rule_stats_get $ul2 111 ingress)
219	local t0_222=$(tc_rule_stats_get $ul2 222 ingress)
220
221	ip vrf exec v$h1 \
222	   $MZ $h1 -q -p 64 -A 192.0.2.1 -B 192.0.2.18 \
223	       -d 1msec -t udp "sp=1024,dp=0-32768"
224
225	local t1_111=$(tc_rule_stats_get $ul2 111 ingress)
226	local t1_222=$(tc_rule_stats_get $ul2 222 ingress)
227
228	local d111=$((t1_111 - t0_111))
229	local d222=$((t1_222 - t0_222))
230	multipath_eval "$what" $weight1 $weight2 $d111 $d222
231
232	ip route replace vrf v$ol1 192.0.2.16/28 \
233	   nexthop dev g1a \
234	   nexthop dev g1b
235	sysctl_restore net.ipv4.fib_multipath_hash_policy
236}
237
238ping_ipv4()
239{
240	ping_test $h1 192.0.2.18
241}
242
243multipath_ipv4()
244{
245	log_info "Running IPv4 multipath tests"
246	multipath4_test "ECMP" 1 1
247	multipath4_test "Weighted MP 2:1" 2 1
248	multipath4_test "Weighted MP 11:45" 11 45
249}
250
251trap cleanup EXIT
252
253setup_prepare
254setup_wait
255tests_run
256
257exit $EXIT_STATUS
258