Skip to content

Commit

Permalink
ebpf-library: Add pages CO-RE macros
Browse files Browse the repository at this point in the history
This commit adds pages the CO-RE macros defined in libbpf's
`bpf_core_read.h` file.

Signed-off-by: Dylan Reimerink <[email protected]>
  • Loading branch information
dylandreimerink committed Dec 16, 2024
1 parent 0d21c24 commit d34bec5
Show file tree
Hide file tree
Showing 34 changed files with 1,439 additions and 33 deletions.
7 changes: 7 additions & 0 deletions .aspell.en.pws
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,16 @@ NUMA
IMM
GPL
MPL
accessor
accessors
centric
enum
enums
relocation
relocations
signable
signedness
typedefs
accumulatively
untrusted
inlined
Expand All @@ -145,6 +151,7 @@ deduplication
dereference
dereferenced
dereferencing
dereferences
incrementing
misprediction
sleepable
Expand Down
93 changes: 93 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ'"
description: "This page documents the 'BPF_CORE_READ' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ`

[:octicons-tag-24: v0.0.6](https://github.com/libbpf/libbpf/releases/tag/v0.0.6)

The `BPF_CORE_READ` macro is used to simplify BPF CO-RE relocatable read, especially when there are few pointer chasing steps.

## Definition

```c
#define BPF_CORE_READ(src, a, ...) ({ \
___type((src), a, ##__VA_ARGS__) __r; \
BPF_CORE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \
__r; \
})
```
## Usage
`BPF_CORE_READ` is used to simplify BPF CO-RE relocatable read, especially when there are few pointer chasing steps. E.g., what in non-BPF world (or in BPF w/ BCC) would be something like:
`#!c int x = s->a.b.c->d.e->f->g;`
can be succinctly achieved using `BPF_CORE_READ` as:
`#!c int x = BPF_CORE_READ(s, a.b.c, d.e, f, g);`
`BPF_CORE_READ` will decompose above statement into 4 [`bpf_core_read`](bpf_core_read.md) (BPF CO-RE relocatable [`bpf_probe_read_kernel`](../../../linux/helper-function/bpf_probe_read_kernel.md) wrapper) calls, logically equivalent to:
1. `const void *__t = s->a.b.c;`
2. `__t = __t->d.e;`
3. `__t = __t->f;`
4. `return __t->g;`
Equivalence is logical, because there is a heavy type casting/preservation involved, as well as all the reads are happening through [`bpf_probe_read_kernel`](../../../linux/helper-function/bpf_probe_read_kernel.md) calls using `__builtin_preserve_access_index`() to emit CO-RE relocations.
!!! note
Only up to 9 "field accessors" are supported, which should be more than enough for any practical purpose.
### Example
```c hl_lines="32 33"
/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#include "vmlinux.h"
#include "net_shared.h"
#include <linux/version.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
/* kprobe is NOT a stable ABI
* kernel functions can be removed, renamed or completely change semantics.
* Number of arguments and their positions can change, etc.
* In such case this bpf+kprobe example will no longer be meaningful
*/
SEC("kprobe.multi/__netif_receive_skb_core*")
int bpf_prog1(struct pt_regs *ctx)
{
/* attaches to kprobe __netif_receive_skb_core,
* looks for packets on loobpack device and prints them
* (wildcard is used for avoiding symbol mismatch due to optimization)
*/
char devname[IFNAMSIZ];
struct net_device *dev;
struct sk_buff *skb;
int len;
bpf_core_read(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx));
dev = BPF_CORE_READ(skb, dev);
len = BPF_CORE_READ(skb, len);
BPF_CORE_READ_STR_INTO(&devname, dev, name);
if (devname[0] == 'l' && devname[1] == 'o') {
char fmt[] = "skb %p len %d\n";
/* using bpf_trace_printk() for DEBUG ONLY */
bpf_trace_printk(fmt, sizeof(fmt), skb, len);
}
return 0;
}
char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;
```
74 changes: 74 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ_BITFIELD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ_BITFIELD'"
description: "This page documents the 'BPF_CORE_READ_BITFIELD' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ_BITFIELD`

[:octicons-tag-24: v0.0.6](https://github.com/libbpf/libbpf/releases/tag/v0.0.6)

The `BPF_CORE_READ_BITFIELD` macro extracts a bitfield from a given structure in a CO-RE relocatable way.

## Definition

```c
#define BPF_CORE_READ_BITFIELD(s, field) ({ \
const void *p = (const void *)s + __CORE_RELO(s, field, BYTE_OFFSET); \
unsigned long long val; \
\
/* This is a so-called barrier_var() operation that makes specified \
* variable "a black box" for optimizing compiler. \
* It forces compiler to perform BYTE_OFFSET relocation on p and use \
* its calculated value in the switch below, instead of applying \
* the same relocation 4 times for each individual memory load. \
*/ \
asm volatile("" : "=r"(p) : "0"(p)); \
\
switch (__CORE_RELO(s, field, BYTE_SIZE)) { \
case 1: val = *(const unsigned char *)p; break; \
case 2: val = *(const unsigned short *)p; break; \
case 4: val = *(const unsigned int *)p; break; \
case 8: val = *(const unsigned long long *)p; break; \
default: val = 0; break; \
} \
val <<= __CORE_RELO(s, field, LSHIFT_U64); \
if (__CORE_RELO(s, field, SIGNED)) \
val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64); \
else \
val = val >> __CORE_RELO(s, field, RSHIFT_U64); \
val; \
})
```
## Usage
`BPF_CORE_READ_BITFIELD` extract bitfield, identified by `s->field`, and return its value as u64. This is a variant of the [`BPF_CORE_READ_BITFIELD_PROBED`](BPF_CORE_READ_BITFIELD_PROBED.md) macro. This macro is using direct memory reads and should be used from BPF program types that support such functionality (e.g., typed [raw tracepoints](../../../linux/program-type/BPF_PROG_TYPE_TRACING.md#raw-tracepoint)).
### Example
```c
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Facebook */
struct tcp_sock {
u32 snd_cwnd; /* Sending congestion window */
/* [...] */
u8 chrono_type : 2, /* current chronograph type */
repair : 1,
tcp_usec_ts : 1, /* TSval values in usec */
is_sack_reneg:1, /* in recovery from loss with SACK reneg? */
is_cwnd_limited:1;/* forward progress limited by snd_cwnd? */
/* [...] */
u32 max_packets_out; /* max packets_out in last window */
}
static inline bool tcp_is_cwnd_limited(const struct sock *sk)
{
const struct tcp_sock *tp = tcp_sk(sk);
/* If in slow start, ensure cwnd grows to twice what was ACKed. */
if (tcp_in_slow_start(tp))
return tp->snd_cwnd < 2 * tp->max_packets_out;
return !!BPF_CORE_READ_BITFIELD(tp, is_cwnd_limited);
}
```
34 changes: 34 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ_BITFIELD_PROBED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ_BITFIELD_PROBED'"
description: "This page documents the 'BPF_CORE_READ_BITFIELD_PROBED' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ_BITFIELD_PROBED`

[:octicons-tag-24: v0.0.6](https://github.com/libbpf/libbpf/releases/tag/v0.0.6)

The `BPF_CORE_READ_BITFIELD_PROBED` macro extracts a bitfield from a given structure in a CO-RE relocatable way.

## Definition

```c
#define BPF_CORE_READ_BITFIELD_PROBED(s, field) ({ \
unsigned long long val = 0; \
\
__CORE_BITFIELD_PROBE_READ(&val, s, field); \
val <<= __CORE_RELO(s, field, LSHIFT_U64); \
if (__CORE_RELO(s, field, SIGNED)) \
val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64); \
else \
val = val >> __CORE_RELO(s, field, RSHIFT_U64); \
val; \
})
```
## Usage
`BPF_CORE_READ_BITFIELD` extract bitfield, identified by `s->field`, and return its value as u64. All this is done in relocatable manner, so bitfield changes such as signedness, bit size, offset changes, this will be handled automatically. This version of macro is using [`bpf_probe_read_kernel`](../../../linux/helper-function/bpf_probe_read_kernel.md) to read underlying integer storage. Macro functions as an expression and its return type is [`bpf_probe_read_kernel`](../../../linux/helper-function/bpf_probe_read_kernel.md) return value: 0, on success, <0 on error.
### Example
!!! example "Docs could be improved"
This part of the docs is incomplete, contributions are very welcome
40 changes: 40 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ_INTO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ_INTO'"
description: "This page documents the 'BPF_CORE_READ_INTO' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ_INTO`

[:octicons-tag-24: v0.0.6](https://github.com/libbpf/libbpf/releases/tag/v0.0.6)

The `BPF_CORE_READ_INTO` macro is a more performance-conscious variant of [`BPF_CORE_READ`](BPF_CORE_READ.md), in which final field is read into user-provided storage.

## Definition

```c
#define BPF_CORE_READ_INTO(dst, src, a, ...) ({ \
___core_read(bpf_core_read, bpf_core_read, \
dst, (src), a, ##__VA_ARGS__) \
})
```
## Usage
`BPF_CORE_READ_INTO` is very similar to [`BPF_CORE_READ`](BPF_CORE_READ.md), but instead of returning the value, it writes the value into the provided destination.
The following two code snippets are equivalent:
```c
int x = BPF_CORE_READ(s, a.b.c, d.e, f, g);
```

```c
int x;
BPF_CORE_READ_INTO(&x, s, a.b.c, d.e, f, g);
```
Please refer to the [`BPF_CORE_READ`](BPF_CORE_READ.md) documentation for more details on usage of it and its variants like this macros.
### Example
!!! example "Docs could be improved"
This part of the docs is incomplete, contributions are very welcome
29 changes: 29 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ_STR_INTO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ_STR_INTO'"
description: "This page documents the 'BPF_CORE_READ_STR_INTO' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ_STR_INTO`

[:octicons-tag-24: v0.0.6](https://github.com/libbpf/libbpf/releases/tag/v0.0.6)

The `BPF_CORE_READ_STR_INTO` macro is a variant of the [`BPF_CORE_READ_INTO`](BPF_CORE_READ_INTO.md) macro, which is used to do a BPF CO-RE relocatable string read into user-provided storage.

## Definition

```c
#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) ({ \
___core_read(bpf_core_read_str, bpf_core_read, \
dst, (src), a, ##__VA_ARGS__) \
})
```
## Usage
`BPF_CORE_READ_STR_INTO` is very similar to [`BPF_CORE_READ_INTO`](BPF_CORE_READ_INTO.md), but it uses the [`bpf_probe_read_kernel_str`](../../../linux/helper-function/bpf_probe_read_kernel_str.md) helper function instead of the [`bpf_probe_read_kernel`](../../../linux/helper-function/bpf_probe_read_kernel.md) helper function. This makes it better suites for reading NUL-terminated strings from kernel memory.
Please refer to the [`BPF_CORE_READ`](BPF_CORE_READ.md) documentation for more details on usage of it and its variants like this macros.
### Example
!!! example "Docs could be improved"
This part of the docs is incomplete, contributions are very welcome
32 changes: 32 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ_USER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ_USER'"
description: "This page documents the 'BPF_CORE_READ_USER' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ_USER`

[:octicons-tag-24: v0.4.0](https://github.com/libbpf/libbpf/releases/tag/v0.4.0)

The `BPF_CORE_READ_USER` macro is the userspace variant of the [`BPF_CORE_READ`](BPF_CORE_READ.md) macro.

## Definition

```c
#define BPF_CORE_READ_USER(src, a, ...) ({ \
___type((src), a, ##__VA_ARGS__) __r; \
BPF_CORE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \
__r; \
})
```
## Usage
The `BPF_CORE_READ_USER` macro is the userspace variant of the [`BPF_CORE_READ`](BPF_CORE_READ.md) macro. The difference being that the [`bpf_probe_read_user`](../../../linux/helper-function/bpf_probe_read_user.md) helper function is used instead of the [`bpf_probe_read_kernel`](../../../linux/helper-function/bpf_probe_read_kernel.md) helper function. This makes it able to read from userspace memory.
All the source types involved are still *kernel types* and need to exist in kernel (or kernel module) BTF, otherwise CO-RE relocation will fail. Custom user types are not relocatable with CO-RE. The typical situation in which `BPF_CORE_READ_USER` might be used is to read kernel UAPI types from the user-space memory passed in as a syscall input argument.
Please refer to the [`BPF_CORE_READ`](BPF_CORE_READ.md) documentation for more details on usage of it and its variants like this macros.
### Example
!!! example "Docs could be improved"
This part of the docs is incomplete, contributions are very welcome
40 changes: 40 additions & 0 deletions docs/ebpf-library/libbpf/ebpf/BPF_CORE_READ_USER_INTO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: "Libbpf eBPF macro 'BPF_CORE_READ_USER_INTO'"
description: "This page documents the 'BPF_CORE_READ_USER_INTO' libbpf eBPF macro, including its definition, usage, and examples."
---
# Libbpf eBPF macro `BPF_CORE_READ_USER_INTO`

[:octicons-tag-24: v0.4.0](https://github.com/libbpf/libbpf/releases/tag/v0.4.0)

The `BPF_CORE_READ_USER_INTO` macro is a more performance-conscious variant of [`BPF_CORE_READ_USER`](BPF_CORE_READ.md), in which final field is read into user-provided storage.

## Definition

```c
#define BPF_CORE_READ_USER_INTO(dst, src, a, ...) ({ \
___core_read(bpf_core_read_user, bpf_core_read_user, \
dst, (src), a, ##__VA_ARGS__) \
})
```
## Usage
`BPF_CORE_READ_USER_INTO` is very similar to [`BPF_CORE_READ_USER`](BPF_CORE_READ_USER.md), but instead of returning the value, it writes the value into the provided destination.
The following two code snippets are equivalent:
```c
int x = BPF_CORE_READ_USER(s, a.b.c, d.e, f, g);
```

```c
int x;
BPF_CORE_READ_USER_INTO(&x, s, a.b.c, d.e, f, g);
```
Please refer to the [`BPF_CORE_READ_USER`](BPF_CORE_READ_USER.md) documentation for more details on usage of it and its variants like this macros.
### Example
!!! example "Docs could be improved"
This part of the docs is incomplete, contributions are very welcome
Loading

0 comments on commit d34bec5

Please sign in to comment.