]>
Commit | Line | Data |
---|---|---|
1bc38b8f | 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) |
6061a3d6 | 2 | |
e3ed2fef WN |
3 | /* |
4 | * common eBPF ELF operations. | |
5 | * | |
6 | * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> | |
7 | * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> | |
8 | * Copyright (C) 2015 Huawei Inc. | |
203d1cac WN |
9 | * |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License as published by the Free Software Foundation; | |
13 | * version 2.1 of the License (not later!) | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU Lesser General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU Lesser General Public | |
21 | * License along with this program; if not, see <http://www.gnu.org/licenses> | |
e3ed2fef WN |
22 | */ |
23 | ||
24 | #include <stdlib.h> | |
1ad9cbb8 | 25 | #include <string.h> |
e3ed2fef WN |
26 | #include <memory.h> |
27 | #include <unistd.h> | |
28 | #include <asm/unistd.h> | |
d7fe74f9 | 29 | #include <errno.h> |
e3ed2fef WN |
30 | #include <linux/bpf.h> |
31 | #include "bpf.h" | |
949abbe8 | 32 | #include "libbpf.h" |
d7fe74f9 | 33 | #include "libbpf_internal.h" |
e3ed2fef WN |
34 | |
35 | /* | |
03671057 | 36 | * When building perf, unistd.h is overridden. __NR_bpf is |
8f9e05fb | 37 | * required to be defined explicitly. |
e3ed2fef WN |
38 | */ |
39 | #ifndef __NR_bpf | |
40 | # if defined(__i386__) | |
41 | # define __NR_bpf 357 | |
42 | # elif defined(__x86_64__) | |
43 | # define __NR_bpf 321 | |
44 | # elif defined(__aarch64__) | |
45 | # define __NR_bpf 280 | |
b0c47807 DM |
46 | # elif defined(__sparc__) |
47 | # define __NR_bpf 349 | |
bad1926d DB |
48 | # elif defined(__s390__) |
49 | # define __NR_bpf 351 | |
ca31ca82 VG |
50 | # elif defined(__arc__) |
51 | # define __NR_bpf 280 | |
e3ed2fef WN |
52 | # else |
53 | # error __NR_bpf not defined. libbpf does not support your arch. | |
54 | # endif | |
55 | #endif | |
56 | ||
cdc6a4ba | 57 | static inline __u64 ptr_to_u64(const void *ptr) |
7bf98369 WN |
58 | { |
59 | return (__u64) (unsigned long) ptr; | |
60 | } | |
61 | ||
cdc6a4ba MS |
62 | static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, |
63 | unsigned int size) | |
e3ed2fef WN |
64 | { |
65 | return syscall(__NR_bpf, cmd, attr, size); | |
66 | } | |
67 | ||
86edaed3 LB |
68 | static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size) |
69 | { | |
70 | int fd; | |
71 | ||
72 | do { | |
73 | fd = sys_bpf(BPF_PROG_LOAD, attr, size); | |
74 | } while (fd < 0 && errno == EAGAIN); | |
75 | ||
76 | return fd; | |
77 | } | |
78 | ||
8a138aed | 79 | int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr) |
e3ed2fef WN |
80 | { |
81 | union bpf_attr attr; | |
82 | ||
83 | memset(&attr, '\0', sizeof(attr)); | |
84 | ||
8a138aed MKL |
85 | attr.map_type = create_attr->map_type; |
86 | attr.key_size = create_attr->key_size; | |
87 | attr.value_size = create_attr->value_size; | |
88 | attr.max_entries = create_attr->max_entries; | |
89 | attr.map_flags = create_attr->map_flags; | |
69a0f9ec YS |
90 | if (create_attr->name) |
91 | memcpy(attr.map_name, create_attr->name, | |
92 | min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1)); | |
8a138aed MKL |
93 | attr.numa_node = create_attr->numa_node; |
94 | attr.btf_fd = create_attr->btf_fd; | |
61746dbe MKL |
95 | attr.btf_key_type_id = create_attr->btf_key_type_id; |
96 | attr.btf_value_type_id = create_attr->btf_value_type_id; | |
f0307a7e | 97 | attr.map_ifindex = create_attr->map_ifindex; |
91134d84 | 98 | attr.inner_map_fd = create_attr->inner_map_fd; |
8a138aed | 99 | |
94cb310c | 100 | return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); |
8a138aed | 101 | } |
88cda1c9 | 102 | |
8a138aed MKL |
103 | int bpf_create_map_node(enum bpf_map_type map_type, const char *name, |
104 | int key_size, int value_size, int max_entries, | |
105 | __u32 map_flags, int node) | |
106 | { | |
107 | struct bpf_create_map_attr map_attr = {}; | |
108 | ||
109 | map_attr.name = name; | |
110 | map_attr.map_type = map_type; | |
111 | map_attr.map_flags = map_flags; | |
112 | map_attr.key_size = key_size; | |
113 | map_attr.value_size = value_size; | |
114 | map_attr.max_entries = max_entries; | |
ad17d0e6 | 115 | if (node >= 0) { |
8a138aed MKL |
116 | map_attr.numa_node = node; |
117 | map_attr.map_flags |= BPF_F_NUMA_NODE; | |
ad17d0e6 | 118 | } |
e3ed2fef | 119 | |
8a138aed | 120 | return bpf_create_map_xattr(&map_attr); |
e3ed2fef | 121 | } |
7bf98369 | 122 | |
ad17d0e6 MKL |
123 | int bpf_create_map(enum bpf_map_type map_type, int key_size, |
124 | int value_size, int max_entries, __u32 map_flags) | |
125 | { | |
8a138aed MKL |
126 | struct bpf_create_map_attr map_attr = {}; |
127 | ||
128 | map_attr.map_type = map_type; | |
129 | map_attr.map_flags = map_flags; | |
130 | map_attr.key_size = key_size; | |
131 | map_attr.value_size = value_size; | |
132 | map_attr.max_entries = max_entries; | |
133 | ||
134 | return bpf_create_map_xattr(&map_attr); | |
ad17d0e6 MKL |
135 | } |
136 | ||
88cda1c9 MKL |
137 | int bpf_create_map_name(enum bpf_map_type map_type, const char *name, |
138 | int key_size, int value_size, int max_entries, | |
139 | __u32 map_flags) | |
140 | { | |
8a138aed MKL |
141 | struct bpf_create_map_attr map_attr = {}; |
142 | ||
143 | map_attr.name = name; | |
144 | map_attr.map_type = map_type; | |
145 | map_attr.map_flags = map_flags; | |
146 | map_attr.key_size = key_size; | |
147 | map_attr.value_size = value_size; | |
148 | map_attr.max_entries = max_entries; | |
149 | ||
150 | return bpf_create_map_xattr(&map_attr); | |
88cda1c9 MKL |
151 | } |
152 | ||
153 | int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name, | |
154 | int key_size, int inner_map_fd, int max_entries, | |
ad17d0e6 | 155 | __u32 map_flags, int node) |
fb30d4b7 MKL |
156 | { |
157 | union bpf_attr attr; | |
158 | ||
159 | memset(&attr, '\0', sizeof(attr)); | |
160 | ||
161 | attr.map_type = map_type; | |
162 | attr.key_size = key_size; | |
163 | attr.value_size = 4; | |
164 | attr.inner_map_fd = inner_map_fd; | |
165 | attr.max_entries = max_entries; | |
166 | attr.map_flags = map_flags; | |
69a0f9ec YS |
167 | if (name) |
168 | memcpy(attr.map_name, name, | |
169 | min(strlen(name), BPF_OBJ_NAME_LEN - 1)); | |
88cda1c9 | 170 | |
ad17d0e6 MKL |
171 | if (node >= 0) { |
172 | attr.map_flags |= BPF_F_NUMA_NODE; | |
173 | attr.numa_node = node; | |
174 | } | |
fb30d4b7 MKL |
175 | |
176 | return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); | |
177 | } | |
178 | ||
88cda1c9 MKL |
179 | int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, |
180 | int key_size, int inner_map_fd, int max_entries, | |
181 | __u32 map_flags) | |
ad17d0e6 | 182 | { |
88cda1c9 MKL |
183 | return bpf_create_map_in_map_node(map_type, name, key_size, |
184 | inner_map_fd, max_entries, map_flags, | |
185 | -1); | |
ad17d0e6 MKL |
186 | } |
187 | ||
3d650141 MKL |
188 | static void * |
189 | alloc_zero_tailing_info(const void *orecord, __u32 cnt, | |
190 | __u32 actual_rec_size, __u32 expected_rec_size) | |
191 | { | |
192 | __u64 info_len = actual_rec_size * cnt; | |
193 | void *info, *nrecord; | |
194 | int i; | |
195 | ||
196 | info = malloc(info_len); | |
197 | if (!info) | |
198 | return NULL; | |
199 | ||
200 | /* zero out bytes kernel does not understand */ | |
201 | nrecord = info; | |
202 | for (i = 0; i < cnt; i++) { | |
203 | memcpy(nrecord, orecord, expected_rec_size); | |
204 | memset(nrecord + expected_rec_size, 0, | |
205 | actual_rec_size - expected_rec_size); | |
206 | orecord += actual_rec_size; | |
207 | nrecord += actual_rec_size; | |
208 | } | |
209 | ||
210 | return info; | |
211 | } | |
212 | ||
d7be143b AI |
213 | int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, |
214 | char *log_buf, size_t log_buf_sz) | |
7bf98369 | 215 | { |
3d650141 | 216 | void *finfo = NULL, *linfo = NULL; |
7bf98369 | 217 | union bpf_attr attr; |
a4021a35 | 218 | __u32 log_level; |
d7be143b AI |
219 | int fd; |
220 | ||
a4021a35 YS |
221 | if (!load_attr || !log_buf != !log_buf_sz) |
222 | return -EINVAL; | |
223 | ||
224 | log_level = load_attr->log_level; | |
da11b417 | 225 | if (log_level > (4 | 2 | 1) || (log_level && !log_buf)) |
d7be143b AI |
226 | return -EINVAL; |
227 | ||
1ad9cbb8 | 228 | memset(&attr, 0, sizeof(attr)); |
d7be143b AI |
229 | attr.prog_type = load_attr->prog_type; |
230 | attr.expected_attach_type = load_attr->expected_attach_type; | |
231 | attr.insn_cnt = (__u32)load_attr->insns_cnt; | |
232 | attr.insns = ptr_to_u64(load_attr->insns); | |
233 | attr.license = ptr_to_u64(load_attr->license); | |
a4021a35 YS |
234 | |
235 | attr.log_level = log_level; | |
236 | if (log_level) { | |
237 | attr.log_buf = ptr_to_u64(log_buf); | |
238 | attr.log_size = log_buf_sz; | |
239 | } else { | |
240 | attr.log_buf = ptr_to_u64(NULL); | |
241 | attr.log_size = 0; | |
242 | } | |
243 | ||
d7be143b | 244 | attr.kern_version = load_attr->kern_version; |
f0307a7e | 245 | attr.prog_ifindex = load_attr->prog_ifindex; |
7e0d0fb5 YS |
246 | attr.prog_btf_fd = load_attr->prog_btf_fd; |
247 | attr.func_info_rec_size = load_attr->func_info_rec_size; | |
248 | attr.func_info_cnt = load_attr->func_info_cnt; | |
249 | attr.func_info = ptr_to_u64(load_attr->func_info); | |
3d650141 MKL |
250 | attr.line_info_rec_size = load_attr->line_info_rec_size; |
251 | attr.line_info_cnt = load_attr->line_info_cnt; | |
252 | attr.line_info = ptr_to_u64(load_attr->line_info); | |
69a0f9ec YS |
253 | if (load_attr->name) |
254 | memcpy(attr.prog_name, load_attr->name, | |
255 | min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1)); | |
04656198 | 256 | attr.prog_flags = load_attr->prog_flags; |
7bf98369 | 257 | |
86edaed3 | 258 | fd = sys_bpf_prog_load(&attr, sizeof(attr)); |
f0187f0b | 259 | if (fd >= 0) |
7bf98369 WN |
260 | return fd; |
261 | ||
2993e051 YS |
262 | /* After bpf_prog_load, the kernel may modify certain attributes |
263 | * to give user space a hint how to deal with loading failure. | |
264 | * Check to see whether we can make some changes and load again. | |
265 | */ | |
3d650141 MKL |
266 | while (errno == E2BIG && (!finfo || !linfo)) { |
267 | if (!finfo && attr.func_info_cnt && | |
268 | attr.func_info_rec_size < load_attr->func_info_rec_size) { | |
269 | /* try with corrected func info records */ | |
270 | finfo = alloc_zero_tailing_info(load_attr->func_info, | |
271 | load_attr->func_info_cnt, | |
272 | load_attr->func_info_rec_size, | |
273 | attr.func_info_rec_size); | |
274 | if (!finfo) | |
275 | goto done; | |
276 | ||
277 | attr.func_info = ptr_to_u64(finfo); | |
278 | attr.func_info_rec_size = load_attr->func_info_rec_size; | |
279 | } else if (!linfo && attr.line_info_cnt && | |
280 | attr.line_info_rec_size < | |
281 | load_attr->line_info_rec_size) { | |
282 | linfo = alloc_zero_tailing_info(load_attr->line_info, | |
283 | load_attr->line_info_cnt, | |
284 | load_attr->line_info_rec_size, | |
285 | attr.line_info_rec_size); | |
286 | if (!linfo) | |
287 | goto done; | |
288 | ||
289 | attr.line_info = ptr_to_u64(linfo); | |
290 | attr.line_info_rec_size = load_attr->line_info_rec_size; | |
291 | } else { | |
292 | break; | |
2993e051 YS |
293 | } |
294 | ||
86edaed3 | 295 | fd = sys_bpf_prog_load(&attr, sizeof(attr)); |
2993e051 | 296 | |
f0187f0b | 297 | if (fd >= 0) |
2993e051 YS |
298 | goto done; |
299 | } | |
300 | ||
a4021a35 | 301 | if (log_level || !log_buf) |
f0187f0b MKL |
302 | goto done; |
303 | ||
7bf98369 WN |
304 | /* Try again with log */ |
305 | attr.log_buf = ptr_to_u64(log_buf); | |
306 | attr.log_size = log_buf_sz; | |
307 | attr.log_level = 1; | |
308 | log_buf[0] = 0; | |
86edaed3 | 309 | fd = sys_bpf_prog_load(&attr, sizeof(attr)); |
2993e051 YS |
310 | done: |
311 | free(finfo); | |
3d650141 | 312 | free(linfo); |
2993e051 | 313 | return fd; |
7bf98369 | 314 | } |
43798bf3 | 315 | |
88cda1c9 MKL |
316 | int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, |
317 | size_t insns_cnt, const char *license, | |
318 | __u32 kern_version, char *log_buf, | |
319 | size_t log_buf_sz) | |
320 | { | |
d7be143b AI |
321 | struct bpf_load_program_attr load_attr; |
322 | ||
323 | memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); | |
324 | load_attr.prog_type = type; | |
325 | load_attr.expected_attach_type = 0; | |
326 | load_attr.name = NULL; | |
327 | load_attr.insns = insns; | |
328 | load_attr.insns_cnt = insns_cnt; | |
329 | load_attr.license = license; | |
330 | load_attr.kern_version = kern_version; | |
331 | ||
332 | return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz); | |
88cda1c9 MKL |
333 | } |
334 | ||
91045f5e | 335 | int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, |
e9ee9efc DM |
336 | size_t insns_cnt, __u32 prog_flags, const char *license, |
337 | __u32 kern_version, char *log_buf, size_t log_buf_sz, | |
338 | int log_level) | |
91045f5e DM |
339 | { |
340 | union bpf_attr attr; | |
341 | ||
1ad9cbb8 | 342 | memset(&attr, 0, sizeof(attr)); |
91045f5e DM |
343 | attr.prog_type = type; |
344 | attr.insn_cnt = (__u32)insns_cnt; | |
345 | attr.insns = ptr_to_u64(insns); | |
346 | attr.license = ptr_to_u64(license); | |
347 | attr.log_buf = ptr_to_u64(log_buf); | |
348 | attr.log_size = log_buf_sz; | |
d6554904 | 349 | attr.log_level = log_level; |
91045f5e DM |
350 | log_buf[0] = 0; |
351 | attr.kern_version = kern_version; | |
e9ee9efc | 352 | attr.prog_flags = prog_flags; |
91045f5e | 353 | |
86edaed3 | 354 | return sys_bpf_prog_load(&attr, sizeof(attr)); |
91045f5e DM |
355 | } |
356 | ||
10ecc728 | 357 | int bpf_map_update_elem(int fd, const void *key, const void *value, |
83d994d0 | 358 | __u64 flags) |
43798bf3 HK |
359 | { |
360 | union bpf_attr attr; | |
361 | ||
1ad9cbb8 | 362 | memset(&attr, 0, sizeof(attr)); |
43798bf3 HK |
363 | attr.map_fd = fd; |
364 | attr.key = ptr_to_u64(key); | |
365 | attr.value = ptr_to_u64(value); | |
366 | attr.flags = flags; | |
367 | ||
368 | return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); | |
369 | } | |
9742da01 | 370 | |
e5ff7c40 | 371 | int bpf_map_lookup_elem(int fd, const void *key, void *value) |
9742da01 WN |
372 | { |
373 | union bpf_attr attr; | |
374 | ||
1ad9cbb8 | 375 | memset(&attr, 0, sizeof(attr)); |
9742da01 WN |
376 | attr.map_fd = fd; |
377 | attr.key = ptr_to_u64(key); | |
378 | attr.value = ptr_to_u64(value); | |
379 | ||
380 | return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); | |
381 | } | |
382 | ||
df5d22fa AS |
383 | int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags) |
384 | { | |
385 | union bpf_attr attr; | |
386 | ||
1ad9cbb8 | 387 | memset(&attr, 0, sizeof(attr)); |
df5d22fa AS |
388 | attr.map_fd = fd; |
389 | attr.key = ptr_to_u64(key); | |
390 | attr.value = ptr_to_u64(value); | |
391 | attr.flags = flags; | |
392 | ||
393 | return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); | |
394 | } | |
395 | ||
43b987d2 MV |
396 | int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) |
397 | { | |
398 | union bpf_attr attr; | |
399 | ||
1ad9cbb8 | 400 | memset(&attr, 0, sizeof(attr)); |
43b987d2 MV |
401 | attr.map_fd = fd; |
402 | attr.key = ptr_to_u64(key); | |
403 | attr.value = ptr_to_u64(value); | |
404 | ||
405 | return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); | |
406 | } | |
407 | ||
e58383b8 | 408 | int bpf_map_delete_elem(int fd, const void *key) |
9742da01 WN |
409 | { |
410 | union bpf_attr attr; | |
411 | ||
1ad9cbb8 | 412 | memset(&attr, 0, sizeof(attr)); |
9742da01 WN |
413 | attr.map_fd = fd; |
414 | attr.key = ptr_to_u64(key); | |
415 | ||
416 | return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); | |
417 | } | |
418 | ||
5f155c25 | 419 | int bpf_map_get_next_key(int fd, const void *key, void *next_key) |
9742da01 WN |
420 | { |
421 | union bpf_attr attr; | |
422 | ||
1ad9cbb8 | 423 | memset(&attr, 0, sizeof(attr)); |
9742da01 WN |
424 | attr.map_fd = fd; |
425 | attr.key = ptr_to_u64(key); | |
426 | attr.next_key = ptr_to_u64(next_key); | |
427 | ||
428 | return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr)); | |
429 | } | |
430 | ||
d859900c DB |
431 | int bpf_map_freeze(int fd) |
432 | { | |
433 | union bpf_attr attr; | |
434 | ||
435 | memset(&attr, 0, sizeof(attr)); | |
436 | attr.map_fd = fd; | |
437 | ||
438 | return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr)); | |
439 | } | |
440 | ||
9742da01 WN |
441 | int bpf_obj_pin(int fd, const char *pathname) |
442 | { | |
443 | union bpf_attr attr; | |
444 | ||
1ad9cbb8 | 445 | memset(&attr, 0, sizeof(attr)); |
9742da01 WN |
446 | attr.pathname = ptr_to_u64((void *)pathname); |
447 | attr.bpf_fd = fd; | |
448 | ||
449 | return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); | |
450 | } | |
451 | ||
452 | int bpf_obj_get(const char *pathname) | |
453 | { | |
454 | union bpf_attr attr; | |
455 | ||
1ad9cbb8 | 456 | memset(&attr, 0, sizeof(attr)); |
9742da01 WN |
457 | attr.pathname = ptr_to_u64((void *)pathname); |
458 | ||
459 | return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); | |
460 | } | |
5dc880de | 461 | |
464bc0fd JF |
462 | int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, |
463 | unsigned int flags) | |
5dc880de JS |
464 | { |
465 | union bpf_attr attr; | |
466 | ||
1ad9cbb8 | 467 | memset(&attr, 0, sizeof(attr)); |
5dc880de | 468 | attr.target_fd = target_fd; |
464bc0fd | 469 | attr.attach_bpf_fd = prog_fd; |
5dc880de | 470 | attr.attach_type = type; |
7f677633 | 471 | attr.attach_flags = flags; |
5dc880de JS |
472 | |
473 | return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); | |
474 | } | |
475 | ||
476 | int bpf_prog_detach(int target_fd, enum bpf_attach_type type) | |
477 | { | |
478 | union bpf_attr attr; | |
479 | ||
1ad9cbb8 | 480 | memset(&attr, 0, sizeof(attr)); |
5dc880de JS |
481 | attr.target_fd = target_fd; |
482 | attr.attach_type = type; | |
483 | ||
484 | return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); | |
485 | } | |
30848873 | 486 | |
244d20ef AS |
487 | int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) |
488 | { | |
489 | union bpf_attr attr; | |
490 | ||
1ad9cbb8 | 491 | memset(&attr, 0, sizeof(attr)); |
244d20ef AS |
492 | attr.target_fd = target_fd; |
493 | attr.attach_bpf_fd = prog_fd; | |
494 | attr.attach_type = type; | |
495 | ||
496 | return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); | |
497 | } | |
498 | ||
5d0cbf9b AS |
499 | int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, |
500 | __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) | |
501 | { | |
502 | union bpf_attr attr; | |
503 | int ret; | |
504 | ||
1ad9cbb8 | 505 | memset(&attr, 0, sizeof(attr)); |
5d0cbf9b AS |
506 | attr.query.target_fd = target_fd; |
507 | attr.query.attach_type = type; | |
508 | attr.query.query_flags = query_flags; | |
509 | attr.query.prog_cnt = *prog_cnt; | |
510 | attr.query.prog_ids = ptr_to_u64(prog_ids); | |
511 | ||
512 | ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr)); | |
513 | if (attach_flags) | |
514 | *attach_flags = attr.query.attach_flags; | |
515 | *prog_cnt = attr.query.prog_cnt; | |
516 | return ret; | |
517 | } | |
518 | ||
30848873 AS |
519 | int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, |
520 | void *data_out, __u32 *size_out, __u32 *retval, | |
521 | __u32 *duration) | |
522 | { | |
523 | union bpf_attr attr; | |
524 | int ret; | |
525 | ||
1ad9cbb8 | 526 | memset(&attr, 0, sizeof(attr)); |
30848873 AS |
527 | attr.test.prog_fd = prog_fd; |
528 | attr.test.data_in = ptr_to_u64(data); | |
529 | attr.test.data_out = ptr_to_u64(data_out); | |
530 | attr.test.data_size_in = size; | |
531 | attr.test.repeat = repeat; | |
532 | ||
533 | ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); | |
534 | if (size_out) | |
535 | *size_out = attr.test.data_size_out; | |
536 | if (retval) | |
537 | *retval = attr.test.retval; | |
538 | if (duration) | |
539 | *duration = attr.test.duration; | |
540 | return ret; | |
541 | } | |
95b9afd3 | 542 | |
64a97591 LB |
543 | int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr) |
544 | { | |
545 | union bpf_attr attr; | |
546 | int ret; | |
547 | ||
548 | if (!test_attr->data_out && test_attr->data_size_out > 0) | |
549 | return -EINVAL; | |
550 | ||
1ad9cbb8 | 551 | memset(&attr, 0, sizeof(attr)); |
64a97591 LB |
552 | attr.test.prog_fd = test_attr->prog_fd; |
553 | attr.test.data_in = ptr_to_u64(test_attr->data_in); | |
554 | attr.test.data_out = ptr_to_u64(test_attr->data_out); | |
555 | attr.test.data_size_in = test_attr->data_size_in; | |
556 | attr.test.data_size_out = test_attr->data_size_out; | |
5e903c65 SF |
557 | attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in); |
558 | attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out); | |
559 | attr.test.ctx_size_in = test_attr->ctx_size_in; | |
560 | attr.test.ctx_size_out = test_attr->ctx_size_out; | |
64a97591 LB |
561 | attr.test.repeat = test_attr->repeat; |
562 | ||
563 | ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); | |
564 | test_attr->data_size_out = attr.test.data_size_out; | |
5e903c65 | 565 | test_attr->ctx_size_out = attr.test.ctx_size_out; |
64a97591 LB |
566 | test_attr->retval = attr.test.retval; |
567 | test_attr->duration = attr.test.duration; | |
568 | return ret; | |
569 | } | |
570 | ||
95b9afd3 MKL |
571 | int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id) |
572 | { | |
573 | union bpf_attr attr; | |
574 | int err; | |
575 | ||
1ad9cbb8 | 576 | memset(&attr, 0, sizeof(attr)); |
95b9afd3 MKL |
577 | attr.start_id = start_id; |
578 | ||
579 | err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr)); | |
580 | if (!err) | |
581 | *next_id = attr.next_id; | |
582 | ||
583 | return err; | |
584 | } | |
585 | ||
586 | int bpf_map_get_next_id(__u32 start_id, __u32 *next_id) | |
587 | { | |
588 | union bpf_attr attr; | |
589 | int err; | |
590 | ||
1ad9cbb8 | 591 | memset(&attr, 0, sizeof(attr)); |
95b9afd3 MKL |
592 | attr.start_id = start_id; |
593 | ||
594 | err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr)); | |
595 | if (!err) | |
596 | *next_id = attr.next_id; | |
597 | ||
598 | return err; | |
599 | } | |
600 | ||
601 | int bpf_prog_get_fd_by_id(__u32 id) | |
602 | { | |
603 | union bpf_attr attr; | |
604 | ||
1ad9cbb8 | 605 | memset(&attr, 0, sizeof(attr)); |
95b9afd3 MKL |
606 | attr.prog_id = id; |
607 | ||
608 | return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr)); | |
609 | } | |
610 | ||
611 | int bpf_map_get_fd_by_id(__u32 id) | |
612 | { | |
613 | union bpf_attr attr; | |
614 | ||
1ad9cbb8 | 615 | memset(&attr, 0, sizeof(attr)); |
95b9afd3 MKL |
616 | attr.map_id = id; |
617 | ||
618 | return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr)); | |
619 | } | |
620 | ||
cd8b8928 MKL |
621 | int bpf_btf_get_fd_by_id(__u32 id) |
622 | { | |
623 | union bpf_attr attr; | |
624 | ||
1ad9cbb8 | 625 | memset(&attr, 0, sizeof(attr)); |
cd8b8928 MKL |
626 | attr.btf_id = id; |
627 | ||
628 | return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr)); | |
629 | } | |
630 | ||
95b9afd3 MKL |
631 | int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len) |
632 | { | |
633 | union bpf_attr attr; | |
634 | int err; | |
635 | ||
1ad9cbb8 | 636 | memset(&attr, 0, sizeof(attr)); |
95b9afd3 MKL |
637 | attr.info.bpf_fd = prog_fd; |
638 | attr.info.info_len = *info_len; | |
639 | attr.info.info = ptr_to_u64(info); | |
640 | ||
641 | err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)); | |
642 | if (!err) | |
643 | *info_len = attr.info.info_len; | |
644 | ||
645 | return err; | |
646 | } | |
949abbe8 | 647 | |
a0fe3e57 AS |
648 | int bpf_raw_tracepoint_open(const char *name, int prog_fd) |
649 | { | |
650 | union bpf_attr attr; | |
651 | ||
1ad9cbb8 | 652 | memset(&attr, 0, sizeof(attr)); |
a0fe3e57 AS |
653 | attr.raw_tracepoint.name = ptr_to_u64(name); |
654 | attr.raw_tracepoint.prog_fd = prog_fd; | |
655 | ||
656 | return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); | |
657 | } | |
658 | ||
8a138aed MKL |
659 | int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, |
660 | bool do_log) | |
661 | { | |
662 | union bpf_attr attr = {}; | |
663 | int fd; | |
664 | ||
665 | attr.btf = ptr_to_u64(btf); | |
666 | attr.btf_size = btf_size; | |
667 | ||
668 | retry: | |
669 | if (do_log && log_buf && log_buf_size) { | |
670 | attr.btf_log_level = 1; | |
671 | attr.btf_log_size = log_buf_size; | |
672 | attr.btf_log_buf = ptr_to_u64(log_buf); | |
673 | } | |
674 | ||
675 | fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr)); | |
676 | if (fd == -1 && !do_log && log_buf && log_buf_size) { | |
677 | do_log = true; | |
678 | goto retry; | |
679 | } | |
680 | ||
681 | return fd; | |
682 | } | |
30687ad9 YS |
683 | |
684 | int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, | |
685 | __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, | |
686 | __u64 *probe_addr) | |
687 | { | |
688 | union bpf_attr attr = {}; | |
689 | int err; | |
690 | ||
691 | attr.task_fd_query.pid = pid; | |
692 | attr.task_fd_query.fd = fd; | |
693 | attr.task_fd_query.flags = flags; | |
694 | attr.task_fd_query.buf = ptr_to_u64(buf); | |
695 | attr.task_fd_query.buf_len = *buf_len; | |
696 | ||
697 | err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr)); | |
698 | *buf_len = attr.task_fd_query.buf_len; | |
699 | *prog_id = attr.task_fd_query.prog_id; | |
700 | *fd_type = attr.task_fd_query.fd_type; | |
701 | *probe_offset = attr.task_fd_query.probe_offset; | |
702 | *probe_addr = attr.task_fd_query.probe_addr; | |
703 | ||
704 | return err; | |
705 | } |