xref: /linux/tools/testing/selftests/bpf/prog_tests/test_tunnel.c (revision 015e7b0b0e8e51f7321ec2aafc1d7fc0a8a5536f)
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 #define IP6_ADDR_TUNL_DEV0 "fc80::100"
75 #define IP6_ADDR_TUNL_DEV1 "fc80::200"
76 
77 #define IP6_ADDR_VETH0 "::11"
78 #define IP6_ADDR1_VETH1 "::22"
79 #define IP6_ADDR2_VETH1 "::bb"
80 
81 #define IP4_ADDR1_HEX_VETH1 0xac1001c8
82 #define IP4_ADDR2_HEX_VETH1 0xac100114
83 #define IP6_ADDR1_HEX_VETH1 0x22
84 #define IP6_ADDR2_HEX_VETH1 0xbb
85 
86 #define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
87 #define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
88 #define MAC_VETH1 "52:54:00:d9:03:00"
89 
90 #define VXLAN_TUNL_DEV0 "vxlan00"
91 #define VXLAN_TUNL_DEV1 "vxlan11"
92 #define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
93 #define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
94 
95 #define IPIP_TUNL_DEV0 "ipip00"
96 #define IPIP_TUNL_DEV1 "ipip11"
97 
98 #define XFRM_AUTH "0x1111111111111111111111111111111111111111"
99 #define XFRM_ENC "0x22222222222222222222222222222222"
100 #define XFRM_SPI_IN_TO_OUT 0x1
101 #define XFRM_SPI_OUT_TO_IN 0x2
102 
103 #define GRE_TUNL_DEV0 "gre00"
104 #define GRE_TUNL_DEV1 "gre11"
105 
106 #define IP6GRE_TUNL_DEV0 "ip6gre00"
107 #define IP6GRE_TUNL_DEV1 "ip6gre11"
108 
109 #define ERSPAN_TUNL_DEV0 "erspan00"
110 #define ERSPAN_TUNL_DEV1 "erspan11"
111 
112 #define IP6ERSPAN_TUNL_DEV0 "ip6erspan00"
113 #define IP6ERSPAN_TUNL_DEV1 "ip6erspan11"
114 
115 #define GENEVE_TUNL_DEV0 "geneve00"
116 #define GENEVE_TUNL_DEV1 "geneve11"
117 
118 #define IP6GENEVE_TUNL_DEV0 "ip6geneve00"
119 #define IP6GENEVE_TUNL_DEV1 "ip6geneve11"
120 
121 #define IP6TNL_TUNL_DEV0 "ip6tnl00"
122 #define IP6TNL_TUNL_DEV1 "ip6tnl11"
123 
124 #define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
125 
126 static int config_device(void)
127 {
128 	SYS(fail, "ip netns add at_ns0");
129 	SYS(fail, "ip link add veth0 address " MAC_VETH1 " type veth peer name veth1");
130 	SYS(fail, "ip link set veth0 netns at_ns0");
131 	SYS(fail, "ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
132 	SYS(fail, "ip link set dev veth1 up mtu 1500");
133 	SYS(fail, "ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
134 	SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
135 
136 	return 0;
137 fail:
138 	return -1;
139 }
140 
141 static void cleanup(void)
142 {
143 	SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
144 	SYS_NOFAIL("ip link del veth1");
145 	SYS_NOFAIL("ip link del %s", VXLAN_TUNL_DEV1);
146 	SYS_NOFAIL("ip link del %s", IP6VXLAN_TUNL_DEV1);
147 }
148 
149 static int add_vxlan_tunnel(void)
150 {
151 	/* at_ns0 namespace */
152 	SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
153 	    VXLAN_TUNL_DEV0);
154 	SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
155 	    VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
156 	SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
157 	    VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
158 	SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
159 	    IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
160 	SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0",
161 	    IP4_ADDR2_VETH1, MAC_VETH1);
162 
163 	/* root namespace */
164 	SYS(fail, "ip link add dev %s type vxlan external gbp dstport 4789",
165 	    VXLAN_TUNL_DEV1);
166 	SYS(fail, "ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
167 	SYS(fail, "ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
168 	SYS(fail, "ip neigh add %s lladdr %s dev %s",
169 	    IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
170 
171 	return 0;
172 fail:
173 	return -1;
174 }
175 
176 static void delete_vxlan_tunnel(void)
177 {
178 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
179 		   VXLAN_TUNL_DEV0);
180 	SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
181 }
182 
183 static int add_ip6vxlan_tunnel(void)
184 {
185 	SYS(fail, "ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
186 	    IP6_ADDR_VETH0);
187 	SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up");
188 	SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
189 	SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
190 	SYS(fail, "ip link set dev veth1 up");
191 
192 	/* at_ns0 namespace */
193 	SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
194 	    IP6VXLAN_TUNL_DEV0);
195 	SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24",
196 	    IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
197 	SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up",
198 	    IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
199 
200 	/* root namespace */
201 	SYS(fail, "ip link add dev %s type vxlan external dstport 4789",
202 	    IP6VXLAN_TUNL_DEV1);
203 	SYS(fail, "ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
204 	SYS(fail, "ip link set dev %s address %s up",
205 	    IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
206 
207 	return 0;
208 fail:
209 	return -1;
210 }
211 
212 static void delete_ip6vxlan_tunnel(void)
213 {
214 	SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
215 		   IP6_ADDR_VETH0);
216 	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
217 	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
218 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
219 		   IP6VXLAN_TUNL_DEV0);
220 	SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
221 }
222 
223 enum ipip_encap {
224 	NONE	= 0,
225 	FOU	= 1,
226 	GUE	= 2,
227 };
228 
229 static int set_ipip_encap(const char *ipproto, const char *type)
230 {
231 	SYS(fail, "ip -n at_ns0 fou add port 5555 %s", ipproto);
232 	SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap %s",
233 	    IPIP_TUNL_DEV0, type);
234 	SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap-dport 5555",
235 	    IPIP_TUNL_DEV0);
236 
237 	return 0;
238 fail:
239 	return -1;
240 }
241 
242 static int set_ipv4_addr(const char *dev0, const char *dev1)
243 {
244 	SYS(fail, "ip -n at_ns0 link set dev %s up", dev0);
245 	SYS(fail, "ip -n at_ns0 addr add dev %s %s/24", dev0, IP4_ADDR_TUNL_DEV0);
246 	SYS(fail, "ip link set dev %s up", dev1);
247 	SYS(fail, "ip addr add dev %s %s/24", dev1, IP4_ADDR_TUNL_DEV1);
248 
249 	return 0;
250 fail:
251 	return 1;
252 }
253 
254 static int add_ipip_tunnel(enum ipip_encap encap)
255 {
256 	int err;
257 	const char *ipproto, *type;
258 
259 	switch (encap) {
260 	case FOU:
261 		ipproto = "ipproto 4";
262 		type = "fou";
263 		break;
264 	case GUE:
265 		ipproto = "gue";
266 		type = ipproto;
267 		break;
268 	default:
269 		ipproto = NULL;
270 		type = ipproto;
271 	}
272 
273 	/* at_ns0 namespace */
274 	SYS(fail, "ip -n at_ns0 link add dev %s type ipip local %s remote %s",
275 	    IPIP_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
276 
277 	if (type && ipproto) {
278 		err = set_ipip_encap(ipproto, type);
279 		if (!ASSERT_OK(err, "set_ipip_encap"))
280 			goto fail;
281 	}
282 
283 	SYS(fail, "ip -n at_ns0 link set dev %s up", IPIP_TUNL_DEV0);
284 	SYS(fail, "ip -n at_ns0 addr add dev %s %s/24",
285 	    IPIP_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
286 
287 	/* root namespace */
288 	if (type && ipproto)
289 		SYS(fail, "ip fou add port 5555 %s", ipproto);
290 	SYS(fail, "ip link add dev %s type ipip external", IPIP_TUNL_DEV1);
291 	SYS(fail, "ip link set dev %s up", IPIP_TUNL_DEV1);
292 	SYS(fail, "ip addr add dev %s %s/24", IPIP_TUNL_DEV1,
293 	    IP4_ADDR_TUNL_DEV1);
294 
295 	return 0;
296 fail:
297 	return -1;
298 }
299 
300 static void delete_ipip_tunnel(void)
301 {
302 	SYS_NOFAIL("ip -n at_ns0 link delete dev %s", IPIP_TUNL_DEV0);
303 	SYS_NOFAIL("ip -n at_ns0 fou del port 5555");
304 	SYS_NOFAIL("ip link delete dev %s", IPIP_TUNL_DEV1);
305 	SYS_NOFAIL("ip fou del port 5555");
306 }
307 
308 static int add_xfrm_tunnel(void)
309 {
310 	/* at_ns0 namespace
311 	 * at_ns0 -> root
312 	 */
313 	SYS(fail,
314 	    "ip netns exec at_ns0 "
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 netns exec at_ns0 "
321 		"ip xfrm policy add src %s/32 dst %s/32 dir out "
322 			"tmpl src %s dst %s proto esp reqid 1 "
323 			"mode tunnel",
324 	    IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
325 
326 	/* root -> at_ns0 */
327 	SYS(fail,
328 	    "ip netns exec at_ns0 "
329 		"ip xfrm state add src %s dst %s proto esp "
330 			"spi %d reqid 2 mode tunnel "
331 			"auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
332 	    IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
333 	SYS(fail,
334 	    "ip netns exec at_ns0 "
335 		"ip xfrm policy add src %s/32 dst %s/32 dir in "
336 			"tmpl src %s dst %s proto esp reqid 2 "
337 			"mode tunnel",
338 	    IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
339 
340 	/* address & route */
341 	SYS(fail, "ip netns exec at_ns0 ip addr add dev veth0 %s/32",
342 	    IP4_ADDR_TUNL_DEV0);
343 	SYS(fail, "ip netns exec at_ns0 ip route add %s dev veth0 via %s src %s",
344 	    IP4_ADDR_TUNL_DEV1, IP4_ADDR1_VETH1, IP4_ADDR_TUNL_DEV0);
345 
346 	/* root namespace
347 	 * at_ns0 -> root
348 	 */
349 	SYS(fail,
350 	    "ip xfrm state add src %s dst %s proto esp "
351 		    "spi %d reqid 1 mode tunnel replay-window 42 "
352 		    "auth-trunc 'hmac(sha1)' %s 96  enc 'cbc(aes)' %s",
353 	    IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
354 	SYS(fail,
355 	    "ip xfrm policy add src %s/32 dst %s/32 dir in "
356 		    "tmpl src %s dst %s proto esp reqid 1 "
357 		    "mode tunnel",
358 	    IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
359 
360 	/* root -> at_ns0 */
361 	SYS(fail,
362 	    "ip xfrm state add src %s dst %s proto esp "
363 		    "spi %d reqid 2 mode tunnel "
364 		    "auth-trunc 'hmac(sha1)' %s 96  enc 'cbc(aes)' %s",
365 	    IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
366 	SYS(fail,
367 	    "ip xfrm policy add src %s/32 dst %s/32 dir out "
368 		    "tmpl src %s dst %s proto esp reqid 2 "
369 		    "mode tunnel",
370 	    IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
371 
372 	/* address & route */
373 	SYS(fail, "ip addr add dev veth1 %s/32", IP4_ADDR_TUNL_DEV1);
374 	SYS(fail, "ip route add %s dev veth1 via %s src %s",
375 	    IP4_ADDR_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR_TUNL_DEV1);
376 
377 	return 0;
378 fail:
379 	return -1;
380 }
381 
382 static void delete_xfrm_tunnel(void)
383 {
384 	SYS_NOFAIL("ip xfrm policy delete dir out src %s/32 dst %s/32",
385 		   IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0);
386 	SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32",
387 		   IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1);
388 	SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d",
389 		   IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT);
390 	SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d",
391 		   IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN);
392 }
393 
394 static int add_ipv4_tunnel(const char *dev0, const char *dev1,
395 			   const char *type, const char *opt)
396 {
397 	if (!type || !opt || !dev0 || !dev1)
398 		return -1;
399 
400 	SYS(fail, "ip -n at_ns0 link add dev %s type %s %s local %s remote %s",
401 	    dev0, type, opt, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
402 
403 	SYS(fail, "ip link add dev %s type %s external", dev1, type);
404 
405 	return set_ipv4_addr(dev0, dev1);
406 fail:
407 	return -1;
408 }
409 
410 static void delete_tunnel(const char *dev0, const char *dev1)
411 {
412 	if (!dev0 || !dev1)
413 		return;
414 
415 	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s", dev0);
416 	SYS_NOFAIL("ip link delete dev %s", dev1);
417 }
418 
419 static int set_ipv6_addr(const char *dev0, const char *dev1)
420 {
421 	/* disable IPv6 DAD because it might take too long and fail tests */
422 	SYS(fail, "ip -n at_ns0 addr add %s/96 dev veth0 nodad", IP6_ADDR_VETH0);
423 	SYS(fail, "ip -n at_ns0 link set dev veth0 up");
424 	SYS(fail, "ip addr add %s/96 dev veth1 nodad", IP6_ADDR1_VETH1);
425 	SYS(fail, "ip link set dev veth1 up");
426 
427 	SYS(fail, "ip -n at_ns0 addr add dev %s %s/24", dev0, IP4_ADDR_TUNL_DEV0);
428 	SYS(fail, "ip -n at_ns0 addr add dev %s %s/96 nodad", dev0, IP6_ADDR_TUNL_DEV0);
429 	SYS(fail, "ip -n at_ns0 link set dev %s up", dev0);
430 
431 	SYS(fail, "ip addr add dev %s %s/24", dev1, IP4_ADDR_TUNL_DEV1);
432 	SYS(fail, "ip addr add dev %s %s/96 nodad", dev1, IP6_ADDR_TUNL_DEV1);
433 	SYS(fail, "ip link set dev %s up", dev1);
434 	return 0;
435 fail:
436 	return 1;
437 }
438 
439 static int add_ipv6_tunnel(const char *dev0, const char *dev1,
440 			   const char *type, const char *opt)
441 {
442 	if (!type || !opt || !dev0 || !dev1)
443 		return -1;
444 
445 	SYS(fail, "ip -n at_ns0 link add dev %s type %s %s local %s remote %s",
446 	    dev0, type, opt, IP6_ADDR_VETH0, IP6_ADDR1_VETH1);
447 
448 	SYS(fail, "ip link add dev %s type %s external", dev1, type);
449 
450 	return set_ipv6_addr(dev0, dev1);
451 fail:
452 	return -1;
453 }
454 
455 static int add_geneve_tunnel(const char *dev0, const char *dev1,
456 			     const char *type, const char *opt)
457 {
458 	if (!type || !opt || !dev0 || !dev1)
459 		return -1;
460 
461 	SYS(fail, "ip -n at_ns0 link add dev %s type %s id 2 %s remote %s",
462 	    dev0, type, opt, IP4_ADDR1_VETH1);
463 
464 	SYS(fail, "ip link add dev %s type %s %s external", dev1, type, opt);
465 
466 	return set_ipv4_addr(dev0, dev1);
467 fail:
468 	return -1;
469 }
470 
471 static int add_ip6geneve_tunnel(const char *dev0, const char *dev1,
472 			     const char *type, const char *opt)
473 {
474 	if (!type || !opt || !dev0 || !dev1)
475 		return -1;
476 
477 	SYS(fail, "ip -n at_ns0 link add dev %s type %s id 22 %s remote %s",
478 	    dev0, type, opt, IP6_ADDR1_VETH1);
479 
480 	SYS(fail, "ip link add dev %s type %s %s external", dev1, type, opt);
481 
482 	return set_ipv6_addr(dev0, dev1);
483 fail:
484 	return -1;
485 }
486 
487 static int test_ping(int family, const char *addr)
488 {
489 	SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
490 	return 0;
491 fail:
492 	return -1;
493 }
494 
495 static void ping_dev0(void)
496 {
497 	/* ping from root namespace test */
498 	test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
499 }
500 
501 static void ping_dev1(void)
502 {
503 	struct nstoken *nstoken;
504 
505 	/* ping from at_ns0 namespace test */
506 	nstoken = open_netns("at_ns0");
507 	if (!ASSERT_OK_PTR(nstoken, "setns"))
508 		return;
509 
510 	test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
511 	close_netns(nstoken);
512 }
513 
514 static void ping6_veth0(void)
515 {
516 	test_ping(AF_INET6, IP6_ADDR_VETH0);
517 }
518 
519 static void ping6_dev0(void)
520 {
521 	test_ping(AF_INET6, IP6_ADDR_TUNL_DEV0);
522 }
523 
524 static void ping6_dev1(void)
525 {
526 	struct nstoken *nstoken;
527 
528 	/* ping from at_ns0 namespace test */
529 	nstoken = open_netns("at_ns0");
530 	if (!ASSERT_OK_PTR(nstoken, "setns"))
531 		return;
532 
533 	test_ping(AF_INET, IP6_ADDR_TUNL_DEV1);
534 	close_netns(nstoken);
535 }
536 
537 static void test_vxlan_tunnel(void)
538 {
539 	struct test_tunnel_kern *skel = NULL;
540 	struct nstoken *nstoken;
541 	int local_ip_map_fd = -1;
542 	int set_src_prog_fd, get_src_prog_fd;
543 	int set_dst_prog_fd;
544 	int key = 0;
545 	uint local_ip;
546 	int err;
547 
548 	/* add vxlan tunnel */
549 	err = add_vxlan_tunnel();
550 	if (!ASSERT_OK(err, "add vxlan tunnel"))
551 		goto done;
552 
553 	/* load and attach bpf prog to tunnel dev tc hook point */
554 	skel = test_tunnel_kern__open_and_load();
555 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
556 		goto done;
557 	get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
558 	set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
559 	if (tc_prog_attach(VXLAN_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd))
560 		goto done;
561 
562 	/* load and attach bpf prog to veth dev tc hook point */
563 	set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst);
564 	if (tc_prog_attach("veth1", set_dst_prog_fd, -1))
565 		goto done;
566 
567 	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
568 	nstoken = open_netns("at_ns0");
569 	if (!ASSERT_OK_PTR(nstoken, "setns src"))
570 		goto done;
571 	set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
572 	if (tc_prog_attach(VXLAN_TUNL_DEV0, -1, set_dst_prog_fd))
573 		goto done;
574 	close_netns(nstoken);
575 
576 	/* use veth1 ip 2 as tunnel source ip */
577 	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
578 	if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
579 		goto done;
580 	local_ip = IP4_ADDR2_HEX_VETH1;
581 	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
582 	if (!ASSERT_OK(err, "update bpf local_ip_map"))
583 		goto done;
584 
585 	/* ping test */
586 	ping_dev0();
587 
588 done:
589 	/* delete vxlan tunnel */
590 	delete_vxlan_tunnel();
591 	if (local_ip_map_fd >= 0)
592 		close(local_ip_map_fd);
593 	if (skel)
594 		test_tunnel_kern__destroy(skel);
595 }
596 
597 static void test_ip6vxlan_tunnel(void)
598 {
599 	struct test_tunnel_kern *skel = NULL;
600 	struct nstoken *nstoken;
601 	int local_ip_map_fd = -1;
602 	int set_src_prog_fd, get_src_prog_fd;
603 	int set_dst_prog_fd;
604 	int key = 0;
605 	uint local_ip;
606 	int err;
607 
608 	/* add vxlan tunnel */
609 	err = add_ip6vxlan_tunnel();
610 	if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
611 		goto done;
612 
613 	/* load and attach bpf prog to tunnel dev tc hook point */
614 	skel = test_tunnel_kern__open_and_load();
615 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
616 		goto done;
617 	get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
618 	set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
619 	if (tc_prog_attach(IP6VXLAN_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd))
620 		goto done;
621 
622 	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
623 	nstoken = open_netns("at_ns0");
624 	if (!ASSERT_OK_PTR(nstoken, "setns src"))
625 		goto done;
626 	set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
627 	if (tc_prog_attach(IP6VXLAN_TUNL_DEV0, -1, set_dst_prog_fd))
628 		goto done;
629 	close_netns(nstoken);
630 
631 	/* use veth1 ip 2 as tunnel source ip */
632 	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
633 	if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
634 		goto done;
635 	local_ip = IP6_ADDR2_HEX_VETH1;
636 	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
637 	if (!ASSERT_OK(err, "update bpf local_ip_map"))
638 		goto done;
639 
640 	/* ping test */
641 	ping_dev0();
642 
643 done:
644 	/* delete ipv6 vxlan tunnel */
645 	delete_ip6vxlan_tunnel();
646 	if (local_ip_map_fd >= 0)
647 		close(local_ip_map_fd);
648 	if (skel)
649 		test_tunnel_kern__destroy(skel);
650 }
651 
652 static void test_ipip_tunnel(enum ipip_encap encap)
653 {
654 	struct test_tunnel_kern *skel = NULL;
655 	int set_src_prog_fd, get_src_prog_fd;
656 	int err;
657 
658 	/* add ipip tunnel */
659 	err = add_ipip_tunnel(encap);
660 	if (!ASSERT_OK(err, "add_ipip_tunnel"))
661 		goto done;
662 
663 	/* load and attach bpf prog to tunnel dev tc hook point */
664 	skel = test_tunnel_kern__open_and_load();
665 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
666 		goto done;
667 
668 	switch (encap) {
669 	case FOU:
670 		get_src_prog_fd = bpf_program__fd(
671 			skel->progs.ipip_encap_get_tunnel);
672 		set_src_prog_fd = bpf_program__fd(
673 			skel->progs.ipip_fou_set_tunnel);
674 		break;
675 	case GUE:
676 		get_src_prog_fd = bpf_program__fd(
677 			skel->progs.ipip_encap_get_tunnel);
678 		set_src_prog_fd = bpf_program__fd(
679 			skel->progs.ipip_gue_set_tunnel);
680 		break;
681 	default:
682 		get_src_prog_fd = bpf_program__fd(
683 			skel->progs.ipip_get_tunnel);
684 		set_src_prog_fd = bpf_program__fd(
685 			skel->progs.ipip_set_tunnel);
686 	}
687 
688 	if (tc_prog_attach(IPIP_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd))
689 		goto done;
690 
691 	ping_dev0();
692 	ping_dev1();
693 
694 done:
695 	/* delete ipip tunnel */
696 	delete_ipip_tunnel();
697 	if (skel)
698 		test_tunnel_kern__destroy(skel);
699 }
700 
701 static void test_xfrm_tunnel(void)
702 {
703 	LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
704 	struct test_tunnel_kern *skel = NULL;
705 	int xdp_prog_fd;
706 	int tc_prog_fd;
707 	int ifindex;
708 	int err;
709 
710 	err = add_xfrm_tunnel();
711 	if (!ASSERT_OK(err, "add_xfrm_tunnel"))
712 		return;
713 
714 	skel = test_tunnel_kern__open_and_load();
715 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
716 		goto done;
717 
718 
719 	/* attach tc prog to tunnel dev */
720 	tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state);
721 	if (tc_prog_attach("veth1", tc_prog_fd, -1))
722 		goto done;
723 
724 	/* attach xdp prog to tunnel dev */
725 	ifindex = if_nametoindex("veth1");
726 	if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
727 		goto done;
728 	xdp_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state_xdp);
729 	if (!ASSERT_GE(xdp_prog_fd, 0, "bpf_program__fd"))
730 		goto done;
731 	err = bpf_xdp_attach(ifindex, xdp_prog_fd, XDP_FLAGS_REPLACE, &opts);
732 	if (!ASSERT_OK(err, "bpf_xdp_attach"))
733 		goto done;
734 
735 	ping_dev1();
736 
737 	if (!ASSERT_EQ(skel->bss->xfrm_reqid, 1, "req_id"))
738 		goto done;
739 	if (!ASSERT_EQ(skel->bss->xfrm_spi, XFRM_SPI_IN_TO_OUT, "spi"))
740 		goto done;
741 	if (!ASSERT_EQ(skel->bss->xfrm_remote_ip, 0xac100164, "remote_ip"))
742 		goto done;
743 	if (!ASSERT_EQ(skel->bss->xfrm_replay_window, 42, "replay_window"))
744 		goto done;
745 
746 done:
747 	delete_xfrm_tunnel();
748 	if (skel)
749 		test_tunnel_kern__destroy(skel);
750 }
751 
752 enum gre_test {
753 	GRE,
754 	GRE_NOKEY,
755 	GRETAP,
756 	GRETAP_NOKEY,
757 };
758 
759 static void test_gre_tunnel(enum gre_test test)
760 {
761 	struct test_tunnel_kern *skel;
762 	int set_fd, get_fd;
763 	int err;
764 
765 	skel = test_tunnel_kern__open_and_load();
766 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
767 		return;
768 
769 	switch (test) {
770 	case GRE:
771 		err = add_ipv4_tunnel(GRE_TUNL_DEV0, GRE_TUNL_DEV1, "gre", "seq");
772 		set_fd = bpf_program__fd(skel->progs.gre_set_tunnel_no_key);
773 		get_fd = bpf_program__fd(skel->progs.gre_get_tunnel);
774 		break;
775 	case GRE_NOKEY:
776 		err = add_ipv4_tunnel(GRE_TUNL_DEV0, GRE_TUNL_DEV1, "gre", "seq key 2");
777 		set_fd = bpf_program__fd(skel->progs.gre_set_tunnel);
778 		get_fd = bpf_program__fd(skel->progs.gre_get_tunnel);
779 		break;
780 	case GRETAP:
781 		err = add_ipv4_tunnel(GRE_TUNL_DEV0, GRE_TUNL_DEV1, "gretap", "seq");
782 		set_fd = bpf_program__fd(skel->progs.gre_set_tunnel_no_key);
783 		get_fd = bpf_program__fd(skel->progs.gre_get_tunnel);
784 		break;
785 	case GRETAP_NOKEY:
786 		err = add_ipv4_tunnel(GRE_TUNL_DEV0, GRE_TUNL_DEV1, "gretap", "seq key 2");
787 		set_fd = bpf_program__fd(skel->progs.gre_set_tunnel);
788 		get_fd = bpf_program__fd(skel->progs.gre_get_tunnel);
789 		break;
790 	}
791 	if (!ASSERT_OK(err, "add tunnel"))
792 		goto done;
793 
794 	if (tc_prog_attach(GRE_TUNL_DEV1, get_fd, set_fd))
795 		goto done;
796 
797 	ping_dev0();
798 	ping_dev1();
799 
800 done:
801 	delete_tunnel(GRE_TUNL_DEV0, GRE_TUNL_DEV1);
802 	test_tunnel_kern__destroy(skel);
803 }
804 
805 enum ip6gre_test {
806 	IP6GRE,
807 	IP6GRETAP
808 };
809 
810 static void test_ip6gre_tunnel(enum ip6gre_test test)
811 {
812 	struct test_tunnel_kern *skel;
813 	int set_fd, get_fd;
814 	int err;
815 
816 	skel = test_tunnel_kern__open_and_load();
817 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
818 		return;
819 
820 	switch (test) {
821 	case IP6GRE:
822 		err = add_ipv6_tunnel(IP6GRE_TUNL_DEV0, IP6GRE_TUNL_DEV1,
823 				      "ip6gre", "flowlabel 0xbcdef key 2");
824 		break;
825 	case IP6GRETAP:
826 		err = add_ipv6_tunnel(IP6GRE_TUNL_DEV0, IP6GRE_TUNL_DEV1,
827 				      "ip6gretap", "flowlabel 0xbcdef key 2");
828 		break;
829 	}
830 	if (!ASSERT_OK(err, "add tunnel"))
831 		goto done;
832 
833 	set_fd = bpf_program__fd(skel->progs.ip6gretap_set_tunnel);
834 	get_fd = bpf_program__fd(skel->progs.ip6gretap_get_tunnel);
835 	if (tc_prog_attach(IP6GRE_TUNL_DEV1, get_fd, set_fd))
836 		goto done;
837 
838 	ping6_veth0();
839 	ping6_dev1();
840 	ping_dev0();
841 	ping_dev1();
842 done:
843 	delete_tunnel(IP6GRE_TUNL_DEV0, IP6GRE_TUNL_DEV1);
844 	test_tunnel_kern__destroy(skel);
845 }
846 
847 enum erspan_test {
848 	V1,
849 	V2
850 };
851 
852 static void test_erspan_tunnel(enum erspan_test test)
853 {
854 	struct test_tunnel_kern *skel;
855 	int set_fd, get_fd;
856 	int err;
857 
858 	skel = test_tunnel_kern__open_and_load();
859 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
860 		return;
861 
862 	switch (test) {
863 	case V1:
864 		err = add_ipv4_tunnel(ERSPAN_TUNL_DEV0, ERSPAN_TUNL_DEV1,
865 				      "erspan", "seq key 2 erspan_ver 1 erspan 123");
866 		break;
867 	case V2:
868 		err = add_ipv4_tunnel(ERSPAN_TUNL_DEV0, ERSPAN_TUNL_DEV1,
869 				      "erspan",
870 				      "seq key 2 erspan_ver 2 erspan_dir egress erspan_hwid 3");
871 		break;
872 	}
873 	if (!ASSERT_OK(err, "add tunnel"))
874 		goto done;
875 
876 	set_fd = bpf_program__fd(skel->progs.erspan_set_tunnel);
877 	get_fd = bpf_program__fd(skel->progs.erspan_get_tunnel);
878 	if (tc_prog_attach(ERSPAN_TUNL_DEV1, get_fd, set_fd))
879 		goto done;
880 
881 	ping_dev0();
882 	ping_dev1();
883 done:
884 	delete_tunnel(ERSPAN_TUNL_DEV0, ERSPAN_TUNL_DEV1);
885 	test_tunnel_kern__destroy(skel);
886 }
887 
888 static void test_ip6erspan_tunnel(enum erspan_test test)
889 {
890 	struct test_tunnel_kern *skel;
891 	int set_fd, get_fd;
892 	int err;
893 
894 	skel = test_tunnel_kern__open_and_load();
895 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
896 		return;
897 
898 	switch (test) {
899 	case V1:
900 		err = add_ipv6_tunnel(IP6ERSPAN_TUNL_DEV0, IP6ERSPAN_TUNL_DEV1,
901 				      "ip6erspan", "seq key 2 erspan_ver 1 erspan 123");
902 		break;
903 	case V2:
904 		err = add_ipv6_tunnel(IP6ERSPAN_TUNL_DEV0, IP6ERSPAN_TUNL_DEV1,
905 				      "ip6erspan",
906 				      "seq key 2 erspan_ver 2 erspan_dir egress erspan_hwid 7");
907 		break;
908 	}
909 	if (!ASSERT_OK(err, "add tunnel"))
910 		goto done;
911 
912 	set_fd = bpf_program__fd(skel->progs.ip4ip6erspan_set_tunnel);
913 	get_fd = bpf_program__fd(skel->progs.ip4ip6erspan_get_tunnel);
914 	if (tc_prog_attach(IP6ERSPAN_TUNL_DEV1, get_fd, set_fd))
915 		goto done;
916 
917 	ping6_veth0();
918 	ping_dev1();
919 done:
920 	delete_tunnel(IP6ERSPAN_TUNL_DEV0, IP6ERSPAN_TUNL_DEV1);
921 	test_tunnel_kern__destroy(skel);
922 }
923 
924 static void test_geneve_tunnel(void)
925 {
926 	struct test_tunnel_kern *skel;
927 	int set_fd, get_fd;
928 	int err;
929 
930 	skel = test_tunnel_kern__open_and_load();
931 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
932 		return;
933 
934 	err = add_geneve_tunnel(GENEVE_TUNL_DEV0, GENEVE_TUNL_DEV1,
935 				"geneve", "dstport 6081");
936 	if (!ASSERT_OK(err, "add tunnel"))
937 		goto done;
938 
939 	set_fd = bpf_program__fd(skel->progs.geneve_set_tunnel);
940 	get_fd = bpf_program__fd(skel->progs.geneve_get_tunnel);
941 	if (tc_prog_attach(GENEVE_TUNL_DEV1, get_fd, set_fd))
942 		goto done;
943 
944 	ping_dev0();
945 	ping_dev1();
946 done:
947 	delete_tunnel(GENEVE_TUNL_DEV0, GENEVE_TUNL_DEV1);
948 	test_tunnel_kern__destroy(skel);
949 }
950 
951 static void test_ip6geneve_tunnel(void)
952 {
953 	struct test_tunnel_kern *skel;
954 	int set_fd, get_fd;
955 	int err;
956 
957 	skel = test_tunnel_kern__open_and_load();
958 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
959 		return;
960 
961 	err = add_ip6geneve_tunnel(IP6GENEVE_TUNL_DEV0, IP6GENEVE_TUNL_DEV1,
962 				   "geneve", "");
963 	if (!ASSERT_OK(err, "add tunnel"))
964 		goto done;
965 
966 	set_fd = bpf_program__fd(skel->progs.ip6geneve_set_tunnel);
967 	get_fd = bpf_program__fd(skel->progs.ip6geneve_get_tunnel);
968 	if (tc_prog_attach(IP6GENEVE_TUNL_DEV1, get_fd, set_fd))
969 		goto done;
970 
971 	ping_dev0();
972 	ping_dev1();
973 done:
974 	delete_tunnel(IP6GENEVE_TUNL_DEV0, IP6GENEVE_TUNL_DEV1);
975 	test_tunnel_kern__destroy(skel);
976 }
977 
978 enum ip6tnl_test {
979 	IPIP6,
980 	IP6IP6
981 };
982 
983 static void test_ip6tnl_tunnel(enum ip6tnl_test test)
984 {
985 	struct test_tunnel_kern *skel;
986 	int set_fd, get_fd;
987 	int err;
988 
989 	skel = test_tunnel_kern__open_and_load();
990 	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
991 		return;
992 
993 	err = add_ipv6_tunnel(IP6TNL_TUNL_DEV0, IP6TNL_TUNL_DEV1, "ip6tnl", "");
994 	if (!ASSERT_OK(err, "add tunnel"))
995 		goto done;
996 
997 	switch (test) {
998 	case IPIP6:
999 		set_fd = bpf_program__fd(skel->progs.ipip6_set_tunnel);
1000 		get_fd = bpf_program__fd(skel->progs.ipip6_get_tunnel);
1001 		break;
1002 	case IP6IP6:
1003 		set_fd = bpf_program__fd(skel->progs.ip6ip6_set_tunnel);
1004 		get_fd = bpf_program__fd(skel->progs.ip6ip6_get_tunnel);
1005 		break;
1006 	}
1007 	if (tc_prog_attach(IP6TNL_TUNL_DEV1, get_fd, set_fd))
1008 		goto done;
1009 
1010 	ping6_veth0();
1011 	switch (test) {
1012 	case IPIP6:
1013 		ping_dev0();
1014 		ping_dev1();
1015 		break;
1016 	case IP6IP6:
1017 		ping6_dev0();
1018 		ping6_dev1();
1019 		break;
1020 	}
1021 
1022 done:
1023 	delete_tunnel(IP6TNL_TUNL_DEV0, IP6TNL_TUNL_DEV1);
1024 	test_tunnel_kern__destroy(skel);
1025 }
1026 
1027 #define RUN_TEST(name, ...)						\
1028 	({								\
1029 		if (test__start_subtest(#name)) {			\
1030 			config_device();				\
1031 			test_ ## name(__VA_ARGS__);			\
1032 			cleanup();					\
1033 		}							\
1034 	})
1035 
1036 static void *test_tunnel_run_tests(void *arg)
1037 {
1038 	RUN_TEST(vxlan_tunnel);
1039 	RUN_TEST(ip6vxlan_tunnel);
1040 	RUN_TEST(ipip_tunnel, NONE);
1041 	RUN_TEST(ipip_tunnel, FOU);
1042 	RUN_TEST(ipip_tunnel, GUE);
1043 	RUN_TEST(xfrm_tunnel);
1044 	RUN_TEST(gre_tunnel, GRE);
1045 	RUN_TEST(gre_tunnel, GRE_NOKEY);
1046 	RUN_TEST(gre_tunnel, GRETAP);
1047 	RUN_TEST(gre_tunnel, GRETAP_NOKEY);
1048 	RUN_TEST(ip6gre_tunnel, IP6GRE);
1049 	RUN_TEST(ip6gre_tunnel, IP6GRETAP);
1050 	RUN_TEST(erspan_tunnel, V1);
1051 	RUN_TEST(erspan_tunnel, V2);
1052 	RUN_TEST(ip6erspan_tunnel, V1);
1053 	RUN_TEST(ip6erspan_tunnel, V2);
1054 	RUN_TEST(geneve_tunnel);
1055 	RUN_TEST(ip6geneve_tunnel);
1056 	RUN_TEST(ip6tnl_tunnel, IPIP6);
1057 	RUN_TEST(ip6tnl_tunnel, IP6IP6);
1058 
1059 	return NULL;
1060 }
1061 
1062 void test_tunnel(void)
1063 {
1064 	pthread_t test_thread;
1065 	int err;
1066 
1067 	/* Run the tests in their own thread to isolate the namespace changes
1068 	 * so they do not affect the environment of other tests.
1069 	 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
1070 	 */
1071 	err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
1072 	if (ASSERT_OK(err, "pthread_create"))
1073 		ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
1074 }
1075