Skip to content

KFunc bpf_iter_num_new


Initialize a new number iterator.


This kfunc initializes the iterator it, priming it to do a numeric iteration from start to end where start <= i < end.

If any of the input arguments are invalid, constructor should make sure to still initialize it such that subsequent bpf_iter_num_next() calls will return NULL. I.e., on error, return error and construct empty iterator.

int bpf_iter_num_new(struct bpf_iter_num *it, int start, int end)


These open coded iterators allow you to do iteration over kernel objects like iterator programs. Except we can just use a classic iterator pattern.

This specific iterator is a numeric iterator which allows us to iterate over a range of numbers. Effectively this gives us yet another way to do a for loop in BPF. The advantage of this method over bounded loops is that the verifier only has to check two states, the bpf_iter_num_next can return NULL or a integer between start and end. So no matter the size of the range, the verifier only has to check these two states, it understands the contract that the iterator will always produce a NULL at some point and terminate.

The advantages over the bpf_loop is that we keep the same scope, and we don't have to move variables back and forth between the main program and the callback via the context.

Program types

The following program types can make use of this kfunc:


struct bpf_iter_num it;
int *v;

bpf_iter_num_new(&it, 2, 5);
while ((v = bpf_iter_num_next(&it))) {
    bpf_printk("X = %d", *v);

Above snippet should output "X = 2", "X = 3", "X = 4". Note that 5 is exclusive and is not returned. This matches similar APIs (e.g., slices in Go or Rust) that implement a range of elements, where end index is non-inclusive.

Libbpf also provides macros to provide a more natural feeling way to write the above:

int *v;

bpf_for(v, start, end) {
    bpf_printk("X = %d", *v);

There is also a repeat macros:

int i = 0;
bpf_repeat(5) {
    bpf_printk("X = %d", i);