Search code examples
llvm-clangbpfebpf

Are loops allowed in Linux's BPF programs?


I am thinking of a solution of replicating packets in the kernel and forward to 5 hosts (unicast). Planning to utilize eBPF/XDP for it.

I am trying to loop for 5 times, and inside the loop I am planning to clone the packet, modify the DST IP address, update the cksum and tx the packet out on the same intf it was received.

I read somewhere loops can't be used in XDP, so not sure if this will work ?

Need the expert's advice please.


Solution

  • Edit August 2022

    The bpf_loop() BPF helper function is available starting with Linux 5.17 (commit), taking a number of iterations, a callback functions, and a context on which to run this callback in a loop within an eBPF program:

    long bpf_loop(u32 nr_loops, void *callback_fn, void *callback_ctx, u64 flags)
    

    Edit June 2019

    Bounded loops have now landed to the kernel, and are available starting with Linux 5.3 (commit).

    Original answer

    No, at this moment loops are not allowed in eBPF programs. Back edges are not allowed, so that the kernel verifier can make sure that the programs terminate (and do not hang the kernel).

    This might change in the future, as kernel developers are working on support for bounding loops.

    There are two possible workarounds worth mentioning. Both suppose that you know how many times you would have to “loop” when writing your program.

    First, there's an exception for back edges, regarding functions. Which means you can have functions, and call them multiple times. So you could have all the content that you would normally put in your loop in a separate function, and call this function as many times as you would loop.

    The second thing is that you can actually write loops in your C code, and ask clang to unroll them at compile time. This looks like the following:

    #pragma clang loop unroll(full)
            for (i = 0; i < 4; i++) {
                /* Do stuff ... */
            }
    

    This means that in the resulting object file the function will be unrolled, it will be replaced by the full series of instructions to be performed, with no actual backward jump.

    There is no solution for a sequence with an arbitrary number of loops at the moment.