More doc fixes

pull/1/head
Alessandro Decina 3 years ago
parent 28158e6028
commit 6c7df27bd0

@ -46,11 +46,13 @@ impl MapLock {
} }
} }
/// A borrowed reference to a BPF map.
pub struct MapRef { pub struct MapRef {
_lock: Arc<RwLock<Map>>, _lock: Arc<RwLock<Map>>,
guard: RwLockReadGuard<'static, Map>, guard: RwLockReadGuard<'static, Map>,
} }
/// A mutable borrowed reference to a BPF map.
pub struct MapRefMut { pub struct MapRefMut {
_lock: Arc<RwLock<Map>>, _lock: Arc<RwLock<Map>>,
guard: RwLockWriteGuard<'static, Map>, guard: RwLockWriteGuard<'static, Map>,

@ -117,6 +117,7 @@ pub enum MapError {
BorrowMutError { name: String }, BorrowMutError { name: String },
} }
/// A generic handle to a BPF map.
#[derive(Debug)] #[derive(Debug)]
pub struct Map { pub struct Map {
pub(crate) obj: obj::Map, pub(crate) obj: obj::Map,

@ -1,3 +1,4 @@
//! A FIFO queue.
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
marker::PhantomData, marker::PhantomData,

@ -1,3 +1,4 @@
//! Socket maps.
mod sock_hash; mod sock_hash;
mod sock_map; mod sock_map;

@ -14,22 +14,48 @@ use crate::{
Pod, Pod,
}; };
/// A hash map that can be shared between eBPF programs and user space. /// A hash map of TCP or UDP sockets.
/// ///
/// It is required that both keys and values implement the [`Pod`] trait. /// A `SockHash` is used to store TCP or UDP sockets. eBPF programs can then be
/// attached to the map to inspect, filter or redirect network buffers on those
/// sockets.
///
/// A `SockHash` can also be used to redirect packets to sockets contained by the
/// map using `bpf_redirect_map()`, `bpf_sk_redirect_hash()` etc.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// # let bpf = aya::Bpf::load(&[], None)?; /// ##[derive(Debug, thiserror::Error)]
/// # enum Error {
/// # #[error(transparent)]
/// # IO(#[from] std::io::Error),
/// # #[error(transparent)]
/// # Map(#[from] aya::maps::MapError),
/// # #[error(transparent)]
/// # Program(#[from] aya::programs::ProgramError),
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError)
/// # }
/// # let mut bpf = aya::Bpf::load(&[], None)?;
/// use std::convert::{TryFrom, TryInto};
/// use std::io::Write;
/// use std::net::TcpStream;
/// use std::os::unix::io::AsRawFd;
/// use aya::maps::SockHash; /// use aya::maps::SockHash;
/// use std::convert::TryFrom; /// use aya::programs::SkMsg;
///
/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_egress)?;
/// ///
/// const CONFIG_KEY_NUM_RETRIES: u8 = 1; /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
/// intercept_egress.insert(1234, client.as_raw_fd(), 0)?;
/// ///
/// let mut hm = SockHash::try_from(bpf.map_mut("CONFIG")?)?; /// // the write will be intercepted
/// hm.insert(CONFIG_KEY_NUM_RETRIES, 3, 0 /* flags */); /// client.write_all(b"foo")?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_SOCKHASH")] #[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
pub struct SockHash<T: Deref<Target = Map>, K> { pub struct SockHash<T: Deref<Target = Map>, K> {
@ -56,8 +82,8 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
}) })
} }
/// Returns a copy of the value associated with the key. /// Returns the fd of the socket stored at the given key.
pub unsafe fn get(&self, key: &K, flags: u64) -> Result<u32, MapError> { pub unsafe fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| {
MapError::SyscallError { MapError::SyscallError {
@ -71,7 +97,7 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
/// An iterator visiting all key-value pairs in arbitrary order. The /// An iterator visiting all key-value pairs in arbitrary order. The
/// iterator item type is `Result<(K, V), MapError>`. /// iterator item type is `Result<(K, V), MapError>`.
pub unsafe fn iter(&self) -> MapIter<'_, K, u32> { pub unsafe fn iter(&self) -> MapIter<'_, K, RawFd> {
MapIter::new(self) MapIter::new(self)
} }
@ -83,23 +109,23 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
} }
impl<T: DerefMut<Target = Map>, K: Pod> SockHash<T, K> { impl<T: DerefMut<Target = Map>, K: Pod> SockHash<T, K> {
/// Inserts a key-value pair into the map. /// Inserts a socket under the given key.
pub fn insert<I: AsRawFd>(&mut self, key: K, value: I, flags: u64) -> Result<(), MapError> { pub fn insert<I: AsRawFd>(&mut self, key: K, value: I, flags: u64) -> Result<(), MapError> {
hash_map::insert(&mut self.inner, key, value.as_raw_fd(), flags) hash_map::insert(&mut self.inner, key, value.as_raw_fd(), flags)
} }
/// Removes a key from the map. /// Removes a socket from the map.
pub fn remove(&mut self, key: &K) -> Result<(), MapError> { pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
hash_map::remove(&mut self.inner, key) hash_map::remove(&mut self.inner, key)
} }
} }
impl<T: Deref<Target = Map>, K: Pod> IterableMap<K, u32> for SockHash<T, K> { impl<T: Deref<Target = Map>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> {
fn map(&self) -> &Map { fn map(&self) -> &Map {
&self.inner &self.inner
} }
unsafe fn get(&self, key: &K) -> Result<u32, MapError> { unsafe fn get(&self, key: &K) -> Result<RawFd, MapError> {
SockHash::get(self, key, 0) SockHash::get(self, key, 0)
} }
} }

