aya: more docs

pull/1/head
Alessandro Decina 4 years ago
parent eea27f52f3
commit 04fde46855

@ -24,7 +24,6 @@
//! * Easy to deploy and fast to build: aya doesn't require kernel headers nor a //! * Easy to deploy and fast to build: aya doesn't require kernel headers nor a
//! C toolchain and a release build completes in a matter of seconds. //! C toolchain and a release build completes in a matter of seconds.
//! //!
//!
//! # Minimum kernel version //! # Minimum kernel version
//! //!
//! Aya currently supports kernels version 5.4 (latest LTS) and newer. //! Aya currently supports kernels version 5.4 (latest LTS) and newer.

@ -1,19 +1,17 @@
//! eBPF map types. //! eBPF data structures used to exchange data with eBPF programs.
//! //!
//! The eBPF platform provides data structures - maps in eBPF speak - that can be used by eBPF //! The eBPF platform provides data structures - maps in eBPF speak - that can be used by eBPF
//! programs and user-space to exchange data. //! programs and user-space to exchange data. When you call
//! //! [`Bpf::load_file`](crate::Bpf::load_file) or [`Bpf::load`](crate::Bpf::load), all the maps
//! When you call [`Bpf::load_file`](crate::Bpf::load_file) or [`Bpf::load`](crate::Bpf::load), aya //! defined in the code get initialized and can then be accessed using
//! transparently discovers all the maps defined in the loaded code and initializes them. The maps //! [`Bpf::map`](crate::Bpf::map) and [`Bpf::map_mut`](crate::Bpf::map_mut).
//! can then be accessed using [`Bpf::map`](crate::Bpf::map) and [`Bpf::map_mut`](crate::Bpf::map_mut).
//! //!
//! # Concrete map types //! # Concrete map types
//! //!
//! Different map types support different operations. [`Bpf::map`](crate::Bpf::map) and //! The eBPF platform provides many map types each supporting different operations.
//! [`Bpf::map_mut`](crate::Bpf::map_mut) always return the opaque [`MapRef`] and [`MapRefMut`] //! [`Bpf::map`](crate::Bpf::map) and [`Bpf::map_mut`](crate::Bpf::map_mut) always return the
//! types respectively, which you can convert to concrete map types using the //! opaque [`MapRef`] and [`MapRefMut`] types respectively. Those two types can be converted to
//! [`TryFrom`](std::convert::TryFrom) trait. For example the code below shows how to insert a //! *concrete map types* using the [`TryFrom`](std::convert::TryFrom) trait. For example:
//! value inside a [`HashMap`](crate::maps::hash_map::HashMap):
//! //!
//! ```no_run //! ```no_run
//! # let bpf = aya::Bpf::load(&[], None)?; //! # let bpf = aya::Bpf::load(&[], None)?;
@ -22,12 +20,15 @@
//! //!
//! const CONFIG_KEY_NUM_RETRIES: u8 = 1; //! const CONFIG_KEY_NUM_RETRIES: u8 = 1;
//! //!
//! // HashMap::try_from() converts MapRefMut to HashMap. It will fail if CONFIG is not an eBPF
//! // hash map.
//! let mut hm = HashMap::try_from(bpf.map_mut("CONFIG")?)?; //! let mut hm = HashMap::try_from(bpf.map_mut("CONFIG")?)?;
//! hm.insert(CONFIG_KEY_NUM_RETRIES, 3, 0 /* flags */); //! hm.insert(CONFIG_KEY_NUM_RETRIES, 3, 0 /* flags */);
//! # Ok::<(), aya::BpfError>(()) //! # Ok::<(), aya::BpfError>(())
//! ``` //! ```
//! //!
//! All the concrete map types implement the [`TryFrom`](std::convert::TryFrom) trait. //! The code above uses `HashMap`, but all the concrete map types implement the
//! `TryFrom` trait.
use std::{convert::TryFrom, ffi::CString, io, os::unix::io::RawFd}; use std::{convert::TryFrom, ffi::CString, io, os::unix::io::RawFd};
use thiserror::Error; use thiserror::Error;

