237 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3===============4libbpf Overview5===============6 7libbpf is a C-based library containing a BPF loader that takes compiled BPF8object files and prepares and loads them into the Linux kernel. libbpf takes the9heavy lifting of loading, verifying, and attaching BPF programs to various10kernel hooks, allowing BPF application developers to focus only on BPF program11correctness and performance.12 13The following are the high-level features supported by libbpf:14 15* Provides high-level and low-level APIs for user space programs to interact16 with BPF programs. The low-level APIs wrap all the bpf system call17 functionality, which is useful when users need more fine-grained control18 over the interactions between user space and BPF programs.19* Provides overall support for the BPF object skeleton generated by bpftool.20 The skeleton file simplifies the process for the user space programs to access21 global variables and work with BPF programs.22* Provides BPF-side APIS, including BPF helper definitions, BPF maps support,23 and tracing helpers, allowing developers to simplify BPF code writing.24* Supports BPF CO-RE mechanism, enabling BPF developers to write portable25 BPF programs that can be compiled once and run across different kernel26 versions.27 28This document will delve into the above concepts in detail, providing a deeper29understanding of the capabilities and advantages of libbpf and how it can help30you develop BPF applications efficiently.31 32BPF App Lifecycle and libbpf APIs33==================================34 35A BPF application consists of one or more BPF programs (either cooperating or36completely independent), BPF maps, and global variables. The global37variables are shared between all BPF programs, which allows them to cooperate on38a common set of data. libbpf provides APIs that user space programs can use to39manipulate the BPF programs by triggering different phases of a BPF application40lifecycle.41 42The following section provides a brief overview of each phase in the BPF life43cycle:44 45* **Open phase**: In this phase, libbpf parses the BPF46 object file and discovers BPF maps, BPF programs, and global variables. After47 a BPF app is opened, user space apps can make additional adjustments48 (setting BPF program types, if necessary; pre-setting initial values for49 global variables, etc.) before all the entities are created and loaded.50 51* **Load phase**: In the load phase, libbpf creates BPF52 maps, resolves various relocations, and verifies and loads BPF programs into53 the kernel. At this point, libbpf validates all the parts of a BPF application54 and loads the BPF program into the kernel, but no BPF program has yet been55 executed. After the load phase, it’s possible to set up the initial BPF map56 state without racing with the BPF program code execution.57 58* **Attachment phase**: In this phase, libbpf59 attaches BPF programs to various BPF hook points (e.g., tracepoints, kprobes,60 cgroup hooks, network packet processing pipeline, etc.). During this61 phase, BPF programs perform useful work such as processing62 packets, or updating BPF maps and global variables that can be read from user63 space.64 65* **Tear down phase**: In the tear down phase,66 libbpf detaches BPF programs and unloads them from the kernel. BPF maps are67 destroyed, and all the resources used by the BPF app are freed.68 69BPF Object Skeleton File70========================71 72BPF skeleton is an alternative interface to libbpf APIs for working with BPF73objects. Skeleton code abstract away generic libbpf APIs to significantly74simplify code for manipulating BPF programs from user space. Skeleton code75includes a bytecode representation of the BPF object file, simplifying the76process of distributing your BPF code. With BPF bytecode embedded, there are no77extra files to deploy along with your application binary.78 79You can generate the skeleton header file ``(.skel.h)`` for a specific object80file by passing the BPF object to the bpftool. The generated BPF skeleton81provides the following custom functions that correspond to the BPF lifecycle,82each of them prefixed with the specific object name:83 84* ``<name>__open()`` – creates and opens BPF application (``<name>`` stands for85 the specific bpf object name)86* ``<name>__load()`` – instantiates, loads,and verifies BPF application parts87* ``<name>__attach()`` – attaches all auto-attachable BPF programs (it’s88 optional, you can have more control by using libbpf APIs directly)89* ``<name>__destroy()`` – detaches all BPF programs and90 frees up all used resources91 92Using the skeleton code is the recommended way to work with bpf programs. Keep93in mind, BPF skeleton provides access to the underlying BPF object, so whatever94was possible to do with generic libbpf APIs is still possible even when the BPF95skeleton is used. It's an additive convenience feature, with no syscalls, and no96cumbersome code.97 98Other Advantages of Using Skeleton File99---------------------------------------100 101* BPF skeleton provides an interface for user space programs to work with BPF102 global variables. The skeleton code memory maps global variables as a struct103 into user space. The struct interface allows user space programs to initialize104 BPF programs before the BPF load phase and fetch and update data from user105 space afterward.106 107* The ``skel.h`` file reflects the object file structure by listing out the108 available maps, programs, etc. BPF skeleton provides direct access to all the109 BPF maps and BPF programs as struct fields. This eliminates the need for110 string-based lookups with ``bpf_object_find_map_by_name()`` and111 ``bpf_object_find_program_by_name()`` APIs, reducing errors due to BPF source112 code and user-space code getting out of sync.113 114* The embedded bytecode representation of the object file ensures that the115 skeleton and the BPF object file are always in sync.116 117BPF Helpers118===========119 120libbpf provides BPF-side APIs that BPF programs can use to interact with the121system. The BPF helpers definition allows developers to use them in BPF code as122any other plain C function. For example, there are helper functions to print123debugging messages, get the time since the system was booted, interact with BPF124maps, manipulate network packets, etc.125 126For a complete description of what the helpers do, the arguments they take, and127the return value, see the `bpf-helpers128<https://man7.org/linux/man-pages/man7/bpf-helpers.7.html>`_ man page.129 130BPF CO-RE (Compile Once – Run Everywhere)131=========================================132 133BPF programs work in the kernel space and have access to kernel memory and data134structures. One limitation that BPF applications come across is the lack of135portability across different kernel versions and configurations. `BCC136<https://github.com/iovisor/bcc/>`_ is one of the solutions for BPF137portability. However, it comes with runtime overhead and a large binary size138from embedding the compiler with the application.139 140libbpf steps up the BPF program portability by supporting the BPF CO-RE concept.141BPF CO-RE brings together BTF type information, libbpf, and the compiler to142produce a single executable binary that you can run on multiple kernel versions143and configurations.144 145To make BPF programs portable libbpf relies on the BTF type information of the146running kernel. Kernel also exposes this self-describing authoritative BTF147information through ``sysfs`` at ``/sys/kernel/btf/vmlinux``.148 149You can generate the BTF information for the running kernel with the following150command:151 152::153 154 $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h155 156The command generates a ``vmlinux.h`` header file with all kernel types157(:doc:`BTF types <../btf>`) that the running kernel uses. Including158``vmlinux.h`` in your BPF program eliminates dependency on system-wide kernel159headers.160 161libbpf enables portability of BPF programs by looking at the BPF program’s162recorded BTF type and relocation information and matching them to BTF163information (vmlinux) provided by the running kernel. libbpf then resolves and164matches all the types and fields, and updates necessary offsets and other165relocatable data to ensure that BPF program’s logic functions correctly for a166specific kernel on the host. BPF CO-RE concept thus eliminates overhead167associated with BPF development and allows developers to write portable BPF168applications without modifications and runtime source code compilation on the169target machine.170 171The following code snippet shows how to read the parent field of a kernel172``task_struct`` using BPF CO-RE and libbf. The basic helper to read a field in a173CO-RE relocatable manner is ``bpf_core_read(dst, sz, src)``, which will read174``sz`` bytes from the field referenced by ``src`` into the memory pointed to by175``dst``.176 177.. code-block:: C178 :emphasize-lines: 6179 180 //...181 struct task_struct *task = (void *)bpf_get_current_task();182 struct task_struct *parent_task;183 int err;184 185 err = bpf_core_read(&parent_task, sizeof(void *), &task->parent);186 if (err) {187 /* handle error */188 }189 190 /* parent_task contains the value of task->parent pointer */191 192In the code snippet, we first get a pointer to the current ``task_struct`` using193``bpf_get_current_task()``. We then use ``bpf_core_read()`` to read the parent194field of task struct into the ``parent_task`` variable. ``bpf_core_read()`` is195just like ``bpf_probe_read_kernel()`` BPF helper, except it records information196about the field that should be relocated on the target kernel. i.e, if the197``parent`` field gets shifted to a different offset within198``struct task_struct`` due to some new field added in front of it, libbpf will199automatically adjust the actual offset to the proper value.200 201Getting Started with libbpf202===========================203 204Check out the `libbpf-bootstrap <https://github.com/libbpf/libbpf-bootstrap>`_205repository with simple examples of using libbpf to build various BPF206applications.207 208See also `libbpf API documentation209<https://libbpf.readthedocs.io/en/latest/api.html>`_.210 211libbpf and Rust212===============213 214If you are building BPF applications in Rust, it is recommended to use the215`Libbpf-rs <https://github.com/libbpf/libbpf-rs>`_ library instead of bindgen216bindings directly to libbpf. Libbpf-rs wraps libbpf functionality in217Rust-idiomatic interfaces and provides libbpf-cargo plugin to handle BPF code218compilation and skeleton generation. Using Libbpf-rs will make building user219space part of the BPF application easier. Note that the BPF program themselves220must still be written in plain C.221 222libbpf logging223==============224 225By default, libbpf logs informational and warning messages to stderr. The226verbosity of these messages can be controlled by setting the environment227variable LIBBPF_LOG_LEVEL to either warn, info, or debug. A custom log228callback can be set using ``libbpf_set_print()``.229 230Additional Documentation231========================232 233* `Program types and ELF Sections <https://libbpf.readthedocs.io/en/latest/program_types.html>`_234* `API naming convention <https://libbpf.readthedocs.io/en/latest/libbpf_naming_convention.html>`_235* `Building libbpf <https://libbpf.readthedocs.io/en/latest/libbpf_build.html>`_236* `API documentation Convention <https://libbpf.readthedocs.io/en/latest/libbpf_naming_convention.html#api-documentation-convention>`_237