• Andrii Nakryiko's avatar
    libbpf: Add BPF ring buffer support · bf99c936
    Andrii Nakryiko authored
    Declaring and instantiating BPF ring buffer doesn't require any changes to
    libbpf, as it's just another type of maps. So using existing BTF-defined maps
    syntax with __uint(type, BPF_MAP_TYPE_RINGBUF) and __uint(max_elements,
    <size-of-ring-buf>) is all that's necessary to create and use BPF ring buffer.
    
    This patch adds BPF ring buffer consumer to libbpf. It is very similar to
    perf_buffer implementation in terms of API, but also attempts to fix some
    minor problems and inconveniences with existing perf_buffer API.
    
    ring_buffer support both single ring buffer use case (with just using
    ring_buffer__new()), as well as allows to add more ring buffers, each with its
    own callback and context. This allows to efficiently poll and consume
    multiple, potentially completely independent, ring buffers, using single
    epoll instance.
    
    The latter is actually a problem in practice for applications
    that are using multiple sets of perf buffers. They have to create multiple
    instances for struct perf_buffer and poll them independently or in a loop,
    each approach having its own problems (e.g., inability to use a common poll
    timeout). struct ring_buffer eliminates this problem by aggregating many
    independent ring buffer instances under the single "ring buffer manager".
    
    Second, perf_buffer's callback can't return error, so applications that need
    to stop polling due to error in data or data signalling the end, have to use
    extra mechanisms to signal that polling has to stop. ring_buffer's callback
    can return error, which will be passed through back to user code and can be
    acted upon appropariately.
    
    Two APIs allow to consume ring buffer data:
      - ring_buffer__poll(), which will wait for data availability notification
        and will consume data only from reported ring buffer(s); this API allows
        to efficiently use resources by reading data only when it becomes
        available;
      - ring_buffer__consume(), will attempt to read new records regardless of
        data availablity notification sub-system. This API is useful for cases
        when lowest latency is required, in expense of burning CPU resources.
    Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Link: https://lore.kernel.org/bpf/20200529075424.3139988-3-andriin@fb.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    bf99c936
libbpf.h 25.3 KB