Skip to main content

aya_friday/
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(test, expect(unused_crate_dependencies, reason = "used in doctests"))]
42
43mod bpf;
44pub mod maps;
45pub mod pin;
46pub mod programs;
47pub mod sys;
48pub mod util;
49
50use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
51
52pub use aya_obj::btf::{Btf, BtfError};
53pub use bpf::*;
54pub use object::Endianness;
55pub use programs::{
56    RawTracePointRunOptions, RawTracePointTestRunResult, TestRun, TestRunAttrs, TestRunOptions,
57    TestRunResult,
58};
59#[doc(hidden)]
60pub use sys::netlink_set_link_up;
61
62// See https://github.com/rust-lang/rust/pull/124210; this structure exists to avoid crashing the
63// process when we try to close a fake file descriptor.
64#[derive(Debug)]
65struct MockableFd {
66    #[cfg(not(test))]
67    fd: OwnedFd,
68    #[cfg(test)]
69    fd: Option<OwnedFd>,
70}
71
72impl MockableFd {
73    #[cfg(test)]
74    const fn mock_signed_fd() -> i32 {
75        1337
76    }
77
78    #[cfg(test)]
79    const fn mock_unsigned_fd() -> u32 {
80        1337
81    }
82
83    #[cfg(not(test))]
84    const fn from_fd(fd: OwnedFd) -> Self {
85        Self { fd }
86    }
87
88    #[cfg(test)]
89    const fn from_fd(fd: OwnedFd) -> Self {
90        let fd = Some(fd);
91        Self { fd }
92    }
93
94    #[cfg(not(test))]
95    const fn inner(&self) -> &OwnedFd {
96        let Self { fd } = self;
97        fd
98    }
99
100    #[cfg(test)]
101    const fn inner(&self) -> &OwnedFd {
102        let Self { fd } = self;
103        fd.as_ref().unwrap()
104    }
105
106    #[cfg(not(test))]
107    fn into_inner(self) -> OwnedFd {
108        self.fd
109    }
110
111    #[cfg(test)]
112    fn into_inner(mut self) -> OwnedFd {
113        self.fd.take().unwrap()
114    }
115
116    fn try_clone(&self) -> std::io::Result<Self> {
117        let fd = self.inner();
118        let fd = fd.try_clone()?;
119        Ok(Self::from_fd(fd))
120    }
121}
122
123impl<T> From<T> for MockableFd
124where
125    OwnedFd: From<T>,
126{
127    fn from(value: T) -> Self {
128        let fd = OwnedFd::from(value);
129        Self::from_fd(fd)
130    }
131}
132
133impl AsFd for MockableFd {
134    fn as_fd(&self) -> BorrowedFd<'_> {
135        self.inner().as_fd()
136    }
137}
138
139impl AsRawFd for MockableFd {
140    fn as_raw_fd(&self) -> RawFd {
141        self.inner().as_raw_fd()
142    }
143}
144
145impl FromRawFd for MockableFd {
146    unsafe fn from_raw_fd(fd: RawFd) -> Self {
147        let fd = unsafe { OwnedFd::from_raw_fd(fd) };
148        Self::from_fd(fd)
149    }
150}
151
152#[cfg(test)]
153impl Drop for MockableFd {
154    fn drop(&mut self) {
155        use std::os::fd::{AsRawFd as _, IntoRawFd as _};
156
157        let Self { fd } = self;
158        let fd = fd.take().unwrap();
159        if fd.as_raw_fd() < Self::mock_signed_fd() {
160            drop(fd)
161        } else {
162            let _raw_fd = fd.into_raw_fd();
163        }
164    }
165}