pull/935/merge
Alessandro Decina 1 year ago committed by GitHub
commit ac09b62b85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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.

@ -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<u32> 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<u32>,
/// BTF type id of the map key
pub btf_key_type_id: u32,
pub(crate) btf_key_type_id: Option<u32>,
/// BTF type id of the map value
pub btf_value_type_id: u32,
pub(crate) btf_value_type_id: Option<u32>,
}
impl From<bpf_map_def> 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<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
@ -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<u8>,

@ -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<Map, ParseError> {
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<bpf_map_def, ParseError> {
fn parse_legacy_map_def(name: &str, data: &[u8]) -> Result<bpf_map_def, ParseError> {
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<bpf_map_def, ParseError> {
}
}
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<Vec<bpf_insn>, ParseError> {
if data.len() % mem::size_of::<bpf_insn>() > 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::<bpf_map_def>() as u64);
fake_sym(&mut obj, 0, 28, "bar", mem::size_of::<bpf_map_def>() as u64);
fake_sym(&mut obj, 0, 60, "baz", mem::size_of::<bpf_map_def>() 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),

@ -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::<Result<HashMap<String, Map>, 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),

@ -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.
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.

@ -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.
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.

@ -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<c_long> {
@ -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,

@ -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(),

@ -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<c_long> {
@ -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,

@ -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<K, V>(map: &MapData) -> Result<(), MapError> {
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 {
return Err(MapError::InvalidKeySize { size, expected });
}
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 {
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> {
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 {
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<BorrowedFd<'_>>,
@ -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<P: AsRef<Path>>(path: P) -> Result<Self, MapError> {
use std::os::unix::ffi::OsStrExt as _;
@ -657,7 +668,7 @@ impl MapData {
pub fn from_fd(fd: OwnedFd) -> Result<Self, MapError> {
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<dyn std::error::Error>>(())
/// ```
pub fn pin<P: AsRef<Path>>(&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, MapError> {
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
pub trait IterableMap<K: Pod, V> {
/// 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);

@ -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.
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 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)?;

@ -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.
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> {
let data = map.borrow();
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 {
return Err(MapError::InvalidKeySize { size, expected });
}
@ -91,7 +91,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
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::<u64>() {
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.
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.

@ -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.
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.

@ -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.
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_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;

Loading…
Cancel
Save