aya: maps: introduce MapError::KeyNotFound

Change get() from -> Result<Option<V>, MapError> to -> Result<V,
MapError> where MapError::KeyNotFound is returned instead of Ok(None) to
signify that the key is not present.
pull/1/head
Alessandro Decina 4 years ago
parent fd142e467c
commit 635dcd44b9

@ -59,13 +59,16 @@ impl<T: Deref<Target = Map>, 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 unsafe fn get(&self, key: &K, flags: u64) -> Result<Option<V>, MapError> { pub unsafe fn get(&self, key: &K, flags: u64) -> Result<V, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| MapError::SyscallError { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code, code,
io_error, io_error,
}) }
})?;
value.ok_or(MapError::KeyNotFound)
} }
/// An iterator visiting all key-value pairs in arbitrary order. The /// An iterator visiting all key-value pairs in arbitrary order. The
@ -98,7 +101,7 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K,
self.inner.deref().fd_or_err() self.inner.deref().fd_or_err()
} }
unsafe fn get(&self, key: &K) -> Result<Option<V>, MapError> { unsafe fn get(&self, key: &K) -> Result<V, MapError> {
HashMap::get(self, key, 0) HashMap::get(self, key, 0)
} }
} }
@ -379,7 +382,10 @@ mod tests {
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
assert!(matches!(unsafe { hm.get(&1, 0) }, Ok(None))); assert!(matches!(
unsafe { hm.get(&1, 0) },
Err(MapError::KeyNotFound)
));
} }
fn bpf_key<T: Copy>(attr: &bpf_attr) -> Option<T> { fn bpf_key<T: Copy>(attr: &bpf_attr) -> Option<T> {

@ -29,8 +29,8 @@ use crate::{
/// const WAKEUPS: u8 = 2; /// const WAKEUPS: u8 = 2;
/// ///
/// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map("COUNTERS")?)?; /// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map("COUNTERS")?)?;
/// let cpu_ids = unsafe { hm.get(&CPU_IDS, 0)?.unwrap() }; /// let cpu_ids = unsafe { hm.get(&CPU_IDS, 0)? };
/// let wakeups = unsafe { hm.get(&WAKEUPS, 0)?.unwrap() }; /// let wakeups = unsafe { hm.get(&WAKEUPS, 0)? };
/// for (cpu_id, wakeups) in cpu_ids.iter().zip(wakeups.iter()) { /// for (cpu_id, wakeups) in cpu_ids.iter().zip(wakeups.iter()) {
/// println!("cpu {} woke up {} times", cpu_id, wakeups); /// println!("cpu {} woke up {} times", cpu_id, wakeups);
/// } /// }
@ -63,15 +63,16 @@ impl<T: Deref<Target = Map>, 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 unsafe fn get(&self, key: &K, flags: u64) -> Result<Option<PerCpuValues<V>>, MapError> { pub unsafe fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(code, io_error)| { let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(code, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code, code,
io_error, io_error,
} }
}) })?;
values.ok_or(MapError::KeyNotFound)
} }
/// An iterator visiting all key-value pairs in arbitrary order. The /// An iterator visiting all key-value pairs in arbitrary order. The
@ -143,7 +144,7 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>>
self.inner.deref().fd_or_err() self.inner.deref().fd_or_err()
} }
unsafe fn get(&self, key: &K) -> Result<Option<PerCpuValues<V>>, MapError> { unsafe fn get(&self, key: &K) -> Result<PerCpuValues<V>, MapError> {
PerCpuHashMap::get(self, key, 0) PerCpuHashMap::get(self, key, 0)
} }
} }

@ -83,6 +83,9 @@ pub enum MapError {
#[error("the index is {index} but `max_entries` is {max_entries}")] #[error("the index is {index} but `max_entries` is {max_entries}")]
OutOfBounds { index: u32, max_entries: u32 }, OutOfBounds { index: u32, max_entries: u32 },
#[error("key not found")]
KeyNotFound,
#[error("the program is not loaded")] #[error("the program is not loaded")]
ProgramNotLoaded, ProgramNotLoaded,
@ -146,7 +149,7 @@ impl Map {
pub(crate) trait IterableMap<K: Pod, V> { pub(crate) trait IterableMap<K: Pod, V> {
fn fd(&self) -> Result<RawFd, MapError>; fn fd(&self) -> Result<RawFd, MapError>;
unsafe fn get(&self, key: &K) -> Result<Option<V>, MapError>; unsafe fn get(&self, key: &K) -> Result<V, MapError>;
} }
/// Iterator returned by `map.keys()`. /// Iterator returned by `map.keys()`.
@ -225,8 +228,8 @@ impl<K: Pod, V> Iterator for MapIter<'_, K, V> {
Some(Ok(key)) => { Some(Ok(key)) => {
let value = unsafe { self.inner.map.get(&key) }; let value = unsafe { self.inner.map.get(&key) };
match value { match value {
Ok(None) => continue, Ok(value) => return Some(Ok((key, value))),
Ok(Some(value)) => return Some(Ok((key, value))), Err(MapError::KeyNotFound) => continue,
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
} }
} }

@ -46,7 +46,7 @@ impl<T: Deref<Target = Map>> ProgramArray<T> {
Ok(ProgramArray { inner: map }) Ok(ProgramArray { inner: map })
} }
pub unsafe fn get(&self, key: &u32, flags: u64) -> Result<Option<RawFd>, MapError> { pub unsafe fn get(&self, key: &u32, flags: u64) -> Result<RawFd, MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
let fd = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { let fd = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| {
MapError::SyscallError { MapError::SyscallError {
@ -55,7 +55,7 @@ impl<T: Deref<Target = Map>> ProgramArray<T> {
io_error, io_error,
} }
})?; })?;
Ok(fd) fd.ok_or(MapError::KeyNotFound)
} }
pub unsafe fn iter<'coll>(&'coll self) -> MapIter<'coll, u32, RawFd> { pub unsafe fn iter<'coll>(&'coll self) -> MapIter<'coll, u32, RawFd> {
@ -133,7 +133,7 @@ impl<T: Deref<Target = Map>> IterableMap<u32, RawFd> for ProgramArray<T> {
self.inner.fd_or_err() self.inner.fd_or_err()
} }
unsafe fn get(&self, index: &u32) -> Result<Option<RawFd>, MapError> { unsafe fn get(&self, index: &u32) -> Result<RawFd, MapError> {
self.get(index, 0) self.get(index, 0)
} }
} }

Loading…
Cancel
Save