use core::{cell::UnsafeCell, hint::unreachable_unchecked, mem};
use aya_ebpf_cty::c_long;
use crate::{
bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY},
helpers::bpf_tail_call,
maps::PinningType,
EbpfContext,
};
#[repr(transparent)]
pub struct ProgramArray {
def: UnsafeCell<bpf_map_def>,
}
unsafe impl Sync for ProgramArray {}
impl ProgramArray {
pub const fn with_max_entries(max_entries: u32, flags: u32) -> ProgramArray {
ProgramArray {
def: UnsafeCell::new(bpf_map_def {
type_: BPF_MAP_TYPE_PROG_ARRAY,
key_size: mem::size_of::<u32>() as u32,
value_size: mem::size_of::<u32>() as u32,
max_entries,
map_flags: flags,
id: 0,
pinning: PinningType::None as u32,
}),
}
}
pub const fn pinned(max_entries: u32, flags: u32) -> ProgramArray {
ProgramArray {
def: UnsafeCell::new(bpf_map_def {
type_: BPF_MAP_TYPE_PROG_ARRAY,
key_size: mem::size_of::<u32>() as u32,
value_size: mem::size_of::<u32>() as u32,
max_entries,
map_flags: flags,
id: 0,
pinning: PinningType::ByName as u32,
}),
}
}
#[cfg(not(unstable))]
pub unsafe fn tail_call<C: EbpfContext>(&self, ctx: &C, index: u32) -> Result<(), c_long> {
let res = bpf_tail_call(ctx.as_ptr(), self.def.get() as *mut _, index);
if res != 0 {
Err(res)
} else {
unreachable_unchecked()
}
}
#[cfg(unstable)]
pub unsafe fn tail_call<C: EbpfContext>(&self, ctx: &C, index: u32) -> Result<!, c_long> {
let res = bpf_tail_call(ctx.as_ptr(), self.def.get() as *mut _, index);
if res != 0 {
Err(res)
} else {
unreachable_unchecked()
}
}
}