[RFC bpf-next 0/3] libbpf: Add support for aliased BPF programs

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

 



TL;DR

This adds libbpf support for creating multiple BPF programs having the
same instructions using symbol aliases.

Context
=======

bpftrace has so-called "wildcarded" probes which allow to attach the
same program to multple different attach points. For k(u)probes, this is
easy to do as we can leverage k(u)probe_multi, however, other program
types (fentry/fexit, tracepoints) don't have such features.

Currently, what bpftrace does is that it creates a copy of the program
for each attach point. This naturally results in a lot of redundant code
in the produced BPF object.

Proposal
========

One way to address this problem would be to use *symbol aliases*. In
short, they allow to have multiple symbol table entries for the same
address. In bpftrace, we would create them using llvm::GlobalAlias. In
C, it can be achieved using compiler __attribute__((alias(...))):

    int BPF_PROG(prog)
    {
        [...]
    }
    int prog_alias() __attribute__((alias("prog")));

When calling bpf_object__open, libbpf is currently able to discover all
the programs and internally does a separate copy of the instructions for
each aliased program. What libbpf cannot do, is perform relocations b/c
it assumes that each instruction belongs to a single program only. The
second patch of this series changes relocation collection such that it
records relocations for each aliased program. With that, bpftrace can
emit just one copy of the full program and an alias for each target
attach point.

For example, considering the following bpftrace script collecting the
number of hits of each VFS function using fentry over a one second
period:

    $ bpftrace -e 'kfunc:vfs_* { @[func] = count() } i:s:1 { exit() }'
    [...]

this change will allow to reduce the size of the in-memory BPF object
that bpftrace generates from 60K to 9K.

For reference, the bpftrace PoC is in [1].

The advantage of this change is that for BPF objects without aliases, it
doesn't introduce any overhead.

Limitations
===========

Unfortunately, the second patch of the series is only sufficient for
bpftrace approach. When using bpftool to generate BPF objects, such as
is done in selftests, it turns out that libbpf linker cannot handle
aliased programs. The reason is that Clang doesn't emit BTF for the
aliased symbols which the linker doesn't expect. This is resolved by the
first patch of the series which improves searching BTF entries for
symbols such that an entry for a different symbol located at the same
address can be used. This, however, requires an additional lookup in the
symbol table during BTF id search in find_glob_sym_btf, increasing the
complexity of the method.

To quantify the impact of this, I ran some simple benchmarks.
The overhead naturally grows with the number of programs in the object.
I took one BPF object from selftests (dynptr_fail.bpf.o) with many (72)
BPF programs inside and extracted some stats from calling

    $ bpftool gen object dynptr_fail.bpf.linked.o dynptr_fail.bpf.o

Here are the stats:

    master:
        0.015922 +- 0.000251 seconds time elapsed  ( +-  1.58% )
        10 calls of find_sym_by_name

    patchset:
        0.020365 +- 0.000261 seconds time elapsed  ( +-  1.28% )
        8382 calls of find_sym_by_name

The overhead is there, however, the linker is still fast for quite a
large number of BPF programs so it would probably cause a noticeable
slowdown only for BPF objects containing thousands of programs.

Another limitation is that aliases cannot be used in combination with
section name-based auto-attachment as the program only exists in a
single section.

Alternative solutions
=====================

As an alternative, bpftrace could use a similar approach to what
retsnoop [2] does: load the program just once and clone it for each
match using manual call of bpf_prog_load. This is certainly feasible but
requires each tool which wants to do this to reimplement the logic.

This patch series is an alternative to retsnoop's approach which I think
is easier to use from tools' perspective so I'm posting this RFC to see
what people think about it.

Viktor

[1] https://github.com/viktormalik/bpftrace/tree/alias-expansion
[2] https://github.com/anakryiko/retsnoop/blob/master/src/mass_attacher.c#L1096

Viktor Malik (3):
  libbpf: Support aliased symbols in linker
  libbpf: Handle relocations in aliased symbols
  selftests/bpf: Add tests for aliased programs

 tools/lib/bpf/libbpf.c                        | 143 ++++++++++--------
 tools/lib/bpf/linker.c                        |  68 +++++----
 .../selftests/bpf/prog_tests/fentry_alias.c   |  41 +++++
 .../selftests/bpf/progs/fentry_alias.c        |  83 ++++++++++
 4 files changed, 246 insertions(+), 89 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/fentry_alias.c
 create mode 100644 tools/testing/selftests/bpf/progs/fentry_alias.c

-- 
2.46.0





[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