aya, aya-obj: split out the ELF bits from MapData

Maps can be created at runtime, in which case they don't have any ELF
info. Split the ELF bits into ElfMapData.

This is in preparation of adding MapData::create() to create maps at
runtime.
pull/935/head
Alessandro Decina 5 months ago
parent ba5bf6f912
commit 6eb38cf990

@ -93,7 +93,7 @@ pub mod programs;
pub mod relocation; pub mod relocation;
mod util; mod util;
pub use maps::Map; pub use maps::{Map, MapDef};
pub use obj::*; pub use obj::*;
/// An error returned from the verifier. /// An error returned from the verifier.

@ -5,7 +5,7 @@ use core::mem;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use crate::std; use crate::std;
use crate::EbpfSectionKind; use crate::{generated::bpf_map_info, EbpfSectionKind};
/// Invalid map type encontered /// Invalid map type encontered
pub struct InvalidMapTypeError { pub struct InvalidMapTypeError {
@ -72,10 +72,11 @@ pub struct MapDef {
pub(crate) max_entries: u32, pub(crate) max_entries: u32,
pub(crate) map_flags: u32, pub(crate) map_flags: u32,
pub(crate) pinning: PinningType, pub(crate) pinning: PinningType,
pub(crate) id: Option<u32>,
/// BTF type id of the map key /// BTF type id of the map key
pub btf_key_type_id: Option<u32>, pub(crate) btf_key_type_id: Option<u32>,
/// BTF type id of the map value /// BTF type id of the map value
pub btf_value_type_id: Option<u32>, pub(crate) btf_value_type_id: Option<u32>,
} }
impl From<bpf_map_def> for MapDef { impl From<bpf_map_def> for MapDef {
@ -87,12 +88,71 @@ impl From<bpf_map_def> for MapDef {
max_entries: def.max_entries, max_entries: def.max_entries,
map_flags: def.map_flags, map_flags: def.map_flags,
pinning: def.pinning, pinning: def.pinning,
id: Option::from(def.id).filter(|id| *id != 0),
btf_key_type_id: None, btf_key_type_id: None,
btf_value_type_id: None, btf_value_type_id: None,
} }
} }
} }
impl From<bpf_map_info> for MapDef {
fn from(info: bpf_map_info) -> Self {
MapDef {
map_type: info.type_,
key_size: info.key_size,
value_size: info.value_size,
max_entries: info.max_entries,
map_flags: info.map_flags,
pinning: PinningType::None,
id: Option::from(info.id).filter(|id| *id != 0),
btf_key_type_id: Option::from(info.btf_key_type_id).filter(|id| *id != 0),
btf_value_type_id: Option::from(info.btf_value_type_id).filter(|id| *id != 0),
}
}
}
impl MapDef {
/// Returns the map type
pub fn map_type(&self) -> u32 {
self.map_type
}
/// Returns the key size in bytes
pub fn key_size(&self) -> u32 {
self.key_size
}
/// Returns the value size in bytes
pub fn value_size(&self) -> u32 {
self.value_size
}
/// Returns the max entry number
pub fn max_entries(&self) -> u32 {
self.max_entries
}
/// Returns the map flags
pub fn map_flags(&self) -> u32 {
self.map_flags
}
/// Returns the pinning type of the map
pub fn pinning(&self) -> PinningType {
self.pinning
}
/// Returns the BTF type id of the map key
pub fn btf_key_type_id(&self) -> Option<u32> {
self.btf_key_type_id
}
/// Returns the BTF type id of the map value
pub fn btf_value_type_id(&self) -> Option<u32> {
self.btf_value_type_id
}
}
/// The pinning type /// The pinning type
/// ///
/// Upon pinning a map, a file representation is created for the map, /// Upon pinning a map, a file representation is created for the map,

