Libbpf eBPF macro bpf_for
The bpf_for
macro is used to make writing a for loop with an open coded iterator easier.
Definition
#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 page.
Example
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;
}