maps: move maps inside RefCells

pull/1/head
Alessandro Decina 4 years ago
parent 77fa7d857c
commit f7cdd2e059

@ -1,4 +1,7 @@
use std::collections::HashMap; use std::{
cell::{Ref, RefCell, RefMut},
collections::HashMap,
};
use thiserror::Error; use thiserror::Error;
@ -45,7 +48,7 @@ unsafe impl object::Pod for bpf_map_def {}
#[derive(Debug)] #[derive(Debug)]
pub struct Bpf { pub struct Bpf {
maps: HashMap<String, Map>, maps: HashMap<String, RefCell<Map>>,
programs: HashMap<String, Program>, programs: HashMap<String, Program>,
} }
@ -91,18 +94,18 @@ impl Bpf {
Ok(Bpf { Ok(Bpf {
maps: maps maps: maps
.drain(..) .drain(..)
.map(|map| (map.obj.name.clone(), map)) .map(|map| (map.obj.name.clone(), RefCell::new(map)))
.collect(), .collect(),
programs, programs,
}) })
} }
pub fn map(&self, name: &str) -> Option<&Map> { pub fn map(&self, name: &str) -> Option<Ref<'_, Map>> {
self.maps.get(name) self.maps.get(name).map(|cell| cell.borrow())
} }
pub fn map_mut(&mut self, name: &str) -> Option<&mut Map> { pub fn map_mut(&self, name: &str) -> Option<RefMut<'_, Map>> {
self.maps.get_mut(name) self.maps.get(name).map(|cell| cell.borrow_mut())
} }
pub fn program(&self, name: &str) -> Option<&Program> { pub fn program(&self, name: &str) -> Option<&Program> {

@ -1,4 +1,10 @@
use std::{convert::TryFrom, marker::PhantomData, mem}; use std::{
cell::{Ref, RefMut},
convert::TryFrom,
marker::PhantomData,
mem,
ops::{Deref, DerefMut},
};
use crate::{ use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_HASH, generated::bpf_map_type::BPF_MAP_TYPE_HASH,
@ -10,15 +16,15 @@ use crate::{
Pod, RawFd, Pod, RawFd,
}; };
pub struct HashMap<T: AsRef<Map>, K, V> { pub struct HashMap<T: Deref<Target = Map>, K, V> {
inner: T, inner: T,
_k: PhantomData<K>, _k: PhantomData<K>,
_v: PhantomData<V>, _v: PhantomData<V>,
} }
impl<T: AsRef<Map>, K: Pod, V: Pod> HashMap<T, K, V> { impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
pub fn new(map: T) -> Result<HashMap<T, K, V>, MapError> { pub fn new(map: T) -> Result<HashMap<T, K, V>, MapError> {
let inner = map.as_ref(); let inner = map.deref();
let map_type = inner.obj.def.map_type; let map_type = inner.obj.def.map_type;
if map_type != BPF_MAP_TYPE_HASH { if map_type != BPF_MAP_TYPE_HASH {
return Err(MapError::InvalidMapType { return Err(MapError::InvalidMapType {
@ -45,7 +51,7 @@ impl<T: AsRef<Map>, K: Pod, V: Pod> HashMap<T, K, V> {
} }
pub unsafe fn get(&self, key: &K, flags: u64) -> Result<Option<V>, MapError> { pub unsafe fn get(&self, key: &K, flags: u64) -> Result<Option<V>, MapError> {
let fd = self.inner.as_ref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_lookup_elem(fd, key, flags) bpf_map_lookup_elem(fd, key, flags)
.map_err(|(code, io_error)| MapError::LookupElementFailed { code, io_error }) .map_err(|(code, io_error)| MapError::LookupElementFailed { code, io_error })
} }
@ -59,31 +65,31 @@ impl<T: AsRef<Map>, K: Pod, V: Pod> HashMap<T, K, V> {
} }
} }
impl<T: AsRef<Map> + AsMut<Map>, K: Pod, V: Pod> HashMap<T, K, V> { impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
pub fn insert(&mut self, key: K, value: V, flags: u64) -> Result<(), MapError> { pub fn insert(&mut self, key: K, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.as_ref().fd_or_err()?; let fd = self.inner.deref_mut().fd_or_err()?;
bpf_map_update_elem(fd, &key, &value, flags) bpf_map_update_elem(fd, &key, &value, flags)
.map_err(|(code, io_error)| MapError::UpdateElementFailed { code, io_error })?; .map_err(|(code, io_error)| MapError::UpdateElementFailed { code, io_error })?;
Ok(()) Ok(())
} }
pub unsafe fn pop(&mut self, key: &K) -> Result<Option<V>, MapError> { pub unsafe fn pop(&mut self, key: &K) -> Result<Option<V>, MapError> {
let fd = self.inner.as_ref().fd_or_err()?; let fd = self.inner.deref_mut().fd_or_err()?;
bpf_map_lookup_and_delete_elem(fd, key) bpf_map_lookup_and_delete_elem(fd, key)
.map_err(|(code, io_error)| MapError::LookupAndDeleteElementFailed { code, io_error }) .map_err(|(code, io_error)| MapError::LookupAndDeleteElementFailed { code, io_error })
} }
pub fn remove(&mut self, key: &K) -> Result<(), MapError> { pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
let fd = self.inner.as_ref().fd_or_err()?; let fd = self.inner.deref_mut().fd_or_err()?;
bpf_map_delete_elem(fd, key) bpf_map_delete_elem(fd, key)
.map(|_| ()) .map(|_| ())
.map_err(|(code, io_error)| MapError::DeleteElementFailed { code, io_error }) .map_err(|(code, io_error)| MapError::DeleteElementFailed { code, io_error })
} }
} }
impl<T: AsRef<Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> { impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
fn fd(&self) -> Result<RawFd, MapError> { fn fd(&self) -> Result<RawFd, MapError> {
self.inner.as_ref().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<Option<V>, MapError> {
@ -91,6 +97,22 @@ impl<T: AsRef<Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
} }
} }
impl<'a, K: Pod, V: Pod> TryFrom<Ref<'a, Map>> for HashMap<Ref<'a, Map>, K, V> {
type Error = MapError;
fn try_from(inner: Ref<'a, Map>) -> Result<HashMap<Ref<'a, Map>, K, V>, MapError> {
HashMap::new(inner)
}
}
impl<'a, K: Pod, V: Pod> TryFrom<RefMut<'a, Map>> for HashMap<RefMut<'a, Map>, K, V> {
type Error = MapError;
fn try_from(inner: RefMut<'a, Map>) -> Result<HashMap<RefMut<'a, Map>, K, V>, MapError> {
HashMap::new(inner)
}
}
impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> { impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> {
type Error = MapError; type Error = MapError;

@ -1,7 +1,10 @@
use std::{ use std::{
cell::RefMut,
convert::TryFrom, convert::TryFrom,
ffi::c_void, ffi::c_void,
fs, io, mem, ptr, slice, fs, io, mem,
ops::DerefMut,
ptr, slice,
str::FromStr, str::FromStr,
sync::atomic::{self, AtomicPtr, Ordering}, sync::atomic::{self, AtomicPtr, Ordering},
}; };
@ -277,18 +280,18 @@ pub enum PerfMapError {
}, },
} }
pub struct PerfMap<'map> { pub struct PerfMap<T: DerefMut<Target = Map>> {
map: &'map Map, map: T,
cpu_fds: Vec<(u32, RawFd)>, cpu_fds: Vec<(u32, RawFd)>,
buffers: Vec<Option<PerfBuffer>>, buffers: Vec<Option<PerfBuffer>>,
} }
impl<'map> PerfMap<'map> { impl<T: DerefMut<Target = Map>> PerfMap<T> {
pub fn new( pub fn new(
map: &'map Map, map: T,
cpu_ids: Option<Vec<u32>>, cpu_ids: Option<Vec<u32>>,
page_count: Option<usize>, page_count: Option<usize>,
) -> Result<PerfMap<'map>, PerfMapError> { ) -> Result<PerfMap<T>, PerfMapError> {
let map_type = map.obj.def.map_type; let map_type = map.obj.def.map_type;
if map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY { if map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY {
return Err(MapError::InvalidMapType { return Err(MapError::InvalidMapType {
@ -345,11 +348,19 @@ impl<'map> PerfMap<'map> {
} }
} }
impl<'inner> TryFrom<&'inner Map> for PerfMap<'inner> { impl<'a> TryFrom<RefMut<'a, Map>> for PerfMap<RefMut<'a, Map>> {
type Error = PerfMapError; type Error = PerfMapError;
fn try_from(inner: &'inner Map) -> Result<PerfMap<'inner>, PerfMapError> { fn try_from(a: RefMut<'a, Map>) -> Result<PerfMap<RefMut<'a, Map>>, PerfMapError> {
PerfMap::new(inner, None, None) PerfMap::new(a, None, None)
}
}
impl<'a> TryFrom<&'a mut Map> for PerfMap<&'a mut Map> {
type Error = PerfMapError;
fn try_from(a: &'a mut Map) -> Result<PerfMap<&'a mut Map>, PerfMapError> {
PerfMap::new(a, None, None)
} }
} }

Loading…
Cancel
Save