use std::default::Default;
use std::slice;
use std::mem;
use crate::error::{Error, Result};
use crate::{Map, Sample};
use bpf_sys::{
XDP_FLAGS_DRV_MODE, XDP_FLAGS_HW_MODE, XDP_FLAGS_MASK, XDP_FLAGS_MODES, XDP_FLAGS_SKB_MODE,
XDP_FLAGS_UPDATE_IF_NOEXIST, BPF_ANY, bpf_map_type_BPF_MAP_TYPE_DEVMAP,
};
use tracing::error;
#[derive(Debug, Clone, Copy)]
#[repr(u32)]
pub enum Flags {
Unset = 0,
UpdateIfNoExist = XDP_FLAGS_UPDATE_IF_NOEXIST,
SkbMode = XDP_FLAGS_SKB_MODE,
DrvMode = XDP_FLAGS_DRV_MODE,
HwMode = XDP_FLAGS_HW_MODE,
Modes = XDP_FLAGS_MODES,
Mask = XDP_FLAGS_MASK,
}
impl Default for Flags {
fn default() -> Self {
Flags::Unset
}
}
#[repr(C)]
pub struct MapData<T> {
data: T,
offset: u32,
size: u32,
payload: [u8; 0],
}
impl<T> MapData<T> {
pub unsafe fn from_sample<U>(sample: &Sample) -> &MapData<U> {
&*(sample.data.as_ptr() as *const MapData<U>)
}
pub fn data(&self) -> &T {
&self.data
}
pub fn payload(&self) -> &[u8] {
unsafe {
let base = self.payload.as_ptr().add(self.offset as usize);
slice::from_raw_parts(base, (self.size - self.offset) as usize)
}
}
}
pub struct DevMap<'a> {
base: &'a Map,
}
impl<'a> DevMap<'a> {
pub fn new(base: &'a Map) -> Result<DevMap<'a>> {
if mem::size_of::<u32>() != base.config.key_size as usize
|| mem::size_of::<u32>() != base.config.value_size as usize
|| (bpf_map_type_BPF_MAP_TYPE_DEVMAP != base.config.type_)
{
error!(
"map definitions (map type and key/value size) of base `Map' and
`DevMap' do not match"
);
return Err(Error::Map);
}
Ok(DevMap { base })
}
pub fn set(&mut self, mut idx: u32, mut interface_index: u32) -> Result<()> {
let ret = unsafe {
bpf_sys::bpf_map_update_elem(
self.base.fd,
&mut idx as *mut _ as *mut _ as *mut _,
&mut interface_index as *mut _ as *mut _,
BPF_ANY.into(), )
};
if ret < 0 {
Err(Error::Map)
} else {
Ok(())
}
}
pub fn delete(&mut self, mut idx: u32) -> Result<()> {
let ret =
unsafe { bpf_sys::bpf_map_delete_elem(self.base.fd, &mut idx as *mut _ as *mut _) };
if ret < 0 {
Err(Error::Map)
} else {
Ok(())
}
}
}