//! Map struct and type bindings. use core::mem; use crate::thiserror::{self, Error}; use alloc::vec::Vec; /// Invalid map type encontered pub struct InvalidMapTypeError { /// The map type pub map_type: u32, } impl TryFrom for crate::generated::bpf_map_type { type Error = InvalidMapTypeError; fn try_from(map_type: u32) -> Result { use crate::generated::bpf_map_type::*; Ok(match map_type { x if x == BPF_MAP_TYPE_UNSPEC as u32 => BPF_MAP_TYPE_UNSPEC, x if x == BPF_MAP_TYPE_HASH as u32 => BPF_MAP_TYPE_HASH, x if x == BPF_MAP_TYPE_ARRAY as u32 => BPF_MAP_TYPE_ARRAY, x if x == BPF_MAP_TYPE_PROG_ARRAY as u32 => BPF_MAP_TYPE_PROG_ARRAY, x if x == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => BPF_MAP_TYPE_PERF_EVENT_ARRAY, x if x == BPF_MAP_TYPE_PERCPU_HASH as u32 => BPF_MAP_TYPE_PERCPU_HASH, x if x == BPF_MAP_TYPE_PERCPU_ARRAY as u32 => BPF_MAP_TYPE_PERCPU_ARRAY, x if x == BPF_MAP_TYPE_STACK_TRACE as u32 => BPF_MAP_TYPE_STACK_TRACE, x if x == BPF_MAP_TYPE_CGROUP_ARRAY as u32 => BPF_MAP_TYPE_CGROUP_ARRAY, x if x == BPF_MAP_TYPE_LRU_HASH as u32 => BPF_MAP_TYPE_LRU_HASH, x if x == BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => BPF_MAP_TYPE_LRU_PERCPU_HASH, x if x == BPF_MAP_TYPE_LPM_TRIE as u32 => BPF_MAP_TYPE_LPM_TRIE, x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER, x if x == BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => BPF_MAP_TYPE_ARRAY_OF_MAPS, x if x == BPF_MAP_TYPE_HASH_OF_MAPS as u32 => BPF_MAP_TYPE_HASH_OF_MAPS, x if x == BPF_MAP_TYPE_DEVMAP as u32 => BPF_MAP_TYPE_DEVMAP, x if x == BPF_MAP_TYPE_SOCKMAP as u32 => BPF_MAP_TYPE_SOCKMAP, x if x == BPF_MAP_TYPE_CPUMAP as u32 => BPF_MAP_TYPE_CPUMAP, x if x == BPF_MAP_TYPE_XSKMAP as u32 => BPF_MAP_TYPE_XSKMAP, x if x == BPF_MAP_TYPE_SOCKHASH as u32 => BPF_MAP_TYPE_SOCKHASH, x if x == BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED as u32 => { BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED } x if x == BPF_MAP_TYPE_CGRP_STORAGE as u32 => BPF_MAP_TYPE_CGRP_STORAGE, x if x == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, x if x == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE as u32 => { BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE } x if x == BPF_MAP_TYPE_QUEUE as u32 => BPF_MAP_TYPE_QUEUE, x if x == BPF_MAP_TYPE_STACK as u32 => BPF_MAP_TYPE_STACK, x if x == BPF_MAP_TYPE_SK_STORAGE as u32 => BPF_MAP_TYPE_SK_STORAGE, x if x == BPF_MAP_TYPE_DEVMAP_HASH as u32 => BPF_MAP_TYPE_DEVMAP_HASH, x if x == BPF_MAP_TYPE_STRUCT_OPS as u32 => BPF_MAP_TYPE_STRUCT_OPS, x if x == BPF_MAP_TYPE_RINGBUF as u32 => BPF_MAP_TYPE_RINGBUF, x if x == BPF_MAP_TYPE_INODE_STORAGE as u32 => BPF_MAP_TYPE_INODE_STORAGE, x if x == BPF_MAP_TYPE_TASK_STORAGE as u32 => BPF_MAP_TYPE_TASK_STORAGE, x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER, x if x == BPF_MAP_TYPE_USER_RINGBUF as u32 => BPF_MAP_TYPE_USER_RINGBUF, x if x == BPF_MAP_TYPE_CGRP_STORAGE as u32 => BPF_MAP_TYPE_CGRP_STORAGE, _ => return Err(InvalidMapTypeError { map_type }), }) } } /// BTF definition of a map #[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, /// BTF type id of the map key pub btf_key_type_id: u32, /// BTF type id of the map value pub btf_value_type_id: u32, } /// The pinning type /// /// Upon pinning a map, a file representation is created for the map, /// so that the map can be alive and retrievable across sessions. #[repr(u32)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] pub enum PinningType { /// No pinning #[default] None = 0, /// Pin by the name ByName = 1, } /// The error type returned when failing to parse a [PinningType] #[derive(Debug, Error)] pub enum PinningError { /// Unsupported pinning type #[error("unsupported pinning type `{pinning_type}`")] Unsupported { /// The unsupported pinning type pinning_type: u32, }, } impl TryFrom for PinningType { type Error = PinningError; fn try_from(value: u32) -> Result { match value { 0 => Ok(PinningType::None), 1 => Ok(PinningType::ByName), pinning_type => Err(PinningError::Unsupported { pinning_type }), } } } /// Map definition in legacy BPF map declaration style #[allow(non_camel_case_types)] #[repr(C)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct bpf_map_def { // minimum features required by old BPF programs /// The map type pub map_type: u32, /// The key_size pub key_size: u32, /// The value size pub value_size: u32, /// Max entry number pub max_entries: u32, /// Map flags pub map_flags: u32, // optional features /// Id pub id: u32, /// Pinning type pub pinning: PinningType, } /// The first five __u32 of `bpf_map_def` must be defined. pub(crate) const MINIMUM_MAP_SIZE: usize = mem::size_of::() * 5; /// Kinds of maps #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum MapKind { /// A map holding `.bss` section data Bss, /// A map holding `.data` section data Data, /// A map holding `.rodata` section data Rodata, /// Other maps Other, } impl From<&str> for MapKind { fn from(s: &str) -> Self { if s == ".bss" { MapKind::Bss } else if s.starts_with(".data") { MapKind::Data } else if s.starts_with(".rodata") { MapKind::Rodata } else { MapKind::Other } } } /// Map data defined in `maps` or `.maps` sections #[derive(Debug, Clone)] pub enum Map { /// A map defined in the `maps` section Legacy(LegacyMap), /// A map defined in the `.maps` section Btf(BtfMap), } impl Map { /// Returns the map type pub fn map_type(&self) -> u32 { match self { Map::Legacy(m) => m.def.map_type, Map::Btf(m) => m.def.map_type, } } /// Returns the key size in bytes pub fn key_size(&self) -> u32 { match self { Map::Legacy(m) => m.def.key_size, Map::Btf(m) => m.def.key_size, } } /// Returns the value size in bytes pub fn value_size(&self) -> u32 { match self { Map::Legacy(m) => m.def.value_size, Map::Btf(m) => m.def.value_size, } } /// Returns the max entry number pub fn max_entries(&self) -> u32 { match self { Map::Legacy(m) => m.def.max_entries, Map::Btf(m) => m.def.max_entries, } } /// Sets the max entry number pub fn set_max_entries(&mut self, v: u32) { match self { Map::Legacy(m) => m.def.max_entries = v, Map::Btf(m) => m.def.max_entries = v, } } /// Returns the map flags pub fn map_flags(&self) -> u32 { match self { Map::Legacy(m) => m.def.map_flags, Map::Btf(m) => m.def.map_flags, } } /// Returns the pinning type of the map pub fn pinning(&self) -> PinningType { match self { Map::Legacy(m) => m.def.pinning, Map::Btf(m) => m.def.pinning, } } /// Returns the map data pub fn data(&self) -> &[u8] { match self { Map::Legacy(m) => &m.data, Map::Btf(m) => &m.data, } } /// Returns the map data as mutable pub fn data_mut(&mut self) -> &mut Vec { match self { Map::Legacy(m) => m.data.as_mut(), Map::Btf(m) => m.data.as_mut(), } } /// Returns the map kind pub fn kind(&self) -> MapKind { match self { Map::Legacy(m) => m.kind, Map::Btf(m) => m.kind, } } /// Returns the section index pub fn section_index(&self) -> usize { match self { Map::Legacy(m) => m.section_index, Map::Btf(m) => m.section_index, } } /// Returns the symbol index pub fn symbol_index(&self) -> usize { match self { Map::Legacy(m) => m.symbol_index, Map::Btf(m) => m.symbol_index, } } } /// A map declared with legacy BPF map declaration style, most likely from a `maps` section. /// /// See [Drop support for legacy BPF map declaration syntax - Libbpf: the road to v1.0](https://github.com/libbpf/libbpf/wiki/Libbpf:-the-road-to-v1.0#drop-support-for-legacy-bpf-map-declaration-syntax) /// for more info. #[derive(Debug, Clone)] pub struct LegacyMap { /// The definition of the map pub def: bpf_map_def, /// The section index pub section_index: usize, /// The symbol index pub symbol_index: usize, /// The map data pub data: Vec, /// The map kind pub kind: MapKind, } /// A BTF-defined map, most likely from a `.maps` section. #[derive(Debug, Clone)] pub struct BtfMap { /// The definition of the map pub def: BtfMapDef, pub(crate) section_index: usize, pub(crate) symbol_index: usize, pub(crate) kind: MapKind, pub(crate) data: Vec, }