@ -16,6 +16,75 @@ use crate::maps::{
Map, MapError, MapRefMut, Map, MapError, MapRefMut,
}; };
/// A `Future` based map that can be used to receive events from eBPF programs using the linux
/// [`perf`](https://perf.wiki.kernel.org/index.php/Main_Page) API.
///
/// This is the async version of [`PerfEventArray`], which provides integration
/// with [tokio](https://docs.rs/tokio) and [async-std](https:/docs.rs/async-std) and a nice `Future` based API.
///
/// To receive events you need to:
/// * call [`AsyncPerfEventArray::open`]
/// * call [`AsyncPerfEventArrayBuffer::read_events`] to read the events
///
/// # Example
///
/// ```no_run
/// # #[derive(thiserror::Error, Debug)]
/// # enum Error {
/// # #[error(transparent)]
/// # IO(#[from] std::io::Error),
/// # #[error(transparent)]
/// # Map(#[from] aya::maps::MapError),
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError),
/// # #[error(transparent)]
/// # PerfBuf(#[from] aya::maps::perf::PerfBufferError),
/// # }
/// # async fn try_main() -> Result<(), Error> {
/// # use async_std::task;
/// # let bpf = aya::Bpf::load(&[], None)?;
/// use aya::maps::perf::{AsyncPerfEventArray, PerfBufferError};
/// use aya::util::online_cpus;
/// use std::convert::TryFrom;
/// use futures::future;
/// use bytes::BytesMut;
///
/// // try to convert the PERF_ARRAY map to an AsyncPerfEventArray
/// let mut perf_array = AsyncPerfEventArray::try_from(bpf.map_mut("PERF_ARRAY")?)?;
///
/// let mut futs = Vec::new();
/// for cpu_id in online_cpus()? {
/// // open a separate perf buffer for each cpu
/// let mut buf = perf_array.open(cpu_id, None)?;
///
/// // process each perf buffer in a separate task
/// // NOTE: use async_std::task::spawn with async-std and tokio::spawn with tokio
/// futs.push(task::spawn(async move {
/// let mut buffers = (0..10)
/// .map(|_| BytesMut::with_capacity(1024))
/// .collect::<Vec<_>>();
///
/// loop {
/// // wait for events
/// let events = buf.read_events(&mut buffers).await?;
///
/// // events.read contains the number of events that have been read,
/// // and is always <= buffers.len()
/// for i in 0..events.read {
/// let buf = &mut buffers[i];
/// // process buf
/// }
/// }
///
/// Ok::<_, PerfBufferError>(())
/// }));
/// }
///
///
/// future::join_all(futs).await;
/// # Ok(())
/// # }
/// ```
pub struct AsyncPerfEventArray<T: DerefMut<Target = Map>> { pub struct AsyncPerfEventArray<T: DerefMut<Target = Map>> {
perf_map: PerfEventArray<T>, perf_map: PerfEventArray<T>,
} }
@ -34,7 +103,7 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArray<T> {
#[cfg(feature = "async_tokio")] #[cfg(feature = "async_tokio")]
async_fd: AsyncFd::new(fd)?, async_fd: AsyncFd::new(fd)?,
#[cfg(feature = "async_std")] #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))]
async_fd: Async::new(fd)?, async_fd: Async::new(fd)?,
}) })
} }
@ -48,13 +117,20 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArray<T> {
} }
} }
/// A `Future` based ring buffer that can receive events from eBPF programs.
///
/// [`AsyncPerfEventArrayBuffer`] is a ring buffer that can receive events from eBPF programs that
/// use `bpf_perf_event_output()`. It's returned by [`AsyncPerfEventArray::open`].
///
/// See the [`AsyncPerfEventArray` documentation](AsyncPerfEventArray) for an overview of how to
/// use perf buffers.
pub struct AsyncPerfEventArrayBuffer<T: DerefMut<Target = Map>> { pub struct AsyncPerfEventArrayBuffer<T: DerefMut<Target = Map>> {
buf: PerfEventArrayBuffer<T>, buf: PerfEventArrayBuffer<T>,
#[cfg(feature = "async_tokio")] #[cfg(feature = "async_tokio")]
async_fd: AsyncFd<RawFd>, async_fd: AsyncFd<RawFd>,
#[cfg(feature = "async_std")] #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))]
async_fd: Async<RawFd>, async_fd: Async<RawFd>,
} }
@ -79,7 +155,7 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
} }
} }
#[cfg(feature = "async_std")] #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))]
impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> { impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
pub async fn read_events( pub async fn read_events(
&mut self, &mut self,

@ -1,12 +1,12 @@
//! Receive events from eBPF programs using the linux `perf` API. //! Ring buffer types used to receive events from eBPF programs using the linux `perf` API.
//! //!
//! See the [`PerfEventArray` documentation](self::PerfEventArray). //! See the [`PerfEventArray`] and [`AsyncPerfEventArray`].
#[cfg(feature = "async")] #[cfg(any(feature = "async", doc))]
mod async_perf_event_array; mod async_perf_event_array;
mod perf_buffer; mod perf_buffer;
mod perf_event_array; mod perf_event_array;
#[cfg(feature = "async")] #[cfg(any(feature = "async", doc))]
pub use async_perf_event_array::*; pub use async_perf_event_array::*;
pub use perf_buffer::*; pub use perf_buffer::*;
pub use perf_event_array::*; pub use perf_event_array::*;

@ -20,7 +20,7 @@ use crate::{
sys::bpf_map_update_elem, sys::bpf_map_update_elem,
}; };
/// A buffer that can receive events from eBPF programs. /// A ring buffer that can receive events from eBPF programs.
/// ///
/// [`PerfEventArrayBuffer`] is a ring buffer that can receive events from eBPF /// [`PerfEventArrayBuffer`] is a ring buffer that can receive events from eBPF
/// programs that use `bpf_perf_event_output()`. It's returned by [`PerfEventArray::open`]. /// programs that use `bpf_perf_event_output()`. It's returned by [`PerfEventArray::open`].

@ -1,4 +1,4 @@
//! Program array (jump table) for eBPF programs. //! An array of eBPF program file descriptors used as a jump table.
use std::{ use std::{
convert::TryFrom, convert::TryFrom,

@ -1,8 +1,10 @@
//! Utility functions.
use std::{fs, io, str::FromStr}; use std::{fs, io, str::FromStr};
const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online"; const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online";
pub(crate) const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible"; pub(crate) const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible";
/// Returns the numeric IDs of the available CPUs.
pub fn online_cpus() -> Result<Vec<u32>, io::Error> { pub fn online_cpus() -> Result<Vec<u32>, io::Error> {
let data = fs::read_to_string(ONLINE_CPUS)?; let data = fs::read_to_string(ONLINE_CPUS)?;
parse_cpu_ranges(data.trim()).map_err(|_| { parse_cpu_ranges(data.trim()).map_err(|_| {
@ -13,7 +15,7 @@ pub fn online_cpus() -> Result<Vec<u32>, io::Error> {
}) })
} }
pub fn possible_cpus() -> Result<Vec<u32>, io::Error> { pub(crate) fn possible_cpus() -> Result<Vec<u32>, io::Error> {
let data = fs::read_to_string(POSSIBLE_CPUS)?; let data = fs::read_to_string(POSSIBLE_CPUS)?;
parse_cpu_ranges(data.trim()).map_err(|_| { parse_cpu_ranges(data.trim()).map_err(|_| {
io::Error::new( io::Error::new(

Loading…
Cancel
Save