bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Daniel Borkmann <daniel@iogearbox.net>
Cc: Stanislav Fomichev <sdf@fomichev.me>,
	Alexei Starovoitov <ast@fb.com>, Andrii Nakryiko <andriin@fb.com>,
	Networking <netdev@vger.kernel.org>, bpf <bpf@vger.kernel.org>,
	Kernel Team <Kernel-team@fb.com>, Yonghong Song <yhs@fb.com>
Subject: Re: [RFC PATCH bpf-next 6/8] libbpf: allow specifying map definitions using BTF
Date: Thu, 6 Jun 2019 16:02:56 -0700	[thread overview]
Message-ID: <CAEf4BzYr_3heu2gb8U-rmbgMPu54ojcdjMZu7M_VaqOyCNGR5g@mail.gmail.com> (raw)
In-Reply-To: <3ff873a8-a1a6-133b-fa20-ad8bc1d347ed@iogearbox.net>

On Thu, Jun 6, 2019 at 2:09 PM Daniel Borkmann <daniel@iogearbox.net> wrote:
>
> On 06/04/2019 07:31 PM, Andrii Nakryiko wrote:
> > On Tue, Jun 4, 2019 at 6:45 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> >> On 06/03, Stanislav Fomichev wrote:
> >>>> BTF is mandatory for _any_ new feature.
> >>> If something is easy to support without asking everyone to upgrade to
> >>> a bleeding edge llvm, why not do it?
> >>> So much for backwards compatibility and flexibility.
> >>>
> >>>> It's for introspection and debuggability in the first place.
> >>>> Good debugging is not optional.
> >>> Once llvm 8+ is everywhere, sure, but we are not there yet (I'm talking
> >>> about upstream LTS distros like ubuntu/redhat).
> >> But putting this aside, one thing that I didn't see addressed in the
> >> cover letter is: what is the main motivation for the series?
> >> Is it to support iproute2 map definitions (so cilium can switch to libbpf)?
> >
> > In general, the motivation is to arrive at a way to support
> > declaratively defining maps in such a way, that:
> > - captures type information (for debuggability/introspection) in
> > coherent and hard-to-screw-up way;
> > - allows to support missing useful features w/ good syntax (e.g.,
> > natural map-in-map case vs current completely manual non-declarative
> > way for libbpf);
> > - ultimately allow iproute2 to use libbpf as unified loader (and thus
> > the need to support its existing features, like
> > BPF_MAP_TYPE_PROG_ARRAY initialization, pinning, map-in-map);
>
> Thanks for working on this & sorry for jumping in late! Generally, I like
> the approach of using BTF to make sense out of the individual members and
> to have extensibility, so overall I think it's a step in the right direction.
> Going back to the example where others complained that the k/v NULL
> initialization feels too much magic from a C pov:
>
> struct {
>         int type;
>         int max_entries;
>         int *key;
>         struct my_value *value;
> } my_map SEC(".maps") = {
>         .type = BPF_MAP_TYPE_ARRAY,
>         .max_entries = 16,
> };
>
> Given LLVM is in charge of emitting BTF plus given gcc/clang seem /both/
> to support *target* specific attributes [0], how about something along these
> lines where the type specific info is annotated as a variable BPF target
> attribute, like:
>
> struct {
>         int type;
>         int max_entries;
> } my_map __attribute__((map(int,struct my_value))) = {
>         .type = BPF_MAP_TYPE_ARRAY,
>         .max_entries = 16,
> };
>
> Of course this would need BPF backend support, but at least that approach
> would be more C like. Thus this would define types where we can automatically

I guess it's technically possible (not a compiler guru, but I don't
see why it wouldn't be possible). But it will require at least two
things:
1. Compiler support, obviously, as you mentioned.
2. BTF specification on how to describe attributes and how to describe
what entities (variable in this case) it is attached to.

2. is not straightforward, as attributes in general is a collection of
values of vastly different types: some values could be integers, some
strings, some, like in this case, would be a reference another BTF
type. It seems like a powerful and potentially useful addition to BTF,
of course, but it's very unclear at this point what's the best way to
represent them.

I'm not relating with "non idiomatic C" motive, though, so all that
seems like unnecessarily heavy-weight way to get something that we can
get today w/o compiler support in a clean, succinct and familiar C
syntax, that to me doesn't look like magic at all.

And if anything, attribute feels just as much magic to me. But here's
very similarly looking macro-trick:

#define MAP_KEY_VALUE_META(KEY, VALUE) KEY *key; VALUE *value;

struct {
       MAP_KEY_VALUE_META(int, struct my_value)
       int type;
       int max_entries;
} my_map SEC(".maps") = {
       .type = BPF_MAP_TYPE_ARRAY,
       .max_entries = 16,
};

Or even:

#define MAP_DEF(KEY, VALUE) struct { KEY *key; VALUE *value; int type;
int max_entries; }

MAP_DEF(int, struct my_value) my_map SEC(".maps") = {
       .type = BPF_MAP_TYPE_ARRAY,
       .max_entries = 16,
};

> derive key/val sizes etc. The SEC() could be dropped as well as map attribute

I think we should at least have an ability to override ELF section
name, just in case we add support to have maps in multiple sections
(e.g., shared library with its own set of maps, or whatever).

