On Thu, Jun 27, 2019 at 2:16 PM Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote: > > On 06/27/2019 12:15 AM, Andrii Nakryiko wrote: > > On Wed, Jun 26, 2019 at 7:25 AM Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote: > [...] > >> What this boils down to is that this should get a proper abstraction, e.g. as > >> in struct libbpf_event which holds the event object. There should be helper > >> functions like libbpf_event_create_{kprobe,uprobe,tracepoint,raw_tracepoint} returning > >> such an struct libbpf_event object on success, and a single libbpf_event_destroy() > >> that does the event specific teardown. bpf_program__attach_event() can then take > >> care of only attaching the program to it. Having an object for this is also more > >> extensible than just a fd number. Nice thing is that this can also be completely > >> internal to libbpf.c as with struct bpf_program and other abstractions where we > >> don't expose the internals in the public header. > > > > Yeah, I totally agree, I think this is a great idea! I don't > > particularly like "event" name, that seems very overloaded term. Do > > you mind if I call this "bpf_hook" instead of "libbpf_event"? I've > > always thought about these different points in the system to which one > > can attach BPF program as hooks exposed from kernel :) > > > > Would it also make sense to do attaching to non-tracing hooks using > > the same mechanism (e.g., all the per-cgroup stuff, sysctl, etc)? Not > > sure how people do that today, will check to see how it's done, but I > > think nothing should conceptually prevent doing that using the same > > abstract bpf_hook way, right? > > I think if we abstract it this way, then absolutely. If I grok the naming conventions > from the README right, then this would be under 'bpf_hook__' prefix. :) Yeah, so this is what I had, API-wise: struct bpf_hook; LIBBPF_API struct bpf_hook *bpf_hook__new_perf_event(int pfd); LIBBPF_API struct bpf_hook *bpf_hook__new_kprobe(bool retprobe, const char *func_name); LIBBPF_API struct bpf_hook *bpf_hook__new_uprobe(bool retprobe, pid_t pid, const char *binary_path, size_t func_offset); LIBBPF_API struct bpf_hook *bpf_hook__new_tracepoint(const char *tp_category, const char *tp_name); LIBBPF_API struct bpf_hook *bpf_hook__new_raw_tracepoint(const char *tp_name); LIBBPF_API int bpf_hook__attach_program(struct bpf_hook *hook, struct bpf_program *prog); LIBBPF_API int bpf_hook__free(struct bpf_hook *hook); You'd use bpf_hook_new_xxx to create struct bpf_hook, which then get's attached using generic bpf_hook__attach_program and detached/freed with generic bpf_hook__free. But once I converted selftests, I realized that this generic bpf_hook__attach_program is kind of unnecessary and is just a boiler-plate extra function that everyone has to call. So now I'm leaning towards a hybrid approach: - bpf_program__attach_xxx will create some specific struct bpf_hook *and* attach bpf_program to it; - bpf_hook__free(struct bpf_hook *) would still be used to detach/free resources, abstracting away specifics of detaching. There are few benefits to this, I think: 1. Less error checking and clean up from caller: attach either succeeds (and you'll have to eventually do bpf_hook__free) or not, and then nothing needs to be cleaned up. With separate create/attach, if create succeeds, but attach fails, you'll have to do extra bpf_hook__free call. This bundling of create/attach does prevent theoretical use case of having hook creation in one place and then pass this generically into another place for attachment, but it seems like a bit far-fetched corner use case, which can be implemented at application level, if necessary. 2. bpf_program__attach has more context for helpful log messages, if something goes wrong. E.g., bpf_program__attach_tracepoint(tp_category, tp_name), once it created perf event FD for tracepoint, can discard tp_category and tp_name and use only FD for attachment. But if attachment fails, we don't really know which tracepoint failed to attach. To facilitate that, you'd need to allocate/copy tp_category/tp_name (just in case for logging), which is PITA. With bundled attach, you can log nice error with context right there with no overhead. This still allows to do cgroup/flow/sysctl/etc attachment in similar uniform way (but that's for another set of patches). Also, I renamed bpf_hook to bpf_link as it seems to convey connection between connection point (hook) and bpf_program better. Alternative might be bpf_assoc, I'll mention that as well in cover letter. Anyways, I think it's better usability without losing anything (realistically) in terms of flexibility for users. I'll post v2 later today. > > Thanks, > Daniel