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; 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 {
@ -65,17 +65,92 @@ impl TryFrom<u32> for crate::generated::bpf_map_type {
/// BTF definition of a map /// BTF definition of a map
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct BtfMapDef { pub struct MapDef {
pub(crate) map_type: u32, pub(crate) map_type: u32,
pub(crate) key_size: u32, pub(crate) key_size: u32,
pub(crate) value_size: u32, pub(crate) value_size: u32,
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: 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: 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 /// The pinning type
@ -266,7 +341,7 @@ impl Map {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LegacyMap { pub struct LegacyMap {
/// The definition of the map /// The definition of the map
pub def: bpf_map_def, pub def: MapDef,
/// The section index /// The section index
pub section_index: usize, pub section_index: usize,
/// The section kind /// The section kind
@ -285,7 +360,7 @@ pub struct LegacyMap {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BtfMap { pub struct BtfMap {
/// The definition of the map /// The definition of the map
pub def: BtfMapDef, pub def: MapDef,
pub(crate) section_index: usize, pub(crate) section_index: usize,
pub(crate) symbol_index: usize, pub(crate) symbol_index: usize,
pub(crate) data: Vec<u8>, pub(crate) data: Vec<u8>,

@ -23,10 +23,9 @@ 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, BtfMapDef, LegacyMap, Map, PinningType, MINIMUM_MAP_SIZE}, maps::{bpf_map_def, BtfMap, LegacyMap, Map, MapDef, PinningType, MINIMUM_MAP_SIZE},
programs::{ programs::{
CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType, XdpAttachType, CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType, XdpAttachType,
}, },
@ -794,14 +793,14 @@ impl Object {
.name .name
.as_ref() .as_ref()
.ok_or(ParseError::MapSymbolNameNotFound { i: *i })?; .ok_or(ParseError::MapSymbolNameNotFound { i: *i })?;
let def = parse_map_def(name, data)?; let def = parse_legacy_map_def(name, data)?;
maps.insert( maps.insert(
name.to_string(), name.to_string(),
Map::Legacy(LegacyMap { Map::Legacy(LegacyMap {
section_index: section.index.0, section_index: section.index.0,
section_kind: section.kind, section_kind: section.kind,
symbol_index: Some(sym.index), symbol_index: Some(sym.index),
def, def: def.into(),
data: Vec::new(), data: Vec::new(),
}), }),
); );
@ -1192,12 +1191,12 @@ fn parse_data_map_section(section: &Section) -> Result<Map, ParseError> {
section_kind: section.kind, section_kind: section.kind,
// Data maps don't require symbols to be relocated // Data maps don't require symbols to be relocated
symbol_index: None, symbol_index: None,
def, def: def.into(),
data, 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 { if data.len() < MINIMUM_MAP_SIZE {
return Err(ParseError::InvalidMapDefinition { return Err(ParseError::InvalidMapDefinition {
name: name.to_owned(), 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)? { let ty = match btf.type_by_id(info.btf_type)? {
BtfType::Var(var) => var, BtfType::Var(var) => var,
other => { 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 map_name = btf.string_at(ty.name_offset)?;
let mut map_def = BtfMapDef::default(); let mut map_def = MapDef::default();
// Safety: union // Safety: union
let root_type = btf.resolve_type(ty.btf_type)?; 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 // Safety: union
let t = pty.btf_type; let t = pty.btf_type;
map_def.key_size = btf.type_size(t)? as u32; 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 { } else {
return Err(BtfError::UnexpectedBtfType { return Err(BtfError::UnexpectedBtfType {
type_id: m.btf_type, 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)? { if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
let t = pty.btf_type; let t = pty.btf_type;
map_def.value_size = btf.type_size(t)? as u32; 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 { } else {
return Err(BtfError::UnexpectedBtfType { return Err(BtfError::UnexpectedBtfType {
type_id: m.btf_type, 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)) 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 /// 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 {
@ -1502,7 +1464,7 @@ mod tests {
#[test] #[test]
fn test_parse_map_def_error() { fn test_parse_map_def_error() {
assert_matches!( assert_matches!(
parse_map_def("foo", &[]), parse_legacy_map_def("foo", &[]),
Err(ParseError::InvalidMapDefinition { .. }) Err(ParseError::InvalidMapDefinition { .. })
); );
} }
@ -1520,7 +1482,7 @@ mod tests {
}; };
assert_eq!( 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 def
); );
} }
@ -1537,7 +1499,7 @@ mod tests {
pinning: PinningType::ByName, 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] #[test]
@ -1554,7 +1516,7 @@ mod tests {
let mut buf = [0u8; 128]; let mut buf = [0u8; 128];
unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, def) }; 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] #[test]
@ -1573,14 +1535,16 @@ mod tests {
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Data, section_kind: EbpfSectionKind::Data,
symbol_index: None, symbol_index: None,
def: bpf_map_def { def: MapDef {
map_type: _map_type, map_type: _map_type,
key_size: 4, key_size: 4,
value_size, value_size,
max_entries: 1, max_entries: 1,
map_flags: 0, map_flags: 0,
id: 0,
pinning: PinningType::None, pinning: PinningType::None,
id: None,
btf_key_type_id: None,
btf_value_type_id: None,
}, },
data, data,
})) if data == map_data && value_size == map_data.len() as u32 })) 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, 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, 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); 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, map_type: 1,
key_size: 2, key_size: 2,
value_size: 3, value_size: 3,
@ -1763,7 +1727,7 @@ mod tests {
map_flags: 5, map_flags: 5,
..Default::default() ..Default::default()
}; };
let map_data = bytes_of(def).to_vec(); let map_data = bytes_of(&def).to_vec();
let mut buf = vec![]; let mut buf = vec![];
buf.extend(&map_data); buf.extend(&map_data);
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("foo"));
assert!(obj.maps.contains_key("bar")); assert!(obj.maps.contains_key("bar"));
assert!(obj.maps.contains_key("baz")); assert!(obj.maps.contains_key("baz"));
let def = MapDef::from(def);
for map in obj.maps.values() { for map in obj.maps.values() {
assert_matches!(map, Map::Legacy(m) => { 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, map_flags: BPF_F_RDONLY_PROG,
id: 1, id: 1,
pinning: PinningType::None, pinning: PinningType::None,
}, }
.into(),
section_index: 1, section_index: 1,
section_kind: EbpfSectionKind::Rodata, section_kind: EbpfSectionKind::Rodata,
symbol_index: Some(1), symbol_index: Some(1),

@ -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},
}; };
@ -104,7 +104,8 @@ mod tests {
value_size: 4, value_size: 4,
max_entries: 1024, max_entries: 1024,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
symbol_index: None, symbol_index: None,
@ -120,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> {
@ -148,7 +149,8 @@ mod tests {
value_size: 4, value_size: 4,
max_entries: 1024, max_entries: 1024,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
symbol_index: None, symbol_index: None,

@ -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 {
@ -73,7 +73,8 @@ mod test_utils {
value_size: 4, value_size: 4,
max_entries: 1024, max_entries: 1024,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
data: Vec::new(), data: Vec::new(),

@ -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},
}; };
@ -221,7 +221,8 @@ mod tests {
value_size: 4, value_size: 4,
max_entries: 1024, max_entries: 1024,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
symbol_index: None, symbol_index: None,
@ -237,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> {
@ -277,7 +278,8 @@ mod tests {
value_size: 4, value_size: 4,
max_entries: 1024, max_entries: 1024,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
symbol_index: None, symbol_index: None,

@ -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
@ -1043,7 +1061,8 @@ mod tests {
value_size: 4, value_size: 4,
max_entries: 1024, max_entries: 1024,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
symbol_index: Some(0), symbol_index: Some(0),
@ -1077,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)
); );
@ -1094,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)
@ -1134,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]
@ -1198,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; 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; 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,
@ -764,7 +764,8 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
value_size: 32, value_size: 32,
max_entries: 1, max_entries: 1,
..Default::default() ..Default::default()
}, }
.into(),
section_index: 0, section_index: 0,
section_kind: EbpfSectionKind::Maps, section_kind: EbpfSectionKind::Maps,
symbol_index: None, symbol_index: None,
@ -775,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