xref: /linux/tools/testing/selftests/bpf/prog_tests/test_tunnel.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 
3 /*
4  * End-to-end eBPF tunnel test suite
5  *   The file tests BPF network tunnel implementation.
6  *
7  * Topology:
8  * ---------
9  *     root namespace   |     at_ns0 namespace
10  *                       |
11  *       -----------     |     -----------
12  *       | tnl dev |     |     | tnl dev |  (overlay network)
13  *       -----------     |     -----------
14  *       metadata-mode   |     metadata-mode
15  *        with bpf       |       with bpf
16  *                       |
17  *       ----------      |     ----------
18  *       |  veth1  | --------- |  veth0  |  (underlay network)
19  *       ----------    peer    ----------
20  *
21  *
22  *  Device Configuration
23  *  --------------------
24  *  root namespace with metadata-mode tunnel + BPF
25  *  Device names and addresses:
26  *	veth1 IP 1: 172.16.1.200, IPv6: 00::22 (underlay)
27  *		IP 2: 172.16.1.20, IPv6: 00::bb (underlay)
28  *	tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)
29  *
30  *  Namespace at_ns0 with native tunnel
31  *  Device names and addresses:
32  *	veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
33  *	tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)
34  *
35  *
36  * End-to-end ping packet flow
37  *  ---------------------------
38  *  Most of the tests start by namespace creation, device configuration,
39  *  then ping the underlay and overlay network.  When doing 'ping 10.1.1.100'
40  *  from root namespace, the following operations happen:
41  *  1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
42  *  2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
43  *     with local_ip=172.16.1.200, remote_ip=172.16.1.100. BPF program choose
44  *     the primary or secondary ip of veth1 as the local ip of tunnel. The
45  *     choice is made based on the value of bpf map local_ip_map.
46  *  3) Outer tunnel header is prepended and route the packet to veth1's egress.
47  *  4) veth0's ingress queue receive the tunneled packet at namespace at_ns0.
48  *  5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet.
49  *  6) Forward the packet to the overlay tnl dev.
50  */
51 
52 #include <arpa/inet.h>
53 #include <linux/if_link.h>
54 #include <linux/if_tun.h>
55 #include <linux/limits.h>
56 #include <linux/sysctl.h>
57 #include <linux/time_types.h>
58 #include <linux/net_tstamp.h>
59 #include <net/if.h>
60 #include <stdbool.h>
61 #include <stdio.h>
62 #include <sys/stat.h>
63 #include <unistd.h>
64 
65 #include "test_progs.h"
66 #include "network_helpers.h"
67 #include "test_tunnel_kern.skel.h"
68 
69 #define IP4_ADDR_VETH0 "172.16.1.100"
70 #define IP4_ADDR1_VETH1 "172.16.1.200"
71 #define IP4_ADDR2_VETH1 "172.16.1.20"
72 #define IP4_ADDR_TUNL_DEV0 "10.1.1.100"
73 #define IP4_ADDR_TUNL_DEV1 "10.1.1.200"
74 
75 #define IP6_ADDR_VETH0 "::11"
76 #define IP6_ADDR1_VETH1 "::22"
77 #define IP6_ADDR2_VETH1 "::bb"
78 
79 #define IP4_ADDR1_HEX_VETH1 0xac1001c8
80 #define IP4_ADDR2_HEX_VETH1 0xac100114
81 #define IP6_ADDR1_HEX_VETH1 0x22
82 #define IP6_ADDR2_HEX_VETH1 0xbb
83 
84 #define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
85 #define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
86 #define MAC_VETH1 "52:54:00:d9:03:00"
87 
88 #define VXLAN_TUNL_DEV0 "vxlan00"
89 #define VXLAN_TUNL_DEV1 "vxlan11"
90 #define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
91 #define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
92 
93 #define IPIP_TUNL_DEV0 "ipip00"
94 #define IPIP_TUNL_DEV1 "ipip11"
95 
96 #define XFRM_AUTH "0x1111111111111111111111111111111111111111"
97 #define XFRM_ENC "0x22222222222222222222222222222222"
98 #define XFRM_SPI_IN_TO_OUT 0x1
99 #define XFRM_SPI_OUT_TO_IN 0x2
100 
101 #define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
102 
103 static int config_device(void)
104 {
105 	SYS(fail, "ip netns add at_ns0");
106 	SYS(fail, "ip link add veth0 address " MAC_VETH1 " type veth peer name veth1");
107 	SYS(fail, "ip link set veth0 netns at_ns0");
108 	SYS(fail, "ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
109 	SYS(fail, "ip link set dev veth1 up mtu 1500");
110 	SYS(fail, "ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
111 	SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
112 
113 	return 0;
114 fail:
115 	return -1;
116 }
117 
118 static void cleanup(void)
119 {
120 	SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
121 	SYS_NOFAIL("ip link del veth1");
122 	SYS_NOFAIL("ip link del %s", VXLAN_TUNL_DEV1);
123 	SYS_NOFAIL("ip link del %s", IP6VXLAN_TUNL_DEV1);
124 }
125 
126 static int add_vxlan_tunnel(void)
127 {
128 	/* at_ns0 namespace */
129 	SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
130 	    VXLAN_TUNL_DEV0);
131 	SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
132 	    VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
133 	SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
134 	    VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
135 	SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
136 	    IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
137 	SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0",
138 	    IP4_ADDR2_VETH1, MAC_VETH1);
139 
140 	/* root namespace */
141 	SYS(fail, "ip link add dev %s type vxlan external gbp dstport 4789",
142 	    VXLAN_TUNL_DEV1);
143 	SYS(fail, "ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
144 	SYS(fail, "ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
145 	SYS(fail, "ip neigh add %s lladdr %s dev %s",
146 	    IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
147 
148 	return 0;
149 fail:
150 	return -1;
151 }
152 
153 static void delete_vxlan_tunnel(void)
154 {
155 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
156 		   VXLAN_TUNL_DEV0);
157 	SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
158 }
159 
160 static int add_ip6vxlan_tunnel(void)
161 {
162 	SYS(fail, "ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
163 	    IP6_ADDR_VETH0);
164 	SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up");
165 	SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
166 	SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
167 	SYS(fail, "ip link set dev veth1 up");
168 
169 	/* at_ns0 namespace */
170 	SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
171 	    IP6VXLAN_TUNL_DEV0);
172 	SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
173 	    IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
174 	SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
175 	    IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
176 
177 	/* root namespace */
178 	SYS(fail, "ip link add dev %s type vxlan external dstport 4789",
179 	    IP6VXLAN_TUNL_DEV1);
180 	SYS(fail, "ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
181 	SYS(fail, "ip link set dev %s address %s up",
182 	    IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
183 
184 	return 0;
185 fail:
186 	return -1;
187 }
188 
189 static void delete_ip6vxlan_tunnel(void)
190 {
191 	SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
192 		   IP6_ADDR_VETH0);
193 	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
194 	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
195 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
196 		   IP6VXLAN_TUNL_DEV0);
197 	SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
198 }
199 
200 enum ipip_encap {
201 	NONE	= 0,
202 	FOU	= 1,
203 	GUE	= 2,
204 };
205 
206 static int set_ipip_encap(const char *ipproto, const char *type)
207 {
208 	SYS(fail, "ip -n at_ns0 fou add port 5555 %s", ipproto);
209 	SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap %s",
210 	    IPIP_TUNL_DEV0, type);
211 	SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap-dport 5555",
212 	    IPIP_TUNL_DEV0);
213 
214 	return 0;
215 fail:
216 	return -1;
217 }
218 
219 static int add_ipip_tunnel(enum ipip_encap encap)
220 {
221 	int err;
222 	const char *ipproto, *type;
223 
224 	switch (encap) {
225 	case FOU:
226 		ipproto = "ipproto 4";
227 		type = "fou";
228 		break;
229 	case GUE:
230 		ipproto = "gue";
231 		type = ipproto;
232 		break;
233 	default:
234 		ipproto = NULL;
235 		type = ipproto;
236 	}
237 
238 	/* at_ns0 namespace */
239 	SYS(fail, "ip -n at_ns0 link add dev %s type ipip local %s remote %s",
240 	    IPIP_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
241 
242 	if (type && ipproto) {
243 		err = set_ipip_encap(ipproto, type);
244 		if (!ASSERT_OK(err, "set_ipip_encap"))
245 			goto fail;
246 	}
247 
248 	SYS(fail, "ip -n at_ns0 link set dev %s up", IPIP_TUNL_DEV0);
249 	SYS(fail, "ip -n at_ns0 addr add dev %s %s/24",
250 	    IPIP_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
251 
252 	/* root namespace */
253 	if (type && ipproto)
254 		SYS(fail, "ip fou add port 5555 %s", ipproto);
255 	SYS(fail, "ip link add dev %s type ipip external", IPIP_TUNL_DEV1);
256 	SYS(fail, "ip link set dev %s up", IPIP_TUNL_DEV1);
257 	SYS(fail, "ip addr add dev %s %s/24", IPIP_TUNL_DEV1,
258 	    IP4_ADDR_TUNL_DEV1);
259 
260 	return 0;
261 fail:
262 	return -1;
263 }
264 
265 static void delete_ipip_tunnel(void)
266 {
267 	SYS_NOFAIL("ip -n at_ns0 link delete dev %s", IPIP_TUNL_DEV0);
268 	SYS_NOFAIL("ip -n at_ns0 fou del port 5555");
269 	SYS_NOFAIL("ip link delete dev %s", IPIP_TUNL_DEV1);
270 	SYS_NOFAIL("ip fou del port 5555");
271 }
272 
273 static int add_xfrm_tunnel(void)
274 {
275 	/* at_ns0 namespace
276 	 * at_ns0 -> root
277 	 */
278 	SYS(fail,
279 	    "ip netns exec at_ns0 "
280 		"ip xfrm state add src %s dst %s proto esp "
281 			"spi %d reqid 1 mode tunnel replay-window 42 "
282 			"auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
283 	    IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
284 	SYS(fail,
285 	    "ip netns exec at_ns0 "
286 		"ip xfrm policy add src %s/32 dst %s/32 dir out "
287 			"tmpl src %s dst %s proto esp reqid 1 "
288 			"mode tunnel",
289 	    IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
290 
291 	/* root -> at_ns0 */
292 	SYS(fail,
293 	    "ip netns exec at_ns0 "
294 		"ip xfrm state add src %s dst %s proto esp "
295 			"spi %d reqid 2 mode tunnel "
296 			"auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
297 	    IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
298 	SYS(fail,
299 	    "ip netns exec at_ns0 "
300 		"ip xfrm policy add src %s/32 dst %s/32 dir in "
301 			"tmpl src %s dst %s proto esp reqid 2 "
302 			"mode tunnel",
303 	    IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
304 
305 	/* address & route */
306 	SYS(fail, "ip netns exec at_ns0 ip addr add dev veth0 %s/32",
307 	    IP4_ADDR_TUNL_DEV0);
308 	SYS(fail, "ip netns exec at_ns0 ip route add %s dev veth0 via %s src %s",
309 	    IP4_ADDR_TUNL_DEV1, IP4_ADDR1_VETH1, IP4_ADDR_TUNL_DEV0);
310 
311 	/* root namespace
312 	 * at_ns0 -> root
313 	 */
314 	SYS(fail,
315 	    "ip xfrm state add src %s dst %s proto esp "
316 		    "spi %d reqid 1 mode tunnel replay-window 42 "
317 		    "auth-trunc 'hmac(sha1)' %s 96  enc 'cbc(aes)' %s",
318 	    IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
319 	SYS(fail,
320 	    "ip xfrm policy add src %s/32 dst %s/32 dir in "
321 		    "tmpl src %s dst %s proto esp reqid 1 "
322 		    "mode tunnel",
323 	    IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
324 
325 	/* root -> at_ns0 */
326 	SYS(fail,
327 	    "ip xfrm state add src %s dst %s proto esp "
328 		    "spi %d reqid 2 mode tunnel "
329 		    "auth-trunc 'hmac(sha1)' %s 96  enc 'cbc(aes)' %s",
330 	    IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
331 	SYS(fail,
332 	    "ip xfrm policy add src %s/32 dst %s/32 dir out "
333 		    "tmpl src %s dst %s proto esp reqid 2 "
334 		    "mode tunnel",
335 	    IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
336 
337 	/* address & route */
338 	SYS(fail, "ip addr add dev veth1 %s/32", IP4_ADDR_TUNL_DEV1);
339 	SYS(fail, "ip route add %s dev veth1 via %s src %s",
340 	    IP4_ADDR_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR_TUNL_DEV1);
341 
342 	return 0;
343 fail:
344 	return -1;
345 }
346 
347 static void delete_xfrm_tunnel(void)
348 {
349 	SYS_NOFAIL("ip xfrm policy delete dir out src %s/32 dst %s/32",
350 		   IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0);
351 	SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32",
352 		   IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1);
353 	SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d",
354 		   IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT);
355 	SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d",
356 		   IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN);
357 }
358 
359 static int test_ping(int family, const char *addr)
360 {
361 	SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
362 	return 0;
363 fail:
364 	return -1;
365 }
366 
367 static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
368 {
369 	DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
370 			    .priority = 1, .prog_fd = igr_fd);
371 	DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
372 			    .priority = 1, .prog_fd = egr_fd);
373 	int ret;
374 
375 	ret = bpf_tc_hook_create(hook);
376 	if (!ASSERT_OK(ret, "create tc hook"))
377 		return ret;
378 
379 	if (igr_fd >= 0) {
380 		hook->attach_point = BPF_TC_INGRESS;
381 		ret = bpf_tc_attach(hook, &opts1);
382 		if (!ASSERT_OK(ret, "bpf_tc_attach")) {
383 			bpf_tc_hook_destroy(hook);
384 			return ret;
385 		}
386 	}
387 
388 	if (egr_fd >= 0) {
389 		hook->attach_point = BPF_TC_EGRESS;
390 		ret = bpf_tc_attach(hook, &opts2);
391 		if (!ASSERT_OK(ret, "bpf_tc_attach")) {
392 			bpf_tc_hook_destroy(hook);
393 			return ret;
394 		}
395 	}
396 
397 	return 0;
398 }
399 
400 static void test_vxlan_tunnel(void)
401 {
402 	struct test_tunnel_kern *skel = NULL;
403 	struct nstoken *nstoken;
404 	int local_ip_map_fd = -1;
405 	int set_src_prog_fd, get_src_prog_fd;
406 	int set_dst_prog_fd;
407 	int key = 0, ifindex = -1;
408 	uint local_ip;
409 	int err;
410 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
411 			    .attach_point = BPF_TC_INGRESS);
412 
413 	/* add vxlan tunnel */
414 	err = add_vxlan_tunnel();
415 	if (!ASSERT_OK(err, "add vxlan tunnel"))
416 		goto done;
417 
418 	/* load and attach bpf prog to tunnel dev tc hook point */
419 	skel = test_tunnel_kern__open_and_load();
420 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
421 		goto done;
422 	ifindex = if_nametoindex(VXLAN_TUNL_DEV1);
423 	if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex"))
424 		goto done;
425 	tc_hook.ifindex = ifindex;
426 	get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
427 	set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
428 	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
429 		goto done;
430 	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
431 		goto done;
432 	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
433 		goto done;
434 
435 	/* load and attach bpf prog to veth dev tc hook point */
436 	ifindex = if_nametoindex("veth1");
437 	if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
438 		goto done;
439 	tc_hook.ifindex = ifindex;
440 	set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst);
441 	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
442 		goto done;
443 	if (attach_tc_prog(&tc_hook, set_dst_prog_fd, -1))
444 		goto done;
445 
446 	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
447 	nstoken = open_netns("at_ns0");
448 	if (!ASSERT_OK_PTR(nstoken, "setns src"))
449 		goto done;
450 	ifindex = if_nametoindex(VXLAN_TUNL_DEV0);
451 	if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex"))
452 		goto done;
453 	tc_hook.ifindex = ifindex;
454 	set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
455 	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
456 		goto done;
457 	if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
458 		goto done;
459 	close_netns(nstoken);
460 
461 	/* use veth1 ip 2 as tunnel source ip */
462 	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
463 	if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
464 		goto done;
465 	local_ip = IP4_ADDR2_HEX_VETH1;
466 	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
467 	if (!ASSERT_OK(err, "update bpf local_ip_map"))
468 		goto done;
469 
470 	/* ping test */
471 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
472 	if (!ASSERT_OK(err, "test_ping"))
473 		goto done;
474 
475 done:
476 	/* delete vxlan tunnel */
477 	delete_vxlan_tunnel();
478 	if (local_ip_map_fd >= 0)
479 		close(local_ip_map_fd);
480 	if (skel)
481 		test_tunnel_kern__destroy(skel);
482 }
483 
484 static void test_ip6vxlan_tunnel(void)
485 {
486 	struct test_tunnel_kern *skel = NULL;
487 	struct nstoken *nstoken;
488 	int local_ip_map_fd = -1;
489 	int set_src_prog_fd, get_src_prog_fd;
490 	int set_dst_prog_fd;
491 	int key = 0, ifindex = -1;
492 	uint local_ip;
493 	int err;
494 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
495 			    .attach_point = BPF_TC_INGRESS);
496 
497 	/* add vxlan tunnel */
498 	err = add_ip6vxlan_tunnel();
499 	if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
500 		goto done;
501 
502 	/* load and attach bpf prog to tunnel dev tc hook point */
503 	skel = test_tunnel_kern__open_and_load();
504 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
505 		goto done;
506 	ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1);
507 	if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex"))
508 		goto done;
509 	tc_hook.ifindex = ifindex;
510 	get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
511 	set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
512 	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
513 		goto done;
514 	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
515 		goto done;
516 	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
517 		goto done;
518 
519 	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
520 	nstoken = open_netns("at_ns0");
521 	if (!ASSERT_OK_PTR(nstoken, "setns src"))
522 		goto done;
523 	ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0);
524 	if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex"))
525 		goto done;
526 	tc_hook.ifindex = ifindex;
527 	set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
528 	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
529 		goto done;
530 	if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
531 		goto done;
532 	close_netns(nstoken);
533 
534 	/* use veth1 ip 2 as tunnel source ip */
535 	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
536 	if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
537 		goto done;
538 	local_ip = IP6_ADDR2_HEX_VETH1;
539 	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
540 	if (!ASSERT_OK(err, "update bpf local_ip_map"))
541 		goto done;
542 
543 	/* ping test */
544 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
545 	if (!ASSERT_OK(err, "test_ping"))
546 		goto done;
547 
548 done:
549 	/* delete ipv6 vxlan tunnel */
550 	delete_ip6vxlan_tunnel();
551 	if (local_ip_map_fd >= 0)
552 		close(local_ip_map_fd);
553 	if (skel)
554 		test_tunnel_kern__destroy(skel);
555 }
556 
557 static void test_ipip_tunnel(enum ipip_encap encap)
558 {
559 	struct test_tunnel_kern *skel = NULL;
560 	struct nstoken *nstoken;
561 	int set_src_prog_fd, get_src_prog_fd;
562 	int ifindex = -1;
563 	int err;
564 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
565 			    .attach_point = BPF_TC_INGRESS);
566 
567 	/* add ipip tunnel */
568 	err = add_ipip_tunnel(encap);
569 	if (!ASSERT_OK(err, "add_ipip_tunnel"))
570 		goto done;
571 
572 	/* load and attach bpf prog to tunnel dev tc hook point */
573 	skel = test_tunnel_kern__open_and_load();
574 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
575 		goto done;
576 	ifindex = if_nametoindex(IPIP_TUNL_DEV1);
577 	if (!ASSERT_NEQ(ifindex, 0, "ipip11 ifindex"))
578 		goto done;
579 	tc_hook.ifindex = ifindex;
580 
581 	switch (encap) {
582 	case FOU:
583 		get_src_prog_fd = bpf_program__fd(
584 			skel->progs.ipip_encap_get_tunnel);
585 		set_src_prog_fd = bpf_program__fd(
586 			skel->progs.ipip_fou_set_tunnel);
587 		break;
588 	case GUE:
589 		get_src_prog_fd = bpf_program__fd(
590 			skel->progs.ipip_encap_get_tunnel);
591 		set_src_prog_fd = bpf_program__fd(
592 			skel->progs.ipip_gue_set_tunnel);
593 		break;
594 	default:
595 		get_src_prog_fd = bpf_program__fd(
596 			skel->progs.ipip_get_tunnel);
597 		set_src_prog_fd = bpf_program__fd(
598 			skel->progs.ipip_set_tunnel);
599 	}
600 
601 	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
602 		goto done;
603 	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
604 		goto done;
605 	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
606 		goto done;
607 
608 	/* ping from root namespace test */
609 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
610 	if (!ASSERT_OK(err, "test_ping"))
611 		goto done;
612 
613 	/* ping from at_ns0 namespace test */
614 	nstoken = open_netns("at_ns0");
615 	if (!ASSERT_OK_PTR(nstoken, "setns"))
616 		goto done;
617 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
618 	if (!ASSERT_OK(err, "test_ping"))
619 		goto done;
620 	close_netns(nstoken);
621 
622 done:
623 	/* delete ipip tunnel */
624 	delete_ipip_tunnel();
625 	if (skel)
626 		test_tunnel_kern__destroy(skel);
627 }
628 
629 static void test_xfrm_tunnel(void)
630 {
631 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
632 			    .attach_point = BPF_TC_INGRESS);
633 	LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
634 	struct test_tunnel_kern *skel = NULL;
635 	struct nstoken *nstoken;
636 	int xdp_prog_fd;
637 	int tc_prog_fd;
638 	int ifindex;
639 	int err;
640 
641 	err = add_xfrm_tunnel();
642 	if (!ASSERT_OK(err, "add_xfrm_tunnel"))
643 		return;
644 
645 	skel = test_tunnel_kern__open_and_load();
646 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
647 		goto done;
648 
649 	ifindex = if_nametoindex("veth1");
650 	if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
651 		goto done;
652 
653 	/* attach tc prog to tunnel dev */
654 	tc_hook.ifindex = ifindex;
655 	tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state);
656 	if (!ASSERT_GE(tc_prog_fd, 0, "bpf_program__fd"))
657 		goto done;
658 	if (attach_tc_prog(&tc_hook, tc_prog_fd, -1))
659 		goto done;
660 
661 	/* attach xdp prog to tunnel dev */
662 	xdp_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state_xdp);
663 	if (!ASSERT_GE(xdp_prog_fd, 0, "bpf_program__fd"))
664 		goto done;
665 	err = bpf_xdp_attach(ifindex, xdp_prog_fd, XDP_FLAGS_REPLACE, &opts);
666 	if (!ASSERT_OK(err, "bpf_xdp_attach"))
667 		goto done;
668 
669 	/* ping from at_ns0 namespace test */
670 	nstoken = open_netns("at_ns0");
671 	if (!ASSERT_OK_PTR(nstoken, "setns"))
672 		goto done;
673 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
674 	close_netns(nstoken);
675 	if (!ASSERT_OK(err, "test_ping"))
676 		goto done;
677 
678 	if (!ASSERT_EQ(skel->bss->xfrm_reqid, 1, "req_id"))
679 		goto done;
680 	if (!ASSERT_EQ(skel->bss->xfrm_spi, XFRM_SPI_IN_TO_OUT, "spi"))
681 		goto done;
682 	if (!ASSERT_EQ(skel->bss->xfrm_remote_ip, 0xac100164, "remote_ip"))
683 		goto done;
684 	if (!ASSERT_EQ(skel->bss->xfrm_replay_window, 42, "replay_window"))
685 		goto done;
686 
687 done:
688 	delete_xfrm_tunnel();
689 	if (skel)
690 		test_tunnel_kern__destroy(skel);
691 }
692 
693 #define RUN_TEST(name, ...)						\
694 	({								\
695 		if (test__start_subtest(#name)) {			\
696 			config_device();				\
697 			test_ ## name(__VA_ARGS__);			\
698 			cleanup();					\
699 		}							\
700 	})
701 
702 static void *test_tunnel_run_tests(void *arg)
703 {
704 	RUN_TEST(vxlan_tunnel);
705 	RUN_TEST(ip6vxlan_tunnel);
706 	RUN_TEST(ipip_tunnel, NONE);
707 	RUN_TEST(ipip_tunnel, FOU);
708 	RUN_TEST(ipip_tunnel, GUE);
709 	RUN_TEST(xfrm_tunnel);
710 
711 	return NULL;
712 }
713 
714 void test_tunnel(void)
715 {
716 	pthread_t test_thread;
717 	int err;
718 
719 	/* Run the tests in their own thread to isolate the namespace changes
720 	 * so they do not affect the environment of other tests.
721 	 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
722 	 */
723 	err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
724 	if (ASSERT_OK(err, "pthread_create"))
725 		ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
726 }
727