use core::marker::PhantomData;
use core::mem;
use crate::bindings::*;
use crate::helpers::*;
#[allow(non_camel_case_types)]
#[repr(C)]
struct bpf_elf_map {
type_: u32,
size_key: u32,
size_value: u32,
max_elem: u32,
flags: u32,
id: u32,
pinning: u32,
}
pub struct TcHashMap<K, V> {
def: bpf_elf_map,
_k: PhantomData<K>,
_v: PhantomData<V>,
}
#[repr(u32)]
#[derive(Clone, Copy)]
pub enum TcMapPinning {
None = 0,
ObjectNamespace,
GlobalNamespace,
}
impl<K, V> TcHashMap<K, V> {
pub const fn with_max_entries(max_entries: u32, pinning: TcMapPinning) -> Self {
Self {
def: bpf_elf_map {
type_: bpf_map_type_BPF_MAP_TYPE_HASH,
size_key: mem::size_of::<K>() as u32,
size_value: mem::size_of::<V>() as u32,
max_elem: max_entries,
flags: 0,
id: 0,
pinning: pinning as u32,
},
_k: PhantomData,
_v: PhantomData,
}
}
#[inline]
pub fn get(&mut self, key: &K) -> Option<&V> {
unsafe {
let value = bpf_map_lookup_elem(
&mut self.def as *mut _ as *mut _,
key as *const _ as *const _,
);
if value.is_null() {
None
} else {
Some(&*(value as *const V))
}
}
}
#[inline]
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
unsafe {
let value = bpf_map_lookup_elem(
&mut self.def as *mut _ as *mut _,
key as *const _ as *const _,
);
if value.is_null() {
None
} else {
Some(&mut *(value as *mut V))
}
}
}
#[inline]
pub fn set(&mut self, key: &K, value: &V) {
unsafe {
bpf_map_update_elem(
&mut self.def as *mut _ as *mut _,
key as *const _ as *const _,
value as *const _ as *const _,
BPF_ANY.into(),
);
}
}
#[inline]
pub fn delete(&mut self, key: &K) {
unsafe {
bpf_map_delete_elem(
&mut self.def as *mut _ as *mut _,
key as *const _ as *const _,
);
}
}
}