Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API to create maps at runtime #935

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aya-obj/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
87 changes: 81 additions & 6 deletions aya-obj/src/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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>,
Expand Down
82 changes: 24 additions & 58 deletions aya-obj/src/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down Expand Up @@ -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(),
}),
);
Expand Down Expand Up @@ -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(),
Expand All @@ -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 => {
Expand All @@ -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)?;
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 { .. })
);
}
Expand All @@ -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
);
}
Expand All @@ -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]
Expand All @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -1755,15 +1719,15 @@ 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,
max_entries: 4,
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);
Expand All @@ -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);
})
}
}
Expand Down Expand Up @@ -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),
Expand Down
Loading
Loading