diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 0687ee23..e7737867 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -55,6 +55,7 @@ pub(crate) struct bpf_map_def { pub(crate) map_flags: u32, } +/// Used to work with eBPF programs and maps. #[derive(Debug)] pub struct Bpf { maps: HashMap, @@ -62,6 +63,20 @@ pub struct Bpf { } impl Bpf { + /// Loads eBPF bytecode from a file. + /// + /// Parses the given object code file and initializes the [maps](crate::maps) defined in it. If + /// the kernel supports [BTF](Btf) debug info, it is automatically loaded from + /// `/sys/kernel/btf/vmlinux`. + /// + /// # Examples + /// + /// ```no_run + /// use aya::Bpf; + /// + /// let bpf = Bpf::load_file("file.o")?; + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn load_file>(path: P) -> Result { let path = path.as_ref(); Bpf::load( @@ -73,6 +88,23 @@ impl Bpf { ) } + /// Load eBPF bytecode. + /// + /// Parses the object code contained in `data` and initializes the [maps](crate::maps) defined + /// in it. If `target_btf` is `Some` and `data` includes BTF debug info, [BTF](Btf) relocations + /// are applied as well. + /// + /// # Examples + /// + /// ```no_run + /// use aya::{Bpf, Btf}; + /// use std::fs; + /// + /// let data = fs::read("file.o").unwrap(); + /// // load the BTF data from /sys/kernel/btf/vmlinux + /// let bpf = Bpf::load(&data, Some(Btf::from_sys_fs()?)); + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn load(data: &[u8], target_btf: Option) -> Result { let mut obj = Object::parse(data)?; @@ -155,6 +187,18 @@ impl Bpf { }) } + /// Returns a reference to the map with the given name. + /// + /// The returned type is mostly opaque. In order to do anything useful with it you need to + /// convert it to a [concrete map type](crate::maps). + /// + /// For more details and examples on maps and their usage, see the [maps module + /// documentation][crate::maps]. + /// + /// # Errors + /// + /// Returns [`MapError::NotFound`] 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 { self.maps .get(name) @@ -168,6 +212,18 @@ impl Bpf { }) } + /// Returns a mutable reference to the map with the given name. + /// + /// The returned type is mostly opaque. In order to do anything useful with it you need to + /// convert it to a [concrete map type](crate::maps). + /// + /// For more details and examples on maps and their usage, see the [maps module + /// documentation][crate::maps]. + /// + /// # Errors + /// + /// Returns [`MapError::NotFound`] 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 { self.maps .get(name) @@ -181,6 +237,20 @@ impl Bpf { }) } + /// An iterator over all the maps. + /// + /// # Examples + /// ```no_run + /// # let mut bpf = aya::Bpf::load(&[], None)?; + /// for (name, map) in bpf.maps() { + /// println!( + /// "found map `{}` of type `{:?}`", + /// name, + /// map?.map_type().unwrap() + /// ); + /// } + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn maps<'a>(&'a self) -> impl Iterator)> + 'a { let ret = self.maps.iter().map(|(name, lock)| { ( @@ -192,6 +262,26 @@ impl Bpf { ret } + /// Returns a reference to the program with the given name. + /// + /// You can use this to inspect a program and its properties. To load and attach a program, use + /// [program_mut](Self::program_mut) instead. + /// + /// For more details on programs and their usage, see the [programs module + /// documentation](crate::programs). + /// + /// # Errors + /// + /// Returns [`ProgramError::NotFound`] if the program does not exist. + /// + /// # Example + /// + /// ```no_run + /// # let bpf = aya::Bpf::load(&[], None)?; + /// let program = bpf.program("SSL_read")?; + /// println!("program SSL_read is of type {:?}", program.prog_type()); + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn program(&self, name: &str) -> Result<&Program, ProgramError> { self.programs .get(name) @@ -200,6 +290,27 @@ impl Bpf { }) } + /// Returns a mutable reference to the program with the given name. + /// + /// 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). + /// + /// # Errors + /// + /// Returns [`ProgramError::NotFound`] if the program does not exist. + /// + /// # Example + /// + /// ```no_run + /// # let mut bpf = aya::Bpf::load(&[], None)?; + /// use aya::programs::UProbe; + /// use std::convert::TryInto; + /// + /// let program: &mut UProbe = bpf.program_mut("SSL_read")?.try_into()?; + /// program.load()?; + /// program.attach(Some("SSL_read"), 0, "libssl", None)?; + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn program_mut(&mut self, name: &str) -> Result<&mut Program, ProgramError> { self.programs .get_mut(name) @@ -208,6 +319,20 @@ impl Bpf { }) } + /// An iterator over all the programs. + /// + /// # Examples + /// ```no_run + /// # let mut bpf = aya::Bpf::load(&[], None)?; + /// for program in bpf.programs() { + /// println!( + /// "found program `{}` of type `{:?}`", + /// program.name(), + /// program.prog_type() + /// ); + /// } + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn programs(&self) -> impl Iterator { self.programs.values() } diff --git a/aya/src/lib.rs b/aya/src/lib.rs index 11914960..86276d65 100644 --- a/aya/src/lib.rs +++ b/aya/src/lib.rs @@ -1,3 +1,33 @@ +//! A library to work with eBPF programs. +//! +//! eBPF is a technology that allows running user-supplied programs inside the +//! Linux kernel. For more info see +//! [https://ebpf.io/what-is-ebpf](https://ebpf.io/what-is-ebpf). +//! +//! Aya is an eBPF library built with a focus on operability and developer experience. It does not +//! rely on [libbpf](https://github.com/libbpf/libbpf) nor [bcc](https://github.com/iovisor/bcc) - +//! it's built from the ground up purely in Rust, using the Linux system call interface directly to +//! load and interact with programs. When linked with musl and in conjunction with BTF, it provides +//! a true [compile once, run everywhere solution](https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html). +//! +//! Some of the major features provided include: +//! +//! * Support for the BPF Type Format (BTF), which is transparently enabled when +//! supported by the target kernel. +//! * Support for global data maps, which means that eBPF programs can make use of global +//! data and variables. This is especially useful when the eBPF code itself is written +//! in Rust, and makes use of byte literals and other initializers that result +//! in global data being created. +//! * Support for function calls, so eBPF programs can call other functions and are not +//! forced to inline everything. +//! * Async support with both [tokio](https://docs.rs/tokio) and [async-std](https://docs.rs/async-std). +//! * 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. +//! +//! +//! # Minimum kernel version +//! +//! Aya currently supports kernels version 5.4 (latest LTS) and newer. #![deny(clippy::all)] #[macro_use]