Re: [PATCH v2 bpf-next 0/6] Dynptr convenience helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 8, 2022 at 5:30 PM Alexei Starovoitov
<alexei.starovoitov@xxxxxxxxx> wrote:
>
> On Thu, Dec 8, 2022 at 4:42 PM Andrii Nakryiko
> <andrii.nakryiko@xxxxxxxxx> wrote:
> >
> > On Wed, Dec 7, 2022 at 5:54 PM Alexei Starovoitov
> > <alexei.starovoitov@xxxxxxxxx> wrote:
> > >
> > > On Wed, Dec 07, 2022 at 12:55:31PM -0800, Joanne Koong wrote:
> > > > This patchset is the 3rd in the dynptr series. The 1st can be found here [0]
> > > > and the 2nd can be found here [1].
> > > >
> > > > In this patchset, the following convenience helpers are added for interacting
> > > > with bpf dynamic pointers:
> > > >
> > > >     * bpf_dynptr_data_rdonly
> > > >     * bpf_dynptr_trim
> > > >     * bpf_dynptr_advance
> > > >     * bpf_dynptr_is_null
> > > >     * bpf_dynptr_is_rdonly
> > > >     * bpf_dynptr_get_size
> > > >     * bpf_dynptr_get_offset
> > > >     * bpf_dynptr_clone
> > > >     * bpf_dynptr_iterator
> > >
> > > This is great, but it really stretches uapi limits.
> >
> > Stretches in what sense? They are simple and straightforward getters
> > and trim/advance/clone are fundamental modifiers to be able to work
> > with a subset of dynptr's overall memory area.
> >
> > > Please convert the above and those in [1] to kfuncs.
> > > I know that there can be an argument made for consistency with existing dynptr uapi
> >
> > yeah, given we have bpf_dynptr_{read,write} and bpf_dynptr_data() as
> > BPF helpers, it makes sense to have such basic things like is_null and
> > trim/advance/clone as BPF helpers as well. Both for consistency and
> > because there is nothing unstable about them. We are not going to
> > remove dynptr as a concept, it's pretty well defined.
> >
> > Out of the above list perhaps only move bpf_dynptr_iterator() might be
> > a candidate for kfunc. Though, personally, it makes sense to me to
> > keep it as BPF helper without GPL restriction as well, given it is
> > meant for networking applications in the first place, and you don't
> > need to be GPL-compatible to write useful networking BPF program, from
> > what I understand. But all the other ones is something you'd need to
> > make actual use of dynptr concept in real-world BPF programs.
> >
> > Can we please have those as BPF helpers, and we can decide to move
> > slightly fancier bpf_dynptr_iterator() (and future dynptr-related
> > extras) into kfunc?
>
> Sorry, uapi concerns are more important here.

What about the overall user experience and adoption?

There is no clean way to ever move from unstable kfunc to a stable helper.

BPF helpers also have the advantage of working on all architectures,
whether that architecture supports kfuncs or not, whether it supports
JIT or not.

BPF helpers are also nicely self-discoverable and documented in
include/uapi/linux/bpf.h, in one place where other BPF helpers are.
This is a big deal, especially for non-expert BPF users (a vast
majority of BPF users).

> non-gpl and consistency don't even come close.
> We've been doing everything new as kfuncs and dynptr is not special.

I think dynptr is quite special. It's a very generic and fundamental
concept, part of core BPF experience. It's a more dynamic counterpart
to an inflexible statically sized `void * + size` pair of arguments
sent to helpers for input or output memory regions. Dynptr has no
inherent dependencies on BTF, kfuncs, trampolines, JIT, nothing.

By requiring kfunc-based helpers we are significantly raising the
obstacles towards adopting dynptr across a wide range of BPF
applications.

And the only advantage in return is that we get a hypothetical chance
to change something in the future. But let's see if that will ever be
necessary for the helpers Joanne is adding:

1. Generic accessors to check validity of *any* dynptr, and it's
inherent properties like offset, available size, read-only property
(just as useful somethings as bpf_ringbuf_query() is for ringbufs,
both for debugging and for various heuristics in production).

