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_tun.h>
54 #include <linux/limits.h>
55 #include <linux/sysctl.h>
56 #include <linux/time_types.h>
57 #include <linux/net_tstamp.h>
58 #include <net/if.h>
59 #include <stdbool.h>
60 #include <stdio.h>
61 #include <sys/stat.h>
62 #include <unistd.h>
63 
64 #include "test_progs.h"
65 #include "network_helpers.h"
66 #include "test_tunnel_kern.skel.h"
67 
68 #define IP4_ADDR_VETH0 "172.16.1.100"
69 #define IP4_ADDR1_VETH1 "172.16.1.200"
70 #define IP4_ADDR2_VETH1 "172.16.1.20"
71 #define IP4_ADDR_TUNL_DEV0 "10.1.1.100"
72 #define IP4_ADDR_TUNL_DEV1 "10.1.1.200"
73 
74 #define IP6_ADDR_VETH0 "::11"
75 #define IP6_ADDR1_VETH1 "::22"
76 #define IP6_ADDR2_VETH1 "::bb"
77 
78 #define IP4_ADDR1_HEX_VETH1 0xac1001c8
79 #define IP4_ADDR2_HEX_VETH1 0xac100114
80 #define IP6_ADDR1_HEX_VETH1 0x22
81 #define IP6_ADDR2_HEX_VETH1 0xbb
82 
83 #define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
84 #define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
85 #define MAC_VETH1 "52:54:00:d9:03:00"
86 
87 #define VXLAN_TUNL_DEV0 "vxlan00"
88 #define VXLAN_TUNL_DEV1 "vxlan11"
89 #define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
90 #define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
91 
92 #define IPIP_TUNL_DEV0 "ipip00"
93 #define IPIP_TUNL_DEV1 "ipip11"
94 
95 #define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
96 
config_device(void)97 static int config_device(void)
98 {
99 	SYS(fail, "ip netns add at_ns0");
100 	SYS(fail, "ip link add veth0 address " MAC_VETH1 " type veth peer name veth1");
101 	SYS(fail, "ip link set veth0 netns at_ns0");
102 	SYS(fail, "ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
103 	SYS(fail, "ip link set dev veth1 up mtu 1500");
104 	SYS(fail, "ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
105 	SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
106 
107 	return 0;
108 fail:
109 	return -1;
110 }
111 
cleanup(void)112 static void cleanup(void)
113 {
114 	SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
115 	SYS_NOFAIL("ip link del veth1 2> /dev/null");
116 	SYS_NOFAIL("ip link del %s 2> /dev/null", VXLAN_TUNL_DEV1);
117 	SYS_NOFAIL("ip link del %s 2> /dev/null", IP6VXLAN_TUNL_DEV1);
118 }
119 
add_vxlan_tunnel(void)120 static int add_vxlan_tunnel(void)
121 {
122 	/* at_ns0 namespace */
123 	SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
124 	    VXLAN_TUNL_DEV0);
125 	SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
126 	    VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
127 	SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
128 	    VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
129 	SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
130 	    IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
131 	SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0",
132 	    IP4_ADDR2_VETH1, MAC_VETH1);
133 
134 	/* root namespace */
135 	SYS(fail, "ip link add dev %s type vxlan external gbp dstport 4789",
136 	    VXLAN_TUNL_DEV1);
137 	SYS(fail, "ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
138 	SYS(fail, "ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
139 	SYS(fail, "ip neigh add %s lladdr %s dev %s",
140 	    IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
141 
142 	return 0;
143 fail:
144 	return -1;
145 }
146 
delete_vxlan_tunnel(void)147 static void delete_vxlan_tunnel(void)
148 {
149 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
150 		   VXLAN_TUNL_DEV0);
151 	SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
152 }
153 
add_ip6vxlan_tunnel(void)154 static int add_ip6vxlan_tunnel(void)
155 {
156 	SYS(fail, "ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
157 	    IP6_ADDR_VETH0);
158 	SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up");
159 	SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
160 	SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
161 	SYS(fail, "ip link set dev veth1 up");
162 
163 	/* at_ns0 namespace */
164 	SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
165 	    IP6VXLAN_TUNL_DEV0);
166 	SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
167 	    IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
168 	SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
169 	    IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
170 
171 	/* root namespace */
172 	SYS(fail, "ip link add dev %s type vxlan external dstport 4789",
173 	    IP6VXLAN_TUNL_DEV1);
174 	SYS(fail, "ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
175 	SYS(fail, "ip link set dev %s address %s up",
176 	    IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
177 
178 	return 0;
179 fail:
180 	return -1;
181 }
182 
delete_ip6vxlan_tunnel(void)183 static void delete_ip6vxlan_tunnel(void)
184 {
185 	SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
186 		   IP6_ADDR_VETH0);
187 	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
188 	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
189 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
190 		   IP6VXLAN_TUNL_DEV0);
191 	SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
192 }
193 
194 enum ipip_encap {
195 	NONE	= 0,
196 	FOU	= 1,
197 	GUE	= 2,
198 };
199 
set_ipip_encap(const char * ipproto,const char * type)200 static int set_ipip_encap(const char *ipproto, const char *type)
201 {
202 	SYS(fail, "ip -n at_ns0 fou add port 5555 %s", ipproto);
203 	SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap %s",
204 	    IPIP_TUNL_DEV0, type);
205 	SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap-dport 5555",
206 	    IPIP_TUNL_DEV0);
207 
208 	return 0;
209 fail:
210 	return -1;
211 }
212 
add_ipip_tunnel(enum ipip_encap encap)213 static int add_ipip_tunnel(enum ipip_encap encap)
214 {
215 	int err;
216 	const char *ipproto, *type;
217 
218 	switch (encap) {
219 	case FOU:
220 		ipproto = "ipproto 4";
221 		type = "fou";
222 		break;
223 	case GUE:
224 		ipproto = "gue";
225 		type = ipproto;
226 		break;
227 	default:
228 		ipproto = NULL;
229 		type = ipproto;
230 	}
231 
232 	/* at_ns0 namespace */
233 	SYS(fail, "ip -n at_ns0 link add dev %s type ipip local %s remote %s",
234 	    IPIP_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
235 
236 	if (type && ipproto) {
237 		err = set_ipip_encap(ipproto, type);
238 		if (!ASSERT_OK(err, "set_ipip_encap"))
239 			goto fail;
240 	}
241 
242 	SYS(fail, "ip -n at_ns0 link set dev %s up", IPIP_TUNL_DEV0);
243 	SYS(fail, "ip -n at_ns0 addr add dev %s %s/24",
244 	    IPIP_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
245 
246 	/* root namespace */
247 	if (type && ipproto)
248 		SYS(fail, "ip fou add port 5555 %s", ipproto);
249 	SYS(fail, "ip link add dev %s type ipip external", IPIP_TUNL_DEV1);
250 	SYS(fail, "ip link set dev %s up", IPIP_TUNL_DEV1);
251 	SYS(fail, "ip addr add dev %s %s/24", IPIP_TUNL_DEV1,
252 	    IP4_ADDR_TUNL_DEV1);
253 
254 	return 0;
255 fail:
256 	return -1;
257 }
258 
delete_ipip_tunnel(void)259 static void delete_ipip_tunnel(void)
260 {
261 	SYS_NOFAIL("ip -n at_ns0 link delete dev %s", IPIP_TUNL_DEV0);
262 	SYS_NOFAIL("ip -n at_ns0 fou del port 5555 2> /dev/null");
263 	SYS_NOFAIL("ip link delete dev %s", IPIP_TUNL_DEV1);
264 	SYS_NOFAIL("ip fou del port 5555 2> /dev/null");
265 }
266 
test_ping(int family,const char * addr)267 static int test_ping(int family, const char *addr)
268 {
269 	SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
270 	return 0;
271 fail:
272 	return -1;
273 }
274 
attach_tc_prog(struct bpf_tc_hook * hook,int igr_fd,int egr_fd)275 static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
276 {
277 	DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
278 			    .priority = 1, .prog_fd = igr_fd);
279 	DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
280 			    .priority = 1, .prog_fd = egr_fd);
281 	int ret;
282 
283 	ret = bpf_tc_hook_create(hook);
284 	if (!ASSERT_OK(ret, "create tc hook"))
285 		return ret;
286 
287 	if (igr_fd >= 0) {
288 		hook->attach_point = BPF_TC_INGRESS;
289 		ret = bpf_tc_attach(hook, &opts1);
290 		if (!ASSERT_OK(ret, "bpf_tc_attach")) {
291 			bpf_tc_hook_destroy(hook);
292 			return ret;
293 		}
294 	}
295 
296 	if (egr_fd >= 0) {
297 		hook->attach_point = BPF_TC_EGRESS;
298 		ret = bpf_tc_attach(hook, &opts2);
299 		if (!ASSERT_OK(ret, "bpf_tc_attach")) {
300 			bpf_tc_hook_destroy(hook);
301 			return ret;
302 		}
303 	}
304 
305 	return 0;
306 }
307 
test_vxlan_tunnel(void)308 static void test_vxlan_tunnel(void)
309 {
310 	struct test_tunnel_kern *skel = NULL;
311 	struct nstoken *nstoken;
312 	int local_ip_map_fd = -1;
313 	int set_src_prog_fd, get_src_prog_fd;
314 	int set_dst_prog_fd;
315 	int key = 0, ifindex = -1;
316 	uint local_ip;
317 	int err;
318 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
319 			    .attach_point = BPF_TC_INGRESS);
320 
321 	/* add vxlan tunnel */
322 	err = add_vxlan_tunnel();
323 	if (!ASSERT_OK(err, "add vxlan tunnel"))
324 		goto done;
325 
326 	/* load and attach bpf prog to tunnel dev tc hook point */
327 	skel = test_tunnel_kern__open_and_load();
328 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
329 		goto done;
330 	ifindex = if_nametoindex(VXLAN_TUNL_DEV1);
331 	if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex"))
332 		goto done;
333 	tc_hook.ifindex = ifindex;
334 	get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
335 	set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
336 	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
337 		goto done;
338 	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
339 		goto done;
340 	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
341 		goto done;
342 
343 	/* load and attach bpf prog to veth dev tc hook point */
344 	ifindex = if_nametoindex("veth1");
345 	if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
346 		goto done;
347 	tc_hook.ifindex = ifindex;
348 	set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst);
349 	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
350 		goto done;
351 	if (attach_tc_prog(&tc_hook, set_dst_prog_fd, -1))
352 		goto done;
353 
354 	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
355 	nstoken = open_netns("at_ns0");
356 	if (!ASSERT_OK_PTR(nstoken, "setns src"))
357 		goto done;
358 	ifindex = if_nametoindex(VXLAN_TUNL_DEV0);
359 	if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex"))
360 		goto done;
361 	tc_hook.ifindex = ifindex;
362 	set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
363 	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
364 		goto done;
365 	if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
366 		goto done;
367 	close_netns(nstoken);
368 
369 	/* use veth1 ip 2 as tunnel source ip */
370 	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
371 	if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
372 		goto done;
373 	local_ip = IP4_ADDR2_HEX_VETH1;
374 	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
375 	if (!ASSERT_OK(err, "update bpf local_ip_map"))
376 		goto done;
377 
378 	/* ping test */
379 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
380 	if (!ASSERT_OK(err, "test_ping"))
381 		goto done;
382 
383 done:
384 	/* delete vxlan tunnel */
385 	delete_vxlan_tunnel();
386 	if (local_ip_map_fd >= 0)
387 		close(local_ip_map_fd);
388 	if (skel)
389 		test_tunnel_kern__destroy(skel);
390 }
391 
test_ip6vxlan_tunnel(void)392 static void test_ip6vxlan_tunnel(void)
393 {
394 	struct test_tunnel_kern *skel = NULL;
395 	struct nstoken *nstoken;
396 	int local_ip_map_fd = -1;
397 	int set_src_prog_fd, get_src_prog_fd;
398 	int set_dst_prog_fd;
399 	int key = 0, ifindex = -1;
400 	uint local_ip;
401 	int err;
402 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
403 			    .attach_point = BPF_TC_INGRESS);
404 
405 	/* add vxlan tunnel */
406 	err = add_ip6vxlan_tunnel();
407 	if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
408 		goto done;
409 
410 	/* load and attach bpf prog to tunnel dev tc hook point */
411 	skel = test_tunnel_kern__open_and_load();
412 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
413 		goto done;
414 	ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1);
415 	if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex"))
416 		goto done;
417 	tc_hook.ifindex = ifindex;
418 	get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
419 	set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
420 	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
421 		goto done;
422 	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
423 		goto done;
424 	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
425 		goto done;
426 
427 	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
428 	nstoken = open_netns("at_ns0");
429 	if (!ASSERT_OK_PTR(nstoken, "setns src"))
430 		goto done;
431 	ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0);
432 	if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex"))
433 		goto done;
434 	tc_hook.ifindex = ifindex;
435 	set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
436 	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
437 		goto done;
438 	if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
439 		goto done;
440 	close_netns(nstoken);
441 
442 	/* use veth1 ip 2 as tunnel source ip */
443 	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
444 	if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
445 		goto done;
446 	local_ip = IP6_ADDR2_HEX_VETH1;
447 	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
448 	if (!ASSERT_OK(err, "update bpf local_ip_map"))
449 		goto done;
450 
451 	/* ping test */
452 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
453 	if (!ASSERT_OK(err, "test_ping"))
454 		goto done;
455 
456 done:
457 	/* delete ipv6 vxlan tunnel */
458 	delete_ip6vxlan_tunnel();
459 	if (local_ip_map_fd >= 0)
460 		close(local_ip_map_fd);
461 	if (skel)
462 		test_tunnel_kern__destroy(skel);
463 }
464 
test_ipip_tunnel(enum ipip_encap encap)465 static void test_ipip_tunnel(enum ipip_encap encap)
466 {
467 	struct test_tunnel_kern *skel = NULL;
468 	struct nstoken *nstoken;
469 	int set_src_prog_fd, get_src_prog_fd;
470 	int ifindex = -1;
471 	int err;
472 	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
473 			    .attach_point = BPF_TC_INGRESS);
474 
475 	/* add ipip tunnel */
476 	err = add_ipip_tunnel(encap);
477 	if (!ASSERT_OK(err, "add_ipip_tunnel"))
478 		goto done;
479 
480 	/* load and attach bpf prog to tunnel dev tc hook point */
481 	skel = test_tunnel_kern__open_and_load();
482 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
483 		goto done;
484 	ifindex = if_nametoindex(IPIP_TUNL_DEV1);
485 	if (!ASSERT_NEQ(ifindex, 0, "ipip11 ifindex"))
486 		goto done;
487 	tc_hook.ifindex = ifindex;
488 
489 	switch (encap) {
490 	case FOU:
491 		get_src_prog_fd = bpf_program__fd(
492 			skel->progs.ipip_encap_get_tunnel);
493 		set_src_prog_fd = bpf_program__fd(
494 			skel->progs.ipip_fou_set_tunnel);
495 		break;
496 	case GUE:
497 		get_src_prog_fd = bpf_program__fd(
498 			skel->progs.ipip_encap_get_tunnel);
499 		set_src_prog_fd = bpf_program__fd(
500 			skel->progs.ipip_gue_set_tunnel);
501 		break;
502 	default:
503 		get_src_prog_fd = bpf_program__fd(
504 			skel->progs.ipip_get_tunnel);
505 		set_src_prog_fd = bpf_program__fd(
506 			skel->progs.ipip_set_tunnel);
507 	}
508 
509 	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
510 		goto done;
511 	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
512 		goto done;
513 	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
514 		goto done;
515 
516 	/* ping from root namespace test */
517 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
518 	if (!ASSERT_OK(err, "test_ping"))
519 		goto done;
520 
521 	/* ping from at_ns0 namespace test */
522 	nstoken = open_netns("at_ns0");
523 	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
524 	if (!ASSERT_OK(err, "test_ping"))
525 		goto done;
526 	close_netns(nstoken);
527 
528 done:
529 	/* delete ipip tunnel */
530 	delete_ipip_tunnel();
531 	if (skel)
532 		test_tunnel_kern__destroy(skel);
533 }
534 
535 #define RUN_TEST(name, ...)						\
536 	({								\
537 		if (test__start_subtest(#name)) {			\
538 			test_ ## name(__VA_ARGS__);			\
539 		}							\
540 	})
541 
test_tunnel_run_tests(void * arg)542 static void *test_tunnel_run_tests(void *arg)
543 {
544 	cleanup();
545 	config_device();
546 
547 	RUN_TEST(vxlan_tunnel);
548 	RUN_TEST(ip6vxlan_tunnel);
549 	RUN_TEST(ipip_tunnel, NONE);
550 	RUN_TEST(ipip_tunnel, FOU);
551 	RUN_TEST(ipip_tunnel, GUE);
552 
553 	cleanup();
554 
555 	return NULL;
556 }
557 
test_tunnel(void)558 void test_tunnel(void)
559 {
560 	pthread_t test_thread;
561 	int err;
562 
563 	/* Run the tests in their own thread to isolate the namespace changes
564 	 * so they do not affect the environment of other tests.
565 	 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
566 	 */
567 	err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
568 	if (ASSERT_OK(err, "pthread_create"))
569 		ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
570 }
571