diff --git a/src/maps/hash_map.rs b/src/maps/hash_map.rs index 5a615160..7ae4662e 100644 --- a/src/maps/hash_map.rs +++ b/src/maps/hash_map.rs @@ -1,16 +1,15 @@ -use std::{convert::TryFrom, marker::PhantomData, mem, os::unix::prelude::RawFd}; +use std::{convert::TryFrom, marker::PhantomData, mem}; use crate::{ generated::bpf_map_type::BPF_MAP_TYPE_HASH, + maps::{IterableMap, Map, MapError, MapIter, MapKeys}, syscalls::{ - bpf_map_delete_elem, bpf_map_get_next_key, bpf_map_lookup_and_delete_elem, - bpf_map_lookup_elem, bpf_map_update_elem, + bpf_map_delete_elem, bpf_map_lookup_and_delete_elem, bpf_map_lookup_elem, + bpf_map_update_elem, }, + Pod, RawFd, }; -use super::{Map, MapError}; -use crate::Pod; - pub struct HashMap, K, V> { inner: T, _k: PhantomData, @@ -82,27 +81,6 @@ impl + AsMut, K: Pod, V: Pod> HashMap { } } -impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> { - type Error = MapError; - - fn try_from(inner: &'a Map) -> Result, MapError> { - HashMap::new(inner) - } -} - -impl<'a, K: Pod, V: Pod> TryFrom<&'a mut Map> for HashMap<&'a mut Map, K, V> { - type Error = MapError; - - fn try_from(inner: &'a mut Map) -> Result, MapError> { - HashMap::new(inner) - } -} - -pub(crate) trait IterableMap { - fn fd(&self) -> Result; - unsafe fn get(&self, key: &K) -> Result, MapError>; -} - impl, K: Pod, V: Pod> IterableMap for HashMap { fn fd(&self) -> Result { self.inner.as_ref().fd_or_err() @@ -113,103 +91,19 @@ impl, K: Pod, V: Pod> IterableMap for HashMap { } } -pub struct MapKeys<'coll, K: Pod, V: Pod> { - map: &'coll dyn IterableMap, - err: bool, - key: Option, -} - -impl<'coll, K: Pod, V: Pod> MapKeys<'coll, K, V> { - fn new(map: &'coll dyn IterableMap) -> MapKeys<'coll, K, V> { - MapKeys { - map, - err: false, - key: None, - } - } -} - -impl Iterator for MapKeys<'_, K, V> { - type Item = Result; - - fn next(&mut self) -> Option> { - if self.err { - return None; - } - - let fd = match self.map.fd() { - Ok(fd) => fd, - Err(e) => { - self.err = true; - return Some(Err(e)); - } - }; - - match bpf_map_get_next_key(fd, self.key.as_ref()) { - Ok(Some(key)) => { - self.key = Some(key); - return Some(Ok(key)); - } - Ok(None) => { - self.key = None; - return None; - } - Err((code, io_error)) => { - self.err = true; - return Some(Err(MapError::GetNextKeyFailed { code, io_error })); - } - } - } -} - -pub struct MapIter<'coll, K: Pod, V: Pod> { - inner: MapKeys<'coll, K, V>, -} - -impl<'coll, K: Pod, V: Pod> MapIter<'coll, K, V> { - fn new(map: &'coll dyn IterableMap) -> MapIter<'coll, K, V> { - MapIter { - inner: MapKeys::new(map), - } - } -} - -impl Iterator for MapIter<'_, K, V> { - type Item = Result<(K, V), MapError>; - - fn next(&mut self) -> Option { - loop { - match self.inner.next() { - Some(Ok(key)) => { - let value = unsafe { self.inner.map.get(&key) }; - match value { - Ok(None) => continue, - Ok(Some(value)) => return Some(Ok((key, value))), - Err(e) => return Some(Err(e)), - } - } - Some(Err(e)) => return Some(Err(e)), - None => return None, - } - } - } -} +impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> { + type Error = MapError; -impl AsRef for &Map { - fn as_ref(&self) -> &Map { - self + fn try_from(inner: &'a Map) -> Result, MapError> { + HashMap::new(inner) } } -impl AsRef for &mut Map { - fn as_ref(&self) -> &Map { - self - } -} +impl<'a, K: Pod, V: Pod> TryFrom<&'a mut Map> for HashMap<&'a mut Map, K, V> { + type Error = MapError; -impl AsMut for &mut Map { - fn as_mut(&mut self) -> &mut Map { - self + fn try_from(inner: &'a mut Map) -> Result, MapError> { + HashMap::new(inner) } } diff --git a/src/maps/mod.rs b/src/maps/mod.rs index dd09a620..ccb518f2 100644 --- a/src/maps/mod.rs +++ b/src/maps/mod.rs @@ -1,7 +1,11 @@ use std::{ffi::CString, io}; use thiserror::Error; -use crate::{obj, syscalls::bpf_create_map, RawFd}; +use crate::{ + obj, + syscalls::{bpf_create_map, bpf_map_get_next_key}, + Pod, RawFd, +}; mod hash_map; pub use hash_map::*; @@ -90,6 +94,93 @@ impl Map { } } +pub(crate) trait IterableMap { + fn fd(&self) -> Result; + unsafe fn get(&self, key: &K) -> Result, MapError>; +} + +pub struct MapKeys<'coll, K: Pod, V: Pod> { + map: &'coll dyn IterableMap, + err: bool, + key: Option, +} + +impl<'coll, K: Pod, V: Pod> MapKeys<'coll, K, V> { + fn new(map: &'coll dyn IterableMap) -> MapKeys<'coll, K, V> { + MapKeys { + map, + err: false, + key: None, + } + } +} + +impl Iterator for MapKeys<'_, K, V> { + type Item = Result; + + fn next(&mut self) -> Option> { + if self.err { + return None; + } + + let fd = match self.map.fd() { + Ok(fd) => fd, + Err(e) => { + self.err = true; + return Some(Err(e)); + } + }; + + match bpf_map_get_next_key(fd, self.key.as_ref()) { + Ok(Some(key)) => { + self.key = Some(key); + return Some(Ok(key)); + } + Ok(None) => { + self.key = None; + return None; + } + Err((code, io_error)) => { + self.err = true; + return Some(Err(MapError::GetNextKeyFailed { code, io_error })); + } + } + } +} + +pub struct MapIter<'coll, K: Pod, V: Pod> { + inner: MapKeys<'coll, K, V>, +} + +impl<'coll, K: Pod, V: Pod> MapIter<'coll, K, V> { + fn new(map: &'coll dyn IterableMap) -> MapIter<'coll, K, V> { + MapIter { + inner: MapKeys::new(map), + } + } +} + +impl Iterator for MapIter<'_, K, V> { + type Item = Result<(K, V), MapError>; + + fn next(&mut self) -> Option { + loop { + match self.inner.next() { + Some(Ok(key)) => { + let value = unsafe { self.inner.map.get(&key) }; + match value { + Ok(None) => continue, + Ok(Some(value)) => return Some(Ok((key, value))), + Err(e) => return Some(Err(e)), + } + } + Some(Err(e)) => return Some(Err(e)), + None => return None, + } + } + } +} + #[cfg(test)] mod tests { use libc::EFAULT;