WIP FPC-III support
[linux/fpc-iii.git] / tools / testing / selftests / bpf / prog_tests / sockopt_multi.c
blob51fac975b3163fd9491fd66210229cea15432f1d
1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "cgroup_helpers.h"
5 static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
7 enum bpf_attach_type attach_type;
8 enum bpf_prog_type prog_type;
9 struct bpf_program *prog;
10 int err;
12 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
13 if (err) {
14 log_err("Failed to deduct types for %s BPF program", title);
15 return -1;
18 prog = bpf_object__find_program_by_title(obj, title);
19 if (!prog) {
20 log_err("Failed to find %s BPF program", title);
21 return -1;
24 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
25 attach_type, BPF_F_ALLOW_MULTI);
26 if (err) {
27 log_err("Failed to attach %s BPF program", title);
28 return -1;
31 return 0;
34 static int prog_detach(struct bpf_object *obj, int cgroup_fd, const char *title)
36 enum bpf_attach_type attach_type;
37 enum bpf_prog_type prog_type;
38 struct bpf_program *prog;
39 int err;
41 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
42 if (err)
43 return -1;
45 prog = bpf_object__find_program_by_title(obj, title);
46 if (!prog)
47 return -1;
49 err = bpf_prog_detach2(bpf_program__fd(prog), cgroup_fd,
50 attach_type);
51 if (err)
52 return -1;
54 return 0;
57 static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
58 int cg_child, int sock_fd)
60 socklen_t optlen;
61 __u8 buf;
62 int err;
64 /* Set IP_TOS to the expected value (0x80). */
66 buf = 0x80;
67 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
68 if (err < 0) {
69 log_err("Failed to call setsockopt(IP_TOS)");
70 goto detach;
73 buf = 0x00;
74 optlen = 1;
75 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
76 if (err) {
77 log_err("Failed to call getsockopt(IP_TOS)");
78 goto detach;
81 if (buf != 0x80) {
82 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
83 err = -1;
84 goto detach;
87 /* Attach child program and make sure it returns new value:
88 * - kernel: -> 0x80
89 * - child: 0x80 -> 0x90
92 err = prog_attach(obj, cg_child, "cgroup/getsockopt/child");
93 if (err)
94 goto detach;
96 buf = 0x00;
97 optlen = 1;
98 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
99 if (err) {
100 log_err("Failed to call getsockopt(IP_TOS)");
101 goto detach;
104 if (buf != 0x90) {
105 log_err("Unexpected getsockopt 0x%x != 0x90", buf);
106 err = -1;
107 goto detach;
110 /* Attach parent program and make sure it returns new value:
111 * - kernel: -> 0x80
112 * - child: 0x80 -> 0x90
113 * - parent: 0x90 -> 0xA0
116 err = prog_attach(obj, cg_parent, "cgroup/getsockopt/parent");
117 if (err)
118 goto detach;
120 buf = 0x00;
121 optlen = 1;
122 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
123 if (err) {
124 log_err("Failed to call getsockopt(IP_TOS)");
125 goto detach;
128 if (buf != 0xA0) {
129 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
130 err = -1;
131 goto detach;
134 /* Setting unexpected initial sockopt should return EPERM:
135 * - kernel: -> 0x40
136 * - child: unexpected 0x40, EPERM
137 * - parent: unexpected 0x40, EPERM
140 buf = 0x40;
141 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
142 if (err < 0) {
143 log_err("Failed to call setsockopt(IP_TOS)");
144 goto detach;
147 buf = 0x00;
148 optlen = 1;
149 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
150 if (!err) {
151 log_err("Unexpected success from getsockopt(IP_TOS)");
152 goto detach;
155 /* Detach child program and make sure we still get EPERM:
156 * - kernel: -> 0x40
157 * - parent: unexpected 0x40, EPERM
160 err = prog_detach(obj, cg_child, "cgroup/getsockopt/child");
161 if (err) {
162 log_err("Failed to detach child program");
163 goto detach;
166 buf = 0x00;
167 optlen = 1;
168 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
169 if (!err) {
170 log_err("Unexpected success from getsockopt(IP_TOS)");
171 goto detach;
174 /* Set initial value to the one the parent program expects:
175 * - kernel: -> 0x90
176 * - parent: 0x90 -> 0xA0
179 buf = 0x90;
180 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
181 if (err < 0) {
182 log_err("Failed to call setsockopt(IP_TOS)");
183 goto detach;
186 buf = 0x00;
187 optlen = 1;
188 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
189 if (err) {
190 log_err("Failed to call getsockopt(IP_TOS)");
191 goto detach;
194 if (buf != 0xA0) {
195 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
196 err = -1;
197 goto detach;
200 detach:
201 prog_detach(obj, cg_child, "cgroup/getsockopt/child");
202 prog_detach(obj, cg_parent, "cgroup/getsockopt/parent");
204 return err;
207 static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
208 int cg_child, int sock_fd)
210 socklen_t optlen;
211 __u8 buf;
212 int err;
214 /* Set IP_TOS to the expected value (0x80). */
216 buf = 0x80;
217 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
218 if (err < 0) {
219 log_err("Failed to call setsockopt(IP_TOS)");
220 goto detach;
223 buf = 0x00;
224 optlen = 1;
225 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
226 if (err) {
227 log_err("Failed to call getsockopt(IP_TOS)");
228 goto detach;
231 if (buf != 0x80) {
232 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
233 err = -1;
234 goto detach;
237 /* Attach child program and make sure it adds 0x10. */
239 err = prog_attach(obj, cg_child, "cgroup/setsockopt");
240 if (err)
241 goto detach;
243 buf = 0x80;
244 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
245 if (err < 0) {
246 log_err("Failed to call setsockopt(IP_TOS)");
247 goto detach;
250 buf = 0x00;
251 optlen = 1;
252 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
253 if (err) {
254 log_err("Failed to call getsockopt(IP_TOS)");
255 goto detach;
258 if (buf != 0x80 + 0x10) {
259 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);
260 err = -1;
261 goto detach;
264 /* Attach parent program and make sure it adds another 0x10. */
266 err = prog_attach(obj, cg_parent, "cgroup/setsockopt");
267 if (err)
268 goto detach;
270 buf = 0x80;
271 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
272 if (err < 0) {
273 log_err("Failed to call setsockopt(IP_TOS)");
274 goto detach;
277 buf = 0x00;
278 optlen = 1;
279 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
280 if (err) {
281 log_err("Failed to call getsockopt(IP_TOS)");
282 goto detach;
285 if (buf != 0x80 + 2 * 0x10) {
286 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);
287 err = -1;
288 goto detach;
291 detach:
292 prog_detach(obj, cg_child, "cgroup/setsockopt");
293 prog_detach(obj, cg_parent, "cgroup/setsockopt");
295 return err;
298 void test_sockopt_multi(void)
300 struct bpf_prog_load_attr attr = {
301 .file = "./sockopt_multi.o",
303 int cg_parent = -1, cg_child = -1;
304 struct bpf_object *obj = NULL;
305 int sock_fd = -1;
306 int err = -1;
307 int ignored;
309 cg_parent = test__join_cgroup("/parent");
310 if (CHECK_FAIL(cg_parent < 0))
311 goto out;
313 cg_child = test__join_cgroup("/parent/child");
314 if (CHECK_FAIL(cg_child < 0))
315 goto out;
317 err = bpf_prog_load_xattr(&attr, &obj, &ignored);
318 if (CHECK_FAIL(err))
319 goto out;
321 sock_fd = socket(AF_INET, SOCK_STREAM, 0);
322 if (CHECK_FAIL(sock_fd < 0))
323 goto out;
325 CHECK_FAIL(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd));
326 CHECK_FAIL(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd));
328 out:
329 close(sock_fd);
330 bpf_object__close(obj);
331 close(cg_child);
332 close(cg_parent);