On Fri, 31 May 2019 15:58:41 -0700, Andrii Nakryiko wrote: > On Fri, May 31, 2019 at 2:28 PM Stanislav Fomichev <sdf@xxxxxxxxxxx> wrote: > > On 05/31, Andrii Nakryiko wrote: > > > 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. > > My 2c: this is too magical and relies on me knowing the expected fields. > > (also, the compiler won't be able to help with the misspellings). I have mixed feelings, too. Especially the key and value fields are very non-idiomatic for C :( They never hold any value or data, while the other fields do. That feels so awkward. I'm no compiler expert, but even something like: struct map_def { void *key_type_ref; } mamap = { .key_type_ref = &(struct key_xyz){}, }; Would feel like less of a hack to me, and then map_def doesn't have to be different for every map. But yea, IDK if it's easy to (a) resolve the type of what key_type points to, or (b) how to do this for scalar types. > I don't think it's really worse than current bpf_map_def approach. In > typical scenario, there are only two fields you need to remember: type > and max_entries (notice, they are called exactly the same as in > bpf_map_def, so this knowledge is transferrable). Then you'll have > key/value, using which you are describing both type (using field's > type) and size (calculated from the type). > > I can relate a bit to that with bpf_map_def you can find definition > and see all possible fields, but one can also find a lot of examples > for new map definitions as well. > > One big advantage of this scheme, though, is that you get that type > association automagically without using BPF_ANNOTATE_KV_PAIR hack, > with no chance of having a mismatch, etc. This is less duplication (no > need to do sizeof(struct my_struct) and struct my_struct as an arg to > that macro) and there is no need to go and ping people to add those > annotations to improve introspection of BPF maps. > > > Relying on BTF, this approach allows for both forward and backward > > > compatibility w.r.t. extending supported map definition features. Old > > > libbpf implementation will ignore fields it doesn't recognize, while new > > > implementations will parse and recognize new optional attributes. > > I also don't know how to feel about old libbpf ignoring some attributes. > > In the kernel we require that the unknown fields are zeroed. > > We probably need to do something like that here? What do you think > > would be a good example of an optional attribute? > > Ignoring is required for forward-compatibility, where old libbpf will > be used to load newer user BPF programs. We can decided not to do it, > in that case it's just a question of erroring out on first unknown > field. This RFC was posted exactly to discuss all these issues with > more general community, as there is no single true way to do this. > > As for examples of when it can be used. It's any feature that can be > considered optional or a hint, so if old libbpf doesn't do that, it's > still not the end of the world (and we can live with that, or can > correct using direct libbpf API calls). On forward compatibility my 0.02c would be - if we want to go there and silently ignore fields it'd be good to have some form of "hard required" bit. For TLVs ABIs it can be a "you have to understand this one" bit, for libbpf perhaps we could add a "min libbpf version required" section? That kind of ties us ELF formats to libbpf specifics (the libbpf version presumably would imply support for features), but I think we want to go there, anyway.