bpf_dynptr_is_null(struct bpf_dynptr *ptr)
long bpf_dynptr_get_size(struct bpf_dynptr *ptr)
long bpf_dynptr_get_offset(struct bpf_dynptr *ptr)
bpf_dynptr_is_rdonly(struct bpf_dynptr *ptr)

There is nothing to add or remove here. No flags, no change in semantics.

2. Manipulators to copy existing dynptr's view and narrow it down to a
subset (e.g., for when you have a large memory blog, but need to
calculate hashes over smaller subset, without destroying original
dynptr, because it will be used later for some other access). We can
debate whether clone should get offset or not, but it doesn't change
much (except usability in common cases). Again, nothing to add or
remove otherwise, and pretty fundamental for real use of full power of
dynptr.

long bpf_dynptr_clone(struct bpf_dynptr *ptr, struct bpf_dynptr
*clone, u32 offset)
long bpf_dynptr_trim(struct bpf_dynptr *ptr, u32 len)
long bpf_dynptr_advance(struct bpf_dynptr *ptr, u32 len)

3. This one is the only one I feel less strongly about, but mostly
because I can implement the same (even though less ergonomically, of
course) with bpf_loop() and bpf_dynptr_{clone,advance}.

long bpf_dynptr_iterator(struct bpf_dynptr *ptr, void *callback_fn,
void *callback_ctx, u64 flags)


All of the above don't add or change any semantics to dynptr as a
concept. There is nothing that we'd need to change.


>
> > > helpers, but we got burned on them once and scrambled to add 'flags' argument.
> > > kfuncs are unstable and can be adjusted/removed at any time later.

It's unfair to block these helpers just because we recided to add
flags to one of the previous ones (before the final release). And even
if we didn't managed to do it in time, the worst things would probably
be another variant of BPF helper. Definitely something to avoid, but
not end of the world. But as I pointed out above, this set of helpers
won't be change, as they just complete already established dynptr
ecosystem of helpers.

> >
> > I don't see why we would remove any of the above list ever? They are
> > generic and fundamental to dynptr as a concept, they can't restrict
> > what dynptr can do in the future.
>
> It's not about removing them, but about changing them.
>
> Just for example the whole discussion of whether frags should
> be handled transparently and how write is handled didn't inspire
> confidence that there is a strong consensus on semantics
> of these new dynptr accessors.

So let's start with acknowledging that skb and xdp buffer abstractions
as logically contiguous memory area are inherently complex and
non-perfect due to the way that kernel handles them for performance
and flexibility reasons.

Let's also note that verifier knows specific flavor of dynptr and thus
can enforce additional restrictions based on specifically SKB/XDP
flavor vs LOCAL/RINGBUF. So just because there is no perfect way to
handle all the SKB/XDP physical non-contiguity, doesn't mean that the
dynptr concept itself is flawed or not well thought out. It's just
that for SKB/XDP there is no perfect solution. Dynptr doesn't change
anything here, rather it actually simplifies a bunch of stuff,
especially for common scenarios.

I'd argue that for wider SKB/XDP dynptr adoption in the networking
world, those dynptr constructor helpers should be helpers and not
kfuncs as well. But I'd wish someone with more networking tie-ins
would argue this instead of me.

>
> Scrambling to add flags to dynptr helpers was another red flag.
>
> All signs are pointing out that we're not ready do fix dynptr api.

I disagree, it's an overly harsh generalization.

> It will evolve and has to evolve without uapi pain.
>
> kfuncs only. For everything. Please.

This is yet another generalized blanket statement I disagree with.
Over the years I've got an impression that the BPF subsystem is
generally a  proud proponent of pragmatic, flexible, and common sense
engineering approaches, so this hard-and-fast rule with no room for
nuance sounds weird.

There are things that belong in fundamental and core BPF concepts, and
it makes sense to keep them as stable abstractions and helpers. And
there are various things (like interfacing into kernel mechanics, its
types and systems) which totally make sense to keep unstable.



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux