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 #include "test_lwt_ip_encap.skel.h"
7
8 #define BPF_FILE "test_lwt_ip_encap.bpf.o"
9
10 #define NETNS_NAME_SIZE 32
11 #define NETNS_BASE "ns-lwt-ip-encap"
12
13 #define IP4_ADDR_1 "172.16.1.100"
14 #define IP4_ADDR_2 "172.16.2.100"
15 #define IP4_ADDR_3 "172.16.3.100"
16 #define IP4_ADDR_4 "172.16.4.100"
17 #define IP4_ADDR_5 "172.16.5.100"
18 #define IP4_ADDR_6 "172.16.6.100"
19 #define IP4_ADDR_7 "172.16.7.100"
20 #define IP4_ADDR_8 "172.16.8.100"
21 #define IP4_ADDR_GRE "172.16.16.100"
22
23 #define IP4_ADDR_SRC IP4_ADDR_1
24 #define IP4_ADDR_DST IP4_ADDR_4
25
26 #define IP6_ADDR_1 "fb01::1"
27 #define IP6_ADDR_2 "fb02::1"
28 #define IP6_ADDR_3 "fb03::1"
29 #define IP6_ADDR_4 "fb04::1"
30 #define IP6_ADDR_5 "fb05::1"
31 #define IP6_ADDR_6 "fb06::1"
32 #define IP6_ADDR_7 "fb07::1"
33 #define IP6_ADDR_8 "fb08::1"
34 #define IP6_ADDR_GRE "fb10::1"
35
36 #define IP4_ADDR_VXLAN "172.16.17.100"
37 #define IP6_ADDR_VXLAN "fb11::1"
38
39 #define IP6_ADDR_SRC IP6_ADDR_1
40 #define IP6_ADDR_DST IP6_ADDR_4
41
42 /* Setup/topology:
43 *
44 * NS1 NS2 NS3
45 * veth1 <---> veth2 veth3 <---> veth4 (the top route)
46 * veth5 <---> veth6 veth7 <---> veth8 (the bottom route)
47 *
48 * Each vethN gets IP[4|6]_ADDR_N address.
49 *
50 * IP*_ADDR_SRC = IP*_ADDR_1
51 * IP*_ADDR_DST = IP*_ADDR_4
52 *
53 * All tests test pings from IP*_ADDR__SRC to IP*_ADDR_DST.
54 *
55 * By default, routes are configured to allow packets to go
56 * IP*_ADDR_1 <=> IP*_ADDR_2 <=> IP*_ADDR_3 <=> IP*_ADDR_4 (the top route).
57 *
58 * A GRE device is installed in NS3 with IP*_ADDR_GRE, and
59 * NS1/NS2 are configured to route packets to IP*_ADDR_GRE via IP*_ADDR_8
60 * (the bottom route).
61 *
62 * Tests:
63 *
64 * 1. Routes NS2->IP*_ADDR_DST are brought down, so the only way a ping
65 * from IP*_ADDR_SRC to IP*_ADDR_DST can work is via IP*_ADDR_GRE.
66 *
67 * 2a. In an egress test, a bpf LWT_XMIT program is installed on veth1
68 * that encaps the packets with an IP/GRE header to route to IP*_ADDR_GRE.
69 *
70 * ping: SRC->[encap at veth1:egress]->GRE:decap->DST
71 * ping replies go DST->SRC directly
72 *
73 * 2b. In an ingress test, a bpf LWT_IN program is installed on veth2
74 * that encaps the packets with an IP/GRE header to route to IP*_ADDR_GRE.
75 *
76 * ping: SRC->[encap at veth2:ingress]->GRE:decap->DST
77 * ping replies go DST->SRC directly
78 */
79
create_ns(char * name,size_t name_sz)80 static int create_ns(char *name, size_t name_sz)
81 {
82 if (!name)
83 goto fail;
84
85 if (!ASSERT_OK(append_tid(name, name_sz), "append TID"))
86 goto fail;
87
88 SYS(fail, "ip netns add %s", name);
89
90 /* rp_filter gets confused by what these tests are doing, so disable it */
91 SYS(fail, "ip netns exec %s sysctl -wq net.ipv4.conf.all.rp_filter=0", name);
92 SYS(fail, "ip netns exec %s sysctl -wq net.ipv4.conf.default.rp_filter=0", name);
93 /* Disable IPv6 DAD because it sometimes takes too long and fails tests */
94 SYS(fail, "ip netns exec %s sysctl -wq net.ipv6.conf.all.accept_dad=0", name);
95 SYS(fail, "ip netns exec %s sysctl -wq net.ipv6.conf.default.accept_dad=0", name);
96
97 return 0;
98 fail:
99 return -1;
100 }
101
set_top_addr(const char * ns1,const char * ns2,const char * ns3)102 static int set_top_addr(const char *ns1, const char *ns2, const char *ns3)
103 {
104 SYS(fail, "ip -n %s a add %s/24 dev veth1", ns1, IP4_ADDR_1);
105 SYS(fail, "ip -n %s a add %s/24 dev veth2", ns2, IP4_ADDR_2);
106 SYS(fail, "ip -n %s a add %s/24 dev veth3", ns2, IP4_ADDR_3);
107 SYS(fail, "ip -n %s a add %s/24 dev veth4", ns3, IP4_ADDR_4);
108 SYS(fail, "ip -n %s -6 a add %s/128 dev veth1", ns1, IP6_ADDR_1);
109 SYS(fail, "ip -n %s -6 a add %s/128 dev veth2", ns2, IP6_ADDR_2);
110 SYS(fail, "ip -n %s -6 a add %s/128 dev veth3", ns2, IP6_ADDR_3);
111 SYS(fail, "ip -n %s -6 a add %s/128 dev veth4", ns3, IP6_ADDR_4);
112
113 SYS(fail, "ip -n %s link set dev veth1 up", ns1);
114 SYS(fail, "ip -n %s link set dev veth2 up", ns2);
115 SYS(fail, "ip -n %s link set dev veth3 up", ns2);
116 SYS(fail, "ip -n %s link set dev veth4 up", ns3);
117
118 return 0;
119 fail:
120 return 1;
121 }
122
set_bottom_addr(const char * ns1,const char * ns2,const char * ns3)123 static int set_bottom_addr(const char *ns1, const char *ns2, const char *ns3)
124 {
125 SYS(fail, "ip -n %s a add %s/24 dev veth5", ns1, IP4_ADDR_5);
126 SYS(fail, "ip -n %s a add %s/24 dev veth6", ns2, IP4_ADDR_6);
127 SYS(fail, "ip -n %s a add %s/24 dev veth7", ns2, IP4_ADDR_7);
128 SYS(fail, "ip -n %s a add %s/24 dev veth8", ns3, IP4_ADDR_8);
129 SYS(fail, "ip -n %s -6 a add %s/128 dev veth5", ns1, IP6_ADDR_5);
130 SYS(fail, "ip -n %s -6 a add %s/128 dev veth6", ns2, IP6_ADDR_6);
131 SYS(fail, "ip -n %s -6 a add %s/128 dev veth7", ns2, IP6_ADDR_7);
132 SYS(fail, "ip -n %s -6 a add %s/128 dev veth8", ns3, IP6_ADDR_8);
133
134 SYS(fail, "ip -n %s link set dev veth5 up", ns1);
135 SYS(fail, "ip -n %s link set dev veth6 up", ns2);
136 SYS(fail, "ip -n %s link set dev veth7 up", ns2);
137 SYS(fail, "ip -n %s link set dev veth8 up", ns3);
138
139 return 0;
140 fail:
141 return 1;
142 }
143
configure_vrf(const char * ns1,const char * ns2)144 static int configure_vrf(const char *ns1, const char *ns2)
145 {
146 if (!ns1 || !ns2)
147 goto fail;
148
149 SYS(fail, "ip -n %s link add red type vrf table 1001", ns1);
150 SYS(fail, "ip -n %s link set red up", ns1);
151 SYS(fail, "ip -n %s route add table 1001 unreachable default metric 8192", ns1);
152 SYS(fail, "ip -n %s -6 route add table 1001 unreachable default metric 8192", ns1);
153 SYS(fail, "ip -n %s link set veth1 vrf red", ns1);
154 SYS(fail, "ip -n %s link set veth5 vrf red", ns1);
155
156 SYS(fail, "ip -n %s link add red type vrf table 1001", ns2);
157 SYS(fail, "ip -n %s link set red up", ns2);
158 SYS(fail, "ip -n %s route add table 1001 unreachable default metric 8192", ns2);
159 SYS(fail, "ip -n %s -6 route add table 1001 unreachable default metric 8192", ns2);
160 SYS(fail, "ip -n %s link set veth2 vrf red", ns2);
161 SYS(fail, "ip -n %s link set veth3 vrf red", ns2);
162 SYS(fail, "ip -n %s link set veth6 vrf red", ns2);
163 SYS(fail, "ip -n %s link set veth7 vrf red", ns2);
164
165 return 0;
166 fail:
167 return -1;
168 }
169
configure_ns1(const char * ns1,const char * vrf)170 static int configure_ns1(const char *ns1, const char *vrf)
171 {
172 struct nstoken *nstoken = NULL;
173
174 if (!ns1 || !vrf)
175 goto fail;
176
177 nstoken = open_netns(ns1);
178 if (!ASSERT_OK_PTR(nstoken, "open ns1"))
179 goto fail;
180
181 /* Top route */
182 SYS(fail, "ip route add %s/32 dev veth1 %s", IP4_ADDR_2, vrf);
183 SYS(fail, "ip route add default dev veth1 via %s %s", IP4_ADDR_2, vrf);
184 SYS(fail, "ip -6 route add %s/128 dev veth1 %s", IP6_ADDR_2, vrf);
185 SYS(fail, "ip -6 route add default dev veth1 via %s %s", IP6_ADDR_2, vrf);
186 /* Bottom route */
187 SYS(fail, "ip route add %s/32 dev veth5 %s", IP4_ADDR_6, vrf);
188 SYS(fail, "ip route add %s/32 dev veth5 via %s %s", IP4_ADDR_7, IP4_ADDR_6, vrf);
189 SYS(fail, "ip route add %s/32 dev veth5 via %s %s", IP4_ADDR_8, IP4_ADDR_6, vrf);
190 SYS(fail, "ip -6 route add %s/128 dev veth5 %s", IP6_ADDR_6, vrf);
191 SYS(fail, "ip -6 route add %s/128 dev veth5 via %s %s", IP6_ADDR_7, IP6_ADDR_6, vrf);
192 SYS(fail, "ip -6 route add %s/128 dev veth5 via %s %s", IP6_ADDR_8, IP6_ADDR_6, vrf);
193
194 close_netns(nstoken);
195 return 0;
196 fail:
197 close_netns(nstoken);
198 return -1;
199 }
200
configure_ns2(const char * ns2,const char * vrf)201 static int configure_ns2(const char *ns2, const char *vrf)
202 {
203 struct nstoken *nstoken = NULL;
204
205 if (!ns2 || !vrf)
206 goto fail;
207
208 nstoken = open_netns(ns2);
209 if (!ASSERT_OK_PTR(nstoken, "open ns2"))
210 goto fail;
211
212 SYS(fail, "ip netns exec %s sysctl -wq net.ipv4.ip_forward=1", ns2);
213 SYS(fail, "ip netns exec %s sysctl -wq net.ipv6.conf.all.forwarding=1", ns2);
214
215 /* Top route */
216 SYS(fail, "ip route add %s/32 dev veth2 %s", IP4_ADDR_1, vrf);
217 SYS(fail, "ip route add %s/32 dev veth3 %s", IP4_ADDR_4, vrf);
218 SYS(fail, "ip -6 route add %s/128 dev veth2 %s", IP6_ADDR_1, vrf);
219 SYS(fail, "ip -6 route add %s/128 dev veth3 %s", IP6_ADDR_4, vrf);
220 /* Bottom route */
221 SYS(fail, "ip route add %s/32 dev veth6 %s", IP4_ADDR_5, vrf);
222 SYS(fail, "ip route add %s/32 dev veth7 %s", IP4_ADDR_8, vrf);
223 SYS(fail, "ip -6 route add %s/128 dev veth6 %s", IP6_ADDR_5, vrf);
224 SYS(fail, "ip -6 route add %s/128 dev veth7 %s", IP6_ADDR_8, vrf);
225
226 close_netns(nstoken);
227 return 0;
228 fail:
229 close_netns(nstoken);
230 return -1;
231 }
232
configure_ns3(const char * ns3)233 static int configure_ns3(const char *ns3)
234 {
235 struct nstoken *nstoken = NULL;
236
237 if (!ns3)
238 goto fail;
239
240 nstoken = open_netns(ns3);
241 if (!ASSERT_OK_PTR(nstoken, "open ns3"))
242 goto fail;
243
244 /* Top route */
245 SYS(fail, "ip route add %s/32 dev veth4", IP4_ADDR_3);
246 SYS(fail, "ip route add %s/32 dev veth4 via %s", IP4_ADDR_1, IP4_ADDR_3);
247 SYS(fail, "ip route add %s/32 dev veth4 via %s", IP4_ADDR_2, IP4_ADDR_3);
248 SYS(fail, "ip -6 route add %s/128 dev veth4", IP6_ADDR_3);
249 SYS(fail, "ip -6 route add %s/128 dev veth4 via %s", IP6_ADDR_1, IP6_ADDR_3);
250 SYS(fail, "ip -6 route add %s/128 dev veth4 via %s", IP6_ADDR_2, IP6_ADDR_3);
251 /* Bottom route */
252 SYS(fail, "ip route add %s/32 dev veth8", IP4_ADDR_7);
253 SYS(fail, "ip route add %s/32 dev veth8 via %s", IP4_ADDR_5, IP4_ADDR_7);
254 SYS(fail, "ip route add %s/32 dev veth8 via %s", IP4_ADDR_6, IP4_ADDR_7);
255 SYS(fail, "ip -6 route add %s/128 dev veth8", IP6_ADDR_7);
256 SYS(fail, "ip -6 route add %s/128 dev veth8 via %s", IP6_ADDR_5, IP6_ADDR_7);
257 SYS(fail, "ip -6 route add %s/128 dev veth8 via %s", IP6_ADDR_6, IP6_ADDR_7);
258
259 /* Configure IPv4 GRE device */
260 SYS(fail, "ip tunnel add gre_dev mode gre remote %s local %s ttl 255",
261 IP4_ADDR_1, IP4_ADDR_GRE);
262 SYS(fail, "ip link set gre_dev up");
263 SYS(fail, "ip a add %s dev gre_dev", IP4_ADDR_GRE);
264
265 /* Configure IPv6 GRE device */
266 SYS(fail, "ip tunnel add gre6_dev mode ip6gre remote %s local %s ttl 255",
267 IP6_ADDR_1, IP6_ADDR_GRE);
268 SYS(fail, "ip link set gre6_dev up");
269 SYS(fail, "ip a add %s dev gre6_dev", IP6_ADDR_GRE);
270
271 close_netns(nstoken);
272 return 0;
273 fail:
274 close_netns(nstoken);
275 return -1;
276 }
277
setup_network(char * ns1,char * ns2,char * ns3,const char * vrf)278 static int setup_network(char *ns1, char *ns2, char *ns3, const char *vrf)
279 {
280 if (!ns1 || !ns2 || !ns3 || !vrf)
281 goto fail;
282
283 SYS(fail, "ip -n %s link add veth1 type veth peer name veth2 netns %s", ns1, ns2);
284 SYS(fail, "ip -n %s link add veth3 type veth peer name veth4 netns %s", ns2, ns3);
285 SYS(fail, "ip -n %s link add veth5 type veth peer name veth6 netns %s", ns1, ns2);
286 SYS(fail, "ip -n %s link add veth7 type veth peer name veth8 netns %s", ns2, ns3);
287
288 if (vrf[0]) {
289 if (!ASSERT_OK(configure_vrf(ns1, ns2), "configure vrf"))
290 goto fail;
291 }
292 if (!ASSERT_OK(set_top_addr(ns1, ns2, ns3), "set top addresses"))
293 goto fail;
294
295 if (!ASSERT_OK(set_bottom_addr(ns1, ns2, ns3), "set bottom addresses"))
296 goto fail;
297
298 if (!ASSERT_OK(configure_ns1(ns1, vrf), "configure ns1 routes"))
299 goto fail;
300
301 if (!ASSERT_OK(configure_ns2(ns2, vrf), "configure ns2 routes"))
302 goto fail;
303
304 if (!ASSERT_OK(configure_ns3(ns3), "configure ns3 routes"))
305 goto fail;
306
307 /* Link bottom route to the GRE tunnels */
308 SYS(fail, "ip -n %s route add %s/32 dev veth5 via %s %s",
309 ns1, IP4_ADDR_GRE, IP4_ADDR_6, vrf);
310 SYS(fail, "ip -n %s route add %s/32 dev veth7 via %s %s",
311 ns2, IP4_ADDR_GRE, IP4_ADDR_8, vrf);
312 SYS(fail, "ip -n %s -6 route add %s/128 dev veth5 via %s %s",
313 ns1, IP6_ADDR_GRE, IP6_ADDR_6, vrf);
314 SYS(fail, "ip -n %s -6 route add %s/128 dev veth7 via %s %s",
315 ns2, IP6_ADDR_GRE, IP6_ADDR_8, vrf);
316
317 return 0;
318 fail:
319 return -1;
320 }
321
remove_routes_to_gredev(const char * ns1,const char * ns2,const char * vrf)322 static int remove_routes_to_gredev(const char *ns1, const char *ns2, const char *vrf)
323 {
324 SYS(fail, "ip -n %s route del %s dev veth5 %s", ns1, IP4_ADDR_GRE, vrf);
325 SYS(fail, "ip -n %s route del %s dev veth7 %s", ns2, IP4_ADDR_GRE, vrf);
326 SYS(fail, "ip -n %s -6 route del %s/128 dev veth5 %s", ns1, IP6_ADDR_GRE, vrf);
327 SYS(fail, "ip -n %s -6 route del %s/128 dev veth7 %s", ns2, IP6_ADDR_GRE, vrf);
328
329 return 0;
330 fail:
331 return -1;
332 }
333
add_unreachable_routes_to_gredev(const char * ns1,const char * ns2,const char * vrf)334 static int add_unreachable_routes_to_gredev(const char *ns1, const char *ns2, const char *vrf)
335 {
336 SYS(fail, "ip -n %s route add unreachable %s/32 %s", ns1, IP4_ADDR_GRE, vrf);
337 SYS(fail, "ip -n %s route add unreachable %s/32 %s", ns2, IP4_ADDR_GRE, vrf);
338 SYS(fail, "ip -n %s -6 route add unreachable %s/128 %s", ns1, IP6_ADDR_GRE, vrf);
339 SYS(fail, "ip -n %s -6 route add unreachable %s/128 %s", ns2, IP6_ADDR_GRE, vrf);
340
341 return 0;
342 fail:
343 return -1;
344 }
345
346 #define GSO_SIZE 5000
347 #define GSO_TCP_PORT 9000
348 /* This tests the fix from commit ea0371f78799 ("net: fix GSO in bpf_lwt_push_ip_encap") */
test_gso_fix(const char * ns1,const char * ns3,int family)349 static int test_gso_fix(const char *ns1, const char *ns3, int family)
350 {
351 const char *ip_addr = family == AF_INET ? IP4_ADDR_DST : IP6_ADDR_DST;
352 char gso_packet[GSO_SIZE] = {};
353 struct nstoken *nstoken = NULL;
354 int sfd, cfd, afd;
355 ssize_t bytes;
356 int ret = -1;
357
358 if (!ns1 || !ns3)
359 return ret;
360
361 nstoken = open_netns(ns3);
362 if (!ASSERT_OK_PTR(nstoken, "open ns3"))
363 return ret;
364
365 sfd = start_server_str(family, SOCK_STREAM, ip_addr, GSO_TCP_PORT, NULL);
366 if (!ASSERT_OK_FD(sfd, "start server"))
367 goto close_netns;
368
369 close_netns(nstoken);
370
371 nstoken = open_netns(ns1);
372 if (!ASSERT_OK_PTR(nstoken, "open ns1"))
373 goto close_server;
374
375 cfd = connect_to_addr_str(family, SOCK_STREAM, ip_addr, GSO_TCP_PORT, NULL);
376 if (!ASSERT_OK_FD(cfd, "connect to server"))
377 goto close_server;
378
379 close_netns(nstoken);
380 nstoken = NULL;
381
382 afd = accept(sfd, NULL, NULL);
383 if (!ASSERT_OK_FD(afd, "accept"))
384 goto close_client;
385
386 /* Send a packet larger than MTU */
387 bytes = send(cfd, gso_packet, GSO_SIZE, 0);
388 if (!ASSERT_EQ(bytes, GSO_SIZE, "send packet"))
389 goto close_accept;
390
391 /* Verify we received all expected bytes */
392 bytes = read(afd, gso_packet, GSO_SIZE);
393 if (!ASSERT_EQ(bytes, GSO_SIZE, "receive packet"))
394 goto close_accept;
395
396 ret = 0;
397
398 close_accept:
399 close(afd);
400 close_client:
401 close(cfd);
402 close_server:
403 close(sfd);
404 close_netns:
405 close_netns(nstoken);
406
407 return ret;
408 }
409
check_ping_ok(const char * ns1)410 static int check_ping_ok(const char *ns1)
411 {
412 SYS(fail, "ip netns exec %s ping -c 1 -W1 -I veth1 %s > /dev/null", ns1, IP4_ADDR_DST);
413 SYS(fail, "ip netns exec %s %s -c 1 -W1 -I veth1 %s > /dev/null", ns1,
414 ping_command(AF_INET6), IP6_ADDR_DST);
415 return 0;
416 fail:
417 return -1;
418 }
419
check_ping_fails(const char * ns1)420 static int check_ping_fails(const char *ns1)
421 {
422 int ret;
423
424 ret = SYS_NOFAIL("ip netns exec %s ping -c 1 -W1 -I veth1 %s", ns1, IP4_ADDR_DST);
425 if (!ret)
426 return -1;
427
428 ret = SYS_NOFAIL("ip netns exec %s %s -c 1 -W1 -I veth1 %s", ns1,
429 ping_command(AF_INET6), IP6_ADDR_DST);
430 if (!ret)
431 return -1;
432
433 return 0;
434 }
435
436 #define EGRESS true
437 #define INGRESS false
438 #define IPV4_ENCAP true
439 #define IPV6_ENCAP false
lwt_ip_encap(bool ipv4_encap,bool egress,const char * vrf)440 static void lwt_ip_encap(bool ipv4_encap, bool egress, const char *vrf)
441 {
442 char ns1[NETNS_NAME_SIZE] = NETNS_BASE "-1-";
443 char ns2[NETNS_NAME_SIZE] = NETNS_BASE "-2-";
444 char ns3[NETNS_NAME_SIZE] = NETNS_BASE "-3-";
445 char *sec = ipv4_encap ? "encap_gre" : "encap_gre6";
446
447 if (!vrf)
448 return;
449
450 if (!ASSERT_OK(create_ns(ns1, NETNS_NAME_SIZE), "create ns1"))
451 goto out;
452 if (!ASSERT_OK(create_ns(ns2, NETNS_NAME_SIZE), "create ns2"))
453 goto out;
454 if (!ASSERT_OK(create_ns(ns3, NETNS_NAME_SIZE), "create ns3"))
455 goto out;
456
457 if (!ASSERT_OK(setup_network(ns1, ns2, ns3, vrf), "setup network"))
458 goto out;
459
460 /* By default, pings work */
461 if (!ASSERT_OK(check_ping_ok(ns1), "ping OK"))
462 goto out;
463
464 /* Remove NS2->DST routes, ping fails */
465 SYS(out, "ip -n %s route del %s/32 dev veth3 %s", ns2, IP4_ADDR_DST, vrf);
466 SYS(out, "ip -n %s -6 route del %s/128 dev veth3 %s", ns2, IP6_ADDR_DST, vrf);
467 if (!ASSERT_OK(check_ping_fails(ns1), "ping expected fail"))
468 goto out;
469
470 /* Install replacement routes (LWT/eBPF), pings succeed */
471 if (egress) {
472 SYS(out, "ip -n %s route add %s encap bpf xmit obj %s sec %s dev veth1 %s",
473 ns1, IP4_ADDR_DST, BPF_FILE, sec, vrf);
474 SYS(out, "ip -n %s -6 route add %s encap bpf xmit obj %s sec %s dev veth1 %s",
475 ns1, IP6_ADDR_DST, BPF_FILE, sec, vrf);
476 } else {
477 SYS(out, "ip -n %s route add %s encap bpf in obj %s sec %s dev veth2 %s",
478 ns2, IP4_ADDR_DST, BPF_FILE, sec, vrf);
479 SYS(out, "ip -n %s -6 route add %s encap bpf in obj %s sec %s dev veth2 %s",
480 ns2, IP6_ADDR_DST, BPF_FILE, sec, vrf);
481 }
482
483 if (!ASSERT_OK(check_ping_ok(ns1), "ping OK"))
484 goto out;
485
486 /* Skip GSO tests with VRF: VRF routing needs properly assigned
487 * source IP/device, which is easy to do with ping but hard with TCP.
488 */
489 if (egress && !vrf[0]) {
490 if (!ASSERT_OK(test_gso_fix(ns1, ns3, AF_INET), "test GSO"))
491 goto out;
492 }
493
494 /* Negative test: remove routes to GRE devices: ping fails */
495 if (!ASSERT_OK(remove_routes_to_gredev(ns1, ns2, vrf), "remove routes to gredev"))
496 goto out;
497 if (!ASSERT_OK(check_ping_fails(ns1), "ping expected fail"))
498 goto out;
499
500 /* Another negative test */
501 if (!ASSERT_OK(add_unreachable_routes_to_gredev(ns1, ns2, vrf),
502 "add unreachable routes"))
503 goto out;
504 ASSERT_OK(check_ping_fails(ns1), "ping expected fail");
505
506 out:
507 SYS_NOFAIL("ip netns del %s", ns1);
508 SYS_NOFAIL("ip netns del %s", ns2);
509 SYS_NOFAIL("ip netns del %s", ns3);
510 }
511
test_lwt_ip_encap_vrf_ipv6(void)512 void test_lwt_ip_encap_vrf_ipv6(void)
513 {
514 if (test__start_subtest("egress"))
515 lwt_ip_encap(IPV6_ENCAP, EGRESS, "vrf red");
516
517 if (test__start_subtest("ingress"))
518 lwt_ip_encap(IPV6_ENCAP, INGRESS, "vrf red");
519 }
520
test_lwt_ip_encap_vrf_ipv4(void)521 void test_lwt_ip_encap_vrf_ipv4(void)
522 {
523 if (test__start_subtest("egress"))
524 lwt_ip_encap(IPV4_ENCAP, EGRESS, "vrf red");
525
526 if (test__start_subtest("ingress"))
527 lwt_ip_encap(IPV4_ENCAP, INGRESS, "vrf red");
528 }
529
test_lwt_ip_encap_ipv6(void)530 void test_lwt_ip_encap_ipv6(void)
531 {
532 if (test__start_subtest("egress"))
533 lwt_ip_encap(IPV6_ENCAP, EGRESS, "");
534
535 if (test__start_subtest("ingress"))
536 lwt_ip_encap(IPV6_ENCAP, INGRESS, "");
537 }
538
test_lwt_ip_encap_ipv4(void)539 void test_lwt_ip_encap_ipv4(void)
540 {
541 if (test__start_subtest("egress"))
542 lwt_ip_encap(IPV4_ENCAP, EGRESS, "");
543
544 if (test__start_subtest("ingress"))
545 lwt_ip_encap(IPV4_ENCAP, INGRESS, "");
546 }
547
548 /*
549 * VxLAN Setup/topology:
550 *
551 * NS1 (IP*_ADDR_1) NS2 NS3 (IP*_ADDR_4)
552 * [ping src]
553 * | top route
554 * veth1 (LWT encap) <<-- veth2 veth3 <<-- veth4 (ping dst)
555 * | ^
556 * (bottom route) | (inner pkt)
557 * v bottom route |
558 * veth5 -->> veth6 veth7 -->> veth8 (vxlan decap)
559 * (IP*_ADDR_VXLAN)
560 *
561 * Add the VxLAN endpoint addresses to NS3's veth8, create standard
562 * VxLAN decap devices bound to those addresses, and install routes so
563 * NS1/NS2 can reach the endpoints via the bottom route. NS2 here is to
564 * make sure the LWT-encap VxLAN packets are routed to NS3 correctly.
565 */
setup_vxlan_routes(const char * ns3,const char * ns1,const char * ns2)566 static int setup_vxlan_routes(const char *ns3, const char *ns1, const char *ns2)
567 {
568 struct nstoken *nstoken;
569
570 nstoken = open_netns(ns3);
571 if (!ASSERT_OK_PTR(nstoken, "open ns3 for vxlan"))
572 return -1;
573
574 SYS(fail_close, "ip a add %s/32 dev veth8", IP4_ADDR_VXLAN);
575 SYS(fail_close, "ip -6 a add %s/128 dev veth8", IP6_ADDR_VXLAN);
576 /*
577 * Standard VxLAN devices to decap the encapsulated packets. The inner
578 * Ethernet frame uses a broadcast dst MAC so the IP stack accepts it
579 * without ARP or FDB configuration.
580 */
581 SYS(fail_close, "ip link add vxlan4 type vxlan id 1 dstport 4789 local %s dev veth8 nolearning noudpcsum",
582 IP4_ADDR_VXLAN);
583 SYS(fail_close, "ip link set vxlan4 up");
584 SYS(fail_close, "ip link add vxlan6 type vxlan id 1 dstport 4789 local %s dev veth8 nolearning udp6zerocsumrx",
585 IP6_ADDR_VXLAN);
586 SYS(fail_close, "ip link set vxlan6 up");
587 close_netns(nstoken);
588
589 SYS(fail, "ip -n %s route add %s/32 dev veth5 via %s",
590 ns1, IP4_ADDR_VXLAN, IP4_ADDR_6);
591 SYS(fail, "ip -n %s route add %s/32 dev veth7 via %s",
592 ns2, IP4_ADDR_VXLAN, IP4_ADDR_8);
593 SYS(fail, "ip -n %s -6 route add %s/128 dev veth5 via %s",
594 ns1, IP6_ADDR_VXLAN, IP6_ADDR_6);
595 SYS(fail, "ip -n %s -6 route add %s/128 dev veth7 via %s",
596 ns2, IP6_ADDR_VXLAN, IP6_ADDR_8);
597 return 0;
598
599 fail_close:
600 close_netns(nstoken);
601 fail:
602 return -1;
603 }
604
lwt_ip_encap_vxlan(bool ipv4_encap)605 static void lwt_ip_encap_vxlan(bool ipv4_encap)
606 {
607 char ns1[NETNS_NAME_SIZE] = NETNS_BASE "-1-";
608 char ns2[NETNS_NAME_SIZE] = NETNS_BASE "-2-";
609 char ns3[NETNS_NAME_SIZE] = NETNS_BASE "-3-";
610 const char *sec = ipv4_encap ? "encap_vxlan" : "encap_vxlan6";
611 int expected_offset = ipv4_encap ? (int)sizeof(struct iphdr)
612 : (int)sizeof(struct ipv6hdr);
613 struct test_lwt_ip_encap *skel = NULL;
614 int thdr_offset, err;
615
616 if (!ASSERT_OK(create_ns(ns1, NETNS_NAME_SIZE), "create ns1"))
617 goto out;
618 if (!ASSERT_OK(create_ns(ns2, NETNS_NAME_SIZE), "create ns2"))
619 goto out;
620 if (!ASSERT_OK(create_ns(ns3, NETNS_NAME_SIZE), "create ns3"))
621 goto out;
622
623 if (!ASSERT_OK(setup_network(ns1, ns2, ns3, ""), "setup network"))
624 goto out;
625
626 if (!ASSERT_OK(setup_vxlan_routes(ns3, ns1, ns2), "setup vxlan routes"))
627 goto out;
628
629 skel = test_lwt_ip_encap__open();
630 if (!ASSERT_OK_PTR(skel, "test_lwt_ip_encap__open"))
631 goto out;
632
633 bpf_program__set_autoload(skel->progs.bpf_lwt_encap_gre, false);
634 bpf_program__set_autoload(skel->progs.bpf_lwt_encap_gre6, false);
635 bpf_program__set_autoload(skel->progs.bpf_lwt_encap_vxlan, false);
636 bpf_program__set_autoload(skel->progs.bpf_lwt_encap_vxlan6, false);
637 bpf_program__set_autoload(skel->progs.fexit_lwt_push_ip_encap, true);
638 skel->rodata->tgt_ip_version = ipv4_encap ? 4 : 6;
639
640 err = test_lwt_ip_encap__load(skel);
641 if (!ASSERT_OK(err, "test_lwt_ip_encap__load"))
642 goto out;
643
644 err = test_lwt_ip_encap__attach(skel);
645 if (!ASSERT_OK(err, "test_lwt_ip_encap__attach"))
646 goto out;
647
648 /* Remove the direct NS2->DST route so packets must go via LWT encap. */
649 SYS(out, "ip -n %s route del %s/32 dev veth3", ns2, IP4_ADDR_DST);
650 SYS(out, "ip -n %s -6 route del %s/128 dev veth3", ns2, IP6_ADDR_DST);
651
652 if (ipv4_encap)
653 SYS(out, "ip -n %s route add %s encap bpf xmit obj %s sec %s dev veth1",
654 ns1, IP4_ADDR_DST, BPF_FILE, sec);
655 else
656 SYS(out, "ip -n %s -6 route add %s encap bpf xmit obj %s sec %s dev veth1",
657 ns1, IP6_ADDR_DST, BPF_FILE, sec);
658
659 skel->bss->fexit_triggered = false;
660
661 if (ipv4_encap)
662 SYS(out, "ip netns exec %s ping -c 1 -W1 %s", ns1, IP4_ADDR_DST);
663 else
664 SYS(out, "ip netns exec %s %s -c 1 -W1 %s", ns1,
665 ping_command(AF_INET6), IP6_ADDR_DST);
666
667 if (!ASSERT_TRUE(skel->bss->fexit_triggered, "fexit_triggered"))
668 goto out;
669
670 thdr_offset = (int)skel->bss->transport_hdr - (int)skel->bss->network_hdr;
671 ASSERT_EQ(thdr_offset, expected_offset, "transport_hdr offset");
672
673 out:
674 test_lwt_ip_encap__destroy(skel);
675 SYS_NOFAIL("ip netns del %s", ns1);
676 SYS_NOFAIL("ip netns del %s", ns2);
677 SYS_NOFAIL("ip netns del %s", ns3);
678 }
679
test_lwt_ip_encap_vxlan_ipv4(void)680 void test_lwt_ip_encap_vxlan_ipv4(void)
681 {
682 lwt_ip_encap_vxlan(IPV4_ENCAP);
683 }
684
test_lwt_ip_encap_vxlan_ipv6(void)685 void test_lwt_ip_encap_vxlan_ipv6(void)
686 {
687 lwt_ip_encap_vxlan(IPV6_ENCAP);
688 }
689