@ -23,8 +23,7 @@ use crate::{
Array, Btf, BtfError, BtfExt, BtfFeatures, BtfType, DataSecEntry, FuncSecInfo, LineSecInfo, Array, Btf, BtfError, BtfExt, BtfFeatures, BtfType, DataSecEntry, FuncSecInfo, LineSecInfo,
}, },
generated::{ generated::{
bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_CALL, BPF_F_RDONLY_PROG, bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_CALL, BPF_F_RDONLY_PROG, BPF_JMP, BPF_K,
BPF_JMP, BPF_K,
}, },
maps::{bpf_map_def, BtfMap, LegacyMap, Map, MapDef, PinningType, MINIMUM_MAP_SIZE}, maps::{bpf_map_def, BtfMap, LegacyMap, Map, MapDef, PinningType, MINIMUM_MAP_SIZE},
programs::{ programs::{
@ -1296,44 +1295,6 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, MapDef),
Ok((map_name.to_string(), map_def)) Ok((map_name.to_string(), map_def))
} }
/// Parses a [bpf_map_info] into a [Map].
pub fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
if info.btf_key_type_id != 0 {
Map::Btf(BtfMap {
def: MapDef {
map_type: info.type_,
key_size: info.key_size,
value_size: info.value_size,
max_entries: info.max_entries,
map_flags: info.map_flags,
pinning: pinned,
btf_key_type_id: Some(info.btf_key_type_id),
btf_value_type_id: Some(info.btf_value_type_id),
},
section_index: 0,
symbol_index: 0,
data: Vec::new(),
})
} else {
Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: info.type_,
key_size: info.key_size,
value_size: info.value_size,
max_entries: info.max_entries,
map_flags: info.map_flags,
pinning: pinned,
id: info.id,
}
.into(),
section_index: 0,
symbol_index: None,
section_kind: EbpfSectionKind::Undefined,
data: Vec::new(),
})
}
}
/// Copies a block of eBPF instructions /// Copies a block of eBPF instructions
pub fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> { pub fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
if data.len() % mem::size_of::<bpf_insn>() > 0 { if data.len() % mem::size_of::<bpf_insn>() > 0 {
@ -1581,6 +1542,7 @@ mod tests {
max_entries: 1, max_entries: 1,
map_flags: 0, map_flags: 0,
pinning: PinningType::None, pinning: PinningType::None,
id: None,
btf_key_type_id: None, btf_key_type_id: None,
btf_value_type_id: None, btf_value_type_id: None,
}, },

@ -21,10 +21,10 @@ use thiserror::Error;
use crate::{ use crate::{
generated::{ generated::{
bpf_map_type, bpf_map_type::*, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, bpf_map_type::{self, *},
AYA_PERF_EVENT_IOC_SET_BPF, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF,
}, },
maps::{Map, MapData, MapError}, maps::{ElfMapData, Map, MapData, MapError},
obj::{ obj::{
btf::{Btf, BtfError}, btf::{Btf, BtfError},
Object, ParseError, ProgramSection, Object, ParseError, ProgramSection,
@ -494,7 +494,7 @@ impl<'a> EbpfLoader<'a> {
} }
let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd());
let mut map = match obj.pinning() { let mut map = match obj.pinning() {
PinningType::None => MapData::create(obj, &name, btf_fd)?, PinningType::None => ElfMapData::create(obj, &name, btf_fd)?,
PinningType::ByName => { PinningType::ByName => {
// pin maps in /sys/fs/bpf by default to align with libbpf // pin maps in /sys/fs/bpf by default to align with libbpf
// behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161. // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161.
@ -502,7 +502,7 @@ impl<'a> EbpfLoader<'a> {
.as_deref() .as_deref()
.unwrap_or_else(|| Path::new("/sys/fs/bpf")); .unwrap_or_else(|| Path::new("/sys/fs/bpf"));
MapData::create_pinned_by_name(path, obj, &name, btf_fd)? ElfMapData::create_pinned_by_name(path, obj, &name, btf_fd)?
} }
}; };
map.finalize()?; map.finalize()?;
@ -517,7 +517,7 @@ impl<'a> EbpfLoader<'a> {
obj.relocate_maps( obj.relocate_maps(
maps.iter() maps.iter()
.map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), data.obj())), .map(|(s, data)| (s.as_str(), data.fd.as_fd().as_raw_fd(), &data.obj)),
&text_sections, &text_sections,
)?; )?;
obj.relocate_calls(&text_sections)?; obj.relocate_calls(&text_sections)?;
@ -697,13 +697,14 @@ impl<'a> EbpfLoader<'a> {
.collect(); .collect();
let maps = maps let maps = maps
.drain() .drain()
.map(|(name, elf_map)| (name, elf_map.into()))
.map(parse_map) .map(parse_map)
.collect::<Result<HashMap<String, Map>, EbpfError>>()?; .collect::<Result<HashMap<String, Map>, EbpfError>>()?;
if !*allow_unsupported_maps { if !*allow_unsupported_maps {
maps.iter().try_for_each(|(_, x)| match x { maps.iter().try_for_each(|(_, x)| match x {
Map::Unsupported(map) => Err(EbpfError::MapError(MapError::Unsupported { Map::Unsupported(map) => Err(EbpfError::MapError(MapError::Unsupported {
map_type: map.obj().map_type(), map_type: map.def.map_type(),
})), })),
_ => Ok(()), _ => Ok(()),
})?; })?;
@ -715,7 +716,7 @@ impl<'a> EbpfLoader<'a> {
fn parse_map(data: (String, MapData)) -> Result<(String, Map), EbpfError> { fn parse_map(data: (String, MapData)) -> Result<(String, Map), EbpfError> {
let (name, map) = data; let (name, map) = data;
let map_type = bpf_map_type::try_from(map.obj().map_type()).map_err(MapError::from)?; let map_type = bpf_map_type::try_from(map.def.map_type()).map_err(MapError::from)?;
let map = match map_type { let map = match map_type {
BPF_MAP_TYPE_ARRAY => Map::Array(map), BPF_MAP_TYPE_ARRAY => Map::Array(map),
BPF_MAP_TYPE_PERCPU_ARRAY => Map::PerCpuArray(map), BPF_MAP_TYPE_PERCPU_ARRAY => Map::PerCpuArray(map),

@ -50,7 +50,7 @@ impl<T: Borrow<MapData>, V: Pod> Array<T, V> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
/// Returns the value stored at the given index. /// Returns the value stored at the given index.

@ -69,7 +69,7 @@ impl<T: Borrow<MapData>, V: Pod> PerCpuArray<T, V> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
/// Returns a slice of values - one for each CPU - stored at the given index. /// Returns a slice of values - one for each CPU - stored at the given index.

@ -91,7 +91,7 @@ mod tests {
bpf_cmd, bpf_cmd,
bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY}, bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
}, },
maps::Map, maps::{ElfMapData, Map},
obj::{self, maps::LegacyMap, EbpfSectionKind}, obj::{self, maps::LegacyMap, EbpfSectionKind},
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
@ -121,7 +121,7 @@ mod tests {
} => Ok(1337), } => Ok(1337),
call => panic!("unexpected syscall {:?}", call), call => panic!("unexpected syscall {:?}", call),
}); });
MapData::create(obj, "foo", None).unwrap() ElfMapData::create(obj, "foo", None).unwrap().into()
} }
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<c_long> {

@ -49,7 +49,7 @@ mod test_utils {
use crate::{ use crate::{
bpf_map_def, bpf_map_def,
generated::{bpf_cmd, bpf_map_type}, generated::{bpf_cmd, bpf_map_type},
maps::MapData, maps::{ElfMapData, MapData},
obj::{self, maps::LegacyMap, EbpfSectionKind}, obj::{self, maps::LegacyMap, EbpfSectionKind},
sys::{override_syscall, Syscall}, sys::{override_syscall, Syscall},
}; };
@ -62,7 +62,7 @@ mod test_utils {
} => Ok(1337), } => Ok(1337),
call => panic!("unexpected syscall {:?}", call), call => panic!("unexpected syscall {:?}", call),
}); });
MapData::create(obj, "foo", None).unwrap() ElfMapData::create(obj, "foo", None).unwrap().into()
} }
pub(super) fn new_obj_map(map_type: bpf_map_type) -> obj::Map { pub(super) fn new_obj_map(map_type: bpf_map_type) -> obj::Map {

@ -208,7 +208,7 @@ mod tests {
bpf_cmd, bpf_cmd,
bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY}, bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
}, },
maps::Map, maps::{ElfMapData, Map},
obj::{self, maps::LegacyMap, EbpfSectionKind}, obj::{self, maps::LegacyMap, EbpfSectionKind},
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
@ -238,7 +238,7 @@ mod tests {
} => Ok(1337), } => Ok(1337),
call => panic!("unexpected syscall {:?}", call), call => panic!("unexpected syscall {:?}", call),
}); });
MapData::create(obj, "foo", None).unwrap() ElfMapData::create(obj, "foo", None).unwrap().into()
} }
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<c_long> {

@ -54,7 +54,10 @@ use std::{
marker::PhantomData, marker::PhantomData,
mem, mem,
ops::Deref, ops::Deref,
os::fd::{AsFd, BorrowedFd, OwnedFd}, os::{
fd::{AsFd, BorrowedFd, OwnedFd},
unix::ffi::OsStrExt as _,
},
path::Path, path::Path,
ptr, ptr,
}; };
@ -66,7 +69,7 @@ use thiserror::Error;
use crate::{ use crate::{
generated::bpf_map_info, generated::bpf_map_info,
obj::{self, parse_map_info, EbpfSectionKind}, obj::{self, EbpfSectionKind},
pin::PinError, pin::PinError,
sys::{ sys::{
bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_fd_by_id, bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_fd_by_id,
@ -74,7 +77,7 @@ use crate::{
iter_map_ids, SyscallError, iter_map_ids, SyscallError,
}, },
util::{bytes_of_bpf_name, nr_cpus, KernelVersion}, util::{bytes_of_bpf_name, nr_cpus, KernelVersion},
PinningType, Pod, Pod,
}; };
pub mod array; pub mod array;
@ -304,27 +307,27 @@ impl Map {
/// Returns the low level map type. /// Returns the low level map type.
fn map_type(&self) -> u32 { fn map_type(&self) -> u32 {
match self { match self {
Self::Array(map) => map.obj.map_type(), Self::Array(map) => map.def.map_type(),
Self::BloomFilter(map) => map.obj.map_type(), Self::BloomFilter(map) => map.def.map_type(),
Self::CpuMap(map) => map.obj.map_type(), Self::CpuMap(map) => map.def.map_type(),
Self::DevMap(map) => map.obj.map_type(), Self::DevMap(map) => map.def.map_type(),
Self::DevMapHash(map) => map.obj.map_type(), Self::DevMapHash(map) => map.def.map_type(),
Self::HashMap(map) => map.obj.map_type(), Self::HashMap(map) => map.def.map_type(),
Self::LpmTrie(map) => map.obj.map_type(), Self::LpmTrie(map) => map.def.map_type(),
Self::LruHashMap(map) => map.obj.map_type(), Self::LruHashMap(map) => map.def.map_type(),
Self::PerCpuArray(map) => map.obj.map_type(), Self::PerCpuArray(map) => map.def.map_type(),
Self::PerCpuHashMap(map) => map.obj.map_type(), Self::PerCpuHashMap(map) => map.def.map_type(),
Self::PerCpuLruHashMap(map) => map.obj.map_type(), Self::PerCpuLruHashMap(map) => map.def.map_type(),
Self::PerfEventArray(map) => map.obj.map_type(), Self::PerfEventArray(map) => map.def.map_type(),
Self::ProgramArray(map) => map.obj.map_type(), Self::ProgramArray(map) => map.def.map_type(),
Self::Queue(map) => map.obj.map_type(), Self::Queue(map) => map.def.map_type(),
Self::RingBuf(map) => map.obj.map_type(), Self::RingBuf(map) => map.def.map_type(),
Self::SockHash(map) => map.obj.map_type(), Self::SockHash(map) => map.def.map_type(),
Self::SockMap(map) => map.obj.map_type(), Self::SockMap(map) => map.def.map_type(),
Self::Stack(map) => map.obj.map_type(), Self::Stack(map) => map.def.map_type(),
Self::StackTraceMap(map) => map.obj.map_type(), Self::StackTraceMap(map) => map.def.map_type(),
Self::Unsupported(map) => map.obj.map_type(), Self::Unsupported(map) => map.def.map_type(),
Self::XskMap(map) => map.obj.map_type(), Self::XskMap(map) => map.def.map_type(),
} }
} }
@ -493,7 +496,7 @@ impl_try_from_map!((K, V) {
}); });
pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> { pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> {
let max_entries = map.obj.max_entries(); let max_entries = map.def.max_entries();
if index >= max_entries { if index >= max_entries {
Err(MapError::OutOfBounds { index, max_entries }) Err(MapError::OutOfBounds { index, max_entries })
} else { } else {
@ -503,12 +506,12 @@ pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> {
pub(crate) fn check_kv_size<K, V>(map: &MapData) -> Result<(), MapError> { pub(crate) fn check_kv_size<K, V>(map: &MapData) -> Result<(), MapError> {
let size = mem::size_of::<K>(); let size = mem::size_of::<K>();
let expected = map.obj.key_size() as usize; let expected = map.def.key_size() as usize;
if size != expected { if size != expected {
return Err(MapError::InvalidKeySize { size, expected }); return Err(MapError::InvalidKeySize { size, expected });
} }
let size = mem::size_of::<V>(); let size = mem::size_of::<V>();
let expected = map.obj.value_size() as usize; let expected = map.def.value_size() as usize;
if size != expected { if size != expected {
return Err(MapError::InvalidValueSize { size, expected }); return Err(MapError::InvalidValueSize { size, expected });
}; };
@ -517,25 +520,22 @@ pub(crate) fn check_kv_size<K, V>(map: &MapData) -> Result<(), MapError> {
pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> { pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
let size = mem::size_of::<V>(); let size = mem::size_of::<V>();
let expected = map.obj.value_size() as usize; let expected = map.def.value_size() as usize;
if size != expected { if size != expected {
return Err(MapError::InvalidValueSize { size, expected }); return Err(MapError::InvalidValueSize { size, expected });
}; };
Ok(()) Ok(())
} }
/// A generic handle to a BPF map.
///
/// You should never need to use this unless you're implementing a new map type.
#[derive(Debug)] #[derive(Debug)]
pub struct MapData { pub(crate) struct ElfMapData {
obj: obj::Map, pub(crate) obj: obj::Map,
fd: MapFd, pub(crate) fd: MapFd,
} }
impl MapData { impl ElfMapData {
/// Creates a new map with the provided `name` /// Creates a new map with the provided `name`
pub fn create( pub(crate) fn create(
obj: obj::Map, obj: obj::Map,
name: &str, name: &str,
btf_fd: Option<BorrowedFd<'_>>, btf_fd: Option<BorrowedFd<'_>>,
@ -591,7 +591,7 @@ impl MapData {
} }
Err(_) => { Err(_) => {
let map = Self::create(obj, name, btf_fd)?; let map = Self::create(obj, name, btf_fd)?;
map.pin(&path).map_err(|error| MapError::PinError { pin_map(&map.fd, &path).map_err(|error| MapError::PinError {
name: Some(name.into()), name: Some(name.into()),
error, error,
})?; })?;
@ -620,7 +620,18 @@ impl MapData {
} }
Ok(()) Ok(())
} }
}
/// A generic handle to a BPF map.
///
/// You should never need to use this unless you're implementing a new map type.
#[derive(Debug)]
pub struct MapData {
pub(crate) def: obj::MapDef,
pub(crate) fd: MapFd,
}
impl MapData {
/// Loads a map from a pinned path in bpffs. /// Loads a map from a pinned path in bpffs.
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, MapError> { pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, MapError> {
use std::os::unix::ffi::OsStrExt as _; use std::os::unix::ffi::OsStrExt as _;
@ -657,7 +668,7 @@ impl MapData {
pub fn from_fd(fd: OwnedFd) -> Result<Self, MapError> { pub fn from_fd(fd: OwnedFd) -> Result<Self, MapError> {
let MapInfo(info) = MapInfo::new_from_fd(fd.as_fd())?; let MapInfo(info) = MapInfo::new_from_fd(fd.as_fd())?;
Ok(Self { Ok(Self {
obj: parse_map_info(info, PinningType::None), def: info.into(),
fd: MapFd(fd), fd: MapFd(fd),
}) })
} }
@ -687,40 +698,47 @@ impl MapData {
/// # Ok::<(), Box<dyn std::error::Error>>(()) /// # Ok::<(), Box<dyn std::error::Error>>(())
/// ``` /// ```
pub fn pin<P: AsRef<Path>>(&self, path: P) -> Result<(), PinError> { pub fn pin<P: AsRef<Path>>(&self, path: P) -> Result<(), PinError> {
use std::os::unix::ffi::OsStrExt as _; let Self { fd, def: _ } = self;
pin_map(fd, path)
let Self { fd, obj: _ } = self;
let path = path.as_ref();
let path_string = CString::new(path.as_os_str().as_bytes()).map_err(|error| {
PinError::InvalidPinPath {
path: path.to_path_buf(),
error,
}
})?;
bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_PIN",
io_error,
})?;
Ok(())
} }
/// Returns the file descriptor of the map. /// Returns the file descriptor of the map.
pub fn fd(&self) -> &MapFd { pub fn fd(&self) -> &MapFd {
let Self { obj: _, fd } = self; let Self { def: _, fd } = self;
fd fd
} }
pub(crate) fn obj(&self) -> &obj::Map {
let Self { obj, fd: _ } = self;
obj
}
/// Returns the kernel's information about the loaded map. /// Returns the kernel's information about the loaded map.
pub fn info(&self) -> Result<MapInfo, MapError> { pub fn info(&self) -> Result<MapInfo, MapError> {
MapInfo::new_from_fd(self.fd.as_fd()) MapInfo::new_from_fd(self.fd.as_fd())
} }
} }
impl From<ElfMapData> for MapData {
fn from(elf_map: ElfMapData) -> Self {
let ElfMapData { fd, obj } = elf_map;
let def = match obj {
aya_obj::Map::Legacy(m) => m.def,
aya_obj::Map::Btf(m) => m.def,
};
Self { def, fd }
}
}
fn pin_map(fd: &MapFd, path: impl AsRef<Path>) -> Result<(), PinError> {
let path = path.as_ref();
let path_string =
CString::new(path.as_os_str().as_bytes()).map_err(|error| PinError::InvalidPinPath {
path: path.to_path_buf(),
error,
})?;
bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_PIN",
io_error,
})?;
Ok(())
}
/// An iterable map /// An iterable map
pub trait IterableMap<K: Pod, V> { pub trait IterableMap<K: Pod, V> {
/// Get a generic map handle /// Get a generic map handle
@ -1078,7 +1096,7 @@ mod tests {
assert_matches!( assert_matches!(
MapData::from_id(1234), MapData::from_id(1234),
Ok(MapData { Ok(MapData {
obj: _, def: _,
fd, fd,
}) => assert_eq!(fd.as_fd().as_raw_fd(), 42) }) => assert_eq!(fd.as_fd().as_raw_fd(), 42)
); );
@ -1095,8 +1113,8 @@ mod tests {
}); });
assert_matches!( assert_matches!(
MapData::create(new_obj_map(), "foo", None), ElfMapData::create(new_obj_map(), "foo", None),
Ok(MapData { Ok(ElfMapData {
obj: _, obj: _,
fd, fd,
}) => assert_eq!(fd.as_fd().as_raw_fd(), 42) }) => assert_eq!(fd.as_fd().as_raw_fd(), 42)
@ -1135,8 +1153,9 @@ mod tests {
_ => Err((-1, io::Error::from_raw_os_error(EFAULT))), _ => Err((-1, io::Error::from_raw_os_error(EFAULT))),
}); });
let map_data = MapData::create(new_obj_map(), TEST_NAME, None).unwrap(); let map_data = ElfMapData::create(new_obj_map(), TEST_NAME, None).unwrap();
assert_eq!(TEST_NAME, map_data.info().unwrap().name_as_str().unwrap()); let info = MapInfo::new_from_fd(map_data.fd.as_fd()).unwrap();
assert_eq!(TEST_NAME, info.name_as_str().unwrap());
} }
#[test] #[test]
@ -1199,7 +1218,7 @@ mod tests {
override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT))));
assert_matches!( assert_matches!(
MapData::create(new_obj_map(), "foo", None), ElfMapData::create(new_obj_map(), "foo", None),
Err(MapError::CreateError { name, code, io_error }) => { Err(MapError::CreateError { name, code, io_error }) => {
assert_eq!(name, "foo"); assert_eq!(name, "foo");
assert_eq!(code, -42); assert_eq!(code, -42);

@ -49,7 +49,7 @@ impl<T: Borrow<MapData>, V: Pod> Queue<T, V> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn capacity(&self) -> u32 { pub fn capacity(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
} }

@ -103,7 +103,7 @@ impl<T: Borrow<MapData>> RingBuf<T> {
let data: &MapData = map.borrow(); let data: &MapData = map.borrow();
let page_size = page_size(); let page_size = page_size();
let map_fd = data.fd().as_fd(); let map_fd = data.fd().as_fd();
let byte_size = data.obj.max_entries(); let byte_size = data.def.max_entries();
let consumer_metadata = ConsumerMetadata::new(map_fd, 0, page_size)?; let consumer_metadata = ConsumerMetadata::new(map_fd, 0, page_size)?;
let consumer = ConsumerPos::new(consumer_metadata); let consumer = ConsumerPos::new(consumer_metadata);
let producer = ProducerData::new(map_fd, page_size, page_size, byte_size)?; let producer = ProducerData::new(map_fd, page_size, page_size, byte_size)?;

@ -49,7 +49,7 @@ impl<T: Borrow<MapData>, V: Pod> Stack<T, V> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn capacity(&self) -> u32 { pub fn capacity(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
} }

@ -81,7 +81,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
pub(crate) fn new(map: T) -> Result<Self, MapError> { pub(crate) fn new(map: T) -> Result<Self, MapError> {
let data = map.borrow(); let data = map.borrow();
let expected = mem::size_of::<u32>(); let expected = mem::size_of::<u32>();
let size = data.obj.key_size() as usize; let size = data.def.key_size() as usize;
if size != expected { if size != expected {
return Err(MapError::InvalidKeySize { size, expected }); return Err(MapError::InvalidKeySize { size, expected });
} }
@ -91,7 +91,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
call: "sysctl", call: "sysctl",
io_error, io_error,
})?; })?;
let size = data.obj.value_size() as usize; let size = data.def.value_size() as usize;
if size > max_stack_depth * mem::size_of::<u64>() { if size > max_stack_depth * mem::size_of::<u64>() {
return Err(MapError::InvalidValueSize { size, expected }); return Err(MapError::InvalidValueSize { size, expected });
} }

@ -70,7 +70,7 @@ impl<T: Borrow<MapData>> CpuMap<T> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
/// Returns the queue size and optional program for a given CPU index. /// Returns the queue size and optional program for a given CPU index.

@ -62,7 +62,7 @@ impl<T: Borrow<MapData>> DevMap<T> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
/// Returns the target interface index and optional program at a given index. /// Returns the target interface index and optional program at a given index.

@ -51,7 +51,7 @@ impl<T: Borrow<MapData>> XskMap<T> {
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.borrow().obj.max_entries() self.inner.borrow().def.max_entries()
} }
} }

@ -20,7 +20,7 @@ use crate::{
bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_map_info, bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_map_info,
bpf_map_type, bpf_prog_info, bpf_prog_type, BPF_F_REPLACE, bpf_map_type, bpf_prog_info, bpf_prog_type, BPF_F_REPLACE,
}, },
maps::{MapData, PerCpuValues}, maps::{ElfMapData, PerCpuValues},
obj::{ obj::{
self, self,
btf::{ btf::{
@ -75,8 +75,8 @@ pub(crate) fn bpf_create_map(
u.btf_fd = 0; u.btf_fd = 0;
} }
_ => { _ => {
u.btf_key_type_id = m.def.btf_key_type_id.unwrap_or_default(); u.btf_key_type_id = m.def.btf_key_type_id().unwrap_or_default();
u.btf_value_type_id = m.def.btf_value_type_id.unwrap_or_default(); u.btf_value_type_id = m.def.btf_value_type_id().unwrap_or_default();
u.btf_fd = btf_fd.map(|fd| fd.as_raw_fd()).unwrap_or_default() as u32; u.btf_fd = btf_fd.map(|fd| fd.as_raw_fd()).unwrap_or_default() as u32;
} }
} }
@ -756,7 +756,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
let mut insns = copy_instructions(prog).unwrap(); let mut insns = copy_instructions(prog).unwrap();
let map = MapData::create( let map = ElfMapData::create(
obj::Map::Legacy(LegacyMap { obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: bpf_map_type::BPF_MAP_TYPE_ARRAY as u32, map_type: bpf_map_type::BPF_MAP_TYPE_ARRAY as u32,
@ -776,7 +776,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
); );
if let Ok(map) = map { if let Ok(map) = map {
insns[0].imm = map.fd().as_fd().as_raw_fd(); insns[0].imm = map.fd.as_fd().as_raw_fd();
let gpl = b"GPL\0"; let gpl = b"GPL\0";
u.license = gpl.as_ptr() as u64; u.license = gpl.as_ptr() as u64;

Loading…
Cancel
Save