> would imply it for LLVM to do the right thing underneath. The normal/actual members
> from the struct has a base set of well-known names that are minimally required
> but there could be custom stuff as well where libbpf would query some user
> defined callback that can handle these. Anyway, main point, what do you think

So regarding callback. I find it hard to imagine how that could be
implemented interface-wise. As each field can have very different
value (it could be another embedded custom struct, not just integer;
or it could be char array of fixed size, etc), which is determined by
BTF, I don't know how I would expose that to custom callback in C type
system.

If I absolutely had to do it, though, how about this approach. We
either add BTF type id of a defining struct to bpf_map_def or add
bpf_map__btf_def() API, which returns it, so:

struct bpf_map *map = bpf_object__find_map_by_name(obj, "my_fancy_map");
struct btf *btf = bpf_object__btf(obj);
__u32 def_id = bpf_map__btf_map_def_type_id(map);
const void *def_data = bpf_map__btf_map_def_data(map);
struct btf_type *t = btf__type_by_id(btf, def_id);

Then application can do whatever parsing it wants on BTF map
definition and extract values in whatever manner suits it. This way
it's just a bunch of very straightforward APIs, instead of callbacks
w/ unclear interface (i.e., you'd still need to expose field_name,
field's type_id, raw pointer to data).

Does this make sense?

But having said that, what are the use cases you have in mind that
require application to put custom stuff into a standardized map
definition?

> about the __attribute__ approach instead? I think this feels cleaner to me at
> least iff feasible.
>
> Thanks,
> Daniel
>
>   [0] https://clang.llvm.org/docs/AttributeReference.html
>       https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
>
> > The only missing feature that can be supported reasonably with
> > bpf_map_def is pinning (as it's just another int field), but all the
> > other use cases requires awkward approach of matching arbitrary IDs,
> > which feels like a bad way forward.
> >
> >> If that's the case, maybe explicitly focus on that? Once we have
> >> proof-of-concept working for iproute2 mode, we can extend it to everything.
>

  reply	other threads:[~2019-06-06 23:03 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-31 20:21 [RFC PATCH bpf-next 0/8] BTF-defined BPF map definitions Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 1/8] libbpf: add common min/max macro to libbpf_internal.h Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 2/8] libbpf: extract BTF loading and simplify ELF parsing logic Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 3/8] libbpf: refactor map initialization Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 4/8] libbpf: identify maps by section index in addition to offset Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 5/8] libbpf: split initialization and loading of BTF Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 6/8] libbpf: allow specifying map definitions using BTF Andrii Nakryiko
2019-05-31 21:28   ` Stanislav Fomichev
2019-05-31 22:58     ` Andrii Nakryiko
2019-06-03  0:33       ` Jakub Kicinski
2019-06-03 21:54         ` Andrii Nakryiko
2019-06-03 23:34           ` Jakub Kicinski
2019-06-03 16:32       ` Stanislav Fomichev
2019-06-03 22:03         ` Andrii Nakryiko
2019-06-04  1:02           ` Stanislav Fomichev
2019-06-04  1:07             ` Alexei Starovoitov
2019-06-04  4:29               ` Stanislav Fomichev
2019-06-04 13:45                 ` Stanislav Fomichev
2019-06-04 17:31                   ` Andrii Nakryiko
2019-06-04 21:07                     ` Stanislav Fomichev
2019-06-04 21:22                       ` Andrii Nakryiko
2019-06-06 21:09                     ` Daniel Borkmann
2019-06-06 23:02                       ` Andrii Nakryiko [this message]
2019-06-06 23:27                         ` Alexei Starovoitov
2019-06-07  0:10                           ` Jakub Kicinski
2019-06-07  0:27                             ` Alexei Starovoitov
2019-06-07  1:02                               ` Jakub Kicinski
2019-06-10  1:17                                 ` explicit maps. Was: " Alexei Starovoitov
2019-06-10 21:15                                   ` Jakub Kicinski
2019-06-10 23:48                                   ` Andrii Nakryiko
2019-06-03 22:34   ` Andrii Nakryiko
2019-06-06 16:42   ` Lorenz Bauer
2019-06-06 22:34     ` Andrii Nakryiko
2019-06-17  9:07       ` Lorenz Bauer
2019-06-17 20:59         ` Andrii Nakryiko
2019-06-20  9:27           ` Lorenz Bauer
2019-06-21  4:05             ` Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 7/8] selftests/bpf: add test for BTF-defined maps Andrii Nakryiko
2019-05-31 20:21 ` [RFC PATCH bpf-next 8/8] selftests/bpf: switch tests to BTF-defined map definitions Andrii Nakryiko
2019-06-11  4:34 [RFC PATCH bpf-next 0/8] BTF-defined BPF " Andrii Nakryiko
2019-06-11  4:35 ` [RFC PATCH bpf-next 6/8] libbpf: allow specifying map definitions using BTF Andrii Nakryiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAEf4BzYr_3heu2gb8U-rmbgMPu54ojcdjMZu7M_VaqOyCNGR5g@mail.gmail.com \
    --to=andrii.nakryiko@gmail.com \
    --cc=Kernel-team@fb.com \
    --cc=andriin@fb.com \
    --cc=ast@fb.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=netdev@vger.kernel.org \
    --cc=sdf@fomichev.me \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).