1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Tests for attaching, detaching, and replacing flow_dissector BPF program.
4 */
5
6#define _GNU_SOURCE
7#include <errno.h>
8#include <fcntl.h>
9#include <sched.h>
10#include <stdbool.h>
11#include <sys/stat.h>
12#include <unistd.h>
13
14#include <linux/bpf.h>
15#include <bpf/bpf.h>
16
17#include "test_progs.h"
18
19static int init_net = -1;
20
21static __u32 query_attached_prog_id(int netns)
22{
23	__u32 prog_ids[1] = {};
24	__u32 prog_cnt = ARRAY_SIZE(prog_ids);
25	int err;
26
27	err = bpf_prog_query(netns, BPF_FLOW_DISSECTOR, 0, NULL,
28			     prog_ids, &prog_cnt);
29	if (CHECK_FAIL(err)) {
30		perror("bpf_prog_query");
31		return 0;
32	}
33
34	return prog_cnt == 1 ? prog_ids[0] : 0;
35}
36
37static bool prog_is_attached(int netns)
38{
39	return query_attached_prog_id(netns) > 0;
40}
41
42static int load_prog(enum bpf_prog_type type)
43{
44	struct bpf_insn prog[] = {
45		BPF_MOV64_IMM(BPF_REG_0, BPF_OK),
46		BPF_EXIT_INSN(),
47	};
48	int fd;
49
50	fd = bpf_test_load_program(type, prog, ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
51	if (CHECK_FAIL(fd < 0))
52		perror("bpf_test_load_program");
53
54	return fd;
55}
56
57static __u32 query_prog_id(int prog)
58{
59	struct bpf_prog_info info = {};
60	__u32 info_len = sizeof(info);
61	int err;
62
63	err = bpf_prog_get_info_by_fd(prog, &info, &info_len);
64	if (CHECK_FAIL(err || info_len != sizeof(info))) {
65		perror("bpf_prog_get_info_by_fd");
66		return 0;
67	}
68
69	return info.id;
70}
71
72static int unshare_net(int old_net)
73{
74	int err, new_net;
75
76	err = unshare(CLONE_NEWNET);
77	if (CHECK_FAIL(err)) {
78		perror("unshare(CLONE_NEWNET)");
79		return -1;
80	}
81	new_net = open("/proc/self/ns/net", O_RDONLY);
82	if (CHECK_FAIL(new_net < 0)) {
83		perror("open(/proc/self/ns/net)");
84		setns(old_net, CLONE_NEWNET);
85		return -1;
86	}
87	return new_net;
88}
89
90static void test_prog_attach_prog_attach(int netns, int prog1, int prog2)
91{
92	int err;
93
94	err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
95	if (CHECK_FAIL(err)) {
96		perror("bpf_prog_attach(prog1)");
97		return;
98	}
99	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
100
101	/* Expect success when attaching a different program */
102	err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
103	if (CHECK_FAIL(err)) {
104		perror("bpf_prog_attach(prog2) #1");
105		goto out_detach;
106	}
107	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
108
109	/* Expect failure when attaching the same program twice */
110	err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
111	if (CHECK_FAIL(!err || errno != EINVAL))
112		perror("bpf_prog_attach(prog2) #2");
113	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
114
115out_detach:
116	err = bpf_prog_detach2(prog2, 0, BPF_FLOW_DISSECTOR);
117	if (CHECK_FAIL(err))
118		perror("bpf_prog_detach");
119	CHECK_FAIL(prog_is_attached(netns));
120}
121
122static void test_link_create_link_create(int netns, int prog1, int prog2)
123{
124	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
125	int link1, link2;
126
127	link1 = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
128	if (CHECK_FAIL(link < 0)) {
129		perror("bpf_link_create(prog1)");
130		return;
131	}
132	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
133
134	/* Expect failure creating link when another link exists */
135	errno = 0;
136	link2 = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
137	if (CHECK_FAIL(link2 >= 0 || errno != E2BIG))
138		perror("bpf_prog_attach(prog2) expected E2BIG");
139	if (link2 >= 0)
140		close(link2);
141	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
142
143	close(link1);
144	CHECK_FAIL(prog_is_attached(netns));
145}
146
147static void test_prog_attach_link_create(int netns, int prog1, int prog2)
148{
149	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
150	int err, link;
151
152	err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
153	if (CHECK_FAIL(err)) {
154		perror("bpf_prog_attach(prog1)");
155		return;
156	}
157	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
158
159	/* Expect failure creating link when prog attached */
160	errno = 0;
161	link = bpf_link_create(prog2, netns, BPF_FLOW_DISSECTOR, &opts);
162	if (CHECK_FAIL(link >= 0 || errno != EEXIST))
163		perror("bpf_link_create(prog2) expected EEXIST");
164	if (link >= 0)
165		close(link);
166	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
167
168	err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
169	if (CHECK_FAIL(err))
170		perror("bpf_prog_detach");
171	CHECK_FAIL(prog_is_attached(netns));
172}
173
174static void test_link_create_prog_attach(int netns, int prog1, int prog2)
175{
176	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
177	int err, link;
178
179	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
180	if (CHECK_FAIL(link < 0)) {
181		perror("bpf_link_create(prog1)");
182		return;
183	}
184	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
185
186	/* Expect failure attaching prog when link exists */
187	errno = 0;
188	err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
189	if (CHECK_FAIL(!err || errno != EEXIST))
190		perror("bpf_prog_attach(prog2) expected EEXIST");
191	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
192
193	close(link);
194	CHECK_FAIL(prog_is_attached(netns));
195}
196
197static void test_link_create_prog_detach(int netns, int prog1, int prog2)
198{
199	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
200	int err, link;
201
202	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
203	if (CHECK_FAIL(link < 0)) {
204		perror("bpf_link_create(prog1)");
205		return;
206	}
207	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
208
209	/* Expect failure detaching prog when link exists */
210	errno = 0;
211	err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
212	if (CHECK_FAIL(!err || errno != EINVAL))
213		perror("bpf_prog_detach expected EINVAL");
214	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
215
216	close(link);
217	CHECK_FAIL(prog_is_attached(netns));
218}
219
220static void test_prog_attach_detach_query(int netns, int prog1, int prog2)
221{
222	int err;
223
224	err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
225	if (CHECK_FAIL(err)) {
226		perror("bpf_prog_attach(prog1)");
227		return;
228	}
229	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
230
231	err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
232	if (CHECK_FAIL(err)) {
233		perror("bpf_prog_detach");
234		return;
235	}
236
237	/* Expect no prog attached after successful detach */
238	CHECK_FAIL(prog_is_attached(netns));
239}
240
241static void test_link_create_close_query(int netns, int prog1, int prog2)
242{
243	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
244	int link;
245
246	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &opts);
247	if (CHECK_FAIL(link < 0)) {
248		perror("bpf_link_create(prog1)");
249		return;
250	}
251	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
252
253	close(link);
254	/* Expect no prog attached after closing last link FD */
255	CHECK_FAIL(prog_is_attached(netns));
256}
257
258static void test_link_update_no_old_prog(int netns, int prog1, int prog2)
259{
260	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
261	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
262	int err, link;
263
264	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
265	if (CHECK_FAIL(link < 0)) {
266		perror("bpf_link_create(prog1)");
267		return;
268	}
269	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
270
271	/* Expect success replacing the prog when old prog not specified */
272	update_opts.flags = 0;
273	update_opts.old_prog_fd = 0;
274	err = bpf_link_update(link, prog2, &update_opts);
275	if (CHECK_FAIL(err))
276		perror("bpf_link_update");
277	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
278
279	close(link);
280	CHECK_FAIL(prog_is_attached(netns));
281}
282
283static void test_link_update_replace_old_prog(int netns, int prog1, int prog2)
284{
285	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
286	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
287	int err, link;
288
289	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
290	if (CHECK_FAIL(link < 0)) {
291		perror("bpf_link_create(prog1)");
292		return;
293	}
294	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
295
296	/* Expect success F_REPLACE and old prog specified to succeed */
297	update_opts.flags = BPF_F_REPLACE;
298	update_opts.old_prog_fd = prog1;
299	err = bpf_link_update(link, prog2, &update_opts);
300	if (CHECK_FAIL(err))
301		perror("bpf_link_update");
302	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
303
304	close(link);
305	CHECK_FAIL(prog_is_attached(netns));
306}
307
308static void test_link_update_same_prog(int netns, int prog1, int prog2)
309{
310	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
311	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
312	int err, link;
313
314	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
315	if (CHECK_FAIL(link < 0)) {
316		perror("bpf_link_create(prog1)");
317		return;
318	}
319	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
320
321	/* Expect success updating the prog with the same one */
322	update_opts.flags = 0;
323	update_opts.old_prog_fd = 0;
324	err = bpf_link_update(link, prog1, &update_opts);
325	if (CHECK_FAIL(err))
326		perror("bpf_link_update");
327	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
328
329	close(link);
330	CHECK_FAIL(prog_is_attached(netns));
331}
332
333static void test_link_update_invalid_opts(int netns, int prog1, int prog2)
334{
335	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
336	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
337	int err, link;
338
339	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
340	if (CHECK_FAIL(link < 0)) {
341		perror("bpf_link_create(prog1)");
342		return;
343	}
344	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
345
346	/* Expect update to fail w/ old prog FD but w/o F_REPLACE*/
347	errno = 0;
348	update_opts.flags = 0;
349	update_opts.old_prog_fd = prog1;
350	err = bpf_link_update(link, prog2, &update_opts);
351	if (CHECK_FAIL(!err || errno != EINVAL)) {
352		perror("bpf_link_update expected EINVAL");
353		goto out_close;
354	}
355	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
356
357	/* Expect update to fail on old prog FD mismatch */
358	errno = 0;
359	update_opts.flags = BPF_F_REPLACE;
360	update_opts.old_prog_fd = prog2;
361	err = bpf_link_update(link, prog2, &update_opts);
362	if (CHECK_FAIL(!err || errno != EPERM)) {
363		perror("bpf_link_update expected EPERM");
364		goto out_close;
365	}
366	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
367
368	/* Expect update to fail for invalid old prog FD */
369	errno = 0;
370	update_opts.flags = BPF_F_REPLACE;
371	update_opts.old_prog_fd = -1;
372	err = bpf_link_update(link, prog2, &update_opts);
373	if (CHECK_FAIL(!err || errno != EBADF)) {
374		perror("bpf_link_update expected EBADF");
375		goto out_close;
376	}
377	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
378
379	/* Expect update to fail with invalid flags */
380	errno = 0;
381	update_opts.flags = BPF_F_ALLOW_MULTI;
382	update_opts.old_prog_fd = 0;
383	err = bpf_link_update(link, prog2, &update_opts);
384	if (CHECK_FAIL(!err || errno != EINVAL))
385		perror("bpf_link_update expected EINVAL");
386	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
387
388out_close:
389	close(link);
390	CHECK_FAIL(prog_is_attached(netns));
391}
392
393static void test_link_update_invalid_prog(int netns, int prog1, int prog2)
394{
395	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
396	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
397	int err, link, prog3;
398
399	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
400	if (CHECK_FAIL(link < 0)) {
401		perror("bpf_link_create(prog1)");
402		return;
403	}
404	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
405
406	/* Expect failure when new prog FD is not valid */
407	errno = 0;
408	update_opts.flags = 0;
409	update_opts.old_prog_fd = 0;
410	err = bpf_link_update(link, -1, &update_opts);
411	if (CHECK_FAIL(!err || errno != EBADF)) {
412		perror("bpf_link_update expected EINVAL");
413		goto out_close_link;
414	}
415	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
416
417	prog3 = load_prog(BPF_PROG_TYPE_SOCKET_FILTER);
418	if (prog3 < 0)
419		goto out_close_link;
420
421	/* Expect failure when new prog FD type doesn't match */
422	errno = 0;
423	update_opts.flags = 0;
424	update_opts.old_prog_fd = 0;
425	err = bpf_link_update(link, prog3, &update_opts);
426	if (CHECK_FAIL(!err || errno != EINVAL))
427		perror("bpf_link_update expected EINVAL");
428	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
429
430	close(prog3);
431out_close_link:
432	close(link);
433	CHECK_FAIL(prog_is_attached(netns));
434}
435
436static void test_link_update_netns_gone(int netns, int prog1, int prog2)
437{
438	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
439	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
440	int err, link, old_net;
441
442	old_net = netns;
443	netns = unshare_net(old_net);
444	if (netns < 0)
445		return;
446
447	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
448	if (CHECK_FAIL(link < 0)) {
449		perror("bpf_link_create(prog1)");
450		return;
451	}
452	CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
453
454	close(netns);
455	err = setns(old_net, CLONE_NEWNET);
456	if (CHECK_FAIL(err)) {
457		perror("setns(CLONE_NEWNET)");
458		close(link);
459		return;
460	}
461
462	/* Expect failure when netns destroyed */
463	errno = 0;
464	update_opts.flags = 0;
465	update_opts.old_prog_fd = 0;
466	err = bpf_link_update(link, prog2, &update_opts);
467	if (CHECK_FAIL(!err || errno != ENOLINK))
468		perror("bpf_link_update");
469
470	close(link);
471}
472
473static void test_link_get_info(int netns, int prog1, int prog2)
474{
475	DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
476	DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
477	struct bpf_link_info info = {};
478	struct stat netns_stat = {};
479	__u32 info_len, link_id;
480	int err, link, old_net;
481
482	old_net = netns;
483	netns = unshare_net(old_net);
484	if (netns < 0)
485		return;
486
487	err = fstat(netns, &netns_stat);
488	if (CHECK_FAIL(err)) {
489		perror("stat(netns)");
490		goto out_resetns;
491	}
492
493	link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
494	if (CHECK_FAIL(link < 0)) {
495		perror("bpf_link_create(prog1)");
496		goto out_resetns;
497	}
498
499	info_len = sizeof(info);
500	err = bpf_link_get_info_by_fd(link, &info, &info_len);
501	if (CHECK_FAIL(err)) {
502		perror("bpf_obj_get_info");
503		goto out_unlink;
504	}
505	CHECK_FAIL(info_len != sizeof(info));
506
507	/* Expect link info to be sane and match prog and netns details */
508	CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
509	CHECK_FAIL(info.id == 0);
510	CHECK_FAIL(info.prog_id != query_prog_id(prog1));
511	CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
512	CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
513
514	update_opts.flags = 0;
515	update_opts.old_prog_fd = 0;
516	err = bpf_link_update(link, prog2, &update_opts);
517	if (CHECK_FAIL(err)) {
518		perror("bpf_link_update(prog2)");
519		goto out_unlink;
520	}
521
522	link_id = info.id;
523	info_len = sizeof(info);
524	err = bpf_link_get_info_by_fd(link, &info, &info_len);
525	if (CHECK_FAIL(err)) {
526		perror("bpf_obj_get_info");
527		goto out_unlink;
528	}
529	CHECK_FAIL(info_len != sizeof(info));
530
531	/* Expect no info change after update except in prog id */
532	CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
533	CHECK_FAIL(info.id != link_id);
534	CHECK_FAIL(info.prog_id != query_prog_id(prog2));
535	CHECK_FAIL(info.netns.netns_ino != netns_stat.st_ino);
536	CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
537
538	/* Leave netns link is attached to and close last FD to it */
539	err = setns(old_net, CLONE_NEWNET);
540	if (CHECK_FAIL(err)) {
541		perror("setns(NEWNET)");
542		goto out_unlink;
543	}
544	close(netns);
545	old_net = -1;
546	netns = -1;
547
548	info_len = sizeof(info);
549	err = bpf_link_get_info_by_fd(link, &info, &info_len);
550	if (CHECK_FAIL(err)) {
551		perror("bpf_obj_get_info");
552		goto out_unlink;
553	}
554	CHECK_FAIL(info_len != sizeof(info));
555
556	/* Expect netns_ino to change to 0 */
557	CHECK_FAIL(info.type != BPF_LINK_TYPE_NETNS);
558	CHECK_FAIL(info.id != link_id);
559	CHECK_FAIL(info.prog_id != query_prog_id(prog2));
560	CHECK_FAIL(info.netns.netns_ino != 0);
561	CHECK_FAIL(info.netns.attach_type != BPF_FLOW_DISSECTOR);
562
563out_unlink:
564	close(link);
565out_resetns:
566	if (old_net != -1)
567		setns(old_net, CLONE_NEWNET);
568	if (netns != -1)
569		close(netns);
570}
571
572static void run_tests(int netns)
573{
574	struct test {
575		const char *test_name;
576		void (*test_func)(int netns, int prog1, int prog2);
577	} tests[] = {
578		{ "prog attach, prog attach",
579		  test_prog_attach_prog_attach },
580		{ "link create, link create",
581		  test_link_create_link_create },
582		{ "prog attach, link create",
583		  test_prog_attach_link_create },
584		{ "link create, prog attach",
585		  test_link_create_prog_attach },
586		{ "link create, prog detach",
587		  test_link_create_prog_detach },
588		{ "prog attach, detach, query",
589		  test_prog_attach_detach_query },
590		{ "link create, close, query",
591		  test_link_create_close_query },
592		{ "link update no old prog",
593		  test_link_update_no_old_prog },
594		{ "link update with replace old prog",
595		  test_link_update_replace_old_prog },
596		{ "link update with same prog",
597		  test_link_update_same_prog },
598		{ "link update invalid opts",
599		  test_link_update_invalid_opts },
600		{ "link update invalid prog",
601		  test_link_update_invalid_prog },
602		{ "link update netns gone",
603		  test_link_update_netns_gone },
604		{ "link get info",
605		  test_link_get_info },
606	};
607	int i, progs[2] = { -1, -1 };
608	char test_name[80];
609
610	for (i = 0; i < ARRAY_SIZE(progs); i++) {
611		progs[i] = load_prog(BPF_PROG_TYPE_FLOW_DISSECTOR);
612		if (progs[i] < 0)
613			goto out_close;
614	}
615
616	for (i = 0; i < ARRAY_SIZE(tests); i++) {
617		snprintf(test_name, sizeof(test_name),
618			 "flow dissector %s%s",
619			 tests[i].test_name,
620			 netns == init_net ? " (init_net)" : "");
621		if (test__start_subtest(test_name))
622			tests[i].test_func(netns, progs[0], progs[1]);
623	}
624out_close:
625	for (i = 0; i < ARRAY_SIZE(progs); i++) {
626		if (progs[i] >= 0)
627			CHECK_FAIL(close(progs[i]));
628	}
629}
630
631void serial_test_flow_dissector_reattach(void)
632{
633	int err, new_net, saved_net;
634
635	saved_net = open("/proc/self/ns/net", O_RDONLY);
636	if (CHECK_FAIL(saved_net < 0)) {
637		perror("open(/proc/self/ns/net");
638		return;
639	}
640
641	init_net = open("/proc/1/ns/net", O_RDONLY);
642	if (CHECK_FAIL(init_net < 0)) {
643		perror("open(/proc/1/ns/net)");
644		goto out_close;
645	}
646
647	err = setns(init_net, CLONE_NEWNET);
648	if (CHECK_FAIL(err)) {
649		perror("setns(/proc/1/ns/net)");
650		goto out_close;
651	}
652
653	if (prog_is_attached(init_net)) {
654		test__skip();
655		printf("Can't test with flow dissector attached to init_net\n");
656		goto out_setns;
657	}
658
659	/* First run tests in root network namespace */
660	run_tests(init_net);
661
662	/* Then repeat tests in a non-root namespace */
663	new_net = unshare_net(init_net);
664	if (new_net < 0)
665		goto out_setns;
666	run_tests(new_net);
667	close(new_net);
668
669out_setns:
670	/* Move back to netns we started in. */
671	err = setns(saved_net, CLONE_NEWNET);
672	if (CHECK_FAIL(err))
673		perror("setns(/proc/self/ns/net)");
674
675out_close:
676	close(init_net);
677	close(saved_net);
678}
679