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