1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <netinet/in.h> |
3 | |
4 | #include "network_helpers.h" |
5 | #include "test_progs.h" |
6 | |
7 | #define BPF_FILE "test_lwt_ip_encap.bpf.o" |
8 | |
9 | #define NETNS_NAME_SIZE 32 |
10 | #define NETNS_BASE "ns-lwt-ip-encap" |
11 | |
12 | #define IP4_ADDR_1 "172.16.1.100" |
13 | #define IP4_ADDR_2 "172.16.2.100" |
14 | #define IP4_ADDR_3 "172.16.3.100" |
15 | #define IP4_ADDR_4 "172.16.4.100" |
16 | #define IP4_ADDR_5 "172.16.5.100" |
17 | #define IP4_ADDR_6 "172.16.6.100" |
18 | #define IP4_ADDR_7 "172.16.7.100" |
19 | #define IP4_ADDR_8 "172.16.8.100" |
20 | #define IP4_ADDR_GRE "172.16.16.100" |
21 | |
22 | #define IP4_ADDR_SRC IP4_ADDR_1 |
23 | #define IP4_ADDR_DST IP4_ADDR_4 |
24 | |
25 | #define IP6_ADDR_1 "fb01::1" |
26 | #define IP6_ADDR_2 "fb02::1" |
27 | #define IP6_ADDR_3 "fb03::1" |
28 | #define IP6_ADDR_4 "fb04::1" |
29 | #define IP6_ADDR_5 "fb05::1" |
30 | #define IP6_ADDR_6 "fb06::1" |
31 | #define IP6_ADDR_7 "fb07::1" |
32 | #define IP6_ADDR_8 "fb08::1" |
33 | #define IP6_ADDR_GRE "fb10::1" |
34 | |
35 | #define IP6_ADDR_SRC IP6_ADDR_1 |
36 | #define IP6_ADDR_DST IP6_ADDR_4 |
37 | |
38 | /* Setup/topology: |
39 | * |
40 | * NS1 NS2 NS3 |
41 | * veth1 <---> veth2 veth3 <---> veth4 (the top route) |
42 | * veth5 <---> veth6 veth7 <---> veth8 (the bottom route) |
43 | * |
44 | * Each vethN gets IP[4|6]_ADDR_N address. |
45 | * |
46 | * IP*_ADDR_SRC = IP*_ADDR_1 |
47 | * IP*_ADDR_DST = IP*_ADDR_4 |
48 | * |
49 | * All tests test pings from IP*_ADDR__SRC to IP*_ADDR_DST. |
50 | * |
51 | * By default, routes are configured to allow packets to go |
52 | * IP*_ADDR_1 <=> IP*_ADDR_2 <=> IP*_ADDR_3 <=> IP*_ADDR_4 (the top route). |
53 | * |
54 | * A GRE device is installed in NS3 with IP*_ADDR_GRE, and |
55 | * NS1/NS2 are configured to route packets to IP*_ADDR_GRE via IP*_ADDR_8 |
56 | * (the bottom route). |
57 | * |
58 | * Tests: |
59 | * |
60 | * 1. Routes NS2->IP*_ADDR_DST are brought down, so the only way a ping |
61 | * from IP*_ADDR_SRC to IP*_ADDR_DST can work is via IP*_ADDR_GRE. |
62 | * |
63 | * 2a. In an egress test, a bpf LWT_XMIT program is installed on veth1 |
64 | * that encaps the packets with an IP/GRE header to route to IP*_ADDR_GRE. |
65 | * |
66 | * ping: SRC->[encap at veth1:egress]->GRE:decap->DST |
67 | * ping replies go DST->SRC directly |
68 | * |
69 | * 2b. In an ingress test, a bpf LWT_IN program is installed on veth2 |
70 | * that encaps the packets with an IP/GRE header to route to IP*_ADDR_GRE. |
71 | * |
72 | * ping: SRC->[encap at veth2:ingress]->GRE:decap->DST |
73 | * ping replies go DST->SRC directly |
74 | */ |
75 | |
76 | static int create_ns(char *name, size_t name_sz) |
77 | { |
78 | if (!name) |
79 | goto fail; |
80 | |
81 | if (!ASSERT_OK(append_tid(name, name_sz), "append TID" )) |
82 | goto fail; |
83 | |
84 | SYS(fail, "ip netns add %s" , name); |
85 | |
86 | /* rp_filter gets confused by what these tests are doing, so disable it */ |
87 | SYS(fail, "ip netns exec %s sysctl -wq net.ipv4.conf.all.rp_filter=0" , name); |
88 | SYS(fail, "ip netns exec %s sysctl -wq net.ipv4.conf.default.rp_filter=0" , name); |
89 | /* Disable IPv6 DAD because it sometimes takes too long and fails tests */ |
90 | SYS(fail, "ip netns exec %s sysctl -wq net.ipv6.conf.all.accept_dad=0" , name); |
91 | SYS(fail, "ip netns exec %s sysctl -wq net.ipv6.conf.default.accept_dad=0" , name); |
92 | |
93 | return 0; |
94 | fail: |
95 | return -1; |
96 | } |
97 | |
98 | static int set_top_addr(const char *ns1, const char *ns2, const char *ns3) |
99 | { |
100 | SYS(fail, "ip -n %s a add %s/24 dev veth1" , ns1, IP4_ADDR_1); |
101 | SYS(fail, "ip -n %s a add %s/24 dev veth2" , ns2, IP4_ADDR_2); |
102 | SYS(fail, "ip -n %s a add %s/24 dev veth3" , ns2, IP4_ADDR_3); |
103 | SYS(fail, "ip -n %s a add %s/24 dev veth4" , ns3, IP4_ADDR_4); |
104 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth1" , ns1, IP6_ADDR_1); |
105 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth2" , ns2, IP6_ADDR_2); |
106 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth3" , ns2, IP6_ADDR_3); |
107 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth4" , ns3, IP6_ADDR_4); |
108 | |
109 | SYS(fail, "ip -n %s link set dev veth1 up" , ns1); |
110 | SYS(fail, "ip -n %s link set dev veth2 up" , ns2); |
111 | SYS(fail, "ip -n %s link set dev veth3 up" , ns2); |
112 | SYS(fail, "ip -n %s link set dev veth4 up" , ns3); |
113 | |
114 | return 0; |
115 | fail: |
116 | return 1; |
117 | } |
118 | |
119 | static int set_bottom_addr(const char *ns1, const char *ns2, const char *ns3) |
120 | { |
121 | SYS(fail, "ip -n %s a add %s/24 dev veth5" , ns1, IP4_ADDR_5); |
122 | SYS(fail, "ip -n %s a add %s/24 dev veth6" , ns2, IP4_ADDR_6); |
123 | SYS(fail, "ip -n %s a add %s/24 dev veth7" , ns2, IP4_ADDR_7); |
124 | SYS(fail, "ip -n %s a add %s/24 dev veth8" , ns3, IP4_ADDR_8); |
125 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth5" , ns1, IP6_ADDR_5); |
126 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth6" , ns2, IP6_ADDR_6); |
127 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth7" , ns2, IP6_ADDR_7); |
128 | SYS(fail, "ip -n %s -6 a add %s/128 dev veth8" , ns3, IP6_ADDR_8); |
129 | |
130 | SYS(fail, "ip -n %s link set dev veth5 up" , ns1); |
131 | SYS(fail, "ip -n %s link set dev veth6 up" , ns2); |
132 | SYS(fail, "ip -n %s link set dev veth7 up" , ns2); |
133 | SYS(fail, "ip -n %s link set dev veth8 up" , ns3); |
134 | |
135 | return 0; |
136 | fail: |
137 | return 1; |
138 | } |
139 | |
140 | static int configure_vrf(const char *ns1, const char *ns2) |
141 | { |
142 | if (!ns1 || !ns2) |
143 | goto fail; |
144 | |
145 | SYS(fail, "ip -n %s link add red type vrf table 1001" , ns1); |
146 | SYS(fail, "ip -n %s link set red up" , ns1); |
147 | SYS(fail, "ip -n %s route add table 1001 unreachable default metric 8192" , ns1); |
148 | SYS(fail, "ip -n %s -6 route add table 1001 unreachable default metric 8192" , ns1); |
149 | SYS(fail, "ip -n %s link set veth1 vrf red" , ns1); |
150 | SYS(fail, "ip -n %s link set veth5 vrf red" , ns1); |
151 | |
152 | SYS(fail, "ip -n %s link add red type vrf table 1001" , ns2); |
153 | SYS(fail, "ip -n %s link set red up" , ns2); |
154 | SYS(fail, "ip -n %s route add table 1001 unreachable default metric 8192" , ns2); |
155 | SYS(fail, "ip -n %s -6 route add table 1001 unreachable default metric 8192" , ns2); |
156 | SYS(fail, "ip -n %s link set veth2 vrf red" , ns2); |
157 | SYS(fail, "ip -n %s link set veth3 vrf red" , ns2); |
158 | SYS(fail, "ip -n %s link set veth6 vrf red" , ns2); |
159 | SYS(fail, "ip -n %s link set veth7 vrf red" , ns2); |
160 | |
161 | return 0; |
162 | fail: |
163 | return -1; |
164 | } |
165 | |
166 | static int configure_ns1(const char *ns1, const char *vrf) |
167 | { |
168 | struct nstoken *nstoken = NULL; |
169 | |
170 | if (!ns1 || !vrf) |
171 | goto fail; |
172 | |
173 | nstoken = open_netns(ns1); |
174 | if (!ASSERT_OK_PTR(nstoken, "open ns1" )) |
175 | goto fail; |
176 | |
177 | /* Top route */ |
178 | SYS(fail, "ip route add %s/32 dev veth1 %s" , IP4_ADDR_2, vrf); |
179 | SYS(fail, "ip route add default dev veth1 via %s %s" , IP4_ADDR_2, vrf); |
180 | SYS(fail, "ip -6 route add %s/128 dev veth1 %s" , IP6_ADDR_2, vrf); |
181 | SYS(fail, "ip -6 route add default dev veth1 via %s %s" , IP6_ADDR_2, vrf); |
182 | /* Bottom route */ |
183 | SYS(fail, "ip route add %s/32 dev veth5 %s" , IP4_ADDR_6, vrf); |
184 | SYS(fail, "ip route add %s/32 dev veth5 via %s %s" , IP4_ADDR_7, IP4_ADDR_6, vrf); |
185 | SYS(fail, "ip route add %s/32 dev veth5 via %s %s" , IP4_ADDR_8, IP4_ADDR_6, vrf); |
186 | SYS(fail, "ip -6 route add %s/128 dev veth5 %s" , IP6_ADDR_6, vrf); |
187 | SYS(fail, "ip -6 route add %s/128 dev veth5 via %s %s" , IP6_ADDR_7, IP6_ADDR_6, vrf); |
188 | SYS(fail, "ip -6 route add %s/128 dev veth5 via %s %s" , IP6_ADDR_8, IP6_ADDR_6, vrf); |
189 | |
190 | close_netns(nstoken); |
191 | return 0; |
192 | fail: |
193 | close_netns(nstoken); |
194 | return -1; |
195 | } |
196 | |
197 | static int configure_ns2(const char *ns2, const char *vrf) |
198 | { |
199 | struct nstoken *nstoken = NULL; |
200 | |
201 | if (!ns2 || !vrf) |
202 | goto fail; |
203 | |
204 | nstoken = open_netns(ns2); |
205 | if (!ASSERT_OK_PTR(nstoken, "open ns2" )) |
206 | goto fail; |
207 | |
208 | SYS(fail, "ip netns exec %s sysctl -wq net.ipv4.ip_forward=1" , ns2); |
209 | SYS(fail, "ip netns exec %s sysctl -wq net.ipv6.conf.all.forwarding=1" , ns2); |
210 | |
211 | /* Top route */ |
212 | SYS(fail, "ip route add %s/32 dev veth2 %s" , IP4_ADDR_1, vrf); |
213 | SYS(fail, "ip route add %s/32 dev veth3 %s" , IP4_ADDR_4, vrf); |
214 | SYS(fail, "ip -6 route add %s/128 dev veth2 %s" , IP6_ADDR_1, vrf); |
215 | SYS(fail, "ip -6 route add %s/128 dev veth3 %s" , IP6_ADDR_4, vrf); |
216 | /* Bottom route */ |
217 | SYS(fail, "ip route add %s/32 dev veth6 %s" , IP4_ADDR_5, vrf); |
218 | SYS(fail, "ip route add %s/32 dev veth7 %s" , IP4_ADDR_8, vrf); |
219 | SYS(fail, "ip -6 route add %s/128 dev veth6 %s" , IP6_ADDR_5, vrf); |
220 | SYS(fail, "ip -6 route add %s/128 dev veth7 %s" , IP6_ADDR_8, vrf); |
221 | |
222 | close_netns(nstoken); |
223 | return 0; |
224 | fail: |
225 | close_netns(nstoken); |
226 | return -1; |
227 | } |
228 | |
229 | static int configure_ns3(const char *ns3) |
230 | { |
231 | struct nstoken *nstoken = NULL; |
232 | |
233 | if (!ns3) |
234 | goto fail; |
235 | |
236 | nstoken = open_netns(ns3); |
237 | if (!ASSERT_OK_PTR(nstoken, "open ns3" )) |
238 | goto fail; |
239 | |
240 | /* Top route */ |
241 | SYS(fail, "ip route add %s/32 dev veth4" , IP4_ADDR_3); |
242 | SYS(fail, "ip route add %s/32 dev veth4 via %s" , IP4_ADDR_1, IP4_ADDR_3); |
243 | SYS(fail, "ip route add %s/32 dev veth4 via %s" , IP4_ADDR_2, IP4_ADDR_3); |
244 | SYS(fail, "ip -6 route add %s/128 dev veth4" , IP6_ADDR_3); |
245 | SYS(fail, "ip -6 route add %s/128 dev veth4 via %s" , IP6_ADDR_1, IP6_ADDR_3); |
246 | SYS(fail, "ip -6 route add %s/128 dev veth4 via %s" , IP6_ADDR_2, IP6_ADDR_3); |
247 | /* Bottom route */ |
248 | SYS(fail, "ip route add %s/32 dev veth8" , IP4_ADDR_7); |
249 | SYS(fail, "ip route add %s/32 dev veth8 via %s" , IP4_ADDR_5, IP4_ADDR_7); |
250 | SYS(fail, "ip route add %s/32 dev veth8 via %s" , IP4_ADDR_6, IP4_ADDR_7); |
251 | SYS(fail, "ip -6 route add %s/128 dev veth8" , IP6_ADDR_7); |
252 | SYS(fail, "ip -6 route add %s/128 dev veth8 via %s" , IP6_ADDR_5, IP6_ADDR_7); |
253 | SYS(fail, "ip -6 route add %s/128 dev veth8 via %s" , IP6_ADDR_6, IP6_ADDR_7); |
254 | |
255 | /* Configure IPv4 GRE device */ |
256 | SYS(fail, "ip tunnel add gre_dev mode gre remote %s local %s ttl 255" , |
257 | IP4_ADDR_1, IP4_ADDR_GRE); |
258 | SYS(fail, "ip link set gre_dev up" ); |
259 | SYS(fail, "ip a add %s dev gre_dev" , IP4_ADDR_GRE); |
260 | |
261 | /* Configure IPv6 GRE device */ |
262 | SYS(fail, "ip tunnel add gre6_dev mode ip6gre remote %s local %s ttl 255" , |
263 | IP6_ADDR_1, IP6_ADDR_GRE); |
264 | SYS(fail, "ip link set gre6_dev up" ); |
265 | SYS(fail, "ip a add %s dev gre6_dev" , IP6_ADDR_GRE); |
266 | |
267 | close_netns(nstoken); |
268 | return 0; |
269 | fail: |
270 | close_netns(nstoken); |
271 | return -1; |
272 | } |
273 | |
274 | static int setup_network(char *ns1, char *ns2, char *ns3, const char *vrf) |
275 | { |
276 | if (!ns1 || !ns2 || !ns3 || !vrf) |
277 | goto fail; |
278 | |
279 | SYS(fail, "ip -n %s link add veth1 type veth peer name veth2 netns %s" , ns1, ns2); |
280 | SYS(fail, "ip -n %s link add veth3 type veth peer name veth4 netns %s" , ns2, ns3); |
281 | SYS(fail, "ip -n %s link add veth5 type veth peer name veth6 netns %s" , ns1, ns2); |
282 | SYS(fail, "ip -n %s link add veth7 type veth peer name veth8 netns %s" , ns2, ns3); |
283 | |
284 | if (vrf[0]) { |
285 | if (!ASSERT_OK(configure_vrf(ns1, ns2), "configure vrf" )) |
286 | goto fail; |
287 | } |
288 | if (!ASSERT_OK(set_top_addr(ns1, ns2, ns3), "set top addresses" )) |
289 | goto fail; |
290 | |
291 | if (!ASSERT_OK(set_bottom_addr(ns1, ns2, ns3), "set bottom addresses" )) |
292 | goto fail; |
293 | |
294 | if (!ASSERT_OK(configure_ns1(ns1, vrf), "configure ns1 routes" )) |
295 | goto fail; |
296 | |
297 | if (!ASSERT_OK(configure_ns2(ns2, vrf), "configure ns2 routes" )) |
298 | goto fail; |
299 | |
300 | if (!ASSERT_OK(configure_ns3(ns3), "configure ns3 routes" )) |
301 | goto fail; |
302 | |
303 | /* Link bottom route to the GRE tunnels */ |
304 | SYS(fail, "ip -n %s route add %s/32 dev veth5 via %s %s" , |
305 | ns1, IP4_ADDR_GRE, IP4_ADDR_6, vrf); |
306 | SYS(fail, "ip -n %s route add %s/32 dev veth7 via %s %s" , |
307 | ns2, IP4_ADDR_GRE, IP4_ADDR_8, vrf); |
308 | SYS(fail, "ip -n %s -6 route add %s/128 dev veth5 via %s %s" , |
309 | ns1, IP6_ADDR_GRE, IP6_ADDR_6, vrf); |
310 | SYS(fail, "ip -n %s -6 route add %s/128 dev veth7 via %s %s" , |
311 | ns2, IP6_ADDR_GRE, IP6_ADDR_8, vrf); |
312 | |
313 | return 0; |
314 | fail: |
315 | return -1; |
316 | } |
317 | |
318 | static int remove_routes_to_gredev(const char *ns1, const char *ns2, const char *vrf) |
319 | { |
320 | SYS(fail, "ip -n %s route del %s dev veth5 %s" , ns1, IP4_ADDR_GRE, vrf); |
321 | SYS(fail, "ip -n %s route del %s dev veth7 %s" , ns2, IP4_ADDR_GRE, vrf); |
322 | SYS(fail, "ip -n %s -6 route del %s/128 dev veth5 %s" , ns1, IP6_ADDR_GRE, vrf); |
323 | SYS(fail, "ip -n %s -6 route del %s/128 dev veth7 %s" , ns2, IP6_ADDR_GRE, vrf); |
324 | |
325 | return 0; |
326 | fail: |
327 | return -1; |
328 | } |
329 | |
330 | static int add_unreachable_routes_to_gredev(const char *ns1, const char *ns2, const char *vrf) |
331 | { |
332 | SYS(fail, "ip -n %s route add unreachable %s/32 %s" , ns1, IP4_ADDR_GRE, vrf); |
333 | SYS(fail, "ip -n %s route add unreachable %s/32 %s" , ns2, IP4_ADDR_GRE, vrf); |
334 | SYS(fail, "ip -n %s -6 route add unreachable %s/128 %s" , ns1, IP6_ADDR_GRE, vrf); |
335 | SYS(fail, "ip -n %s -6 route add unreachable %s/128 %s" , ns2, IP6_ADDR_GRE, vrf); |
336 | |
337 | return 0; |
338 | fail: |
339 | return -1; |
340 | } |
341 | |
342 | #define GSO_SIZE 5000 |
343 | #define GSO_TCP_PORT 9000 |
344 | /* This tests the fix from commit ea0371f78799 ("net: fix GSO in bpf_lwt_push_ip_encap") */ |
345 | static int test_gso_fix(const char *ns1, const char *ns3, int family) |
346 | { |
347 | const char *ip_addr = family == AF_INET ? IP4_ADDR_DST : IP6_ADDR_DST; |
348 | char gso_packet[GSO_SIZE] = {}; |
349 | struct nstoken *nstoken = NULL; |
350 | int sfd, cfd, afd; |
351 | ssize_t bytes; |
352 | int ret = -1; |
353 | |
354 | if (!ns1 || !ns3) |
355 | return ret; |
356 | |
357 | nstoken = open_netns(ns3); |
358 | if (!ASSERT_OK_PTR(nstoken, "open ns3" )) |
359 | return ret; |
360 | |
361 | sfd = start_server_str(family, SOCK_STREAM, ip_addr, GSO_TCP_PORT, NULL); |
362 | if (!ASSERT_OK_FD(sfd, "start server" )) |
363 | goto close_netns; |
364 | |
365 | close_netns(nstoken); |
366 | |
367 | nstoken = open_netns(ns1); |
368 | if (!ASSERT_OK_PTR(nstoken, "open ns1" )) |
369 | goto close_server; |
370 | |
371 | cfd = connect_to_addr_str(family, SOCK_STREAM, ip_addr, GSO_TCP_PORT, NULL); |
372 | if (!ASSERT_OK_FD(cfd, "connect to server" )) |
373 | goto close_server; |
374 | |
375 | close_netns(nstoken); |
376 | nstoken = NULL; |
377 | |
378 | afd = accept(sfd, NULL, NULL); |
379 | if (!ASSERT_OK_FD(afd, "accept" )) |
380 | goto close_client; |
381 | |
382 | /* Send a packet larger than MTU */ |
383 | bytes = send(cfd, gso_packet, GSO_SIZE, 0); |
384 | if (!ASSERT_EQ(bytes, GSO_SIZE, "send packet" )) |
385 | goto close_accept; |
386 | |
387 | /* Verify we received all expected bytes */ |
388 | bytes = read(afd, gso_packet, GSO_SIZE); |
389 | if (!ASSERT_EQ(bytes, GSO_SIZE, "receive packet" )) |
390 | goto close_accept; |
391 | |
392 | ret = 0; |
393 | |
394 | close_accept: |
395 | close(afd); |
396 | close_client: |
397 | close(cfd); |
398 | close_server: |
399 | close(sfd); |
400 | close_netns: |
401 | close_netns(nstoken); |
402 | |
403 | return ret; |
404 | } |
405 | |
406 | static int check_ping_ok(const char *ns1) |
407 | { |
408 | SYS(fail, "ip netns exec %s ping -c 1 -W1 -I veth1 %s > /dev/null" , ns1, IP4_ADDR_DST); |
409 | SYS(fail, "ip netns exec %s ping6 -c 1 -W1 -I veth1 %s > /dev/null" , ns1, IP6_ADDR_DST); |
410 | return 0; |
411 | fail: |
412 | return -1; |
413 | } |
414 | |
415 | static int check_ping_fails(const char *ns1) |
416 | { |
417 | int ret; |
418 | |
419 | ret = SYS_NOFAIL("ip netns exec %s ping -c 1 -W1 -I veth1 %s" , ns1, IP4_ADDR_DST); |
420 | if (!ret) |
421 | return -1; |
422 | |
423 | ret = SYS_NOFAIL("ip netns exec %s ping6 -c 1 -W1 -I veth1 %s" , ns1, IP6_ADDR_DST); |
424 | if (!ret) |
425 | return -1; |
426 | |
427 | return 0; |
428 | } |
429 | |
430 | #define EGRESS true |
431 | #define INGRESS false |
432 | #define IPV4_ENCAP true |
433 | #define IPV6_ENCAP false |
434 | static void lwt_ip_encap(bool ipv4_encap, bool egress, const char *vrf) |
435 | { |
436 | char ns1[NETNS_NAME_SIZE] = NETNS_BASE "-1-" ; |
437 | char ns2[NETNS_NAME_SIZE] = NETNS_BASE "-2-" ; |
438 | char ns3[NETNS_NAME_SIZE] = NETNS_BASE "-3-" ; |
439 | char *sec = ipv4_encap ? "encap_gre" : "encap_gre6" ; |
440 | |
441 | if (!vrf) |
442 | return; |
443 | |
444 | if (!ASSERT_OK(create_ns(ns1, NETNS_NAME_SIZE), "create ns1" )) |
445 | goto out; |
446 | if (!ASSERT_OK(create_ns(ns2, NETNS_NAME_SIZE), "create ns2" )) |
447 | goto out; |
448 | if (!ASSERT_OK(create_ns(ns3, NETNS_NAME_SIZE), "create ns3" )) |
449 | goto out; |
450 | |
451 | if (!ASSERT_OK(setup_network(ns1, ns2, ns3, vrf), "setup network" )) |
452 | goto out; |
453 | |
454 | /* By default, pings work */ |
455 | if (!ASSERT_OK(check_ping_ok(ns1), "ping OK" )) |
456 | goto out; |
457 | |
458 | /* Remove NS2->DST routes, ping fails */ |
459 | SYS(out, "ip -n %s route del %s/32 dev veth3 %s" , ns2, IP4_ADDR_DST, vrf); |
460 | SYS(out, "ip -n %s -6 route del %s/128 dev veth3 %s" , ns2, IP6_ADDR_DST, vrf); |
461 | if (!ASSERT_OK(check_ping_fails(ns1), "ping expected fail" )) |
462 | goto out; |
463 | |
464 | /* Install replacement routes (LWT/eBPF), pings succeed */ |
465 | if (egress) { |
466 | SYS(out, "ip -n %s route add %s encap bpf xmit obj %s sec %s dev veth1 %s" , |
467 | ns1, IP4_ADDR_DST, BPF_FILE, sec, vrf); |
468 | SYS(out, "ip -n %s -6 route add %s encap bpf xmit obj %s sec %s dev veth1 %s" , |
469 | ns1, IP6_ADDR_DST, BPF_FILE, sec, vrf); |
470 | } else { |
471 | SYS(out, "ip -n %s route add %s encap bpf in obj %s sec %s dev veth2 %s" , |
472 | ns2, IP4_ADDR_DST, BPF_FILE, sec, vrf); |
473 | SYS(out, "ip -n %s -6 route add %s encap bpf in obj %s sec %s dev veth2 %s" , |
474 | ns2, IP6_ADDR_DST, BPF_FILE, sec, vrf); |
475 | } |
476 | |
477 | if (!ASSERT_OK(check_ping_ok(ns1), "ping OK" )) |
478 | goto out; |
479 | |
480 | /* Skip GSO tests with VRF: VRF routing needs properly assigned |
481 | * source IP/device, which is easy to do with ping but hard with TCP. |
482 | */ |
483 | if (egress && !vrf[0]) { |
484 | if (!ASSERT_OK(test_gso_fix(ns1, ns3, AF_INET), "test GSO" )) |
485 | goto out; |
486 | } |
487 | |
488 | /* Negative test: remove routes to GRE devices: ping fails */ |
489 | if (!ASSERT_OK(remove_routes_to_gredev(ns1, ns2, vrf), "remove routes to gredev" )) |
490 | goto out; |
491 | if (!ASSERT_OK(check_ping_fails(ns1), "ping expected fail" )) |
492 | goto out; |
493 | |
494 | /* Another negative test */ |
495 | if (!ASSERT_OK(add_unreachable_routes_to_gredev(ns1, ns2, vrf), |
496 | "add unreachable routes" )) |
497 | goto out; |
498 | ASSERT_OK(check_ping_fails(ns1), "ping expected fail" ); |
499 | |
500 | out: |
501 | SYS_NOFAIL("ip netns del %s" , ns1); |
502 | SYS_NOFAIL("ip netns del %s" , ns2); |
503 | SYS_NOFAIL("ip netns del %s" , ns3); |
504 | } |
505 | |
506 | void test_lwt_ip_encap_vrf_ipv6(void) |
507 | { |
508 | if (test__start_subtest("egress" )) |
509 | lwt_ip_encap(IPV6_ENCAP, EGRESS, "vrf red" ); |
510 | |
511 | if (test__start_subtest("ingress" )) |
512 | lwt_ip_encap(IPV6_ENCAP, INGRESS, "vrf red" ); |
513 | } |
514 | |
515 | void test_lwt_ip_encap_vrf_ipv4(void) |
516 | { |
517 | if (test__start_subtest("egress" )) |
518 | lwt_ip_encap(IPV4_ENCAP, EGRESS, "vrf red" ); |
519 | |
520 | if (test__start_subtest("ingress" )) |
521 | lwt_ip_encap(IPV4_ENCAP, INGRESS, "vrf red" ); |
522 | } |
523 | |
524 | void test_lwt_ip_encap_ipv6(void) |
525 | { |
526 | if (test__start_subtest("egress" )) |
527 | lwt_ip_encap(IPV6_ENCAP, EGRESS, "" ); |
528 | |
529 | if (test__start_subtest("ingress" )) |
530 | lwt_ip_encap(IPV6_ENCAP, INGRESS, "" ); |
531 | } |
532 | |
533 | void test_lwt_ip_encap_ipv4(void) |
534 | { |
535 | if (test__start_subtest("egress" )) |
536 | lwt_ip_encap(IPV4_ENCAP, EGRESS, "" ); |
537 | |
538 | if (test__start_subtest("ingress" )) |
539 | lwt_ip_encap(IPV4_ENCAP, INGRESS, "" ); |
540 | } |
541 | |