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

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

 



On Mon, Dec 12, 2022 at 12:12 PM Andrii Nakryiko
<andrii.nakryiko@xxxxxxxxx> wrote:
>
> 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.

Oh interesting, I didn't realize some architectures do not support kfuncs.

Out of curiosity, can you elaborate on "no clean way to move from
unstable kfunc to a stable helper"? If for example we needed to move
something from kfunc -> helper, could we not just remove the code
where we added it as a kfunc (eg defining a BTF_ID for it) and add it
as a helper instead?

>
> 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.

I'm not that familiar with the semantics of bpf kfuncs, so to clarify:
from a user API perspective, is there any difference in calling the
function from the bpf program as a helper vs. kfunc?

>
> >
> > 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.

I agree with all of your points. I know Alexei is on PTO these next
two weeks, so I will in the meantime table this and work on the dynptr
memory allocation patchset and a dynptr documentation write-up.

Thanks for the discussion!



[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