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. 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). > > > Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> > > > --- > > > tools/lib/bpf/libbpf.c | 59 ++++++++++++++++++++++++++++++++++++++++ > > > tools/lib/bpf/libbpf.h | 4 +++ > > > tools/lib/bpf/libbpf.map | 2 ++ > > > 3 files changed, 65 insertions(+) > > > [...]