use crate::{
error::Result,
helpers::{bpf_map_lookup_elem, bpf_map_update_elem, bpf_redirect_map},
libbpf::{BpfMapDef, BpfMapType, BpfUpdateElemFlags, XdpAction},
};
pub use crate::maps::*;
macro_rules! map_new {
($map_type:path: $type_const:expr) => {
pub const fn new(max_entries: u32) -> $map_type {
$map_type {
def: BpfMapDef::new($type_const, max_entries),
}
}
};
}
macro_rules! map_def {
($(#[$outer:meta])*
struct $map_type:ident < $key:ty, $value:ty >: $type_const:expr) => {
#[repr(transparent)]
$(#[$outer])*
pub struct $map_type<$key, $value> {
def: BpfMapDef<$key, $value>,
}
impl<$key, $value> $map_type<$key, $value> { map_new! {$map_type<$key, $value>: $type_const} }
impl<$key, $value> Map for $map_type<$key, $value> { type Key = $key; type Value = $value; }
};
($(#[$outer:meta])*
struct $map_type:ident < $value:ident >: $type_const:expr) => {
#[repr(transparent)]
$(#[$outer])*
pub struct $map_type <$value> {
def: BpfMapDef<u32, $value>,
}
impl<$value> $map_type<$value> { map_new! {$map_type<$value>: $type_const} }
impl<$value> Map for $map_type<$value> { type Key = u32; type Value = $value; }
};
($(#[$outer:meta])*
struct $map_type:ident : $type_const:expr) => {
#[repr(transparent)]
$(#[$outer])*
pub struct $map_type {
def: BpfMapDef<u32, u32>,
}
impl $map_type { map_new! {$map_type: $type_const} }
impl Map for $map_type { type Key = u32; type Value = u32; }
};
}
pub trait Redirect: Map {
fn redirect_or(&self, target: Self::Key, default_action: XdpAction) -> XdpAction;
fn redirect(&self, target: Self::Key) -> XdpAction {
self.redirect_or(target, XdpAction::ABORTED)
}
}
pub trait LookupMut: Map {
unsafe fn lookup_mut<'a>(&'a self, key: &Self::Key) -> Option<&'a mut Self::Value>;
}
macro_rules! impl_map_redirect {
($map_def:ty) => {
impl Redirect for $map_def {
fn redirect_or(&self, target: u32, default_action: XdpAction) -> XdpAction {
bpf_redirect_map(&self.def, &target, default_action)
}
}
};
}
macro_rules! impl_map_lookup_mut {
($map_type:ident < $($gen:ident),* > ) => {
impl<$($gen,)*> LookupMut for $map_type<$($gen,)*> {
unsafe fn lookup_mut<'a>(&'a self, key: &Self::Key) -> Option<&'a mut Self::Value> {
bpf_map_lookup_elem(&self.def, key)
}
}
};
}
macro_rules! impl_map_update {
($map_type:ident < $($gen:ident),* > ) => {
impl<$($gen,)*> Update for $map_type<$($gen,)*> {
fn update(&mut self, key: &Self::Key, value: &Self::Value, flags: BpfUpdateElemFlags) -> Result<()> {
bpf_map_update_elem(&mut self.def, key, value, flags)
}
}
};
}
map_def! {
struct CpuMap: BpfMapType::CPUMAP
}
impl_map_redirect!(CpuMap);
map_def! {
struct XskMap: BpfMapType::XSKMAP
}
impl_map_redirect!(XskMap);
map_def! {
struct DevMap: BpfMapType::DEVMAP
}
impl_map_redirect!(DevMap);
map_def! {
struct Array<T>: BpfMapType::ARRAY
}
impl_map_lookup_mut!(Array<T>);
impl_map_update!(Array<T>);
map_def! {
struct PerCpuArray<T>: BpfMapType::PERCPU_ARRAY
}
impl_map_lookup_mut!(PerCpuArray<T>);
impl_map_update!(PerCpuArray<T>);