On Wed, Apr 27, 2022 at 10:45 PM Yafang Shao <laoar.shao@xxxxxxxxx> wrote: > > On Wed, Apr 27, 2022 at 7:16 AM Andrii Nakryiko > <andrii.nakryiko@xxxxxxxxx> wrote: > > > > On Tue, Apr 26, 2022 at 8:59 AM Yafang Shao <laoar.shao@xxxxxxxxx> wrote: > > > > > > On Mon, Apr 25, 2022 at 9:57 PM Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote: > > > > > > > > On 4/23/22 4:00 PM, Yafang Shao wrote: > > > > > Currently there're helpers for allowing to open/load/attach BPF object > > > > > through BPF object skeleton. Let's also add helpers for pinning through > > > > > BPF object skeleton. It could simplify BPF userspace code which wants to > > > > > pin the progs into bpffs. > > > > > > > > Please elaborate some more on your use case/rationale for the commit message, > > > > do you have orchestration code that will rely on these specifically? > > > > > > > > > > We have a bpf manager on our production environment to maintain the > > > bpf programs, some of which need to be pinned in bpffs, for example > > > tracing bpf programs, perf_event programs and other bpf hooks added by > > > ourselves for performance tuning. These bpf programs don't need a > > > user agent, while they really work like a kernel module, that is why > > > we pin them. For these kinds of bpf programs, the bpf manager can help > > > to simplify the development and deployment. Take the improvement on > > > development for example, the user doesn't need to write userspace > > > code while he focuses on the kernel side only, and then bpf manager > > > will do all the other things. Below is a simple example, > > > Step1, gen the skeleton for the user provided bpf object file, > > > $ bpftool gen skeleton test.bpf.o > simple.skel.h > > > Step2, Compile the bpf object file into a runnable binary > > > #include "simple.skel.h" > > > > > > #define SIMPLE_BPF_PIN(name, path) \ > > > ({ \ > > > struct name##_bpf *obj; \ > > > int err = 0; \ > > > \ > > > obj = name##_bpf__open(); \ > > > if (!obj) { \ > > > err = -errno; \ > > > goto cleanup; \ > > > } \ > > > \ > > > err = name##_bpf__load(obj); \ > > > if (err) \ > > > goto cleanup; \ > > > \ > > > err = name##_bpf__attach(obj); \ > > > if (err) \ > > > goto cleanup; \ > > > \ > > > err = name##_bpf__pin_prog(obj, path); \ > > > if (err) \ > > > goto cleanup; \ > > > \ > > > goto end; \ > > > \ > > > cleanup: \ > > > name##_bpf__destroy(obj); \ > > > end: \ > > > err; \ > > > }) > > > > > > SIMPLE_BPF_PIN(test, "/sys/fs/bpf"); > > > > > > As the userspace code of FD-based bpf objects are all > > > the same, so we can abstract them as above. The pathset means to add > > > the non-exist "name##_bpf__pin_prog(obj, path)" for it. > > > > > > > Your BPF manager is user-space code that you control, right? I'm not > > sure how skeleton is helpful here given your BPF manager is generic > > and doesn't work with any specific skeleton, if I understand the idea. > > But let's assume that you use skeleton to also embed BPF ELF bytes and > > pass them to your manager for "activation". Once you open and load > > bpf_object, your BPF manager can generically iterate all BPF programs > > using bpf_object_for_each_program(), attempt to attach them with > > bpf_program__attach() (see how bpf_object__attach_skeleton is handling > > non-auto-attachable programs) and immediately pin the link (no need to > > even store it, you can destroy it after pinning immediately). All this > > is using generic libbpf APIs and requires no code generation. > > Many thanks for the detailed explanation. Your suggestion can also > work, but with the skeleton we can also generate a binary which can > run independently. (Technically speaking, the binary is the same as > './bpf_install target.bpf.o'). > Forgot to mention that with skeleton we can also modify the global data defined in bpf object file, that may need to be abstracted as a new common helper. The bpf_object__* functions can't do it, right ? > > But keep > > in mind that not all struct bpf_link in libbpf are pinnable (not all > > links have FD-based BPF link in kernel associated with them), so > > you'll have to deal with that somehow (and what you didn't do in this > > patch for libbpf implementation). > > > > Right, I have found it. If I understand it correctly, only the link > types defined in enum bpf_link_type (which is in > include/uapi/linux/bpf.h) are pinnable, right? > > BTW, is it possible to support pinning all struct bpf_link in libbpf ? > > > -- > Regards > Yafang -- Regards Yafang