Merge pull request #758 from aya-rs/map-fd-not-option

aya: MapData::fd is non-optional
reviewable/pr761/r1
Tamir Duberstein 1 year ago committed by GitHub
commit 1d5f764d07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -73,15 +73,6 @@ pub enum RelocationError {
address: u64, address: u64,
}, },
/// Referenced map not created yet
#[error("the map `{name}` at section `{section_index}` has not been created")]
MapNotCreated {
/// The section index
section_index: usize,
/// The map name
name: String,
},
/// Invalid relocation offset /// Invalid relocation offset
#[error("invalid offset `{offset}` applying relocation #{relocation_number}")] #[error("invalid offset `{offset}` applying relocation #{relocation_number}")]
InvalidRelocationOffset { InvalidRelocationOffset {
@ -114,7 +105,7 @@ pub(crate) struct Symbol {
impl Object { impl Object {
/// Relocates the map references /// Relocates the map references
pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>( pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, i32, &'a Map)>>(
&mut self, &mut self,
maps: I, maps: I,
text_sections: &HashSet<usize>, text_sections: &HashSet<usize>,
@ -187,8 +178,8 @@ impl Object {
fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>( fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
fun: &mut Function, fun: &mut Function,
relocations: I, relocations: I,
maps_by_section: &HashMap<usize, (&str, Option<i32>, &Map)>, maps_by_section: &HashMap<usize, (&str, i32, &Map)>,
maps_by_symbol: &HashMap<usize, (&str, Option<i32>, &Map)>, maps_by_symbol: &HashMap<usize, (&str, i32, &Map)>,
symbol_table: &HashMap<usize, Symbol>, symbol_table: &HashMap<usize, Symbol>,
text_sections: &HashSet<usize>, text_sections: &HashSet<usize>,
) -> Result<(), RelocationError> { ) -> Result<(), RelocationError> {
@ -230,7 +221,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
continue; continue;
} }
let (name, fd, map) = if let Some(m) = maps_by_symbol.get(&rel.symbol_index) { let (_name, fd, map) = if let Some(m) = maps_by_symbol.get(&rel.symbol_index) {
let map = &m.2; let map = &m.2;
debug!( debug!(
"relocating map by symbol index {:?}, kind {:?} at insn {ins_index} in section {}", "relocating map by symbol index {:?}, kind {:?} at insn {ins_index} in section {}",
@ -266,18 +257,13 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
}; };
debug_assert_eq!(map.section_index(), section_index); debug_assert_eq!(map.section_index(), section_index);
let map_fd = fd.ok_or_else(|| RelocationError::MapNotCreated {
name: (*name).into(),
section_index,
})?;
if !map.data().is_empty() { if !map.data().is_empty() {
instructions[ins_index].set_src_reg(BPF_PSEUDO_MAP_VALUE as u8); instructions[ins_index].set_src_reg(BPF_PSEUDO_MAP_VALUE as u8);
instructions[ins_index + 1].imm = instructions[ins_index].imm + sym.address as i32; instructions[ins_index + 1].imm = instructions[ins_index].imm + sym.address as i32;
} else { } else {
instructions[ins_index].set_src_reg(BPF_PSEUDO_MAP_FD as u8); instructions[ins_index].set_src_reg(BPF_PSEUDO_MAP_FD as u8);
} }
instructions[ins_index].imm = map_fd; instructions[ins_index].imm = *fd;
} }
Ok(()) Ok(())
@ -588,7 +574,7 @@ mod test {
let maps_by_section = HashMap::new(); let maps_by_section = HashMap::new();
let map = fake_legacy_map(1); let map = fake_legacy_map(1);
let maps_by_symbol = HashMap::from([(1, ("test_map", Some(1), &map))]); let maps_by_symbol = HashMap::from([(1, ("test_map", 1, &map))]);
relocate_maps( relocate_maps(
&mut fun, &mut fun,
@ -642,8 +628,8 @@ mod test {
let map_1 = fake_legacy_map(1); let map_1 = fake_legacy_map(1);
let map_2 = fake_legacy_map(2); let map_2 = fake_legacy_map(2);
let maps_by_symbol = HashMap::from([ let maps_by_symbol = HashMap::from([
(1, ("test_map_1", Some(1), &map_1)), (1, ("test_map_1", 1, &map_1)),
(2, ("test_map_2", Some(2), &map_2)), (2, ("test_map_2", 2, &map_2)),
]); ]);
relocate_maps( relocate_maps(
@ -683,7 +669,7 @@ mod test {
let maps_by_section = HashMap::new(); let maps_by_section = HashMap::new();
let map = fake_btf_map(1); let map = fake_btf_map(1);
let maps_by_symbol = HashMap::from([(1, ("test_map", Some(1), &map))]); let maps_by_symbol = HashMap::from([(1, ("test_map", 1, &map))]);
relocate_maps( relocate_maps(
&mut fun, &mut fun,
@ -737,8 +723,8 @@ mod test {
let map_1 = fake_btf_map(1); let map_1 = fake_btf_map(1);
let map_2 = fake_btf_map(2); let map_2 = fake_btf_map(2);
let maps_by_symbol = HashMap::from([ let maps_by_symbol = HashMap::from([
(1, ("test_map_1", Some(1), &map_1)), (1, ("test_map_1", 1, &map_1)),
(2, ("test_map_2", Some(2), &map_2)), (2, ("test_map_2", 2, &map_2)),
]); ]);
relocate_maps( relocate_maps(

@ -4,7 +4,7 @@ use std::{
ffi::CString, ffi::CString,
fs, io, fs, io,
os::{ os::{
fd::{AsFd as _, OwnedFd, RawFd}, fd::{AsFd as _, OwnedFd},
raw::c_int, raw::c_int,
}, },
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -475,35 +475,15 @@ impl<'a> BpfLoader<'a> {
} }
} }
} }
let mut map = MapData { let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd());
obj, let mut map = match obj.pinning() {
fd: None, PinningType::None => MapData::create(obj, &name, btf_fd)?,
pinned: false,
};
let fd = match map.obj.pinning() {
PinningType::ByName => { PinningType::ByName => {
let path = match &map_pin_path { let path = map_pin_path.as_ref().ok_or(BpfError::NoPinPath)?;
Some(p) => p, MapData::create_pinned(path, obj, &name, btf_fd)?
None => return Err(BpfError::NoPinPath),
};
// try to open map in case it's already pinned
match map.open_pinned(&name, path) {
Ok(fd) => {
map.pinned = true;
fd as RawFd
}
Err(_) => {
let fd = map.create(&name, btf_fd.as_deref().map(|f| f.as_fd()))?;
map.pin(&name, path).map_err(|error| MapError::PinError {
name: Some(name.to_string()),
error,
})?;
fd
}
}
} }
PinningType::None => map.create(&name, btf_fd.as_deref().map(|f| f.as_fd()))?,
}; };
let fd = map.fd;
if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss { if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss {
bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0) bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0)
.map_err(|(_, io_error)| SyscallError { .map_err(|(_, io_error)| SyscallError {

@ -39,8 +39,6 @@ impl<T: Borrow<MapData>, V: Pod> Array<T, V> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<u32, V>(data)?; check_kv_size::<u32, V>(data)?;
let _fd = data.fd_or_err()?;
Ok(Array { Ok(Array {
inner: map, inner: map,
_v: PhantomData, _v: PhantomData,
@ -63,7 +61,7 @@ impl<T: Borrow<MapData>, V: Pod> Array<T, V> {
pub fn get(&self, index: &u32, flags: u64) -> Result<V, MapError> { pub fn get(&self, index: &u32, flags: u64) -> Result<V, MapError> {
let data = self.inner.borrow(); let data = self.inner.borrow();
check_bounds(data, *index)?; check_bounds(data, *index)?;
let fd = data.fd_or_err()?; let fd = data.fd;
let value = let value =
bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| SyscallError { bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| SyscallError {
@ -90,7 +88,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Array<T, V> {
pub fn set(&mut self, index: u32, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, index)?; check_bounds(data, index)?;
let fd = data.fd_or_err()?; let fd = data.fd;
bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| { bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| {
SyscallError { SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",

@ -58,8 +58,6 @@ impl<T: Borrow<MapData>, V: Pod> PerCpuArray<T, V> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<u32, V>(data)?; check_kv_size::<u32, V>(data)?;
let _fd = data.fd_or_err()?;
Ok(PerCpuArray { Ok(PerCpuArray {
inner: map, inner: map,
_v: PhantomData, _v: PhantomData,
@ -82,7 +80,7 @@ impl<T: Borrow<MapData>, V: Pod> PerCpuArray<T, V> {
pub fn get(&self, index: &u32, flags: u64) -> Result<PerCpuValues<V>, MapError> { pub fn get(&self, index: &u32, flags: u64) -> Result<PerCpuValues<V>, MapError> {
let data = self.inner.borrow(); let data = self.inner.borrow();
check_bounds(data, *index)?; check_bounds(data, *index)?;
let fd = data.fd_or_err()?; let fd = data.fd;
let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| { let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| {
SyscallError { SyscallError {
@ -110,7 +108,7 @@ impl<T: BorrowMut<MapData>, V: Pod> PerCpuArray<T, V> {
pub fn set(&mut self, index: u32, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, index)?; check_bounds(data, index)?;
let fd = data.fd_or_err()?; let fd = data.fd;
bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| { bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| {
SyscallError { SyscallError {

@ -56,8 +56,6 @@ impl<T: Borrow<MapData>> ProgramArray<T> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<u32, RawFd>(data)?; check_kv_size::<u32, RawFd>(data)?;
let _fd = data.fd_or_err()?;
Ok(ProgramArray { inner: map }) Ok(ProgramArray { inner: map })
} }
@ -76,7 +74,7 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, index)?; check_bounds(data, index)?;
let fd = data.fd_or_err()?; let fd = data.fd;
let prog_fd = program.as_fd(); let prog_fd = program.as_fd();
let prog_fd = prog_fd.as_raw_fd(); let prog_fd = prog_fd.as_raw_fd();
@ -96,7 +94,7 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, *index)?; check_bounds(data, *index)?;
let fd = self.inner.borrow_mut().fd_or_err()?; let fd = self.inner.borrow_mut().fd;
bpf_map_delete_elem(fd, index) bpf_map_delete_elem(fd, index)
.map(|_| ()) .map(|_| ())

@ -1,5 +1,8 @@
//! A Bloom Filter. //! A Bloom Filter.
use std::{borrow::Borrow, marker::PhantomData}; use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
};
use crate::{ use crate::{
maps::{check_v_size, MapData, MapError}, maps::{check_v_size, MapData, MapError},
@ -41,8 +44,6 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
let data = map.borrow(); let data = map.borrow();
check_v_size::<V>(data)?; check_v_size::<V>(data)?;
let _ = data.fd_or_err()?;
Ok(BloomFilter { Ok(BloomFilter {
inner: map, inner: map,
_v: PhantomData, _v: PhantomData,
@ -51,7 +52,7 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
/// Query the existence of the element. /// Query the existence of the element.
pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> { pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags) bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags)
.map_err(|(_, io_error)| SyscallError { .map_err(|(_, io_error)| SyscallError {
@ -61,10 +62,12 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
.ok_or(MapError::ElementNotFound)?; .ok_or(MapError::ElementNotFound)?;
Ok(()) Ok(())
} }
}
impl<T: BorrowMut<MapData>, V: Pod> BloomFilter<T, V> {
/// Inserts a value into the map. /// Inserts a value into the map.
pub fn insert(&self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> { pub fn insert(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow_mut().fd;
bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError { bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_push_elem", call: "bpf_map_push_elem",
io_error, io_error,
@ -106,17 +109,24 @@ mod tests {
}) })
} }
fn new_map(obj: obj::Map) -> MapData {
override_syscall(|call| match call {
Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_CREATE,
..
} => Ok(1337),
call => panic!("unexpected syscall {:?}", call),
});
MapData::create(obj, "foo", None).unwrap()
}
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }
#[test] #[test]
fn test_wrong_value_size() { fn test_wrong_value_size() {
let map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!( assert_matches!(
BloomFilter::<_, u16>::new(&map), BloomFilter::<_, u16>::new(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
@ -128,25 +138,21 @@ mod tests {
#[test] #[test]
fn test_try_from_wrong_map() { fn test_try_from_wrong_map() {
let map_data = MapData { let map = new_map(obj::Map::Legacy(LegacyMap {
obj: obj::Map::Legacy(LegacyMap { def: bpf_map_def {
def: bpf_map_def { map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32, key_size: 4,
key_size: 4, value_size: 4,
value_size: 4, max_entries: 1024,
max_entries: 1024, ..Default::default()
..Default::default() },
}, section_index: 0,
section_index: 0, section_kind: BpfSectionKind::Maps,
section_kind: BpfSectionKind::Maps, symbol_index: None,
symbol_index: None, data: Vec::new(),
data: Vec::new(), }));
}),
fd: None, let map = Map::PerfEventArray(map);
pinned: false,
};
let map = Map::PerfEventArray(map_data);
assert_matches!( assert_matches!(
BloomFilter::<_, u32>::try_from(&map), BloomFilter::<_, u32>::try_from(&map),
@ -154,53 +160,27 @@ mod tests {
); );
} }
#[test]
fn test_new_not_created() {
let mut map = MapData {
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!(
BloomFilter::<_, u32>::new(&mut map),
Err(MapError::NotCreated { .. })
);
}
#[test] #[test]
fn test_new_ok() { fn test_new_ok() {
let mut map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
assert!(BloomFilter::<_, u32>::new(&mut map).is_ok()); assert!(BloomFilter::<_, u32>::new(&map).is_ok());
} }
#[test] #[test]
fn test_try_from_ok() { fn test_try_from_ok() {
let map_data = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let map = Map::BloomFilter(map_data); let map = Map::BloomFilter(map);
assert!(BloomFilter::<_, u32>::try_from(&map).is_ok()) assert!(BloomFilter::<_, u32>::try_from(&map).is_ok())
} }
#[test] #[test]
fn test_insert_syscall_error() { fn test_insert_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let mut map = new_map(new_obj_map());
let mut bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
let mut map = MapData { override_syscall(|_| sys_error(EFAULT));
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
assert_matches!( assert_matches!(
bloom_filter.insert(1, 0), bloom_filter.insert(1, 0),
@ -210,6 +190,9 @@ mod tests {
#[test] #[test]
fn test_insert_ok() { fn test_insert_ok() {
let mut map = new_map(new_obj_map());
let mut bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM, cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM,
@ -218,26 +201,16 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
assert!(bloom_filter.insert(0, 42).is_ok()); assert!(bloom_filter.insert(0, 42).is_ok());
} }
#[test] #[test]
fn test_contains_syscall_error() { fn test_contains_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let map = new_map(new_obj_map());
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();
override_syscall(|_| sys_error(EFAULT));
assert_matches!( assert_matches!(
bloom_filter.contains(&1, 0), bloom_filter.contains(&1, 0),
Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
@ -246,6 +219,9 @@ mod tests {
#[test] #[test]
fn test_contains_not_found() { fn test_contains_not_found() {
let map = new_map(new_obj_map());
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_LOOKUP_ELEM, cmd: bpf_cmd::BPF_MAP_LOOKUP_ELEM,
@ -253,12 +229,6 @@ mod tests {
} => sys_error(ENOENT), } => sys_error(ENOENT),
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();
assert_matches!(bloom_filter.contains(&1, 0), Err(MapError::ElementNotFound)); assert_matches!(bloom_filter.contains(&1, 0), Err(MapError::ElementNotFound));
} }

@ -42,7 +42,6 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> HashMap<T, K, V> {
pub(crate) fn new(map: T) -> Result<HashMap<T, K, V>, MapError> { pub(crate) fn new(map: T) -> Result<HashMap<T, K, V>, MapError> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<K, V>(data)?; check_kv_size::<K, V>(data)?;
let _ = data.fd_or_err()?;
Ok(HashMap { Ok(HashMap {
inner: map, inner: map,
@ -53,7 +52,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> HashMap<T, K, V> {
/// Returns a copy of the value associated with the key. /// Returns a copy of the value associated with the key.
pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> { pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem", call: "bpf_map_lookup_elem",
io_error, io_error,
@ -137,17 +136,24 @@ mod tests {
}) })
} }
fn new_map(obj: obj::Map) -> MapData {
override_syscall(|call| match call {
Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_CREATE,
..
} => Ok(1337),
call => panic!("unexpected syscall {:?}", call),
});
MapData::create(obj, "foo", None).unwrap()
}
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }
#[test] #[test]
fn test_wrong_key_size() { fn test_wrong_key_size() {
let map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!( assert_matches!(
HashMap::<_, u8, u32>::new(&map), HashMap::<_, u8, u32>::new(&map),
Err(MapError::InvalidKeySize { Err(MapError::InvalidKeySize {
@ -159,11 +165,7 @@ mod tests {
#[test] #[test]
fn test_wrong_value_size() { fn test_wrong_value_size() {
let map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!( assert_matches!(
HashMap::<_, u32, u16>::new(&map), HashMap::<_, u32, u16>::new(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
@ -175,13 +177,8 @@ mod tests {
#[test] #[test]
fn test_try_from_wrong_map() { fn test_try_from_wrong_map() {
let map_data = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(), let map = Map::Array(map);
fd: None,
pinned: false,
};
let map = Map::Array(map_data);
assert_matches!( assert_matches!(
HashMap::<_, u8, u32>::try_from(&map), HashMap::<_, u8, u32>::try_from(&map),
Err(MapError::InvalidMapType { .. }) Err(MapError::InvalidMapType { .. })
@ -190,13 +187,8 @@ mod tests {
#[test] #[test]
fn test_try_from_wrong_map_values() { fn test_try_from_wrong_map_values() {
let map_data = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(), let map = Map::HashMap(map);
fd: None,
pinned: false,
};
let map = Map::HashMap(map_data);
assert_matches!( assert_matches!(
HashMap::<_, u32, u16>::try_from(&map), HashMap::<_, u32, u16>::try_from(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
@ -206,79 +198,46 @@ mod tests {
); );
} }
#[test]
fn test_new_not_created() {
let mut map = MapData {
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!(
HashMap::<_, u32, u32>::new(&mut map),
Err(MapError::NotCreated { .. })
);
}
#[test] #[test]
fn test_new_ok() { fn test_new_ok() {
let mut map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(), assert!(HashMap::<_, u32, u32>::new(&map).is_ok());
fd: Some(42),
pinned: false,
};
assert!(HashMap::<_, u32, u32>::new(&mut map).is_ok());
} }
#[test] #[test]
fn test_try_from_ok() { fn test_try_from_ok() {
let map_data = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(), let map = Map::HashMap(map);
fd: Some(42),
pinned: false,
};
let map = Map::HashMap(map_data);
assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok()) assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok())
} }
#[test] #[test]
fn test_try_from_ok_lru() { fn test_try_from_ok_lru() {
let map_data = MapData { let map = new_map(obj::Map::Legacy(LegacyMap {
obj: obj::Map::Legacy(LegacyMap { def: bpf_map_def {
def: bpf_map_def { map_type: BPF_MAP_TYPE_LRU_HASH as u32,
map_type: BPF_MAP_TYPE_LRU_HASH as u32, key_size: 4,
key_size: 4, value_size: 4,
value_size: 4, max_entries: 1024,
max_entries: 1024, ..Default::default()
..Default::default() },
}, section_index: 0,
section_index: 0, section_kind: BpfSectionKind::Maps,
section_kind: BpfSectionKind::Maps, symbol_index: None,
symbol_index: None, data: Vec::new(),
data: Vec::new(), }));
}), let map = Map::HashMap(map);
fd: Some(42),
pinned: false,
};
let map = Map::HashMap(map_data);
assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok()) assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok())
} }
#[test] #[test]
fn test_insert_syscall_error() { fn test_insert_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let mut map = new_map(new_obj_map());
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
override_syscall(|_| sys_error(EFAULT));
assert_matches!( assert_matches!(
hm.insert(1, 42, 0), hm.insert(1, 42, 0),
Err(MapError::SyscallError(SyscallError { call: "bpf_map_update_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError(SyscallError { call: "bpf_map_update_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
@ -287,6 +246,9 @@ mod tests {
#[test] #[test]
fn test_insert_ok() { fn test_insert_ok() {
let mut map = new_map(new_obj_map());
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM, cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM,
@ -295,18 +257,14 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
assert!(hm.insert(1, 42, 0).is_ok()); assert!(hm.insert(1, 42, 0).is_ok());
} }
#[test] #[test]
fn test_insert_boxed_ok() { fn test_insert_boxed_ok() {
let mut map = new_map(new_obj_map());
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM, cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM,
@ -315,27 +273,16 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
assert!(hm.insert(Box::new(1), Box::new(42), 0).is_ok()); assert!(hm.insert(Box::new(1), Box::new(42), 0).is_ok());
} }
#[test] #[test]
fn test_remove_syscall_error() { fn test_remove_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let mut map = new_map(new_obj_map());
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
override_syscall(|_| sys_error(EFAULT));
assert_matches!( assert_matches!(
hm.remove(&1), hm.remove(&1),
Err(MapError::SyscallError(SyscallError { call: "bpf_map_delete_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError(SyscallError { call: "bpf_map_delete_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
@ -344,6 +291,9 @@ mod tests {
#[test] #[test]
fn test_remove_ok() { fn test_remove_ok() {
let mut map = new_map(new_obj_map());
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_DELETE_ELEM, cmd: bpf_cmd::BPF_MAP_DELETE_ELEM,
@ -352,24 +302,13 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
assert!(hm.remove(&1).is_ok()); assert!(hm.remove(&1).is_ok());
} }
#[test] #[test]
fn test_get_syscall_error() { fn test_get_syscall_error() {
let map = new_map(new_obj_map());
override_syscall(|_| sys_error(EFAULT)); override_syscall(|_| sys_error(EFAULT));
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
assert_matches!( assert_matches!(
@ -380,6 +319,7 @@ mod tests {
#[test] #[test]
fn test_get_not_found() { fn test_get_not_found() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_LOOKUP_ELEM, cmd: bpf_cmd::BPF_MAP_LOOKUP_ELEM,
@ -387,11 +327,6 @@ mod tests {
} => sys_error(ENOENT), } => sys_error(ENOENT),
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
assert_matches!(hm.get(&1, 0), Err(MapError::KeyNotFound)); assert_matches!(hm.get(&1, 0), Err(MapError::KeyNotFound));
@ -416,6 +351,7 @@ mod tests {
#[test] #[test]
fn test_keys_empty() { fn test_keys_empty() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -423,11 +359,6 @@ mod tests {
} => sys_error(ENOENT), } => sys_error(ENOENT),
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let keys = hm.keys().collect::<Result<Vec<_>, _>>(); let keys = hm.keys().collect::<Result<Vec<_>, _>>();
assert_matches!(keys, Ok(ks) if ks.is_empty()) assert_matches!(keys, Ok(ks) if ks.is_empty())
@ -463,6 +394,8 @@ mod tests {
// to support stable as well. // to support stable as well.
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_keys() { fn test_keys() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -471,11 +404,6 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let keys = hm.keys().collect::<Result<Vec<_>, _>>().unwrap(); let keys = hm.keys().collect::<Result<Vec<_>, _>>().unwrap();
@ -488,6 +416,7 @@ mod tests {
// to support stable as well. // to support stable as well.
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_keys_error() { fn test_keys_error() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -503,11 +432,6 @@ mod tests {
} }
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let mut keys = hm.keys(); let mut keys = hm.keys();
@ -529,6 +453,7 @@ mod tests {
// to support stable as well. // to support stable as well.
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_iter() { fn test_iter() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -540,11 +465,6 @@ mod tests {
} => lookup_elem(attr), } => lookup_elem(attr),
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let items = hm.iter().collect::<Result<Vec<_>, _>>().unwrap(); let items = hm.iter().collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(&items, &[(10, 100), (20, 200), (30, 300)]) assert_eq!(&items, &[(10, 100), (20, 200), (30, 300)])
@ -556,6 +476,7 @@ mod tests {
// to support stable as well. // to support stable as well.
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_iter_key_deleted() { fn test_iter_key_deleted() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -577,11 +498,6 @@ mod tests {
} }
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let items = hm.iter().collect::<Result<Vec<_>, _>>().unwrap(); let items = hm.iter().collect::<Result<Vec<_>, _>>().unwrap();
@ -594,6 +510,7 @@ mod tests {
// to support stable as well. // to support stable as well.
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_iter_key_error() { fn test_iter_key_error() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -615,11 +532,6 @@ mod tests {
} => lookup_elem(attr), } => lookup_elem(attr),
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let mut iter = hm.iter(); let mut iter = hm.iter();
@ -641,6 +553,7 @@ mod tests {
// to support stable as well. // to support stable as well.
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_iter_value_error() { fn test_iter_value_error() {
let map = new_map(new_obj_map());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY, cmd: bpf_cmd::BPF_MAP_GET_NEXT_KEY,
@ -662,11 +575,6 @@ mod tests {
} }
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let mut iter = hm.iter(); let mut iter = hm.iter();

@ -20,7 +20,7 @@ pub(crate) fn insert<K: Pod, V: Pod>(
value: &V, value: &V,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), MapError> {
let fd = map.fd_or_err()?; let fd = map.fd;
bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| SyscallError { bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",
io_error, io_error,
@ -30,7 +30,7 @@ pub(crate) fn insert<K: Pod, V: Pod>(
} }
pub(crate) fn remove<K: Pod>(map: &MapData, key: &K) -> Result<(), MapError> { pub(crate) fn remove<K: Pod>(map: &MapData, key: &K) -> Result<(), MapError> {
let fd = map.fd_or_err()?; let fd = map.fd;
bpf_map_delete_elem(fd, key) bpf_map_delete_elem(fd, key)
.map(|_| ()) .map(|_| ())
.map_err(|(_, io_error)| { .map_err(|(_, io_error)| {

@ -52,8 +52,6 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<K, V>(data)?; check_kv_size::<K, V>(data)?;
let _ = data.fd_or_err()?;
Ok(PerCpuHashMap { Ok(PerCpuHashMap {
inner: map, inner: map,
_k: PhantomData, _k: PhantomData,
@ -63,7 +61,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
/// Returns a slice of values - one for each CPU - associated with the key. /// Returns a slice of values - one for each CPU - associated with the key.
pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> { pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let values = let values =
bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| SyscallError { bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem", call: "bpf_map_lookup_elem",
@ -120,7 +118,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
values: PerCpuValues<V>, values: PerCpuValues<V>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), MapError> {
let fd = self.inner.borrow_mut().fd_or_err()?; let fd = self.inner.borrow_mut().fd;
bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err( bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err(
|(_, io_error)| SyscallError { |(_, io_error)| SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",

@ -117,8 +117,6 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<Key<K>, V>(data)?; check_kv_size::<Key<K>, V>(data)?;
let _ = data.fd_or_err()?;
Ok(LpmTrie { Ok(LpmTrie {
inner: map, inner: map,
_k: PhantomData, _k: PhantomData,
@ -128,7 +126,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie. /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> { pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem", call: "bpf_map_lookup_elem",
io_error, io_error,
@ -157,7 +155,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
value: impl Borrow<V>, value: impl Borrow<V>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| { bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| {
SyscallError { SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",
@ -172,7 +170,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// ///
/// Both the prefix and data must match exactly - this method does not do a longest prefix match. /// Both the prefix and data must match exactly - this method does not do a longest prefix match.
pub fn remove(&mut self, key: &Key<K>) -> Result<(), MapError> { pub fn remove(&mut self, key: &Key<K>) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
bpf_map_delete_elem(fd, key) bpf_map_delete_elem(fd, key)
.map(|_| ()) .map(|_| ())
.map_err(|(_, io_error)| { .map_err(|(_, io_error)| {
@ -228,17 +226,24 @@ mod tests {
}) })
} }
fn new_map(obj: obj::Map) -> MapData {
override_syscall(|call| match call {
Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_CREATE,
..
} => Ok(1337),
call => panic!("unexpected syscall {:?}", call),
});
MapData::create(obj, "foo", None).unwrap()
}
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }
#[test] #[test]
fn test_wrong_key_size() { fn test_wrong_key_size() {
let map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!( assert_matches!(
LpmTrie::<_, u16, u32>::new(&map), LpmTrie::<_, u16, u32>::new(&map),
Err(MapError::InvalidKeySize { Err(MapError::InvalidKeySize {
@ -250,11 +255,7 @@ mod tests {
#[test] #[test]
fn test_wrong_value_size() { fn test_wrong_value_size() {
let map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!( assert_matches!(
LpmTrie::<_, u32, u16>::new(&map), LpmTrie::<_, u32, u16>::new(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
@ -266,25 +267,21 @@ mod tests {
#[test] #[test]
fn test_try_from_wrong_map() { fn test_try_from_wrong_map() {
let map_data = MapData { let map = new_map(obj::Map::Legacy(LegacyMap {
obj: obj::Map::Legacy(LegacyMap { def: bpf_map_def {
def: bpf_map_def { map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32, key_size: 4,
key_size: 4, value_size: 4,
value_size: 4, max_entries: 1024,
max_entries: 1024, ..Default::default()
..Default::default() },
}, section_index: 0,
section_index: 0, section_kind: BpfSectionKind::Maps,
section_kind: BpfSectionKind::Maps, symbol_index: None,
symbol_index: None, data: Vec::new(),
data: Vec::new(), }));
}),
fd: None, let map = Map::PerfEventArray(map);
pinned: false,
};
let map = Map::PerfEventArray(map_data);
assert_matches!( assert_matches!(
LpmTrie::<_, u32, u32>::try_from(&map), LpmTrie::<_, u32, u32>::try_from(&map),
@ -292,55 +289,30 @@ mod tests {
); );
} }
#[test]
fn test_new_not_created() {
let mut map = MapData {
obj: new_obj_map(),
fd: None,
pinned: false,
};
assert_matches!(
LpmTrie::<_, u32, u32>::new(&mut map),
Err(MapError::NotCreated { .. })
);
}
#[test] #[test]
fn test_new_ok() { fn test_new_ok() {
let mut map = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
assert!(LpmTrie::<_, u32, u32>::new(&mut map).is_ok()); assert!(LpmTrie::<_, u32, u32>::new(&map).is_ok());
} }
#[test] #[test]
fn test_try_from_ok() { fn test_try_from_ok() {
let map_data = MapData { let map = new_map(new_obj_map());
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let map = Map::LpmTrie(map_data); let map = Map::LpmTrie(map);
assert!(LpmTrie::<_, u32, u32>::try_from(&map).is_ok()) assert!(LpmTrie::<_, u32, u32>::try_from(&map).is_ok())
} }
#[test] #[test]
fn test_insert_syscall_error() { fn test_insert_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let mut map = new_map(new_obj_map());
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
override_syscall(|_| sys_error(EFAULT));
assert_matches!( assert_matches!(
trie.insert(&key, 1, 0), trie.insert(&key, 1, 0),
Err(MapError::SyscallError(SyscallError { call: "bpf_map_update_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError(SyscallError { call: "bpf_map_update_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
@ -349,6 +321,11 @@ mod tests {
#[test] #[test]
fn test_insert_ok() { fn test_insert_ok() {
let mut map = new_map(new_obj_map());
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM, cmd: bpf_cmd::BPF_MAP_UPDATE_ELEM,
@ -357,30 +334,18 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(trie.insert(&key, 1, 0).is_ok()); assert!(trie.insert(&key, 1, 0).is_ok());
} }
#[test] #[test]
fn test_remove_syscall_error() { fn test_remove_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let mut map = new_map(new_obj_map());
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
override_syscall(|_| sys_error(EFAULT));
assert_matches!( assert_matches!(
trie.remove(&key), trie.remove(&key),
Err(MapError::SyscallError(SyscallError { call: "bpf_map_delete_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError(SyscallError { call: "bpf_map_delete_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
@ -389,6 +354,11 @@ mod tests {
#[test] #[test]
fn test_remove_ok() { fn test_remove_ok() {
let mut map = new_map(new_obj_map());
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_DELETE_ELEM, cmd: bpf_cmd::BPF_MAP_DELETE_ELEM,
@ -397,29 +367,18 @@ mod tests {
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(trie.remove(&key).is_ok()); assert!(trie.remove(&key).is_ok());
} }
#[test] #[test]
fn test_get_syscall_error() { fn test_get_syscall_error() {
override_syscall(|_| sys_error(EFAULT)); let map = new_map(new_obj_map());
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap(); let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
override_syscall(|_| sys_error(EFAULT));
assert_matches!( assert_matches!(
trie.get(&key, 0), trie.get(&key, 0),
Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
@ -428,6 +387,11 @@ mod tests {
#[test] #[test]
fn test_get_not_found() { fn test_get_not_found() {
let map = new_map(new_obj_map());
let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be());
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::Bpf { Syscall::Bpf {
cmd: bpf_cmd::BPF_MAP_LOOKUP_ELEM, cmd: bpf_cmd::BPF_MAP_LOOKUP_ELEM,
@ -435,14 +399,6 @@ mod tests {
} => sys_error(ENOENT), } => sys_error(ENOENT),
_ => sys_error(EFAULT), _ => sys_error(EFAULT),
}); });
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be());
assert_matches!(trie.get(&key, 0), Err(MapError::KeyNotFound)); assert_matches!(trie.get(&key, 0), Err(MapError::KeyNotFound));
} }

@ -103,17 +103,6 @@ pub enum MapError {
name: String, name: String,
}, },
/// The map has not been created
#[error("the map has not been created")]
NotCreated,
/// The map has already been created
#[error("the map `{name}` has already been created")]
AlreadyCreated {
/// Map name
name: String,
},
/// Failed to create map /// Failed to create map
#[error("failed to create map `{name}` with code {code}")] #[error("failed to create map `{name}` with code {code}")]
CreateError { CreateError {
@ -480,7 +469,7 @@ pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
#[derive(Debug)] #[derive(Debug)]
pub struct MapData { pub struct MapData {
pub(crate) obj: obj::Map, pub(crate) obj: obj::Map,
pub(crate) fd: Option<RawFd>, pub(crate) fd: RawFd,
/// Indicates if this map has been pinned to bpffs /// Indicates if this map has been pinned to bpffs
pub pinned: bool, pub pinned: bool,
} }
@ -488,22 +477,18 @@ pub struct MapData {
impl MapData { impl MapData {
/// Creates a new map with the provided `name` /// Creates a new map with the provided `name`
pub fn create( pub fn create(
&mut self, obj: obj::Map,
name: &str, name: &str,
btf_fd: Option<BorrowedFd<'_>>, btf_fd: Option<BorrowedFd<'_>>,
) -> Result<RawFd, MapError> { ) -> Result<Self, MapError> {
if self.fd.is_some() {
return Err(MapError::AlreadyCreated { name: name.into() });
}
let c_name = CString::new(name).map_err(|_| MapError::InvalidName { name: name.into() })?; let c_name = CString::new(name).map_err(|_| MapError::InvalidName { name: name.into() })?;
#[cfg(not(test))] #[cfg(not(test))]
let kernel_version = KernelVersion::current().unwrap(); let kernel_version = KernelVersion::current().unwrap();
#[cfg(test)] #[cfg(test)]
let kernel_version = KernelVersion::new(0xff, 0xff, 0xff); let kernel_version = KernelVersion::new(0xff, 0xff, 0xff);
let fd = bpf_create_map(&c_name, &self.obj, btf_fd, kernel_version).map_err( let fd =
|(code, io_error)| { bpf_create_map(&c_name, &obj, btf_fd, kernel_version).map_err(|(code, io_error)| {
if kernel_version < KernelVersion::new(5, 11, 0) { if kernel_version < KernelVersion::new(5, 11, 0) {
maybe_warn_rlimit(); maybe_warn_rlimit();
} }
@ -513,28 +498,42 @@ impl MapData {
code, code,
io_error, io_error,
} }
}, })?;
)?;
Ok(*self.fd.insert(fd as RawFd)) Ok(Self {
obj,
fd: fd as RawFd,
pinned: false,
})
} }
pub(crate) fn open_pinned<P: AsRef<Path>>( pub(crate) fn create_pinned<P: AsRef<Path>>(
&mut self,
name: &str,
path: P, path: P,
) -> Result<RawFd, MapError> { obj: obj::Map,
if self.fd.is_some() { name: &str,
return Err(MapError::AlreadyCreated { name: name.into() }); btf_fd: Option<BorrowedFd<'_>>,
} ) -> Result<Self, MapError> {
// try to open map in case it's already pinned
let map_path = path.as_ref().join(name); let map_path = path.as_ref().join(name);
let path_string = CString::new(map_path.to_str().unwrap()).unwrap(); let path_string = CString::new(map_path.to_str().unwrap()).unwrap();
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { match bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET", call: "BPF_OBJ_GET",
io_error, io_error,
})?; }) {
Ok(fd) => Ok(Self {
Ok(*self.fd.insert(fd.into_raw_fd())) obj,
fd: fd.into_raw_fd(),
pinned: false,
}),
Err(_) => {
let mut map = Self::create(obj, name, btf_fd)?;
map.pin(name, path).map_err(|error| MapError::PinError {
name: Some(name.into()),
error,
})?;
Ok(map)
}
}
} }
/// Loads a map from a pinned path in bpffs. /// Loads a map from a pinned path in bpffs.
@ -558,7 +557,7 @@ impl MapData {
Ok(MapData { Ok(MapData {
obj: parse_map_info(info, PinningType::ByName), obj: parse_map_info(info, PinningType::ByName),
fd: Some(fd.into_raw_fd()), fd: fd.into_raw_fd(),
pinned: true, pinned: true,
}) })
} }
@ -573,59 +572,54 @@ impl MapData {
Ok(MapData { Ok(MapData {
obj: parse_map_info(info, PinningType::None), obj: parse_map_info(info, PinningType::None),
fd: Some(fd.into_raw_fd()), fd: fd.into_raw_fd(),
pinned: false, pinned: false,
}) })
} }
pub(crate) fn fd_or_err(&self) -> Result<RawFd, MapError> {
self.fd.ok_or(MapError::NotCreated)
}
pub(crate) fn pin<P: AsRef<Path>>(&mut self, name: &str, path: P) -> Result<(), PinError> { pub(crate) fn pin<P: AsRef<Path>>(&mut self, name: &str, path: P) -> Result<(), PinError> {
if self.pinned { let Self { fd, pinned, obj: _ } = self;
if *pinned {
return Err(PinError::AlreadyPinned { name: name.into() }); return Err(PinError::AlreadyPinned { name: name.into() });
} }
let map_path = path.as_ref().join(name); let map_path = path.as_ref().join(name);
let fd = self.fd.ok_or(PinError::NoFd {
name: name.to_string(),
})?;
let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| { let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| {
PinError::InvalidPinPath { PinError::InvalidPinPath {
error: e.to_string(), error: e.to_string(),
} }
})?; })?;
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| SyscallError { bpf_pin_object(*fd, &path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_PIN", call: "BPF_OBJ_PIN",
io_error, io_error,
})?; })?;
self.pinned = true; *pinned = true;
Ok(()) Ok(())
} }
/// Returns the file descriptor of the map. /// Returns the file descriptor of the map.
/// ///
/// Can be converted to [`RawFd`] using [`AsRawFd`]. /// Can be converted to [`RawFd`] using [`AsRawFd`].
pub fn fd(&self) -> Option<MapFd> { pub fn fd(&self) -> MapFd {
self.fd.map(MapFd) MapFd(self.fd)
} }
} }
impl Drop for MapData { impl Drop for MapData {
fn drop(&mut self) { fn drop(&mut self) {
// TODO: Replace this with an OwnedFd once that is stabilized. // TODO: Replace this with an OwnedFd once that is stabilized.
if let Some(fd) = self.fd.take() { //
unsafe { libc::close(fd) }; // SAFETY: `drop` is only called once.
} unsafe { libc::close(self.fd) };
} }
} }
impl Clone for MapData { impl Clone for MapData {
fn clone(&self) -> MapData { fn clone(&self) -> Self {
MapData { let Self { obj, fd, pinned } = self;
obj: self.obj.clone(), Self {
fd: self.fd.map(|fd| unsafe { libc::dup(fd) }), obj: obj.clone(),
pinned: self.pinned, fd: unsafe { libc::dup(*fd) },
pinned: *pinned,
} }
} }
} }
@ -664,14 +658,7 @@ impl<K: Pod> Iterator for MapKeys<'_, K> {
return None; return None;
} }
let fd = match self.map.fd_or_err() { let fd = self.map.fd;
Ok(fd) => fd,
Err(e) => {
self.err = true;
return Some(Err(e));
}
};
let key = let key =
bpf_map_get_next_key(fd, self.key.as_ref()).map_err(|(_, io_error)| SyscallError { bpf_map_get_next_key(fd, self.key.as_ref()).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_get_next_key", call: "bpf_map_get_next_key",
@ -854,14 +841,6 @@ mod tests {
}) })
} }
fn new_map() -> MapData {
MapData {
obj: new_obj_map(),
fd: None,
pinned: false,
}
}
#[test] #[test]
fn test_create() { fn test_create() {
override_syscall(|call| match call { override_syscall(|call| match call {
@ -872,12 +851,13 @@ mod tests {
_ => Err((-1, io::Error::from_raw_os_error(EFAULT))), _ => Err((-1, io::Error::from_raw_os_error(EFAULT))),
}); });
let mut map = new_map();
assert_matches!(map.create("foo", None), Ok(42));
assert_eq!(map.fd, Some(42));
assert_matches!( assert_matches!(
map.create("foo", None), MapData::create(new_obj_map(), "foo", None),
Err(MapError::AlreadyCreated { .. }) Ok(MapData {
obj: _,
fd: 42,
pinned: false
})
); );
} }
@ -885,19 +865,13 @@ mod tests {
fn test_create_failed() { fn test_create_failed() {
override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT))));
let mut map = new_map(); assert_matches!(
let ret = map.create("foo", None); MapData::create(new_obj_map(), "foo", None),
assert_matches!(ret, Err(MapError::CreateError { .. })); Err(MapError::CreateError { name, code, io_error }) => {
if let Err(MapError::CreateError { assert_eq!(name, "foo");
name, assert_eq!(code, -42);
code, assert_eq!(io_error.raw_os_error(), Some(EFAULT));
io_error, }
}) = ret );
{
assert_eq!(name, "foo");
assert_eq!(code, -42);
assert_eq!(io_error.raw_os_error(), Some(EFAULT));
}
assert_eq!(map.fd, None);
} }
} }

@ -162,8 +162,6 @@ pub struct PerfEventArray<T> {
impl<T: Borrow<MapData>> PerfEventArray<T> { impl<T: Borrow<MapData>> PerfEventArray<T> {
pub(crate) fn new(map: T) -> Result<PerfEventArray<T>, MapError> { pub(crate) fn new(map: T) -> Result<PerfEventArray<T>, MapError> {
let _fd = map.borrow().fd_or_err()?;
Ok(PerfEventArray { Ok(PerfEventArray {
map: Arc::new(map), map: Arc::new(map),
page_size: page_size(), page_size: page_size(),
@ -184,7 +182,7 @@ impl<T: BorrowMut<MapData> + Borrow<MapData>> PerfEventArray<T> {
// this cannot fail as new() checks that the fd is open // this cannot fail as new() checks that the fd is open
let map_data: &MapData = self.map.deref().borrow(); let map_data: &MapData = self.map.deref().borrow();
let map_fd = map_data.fd_or_err().unwrap(); let map_fd = map_data.fd;
let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?; let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?;
bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0) bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0)
.map_err(|(_, io_error)| io_error)?; .map_err(|(_, io_error)| io_error)?;

@ -38,8 +38,6 @@ impl<T: Borrow<MapData>, V: Pod> Queue<T, V> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<(), V>(data)?; check_kv_size::<(), V>(data)?;
let _fd = data.fd_or_err()?;
Ok(Queue { Ok(Queue {
inner: map, inner: map,
_v: PhantomData, _v: PhantomData,
@ -62,7 +60,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
/// Returns [`MapError::ElementNotFound`] if the queue is empty, [`MapError::SyscallError`] /// Returns [`MapError::ElementNotFound`] if the queue is empty, [`MapError::SyscallError`]
/// if `bpf_map_lookup_and_delete_elem` fails. /// if `bpf_map_lookup_and_delete_elem` fails.
pub fn pop(&mut self, flags: u64) -> Result<V, MapError> { pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err( let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
|(_, io_error)| SyscallError { |(_, io_error)| SyscallError {
@ -79,7 +77,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
/// ///
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> { pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError { bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_push_elem", call: "bpf_map_push_elem",
io_error, io_error,

@ -72,7 +72,6 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
pub(crate) fn new(map: T) -> Result<SockHash<T, K>, MapError> { pub(crate) fn new(map: T) -> Result<SockHash<T, K>, MapError> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<K, u32>(data)?; check_kv_size::<K, u32>(data)?;
let _ = data.fd_or_err()?;
Ok(SockHash { Ok(SockHash {
inner: map, inner: map,
@ -82,7 +81,7 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
/// Returns the fd of the socket stored at the given key. /// Returns the fd of the socket stored at the given key.
pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> { pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem", call: "bpf_map_lookup_elem",
io_error, io_error,
@ -107,7 +106,7 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
/// The returned file descriptor can be used to attach programs that work with /// The returned file descriptor can be used to attach programs that work with
/// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb).
pub fn fd(&self) -> Result<SockMapFd, MapError> { pub fn fd(&self) -> Result<SockMapFd, MapError> {
Ok(SockMapFd(self.inner.borrow().fd_or_err()?)) Ok(SockMapFd(self.inner.borrow().fd))
} }
} }

@ -49,8 +49,6 @@ impl<T: Borrow<MapData>> SockMap<T> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<u32, RawFd>(data)?; check_kv_size::<u32, RawFd>(data)?;
let _fd = data.fd_or_err()?;
Ok(SockMap { inner: map }) Ok(SockMap { inner: map })
} }
@ -65,7 +63,7 @@ impl<T: Borrow<MapData>> SockMap<T> {
/// The returned file descriptor can be used to attach programs that work with /// The returned file descriptor can be used to attach programs that work with
/// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb).
pub fn fd(&self) -> Result<SockMapFd, MapError> { pub fn fd(&self) -> Result<SockMapFd, MapError> {
Ok(SockMapFd(self.inner.borrow().fd_or_err()?)) Ok(SockMapFd(self.inner.borrow().fd))
} }
} }
@ -73,7 +71,7 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
/// Stores a socket into the map. /// Stores a socket into the map.
pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> { pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
let fd = data.fd_or_err()?; let fd = data.fd;
check_bounds(data, index)?; check_bounds(data, index)?;
bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err( bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
|(_, io_error)| SyscallError { |(_, io_error)| SyscallError {
@ -87,7 +85,7 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
/// Removes the socket stored at `index` from the map. /// Removes the socket stored at `index` from the map.
pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
let fd = data.fd_or_err()?; let fd = data.fd;
check_bounds(data, *index)?; check_bounds(data, *index)?;
bpf_map_delete_elem(fd, index) bpf_map_delete_elem(fd, index)
.map(|_| ()) .map(|_| ())

@ -38,8 +38,6 @@ impl<T: Borrow<MapData>, V: Pod> Stack<T, V> {
let data = map.borrow(); let data = map.borrow();
check_kv_size::<(), V>(data)?; check_kv_size::<(), V>(data)?;
let _fd = data.fd_or_err()?;
Ok(Stack { Ok(Stack {
inner: map, inner: map,
_v: PhantomData, _v: PhantomData,
@ -62,7 +60,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
/// Returns [`MapError::ElementNotFound`] if the stack is empty, [`MapError::SyscallError`] /// Returns [`MapError::ElementNotFound`] if the stack is empty, [`MapError::SyscallError`]
/// if `bpf_map_lookup_and_delete_elem` fails. /// if `bpf_map_lookup_and_delete_elem` fails.
pub fn pop(&mut self, flags: u64) -> Result<V, MapError> { pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err( let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
|(_, io_error)| SyscallError { |(_, io_error)| SyscallError {
@ -79,7 +77,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
/// ///
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> { pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| { bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| {
SyscallError { SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",

@ -89,7 +89,6 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
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 });
} }
let _fd = data.fd_or_err()?;
Ok(StackTraceMap { Ok(StackTraceMap {
inner: map, inner: map,
@ -104,7 +103,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
/// Returns [`MapError::KeyNotFound`] if there is no stack trace with the /// Returns [`MapError::KeyNotFound`] if there is no stack trace with the
/// given `stack_id`, or [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. /// given `stack_id`, or [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails.
pub fn get(&self, stack_id: &u32, flags: u64) -> Result<StackTrace, MapError> { pub fn get(&self, stack_id: &u32, flags: u64) -> Result<StackTrace, MapError> {
let fd = self.inner.borrow().fd_or_err()?; let fd = self.inner.borrow().fd;
let mut frames = vec![0; self.max_stack_depth]; let mut frames = vec![0; self.max_stack_depth];
bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags) bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags)

@ -704,8 +704,8 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
let mut insns = copy_instructions(prog).unwrap(); let mut insns = copy_instructions(prog).unwrap();
let mut map_data = MapData { let map = MapData::create(
obj: 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,
key_size: 4, key_size: 4,
@ -718,12 +718,12 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
symbol_index: None, symbol_index: None,
data: Vec::new(), data: Vec::new(),
}), }),
fd: None, "aya_global",
pinned: false, None,
}; );
if let Ok(map_fd) = map_data.create("aya_global", None) { if let Ok(map) = map {
insns[0].imm = map_fd; insns[0].imm = map.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;

@ -74,7 +74,7 @@ fn use_map_with_rbpf() {
object object
.relocate_maps( .relocate_maps(
maps.iter() maps.iter()
.map(|(s, (fd, map))| (s.as_ref() as &str, Some(*fd), map)), .map(|(s, (fd, map))| (s.as_ref() as &str, *fd, map)),
&text_sections, &text_sections,
) )
.expect("Relocation failed"); .expect("Relocation failed");

@ -5972,7 +5972,7 @@ impl aya_obj::Object
pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError> pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError>
impl aya_obj::Object impl aya_obj::Object
pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, core::option::Option<i32>, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, i32, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
impl core::clone::Clone for aya_obj::Object impl core::clone::Clone for aya_obj::Object
pub fn aya_obj::Object::clone(&self) -> aya_obj::Object pub fn aya_obj::Object::clone(&self) -> aya_obj::Object
impl core::fmt::Debug for aya_obj::Object impl core::fmt::Debug for aya_obj::Object
@ -6288,9 +6288,6 @@ pub enum aya_obj::relocation::RelocationError
pub aya_obj::relocation::RelocationError::InvalidRelocationOffset pub aya_obj::relocation::RelocationError::InvalidRelocationOffset
pub aya_obj::relocation::RelocationError::InvalidRelocationOffset::offset: u64 pub aya_obj::relocation::RelocationError::InvalidRelocationOffset::offset: u64
pub aya_obj::relocation::RelocationError::InvalidRelocationOffset::relocation_number: usize pub aya_obj::relocation::RelocationError::InvalidRelocationOffset::relocation_number: usize
pub aya_obj::relocation::RelocationError::MapNotCreated
pub aya_obj::relocation::RelocationError::MapNotCreated::name: alloc::string::String
pub aya_obj::relocation::RelocationError::MapNotCreated::section_index: usize
pub aya_obj::relocation::RelocationError::SectionNotFound pub aya_obj::relocation::RelocationError::SectionNotFound
pub aya_obj::relocation::RelocationError::SectionNotFound::section_index: usize pub aya_obj::relocation::RelocationError::SectionNotFound::section_index: usize
pub aya_obj::relocation::RelocationError::SectionNotFound::symbol_index: usize pub aya_obj::relocation::RelocationError::SectionNotFound::symbol_index: usize
@ -6687,7 +6684,7 @@ impl aya_obj::Object
pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError> pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError>
impl aya_obj::Object impl aya_obj::Object
pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, core::option::Option<i32>, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, i32, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
impl core::clone::Clone for aya_obj::Object impl core::clone::Clone for aya_obj::Object
pub fn aya_obj::Object::clone(&self) -> aya_obj::Object pub fn aya_obj::Object::clone(&self) -> aya_obj::Object
impl core::fmt::Debug for aya_obj::Object impl core::fmt::Debug for aya_obj::Object

@ -126,7 +126,8 @@ pub mod aya::maps::bloom_filter
pub struct aya::maps::bloom_filter::BloomFilter<T, V: aya::Pod> pub struct aya::maps::bloom_filter::BloomFilter<T, V: aya::Pod>
impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V> impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
pub fn aya::maps::bloom_filter::BloomFilter<T, V>::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::bloom_filter::BloomFilter<T, V>::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError>
pub fn aya::maps::bloom_filter::BloomFilter<T, V>::insert(&self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
pub fn aya::maps::bloom_filter::BloomFilter<T, V>::insert(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>
pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>, aya::maps::MapError> pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>, aya::maps::MapError>
@ -966,8 +967,6 @@ pub fn aya::maps::Map::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya::maps::Map impl<T> core::convert::From<T> for aya::maps::Map
pub fn aya::maps::Map::from(t: T) -> T pub fn aya::maps::Map::from(t: T) -> T
pub enum aya::maps::MapError pub enum aya::maps::MapError
pub aya::maps::MapError::AlreadyCreated
pub aya::maps::MapError::AlreadyCreated::name: alloc::string::String
pub aya::maps::MapError::CreateError pub aya::maps::MapError::CreateError
pub aya::maps::MapError::CreateError::code: libc::unix::linux_like::linux::gnu::b64::x86_64::not_x32::c_long pub aya::maps::MapError::CreateError::code: libc::unix::linux_like::linux::gnu::b64::x86_64::not_x32::c_long
pub aya::maps::MapError::CreateError::io_error: std::io::error::Error pub aya::maps::MapError::CreateError::io_error: std::io::error::Error
@ -984,7 +983,6 @@ pub aya::maps::MapError::InvalidValueSize
pub aya::maps::MapError::InvalidValueSize::expected: usize pub aya::maps::MapError::InvalidValueSize::expected: usize
pub aya::maps::MapError::InvalidValueSize::size: usize pub aya::maps::MapError::InvalidValueSize::size: usize
pub aya::maps::MapError::KeyNotFound pub aya::maps::MapError::KeyNotFound
pub aya::maps::MapError::NotCreated
pub aya::maps::MapError::OutOfBounds pub aya::maps::MapError::OutOfBounds
pub aya::maps::MapError::OutOfBounds::index: u32 pub aya::maps::MapError::OutOfBounds::index: u32
pub aya::maps::MapError::OutOfBounds::max_entries: u32 pub aya::maps::MapError::OutOfBounds::max_entries: u32
@ -1104,7 +1102,8 @@ pub fn aya::maps::perf::AsyncPerfEventArray<T>::from(t: T) -> T
pub struct aya::maps::BloomFilter<T, V: aya::Pod> pub struct aya::maps::BloomFilter<T, V: aya::Pod>
impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V> impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
pub fn aya::maps::bloom_filter::BloomFilter<T, V>::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::bloom_filter::BloomFilter<T, V>::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError>
pub fn aya::maps::bloom_filter::BloomFilter<T, V>::insert(&self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
pub fn aya::maps::bloom_filter::BloomFilter<T, V>::insert(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>
pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>, aya::maps::MapError> pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>, aya::maps::MapError>
@ -1226,12 +1225,12 @@ pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::from(t: T) -> T
pub struct aya::maps::MapData pub struct aya::maps::MapData
pub aya::maps::MapData::pinned: bool pub aya::maps::MapData::pinned: bool
impl aya::maps::MapData impl aya::maps::MapData
pub fn aya::maps::MapData::create(&mut self, name: &str, btf_fd: core::option::Option<std::os::fd::owned::BorrowedFd<'_>>) -> core::result::Result<std::os::fd::raw::RawFd, aya::maps::MapError> pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option<std::os::fd::owned::BorrowedFd<'_>>) -> core::result::Result<Self, aya::maps::MapError>
pub fn aya::maps::MapData::fd(&self) -> core::option::Option<aya::maps::MapFd> pub fn aya::maps::MapData::fd(&self) -> aya::maps::MapFd
pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result<aya::maps::MapData, aya::maps::MapError> pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result<aya::maps::MapData, aya::maps::MapError>
pub fn aya::maps::MapData::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<aya::maps::MapData, aya::maps::MapError> pub fn aya::maps::MapData::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<aya::maps::MapData, aya::maps::MapError>
impl core::clone::Clone for aya::maps::MapData impl core::clone::Clone for aya::maps::MapData
pub fn aya::maps::MapData::clone(&self) -> aya::maps::MapData pub fn aya::maps::MapData::clone(&self) -> Self
impl core::ops::drop::Drop for aya::maps::MapData impl core::ops::drop::Drop for aya::maps::MapData
pub fn aya::maps::MapData::drop(&mut self) pub fn aya::maps::MapData::drop(&mut self)
impl core::fmt::Debug for aya::maps::MapData impl core::fmt::Debug for aya::maps::MapData

Loading…
Cancel
Save