aya: rework IterableMap and ProgramArray

Make MapKeys not use IterableMap. Leave only ProgramArray::get,
ProgramArray::set and ProgramArray::unset exposed as the other syscalls
don't work consistently for program arrays.
pull/1/head
Alessandro Decina 4 years ago
parent aa3a30d196
commit 74d5f17559

@ -125,8 +125,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Array<T, V> {
} }
impl<T: Deref<Target = Map>, V: Pod> IterableMap<u32, V> for Array<T, V> { impl<T: Deref<Target = Map>, V: Pod> IterableMap<u32, V> for Array<T, V> {
fn fd(&self) -> Result<RawFd, MapError> { fn map(&self) -> &Map {
self.inner.fd_or_err() &self.inner
} }
unsafe fn get(&self, index: &u32) -> Result<V, MapError> { unsafe fn get(&self, index: &u32) -> Result<V, MapError> {

@ -46,24 +46,8 @@ 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<RawFd, MapError> { pub unsafe fn keys<'coll>(&'coll self) -> MapKeys<'coll, u32> {
let fd = self.inner.fd_or_err()?; MapKeys::new(&self.inner)
let fd = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
code,
io_error,
}
})?;
fd.ok_or(MapError::KeyNotFound)
}
pub unsafe fn iter<'coll>(&'coll self) -> MapIter<'coll, u32, RawFd> {
MapIter::new(self)
}
pub unsafe fn keys<'coll>(&'coll self) -> MapKeys<'coll, u32, RawFd> {
MapKeys::new(self)
} }
fn check_bounds(&self, index: u32) -> Result<(), MapError> { fn check_bounds(&self, index: u32) -> Result<(), MapError> {
@ -77,10 +61,10 @@ impl<T: Deref<Target = Map>> ProgramArray<T> {
} }
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> { impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
/// Insert a program file descriptor in the jump table. /// Sets the target program file descriptor for the given index in the jump table.
/// ///
/// When an eBPF program calls `bpf_tail_call(prog_array, index)`, `program` /// When an eBPF program calls `bpf_tail_call(prog_array, index)`, control
/// will be executed. /// flow will jump to `program`.
/// ///
/// # Example /// # Example
/// ```no_run /// ```no_run
@ -91,15 +75,10 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
/// ///
/// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?; /// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?;
/// let prog: &KProbe = bpf.program("example_prog")?.try_into()?; /// let prog: &KProbe = bpf.program("example_prog")?.try_into()?;
/// prog_array.insert(0, prog, 0 /* flags */); /// prog_array.set(0, prog, 0 /* flags */);
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
pub fn insert( pub fn set(&mut self, index: u32, program: &dyn ProgramFd, flags: u64) -> Result<(), MapError> {
&mut self,
index: u32,
program: &dyn ProgramFd,
flags: u64,
) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
self.check_bounds(index)?; self.check_bounds(index)?;
let prog_fd = program.fd().ok_or(MapError::ProgramNotLoaded)?; let prog_fd = program.fd().ok_or(MapError::ProgramNotLoaded)?;
@ -114,8 +93,10 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
Ok(()) Ok(())
} }
/// Remove an entry from the jump table. /// Clears the value at index in the jump table.
pub fn remove(&mut self, index: &u32) -> Result<(), MapError> { ///
/// Calling `bpf_tail_call(prog_array, index)` on an index that has been results in a failure.
pub fn unset(&mut self, index: &u32) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
self.check_bounds(*index)?; self.check_bounds(*index)?;
bpf_map_delete_elem(fd, index) bpf_map_delete_elem(fd, index)
@ -128,16 +109,6 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
} }
} }
impl<T: Deref<Target = Map>> IterableMap<u32, RawFd> for ProgramArray<T> {
fn fd(&self) -> Result<RawFd, MapError> {
self.inner.fd_or_err()
}
unsafe fn get(&self, index: &u32) -> Result<RawFd, MapError> {
self.get(index, 0)
}
}
impl TryFrom<MapRef> for ProgramArray<MapRef> { impl TryFrom<MapRef> for ProgramArray<MapRef> {
type Error = MapError; type Error = MapError;

@ -80,8 +80,8 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
/// An iterator visiting all keys in arbitrary order. The iterator element /// An iterator visiting all keys in arbitrary order. The iterator element
/// type is `Result<K, MapError>`. /// type is `Result<K, MapError>`.
pub unsafe fn keys(&self) -> MapKeys<'_, K, V> { pub unsafe fn keys(&self) -> MapKeys<'_, K> {
MapKeys::new(self) MapKeys::new(&self.inner)
} }
} }
@ -98,8 +98,8 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
} }
impl<T: Deref<Target = 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 map(&self) -> &Map {
self.inner.deref().fd_or_err() &self.inner
} }
unsafe fn get(&self, key: &K) -> Result<V, MapError> { unsafe fn get(&self, key: &K) -> Result<V, MapError> {

@ -90,8 +90,8 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
/// An iterator visiting all keys in arbitrary order. The iterator element /// An iterator visiting all keys in arbitrary order. The iterator element
/// type is `Result<K, MapError>`. /// type is `Result<K, MapError>`.
pub unsafe fn keys(&self) -> MapKeys<'_, K, PerCpuValues<V>> { pub unsafe fn keys(&self) -> MapKeys<'_, K> {
MapKeys::new(self) MapKeys::new(&self.inner)
} }
} }
@ -147,8 +147,8 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>> impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>>
for PerCpuHashMap<T, K, V> for PerCpuHashMap<T, K, V>
{ {
fn fd(&self) -> Result<RawFd, MapError> { fn map(&self) -> &Map {
self.inner.deref().fd_or_err() &self.inner
} }
unsafe fn get(&self, key: &K) -> Result<PerCpuValues<V>, MapError> { unsafe fn get(&self, key: &K) -> Result<PerCpuValues<V>, MapError> {

@ -29,7 +29,10 @@
//! //!
//! The code above uses `HashMap`, but all the concrete map types implement the //! The code above uses `HashMap`, but all the concrete map types implement the
//! `TryFrom` trait. //! `TryFrom` trait.
use std::{convert::TryFrom, ffi::CString, io, mem, ops::Deref, os::unix::io::RawFd, ptr}; use std::{
convert::TryFrom, ffi::CString, io, marker::PhantomData, mem, ops::Deref, os::unix::io::RawFd,
ptr,
};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
@ -148,19 +151,20 @@ impl Map {
} }
pub(crate) trait IterableMap<K: Pod, V> { pub(crate) trait IterableMap<K: Pod, V> {
fn fd(&self) -> Result<RawFd, MapError>; fn map(&self) -> &Map;
unsafe fn get(&self, key: &K) -> Result<V, MapError>; unsafe fn get(&self, key: &K) -> Result<V, MapError>;
} }
/// Iterator returned by `map.keys()`. /// Iterator returned by `map.keys()`.
pub struct MapKeys<'coll, K: Pod, V> { pub struct MapKeys<'coll, K: Pod> {
map: &'coll dyn IterableMap<K, V>, map: &'coll Map,
err: bool, err: bool,
key: Option<K>, key: Option<K>,
} }
impl<'coll, K: Pod, V> MapKeys<'coll, K, V> { impl<'coll, K: Pod> MapKeys<'coll, K> {
fn new(map: &'coll dyn IterableMap<K, V>) -> MapKeys<'coll, K, V> { fn new(map: &'coll Map) -> MapKeys<'coll, K> {
MapKeys { MapKeys {
map, map,
err: false, err: false,
@ -169,7 +173,7 @@ impl<'coll, K: Pod, V> MapKeys<'coll, K, V> {
} }
} }
impl<K: Pod, V> Iterator for MapKeys<'_, K, V> { impl<K: Pod> Iterator for MapKeys<'_, K> {
type Item = Result<K, MapError>; type Item = Result<K, MapError>;
fn next(&mut self) -> Option<Result<K, MapError>> { fn next(&mut self) -> Option<Result<K, MapError>> {
@ -177,7 +181,7 @@ impl<K: Pod, V> Iterator for MapKeys<'_, K, V> {
return None; return None;
} }
let fd = match self.map.fd() { let fd = match self.map.fd_or_err() {
Ok(fd) => fd, Ok(fd) => fd,
Err(e) => { Err(e) => {
self.err = true; self.err = true;
@ -208,13 +212,17 @@ impl<K: Pod, V> Iterator for MapKeys<'_, K, V> {
/// Iterator returned by `map.iter()`. /// Iterator returned by `map.iter()`.
pub struct MapIter<'coll, K: Pod, V> { pub struct MapIter<'coll, K: Pod, V> {
inner: MapKeys<'coll, K, V>, keys: MapKeys<'coll, K>,
map: &'coll dyn IterableMap<K, V>,
_v: PhantomData<V>,
} }
impl<'coll, K: Pod, V> MapIter<'coll, K, V> { impl<'coll, K: Pod, V> MapIter<'coll, K, V> {
fn new(map: &'coll dyn IterableMap<K, V>) -> MapIter<'coll, K, V> { fn new(map: &'coll dyn IterableMap<K, V>) -> MapIter<'coll, K, V> {
MapIter { MapIter {
inner: MapKeys::new(map), keys: MapKeys::new(map.map()),
map,
_v: PhantomData,
} }
} }
} }
@ -224,9 +232,9 @@ impl<K: Pod, V> Iterator for MapIter<'_, K, V> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
match self.inner.next() { match self.keys.next() {
Some(Ok(key)) => { Some(Ok(key)) => {
let value = unsafe { self.inner.map.get(&key) }; let value = unsafe { self.map.get(&key) };
match value { match value {
Ok(value) => return Some(Ok((key, value))), Ok(value) => return Some(Ok((key, value))),
Err(MapError::KeyNotFound) => continue, Err(MapError::KeyNotFound) => continue,

Loading…
Cancel
Save