use alloc::vec::Vec;
use crate::{EbpfSectionKind, InvalidTypeBinding, generated::bpf_map_type};
impl TryFrom<u32> for bpf_map_type {
type Error = InvalidTypeBinding<u32>;
fn try_from(map_type: u32) -> Result<Self, Self::Error> {
Ok(match map_type {
x if x == Self::BPF_MAP_TYPE_UNSPEC as u32 => Self::BPF_MAP_TYPE_UNSPEC,
x if x == Self::BPF_MAP_TYPE_HASH as u32 => Self::BPF_MAP_TYPE_HASH,
x if x == Self::BPF_MAP_TYPE_ARRAY as u32 => Self::BPF_MAP_TYPE_ARRAY,
x if x == Self::BPF_MAP_TYPE_PROG_ARRAY as u32 => Self::BPF_MAP_TYPE_PROG_ARRAY,
x if x == Self::BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => {
Self::BPF_MAP_TYPE_PERF_EVENT_ARRAY
}
x if x == Self::BPF_MAP_TYPE_PERCPU_HASH as u32 => Self::BPF_MAP_TYPE_PERCPU_HASH,
x if x == Self::BPF_MAP_TYPE_PERCPU_ARRAY as u32 => Self::BPF_MAP_TYPE_PERCPU_ARRAY,
x if x == Self::BPF_MAP_TYPE_STACK_TRACE as u32 => Self::BPF_MAP_TYPE_STACK_TRACE,
x if x == Self::BPF_MAP_TYPE_CGROUP_ARRAY as u32 => Self::BPF_MAP_TYPE_CGROUP_ARRAY,
x if x == Self::BPF_MAP_TYPE_LRU_HASH as u32 => Self::BPF_MAP_TYPE_LRU_HASH,
x if x == Self::BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => {
Self::BPF_MAP_TYPE_LRU_PERCPU_HASH
}
x if x == Self::BPF_MAP_TYPE_LPM_TRIE as u32 => Self::BPF_MAP_TYPE_LPM_TRIE,
x if x == Self::BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => Self::BPF_MAP_TYPE_ARRAY_OF_MAPS,
x if x == Self::BPF_MAP_TYPE_HASH_OF_MAPS as u32 => Self::BPF_MAP_TYPE_HASH_OF_MAPS,
x if x == Self::BPF_MAP_TYPE_DEVMAP as u32 => Self::BPF_MAP_TYPE_DEVMAP,
x if x == Self::BPF_MAP_TYPE_SOCKMAP as u32 => Self::BPF_MAP_TYPE_SOCKMAP,
x if x == Self::BPF_MAP_TYPE_CPUMAP as u32 => Self::BPF_MAP_TYPE_CPUMAP,
x if x == Self::BPF_MAP_TYPE_XSKMAP as u32 => Self::BPF_MAP_TYPE_XSKMAP,
x if x == Self::BPF_MAP_TYPE_SOCKHASH as u32 => Self::BPF_MAP_TYPE_SOCKHASH,
x if x == Self::BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED as u32 => {
Self::BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED
}
x if x == Self::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => {
Self::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
}
x if x == Self::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED as u32 => {
Self::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED
}
x if x == Self::BPF_MAP_TYPE_QUEUE as u32 => Self::BPF_MAP_TYPE_QUEUE,
x if x == Self::BPF_MAP_TYPE_STACK as u32 => Self::BPF_MAP_TYPE_STACK,
x if x == Self::BPF_MAP_TYPE_SK_STORAGE as u32 => Self::BPF_MAP_TYPE_SK_STORAGE,
x if x == Self::BPF_MAP_TYPE_DEVMAP_HASH as u32 => Self::BPF_MAP_TYPE_DEVMAP_HASH,
x if x == Self::BPF_MAP_TYPE_STRUCT_OPS as u32 => Self::BPF_MAP_TYPE_STRUCT_OPS,
x if x == Self::BPF_MAP_TYPE_RINGBUF as u32 => Self::BPF_MAP_TYPE_RINGBUF,
x if x == Self::BPF_MAP_TYPE_INODE_STORAGE as u32 => Self::BPF_MAP_TYPE_INODE_STORAGE,
x if x == Self::BPF_MAP_TYPE_TASK_STORAGE as u32 => Self::BPF_MAP_TYPE_TASK_STORAGE,
x if x == Self::BPF_MAP_TYPE_BLOOM_FILTER as u32 => Self::BPF_MAP_TYPE_BLOOM_FILTER,
x if x == Self::BPF_MAP_TYPE_USER_RINGBUF as u32 => Self::BPF_MAP_TYPE_USER_RINGBUF,
x if x == Self::BPF_MAP_TYPE_CGRP_STORAGE as u32 => Self::BPF_MAP_TYPE_CGRP_STORAGE,
x if x == Self::BPF_MAP_TYPE_ARENA as u32 => Self::BPF_MAP_TYPE_ARENA,
_ => return Err(InvalidTypeBinding { value: map_type }),
})
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct BtfMapDef {
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
pub(crate) pinning: PinningType,
pub btf_key_type_id: u32,
pub btf_value_type_id: u32,
}
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
pub enum PinningType {
#[default]
None = 0,
ByName = 1,
}
#[derive(Debug, thiserror::Error)]
pub enum PinningError {
#[error("unsupported pinning type `{pinning_type}`")]
Unsupported {
pinning_type: u32,
},
}
impl TryFrom<u32> for PinningType {
type Error = PinningError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::None),
1 => Ok(Self::ByName),
pinning_type => Err(PinningError::Unsupported { pinning_type }),
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct bpf_map_def {
pub map_type: u32,
pub key_size: u32,
pub value_size: u32,
pub max_entries: u32,
pub map_flags: u32,
pub id: u32,
pub pinning: PinningType,
}
pub(crate) const MINIMUM_MAP_SIZE: usize = size_of::<u32>() * 5;
#[derive(Debug, Clone)]
pub enum Map {
Legacy(LegacyMap),
Btf(BtfMap),
}
impl Map {
pub const fn map_type(&self) -> u32 {
match self {
Self::Legacy(m) => m.def.map_type,
Self::Btf(m) => m.def.map_type,
}
}
pub const fn key_size(&self) -> u32 {
match self {
Self::Legacy(m) => m.def.key_size,
Self::Btf(m) => m.def.key_size,
}
}
pub const fn value_size(&self) -> u32 {
match self {
Self::Legacy(m) => m.def.value_size,
Self::Btf(m) => m.def.value_size,
}
}
pub const fn set_value_size(&mut self, size: u32) {
match self {
Self::Legacy(m) => m.def.value_size = size,
Self::Btf(m) => m.def.value_size = size,
}
}
pub const fn max_entries(&self) -> u32 {
match self {
Self::Legacy(m) => m.def.max_entries,
Self::Btf(m) => m.def.max_entries,
}
}
pub const fn set_max_entries(&mut self, v: u32) {
match self {
Self::Legacy(m) => m.def.max_entries = v,
Self::Btf(m) => m.def.max_entries = v,
}
}
pub const fn map_flags(&self) -> u32 {
match self {
Self::Legacy(m) => m.def.map_flags,
Self::Btf(m) => m.def.map_flags,
}
}
pub const fn pinning(&self) -> PinningType {
match self {
Self::Legacy(m) => m.def.pinning,
Self::Btf(m) => m.def.pinning,
}
}
pub fn data(&self) -> &[u8] {
match self {
Self::Legacy(m) => &m.data,
Self::Btf(m) => &m.data,
}
}
pub fn data_mut(&mut self) -> &mut Vec<u8> {
match self {
Self::Legacy(m) => m.data.as_mut(),
Self::Btf(m) => m.data.as_mut(),
}
}
pub const fn section_index(&self) -> usize {
match self {
Self::Legacy(m) => m.section_index,
Self::Btf(m) => m.section_index,
}
}
pub const fn section_kind(&self) -> EbpfSectionKind {
match self {
Self::Legacy(m) => m.section_kind,
Self::Btf(_) => EbpfSectionKind::BtfMaps,
}
}
pub const fn symbol_index(&self) -> Option<usize> {
match self {
Self::Legacy(m) => m.symbol_index,
Self::Btf(m) => Some(m.symbol_index),
}
}
pub fn inner(&self) -> Option<Self> {
match self {
Self::Legacy(m) => m.inner_def.as_ref().map(|inner_def| {
Self::Legacy(LegacyMap {
def: *inner_def,
inner_def: None,
section_index: 0,
section_kind: EbpfSectionKind::Undefined,
symbol_index: None,
data: Vec::new(),
})
}),
Self::Btf(m) => m.inner_def.as_ref().map(|inner_def| {
Self::Btf(BtfMap {
def: *inner_def,
inner_def: None,
section_index: 0,
symbol_index: 0,
data: Vec::new(),
})
}),
}
}
pub const fn new_from_params(
map_type: u32,
key_size: u32,
value_size: u32,
max_entries: u32,
flags: u32,
) -> Self {
Self::Legacy(LegacyMap {
def: bpf_map_def {
map_type,
key_size,
value_size,
max_entries,
map_flags: flags,
id: 0,
pinning: PinningType::None,
},
inner_def: None,
section_index: 0,
section_kind: EbpfSectionKind::Undefined,
symbol_index: None,
data: Vec::new(),
})
}
}
#[derive(Debug, Clone)]
pub struct LegacyMap {
pub def: bpf_map_def,
pub inner_def: Option<bpf_map_def>,
pub section_index: usize,
pub section_kind: EbpfSectionKind,
pub symbol_index: Option<usize>,
pub data: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct BtfMap {
pub def: BtfMapDef,
pub(crate) inner_def: Option<BtfMapDef>,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) data: Vec<u8>,
}