xref: /linux/tools/testing/selftests/bpf/prog_tests/lwt_ip_encap.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
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