Blame view
tools/lib/bpf/bpf.c
24 KB
1bc38b8ff
|
1 |
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) |
6061a3d67
|
2 |
|
e3ed2fef2
|
3 4 5 6 7 8 |
/* * common eBPF ELF operations. * * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> * Copyright (C) 2015 Huawei Inc. |
203d1caca
|
9 10 11 12 13 14 15 16 17 18 19 20 21 |
* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License (not later!) * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see <http://www.gnu.org/licenses> |
e3ed2fef2
|
22 23 24 |
*/ #include <stdlib.h> |
1ad9cbb89
|
25 |
#include <string.h> |
e3ed2fef2
|
26 27 28 |
#include <memory.h> #include <unistd.h> #include <asm/unistd.h> |
d7fe74f94
|
29 |
#include <errno.h> |
e3ed2fef2
|
30 31 |
#include <linux/bpf.h> #include "bpf.h" |
949abbe88
|
32 |
#include "libbpf.h" |
d7fe74f94
|
33 |
#include "libbpf_internal.h" |
e3ed2fef2
|
34 35 |
/* |
03671057c
|
36 |
* When building perf, unistd.h is overridden. __NR_bpf is |
8f9e05fb2
|
37 |
* required to be defined explicitly. |
e3ed2fef2
|
38 39 40 41 42 43 44 45 |
*/ #ifndef __NR_bpf # if defined(__i386__) # define __NR_bpf 357 # elif defined(__x86_64__) # define __NR_bpf 321 # elif defined(__aarch64__) # define __NR_bpf 280 |
b0c47807d
|
46 47 |
# elif defined(__sparc__) # define __NR_bpf 349 |
bad1926dd
|
48 49 |
# elif defined(__s390__) # define __NR_bpf 351 |
ca31ca824
|
50 51 |
# elif defined(__arc__) # define __NR_bpf 280 |
e3ed2fef2
|
52 53 54 55 |
# else # error __NR_bpf not defined. libbpf does not support your arch. # endif #endif |
cdc6a4ba8
|
56 |
static inline __u64 ptr_to_u64(const void *ptr) |
7bf98369a
|
57 58 59 |
{ return (__u64) (unsigned long) ptr; } |
cdc6a4ba8
|
60 61 |
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size) |
e3ed2fef2
|
62 63 64 |
{ return syscall(__NR_bpf, cmd, attr, size); } |
86edaed37
|
65 66 67 68 69 70 71 72 73 74 |
static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size) { int fd; do { fd = sys_bpf(BPF_PROG_LOAD, attr, size); } while (fd < 0 && errno == EAGAIN); return fd; } |
8a138aed4
|
75 |
int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr) |
e3ed2fef2
|
76 77 78 79 |
{ union bpf_attr attr; memset(&attr, '\0', sizeof(attr)); |
8a138aed4
|
80 81 82 83 84 |
attr.map_type = create_attr->map_type; attr.key_size = create_attr->key_size; attr.value_size = create_attr->value_size; attr.max_entries = create_attr->max_entries; attr.map_flags = create_attr->map_flags; |
69a0f9ece
|
85 86 87 |
if (create_attr->name) memcpy(attr.map_name, create_attr->name, min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1)); |
8a138aed4
|
88 89 |
attr.numa_node = create_attr->numa_node; attr.btf_fd = create_attr->btf_fd; |
61746dbe1
|
90 91 |
attr.btf_key_type_id = create_attr->btf_key_type_id; attr.btf_value_type_id = create_attr->btf_value_type_id; |
f0307a7ed
|
92 |
attr.map_ifindex = create_attr->map_ifindex; |
590a00888
|
93 94 95 96 97 |
if (attr.map_type == BPF_MAP_TYPE_STRUCT_OPS) attr.btf_vmlinux_value_type_id = create_attr->btf_vmlinux_value_type_id; else attr.inner_map_fd = create_attr->inner_map_fd; |
8a138aed4
|
98 |
|
94cb310cf
|
99 |
return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); |
8a138aed4
|
100 |
} |
88cda1c9d
|
101 |
|
8a138aed4
|
102 103 104 105 106 107 108 109 110 111 112 113 |
int bpf_create_map_node(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, __u32 map_flags, int node) { struct bpf_create_map_attr map_attr = {}; map_attr.name = name; map_attr.map_type = map_type; map_attr.map_flags = map_flags; map_attr.key_size = key_size; map_attr.value_size = value_size; map_attr.max_entries = max_entries; |
ad17d0e6c
|
114 |
if (node >= 0) { |
8a138aed4
|
115 116 |
map_attr.numa_node = node; map_attr.map_flags |= BPF_F_NUMA_NODE; |
ad17d0e6c
|
117 |
} |
e3ed2fef2
|
118 |
|
8a138aed4
|
119 |
return bpf_create_map_xattr(&map_attr); |
e3ed2fef2
|
120 |
} |
7bf98369a
|
121 |
|
ad17d0e6c
|
122 123 124 |
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, __u32 map_flags) { |
8a138aed4
|
125 126 127 128 129 130 131 132 133 |
struct bpf_create_map_attr map_attr = {}; map_attr.map_type = map_type; map_attr.map_flags = map_flags; map_attr.key_size = key_size; map_attr.value_size = value_size; map_attr.max_entries = max_entries; return bpf_create_map_xattr(&map_attr); |
ad17d0e6c
|
134 |
} |
88cda1c9d
|
135 136 137 138 |
int bpf_create_map_name(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, __u32 map_flags) { |
8a138aed4
|
139 140 141 142 143 144 145 146 147 148 |
struct bpf_create_map_attr map_attr = {}; map_attr.name = name; map_attr.map_type = map_type; map_attr.map_flags = map_flags; map_attr.key_size = key_size; map_attr.value_size = value_size; map_attr.max_entries = max_entries; return bpf_create_map_xattr(&map_attr); |
88cda1c9d
|
149 150 151 152 |
} int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name, int key_size, int inner_map_fd, int max_entries, |
ad17d0e6c
|
153 |
__u32 map_flags, int node) |
fb30d4b71
|
154 155 156 157 158 159 160 161 162 163 164 |
{ union bpf_attr attr; memset(&attr, '\0', sizeof(attr)); attr.map_type = map_type; attr.key_size = key_size; attr.value_size = 4; attr.inner_map_fd = inner_map_fd; attr.max_entries = max_entries; attr.map_flags = map_flags; |
69a0f9ece
|
165 166 167 |
if (name) memcpy(attr.map_name, name, min(strlen(name), BPF_OBJ_NAME_LEN - 1)); |
88cda1c9d
|
168 |
|
ad17d0e6c
|
169 170 171 172 |
if (node >= 0) { attr.map_flags |= BPF_F_NUMA_NODE; attr.numa_node = node; } |
fb30d4b71
|
173 174 175 |
return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); } |
88cda1c9d
|
176 177 178 |
int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, int key_size, int inner_map_fd, int max_entries, __u32 map_flags) |
ad17d0e6c
|
179 |
{ |
88cda1c9d
|
180 181 182 |
return bpf_create_map_in_map_node(map_type, name, key_size, inner_map_fd, max_entries, map_flags, -1); |
ad17d0e6c
|
183 |
} |
3d6501414
|
184 185 186 187 |
static void * alloc_zero_tailing_info(const void *orecord, __u32 cnt, __u32 actual_rec_size, __u32 expected_rec_size) { |
4ee113561
|
188 |
__u64 info_len = (__u64)actual_rec_size * cnt; |
3d6501414
|
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
void *info, *nrecord; int i; info = malloc(info_len); if (!info) return NULL; /* zero out bytes kernel does not understand */ nrecord = info; for (i = 0; i < cnt; i++) { memcpy(nrecord, orecord, expected_rec_size); memset(nrecord + expected_rec_size, 0, actual_rec_size - expected_rec_size); orecord += actual_rec_size; nrecord += actual_rec_size; } return info; } |
d7be143b6
|
208 209 |
int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, char *log_buf, size_t log_buf_sz) |
7bf98369a
|
210 |
{ |
3d6501414
|
211 |
void *finfo = NULL, *linfo = NULL; |
7bf98369a
|
212 |
union bpf_attr attr; |
a4021a357
|
213 |
__u32 log_level; |
d7be143b6
|
214 |
int fd; |
a4021a357
|
215 216 217 218 |
if (!load_attr || !log_buf != !log_buf_sz) return -EINVAL; log_level = load_attr->log_level; |
da11b4175
|
219 |
if (log_level > (4 | 2 | 1) || (log_level && !log_buf)) |
d7be143b6
|
220 |
return -EINVAL; |
1ad9cbb89
|
221 |
memset(&attr, 0, sizeof(attr)); |
d7be143b6
|
222 223 |
attr.prog_type = load_attr->prog_type; attr.expected_attach_type = load_attr->expected_attach_type; |
1e092a031
|
224 225 |
if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS || attr.prog_type == BPF_PROG_TYPE_LSM) { |
590a00888
|
226 |
attr.attach_btf_id = load_attr->attach_btf_id; |
2db6eab18
|
227 228 |
} else if (attr.prog_type == BPF_PROG_TYPE_TRACING || attr.prog_type == BPF_PROG_TYPE_EXT) { |
12a8654b2
|
229 |
attr.attach_btf_id = load_attr->attach_btf_id; |
e7bf94dbb
|
230 231 |
attr.attach_prog_fd = load_attr->attach_prog_fd; } else { |
12a8654b2
|
232 |
attr.prog_ifindex = load_attr->prog_ifindex; |
e7bf94dbb
|
233 234 |
attr.kern_version = load_attr->kern_version; } |
d7be143b6
|
235 236 237 |
attr.insn_cnt = (__u32)load_attr->insns_cnt; attr.insns = ptr_to_u64(load_attr->insns); attr.license = ptr_to_u64(load_attr->license); |
a4021a357
|
238 239 240 241 242 243 244 245 246 |
attr.log_level = log_level; if (log_level) { attr.log_buf = ptr_to_u64(log_buf); attr.log_size = log_buf_sz; } else { attr.log_buf = ptr_to_u64(NULL); attr.log_size = 0; } |
7e0d0fb55
|
247 248 249 250 |
attr.prog_btf_fd = load_attr->prog_btf_fd; attr.func_info_rec_size = load_attr->func_info_rec_size; attr.func_info_cnt = load_attr->func_info_cnt; attr.func_info = ptr_to_u64(load_attr->func_info); |
3d6501414
|
251 252 253 |
attr.line_info_rec_size = load_attr->line_info_rec_size; attr.line_info_cnt = load_attr->line_info_cnt; attr.line_info = ptr_to_u64(load_attr->line_info); |
69a0f9ece
|
254 255 256 |
if (load_attr->name) memcpy(attr.prog_name, load_attr->name, min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1)); |
046561981
|
257 |
attr.prog_flags = load_attr->prog_flags; |
7bf98369a
|
258 |
|
86edaed37
|
259 |
fd = sys_bpf_prog_load(&attr, sizeof(attr)); |
f0187f0b1
|
260 |
if (fd >= 0) |
7bf98369a
|
261 |
return fd; |
2993e0515
|
262 263 264 265 |
/* After bpf_prog_load, the kernel may modify certain attributes * to give user space a hint how to deal with loading failure. * Check to see whether we can make some changes and load again. */ |
3d6501414
|
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
while (errno == E2BIG && (!finfo || !linfo)) { if (!finfo && attr.func_info_cnt && attr.func_info_rec_size < load_attr->func_info_rec_size) { /* try with corrected func info records */ finfo = alloc_zero_tailing_info(load_attr->func_info, load_attr->func_info_cnt, load_attr->func_info_rec_size, attr.func_info_rec_size); if (!finfo) goto done; attr.func_info = ptr_to_u64(finfo); attr.func_info_rec_size = load_attr->func_info_rec_size; } else if (!linfo && attr.line_info_cnt && attr.line_info_rec_size < load_attr->line_info_rec_size) { linfo = alloc_zero_tailing_info(load_attr->line_info, load_attr->line_info_cnt, load_attr->line_info_rec_size, attr.line_info_rec_size); if (!linfo) goto done; attr.line_info = ptr_to_u64(linfo); attr.line_info_rec_size = load_attr->line_info_rec_size; } else { break; |
2993e0515
|
293 |
} |
86edaed37
|
294 |
fd = sys_bpf_prog_load(&attr, sizeof(attr)); |
2993e0515
|
295 |
|
f0187f0b1
|
296 |
if (fd >= 0) |
2993e0515
|
297 298 |
goto done; } |
a4021a357
|
299 |
if (log_level || !log_buf) |
f0187f0b1
|
300 |
goto done; |
7bf98369a
|
301 302 303 304 305 |
/* Try again with log */ attr.log_buf = ptr_to_u64(log_buf); attr.log_size = log_buf_sz; attr.log_level = 1; log_buf[0] = 0; |
86edaed37
|
306 |
fd = sys_bpf_prog_load(&attr, sizeof(attr)); |
2993e0515
|
307 308 |
done: free(finfo); |
3d6501414
|
309 |
free(linfo); |
2993e0515
|
310 |
return fd; |
7bf98369a
|
311 |
} |
43798bf37
|
312 |
|
88cda1c9d
|
313 314 315 316 317 |
int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, size_t insns_cnt, const char *license, __u32 kern_version, char *log_buf, size_t log_buf_sz) { |
d7be143b6
|
318 319 320 321 322 323 324 325 326 327 328 329 |
struct bpf_load_program_attr load_attr; memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); load_attr.prog_type = type; load_attr.expected_attach_type = 0; load_attr.name = NULL; load_attr.insns = insns; load_attr.insns_cnt = insns_cnt; load_attr.license = license; load_attr.kern_version = kern_version; return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz); |
88cda1c9d
|
330 |
} |
91045f5e5
|
331 |
int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, |
e9ee9efc0
|
332 333 334 |
size_t insns_cnt, __u32 prog_flags, const char *license, __u32 kern_version, char *log_buf, size_t log_buf_sz, int log_level) |
91045f5e5
|
335 336 |
{ union bpf_attr attr; |
1ad9cbb89
|
337 |
memset(&attr, 0, sizeof(attr)); |
91045f5e5
|
338 339 340 341 342 343 |
attr.prog_type = type; attr.insn_cnt = (__u32)insns_cnt; attr.insns = ptr_to_u64(insns); attr.license = ptr_to_u64(license); attr.log_buf = ptr_to_u64(log_buf); attr.log_size = log_buf_sz; |
d65549041
|
344 |
attr.log_level = log_level; |
91045f5e5
|
345 346 |
log_buf[0] = 0; attr.kern_version = kern_version; |
e9ee9efc0
|
347 |
attr.prog_flags = prog_flags; |
91045f5e5
|
348 |
|
86edaed37
|
349 |
return sys_bpf_prog_load(&attr, sizeof(attr)); |
91045f5e5
|
350 |
} |
10ecc728f
|
351 |
int bpf_map_update_elem(int fd, const void *key, const void *value, |
83d994d02
|
352 |
__u64 flags) |
43798bf37
|
353 354 |
{ union bpf_attr attr; |
1ad9cbb89
|
355 |
memset(&attr, 0, sizeof(attr)); |
43798bf37
|
356 357 358 359 360 361 362 |
attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); attr.flags = flags; return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); } |
9742da015
|
363 |
|
e5ff7c401
|
364 |
int bpf_map_lookup_elem(int fd, const void *key, void *value) |
9742da015
|
365 366 |
{ union bpf_attr attr; |
1ad9cbb89
|
367 |
memset(&attr, 0, sizeof(attr)); |
9742da015
|
368 369 370 371 372 373 |
attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); } |
df5d22fac
|
374 375 376 |
int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags) { union bpf_attr attr; |
1ad9cbb89
|
377 |
memset(&attr, 0, sizeof(attr)); |
df5d22fac
|
378 379 380 381 382 383 384 |
attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); attr.flags = flags; return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); } |
43b987d23
|
385 386 387 |
int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) { union bpf_attr attr; |
1ad9cbb89
|
388 |
memset(&attr, 0, sizeof(attr)); |
43b987d23
|
389 390 391 392 393 394 |
attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); } |
e58383b80
|
395 |
int bpf_map_delete_elem(int fd, const void *key) |
9742da015
|
396 397 |
{ union bpf_attr attr; |
1ad9cbb89
|
398 |
memset(&attr, 0, sizeof(attr)); |
9742da015
|
399 400 401 402 403 |
attr.map_fd = fd; attr.key = ptr_to_u64(key); return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); } |
5f155c256
|
404 |
int bpf_map_get_next_key(int fd, const void *key, void *next_key) |
9742da015
|
405 406 |
{ union bpf_attr attr; |
1ad9cbb89
|
407 |
memset(&attr, 0, sizeof(attr)); |
9742da015
|
408 409 410 411 412 413 |
attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.next_key = ptr_to_u64(next_key); return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr)); } |
d859900c4
|
414 415 416 417 418 419 420 421 422 |
int bpf_map_freeze(int fd) { union bpf_attr attr; memset(&attr, 0, sizeof(attr)); attr.map_fd = fd; return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr)); } |
2ab3d86ea
|
423 424 425 426 427 |
static int bpf_map_batch_common(int cmd, int fd, void *in_batch, void *out_batch, void *keys, void *values, __u32 *count, const struct bpf_map_batch_opts *opts) { |
858e284f0
|
428 |
union bpf_attr attr; |
2ab3d86ea
|
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
int ret; if (!OPTS_VALID(opts, bpf_map_batch_opts)) return -EINVAL; memset(&attr, 0, sizeof(attr)); attr.batch.map_fd = fd; attr.batch.in_batch = ptr_to_u64(in_batch); attr.batch.out_batch = ptr_to_u64(out_batch); attr.batch.keys = ptr_to_u64(keys); attr.batch.values = ptr_to_u64(values); attr.batch.count = *count; attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0); attr.batch.flags = OPTS_GET(opts, flags, 0); ret = sys_bpf(cmd, &attr, sizeof(attr)); *count = attr.batch.count; return ret; } int bpf_map_delete_batch(int fd, void *keys, __u32 *count, const struct bpf_map_batch_opts *opts) { return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL, NULL, keys, NULL, count, opts); } int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys, void *values, __u32 *count, const struct bpf_map_batch_opts *opts) { return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch, out_batch, keys, values, count, opts); } int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch, void *keys, void *values, __u32 *count, const struct bpf_map_batch_opts *opts) { return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH, fd, in_batch, out_batch, keys, values, count, opts); } int bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count, const struct bpf_map_batch_opts *opts) { return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL, keys, values, count, opts); } |
9742da015
|
480 481 482 |
int bpf_obj_pin(int fd, const char *pathname) { union bpf_attr attr; |
1ad9cbb89
|
483 |
memset(&attr, 0, sizeof(attr)); |
9742da015
|
484 485 486 487 488 489 490 491 492 |
attr.pathname = ptr_to_u64((void *)pathname); attr.bpf_fd = fd; return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); } int bpf_obj_get(const char *pathname) { union bpf_attr attr; |
1ad9cbb89
|
493 |
memset(&attr, 0, sizeof(attr)); |
9742da015
|
494 495 496 497 |
attr.pathname = ptr_to_u64((void *)pathname); return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); } |
5dc880de6
|
498 |
|
464bc0fd6
|
499 500 |
int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, unsigned int flags) |
5dc880de6
|
501 |
{ |
cdbee3839
|
502 503 504 505 506 507 508 509 510 511 512 |
DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts, .flags = flags, ); return bpf_prog_attach_xattr(prog_fd, target_fd, type, &opts); } int bpf_prog_attach_xattr(int prog_fd, int target_fd, enum bpf_attach_type type, const struct bpf_prog_attach_opts *opts) { |
5dc880de6
|
513 |
union bpf_attr attr; |
cdbee3839
|
514 515 |
if (!OPTS_VALID(opts, bpf_prog_attach_opts)) return -EINVAL; |
1ad9cbb89
|
516 |
memset(&attr, 0, sizeof(attr)); |
5dc880de6
|
517 |
attr.target_fd = target_fd; |
464bc0fd6
|
518 |
attr.attach_bpf_fd = prog_fd; |
5dc880de6
|
519 |
attr.attach_type = type; |
cdbee3839
|
520 521 |
attr.attach_flags = OPTS_GET(opts, flags, 0); attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0); |
5dc880de6
|
522 523 524 525 526 527 528 |
return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); } int bpf_prog_detach(int target_fd, enum bpf_attach_type type) { union bpf_attr attr; |
1ad9cbb89
|
529 |
memset(&attr, 0, sizeof(attr)); |
5dc880de6
|
530 531 532 533 534 |
attr.target_fd = target_fd; attr.attach_type = type; return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); } |
308488737
|
535 |
|
244d20efd
|
536 537 538 |
int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) { union bpf_attr attr; |
1ad9cbb89
|
539 |
memset(&attr, 0, sizeof(attr)); |
244d20efd
|
540 541 542 543 544 545 |
attr.target_fd = target_fd; attr.attach_bpf_fd = prog_fd; attr.attach_type = type; return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); } |
cc4f864bb
|
546 547 548 549 |
int bpf_link_create(int prog_fd, int target_fd, enum bpf_attach_type attach_type, const struct bpf_link_create_opts *opts) { |
a53590914
|
550 |
__u32 target_btf_id, iter_info_len; |
cc4f864bb
|
551 552 553 554 |
union bpf_attr attr; if (!OPTS_VALID(opts, bpf_link_create_opts)) return -EINVAL; |
a53590914
|
555 556 557 558 559 |
iter_info_len = OPTS_GET(opts, iter_info_len, 0); target_btf_id = OPTS_GET(opts, target_btf_id, 0); if (iter_info_len && target_btf_id) return -EINVAL; |
cc4f864bb
|
560 561 562 563 |
memset(&attr, 0, sizeof(attr)); attr.link_create.prog_fd = prog_fd; attr.link_create.target_fd = target_fd; attr.link_create.attach_type = attach_type; |
cd31039a7
|
564 |
attr.link_create.flags = OPTS_GET(opts, flags, 0); |
a53590914
|
565 566 567 568 569 570 571 572 |
if (iter_info_len) { attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0)); attr.link_create.iter_info_len = iter_info_len; } else if (target_btf_id) { attr.link_create.target_btf_id = target_btf_id; } |
cc4f864bb
|
573 574 575 |
return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr)); } |
2e49527e5
|
576 577 578 579 580 581 582 583 584 |
int bpf_link_detach(int link_fd) { union bpf_attr attr; memset(&attr, 0, sizeof(attr)); attr.link_detach.link_fd = link_fd; return sys_bpf(BPF_LINK_DETACH, &attr, sizeof(attr)); } |
cc4f864bb
|
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 |
int bpf_link_update(int link_fd, int new_prog_fd, const struct bpf_link_update_opts *opts) { union bpf_attr attr; if (!OPTS_VALID(opts, bpf_link_update_opts)) return -EINVAL; memset(&attr, 0, sizeof(attr)); attr.link_update.link_fd = link_fd; attr.link_update.new_prog_fd = new_prog_fd; attr.link_update.flags = OPTS_GET(opts, flags, 0); attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0); return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr)); } |
c09add2fb
|
601 602 603 604 605 606 607 608 609 |
int bpf_iter_create(int link_fd) { union bpf_attr attr; memset(&attr, 0, sizeof(attr)); attr.iter_create.link_fd = link_fd; return sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr)); } |
5d0cbf9b6
|
610 611 612 613 614 |
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) { union bpf_attr attr; int ret; |
1ad9cbb89
|
615 |
memset(&attr, 0, sizeof(attr)); |
5d0cbf9b6
|
616 617 618 619 620 621 622 623 624 625 626 627 |
attr.query.target_fd = target_fd; attr.query.attach_type = type; attr.query.query_flags = query_flags; attr.query.prog_cnt = *prog_cnt; attr.query.prog_ids = ptr_to_u64(prog_ids); ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr)); if (attach_flags) *attach_flags = attr.query.attach_flags; *prog_cnt = attr.query.prog_cnt; return ret; } |
308488737
|
628 629 630 631 632 633 |
int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, void *data_out, __u32 *size_out, __u32 *retval, __u32 *duration) { union bpf_attr attr; int ret; |
1ad9cbb89
|
634 |
memset(&attr, 0, sizeof(attr)); |
308488737
|
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
attr.test.prog_fd = prog_fd; attr.test.data_in = ptr_to_u64(data); attr.test.data_out = ptr_to_u64(data_out); attr.test.data_size_in = size; attr.test.repeat = repeat; ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); if (size_out) *size_out = attr.test.data_size_out; if (retval) *retval = attr.test.retval; if (duration) *duration = attr.test.duration; return ret; } |
95b9afd39
|
650 |
|
64a975913
|
651 652 653 654 655 656 657 |
int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr) { union bpf_attr attr; int ret; if (!test_attr->data_out && test_attr->data_size_out > 0) return -EINVAL; |
1ad9cbb89
|
658 |
memset(&attr, 0, sizeof(attr)); |
64a975913
|
659 660 661 662 663 |
attr.test.prog_fd = test_attr->prog_fd; attr.test.data_in = ptr_to_u64(test_attr->data_in); attr.test.data_out = ptr_to_u64(test_attr->data_out); attr.test.data_size_in = test_attr->data_size_in; attr.test.data_size_out = test_attr->data_size_out; |
5e903c656
|
664 665 666 667 |
attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in); attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out); attr.test.ctx_size_in = test_attr->ctx_size_in; attr.test.ctx_size_out = test_attr->ctx_size_out; |
64a975913
|
668 669 670 671 |
attr.test.repeat = test_attr->repeat; ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); test_attr->data_size_out = attr.test.data_size_out; |
5e903c656
|
672 |
test_attr->ctx_size_out = attr.test.ctx_size_out; |
64a975913
|
673 674 675 676 |
test_attr->retval = attr.test.retval; test_attr->duration = attr.test.duration; return ret; } |
88f7fe723
|
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 |
int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts) { union bpf_attr attr; int ret; if (!OPTS_VALID(opts, bpf_test_run_opts)) return -EINVAL; memset(&attr, 0, sizeof(attr)); attr.test.prog_fd = prog_fd; attr.test.cpu = OPTS_GET(opts, cpu, 0); attr.test.flags = OPTS_GET(opts, flags, 0); attr.test.repeat = OPTS_GET(opts, repeat, 0); attr.test.duration = OPTS_GET(opts, duration, 0); attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0); attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0); attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0); attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0); attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL)); attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL)); attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL)); attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL)); ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); OPTS_SET(opts, data_size_out, attr.test.data_size_out); OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out); OPTS_SET(opts, duration, attr.test.duration); OPTS_SET(opts, retval, attr.test.retval); return ret; } |
a6e130c42
|
707 |
static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd) |
95b9afd39
|
708 709 710 |
{ union bpf_attr attr; int err; |
1ad9cbb89
|
711 |
memset(&attr, 0, sizeof(attr)); |
95b9afd39
|
712 |
attr.start_id = start_id; |
a6e130c42
|
713 |
err = sys_bpf(cmd, &attr, sizeof(attr)); |
95b9afd39
|
714 715 716 717 718 |
if (!err) *next_id = attr.next_id; return err; } |
a6e130c42
|
719 |
int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id) |
95b9afd39
|
720 |
{ |
a6e130c42
|
721 722 |
return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID); } |
95b9afd39
|
723 |
|
a6e130c42
|
724 725 726 |
int bpf_map_get_next_id(__u32 start_id, __u32 *next_id) { return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID); |
95b9afd39
|
727 |
} |
09d7c2e32
|
728 729 730 731 |
int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id) { return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID); } |
0dbc86683
|
732 733 734 735 |
int bpf_link_get_next_id(__u32 start_id, __u32 *next_id) { return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID); } |
95b9afd39
|
736 737 738 |
int bpf_prog_get_fd_by_id(__u32 id) { union bpf_attr attr; |
1ad9cbb89
|
739 |
memset(&attr, 0, sizeof(attr)); |
95b9afd39
|
740 741 742 743 744 745 746 747 |
attr.prog_id = id; return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr)); } int bpf_map_get_fd_by_id(__u32 id) { union bpf_attr attr; |
1ad9cbb89
|
748 |
memset(&attr, 0, sizeof(attr)); |
95b9afd39
|
749 750 751 752 |
attr.map_id = id; return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr)); } |
cd8b89280
|
753 754 755 |
int bpf_btf_get_fd_by_id(__u32 id) { union bpf_attr attr; |
1ad9cbb89
|
756 |
memset(&attr, 0, sizeof(attr)); |
cd8b89280
|
757 758 759 760 |
attr.btf_id = id; return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr)); } |
0dbc86683
|
761 762 763 764 765 766 767 768 769 770 771 |
int bpf_link_get_fd_by_id(__u32 id) { union bpf_attr attr; memset(&attr, 0, sizeof(attr)); attr.link_id = id; return sys_bpf(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr)); } int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len) |
95b9afd39
|
772 773 774 |
{ union bpf_attr attr; int err; |
1ad9cbb89
|
775 |
memset(&attr, 0, sizeof(attr)); |
0dbc86683
|
776 |
attr.info.bpf_fd = bpf_fd; |
95b9afd39
|
777 778 779 780 781 782 783 784 785 |
attr.info.info_len = *info_len; attr.info.info = ptr_to_u64(info); err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)); if (!err) *info_len = attr.info.info_len; return err; } |
949abbe88
|
786 |
|
a0fe3e574
|
787 788 789 |
int bpf_raw_tracepoint_open(const char *name, int prog_fd) { union bpf_attr attr; |
1ad9cbb89
|
790 |
memset(&attr, 0, sizeof(attr)); |
a0fe3e574
|
791 792 793 794 795 |
attr.raw_tracepoint.name = ptr_to_u64(name); attr.raw_tracepoint.prog_fd = prog_fd; return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); } |
b86042478
|
796 |
int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, |
8a138aed4
|
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 |
bool do_log) { union bpf_attr attr = {}; int fd; attr.btf = ptr_to_u64(btf); attr.btf_size = btf_size; retry: if (do_log && log_buf && log_buf_size) { attr.btf_log_level = 1; attr.btf_log_size = log_buf_size; attr.btf_log_buf = ptr_to_u64(log_buf); } fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr)); if (fd == -1 && !do_log && log_buf && log_buf_size) { do_log = true; goto retry; } return fd; } |
30687ad94
|
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, __u64 *probe_addr) { union bpf_attr attr = {}; int err; attr.task_fd_query.pid = pid; attr.task_fd_query.fd = fd; attr.task_fd_query.flags = flags; attr.task_fd_query.buf = ptr_to_u64(buf); attr.task_fd_query.buf_len = *buf_len; err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr)); *buf_len = attr.task_fd_query.buf_len; *prog_id = attr.task_fd_query.prog_id; *fd_type = attr.task_fd_query.fd_type; *probe_offset = attr.task_fd_query.probe_offset; *probe_addr = attr.task_fd_query.probe_addr; return err; } |
0bee10671
|
843 844 845 846 847 848 849 850 851 852 |
int bpf_enable_stats(enum bpf_stats_type type) { union bpf_attr attr; memset(&attr, 0, sizeof(attr)); attr.enable_stats.type = type; return sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr)); } |
5d23328dc
|
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 |
int bpf_prog_bind_map(int prog_fd, int map_fd, const struct bpf_prog_bind_opts *opts) { union bpf_attr attr; if (!OPTS_VALID(opts, bpf_prog_bind_opts)) return -EINVAL; memset(&attr, 0, sizeof(attr)); attr.prog_bind_map.prog_fd = prog_fd; attr.prog_bind_map.map_fd = map_fd; attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0); return sys_bpf(BPF_PROG_BIND_MAP, &attr, sizeof(attr)); } |