• Andrii Nakryiko's avatar
    bpf: implement numbers iterator · 6018e1f4
    Andrii Nakryiko authored
    Implement the first open-coded iterator type over a range of integers.
    
    It's public API consists of:
      - bpf_iter_num_new() constructor, which accepts [start, end) range
        (that is, start is inclusive, end is exclusive).
      - bpf_iter_num_next() which will keep returning read-only pointer to int
        until the range is exhausted, at which point NULL will be returned.
        If bpf_iter_num_next() is kept calling after this, NULL will be
        persistently returned.
      - bpf_iter_num_destroy() destructor, which needs to be called at some
        point to clean up iterator state. BPF verifier enforces that iterator
        destructor is called at some point before BPF program exits.
    
    Note that `start = end = X` is a valid combination to setup an empty
    iterator. bpf_iter_num_new() will return 0 (success) for any such
    combination.
    
    If bpf_iter_num_new() detects invalid combination of input arguments, it
    returns error, resets iterator state to, effectively, empty iterator, so
    any subsequent call to bpf_iter_num_next() will keep returning NULL.
    
    BPF verifier has no knowledge that returned integers are in the
    [start, end) value range, as both `start` and `end` are not statically
    known and enforced: they are runtime values.
    
    While the implementation is pretty trivial, some care needs to be taken
    to avoid overflows and underflows. Subsequent selftests will validate
    correctness of [start, end) semantics, especially around extremes
    (INT_MIN and INT_MAX).
    
    Similarly to bpf_loop(), we enforce that no more than BPF_MAX_LOOPS can
    be specified.
    
    bpf_iter_num_{new,next,destroy}() is a logical evolution from bounded
    BPF loops and bpf_loop() helper and is the basis for implementing
    ergonomic BPF loops with no statically known or verified bounds.
    Subsequent patches implement bpf_for() macro, demonstrating how this can
    be wrapped into something that works and feels like a normal for() loop
    in C language.
    Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
    Link: https://lore.kernel.org/r/20230308184121.1165081-5-andrii@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    6018e1f4
helpers.c 65.4 KB