aya_friday/maps/array/program_array.rs
1//! An array of eBPF program file descriptors used as a jump table.
2
3use std::{
4 borrow::{Borrow, BorrowMut},
5 os::fd::{AsFd as _, AsRawFd as _, RawFd},
6};
7
8use crate::{
9 maps::{MapData, MapError, MapKeys, check_bounds, check_kv_size, hash_map},
10 programs::ProgramFd,
11};
12
13/// An array of eBPF program file descriptors used as a jump table.
14///
15/// eBPF programs can jump to other programs calling `bpf_tail_call(ctx,
16/// prog_array, index)`. You can use [`ProgramArray`] to configure which
17/// programs correspond to which jump indexes.
18///
19/// # Minimum kernel version
20///
21/// The minimum kernel version required to use this feature is 4.2.
22///
23/// # Examples
24/// ```no_run
25/// # let mut bpf = aya::Ebpf::load(&[])?;
26/// use aya::maps::ProgramArray;
27/// use aya::programs::CgroupSkb;
28///
29/// let mut prog_array = ProgramArray::try_from(bpf.take_map("JUMP_TABLE").unwrap())?;
30/// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?;
31/// let prog_0_fd = prog_0.fd().unwrap();
32/// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?;
33/// let prog_1_fd = prog_1.fd().unwrap();
34/// let prog_2: &CgroupSkb = bpf.program("example_prog_2").unwrap().try_into()?;
35/// let prog_2_fd = prog_2.fd().unwrap();
36/// let flags = 0;
37///
38/// // bpf_tail_call(ctx, JUMP_TABLE, 0) will jump to prog_0
39/// prog_array.set(0, prog_0_fd, flags);
40///
41/// // bpf_tail_call(ctx, JUMP_TABLE, 1) will jump to prog_1
42/// prog_array.set(1, prog_1_fd, flags);
43///
44/// // bpf_tail_call(ctx, JUMP_TABLE, 2) will jump to prog_2
45/// prog_array.set(2, prog_2_fd, flags);
46/// # Ok::<(), aya::EbpfError>(())
47/// ```
48#[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
49pub struct ProgramArray<T> {
50 pub(crate) inner: T,
51}
52
53impl<T: Borrow<MapData>> ProgramArray<T> {
54 pub(crate) fn new(map: T) -> Result<Self, MapError> {
55 let data = map.borrow();
56 check_kv_size::<u32, RawFd>(data)?;
57
58 Ok(Self { inner: map })
59 }
60
61 /// An iterator over the indices of the array that point to a program.
62 pub fn indices(&self) -> MapKeys<'_, u32> {
63 MapKeys::new(self.inner.borrow())
64 }
65}
66
67impl<T: BorrowMut<MapData>> ProgramArray<T> {
68 /// Sets the target program file descriptor for the given index in the jump table.
69 ///
70 /// When an eBPF program calls `bpf_tail_call(ctx, prog_array, index)`, control
71 /// flow will jump to `program`.
72 pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> {
73 let data = self.inner.borrow_mut();
74 check_bounds(data, index)?;
75 hash_map::insert(data, &index, &program.as_fd().as_raw_fd(), flags)
76 }
77
78 /// Clears the value at index in the jump table.
79 ///
80 /// Calling `bpf_tail_call(ctx, prog_array, index)` on an index that has been cleared returns an
81 /// error.
82 pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
83 let data = self.inner.borrow_mut();
84 check_bounds(data, *index)?;
85 hash_map::remove(data, index)
86 }
87}