Skip to content

Commit

Permalink
libbpf/ebpf: Added pages for open coded iterator macros
Browse files Browse the repository at this point in the history
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
dylandreimerink committed Nov 23, 2024
1 parent 985a8c5 commit 31752fb
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@
- [`BPF_SEQ_PRINTF`](bpf_seq_printf.md)
- [`BPF_SNPRINTF`](bpf_snprintf.md)
- [`bpf_printk`](bpf_printk.md)
- Open coded iterator loop macros
- [`bpf_for_each`](bpf_for_each.md)
- [`bpf_for`](bpf_for.md)
- [`bpf_repeat`](bpf_repeat.md)
55 changes: 55 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/bpf_for.md
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;
}
```
78 changes: 78 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/bpf_for_each.md
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;
}
```
44 changes: 44 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/bpf_repeat.md
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;
}
}
```
6 changes: 3 additions & 3 deletions docs/ebpf-library/libbpf/ebpf/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ The file contains definitions for the following:
* [`BPF_SNPRINTF`](bpf_snprintf.md)
* [`bpf_printk`](bpf_printk.md)
* Open coded iterator loop macros
* `bpf_for_each`
* `bpf_for`
* `bpf_repeat`
* [`bpf_for_each`](bpf_for_each.md)
* [`bpf_for`](bpf_for.md)
* [`bpf_repeat`](bpf_repeat.md)

## [`bpf_endian.h`](https://github.com/libbpf/libbpf/blob/master/src/bpf_endian.h)

Expand Down

0 comments on commit 31752fb

Please sign in to comment.