use core::{cell::UnsafeCell, marker::PhantomData, mem}; use aya_ebpf_bindings::bindings::BPF_F_NO_PREALLOC; use aya_ebpf_cty::c_long; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_LPM_TRIE}, insert, lookup, maps::PinningType, remove, }; #[repr(transparent)] pub struct LpmTrie { def: UnsafeCell, _k: PhantomData, _v: PhantomData, } unsafe impl Sync for LpmTrie {} #[repr(C, packed)] pub struct Key { /// Represents the number of bits matched against. pub prefix_len: u32, /// Represents arbitrary data stored in the LpmTrie. pub data: K, } impl Key { pub fn new(prefix_len: u32, data: K) -> Self { Self { prefix_len, data } } } impl LpmTrie { pub const fn with_max_entries(max_entries: u32, flags: u32) -> LpmTrie { let flags = flags | BPF_F_NO_PREALLOC; LpmTrie { def: UnsafeCell::new(build_def::( BPF_MAP_TYPE_LPM_TRIE, max_entries, flags, PinningType::None, )), _k: PhantomData, _v: PhantomData, } } pub const fn pinned(max_entries: u32, flags: u32) -> LpmTrie { let flags = flags | BPF_F_NO_PREALLOC; LpmTrie { def: UnsafeCell::new(build_def::( BPF_MAP_TYPE_LPM_TRIE, max_entries, flags, PinningType::ByName, )), _k: PhantomData, _v: PhantomData, } } #[inline] pub fn get(&self, key: &Key) -> Option<&V> { lookup(self.def.get(), key).map(|p| unsafe { p.as_ref() }) } #[inline] pub fn insert(&self, key: &Key, value: &V, flags: u64) -> Result<(), c_long> { insert(self.def.get(), key, value, flags) } #[inline] pub fn remove(&self, key: &Key) -> Result<(), c_long> { remove(self.def.get(), key) } } const fn build_def(ty: u32, max_entries: u32, flags: u32, pin: PinningType) -> bpf_map_def { bpf_map_def { type_: ty, key_size: mem::size_of::>() as u32, value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, pinning: pin as u32, } }