@ -13,14 +13,29 @@ use crate::{
sys::{bpf_map_delete_elem, bpf_map_update_elem}, sys::{bpf_map_delete_elem, bpf_map_update_elem},
}; };
/// An array of TCP or UDP sock objects. Primarly used for doing socket redirect with eBPF helpers. /// An array of TCP or UDP sockets.
/// ///
/// A sock map can have two eBPF programs attached: one to parse packets and one to provide a /// A `SockMap` is used to store TCP or UDP sockets. eBPF programs can then be
/// redirect decision on packets. Whenever a sock object is added to the map, the map's programs /// attached to the map to inspect, filter or redirect network buffers on those
/// are automatically attached to the socket. /// sockets.
///
/// A `SockMap` can also be used to redirect packets to sockets contained by the
/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc.
/// ///
/// # Example /// # Example
/// ///
/// ```no_run
/// # let mut bpf = aya::Bpf::load(&[], None)?;
/// use std::convert::{TryFrom, TryInto};
/// use aya::maps::SockMap;
/// use aya::programs::SkMsg;
///
/// let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_egress)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
pub struct SockMap<T: Deref<Target = Map>> { pub struct SockMap<T: Deref<Target = Map>> {
pub(crate) inner: T, pub(crate) inner: T,
} }
@ -66,10 +81,7 @@ impl<T: Deref<Target = Map>> SockMap<T> {
} }
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> { impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
/// Stores a TCP socket into the map. /// Stores a socket into the map.
///
/// eBPF programs can then pass `index` to the `bpf_sk_redirect_map()` helper to redirect
/// packets to the corresponding socket.
pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> { pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, 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)?;
@ -83,7 +95,7 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
Ok(()) Ok(())
} }
/// Removes the TCP socket stored at `index` from the map. /// Removes the socket stored at `index` from the map.
pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { pub fn clear_index(&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)?;

@ -1,3 +1,4 @@
//! A LIFO stack.
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
marker::PhantomData, marker::PhantomData,
@ -13,6 +14,19 @@ use crate::{
}; };
/// A LIFO stack. /// A LIFO stack.
///
/// # Example
/// ```no_run
/// # let bpf = aya::Bpf::load(&[], None)?;
/// use aya::maps::Stack;
/// use std::convert::TryFrom;
///
/// let mut stack = Stack::try_from(bpf.map_mut("STACK")?)?;
/// stack.push(42, 0)?;
/// stack.push(43, 0)?;
/// assert_eq!(stack.pop(0)?, 43);
/// # Ok::<(), aya::BpfError>(())
/// ```
pub struct Stack<T: Deref<Target = Map>, V: Pod> { pub struct Stack<T: Deref<Target = Map>, V: Pod> {
inner: T, inner: T,
_v: PhantomData<V>, _v: PhantomData<V>,
@ -78,19 +92,6 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
/// # Errors /// # Errors
/// ///
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
///
/// # Example
/// ```no_run
/// # let bpf = aya::Bpf::load(&[], None)?;
/// use aya::maps::Stack;
/// use std::convert::TryFrom;
///
/// let mut stack = Stack::try_from(bpf.map_mut("ARRAY")?)?;
/// stack.push(42, 0)?;
/// stack.push(43, 0)?;
/// assert_eq!(stack.pop(0)?, 43);
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> { pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
bpf_map_update_elem(fd, &0, &value, flags).map_err(|(code, io_error)| { bpf_map_update_elem(fd, &0, &value, flags).map_err(|(code, io_error)| {

@ -14,6 +14,15 @@ pub enum SkSkbKind {
StreamVerdict, StreamVerdict,
} }
/// A socket buffer program.
///
/// Socket buffer programs are attached to [socket maps], and can be used to
/// inspect, redirect or filter packet. See [SockMap] and [SockHash] for more
/// info and examples.
///
/// [socket maps]: crate::maps::sock
/// [SockMap]: crate::maps::SockMap
/// [SockHash]: crate::maps::SockHash
#[derive(Debug)] #[derive(Debug)]
pub struct SkSkb { pub struct SkSkb {
pub(crate) data: ProgramData, pub(crate) data: ProgramData,
@ -33,7 +42,7 @@ impl SkSkb {
self.data.name.to_string() self.data.name.to_string()
} }
/// Attaches the program to the given sockmap. /// Attaches the program to the given socket map.
pub fn attach(&mut self, map: &dyn SocketMap) -> Result<LinkRef, ProgramError> { pub fn attach(&mut self, map: &dyn SocketMap) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?; let prog_fd = self.data.fd_or_err()?;
let map_fd = map.fd_or_err()?; let map_fd = map.fd_or_err()?;

Loading…
Cancel
Save