treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / tools / testing / selftests / bpf / prog_tests / flow_dissector_reattach.c
blob1f51ba66b98bb896c8a035966bcc585cc54d16eb
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Test that the flow_dissector program can be updated with a single
4 * syscall by attaching a new program that replaces the existing one.
6 * Corner case - the same program cannot be attached twice.
7 */
9 #define _GNU_SOURCE
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <sched.h>
13 #include <stdbool.h>
14 #include <unistd.h>
16 #include <linux/bpf.h>
17 #include <bpf/bpf.h>
19 #include "test_progs.h"
21 static bool is_attached(int netns)
23 __u32 cnt;
24 int err;
26 err = bpf_prog_query(netns, BPF_FLOW_DISSECTOR, 0, NULL, NULL, &cnt);
27 if (CHECK_FAIL(err)) {
28 perror("bpf_prog_query");
29 return true; /* fail-safe */
32 return cnt > 0;
35 static int load_prog(void)
37 struct bpf_insn prog[] = {
38 BPF_MOV64_IMM(BPF_REG_0, BPF_OK),
39 BPF_EXIT_INSN(),
41 int fd;
43 fd = bpf_load_program(BPF_PROG_TYPE_FLOW_DISSECTOR, prog,
44 ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
45 if (CHECK_FAIL(fd < 0))
46 perror("bpf_load_program");
48 return fd;
51 static void do_flow_dissector_reattach(void)
53 int prog_fd[2] = { -1, -1 };
54 int err;
56 prog_fd[0] = load_prog();
57 if (prog_fd[0] < 0)
58 return;
60 prog_fd[1] = load_prog();
61 if (prog_fd[1] < 0)
62 goto out_close;
64 err = bpf_prog_attach(prog_fd[0], 0, BPF_FLOW_DISSECTOR, 0);
65 if (CHECK_FAIL(err)) {
66 perror("bpf_prog_attach-0");
67 goto out_close;
70 /* Expect success when attaching a different program */
71 err = bpf_prog_attach(prog_fd[1], 0, BPF_FLOW_DISSECTOR, 0);
72 if (CHECK_FAIL(err)) {
73 perror("bpf_prog_attach-1");
74 goto out_detach;
77 /* Expect failure when attaching the same program twice */
78 err = bpf_prog_attach(prog_fd[1], 0, BPF_FLOW_DISSECTOR, 0);
79 if (CHECK_FAIL(!err || errno != EINVAL))
80 perror("bpf_prog_attach-2");
82 out_detach:
83 err = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
84 if (CHECK_FAIL(err))
85 perror("bpf_prog_detach");
87 out_close:
88 close(prog_fd[1]);
89 close(prog_fd[0]);
92 void test_flow_dissector_reattach(void)
94 int init_net, self_net, err;
96 self_net = open("/proc/self/ns/net", O_RDONLY);
97 if (CHECK_FAIL(self_net < 0)) {
98 perror("open(/proc/self/ns/net");
99 return;
102 init_net = open("/proc/1/ns/net", O_RDONLY);
103 if (CHECK_FAIL(init_net < 0)) {
104 perror("open(/proc/1/ns/net)");
105 goto out_close;
108 err = setns(init_net, CLONE_NEWNET);
109 if (CHECK_FAIL(err)) {
110 perror("setns(/proc/1/ns/net)");
111 goto out_close;
114 if (is_attached(init_net)) {
115 test__skip();
116 printf("Can't test with flow dissector attached to init_net\n");
117 goto out_setns;
120 /* First run tests in root network namespace */
121 do_flow_dissector_reattach();
123 /* Then repeat tests in a non-root namespace */
124 err = unshare(CLONE_NEWNET);
125 if (CHECK_FAIL(err)) {
126 perror("unshare(CLONE_NEWNET)");
127 goto out_setns;
129 do_flow_dissector_reattach();
131 out_setns:
132 /* Move back to netns we started in. */
133 err = setns(self_net, CLONE_NEWNET);
134 if (CHECK_FAIL(err))
135 perror("setns(/proc/self/ns/net)");
137 out_close:
138 close(init_net);
139 close(self_net);