From a837fb41ac0c385073b77b71f84f18d0ad876131 Mon Sep 17 00:00:00 2001 From: Dylan Reimerink Date: Sun, 15 Sep 2024 14:05:51 +0200 Subject: [PATCH] linux/concepts: Add functions concept page In addition the the functions concept page, also added the missing BPF_MAP_TYPE_ARENA map type page, although still empty. And pimped the linux concepts index page so its not just a boring list but slightly more visually appealing. Signed-off-by: Dylan Reimerink --- .aspell.en.pws | 2 + docs/linux/concepts/SUMMARY.md | 1 + docs/linux/concepts/functions.md | 49 +++++++++ docs/linux/concepts/index.md | 124 +++++++++++++++++++--- docs/linux/map-type/BPF_MAP_TYPE_ARENA.md | 19 ++++ docs/linux/map-type/SUMMARY.md | 1 + docs/linux/map-type/index.md | 1 + 7 files changed, 183 insertions(+), 14 deletions(-) create mode 100644 docs/linux/concepts/functions.md create mode 100644 docs/linux/map-type/BPF_MAP_TYPE_ARENA.md diff --git a/.aspell.en.pws b/.aspell.en.pws index c64e15e7..fd3dc61e 100644 --- a/.aspell.en.pws +++ b/.aspell.en.pws @@ -207,3 +207,5 @@ Mellanox init UID GID +decl +inlining diff --git a/docs/linux/concepts/SUMMARY.md b/docs/linux/concepts/SUMMARY.md index 93cc19a0..65751df1 100644 --- a/docs/linux/concepts/SUMMARY.md +++ b/docs/linux/concepts/SUMMARY.md @@ -1,6 +1,7 @@ * [`index.md`](index.md) * [Maps](maps.md) * [Verifier](verifier.md) +* [Functions](functions.md) * [Concurrency](concurrency.md) * [Pinning](pinning.md) * [Tail calls](tail-calls.md) diff --git a/docs/linux/concepts/functions.md b/docs/linux/concepts/functions.md new file mode 100644 index 00000000..31a474e2 --- /dev/null +++ b/docs/linux/concepts/functions.md @@ -0,0 +1,49 @@ +--- +title: Functions +description: This page explains the concept of eBPF functions, the different ways to use them, and how their usage has changed over time. +--- +# Functions + +When we talk about a function, we are referring to a function you would write in C or comparable programming language. In eBPF, the term function, program, and sub-program are often used interchangeably. A program refers to a function with a single argument, that being the context. A program can be attached to a hook point. Sub-programs, also referred to as BPF-to-BPF functions, are functions with zero to five arguments, they cannot be attached to a hook point, and are called from a program or special mechanism. + +## Calling convention + +The eBPF instruction set defines the calling convention for functions, these include programs, sub-programs, helper functions and kfuncs. Every function no matter who defines it uses the same calling convention. The R0 register is uses as the return value, a function should set it before returning unless it is a void function. Registers R1-R5 are used for arguments, R1 for the first argument, R2 for the second, and so on. Unlike calling conventions on native architectures, arguments are never passed via the stack. So 5 arguments is a hard limit, structures must be used to work around this. Registers R1-5 are clobbered after a function call, the verifier will not allow you to read from them until they are set with a known value. R6-9 are callee saved registers, they are preserved across function calls. + +## BPF to BPF functions (sub-programs) + +In [:octicons-tag-24: v4.16](https://github.com/torvalds/linux/commit/cc8b0b92a1699bc32f7fec71daa2bfc90de43a4d) BPF to BPF function calls were added. This allows BPF programs to reuse logic within the same program. A function can take up to 5 arguments, limited by the calling convention. It gets a fresh stack frame, which like any stack is free-ed and reused after the program exits. Functions can also access memory on the stack of a caller if a pointer to it is passed as an argument. Functions are limited to a maximum call depth of 8, so recursion of any meaningful depth is not possible. + +### Function inlining + +By default, the compiler will chose inline a function or to keep it a separate function. Compilers can be encouraged to inline or not inline a function with arguments like `__attribute__((always_inline))` or `__attribute__((noinline))`. Inlined functions do not incur the overhead of a function call as they will become part of the calling function. Inlined functions can also be optimized per call site since arguments are known. + +### Tail calls + +When function calls are combined with [tail calls](tail-calls.md) the available stack size per program will shrink from `512` bytes to `256` bytes. The reasoning being that when a tail call is made, the current stack frame is reused, but if that tail call is made from a function, the stack of the caller can not be reused. By default, kernel threads are limited to 8k stack sizes. By decreasing the max stack size, it is harder to run out of stack space, though it is still possible. + +### Function by function verification + +Until [:octicons-tag-24: v5.6](https://github.com/torvalds/linux/commit/51c39bb1d5d105a02e29aa7960f0a395086e6342) the verifier would re-verify that a function was safe for every call site. Meaning that if you have a function which is called 10 times, then the verifier would check for every call that with the given inputs the function was save. This defeats the purpose of functions somewhat since you still incur verifier complexity for every call. + +Since [:octicons-tag-24: v5.6](https://github.com/torvalds/linux/commit/51c39bb1d5d105a02e29aa7960f0a395086e6342) a distinction is made between "static" and "global" functions. Static functions are still verified as usual. But global functions undergo "function by function verification". This means that the verifier will verify every function once, and even out of order. It will assume all possible input values are possible, since it will not check every call site anymore. Therefor, functions might require more input checking to pass the verifier. This change reduces verification times and complexity. Static functions are functions marked with the `static` keyword in the C code, global functions regular non-static functions. + +### Global function replacement + +Also added in [:octicons-tag-24: v5.6](https://github.com/torvalds/linux/commit/be8704ff07d2374bcc5c675526f95e70c6459683) is the ability to replace global functions. The primary use case for this is libxdp which used this to implement XDP program chaining from a dispatcher program. + +See [Program Type `BPF_PROG_TYPE_EXT`](../program-type/BPF_PROG_TYPE_EXT.md) for more information. + +### Callbacks + +In [:octicons-tag-24: v5.13](https://github.com/torvalds/linux/commit/69c087ba6225b574afb6e505b72cb75242a3d844) the verifier was extended to allow for callbacks. Since then a number of helper function and kfuncs have been added that call back into given functions. + +### Argument annotations + +In [:octicons-tag-24: v6.8](https://github.com/torvalds/linux/commit/94e1c70a34523b5e1529e4ec508316acc6a26a2b) global function argument annotation were added. These are a set of annotations (in practice these are BTF decl tags), which if added to an attribute, tell the verifier to restrict the input values to the function. Possible tags are: + +* `__arg_ctx` - The argument is a pointer to a program context. +* `__arg_nonnull` - The argument can not be NULL. +* `__arg_nullable` - The argument can be NULL. +* `__arg_trusted` - The argument must be a [trusted value](kfuncs.md#kf_trusted_args). +* `__arg_arena` - The argument must be a pointer to a [memory arena](../map-type/BPF_MAP_TYPE_ARENA.md). diff --git a/docs/linux/concepts/index.md b/docs/linux/concepts/index.md index 4f8c00cc..fc335ed2 100644 --- a/docs/linux/concepts/index.md +++ b/docs/linux/concepts/index.md @@ -1,20 +1,116 @@ --- title: Linux eBPF concepts description: An index of Linux specific eBPF concepts. +hide: toc --- # Linux eBPF concepts -This is an index of Linux specific eBPF concepts and features. - -* [Maps](maps.md) -* [Verifier](verifier.md) -* [Concurrency](concurrency.md) -* [Pinning](pinning.md) -* [Tail calls](tail-calls.md) -* [Loops](loops.md) -* [Timers](timers.md) -* [Resource Limit](resource-limit.md) -* [AF_XDP](af_xdp.md) -* [KFuncs](kfuncs.md) -* [dynptrs](dynptrs.md) -* [token](token.md) +This is an index of Linux specific eBPF concepts and features. For more generic eBPF concepts that are not Linux specific, see the [eBPF concepts](../../concepts/index.md) page. + +
+ +- __Maps__ + + --- + + Maps allow for data storage and communication + + [:octicons-arrow-right-24: Maps](./maps.md) + +- __Verifier__ + + --- + + The verifier checks the safety of eBPF programs + + [:octicons-arrow-right-24: Verifier](./verifier.md) + +- __Functions__ + + --- + + This page explains how functions work for eBPF on Linux + + [:octicons-arrow-right-24: Functions](./functions.md) + +- __Concurrency__ + + --- + + This page explains the effects of concurrency on eBPF programs and how to handle it + + [:octicons-arrow-right-24: Concurrency](./concurrency.md) + +- __Pinning__ + + --- + + Pinning allows the file system to reference eBPF objects and keep them alive + + [:octicons-arrow-right-24: Pinning](./pinning.md) + +- __Tail calls__ + + --- + + Tail calls allow for the chaining of eBPF programs + + [:octicons-arrow-right-24: Tail calls](./tail-calls.md) + +- __Loops__ + + --- + + Loops in eBPF are not trivial, this page explains how to use different types of loops + + [:octicons-arrow-right-24: Loops](./loops.md) + +- __Timers__ + + --- + + Timers allow for the scheduling of eBPF functions to execute at a later time + + [:octicons-arrow-right-24: Timers](./timers.md) + +- __Resource Limit__ + + --- + + This page explains how the Linux kernel counts and restricts the resources used by eBPF + + [:octicons-arrow-right-24: Resource Limit](./resource-limit.md) + +- __AF_XDP__ + + --- + + AF_XDP allows you to bypass the kernel network stack and process packets in userspace + + [:octicons-arrow-right-24: AF_XDP](./af_xdp.md) + +- __KFuncs__ + + --- + + KFuncs allow for the calling of kernel functions from eBPF programs + + [:octicons-arrow-right-24: KFuncs](./kfuncs.md) + +- __Dynamic pointers__ + + --- + + Dynamic pointers are pointers with metadata, moving memory safety checks to runtime + + [:octicons-arrow-right-24: Dynptrs](./dynptrs.md) + +- __eBPF Tokens__ + + --- + + eBPF tokens are like authentication tokens for eBPF operations + + [:octicons-arrow-right-24: Token](./token.md) + +
diff --git a/docs/linux/map-type/BPF_MAP_TYPE_ARENA.md b/docs/linux/map-type/BPF_MAP_TYPE_ARENA.md new file mode 100644 index 00000000..a8c72a5f --- /dev/null +++ b/docs/linux/map-type/BPF_MAP_TYPE_ARENA.md @@ -0,0 +1,19 @@ +--- +title: "Map Type 'BPF_MAP_TYPE_ARENA'" +description: "This page documents the 'BPF_MAP_TYPE_ARENA' eBPF map type, including its definition, usage, program types that can use it, and examples." +--- +# Map type `BPF_MAP_TYPE_ARENA` + + +[:octicons-tag-24: v6.9](https://github.com/torvalds/linux/commit/317460317a02a1af512697e6e964298dedd8a163) + + +!!! example "Docs could be improved" + This part of the docs is incomplete, contributions are very welcome + + + diff --git a/docs/linux/map-type/SUMMARY.md b/docs/linux/map-type/SUMMARY.md index b9157d3d..c4a976ab 100644 --- a/docs/linux/map-type/SUMMARY.md +++ b/docs/linux/map-type/SUMMARY.md @@ -10,6 +10,7 @@ * [`BPF_MAP_TYPE_LRU_PERCPU_HASH`](BPF_MAP_TYPE_LRU_PERCPU_HASH.md) * [`BPF_MAP_TYPE_LPM_TRIE`](BPF_MAP_TYPE_LPM_TRIE.md) * [`BPF_MAP_TYPE_BLOOM_FILTER`](BPF_MAP_TYPE_BLOOM_FILTER.md) + * [`BPF_MAP_TYPE_ARENA`](BPF_MAP_TYPE_ARENA.md) * Map in map * [`BPF_MAP_TYPE_ARRAY_OF_MAPS`](BPF_MAP_TYPE_ARRAY_OF_MAPS.md) * [`BPF_MAP_TYPE_HASH_OF_MAPS`](BPF_MAP_TYPE_HASH_OF_MAPS.md) diff --git a/docs/linux/map-type/index.md b/docs/linux/map-type/index.md index 50fd8db5..325e21e3 100644 --- a/docs/linux/map-type/index.md +++ b/docs/linux/map-type/index.md @@ -20,6 +20,7 @@ These map types are not limited to a very specific use case but can be used in a * `BPF_MAP_TYPE_LRU_PERCPU_HASH` * [`BPF_MAP_TYPE_LPM_TRIE`](BPF_MAP_TYPE_LPM_TRIE.md) * [`BPF_MAP_TYPE_BLOOM_FILTER`](BPF_MAP_TYPE_BLOOM_FILTER.md) + * [`BPF_MAP_TYPE_ARENA`](BPF_MAP_TYPE_ARENA.md) ## Map in map