use std::{
ffi::CString,
os::fd::{AsFd as _, BorrowedFd},
path::Path,
};
use aya_obj::generated::{bpf_map_info, bpf_map_type};
use super::{MapError, MapFd};
use crate::{
sys::{
bpf_get_object, bpf_map_get_fd_by_id, bpf_map_get_info_by_fd, iter_map_ids, SyscallError,
},
util::bytes_of_bpf_name,
FEATURES,
};
#[doc(alias = "bpf_map_info")]
#[derive(Debug)]
pub struct MapInfo(pub(crate) bpf_map_info);
impl MapInfo {
pub(crate) fn new_from_fd(fd: BorrowedFd<'_>) -> Result<Self, MapError> {
let info = bpf_map_get_info_by_fd(fd.as_fd())?;
Ok(Self(info))
}
pub fn from_id(id: u32) -> Result<Self, MapError> {
bpf_map_get_fd_by_id(id)
.map_err(MapError::from)
.and_then(|fd| Self::new_from_fd(fd.as_fd()))
}
pub fn map_type(&self) -> Result<MapType, MapError> {
bpf_map_type::try_from(self.0.type_)
.unwrap_or(bpf_map_type::__MAX_BPF_MAP_TYPE)
.try_into()
}
pub fn id(&self) -> u32 {
self.0.id
}
pub fn key_size(&self) -> u32 {
self.0.key_size
}
pub fn value_size(&self) -> u32 {
self.0.value_size
}
pub fn max_entries(&self) -> u32 {
self.0.max_entries
}
pub fn map_flags(&self) -> u32 {
self.0.map_flags
}
pub fn name(&self) -> &[u8] {
bytes_of_bpf_name(&self.0.name)
}
pub fn name_as_str(&self) -> Option<&str> {
let name = std::str::from_utf8(self.name()).ok()?;
(FEATURES.bpf_name() || !name.is_empty()).then_some(name)
}
pub fn fd(&self) -> Result<MapFd, MapError> {
let Self(info) = self;
let fd = bpf_map_get_fd_by_id(info.id)?;
Ok(MapFd::from_fd(fd))
}
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, MapError> {
use std::os::unix::ffi::OsStrExt as _;
let path_string = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap();
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})?;
Self::new_from_fd(fd.as_fd())
}
}
pub fn loaded_maps() -> impl Iterator<Item = Result<MapInfo, MapError>> {
iter_map_ids().map(|id| {
let id = id?;
MapInfo::from_id(id)
})
}
#[non_exhaustive]
#[doc(alias = "bpf_map_type")]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MapType {
Unspecified = bpf_map_type::BPF_MAP_TYPE_UNSPEC as isize,
#[doc(alias = "BPF_MAP_TYPE_HASH")]
Hash = bpf_map_type::BPF_MAP_TYPE_HASH as isize,
#[doc(alias = "BPF_MAP_TYPE_ARRAY")]
Array = bpf_map_type::BPF_MAP_TYPE_ARRAY as isize,
#[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
ProgramArray = bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY as isize,
#[doc(alias = "BPF_MAP_TYPE_PERF_EVENT_ARRAY")]
PerfEventArray = bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY as isize,
#[doc(alias = "BPF_MAP_TYPE_PERCPU_HASH")]
PerCpuHash = bpf_map_type::BPF_MAP_TYPE_PERCPU_HASH as isize,
#[doc(alias = "BPF_MAP_TYPE_PERCPU_ARRAY")]
PerCpuArray = bpf_map_type::BPF_MAP_TYPE_PERCPU_ARRAY as isize,
#[doc(alias = "BPF_MAP_TYPE_STACK_TRACE")]
StackTrace = bpf_map_type::BPF_MAP_TYPE_STACK_TRACE as isize,
#[doc(alias = "BPF_MAP_TYPE_CGROUP_ARRAY")]
CgroupArray = bpf_map_type::BPF_MAP_TYPE_CGROUP_ARRAY as isize,
#[doc(alias = "BPF_MAP_TYPE_LRU_HASH")]
LruHash = bpf_map_type::BPF_MAP_TYPE_LRU_HASH as isize,
#[doc(alias = "BPF_MAP_TYPE_LRU_PERCPU_HASH")]
LruPerCpuHash = bpf_map_type::BPF_MAP_TYPE_LRU_PERCPU_HASH as isize,
#[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")]
LpmTrie = bpf_map_type::BPF_MAP_TYPE_LPM_TRIE as isize,
#[doc(alias = "BPF_MAP_TYPE_ARRAY_OF_MAPS")]
ArrayOfMaps = bpf_map_type::BPF_MAP_TYPE_ARRAY_OF_MAPS as isize,
#[doc(alias = "BPF_MAP_TYPE_HASH_OF_MAPS")]
HashOfMaps = bpf_map_type::BPF_MAP_TYPE_HASH_OF_MAPS as isize,
#[doc(alias = "BPF_MAP_TYPE_DEVMAP")]
DevMap = bpf_map_type::BPF_MAP_TYPE_DEVMAP as isize,
#[doc(alias = "BPF_MAP_TYPE_SOCKMAP")]
SockMap = bpf_map_type::BPF_MAP_TYPE_SOCKMAP as isize,
#[doc(alias = "BPF_MAP_TYPE_CPUMAP")]
CpuMap = bpf_map_type::BPF_MAP_TYPE_CPUMAP as isize,
#[doc(alias = "BPF_MAP_TYPE_XSKMAP")]
XskMap = bpf_map_type::BPF_MAP_TYPE_XSKMAP as isize,
#[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
SockHash = bpf_map_type::BPF_MAP_TYPE_SOCKHASH as isize,
#[doc(alias = "BPF_MAP_TYPE_CGROUP_STORAGE")]
#[doc(alias = "BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED")]
CgroupStorage = bpf_map_type::BPF_MAP_TYPE_CGROUP_STORAGE as isize,
#[doc(alias = "BPF_MAP_TYPE_REUSEPORT_SOCKARRAY")]
ReuseportSockArray = bpf_map_type::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as isize,
#[doc(alias = "BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE")]
#[doc(alias = "BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED")]
PerCpuCgroupStorage = bpf_map_type::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE as isize,
#[doc(alias = "BPF_MAP_TYPE_QUEUE")]
Queue = bpf_map_type::BPF_MAP_TYPE_QUEUE as isize,
#[doc(alias = "BPF_MAP_TYPE_STACK")]
Stack = bpf_map_type::BPF_MAP_TYPE_STACK as isize,
#[doc(alias = "BPF_MAP_TYPE_SK_STORAGE")]
SkStorage = bpf_map_type::BPF_MAP_TYPE_SK_STORAGE as isize,
#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")]
DevMapHash = bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH as isize,
#[doc(alias = "BPF_MAP_TYPE_STRUCT_OPS")]
StructOps = bpf_map_type::BPF_MAP_TYPE_STRUCT_OPS as isize,
#[doc(alias = "BPF_MAP_TYPE_RINGBUF")]
RingBuf = bpf_map_type::BPF_MAP_TYPE_RINGBUF as isize,
#[doc(alias = "BPF_MAP_TYPE_INODE_STORAGE")]
InodeStorage = bpf_map_type::BPF_MAP_TYPE_INODE_STORAGE as isize,
#[doc(alias = "BPF_MAP_TYPE_TASK_STORAGE")]
TaskStorage = bpf_map_type::BPF_MAP_TYPE_TASK_STORAGE as isize,
#[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")]
BloomFilter = bpf_map_type::BPF_MAP_TYPE_BLOOM_FILTER as isize,
#[doc(alias = "BPF_MAP_TYPE_USER_RINGBUF")]
UserRingBuf = bpf_map_type::BPF_MAP_TYPE_USER_RINGBUF as isize,
#[doc(alias = "BPF_MAP_TYPE_CGRP_STORAGE")]
CgrpStorage = bpf_map_type::BPF_MAP_TYPE_CGRP_STORAGE as isize,
#[doc(alias = "BPF_MAP_TYPE_ARENA")]
Arena = bpf_map_type::BPF_MAP_TYPE_ARENA as isize,
}
impl TryFrom<bpf_map_type> for MapType {
type Error = MapError;
fn try_from(map_type: bpf_map_type) -> Result<Self, Self::Error> {
use bpf_map_type::*;
Ok(match map_type {
BPF_MAP_TYPE_UNSPEC => Self::Unspecified,
BPF_MAP_TYPE_HASH => Self::Hash,
BPF_MAP_TYPE_ARRAY => Self::Array,
BPF_MAP_TYPE_PROG_ARRAY => Self::ProgramArray,
BPF_MAP_TYPE_PERF_EVENT_ARRAY => Self::PerfEventArray,
BPF_MAP_TYPE_PERCPU_HASH => Self::PerCpuHash,
BPF_MAP_TYPE_PERCPU_ARRAY => Self::PerCpuArray,
BPF_MAP_TYPE_STACK_TRACE => Self::StackTrace,
BPF_MAP_TYPE_CGROUP_ARRAY => Self::CgroupArray,
BPF_MAP_TYPE_LRU_HASH => Self::LruHash,
BPF_MAP_TYPE_LRU_PERCPU_HASH => Self::LruPerCpuHash,
BPF_MAP_TYPE_LPM_TRIE => Self::LpmTrie,
BPF_MAP_TYPE_ARRAY_OF_MAPS => Self::ArrayOfMaps,
BPF_MAP_TYPE_HASH_OF_MAPS => Self::HashOfMaps,
BPF_MAP_TYPE_DEVMAP => Self::DevMap,
BPF_MAP_TYPE_SOCKMAP => Self::SockMap,
BPF_MAP_TYPE_CPUMAP => Self::CpuMap,
BPF_MAP_TYPE_XSKMAP => Self::XskMap,
BPF_MAP_TYPE_SOCKHASH => Self::SockHash,
BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED => Self::CgroupStorage,
BPF_MAP_TYPE_REUSEPORT_SOCKARRAY => Self::ReuseportSockArray,
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED => Self::PerCpuCgroupStorage,
BPF_MAP_TYPE_QUEUE => Self::Queue,
BPF_MAP_TYPE_STACK => Self::Stack,
BPF_MAP_TYPE_SK_STORAGE => Self::SkStorage,
BPF_MAP_TYPE_DEVMAP_HASH => Self::DevMapHash,
BPF_MAP_TYPE_STRUCT_OPS => Self::StructOps,
BPF_MAP_TYPE_RINGBUF => Self::RingBuf,
BPF_MAP_TYPE_INODE_STORAGE => Self::InodeStorage,
BPF_MAP_TYPE_TASK_STORAGE => Self::TaskStorage,
BPF_MAP_TYPE_BLOOM_FILTER => Self::BloomFilter,
BPF_MAP_TYPE_USER_RINGBUF => Self::UserRingBuf,
BPF_MAP_TYPE_CGRP_STORAGE => Self::CgrpStorage,
BPF_MAP_TYPE_ARENA => Self::Arena,
__MAX_BPF_MAP_TYPE => {
return Err(MapError::InvalidMapType {
map_type: map_type as u32,
})
}
})
}
}