Skip to main content

aya/
lib.rs

1//! [![](https://aya-rs.dev/assets/images/aya_logo_docs.svg)](https://aya-rs.dev)
2//!
3//! A library to work with eBPF programs.
4//!
5//! eBPF is a technology that allows running user-supplied programs inside the
6//! Linux kernel. For more info see
7//! [https://ebpf.io/what-is-ebpf](https://ebpf.io/what-is-ebpf).
8//!
9//! Aya is an eBPF library built with a focus on operability and developer experience. It does not
10//! rely on [libbpf](https://github.com/libbpf/libbpf) nor [bcc](https://github.com/iovisor/bcc) -
11//! it's built from the ground up purely in Rust, using only the [libc](https://crates.io/libc)
12//! crate to execute syscalls. With BTF support and when linked with musl, it offers a true
13//! [compile once, run everywhere
14//! solution](https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html),
15//! where a single self-contained binary can be deployed on many linux distributions
16//! and kernel versions.
17//!
18//! Some of the major features provided include:
19//!
20//! * Support for the **BPF Type Format** (BTF), which is transparently enabled when
21//!   supported by the target kernel. This allows eBPF programs compiled against
22//!   one kernel version to run on different kernel versions without the need to
23//!   recompile.
24//! * Support for function call relocation and global data maps, which
25//!   allows eBPF programs to make **function calls** and use **global variables
26//!   and initializers**.
27//! * **Async support** with both [tokio] and [async-std].
28//! * Easy to deploy and fast to build: aya doesn't require a kernel build or
29//!   compiled headers, and not even a C toolchain; a release build completes in a matter
30//!   of seconds.
31//!
32//! [tokio]: https://docs.rs/tokio
33//! [async-std]: https://docs.rs/async-std
34
35#![doc(
36    html_logo_url = "https://aya-rs.dev/assets/images/crabby.svg",
37    html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg"
38)]
39#![cfg_attr(docsrs, feature(doc_cfg))]
40#![deny(missing_docs)]
41#![cfg_attr(
42    all(test, not(feature = "test-helpers")),
43    expect(unused_crate_dependencies, reason = "used in doctests")
44)]
45
46mod bpf;
47pub mod maps;
48pub mod pin;
49pub mod programs;
50pub mod sys;
51#[cfg(feature = "test-helpers")]
52pub mod test_helpers;
53pub mod util;
54
55use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
56
57pub use aya_obj::btf::{Btf, BtfError};
58pub use bpf::*;
59pub use object::Endianness;
60pub use programs::{
61    RawTracePointRunOptions, RawTracePointTestRunResult, TestRun, TestRunAttrs, TestRunOptions,
62    TestRunResult,
63};
64#[doc(hidden)]
65pub use sys::netlink_set_link_up;
66
67// See https://github.com/rust-lang/rust/pull/124210; this structure exists to avoid crashing the
68// process when we try to close a fake file descriptor.
69#[derive(Debug)]
70struct MockableFd {
71    #[cfg(not(test))]
72    fd: OwnedFd,
73    #[cfg(test)]
74    fd: Option<OwnedFd>,
75}
76
77impl MockableFd {
78    #[cfg(test)]
79    const fn mock_signed_fd() -> i32 {
80        1337
81    }
82
83    #[cfg(test)]
84    const fn mock_unsigned_fd() -> u32 {
85        1337
86    }
87
88    #[cfg(not(test))]
89    const fn from_fd(fd: OwnedFd) -> Self {
90        Self { fd }
91    }
92
93    #[cfg(test)]
94    const fn from_fd(fd: OwnedFd) -> Self {
95        let fd = Some(fd);
96        Self { fd }
97    }
98
99    #[cfg(not(test))]
100    const fn inner(&self) -> &OwnedFd {
101        let Self { fd } = self;
102        fd
103    }
104
105    #[cfg(test)]
106    const fn inner(&self) -> &OwnedFd {
107        let Self { fd } = self;
108        fd.as_ref().unwrap()
109    }
110
111    #[cfg(not(test))]
112    fn into_inner(self) -> OwnedFd {
113        self.fd
114    }
115
116    #[cfg(test)]
117    fn into_inner(mut self) -> OwnedFd {
118        self.fd.take().unwrap()
119    }
120
121    fn try_clone(&self) -> std::io::Result<Self> {
122        let fd = self.inner();
123        let fd = fd.try_clone()?;
124        Ok(Self::from_fd(fd))
125    }
126}
127
128impl<T> From<T> for MockableFd
129where
130    OwnedFd: From<T>,
131{
132    fn from(value: T) -> Self {
133        let fd = OwnedFd::from(value);
134        Self::from_fd(fd)
135    }
136}
137
138impl AsFd for MockableFd {
139    fn as_fd(&self) -> BorrowedFd<'_> {
140        self.inner().as_fd()
141    }
142}
143
144impl AsRawFd for MockableFd {
145    fn as_raw_fd(&self) -> RawFd {
146        self.inner().as_raw_fd()
147    }
148}
149
150impl FromRawFd for MockableFd {
151    unsafe fn from_raw_fd(fd: RawFd) -> Self {
152        let fd = unsafe { OwnedFd::from_raw_fd(fd) };
153        Self::from_fd(fd)
154    }
155}
156
157#[cfg(test)]
158impl Drop for MockableFd {
159    fn drop(&mut self) {
160        use std::os::fd::{AsRawFd as _, IntoRawFd as _};
161
162        let Self { fd } = self;
163        let fd = fd.take().unwrap();
164        if fd.as_raw_fd() < Self::mock_signed_fd() {
165            drop(fd)
166        } else {
167            let _raw_fd = fd.into_raw_fd();
168        }
169    }
170}