diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index ea0e56702..27c0df99d 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -93,7 +93,7 @@ pub mod programs; pub mod relocation; mod util; -pub use maps::Map; +pub use maps::{Map, MapDef}; pub use obj::*; /// An error returned from the verifier. diff --git a/aya-obj/src/maps.rs b/aya-obj/src/maps.rs index ca85bba7f..1ca737e96 100644 --- a/aya-obj/src/maps.rs +++ b/aya-obj/src/maps.rs @@ -5,7 +5,7 @@ use core::mem; #[cfg(not(feature = "std"))] use crate::std; -use crate::EbpfSectionKind; +use crate::{generated::bpf_map_info, EbpfSectionKind}; /// Invalid map type encontered pub struct InvalidMapTypeError { @@ -65,17 +65,92 @@ impl TryFrom for crate::generated::bpf_map_type { /// BTF definition of a map #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] -pub struct BtfMapDef { +pub struct MapDef { 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(crate) id: Option, /// BTF type id of the map key - pub btf_key_type_id: u32, + pub(crate) btf_key_type_id: Option, /// BTF type id of the map value - pub btf_value_type_id: u32, + pub(crate) btf_value_type_id: Option, +} + +impl From for MapDef { + fn from(def: bpf_map_def) -> Self { + Self { + map_type: def.map_type, + key_size: def.key_size, + value_size: def.value_size, + max_entries: def.max_entries, + map_flags: def.map_flags, + pinning: def.pinning, + id: Option::from(def.id).filter(|id| *id != 0), + btf_key_type_id: None, + btf_value_type_id: None, + } + } +} + +impl From 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 { + self.btf_key_type_id + } + + /// Returns the BTF type id of the map value + pub fn btf_value_type_id(&self) -> Option { + self.btf_value_type_id + } } /// The pinning type @@ -266,7 +341,7 @@ impl Map { #[derive(Debug, Clone)] pub struct LegacyMap { /// The definition of the map - pub def: bpf_map_def, + pub def: MapDef, /// The section index pub section_index: usize, /// The section kind @@ -285,7 +360,7 @@ pub struct LegacyMap { #[derive(Debug, Clone)] pub struct BtfMap { /// The definition of the map - pub def: BtfMapDef, + pub def: MapDef, pub(crate) section_index: usize, pub(crate) symbol_index: usize, pub(crate) data: Vec, diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index f6f4fc8b5..7b9695df8 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -23,10 +23,9 @@ use crate::{ Array, Btf, BtfError, BtfExt, BtfFeatures, BtfType, DataSecEntry, FuncSecInfo, LineSecInfo, }, generated::{ - bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_CALL, BPF_F_RDONLY_PROG, - BPF_JMP, BPF_K, + bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_CALL, BPF_F_RDONLY_PROG, BPF_JMP, BPF_K, }, - maps::{bpf_map_def, BtfMap, BtfMapDef, LegacyMap, Map, PinningType, MINIMUM_MAP_SIZE}, + maps::{bpf_map_def, BtfMap, LegacyMap, Map, MapDef, PinningType, MINIMUM_MAP_SIZE}, programs::{ CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType, XdpAttachType, }, @@ -794,14 +793,14 @@ impl Object { .name .as_ref() .ok_or(ParseError::MapSymbolNameNotFound { i: *i })?; - let def = parse_map_def(name, data)?; + let def = parse_legacy_map_def(name, data)?; maps.insert( name.to_string(), Map::Legacy(LegacyMap { section_index: section.index.0, section_kind: section.kind, symbol_index: Some(sym.index), - def, + def: def.into(), data: Vec::new(), }), ); @@ -1192,12 +1191,12 @@ fn parse_data_map_section(section: &Section) -> Result { section_kind: section.kind, // Data maps don't require symbols to be relocated symbol_index: None, - def, + def: def.into(), data, })) } -fn parse_map_def(name: &str, data: &[u8]) -> Result { +fn parse_legacy_map_def(name: &str, data: &[u8]) -> Result { if data.len() < MINIMUM_MAP_SIZE { return Err(ParseError::InvalidMapDefinition { name: name.to_owned(), @@ -1217,7 +1216,7 @@ fn parse_map_def(name: &str, data: &[u8]) -> Result { } } -fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDef), BtfError> { +fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, MapDef), BtfError> { let ty = match btf.type_by_id(info.btf_type)? { BtfType::Var(var) => var, other => { @@ -1227,7 +1226,7 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe } }; let map_name = btf.string_at(ty.name_offset)?; - let mut map_def = BtfMapDef::default(); + let mut map_def = MapDef::default(); // Safety: union let root_type = btf.resolve_type(ty.btf_type)?; @@ -1250,7 +1249,7 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe // Safety: union let t = pty.btf_type; map_def.key_size = btf.type_size(t)? as u32; - map_def.btf_key_type_id = t; + map_def.btf_key_type_id = Some(t); } else { return Err(BtfError::UnexpectedBtfType { type_id: m.btf_type, @@ -1264,7 +1263,7 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? { let t = pty.btf_type; map_def.value_size = btf.type_size(t)? as u32; - map_def.btf_value_type_id = t; + map_def.btf_value_type_id = Some(t); } else { return Err(BtfError::UnexpectedBtfType { type_id: m.btf_type, @@ -1296,43 +1295,6 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe 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: BtfMapDef { - 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: info.btf_key_type_id, - btf_value_type_id: 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, - }, - section_index: 0, - symbol_index: None, - section_kind: EbpfSectionKind::Undefined, - data: Vec::new(), - }) - } -} - /// Copies a block of eBPF instructions pub fn copy_instructions(data: &[u8]) -> Result, ParseError> { if data.len() % mem::size_of::() > 0 { @@ -1502,7 +1464,7 @@ mod tests { #[test] fn test_parse_map_def_error() { assert_matches!( - parse_map_def("foo", &[]), + parse_legacy_map_def("foo", &[]), Err(ParseError::InvalidMapDefinition { .. }) ); } @@ -1520,7 +1482,7 @@ mod tests { }; assert_eq!( - parse_map_def("foo", &bytes_of(&def)[..MINIMUM_MAP_SIZE]).unwrap(), + parse_legacy_map_def("foo", &bytes_of(&def)[..MINIMUM_MAP_SIZE]).unwrap(), def ); } @@ -1537,7 +1499,7 @@ mod tests { pinning: PinningType::ByName, }; - assert_eq!(parse_map_def("foo", bytes_of(&def)).unwrap(), def); + assert_eq!(parse_legacy_map_def("foo", bytes_of(&def)).unwrap(), def); } #[test] @@ -1554,7 +1516,7 @@ mod tests { let mut buf = [0u8; 128]; unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, def) }; - assert_eq!(parse_map_def("foo", &buf).unwrap(), def); + assert_eq!(parse_legacy_map_def("foo", &buf).unwrap(), def); } #[test] @@ -1573,14 +1535,16 @@ mod tests { section_index: 0, section_kind: EbpfSectionKind::Data, symbol_index: None, - def: bpf_map_def { + def: MapDef { map_type: _map_type, key_size: 4, value_size, max_entries: 1, map_flags: 0, - id: 0, pinning: PinningType::None, + id: None, + btf_key_type_id: None, + btf_value_type_id: None, }, data, })) if data == map_data && value_size == map_data.len() as u32 @@ -1755,7 +1719,7 @@ mod tests { fake_sym(&mut obj, 0, 0, "foo", mem::size_of::() as u64); fake_sym(&mut obj, 0, 28, "bar", mem::size_of::() as u64); fake_sym(&mut obj, 0, 60, "baz", mem::size_of::() as u64); - let def = &bpf_map_def { + let def = bpf_map_def { map_type: 1, key_size: 2, value_size: 3, @@ -1763,7 +1727,7 @@ mod tests { map_flags: 5, ..Default::default() }; - let map_data = bytes_of(def).to_vec(); + let map_data = bytes_of(&def).to_vec(); let mut buf = vec![]; buf.extend(&map_data); buf.extend(&map_data); @@ -1782,9 +1746,10 @@ mod tests { assert!(obj.maps.contains_key("foo")); assert!(obj.maps.contains_key("bar")); assert!(obj.maps.contains_key("baz")); + let def = MapDef::from(def); for map in obj.maps.values() { assert_matches!(map, Map::Legacy(m) => { - assert_eq!(&m.def, def); + assert_eq!(m.def, def); }) } } @@ -2549,7 +2514,8 @@ mod tests { map_flags: BPF_F_RDONLY_PROG, id: 1, pinning: PinningType::None, - }, + } + .into(), section_index: 1, section_kind: EbpfSectionKind::Rodata, symbol_index: Some(1), diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 42a9a4899..92f2c0a9b 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -21,10 +21,10 @@ use thiserror::Error; use crate::{ generated::{ - bpf_map_type, bpf_map_type::*, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, - AYA_PERF_EVENT_IOC_SET_BPF, + bpf_map_type::{self, *}, + 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::{ btf::{Btf, BtfError}, Object, ParseError, ProgramSection, @@ -494,7 +494,7 @@ impl<'a> EbpfLoader<'a> { } let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); let mut map = match obj.pinning() { - PinningType::None => MapData::create(obj, &name, btf_fd)?, + PinningType::None => ElfMapData::create(obj, &name, btf_fd)?, PinningType::ByName => { // 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. @@ -502,7 +502,7 @@ impl<'a> EbpfLoader<'a> { .as_deref() .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()?; @@ -517,7 +517,7 @@ impl<'a> EbpfLoader<'a> { obj.relocate_maps( 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, )?; obj.relocate_calls(&text_sections)?; @@ -697,13 +697,14 @@ impl<'a> EbpfLoader<'a> { .collect(); let maps = maps .drain() + .map(|(name, elf_map)| (name, elf_map.into())) .map(parse_map) .collect::, EbpfError>>()?; if !*allow_unsupported_maps { maps.iter().try_for_each(|(_, x)| match x { Map::Unsupported(map) => Err(EbpfError::MapError(MapError::Unsupported { - map_type: map.obj().map_type(), + map_type: map.def.map_type(), })), _ => Ok(()), })?; @@ -715,7 +716,7 @@ impl<'a> EbpfLoader<'a> { fn parse_map(data: (String, MapData)) -> Result<(String, Map), EbpfError> { 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 { BPF_MAP_TYPE_ARRAY => Map::Array(map), BPF_MAP_TYPE_PERCPU_ARRAY => Map::PerCpuArray(map), diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 8ca907f54..093a56a52 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -50,7 +50,7 @@ impl, V: Pod> Array { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. 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. diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index 5238da735..43cd81ccb 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -69,7 +69,7 @@ impl, V: Pod> PerCpuArray { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. 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. diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index 817c785c4..adac19bc7 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -91,7 +91,7 @@ mod tests { bpf_cmd, bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY}, }, - maps::Map, + maps::{ElfMapData, Map}, obj::{self, maps::LegacyMap, EbpfSectionKind}, sys::{override_syscall, SysResult, Syscall}, }; @@ -104,7 +104,8 @@ mod tests { value_size: 4, max_entries: 1024, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, symbol_index: None, @@ -120,7 +121,7 @@ mod tests { } => Ok(1337), call => panic!("unexpected syscall {:?}", call), }); - MapData::create(obj, "foo", None).unwrap() + ElfMapData::create(obj, "foo", None).unwrap().into() } fn sys_error(value: i32) -> SysResult { @@ -148,7 +149,8 @@ mod tests { value_size: 4, max_entries: 1024, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, symbol_index: None, diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index 93f345bde..d214227cf 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -49,7 +49,7 @@ mod test_utils { use crate::{ bpf_map_def, generated::{bpf_cmd, bpf_map_type}, - maps::MapData, + maps::{ElfMapData, MapData}, obj::{self, maps::LegacyMap, EbpfSectionKind}, sys::{override_syscall, Syscall}, }; @@ -62,7 +62,7 @@ mod test_utils { } => Ok(1337), 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 { @@ -73,7 +73,8 @@ mod test_utils { value_size: 4, max_entries: 1024, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, data: Vec::new(), diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index c3dd528a8..aa1db973c 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -208,7 +208,7 @@ mod tests { bpf_cmd, bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY}, }, - maps::Map, + maps::{ElfMapData, Map}, obj::{self, maps::LegacyMap, EbpfSectionKind}, sys::{override_syscall, SysResult, Syscall}, }; @@ -221,7 +221,8 @@ mod tests { value_size: 4, max_entries: 1024, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, symbol_index: None, @@ -237,7 +238,7 @@ mod tests { } => Ok(1337), call => panic!("unexpected syscall {:?}", call), }); - MapData::create(obj, "foo", None).unwrap() + ElfMapData::create(obj, "foo", None).unwrap().into() } fn sys_error(value: i32) -> SysResult { @@ -277,7 +278,8 @@ mod tests { value_size: 4, max_entries: 1024, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, symbol_index: None, diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 7c1d2a842..1d1f8e746 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -54,7 +54,10 @@ use std::{ marker::PhantomData, mem, ops::Deref, - os::fd::{AsFd, BorrowedFd, OwnedFd}, + os::{ + fd::{AsFd, BorrowedFd, OwnedFd}, + unix::ffi::OsStrExt as _, + }, path::Path, ptr, }; @@ -66,7 +69,7 @@ use thiserror::Error; use crate::{ generated::bpf_map_info, - obj::{self, parse_map_info, EbpfSectionKind}, + obj::{self, EbpfSectionKind}, pin::PinError, sys::{ 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, }, util::{bytes_of_bpf_name, nr_cpus, KernelVersion}, - PinningType, Pod, + Pod, }; pub mod array; @@ -304,27 +307,27 @@ impl Map { /// Returns the low level map type. fn map_type(&self) -> u32 { match self { - Self::Array(map) => map.obj.map_type(), - Self::BloomFilter(map) => map.obj.map_type(), - Self::CpuMap(map) => map.obj.map_type(), - Self::DevMap(map) => map.obj.map_type(), - Self::DevMapHash(map) => map.obj.map_type(), - Self::HashMap(map) => map.obj.map_type(), - Self::LpmTrie(map) => map.obj.map_type(), - Self::LruHashMap(map) => map.obj.map_type(), - Self::PerCpuArray(map) => map.obj.map_type(), - Self::PerCpuHashMap(map) => map.obj.map_type(), - Self::PerCpuLruHashMap(map) => map.obj.map_type(), - Self::PerfEventArray(map) => map.obj.map_type(), - Self::ProgramArray(map) => map.obj.map_type(), - Self::Queue(map) => map.obj.map_type(), - Self::RingBuf(map) => map.obj.map_type(), - Self::SockHash(map) => map.obj.map_type(), - Self::SockMap(map) => map.obj.map_type(), - Self::Stack(map) => map.obj.map_type(), - Self::StackTraceMap(map) => map.obj.map_type(), - Self::Unsupported(map) => map.obj.map_type(), - Self::XskMap(map) => map.obj.map_type(), + Self::Array(map) => map.def.map_type(), + Self::BloomFilter(map) => map.def.map_type(), + Self::CpuMap(map) => map.def.map_type(), + Self::DevMap(map) => map.def.map_type(), + Self::DevMapHash(map) => map.def.map_type(), + Self::HashMap(map) => map.def.map_type(), + Self::LpmTrie(map) => map.def.map_type(), + Self::LruHashMap(map) => map.def.map_type(), + Self::PerCpuArray(map) => map.def.map_type(), + Self::PerCpuHashMap(map) => map.def.map_type(), + Self::PerCpuLruHashMap(map) => map.def.map_type(), + Self::PerfEventArray(map) => map.def.map_type(), + Self::ProgramArray(map) => map.def.map_type(), + Self::Queue(map) => map.def.map_type(), + Self::RingBuf(map) => map.def.map_type(), + Self::SockHash(map) => map.def.map_type(), + Self::SockMap(map) => map.def.map_type(), + Self::Stack(map) => map.def.map_type(), + Self::StackTraceMap(map) => map.def.map_type(), + Self::Unsupported(map) => map.def.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> { - let max_entries = map.obj.max_entries(); + let max_entries = map.def.max_entries(); if index >= max_entries { Err(MapError::OutOfBounds { index, max_entries }) } else { @@ -503,12 +506,12 @@ pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> { pub(crate) fn check_kv_size(map: &MapData) -> Result<(), MapError> { let size = mem::size_of::(); - let expected = map.obj.key_size() as usize; + let expected = map.def.key_size() as usize; if size != expected { return Err(MapError::InvalidKeySize { size, expected }); } let size = mem::size_of::(); - let expected = map.obj.value_size() as usize; + let expected = map.def.value_size() as usize; if size != expected { return Err(MapError::InvalidValueSize { size, expected }); }; @@ -517,25 +520,22 @@ pub(crate) fn check_kv_size(map: &MapData) -> Result<(), MapError> { pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { let size = mem::size_of::(); - let expected = map.obj.value_size() as usize; + let expected = map.def.value_size() as usize; if size != expected { return Err(MapError::InvalidValueSize { size, expected }); }; 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 { - obj: obj::Map, - fd: MapFd, +pub(crate) struct ElfMapData { + pub(crate) obj: obj::Map, + pub(crate) fd: MapFd, } -impl MapData { +impl ElfMapData { /// Creates a new map with the provided `name` - pub fn create( + pub(crate) fn create( obj: obj::Map, name: &str, btf_fd: Option>, @@ -591,7 +591,7 @@ impl MapData { } Err(_) => { 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()), error, })?; @@ -620,7 +620,18 @@ impl MapData { } 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. pub fn from_pin>(path: P) -> Result { use std::os::unix::ffi::OsStrExt as _; @@ -657,7 +668,7 @@ impl MapData { pub fn from_fd(fd: OwnedFd) -> Result { let MapInfo(info) = MapInfo::new_from_fd(fd.as_fd())?; Ok(Self { - obj: parse_map_info(info, PinningType::None), + def: info.into(), fd: MapFd(fd), }) } @@ -687,40 +698,47 @@ impl MapData { /// # Ok::<(), Box>(()) /// ``` pub fn pin>(&self, path: P) -> Result<(), PinError> { - use std::os::unix::ffi::OsStrExt as _; - - 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(()) + let Self { fd, def: _ } = self; + pin_map(fd, path) } /// Returns the file descriptor of the map. pub fn fd(&self) -> &MapFd { - let Self { obj: _, fd } = self; + let Self { def: _, fd } = self; fd } - pub(crate) fn obj(&self) -> &obj::Map { - let Self { obj, fd: _ } = self; - obj - } - /// Returns the kernel's information about the loaded map. pub fn info(&self) -> Result { MapInfo::new_from_fd(self.fd.as_fd()) } } +impl From 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) -> 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 pub trait IterableMap { /// Get a generic map handle @@ -1043,7 +1061,8 @@ mod tests { value_size: 4, max_entries: 1024, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, symbol_index: Some(0), @@ -1077,7 +1096,7 @@ mod tests { assert_matches!( MapData::from_id(1234), Ok(MapData { - obj: _, + def: _, fd, }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) ); @@ -1094,8 +1113,8 @@ mod tests { }); assert_matches!( - MapData::create(new_obj_map(), "foo", None), - Ok(MapData { + ElfMapData::create(new_obj_map(), "foo", None), + Ok(ElfMapData { obj: _, fd, }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) @@ -1134,8 +1153,9 @@ mod tests { _ => Err((-1, io::Error::from_raw_os_error(EFAULT))), }); - let map_data = MapData::create(new_obj_map(), TEST_NAME, None).unwrap(); - assert_eq!(TEST_NAME, map_data.info().unwrap().name_as_str().unwrap()); + let map_data = ElfMapData::create(new_obj_map(), TEST_NAME, None).unwrap(); + let info = MapInfo::new_from_fd(map_data.fd.as_fd()).unwrap(); + assert_eq!(TEST_NAME, info.name_as_str().unwrap()); } #[test] @@ -1198,7 +1218,7 @@ mod tests { override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); assert_matches!( - MapData::create(new_obj_map(), "foo", None), + ElfMapData::create(new_obj_map(), "foo", None), Err(MapError::CreateError { name, code, io_error }) => { assert_eq!(name, "foo"); assert_eq!(code, -42); diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index 9c3425255..53a8d9ad3 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -49,7 +49,7 @@ impl, V: Pod> Queue { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. pub fn capacity(&self) -> u32 { - self.inner.borrow().obj.max_entries() + self.inner.borrow().def.max_entries() } } diff --git a/aya/src/maps/ring_buf.rs b/aya/src/maps/ring_buf.rs index e4cb3cb43..103e7903e 100644 --- a/aya/src/maps/ring_buf.rs +++ b/aya/src/maps/ring_buf.rs @@ -103,7 +103,7 @@ impl> RingBuf { let data: &MapData = map.borrow(); let page_size = page_size(); 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 = ConsumerPos::new(consumer_metadata); let producer = ProducerData::new(map_fd, page_size, page_size, byte_size)?; diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index 8a7b94bd9..51019845b 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -49,7 +49,7 @@ impl, V: Pod> Stack { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. pub fn capacity(&self) -> u32 { - self.inner.borrow().obj.max_entries() + self.inner.borrow().def.max_entries() } } diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index 74b85b660..c6f2363b9 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -81,7 +81,7 @@ impl> StackTraceMap { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); let expected = mem::size_of::(); - let size = data.obj.key_size() as usize; + let size = data.def.key_size() as usize; if size != expected { return Err(MapError::InvalidKeySize { size, expected }); } @@ -91,7 +91,7 @@ impl> StackTraceMap { call: "sysctl", 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::() { return Err(MapError::InvalidValueSize { size, expected }); } diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index b5c0727c6..20d1f9fe9 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -70,7 +70,7 @@ impl> CpuMap { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. 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. diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index 44062df55..151e0cac6 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -62,7 +62,7 @@ impl> DevMap { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. 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. diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs index 95c593cc3..38d813090 100644 --- a/aya/src/maps/xdp/xsk_map.rs +++ b/aya/src/maps/xdp/xsk_map.rs @@ -51,7 +51,7 @@ impl> XskMap { /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. pub fn len(&self) -> u32 { - self.inner.borrow().obj.max_entries() + self.inner.borrow().def.max_entries() } } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index f1a6d9168..8eba9c905 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -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_map_type, bpf_prog_info, bpf_prog_type, BPF_F_REPLACE, }, - maps::{MapData, PerCpuValues}, + maps::{ElfMapData, PerCpuValues}, obj::{ self, btf::{ @@ -75,8 +75,8 @@ pub(crate) fn bpf_create_map( u.btf_fd = 0; } _ => { - u.btf_key_type_id = m.def.btf_key_type_id; - u.btf_value_type_id = m.def.btf_value_type_id; + 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_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 map = MapData::create( + let map = ElfMapData::create( obj::Map::Legacy(LegacyMap { def: bpf_map_def { map_type: bpf_map_type::BPF_MAP_TYPE_ARRAY as u32, @@ -764,7 +764,8 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { value_size: 32, max_entries: 1, ..Default::default() - }, + } + .into(), section_index: 0, section_kind: EbpfSectionKind::Maps, symbol_index: None, @@ -775,7 +776,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { ); 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"; u.license = gpl.as_ptr() as u64;