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	tc qdisc add dev $ul1 clsact
98	tc filter add dev $ul1 egress pref 111 prot ipv4 \
99	   flower dst_ip 192.0.2.66 action pass
100	tc filter add dev $ul1 egress pref 222 prot ipv4 \
101	   flower dst_ip 192.0.2.82 action pass
102}
103
104sw1_destroy()
105{
106	tc qdisc del dev $ul1 clsact
107
108	ip route del vrf v$ol1 192.0.2.16/28
109
110	ip route del vrf v$ol1 192.0.2.82/32 via 192.0.2.146
111	__simple_if_fini g1b 192.0.2.81/32
112	tunnel_destroy g1b
113
114	ip route del vrf v$ol1 192.0.2.66/32 via 192.0.2.130
115	__simple_if_fini g1a 192.0.2.65/32
116	tunnel_destroy g1a
117
118	vlan_destroy $ul1 222
119	vlan_destroy $ul1 111
120	__simple_if_fini $ul1
121	simple_if_fini $ol1 192.0.2.2/28
122}
123
124sw2_create()
125{
126	simple_if_init $ol2 192.0.2.17/28
127	__simple_if_init $ul2 v$ol2
128	vlan_create $ul2 111 v$ol2 192.0.2.130/28
129	vlan_create $ul2 222 v$ol2 192.0.2.146/28
130
131	tunnel_create g2a gre 192.0.2.66 192.0.2.65 tos inherit dev v$ol2
132	__simple_if_init g2a v$ol2 192.0.2.66/32
133	ip route add vrf v$ol2 192.0.2.65/32 via 192.0.2.129
134
135	tunnel_create g2b gre 192.0.2.82 192.0.2.81 tos inherit dev v$ol2
136	__simple_if_init g2b v$ol2 192.0.2.82/32
137	ip route add vrf v$ol2 192.0.2.81/32 via 192.0.2.145
138
139	ip route add vrf v$ol2 192.0.2.0/28 \
140	   nexthop dev g2a \
141	   nexthop dev g2b
142}
143
144sw2_destroy()
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
192cleanup()
193{
194	pre_cleanup
195
196	h2_destroy
197	sw2_destroy
198	sw1_destroy
199	h1_destroy
200	vrf_cleanup
201}
202
203multipath4_test()
204{
205	local what=$1; shift
206	local weight1=$1; shift
207	local weight2=$1; shift
208
209	sysctl_set net.ipv4.fib_multipath_hash_policy 1
210	ip route replace vrf v$ol1 192.0.2.16/28 \
211	   nexthop dev g1a weight $weight1 \
212	   nexthop dev g1b weight $weight2
213
214	local t0_111=$(tc_rule_stats_get $ul1 111 egress)
215	local t0_222=$(tc_rule_stats_get $ul1 222 egress)
216
217	ip vrf exec v$h1 \
218	   $MZ $h1 -q -p 64 -A 192.0.2.1 -B 192.0.2.18 \
219	       -d 1msec -t udp "sp=1024,dp=0-32768"
220
221	local t1_111=$(tc_rule_stats_get $ul1 111 egress)
222	local t1_222=$(tc_rule_stats_get $ul1 222 egress)
223
224	local d111=$((t1_111 - t0_111))
225	local d222=$((t1_222 - t0_222))
226	multipath_eval "$what" $weight1 $weight2 $d111 $d222
227
228	ip route replace vrf v$ol1 192.0.2.16/28 \
229	   nexthop dev g1a \
230	   nexthop dev g1b
231	sysctl_restore net.ipv4.fib_multipath_hash_policy
232}
233
234ping_ipv4()
235{
236	ping_test $h1 192.0.2.18
237}
238
239multipath_ipv4()
240{
241	log_info "Running IPv4 multipath tests"
242	multipath4_test "ECMP" 1 1
243	multipath4_test "Weighted MP 2:1" 2 1
244	multipath4_test "Weighted MP 11:45" 11 45
245}
246
247trap cleanup EXIT
248
249setup_prepare
250setup_wait
251tests_run
252
253exit $EXIT_STATUS
254