1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use crate::{EbpfContext, btf_maps::btf_map_def, helpers::bpf_tail_call};
btf_map_def!(
/// A BTF-compatible BPF program array map.
///
/// This map type stores an array of program indices for tail calling.
/// Both keys and values are `u32`; values are file descriptors of BPF
/// programs to tail-call into.
///
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 4.20.
/// `BPF_MAP_TYPE_PROG_ARRAY` itself dates back to 4.2, but kernels
/// prior to 4.20 either silently dropped BTF for prog-array maps
/// (4.18) or rejected BTF `BPF_MAP_CREATE` with `-ENOTSUPP` (4.19).
///
/// # Example
///
/// ```rust
/// use aya_ebpf::{btf_maps::ProgramArray, macros::btf_map};
///
/// #[btf_map]
/// static JUMP_TABLE: ProgramArray<16> = ProgramArray::new();
/// ```
pub struct ProgramArray<; const MAX_ENTRIES: usize, const FLAGS: usize = 0>,
map_type: BPF_MAP_TYPE_PROG_ARRAY,
max_entries: MAX_ENTRIES,
map_flags: FLAGS,
key_type: u32,
value_type: u32,
);
impl<const MAX_ENTRIES: usize, const FLAGS: usize> ProgramArray<MAX_ENTRIES, FLAGS> {
/// Performs a tail call into a program indexed by this map.
///
/// # Safety
///
/// This function is inherently unsafe, since it causes control flow to
/// jump into another eBPF program. This can have side effects, such as
/// drop methods not being called. Note that tail calling into an eBPF
/// program is not the same thing as a function call -- control flow
/// never returns to the caller.
///
/// # Return Value
///
/// On success, this function does not return into the original program.
/// On failure, control returns to the caller. The kernel's
/// `bpf_tail_call` helper is declared with `ret_type = RET_VOID` and
/// does not write `R0` on failure, so callers cannot distinguish
/// between the three failure modes (out-of-bounds index, empty slot,
/// or `MAX_TAIL_CALL_CNT` exceeded).
pub unsafe fn tail_call<C: EbpfContext>(&self, ctx: &C, index: u32) {
// SAFETY: `ctx` and `self` are valid pointers managed by aya.
unsafe {
bpf_tail_call(ctx.as_ptr(), self.as_ptr(), index);
}
}
}