• Andrii Nakryiko's avatar
    libbpf: allow specifying map definitions using BTF · abd29c93
    Andrii Nakryiko authored
    This patch adds support for a new way to define BPF maps. It relies on
    BTF to describe mandatory and optional attributes of a map, as well as
    captures type information of key and value naturally. This eliminates
    the need for BPF_ANNOTATE_KV_PAIR hack and ensures key/value sizes are
    always in sync with the key/value type.
    
    Relying on BTF, this approach allows for both forward and backward
    compatibility w.r.t. extending supported map definition features. By
    default, any unrecognized attributes are treated as an error, but it's
    possible relax this using MAPS_RELAX_COMPAT flag. New attributes, added
    in the future will need to be optional.
    
    The outline of the new map definition (short, BTF-defined maps) is as follows:
    1. All the maps should be defined in .maps ELF section. It's possible to
       have both "legacy" map definitions in `maps` sections and BTF-defined
       maps in .maps sections. Everything will still work transparently.
    2. The map declaration and initialization is done through
       a global/static variable of a struct type with few mandatory and
       extra optional fields:
       - type field is mandatory and specified type of BPF map;
       - key/value fields are mandatory and capture key/value type/size information;
       - max_entries attribute is optional; if max_entries is not specified or
         initialized, it has to be provided in runtime through libbpf API
         before loading bpf_object;
       - map_flags is optional and if not defined, will be assumed to be 0.
    3. Key/value fields should be **a pointer** to a type describing
       key/value. The pointee type is assumed (and will be recorded as such
       and used for size determination) to be a type describing key/value of
       the map. This is done to save excessive amounts of space allocated in
       corresponding ELF sections for key/value of big size.
    4. As some maps disallow having BTF type ID associated with key/value,
       it's possible to specify key/value size explicitly without
       associating BTF type ID with it. Use key_size and value_size fields
       to do that (see example below).
    
    Here's an example of simple ARRAY map defintion:
    
    struct my_value { int x, y, z; };
    
    struct {
    	int type;
    	int max_entries;
    	int *key;
    	struct my_value *value;
    } btf_map SEC(".maps") = {
    	.type = BPF_MAP_TYPE_ARRAY,
    	.max_entries = 16,
    };
    
    This will define BPF ARRAY map 'btf_map' with 16 elements. The key will
    be of type int and thus key size will be 4 bytes. The value is struct
    my_value of size 12 bytes. This map can be used from C code exactly the
    same as with existing maps defined through struct bpf_map_def.
    
    Here's an example of STACKMAP definition (which currently disallows BTF type
    IDs for key/value):
    
    struct {
    	__u32 type;
    	__u32 max_entries;
    	__u32 map_flags;
    	__u32 key_size;
    	__u32 value_size;
    } stackmap SEC(".maps") = {
    	.type = BPF_MAP_TYPE_STACK_TRACE,
    	.max_entries = 128,
    	.map_flags = BPF_F_STACK_BUILD_ID,
    	.key_size = sizeof(__u32),
    	.value_size = PERF_MAX_STACK_DEPTH * sizeof(struct bpf_stack_build_id),
    };
    
    This approach is naturally extended to support map-in-map, by making a value
    field to be another struct that describes inner map. This feature is not
    implemented yet. It's also possible to incrementally add features like pinning
    with full backwards and forward compatibility. Support for static
    initialization of BPF_MAP_TYPE_PROG_ARRAY using pointers to BPF programs
    is also on the roadmap.
    Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
    Acked-by: default avatarSong Liu <songliubraving@fb.com>
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    abd29c93
libbpf.c 102 KB