aya: remove RwLocks and Ref wrappers on bpf maps.

This improves performance by removing the runtime checking of borrowing
rules. In order to retain a similar level of flexibility as the previous
implementation permitted, `take_map` and `return_map` are added as
methods to Bpf, allowing callers to move ownership of a Map.

This also removes the need for the parking_lot dependency.
pull/118/head
Thia Wyrod 3 years ago
parent 07a6016ebb
commit b90c1fe349
No known key found for this signature in database
GPG Key ID: 55D3AB7E5658CA0C

@ -17,7 +17,6 @@ object = { version = "0.27", default-features = false, features = ["std", "read_
bitflags = "1.2.1"
bytes = "1"
lazy_static = "1"
parking_lot = { version = "0.11.1", features = ["send_guard"] }
futures = { version = "0.3.12", optional = true, default-features = false, features = ["std"] }
tokio = { version = "1.2.0", features = ["macros", "rt", "rt-multi-thread", "net"], optional = true }
async-std = { version = "1.9.0", optional = true }

@ -1,6 +1,6 @@
use std::{
borrow::Cow,
collections::HashMap,
collections::{hash_map::Entry, HashMap},
error::Error,
ffi::CString,
fs, io,
@ -15,7 +15,7 @@ use crate::{
bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY, AYA_PERF_EVENT_IOC_DISABLE,
AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF,
},
maps::{Map, MapError, MapLock, MapRef, MapRefMut},
maps::{Map, MapError},
obj::{
btf::{Btf, BtfError},
Object, ParseError, ProgramSection,
@ -319,10 +319,6 @@ impl<'a> BpfLoader<'a> {
(name, program)
})
.collect();
let maps = maps
.drain()
.map(|(name, map)| (name, MapLock::new(map)))
.collect();
Ok(Bpf { maps, programs })
}
}
@ -336,7 +332,7 @@ impl<'a> Default for BpfLoader<'a> {
/// The main entry point into the library, used to work with eBPF programs and maps.
#[derive(Debug)]
pub struct Bpf {
maps: HashMap<String, MapLock>,
maps: HashMap<String, Map>,
programs: HashMap<String, Program>,
}
@ -395,47 +391,50 @@ impl Bpf {
///
/// For more details and examples on maps and their usage, see the [maps module
/// documentation][crate::maps].
pub fn map(&self, name: &str) -> Option<&Map> {
self.maps.get(name)
}
/// Returns a mutable reference to the map with the given name.
///
/// # Errors
/// The returned type is mostly opaque. In order to do anything useful with it you need to
/// convert it to a [typed map](crate::maps).
///
/// Returns [`MapError::MapNotFound`] if the map does not exist. If the map is already borrowed
/// mutably with [map_mut](Self::map_mut) then [`MapError::BorrowError`] is returned.
pub fn map(&self, name: &str) -> Result<MapRef, MapError> {
self.maps
.get(name)
.ok_or_else(|| MapError::MapNotFound {
name: name.to_owned(),
})
.and_then(|lock| {
lock.try_read().map_err(|_| MapError::BorrowError {
name: name.to_owned(),
})
})
/// For more details and examples on maps and their usage, see the [maps module
/// documentation][crate::maps].
pub fn map_mut(&mut self, name: &str) -> Option<&mut Map> {
self.maps.get_mut(name)
}
/// Returns a mutable reference to the map with the given name.
/// Take ownership of the map with the given name. Useful when intending to maintain frequent
/// access to a map without repeatedly incurring the cost of converting it into a
/// [typed map](crate::maps).
///
/// The returned type is mostly opaque. In order to do anything useful with it you need to
/// convert it to a [typed map](crate::maps).
///
/// For more details and examples on maps and their usage, see the [maps module
/// documentation][crate::maps].
pub fn take_map(&mut self, name: &str) -> Option<(String, Map)> {
self.maps.remove_entry(name)
}
/// Return ownership of the map with the given name. This is the dual of [take_map](Self::take_map).
///
/// For more details and examples on maps and their usage, see the [maps module
/// documentation][crate::maps].
///
/// # Errors
///
/// Returns [`MapError::MapNotFound`] if the map does not exist. If the map is already borrowed
/// mutably with [map_mut](Self::map_mut) then [`MapError::BorrowError`] is returned.
pub fn map_mut(&self, name: &str) -> Result<MapRefMut, MapError> {
self.maps
.get(name)
.ok_or_else(|| MapError::MapNotFound {
name: name.to_owned(),
})
.and_then(|lock| {
lock.try_write().map_err(|_| MapError::BorrowError {
name: name.to_owned(),
})
})
/// Returns [`MapError::Occupied`] if a map already exists at the given name.
pub fn return_map(&mut self, name: String, map: Map) -> Result<(), MapError> {
match self.maps.entry(name) {
Entry::Vacant(vacant) => {
vacant.insert(map);
Ok(())
}
Entry::Occupied(_) => Err(MapError::Occupied),
}
}
/// An iterator over all the maps.
@ -447,23 +446,16 @@ impl Bpf {
/// println!(
/// "found map `{}` of type `{:?}`",
/// name,
/// map?.map_type().unwrap()
/// map.map_type().unwrap()
/// );
/// }
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn maps(&self) -> impl Iterator<Item = (&str, Result<MapRef, MapError>)> {
let ret = self.maps.iter().map(|(name, lock)| {
(
name.as_str(),
lock.try_read()
.map_err(|_| MapError::BorrowError { name: name.clone() }),
)
});
ret
pub fn maps(&self) -> impl Iterator<Item = (&str, &Map)> {
self.maps.iter().map(|(s, m)| (s.as_str(), m))
}
/// Returns a reference to the program with the given name.
/// Returns a reference to the program with the given name if it exists.
///
/// You can use this to inspect a program and its properties. To load and attach a program, use
/// [program_mut](Self::program_mut) instead.
@ -483,7 +475,7 @@ impl Bpf {
self.programs.get(name)
}
/// Returns a mutable reference to the program with the given name.
/// Returns a mutable reference to the program with the given name if it exists.
///
/// Used to get a program before loading and attaching it. For more details on programs and
/// their usage, see the [programs module documentation](crate::programs).
@ -504,7 +496,7 @@ impl Bpf {
self.programs.get_mut(name)
}
/// An iterator over all the programs.
/// An iterator over all of the programs.
///
/// # Examples
/// ```no_run

@ -7,7 +7,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_ARRAY,
maps::{IterableMap, Map, MapError, MapRef, MapRefMut},
maps::{IterableMap, Map, MapError},
sys::{bpf_map_lookup_elem, bpf_map_update_elem},
Pod,
};
@ -23,11 +23,11 @@ use crate::{
///
/// # Examples
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::Array;
/// use std::convert::TryFrom;
///
/// let mut array = Array::try_from(bpf.map_mut("ARRAY")?)?;
/// let mut array = Array::try_from(bpf.map_mut("ARRAY").unwrap())?;
/// array.set(1, 42, 0)?;
/// assert_eq!(array.get(&1, 0)?, 42);
/// # Ok::<(), aya::BpfError>(())
@ -139,18 +139,18 @@ impl<T: Deref<Target = Map>, V: Pod> IterableMap<u32, V> for Array<T, V> {
}
}
impl<V: Pod> TryFrom<MapRef> for Array<MapRef, V> {
impl<'a, V: Pod> TryFrom<&'a Map> for Array<&'a Map, V> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<Array<MapRef, V>, MapError> {
fn try_from(a: &'a Map) -> Result<Array<&'a Map, V>, MapError> {
Array::new(a)
}
}
impl<V: Pod> TryFrom<MapRefMut> for Array<MapRefMut, V> {
impl<'a, V: Pod> TryFrom<&'a mut Map> for Array<&'a mut Map, V> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<Array<MapRefMut, V>, MapError> {
fn try_from(a: &'a mut Map) -> Result<Array<&'a mut Map, V>, MapError> {
Array::new(a)
}
}

@ -7,7 +7,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_PERCPU_ARRAY,
maps::{IterableMap, Map, MapError, MapRef, MapRefMut, PerCpuValues},
maps::{IterableMap, Map, MapError, PerCpuValues},
sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
Pod,
};
@ -32,12 +32,12 @@ use crate::{
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError)
/// # }
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::{PerCpuArray, PerCpuValues};
/// use aya::util::nr_cpus;
/// use std::convert::TryFrom;
///
/// let mut array = PerCpuArray::try_from(bpf.map_mut("ARRAY")?)?;
/// let mut array = PerCpuArray::try_from(bpf.map_mut("ARRAY").unwrap())?;
///
/// // set array[1] = 42 for all cpus
/// let nr_cpus = nr_cpus()?;
@ -158,18 +158,18 @@ impl<T: Deref<Target = Map>, V: Pod> IterableMap<u32, PerCpuValues<V>> for PerCp
}
}
impl<V: Pod> TryFrom<MapRef> for PerCpuArray<MapRef, V> {
impl<'a, V: Pod> TryFrom<&'a Map> for PerCpuArray<&'a Map, V> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<PerCpuArray<MapRef, V>, MapError> {
fn try_from(a: &'a Map) -> Result<PerCpuArray<&'a Map, V>, MapError> {
PerCpuArray::new(a)
}
}
impl<V: Pod> TryFrom<MapRefMut> for PerCpuArray<MapRefMut, V> {
impl<'a, V: Pod> TryFrom<&'a mut Map> for PerCpuArray<&'a mut Map, V> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<PerCpuArray<MapRefMut, V>, MapError> {
fn try_from(a: &'a mut Map) -> Result<PerCpuArray<&'a mut Map, V>, MapError> {
PerCpuArray::new(a)
}
}

@ -9,7 +9,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY,
maps::{Map, MapError, MapKeys, MapRef, MapRefMut},
maps::{Map, MapError, MapKeys},
programs::ProgramFd,
sys::{bpf_map_delete_elem, bpf_map_update_elem},
};
@ -26,12 +26,13 @@ use crate::{
///
/// # Examples
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::ProgramArray;
/// use aya::programs::{CgroupSkb, ProgramFd};
/// use std::convert::{TryFrom, TryInto};
///
/// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?;
/// let (name, mut map) = bpf.take_map("JUMP_TABLE").unwrap();
/// let mut prog_array = ProgramArray::try_from(&mut map)?;
/// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?;
/// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?;
/// let prog_2: &CgroupSkb = bpf.program("example_prog_2").unwrap().try_into()?;
@ -46,6 +47,8 @@ use crate::{
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 2) will jump to prog_2
/// prog_array.set(2, prog_2, flags);
///
/// bpf.return_map(name, map)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
#[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
@ -130,18 +133,18 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
}
}
impl TryFrom<MapRef> for ProgramArray<MapRef> {
impl<'a> TryFrom<&'a Map> for ProgramArray<&'a Map> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<ProgramArray<MapRef>, MapError> {
fn try_from(a: &'a Map) -> Result<ProgramArray<&'a Map>, MapError> {
ProgramArray::new(a)
}
}
impl TryFrom<MapRefMut> for ProgramArray<MapRefMut> {
impl<'a> TryFrom<&'a mut Map> for ProgramArray<&'a mut Map> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<ProgramArray<MapRefMut>, MapError> {
fn try_from(a: &'a mut Map) -> Result<ProgramArray<&'a mut Map>, MapError> {
ProgramArray::new(a)
}
}

@ -6,7 +6,7 @@ use std::{
use crate::{
generated::bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH},
maps::{hash_map, IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut},
maps::{hash_map, IterableMap, Map, MapError, MapIter, MapKeys},
sys::bpf_map_lookup_elem,
Pod,
};
@ -20,11 +20,11 @@ use crate::{
/// # Examples
///
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::HashMap;
/// use std::convert::TryFrom;
///
/// let mut redirect_ports = HashMap::try_from(bpf.map_mut("REDIRECT_PORTS")?)?;
/// let mut redirect_ports = HashMap::try_from(bpf.map_mut("REDIRECT_PORTS").unwrap())?;
///
/// // redirect port 80 to 8080
/// redirect_ports.insert(80, 8080, 0);
@ -108,22 +108,6 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K,
}
}
impl<K: Pod, V: Pod> TryFrom<MapRef> for HashMap<MapRef, K, V> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<HashMap<MapRef, K, V>, MapError> {
HashMap::new(a)
}
}
impl<K: Pod, V: Pod> TryFrom<MapRefMut> for HashMap<MapRefMut, K, V> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<HashMap<MapRefMut, K, V>, MapError> {
HashMap::new(a)
}
}
impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> {
type Error = MapError;

@ -7,9 +7,7 @@ use std::{
use crate::{
generated::bpf_map_type::{BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH},
maps::{
hash_map, IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut, PerCpuValues,
},
maps::{hash_map, IterableMap, Map, MapError, MapIter, MapKeys, PerCpuValues},
sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
Pod,
};
@ -27,14 +25,14 @@ use crate::{
/// # Examples
///
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::PerCpuHashMap;
/// use std::convert::TryFrom;
///
/// const CPU_IDS: u8 = 1;
/// 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").unwrap())?;
/// let cpu_ids = unsafe { hm.get(&CPU_IDS, 0)? };
/// let wakeups = unsafe { hm.get(&WAKEUPS, 0)? };
/// for (cpu_id, wakeups) in cpu_ids.iter().zip(wakeups.iter()) {
@ -113,14 +111,14 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError)
/// # }
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::{PerCpuHashMap, PerCpuValues};
/// use aya::util::nr_cpus;
/// use std::convert::TryFrom;
///
/// const RETRIES: u8 = 1;
///
/// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map_mut("PER_CPU_STORAGE")?)?;
/// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map_mut("PER_CPU_STORAGE").unwrap())?;
/// hm.insert(
/// RETRIES,
/// PerCpuValues::try_from(vec![3u32; nr_cpus()?])?,
@ -159,22 +157,6 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>>
}
}
impl<K: Pod, V: Pod> TryFrom<MapRef> for PerCpuHashMap<MapRef, K, V> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<PerCpuHashMap<MapRef, K, V>, MapError> {
PerCpuHashMap::new(a)
}
}
impl<K: Pod, V: Pod> TryFrom<MapRefMut> for PerCpuHashMap<MapRefMut, K, V> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<PerCpuHashMap<MapRefMut, K, V>, MapError> {
PerCpuHashMap::new(a)
}
}
impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for PerCpuHashMap<&'a Map, K, V> {
type Error = MapError;

@ -1,81 +0,0 @@
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::{
mem,
ops::{Deref, DerefMut},
sync::Arc,
};
use crate::maps::Map;
pub(crate) struct MapLockError;
/* FIXME: write a full RwLock implementation that doesn't use borrowing guards
* so that try_read() and try_write() don't have to use the ugly lifetime
* extension hack */
#[derive(Debug)]
pub(crate) struct MapLock {
inner: Arc<RwLock<Map>>,
}
impl MapLock {
pub(crate) fn new(map: Map) -> MapLock {
MapLock {
inner: Arc::new(RwLock::new(map)),
}
}
pub(crate) fn try_read(&self) -> Result<MapRef, MapLockError> {
let lock: Option<RwLockReadGuard<'static, Map>> =
unsafe { mem::transmute(self.inner.try_read()) };
lock.map(|guard| MapRef {
_lock: self.inner.clone(),
guard,
})
.ok_or(MapLockError)
}
pub(crate) fn try_write(&self) -> Result<MapRefMut, MapLockError> {
let lock: Option<RwLockWriteGuard<'static, Map>> =
unsafe { mem::transmute(self.inner.try_write()) };
lock.map(|guard| MapRefMut {
_lock: self.inner.clone(),
guard,
})
.ok_or(MapLockError)
}
}
/// A borrowed reference to a BPF map.
pub struct MapRef {
_lock: Arc<RwLock<Map>>,
guard: RwLockReadGuard<'static, Map>,
}
/// A mutable borrowed reference to a BPF map.
pub struct MapRefMut {
_lock: Arc<RwLock<Map>>,
guard: RwLockWriteGuard<'static, Map>,
}
impl Deref for MapRef {
type Target = Map;
fn deref(&self) -> &Map {
&*self.guard
}
}
impl Deref for MapRefMut {
type Target = Map;
fn deref(&self) -> &Map {
&*self.guard
}
}
impl DerefMut for MapRefMut {
fn deref_mut(&mut self) -> &mut Map {
&mut *self.guard
}
}

@ -11,7 +11,7 @@
//!
//! The eBPF API includes many map types each supporting different operations.
//! [`Bpf::map`](crate::Bpf::map) and [`Bpf::map_mut`](crate::Bpf::map_mut) always return the
//! opaque [`MapRef`] and [`MapRefMut`] types respectively. Those two types can be converted to
//! opaque &Map and &mut Map types respectively. Those two types can be converted to
//! *typed maps* using the [`TryFrom`](std::convert::TryFrom) trait. For example:
//!
//! ```no_run
@ -20,10 +20,12 @@
//! use aya::maps::SockMap;
//! use aya::programs::SkMsg;
//!
//! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
//! let (name, mut map) = bpf.take_map("INTERCEPT_EGRESS").unwrap();
//! let intercept_egress = SockMap::try_from(&mut map)?;
//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
//! prog.load()?;
//! prog.attach(&intercept_egress)?;
//! bpf.return_map(name, map)?;
//! # Ok::<(), aya::BpfError>(())
//! ```
//!
@ -46,8 +48,6 @@ use crate::{
Pod,
};
mod map_lock;
pub mod array;
pub mod hash_map;
pub mod perf;
@ -58,7 +58,6 @@ pub mod stack_trace;
pub use array::{Array, PerCpuArray, ProgramArray};
pub use hash_map::{HashMap, PerCpuHashMap};
pub use map_lock::*;
pub use perf::PerfEventArray;
pub use queue::Queue;
pub use sock::{SockHash, SockMap};
@ -67,8 +66,8 @@ pub use stack_trace::StackTraceMap;
#[derive(Error, Debug)]
pub enum MapError {
#[error("map `{name}` not found ")]
MapNotFound { name: String },
#[error("map already exists")]
Occupied,
#[error("invalid map type {map_type}")]
InvalidMapType { map_type: u32 },
@ -129,12 +128,6 @@ pub enum MapError {
#[source]
io_error: io::Error,
},
#[error("map `{name}` is borrowed mutably")]
BorrowError { name: String },
#[error("map `{name}` is already borrowed")]
BorrowMutError { name: String },
}
/// A generic handle to a BPF map.

@ -13,7 +13,7 @@ use tokio::io::unix::AsyncFd;
use crate::maps::{
perf::{Events, PerfBufferError, PerfEventArray, PerfEventArrayBuffer},
Map, MapError, MapRefMut,
Map, MapError,
};
/// A `Future` based map that can be used to receive events from eBPF programs using the linux
@ -198,10 +198,10 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
}
}
impl TryFrom<MapRefMut> for AsyncPerfEventArray<MapRefMut> {
impl<'a> TryFrom<&'a mut Map> for AsyncPerfEventArray<&'a mut Map> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<AsyncPerfEventArray<MapRefMut>, MapError> {
fn try_from(a: &'a mut Map) -> Result<AsyncPerfEventArray<&'a mut Map>, MapError> {
AsyncPerfEventArray::new(a)
}
}

@ -15,7 +15,7 @@ use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY,
maps::{
perf::{Events, PerfBuffer, PerfBufferError},
Map, MapError, MapRefMut,
Map, MapError,
},
sys::bpf_map_update_elem,
};
@ -109,13 +109,13 @@ impl<T: DerefMut<Target = Map>> AsRawFd for PerfEventArrayBuffer<T> {
/// # #[error(transparent)]
/// # PerfBuf(#[from] aya::maps::perf::PerfBufferError),
/// # }
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::PerfEventArray;
/// use aya::util::online_cpus;
/// use std::convert::{TryFrom, TryInto};
/// use bytes::BytesMut;
///
/// let mut perf_array = PerfEventArray::try_from(bpf.map_mut("EVENTS")?)?;
/// let mut perf_array = PerfEventArray::try_from(bpf.map_mut("EVENTS").unwrap())?;
///
/// // eBPF programs are going to write to the EVENTS perf array, using the id of the CPU they're
/// // running on as the array index.
@ -205,10 +205,10 @@ impl<T: DerefMut<Target = Map>> PerfEventArray<T> {
}
}
impl TryFrom<MapRefMut> for PerfEventArray<MapRefMut> {
impl<'a> TryFrom<&'a mut Map> for PerfEventArray<&'a mut Map> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<PerfEventArray<MapRefMut>, MapError> {
fn try_from(a: &'a mut Map) -> Result<PerfEventArray<&'a mut Map>, MapError> {
PerfEventArray::new(a)
}
}

@ -8,7 +8,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_QUEUE,
maps::{Map, MapError, MapRef, MapRefMut},
maps::{Map, MapError},
sys::{bpf_map_lookup_and_delete_elem, bpf_map_push_elem},
Pod,
};
@ -21,11 +21,11 @@ use crate::{
///
/// # Examples
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::Queue;
/// use std::convert::TryFrom;
///
/// let mut queue = Queue::try_from(bpf.map_mut("ARRAY")?)?;
/// let mut queue = Queue::try_from(bpf.map_mut("ARRAY").unwrap())?;
/// queue.push(42, 0)?;
/// queue.push(43, 0)?;
/// assert_eq!(queue.pop(0)?, 42);
@ -110,18 +110,18 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
}
}
impl<V: Pod> TryFrom<MapRef> for Queue<MapRef, V> {
impl<'a, V: Pod> TryFrom<&'a Map> for Queue<&'a Map, V> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<Queue<MapRef, V>, MapError> {
fn try_from(a: &'a Map) -> Result<Queue<&'a Map, V>, MapError> {
Queue::new(a)
}
}
impl<V: Pod> TryFrom<MapRefMut> for Queue<MapRefMut, V> {
impl<'a, V: Pod> TryFrom<&'a mut Map> for Queue<&'a mut Map, V> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<Queue<MapRefMut, V>, MapError> {
fn try_from(a: &'a mut Map) -> Result<Queue<&'a mut Map, V>, MapError> {
Queue::new(a)
}
}

@ -7,9 +7,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_SOCKHASH,
maps::{
hash_map, sock::SocketMap, IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut,
},
maps::{hash_map, sock::SocketMap, IterableMap, Map, MapError, MapIter, MapKeys},
sys::bpf_map_lookup_elem,
Pod,
};
@ -49,13 +47,15 @@ use crate::{
/// use aya::maps::SockHash;
/// use aya::programs::SkMsg;
///
/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
/// let (name, mut map) = bpf.take_map("INTERCEPT_EGRESS").unwrap();
/// let mut intercept_egress = SockHash::try_from(&mut map)?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_egress)?;
///
/// let mut client = TcpStream::connect("127.0.0.1:1234")?;
/// intercept_egress.insert(1234, client.as_raw_fd(), 0)?;
/// bpf.return_map(name, map)?;
///
/// // the write will be intercepted
/// client.write_all(b"foo")?;
@ -140,18 +140,18 @@ impl<T: DerefMut<Target = Map>, K: Pod> SocketMap for SockHash<T, K> {
}
}
impl<K: Pod> TryFrom<MapRef> for SockHash<MapRef, K> {
impl<'a, K: Pod> TryFrom<&'a Map> for SockHash<&'a Map, K> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<SockHash<MapRef, K>, MapError> {
fn try_from(a: &'a Map) -> Result<SockHash<&'a Map, K>, MapError> {
SockHash::new(a)
}
}
impl<K: Pod> TryFrom<MapRefMut> for SockHash<MapRefMut, K> {
impl<'a, K: Pod> TryFrom<&'a mut Map> for SockHash<&'a mut Map, K> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<SockHash<MapRefMut, K>, MapError> {
fn try_from(a: &'a mut Map) -> Result<SockHash<&'a mut Map, K>, MapError> {
SockHash::new(a)
}
}

@ -9,7 +9,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_SOCKMAP,
maps::{sock::SocketMap, Map, MapError, MapKeys, MapRef, MapRefMut},
maps::{sock::SocketMap, Map, MapError, MapKeys},
sys::{bpf_map_delete_elem, bpf_map_update_elem},
};
@ -34,10 +34,12 @@ use crate::{
/// use aya::maps::SockMap;
/// use aya::programs::SkSkb;
///
/// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?;
/// let (name, mut map) = bpf.take_map("INTERCEPT_EGRESS").unwrap();
/// let intercept_ingress = SockMap::try_from(&mut map)?;
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_ingress)?;
/// bpf.return_map(name, map)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
#[doc(alias = "BPF_MAP_TYPE_SOCKMAP")]
@ -120,18 +122,18 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SocketMap for SockMap<T> {
}
}
impl TryFrom<MapRef> for SockMap<MapRef> {
impl<'a> TryFrom<&'a Map> for SockMap<&'a Map> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<SockMap<MapRef>, MapError> {
fn try_from(a: &'a Map) -> Result<SockMap<&'a Map>, MapError> {
SockMap::new(a)
}
}
impl TryFrom<MapRefMut> for SockMap<MapRefMut> {
impl<'a> TryFrom<&'a mut Map> for SockMap<&'a mut Map> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<SockMap<MapRefMut>, MapError> {
fn try_from(a: &'a mut Map) -> Result<SockMap<&'a mut Map>, MapError> {
SockMap::new(a)
}
}

@ -8,7 +8,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_STACK,
maps::{Map, MapError, MapRef, MapRefMut},
maps::{Map, MapError},
sys::{bpf_map_lookup_and_delete_elem, bpf_map_update_elem},
Pod,
};
@ -21,11 +21,11 @@ use crate::{
///
/// # Examples
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::Stack;
/// use std::convert::TryFrom;
///
/// let mut stack = Stack::try_from(bpf.map_mut("STACK")?)?;
/// let mut stack = Stack::try_from(bpf.map_mut("STACK").unwrap())?;
/// stack.push(42, 0)?;
/// stack.push(43, 0)?;
/// assert_eq!(stack.pop(0)?, 43);
@ -110,18 +110,18 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
}
}
impl<V: Pod> TryFrom<MapRef> for Stack<MapRef, V> {
impl<'a, V: Pod> TryFrom<&'a Map> for Stack<&'a Map, V> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<Stack<MapRef, V>, MapError> {
fn try_from(a: &'a Map) -> Result<Stack<&'a Map, V>, MapError> {
Stack::new(a)
}
}
impl<V: Pod> TryFrom<MapRefMut> for Stack<MapRefMut, V> {
impl<'a, V: Pod> TryFrom<&'a mut Map> for Stack<&'a mut Map, V> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<Stack<MapRefMut, V>, MapError> {
fn try_from(a: &'a mut Map) -> Result<Stack<&'a mut Map, V>, MapError> {
Stack::new(a)
}
}

@ -7,7 +7,7 @@ use std::{
use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_STACK_TRACE,
maps::{IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut},
maps::{IterableMap, Map, MapError, MapIter, MapKeys},
sys::bpf_map_lookup_elem_ptr,
};
@ -39,7 +39,7 @@ use crate::{
/// use aya::util::kernel_symbols;
/// use std::convert::TryFrom;
///
/// let mut stack_traces = StackTraceMap::try_from(bpf.map("STACK_TRACES")?)?;
/// let mut stack_traces = StackTraceMap::try_from(bpf.map("STACK_TRACES").unwrap())?;
/// // load kernel symbols from /proc/kallsyms
/// let ksyms = kernel_symbols()?;
///
@ -161,18 +161,18 @@ impl<T: Deref<Target = Map>> IterableMap<u32, StackTrace> for StackTraceMap<T> {
}
}
impl TryFrom<MapRef> for StackTraceMap<MapRef> {
impl<'a> TryFrom<&'a Map> for StackTraceMap<&'a Map> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<StackTraceMap<MapRef>, MapError> {
fn try_from(a: &'a Map) -> Result<StackTraceMap<&'a Map>, MapError> {
StackTraceMap::new(a)
}
}
impl TryFrom<MapRefMut> for StackTraceMap<MapRefMut> {
impl<'a> TryFrom<&'a mut Map> for StackTraceMap<&'a mut Map> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<StackTraceMap<MapRefMut>, MapError> {
fn try_from(a: &'a mut Map) -> Result<StackTraceMap<&'a mut Map>, MapError> {
StackTraceMap::new(a)
}
}

@ -37,7 +37,8 @@ use crate::{
/// use aya::maps::SockHash;
/// use aya::programs::SkMsg;
///
/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
/// let (name, mut map) = bpf.take_map("INTERCEPT_EGRESS").unwrap();
/// let mut intercept_egress = SockHash::try_from(&mut map)?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_egress)?;
@ -47,6 +48,7 @@ use crate::{
///
/// // the write will be intercepted
/// client.write_all(b"foo")?;
/// bpf.return_map(name, map)?;
/// # Ok::<(), Error>(())
/// ```
///

@ -33,10 +33,12 @@ pub enum SkSkbKind {
/// use aya::maps::SockMap;
/// use aya::programs::SkSkb;
///
/// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?;
/// let (name, mut map) = bpf.take_map("INTERCEPT_EGRESS").unwrap();
/// let intercept_ingress = SockMap::try_from(&mut map)?;
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_ingress)?;
/// bpf.return_map(name, map)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
///

Loading…
Cancel
Save