aya_ebpf/maps/program_array.rs
1use crate::{
2 EbpfContext,
3 bindings::bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY,
4 helpers::bpf_tail_call,
5 maps::{MapDef, PinningType},
6};
7
8/// A BPF map that stores an array of program indices for tail calling.
9///
10/// # Examples
11///
12/// ```no_run
13/// use aya_ebpf::{macros::map, maps::ProgramArray};
14/// # use aya_ebpf::{programs::LsmContext};
15///
16/// #[map]
17/// static JUMP_TABLE: ProgramArray = ProgramArray::with_max_entries(16, 0);
18///
19/// # unsafe fn try_test(ctx: &LsmContext) {
20/// let index: u32 = 13;
21///
22/// unsafe {
23/// JUMP_TABLE.tail_call(ctx, index);
24/// }
25/// # }
26/// ```
27#[repr(transparent)]
28pub struct ProgramArray {
29 def: MapDef,
30}
31
32impl ProgramArray {
33 map_constructors!(u32, u32, BPF_MAP_TYPE_PROG_ARRAY);
34
35 /// Performs a tail call into a program indexed by this map.
36 ///
37 /// # Safety
38 ///
39 /// This function is inherently unsafe, since it causes control flow to
40 /// jump into another eBPF program. This can have side effects, such as
41 /// drop methods not being called. Note that tail calling into an eBPF
42 /// program is not the same thing as a function call -- control flow
43 /// never returns to the caller.
44 ///
45 /// # Return Value
46 ///
47 /// On success, this function does not return into the original program.
48 /// On failure, control returns to the caller. The kernel's
49 /// `bpf_tail_call` helper is declared with `ret_type = RET_VOID` and
50 /// does not write `R0` on failure, so callers cannot distinguish
51 /// between the three failure modes (out-of-bounds index, empty slot,
52 /// or `MAX_TAIL_CALL_CNT` exceeded).
53 pub unsafe fn tail_call<C: EbpfContext>(&self, ctx: &C, index: u32) {
54 // SAFETY: `ctx` and `self.def` are valid pointers managed by aya.
55 unsafe {
56 bpf_tail_call(ctx.as_ptr(), self.def.as_ptr().cast(), index);
57 }
58 }
59}