-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libbpf/ebpf: Added pages for open coded iterator macros
This commit adds pages for the open coded iterator macros that are available in the libbpf ebpf library. Signed-off-by: Dylan Reimerink <[email protected]>
- Loading branch information
1 parent
985a8c5
commit 31752fb
Showing
5 changed files
with
184 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--- | ||
title: "Libbpf eBPF macro 'bpf_for'" | ||
description: "This page documents the 'bpf_for' libbpf eBPF macro, including its definition, usage, and examples." | ||
--- | ||
# Libbpf eBPF macro `bpf_for` | ||
|
||
[:octicons-tag-24: v1.2.0](https://github.com/libbpf/libbpf/releases/tag/v1.2.0) | ||
|
||
The `bpf_for` macro is used to make writing a for loop with an open coded iterator easier. | ||
|
||
## Definition | ||
|
||
```c | ||
#define bpf_for(i, start, end) for ( \ | ||
/* initialize and define destructor */ \ | ||
struct bpf_iter_num ___it __attribute__((aligned(8), /* enforce, just in case */ \ | ||
cleanup(bpf_iter_num_destroy))), \ | ||
/* ___p pointer is necessary to call bpf_iter_num_new() *once* to init ___it */ \ | ||
*___p __attribute__((unused)) = ( \ | ||
bpf_iter_num_new(&___it, (start), (end)), \ | ||
/* this is a workaround for Clang bug: it currently doesn't emit BTF */ \ | ||
/* for bpf_iter_num_destroy() when used from cleanup() attribute */ \ | ||
(void)bpf_iter_num_destroy, (void *)0); \ | ||
({ \ | ||
/* iteration step */ \ | ||
int *___t = bpf_iter_num_next(&___it); \ | ||
/* termination and bounds check */ \ | ||
(___t && ((i) = *___t, (i) >= (start) && (i) < (end))); \ | ||
}); \ | ||
) | ||
``` | ||
## Usage | ||
This macro makes writing a for loop with an open coded iterator easier. `bpf_for` specifically uses the numeric open coded iterator, which instead of looping over kernel structures loops over a range of numbers. | ||
The `bpf_for` macro is a neat shorthand for manually writing the iteration logic. | ||
The reason you might want to use this instead of a traditional `for` loop is to get a large loop count without making the verifier upset. Using the open code numeric iterator allows for a large number of iterations without inflating complexity and while keeping the current scope. For details see the [loops concept](../../../linux/concepts/loops.md) page. | ||
### Example | ||
```c | ||
SEC("raw_tp/sys_enter") | ||
int iter_next_rcu(const void *ctx) | ||
{ | ||
int v; | ||
// Will print 2, 3, 4, 5 | ||
bpf_for(v, 2, 5) { | ||
bpf_printk("X = %d", v); | ||
} | ||
return 0; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
title: "Libbpf eBPF macro 'bpf_for_each'" | ||
description: "This page documents the 'bpf_for_each' libbpf eBPF macro, including its definition, usage, and examples." | ||
--- | ||
# Libbpf eBPF macro `bpf_for_each` | ||
|
||
[:octicons-tag-24: v1.2.0](https://github.com/libbpf/libbpf/releases/tag/v1.2.0) | ||
|
||
The `bpf_for_each` macro is used to make looping over open-coded iterators easier. | ||
|
||
## Definition | ||
|
||
```c | ||
#define bpf_for_each(type, cur, args...) for ( \ | ||
/* initialize and define destructor */ \ | ||
struct bpf_iter_##type ___it __attribute__((aligned(8), /* enforce, just in case */, \ | ||
cleanup(bpf_iter_##type##_destroy))), \ | ||
/* ___p pointer is just to call bpf_iter_##type##_new() *once* to init ___it */ \ | ||
*___p __attribute__((unused)) = ( \ | ||
bpf_iter_##type##_new(&___it, ##args), \ | ||
/* this is a workaround for Clang bug: it currently doesn't emit BTF */ \ | ||
/* for bpf_iter_##type##_destroy() when used from cleanup() attribute */ \ | ||
(void)bpf_iter_##type##_destroy, (void *)0); \ | ||
/* iteration and termination check */ \ | ||
(((cur) = bpf_iter_##type##_next(&___it))); \ | ||
) | ||
``` | ||
## Usage | ||
This macro makes looping over open coded iterators easier. Open coded iterators were introduced in kernel [:octicons-tag-24: v6.4](https://github.com/torvalds/linux/commit/06accc8779c1d558a5b5a21f2ac82b0c95827ddd) and allow for iterating/looping over specific kernel data structures. | ||
Normally, you would have to write iteration logic manually like: | ||
```c | ||
SEC("raw_tp/sys_enter") | ||
int my_example(const void *ctx) | ||
{ | ||
struct bpf_iter_task task_it; | ||
struct task_struct *task_ptr; | ||
// Initialize the iterator, request to iterate over all processes on the system | ||
bpf_iter_task_new(&task_it, NULL, BPF_TASK_ITER_ALL_PROCS); | ||
// Loop until `bpf_iter_task_next` returns NULL | ||
while((task_ptr = bpf_iter_task_next(&task_it))) { | ||
// Do something with the task pointer | ||
if (/* We found the task we are looking for*/) | ||
break; | ||
} | ||
bpf_iter_task_destroy(&task_it); | ||
return 0; | ||
} | ||
``` | ||
|
||
There are a few different iterator types, all follow the same naming convention: `bpf_iter_<type>_{new,next,destroy}`. The `bpf_for_each` macro makes use of this to simplify the iteration logic the user has to write. | ||
|
||
The first argument is the `<type>` part of the iterator functions. The second argument is the variable name that will be used to store the current iterator value. And the rest of the arguments are passed to the `bpf_iter_<type>_new` function, the exact meaning depends on the iterator type. | ||
|
||
### Example | ||
|
||
```c | ||
SEC("raw_tp/sys_enter") | ||
int my_example(const void *ctx) | ||
{ | ||
struct task_struct *task_ptr; | ||
bpf_for_each(task, task_ptr, NULL, BPF_TASK_ITER_ALL_PROCS) { | ||
// Do something with the task pointer | ||
|
||
if (/* We found the task we are looking for*/) | ||
break; | ||
} | ||
|
||
return 0; | ||
} | ||
``` | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--- | ||
title: "Libbpf eBPF macro 'bpf_repeat'" | ||
description: "This page documents the 'bpf_repeat' libbpf eBPF macro, including its definition, usage, and examples." | ||
--- | ||
# Libbpf eBPF macro `bpf_repeat` | ||
|
||
[:octicons-tag-24: v1.2.0](https://github.com/libbpf/libbpf/releases/tag/v1.2.0) | ||
|
||
The `bpf_repeat` macro is used it easier to write a loop that repeats X times using open coded iterators. | ||
|
||
## Definition | ||
|
||
```c | ||
#define bpf_repeat(N) for ( \ | ||
/* initialize and define destructor */ \ | ||
struct bpf_iter_num ___it __attribute__((aligned(8), /* enforce, just in case */ \ | ||
cleanup(bpf_iter_num_destroy))), \ | ||
/* ___p pointer is necessary to call bpf_iter_num_new() *once* to init ___it */ \ | ||
*___p __attribute__((unused)) = ( \ | ||
bpf_iter_num_new(&___it, 0, (N)), \ | ||
/* this is a workaround for Clang bug: it currently doesn't emit BTF */ \ | ||
/* for bpf_iter_num_destroy() when used from cleanup() attribute */ \ | ||
(void)bpf_iter_num_destroy, (void *)0); \ | ||
bpf_iter_num_next(&___it); \ | ||
/* nothing here */ \ | ||
) | ||
``` | ||
## Usage | ||
This macro makes writing a loop that repeats X times using open coded iterators easier. `bpf_repeat` is a simplified version of the [`bpf_for`](bpf_for.md) macro, which simply executes the loop body `N` times and does not make the iteration count available. | ||
### Example | ||
```c | ||
SEC("raw_tp/sys_enter") | ||
int iter_next_rcu(const void *ctx) | ||
{ | ||
bpf_repeat(64) { | ||
if (try_to_do_something()) | ||
break; | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters