From 9ff1bf3d3bb8f3d51ecaf625dbf3f8d2dbb51abc Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 23 Aug 2023 11:01:23 -0400 Subject: [PATCH 01/95] aya: fix docs build Appease the new lint rustdoc::redundant_explicit_links that was added in https://github.com/rust-lang/rust/pull/113167. --- aya/src/maps/mod.rs | 10 +++++----- aya/src/maps/perf/mod.rs | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 8458989c..cf39277d 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -5,17 +5,17 @@ //! [`Bpf::load_file`](crate::Bpf::load_file) or //! [`Bpf::load`](crate::Bpf::load), all the maps defined in the eBPF code get //! initialized and can then be accessed using [`Bpf::map`](crate::Bpf::map), -//! [`Bpf::map_mut`](crate::Bpf::map_mut), or [`Bpf::take_map`](crate::Bpf::take_map). +//! [`Bpf::map_mut`](crate::Bpf::map_mut), or +//! [`Bpf::take_map`](crate::Bpf::take_map). //! //! # Typed maps //! //! The eBPF API includes many map types each supporting different operations. //! [`Bpf::map`](crate::Bpf::map), [`Bpf::map_mut`](crate::Bpf::map_mut), and -//! [`Bpf::take_map`](crate::Bpf::take_map) always return the -//! opaque [`&Map`](crate::maps::Map), [`&mut Map`](crate::maps::Map), and [`Map`](crate::maps::Map) +//! [`Bpf::take_map`](crate::Bpf::take_map) always return the opaque +//! [`&Map`](crate::maps::Map), [`&mut Map`](crate::maps::Map), and [`Map`] //! types respectively. Those three types can be converted to *typed maps* using -//! the [`TryFrom`](std::convert::TryFrom) or [`TryInto`](std::convert::TryInto) -//! trait. For example: +//! the [`TryFrom`] or [`TryInto`] trait. For example: //! //! ```no_run //! # let mut bpf = aya::Bpf::load(&[])?; diff --git a/aya/src/maps/perf/mod.rs b/aya/src/maps/perf/mod.rs index 80f08b61..765b052d 100644 --- a/aya/src/maps/perf/mod.rs +++ b/aya/src/maps/perf/mod.rs @@ -1,6 +1,7 @@ -//! Ring buffer types used to 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`](crate::maps::PerfEventArray) and [`AsyncPerfEventArray`](crate::maps::perf::AsyncPerfEventArray). +//! See [`PerfEventArray`] and [`AsyncPerfEventArray`]. #[cfg(any(feature = "async_tokio", feature = "async_std"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "async_tokio", feature = "async_std"))))] mod async_perf_event_array; From b91d90d6b935363a07a5e8d374025cd9728e927d Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 23 Aug 2023 12:41:33 -0400 Subject: [PATCH 02/95] github: build qemu from source if bad signature See https://github.com/Homebrew/homebrew-core/issues/140244. --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdb8b994..c6deec21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -204,6 +204,8 @@ jobs: echo /usr/local/opt/findutils/libexec/gnubin >> $GITHUB_PATH echo /usr/local/opt/gnu-tar/libexec/gnubin >> $GITHUB_PATH echo /usr/local/opt/llvm/bin >> $GITHUB_PATH + # https://github.com/Homebrew/homebrew-core/issues/140244 + codesign --verify $(which qemu-system-x86_64) || brew reinstall qemu --build-from-source - name: bpf-linker if: runner.os == 'macOS' From abda239d635e70c34898a425d119040d1bac39a5 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 11 Aug 2023 16:03:53 -0400 Subject: [PATCH 03/95] aya: deny various allow-by-default lints Notably: - clippy::use_self: replaced many T with Self. - single_use_lifetimes: removed some single use lifetimes. - unreachable_pub: removed some unreachable pub items. - unused_crate_dependencies: removed unused futures,parking_lot deps. - unused_qualifications: found a potential `crate` vs `$crate` bug. - let_underscore_drop: not enabled, seems to trigger false positives. - missing_copy_implementations: not enabled, unclear if we want this. - unsafe_op_in_unsafe_fn: not enabled, unclear if we want this. - unused_results: not enabled, needs many fixes (but I think wanted). --- Cargo.toml | 2 - aya/Cargo.toml | 2 - aya/src/bpf.rs | 14 +- aya/src/lib.rs | 46 ++++- aya/src/maps/array/array.rs | 4 +- aya/src/maps/array/per_cpu_array.rs | 4 +- aya/src/maps/array/program_array.rs | 4 +- aya/src/maps/bloom_filter.rs | 4 +- aya/src/maps/hash_map/hash_map.rs | 6 +- aya/src/maps/hash_map/per_cpu_hash_map.rs | 6 +- aya/src/maps/lpm_trie.rs | 4 +- aya/src/maps/mod.rs | 60 +++--- aya/src/maps/perf/async_perf_event_array.rs | 5 +- aya/src/maps/perf/perf_buffer.rs | 10 +- aya/src/maps/perf/perf_event_array.rs | 4 +- aya/src/maps/queue.rs | 4 +- aya/src/maps/sock/sock_hash.rs | 6 +- aya/src/maps/sock/sock_map.rs | 4 +- aya/src/maps/stack.rs | 4 +- aya/src/maps/stack_trace.rs | 4 +- aya/src/programs/cgroup_device.rs | 8 +- aya/src/programs/cgroup_skb.rs | 8 +- aya/src/programs/cgroup_sock.rs | 8 +- aya/src/programs/cgroup_sock_addr.rs | 8 +- aya/src/programs/cgroup_sockopt.rs | 8 +- aya/src/programs/cgroup_sysctl.rs | 8 +- aya/src/programs/kprobe.rs | 2 +- aya/src/programs/links.rs | 29 +-- aya/src/programs/lirc_mode2.rs | 4 +- aya/src/programs/mod.rs | 212 ++++++++++---------- aya/src/programs/perf_attach.rs | 8 +- aya/src/programs/perf_event.rs | 2 +- aya/src/programs/probe.rs | 4 +- aya/src/programs/tc.rs | 10 +- aya/src/programs/trace_point.rs | 2 +- aya/src/programs/uprobe.rs | 10 +- aya/src/programs/utils.rs | 2 +- aya/src/programs/xdp.rs | 38 ++-- aya/src/sys/bpf.rs | 10 +- aya/src/sys/fake.rs | 6 +- aya/src/sys/mod.rs | 7 +- aya/src/sys/netlink.rs | 22 +- aya/src/util.rs | 4 +- xtask/public-api/aya.txt | 18 +- 44 files changed, 332 insertions(+), 303 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f4d1df95..1eb34af9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,6 @@ core-error = { version = "0.0.0", default-features = false } dialoguer = { version = "0.10", default-features = false } diff = { version = "0.1.13", default-features = false } env_logger = { version = "0.10", default-features = false } -futures = { version = "0.3.12", default-features = false } hashbrown = { version = "0.14", default-features = false } indoc = { version = "2.0", default-features = false } integration-ebpf = { path = "test/integration-ebpf", default-features = false } @@ -77,7 +76,6 @@ netns-rs = { version = "0.1", default-features = false } nix = { version = "0.26.2", default-features = false } num_enum = { version = "0.7", default-features = false } object = { version = "0.32", default-features = false } -parking_lot = { version = "0.12.0", default-features = false } proc-macro-error = { version = "1.0", default-features = false } proc-macro2 = { version = "1", default-features = false } public-api = { version = "0.31.2", default-features = false } diff --git a/aya/Cargo.toml b/aya/Cargo.toml index 4e5eec16..59025b2d 100644 --- a/aya/Cargo.toml +++ b/aya/Cargo.toml @@ -24,13 +24,11 @@ object = { workspace = true, default-features = false, features = [ "read_core", "std", ] } -parking_lot = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = ["rt"], optional = true } [dev-dependencies] assert_matches = { workspace = true } -futures = { workspace = true } tempfile = { workspace = true } [features] diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index f5841f3f..f8bf467c 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -71,7 +71,7 @@ unsafe impl Pod for [T; N] {} pub use aya_obj::maps::{bpf_map_def, PinningType}; -lazy_static! { +lazy_static::lazy_static! { pub(crate) static ref FEATURES: Features = detect_features(); } @@ -138,7 +138,7 @@ pub struct BpfLoader<'a> { allow_unsupported_maps: bool, } -bitflags! { +bitflags::bitflags! { /// Used to set the verifier log level flags in [BpfLoader](BpfLoader::verifier_log_level()). #[derive(Clone, Copy, Debug)] pub struct VerifierLogLevel: u32 { @@ -161,8 +161,8 @@ impl Default for VerifierLogLevel { impl<'a> BpfLoader<'a> { /// Creates a new loader instance. - pub fn new() -> BpfLoader<'a> { - BpfLoader { + pub fn new() -> Self { + Self { btf: Btf::from_sys_fs().ok().map(Cow::Owned), map_pin_path: None, globals: HashMap::new(), @@ -738,7 +738,7 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { Ok((name, map)) } -impl<'a> Default for BpfLoader<'a> { +impl Default for BpfLoader<'_> { fn default() -> Self { BpfLoader::new() } @@ -768,7 +768,7 @@ impl Bpf { /// let bpf = Bpf::load_file("file.o")?; /// # Ok::<(), aya::BpfError>(()) /// ``` - pub fn load_file>(path: P) -> Result { + pub fn load_file>(path: P) -> Result { BpfLoader::new() .btf(Btf::from_sys_fs().ok().as_ref()) .load_file(path) @@ -793,7 +793,7 @@ impl Bpf { /// let bpf = Bpf::load(&data)?; /// # Ok::<(), aya::BpfError>(()) /// ``` - pub fn load(data: &[u8]) -> Result { + pub fn load(data: &[u8]) -> Result { BpfLoader::new() .btf(Btf::from_sys_fs().ok().as_ref()) .load(data) diff --git a/aya/src/lib.rs b/aya/src/lib.rs index 4ba70c2a..743ea26d 100644 --- a/aya/src/lib.rs +++ b/aya/src/lib.rs @@ -37,13 +37,47 @@ html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg" )] #![cfg_attr(docsrs, feature(doc_cfg))] -#![deny(clippy::all, missing_docs)] +#![deny( + clippy::all, + clippy::use_self, + absolute_paths_not_starting_with_crate, + deprecated_in_future, + elided_lifetimes_in_paths, + explicit_outlives_requirements, + ffi_unwind_calls, + keyword_idents, + //let_underscore_drop, + macro_use_extern_crate, + meta_variable_misuse, + missing_abi, + //missing_copy_implementations, + missing_docs, + non_ascii_idents, + noop_method_call, + pointer_structural_match, + rust_2021_incompatible_closure_captures, + rust_2021_incompatible_or_patterns, + rust_2021_prefixes_incompatible_syntax, + rust_2021_prelude_collisions, + single_use_lifetimes, + trivial_numeric_casts, + unreachable_pub, + //unsafe_op_in_unsafe_fn, + unstable_features, + unused_crate_dependencies, + unused_extern_crates, + unused_import_braces, + unused_lifetimes, + unused_macro_rules, + unused_qualifications, + //unused_results, + unused_tuple_struct_fields, +)] #![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)] - -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate bitflags; +#![cfg_attr( + all(feature = "async_tokio", feature = "async_std"), + allow(unused_crate_dependencies) +)] mod bpf; use aya_obj::generated; diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 97bb46d6..64454a3c 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -35,11 +35,11 @@ pub struct Array { } impl, V: Pod> Array { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(Array { + Ok(Self { inner: map, _v: PhantomData, }) diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index 6405af4a..db6169bd 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -54,11 +54,11 @@ pub struct PerCpuArray { } impl, V: Pod> PerCpuArray { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(PerCpuArray { + Ok(Self { inner: map, _v: PhantomData, }) diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index e2152b56..a38ce023 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -52,11 +52,11 @@ pub struct ProgramArray { } impl> ProgramArray { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(ProgramArray { inner: map }) + Ok(Self { inner: map }) } /// An iterator over the indices of the array that point to a program. The iterator item type diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index 84bff986..0396d0f6 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -40,11 +40,11 @@ pub struct BloomFilter { } impl, V: Pod> BloomFilter { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_v_size::(data)?; - Ok(BloomFilter { + Ok(Self { inner: map, _v: PhantomData, }) diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index b2f9e547..1f8a2f9c 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -39,11 +39,11 @@ pub struct HashMap { } impl, K: Pod, V: Pod> HashMap { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(HashMap { + Ok(Self { inner: map, _k: PhantomData, _v: PhantomData, @@ -96,7 +96,7 @@ impl, K: Pod, V: Pod> IterableMap for HashMap } fn get(&self, key: &K) -> Result { - HashMap::get(self, key, 0) + Self::get(self, key, 0) } } diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index 7fd90ec0..5ae177f2 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -48,11 +48,11 @@ pub struct PerCpuHashMap { } impl, K: Pod, V: Pod> PerCpuHashMap { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(PerCpuHashMap { + Ok(Self { inner: map, _k: PhantomData, _v: PhantomData, @@ -143,6 +143,6 @@ impl, K: Pod, V: Pod> IterableMap> } fn get(&self, key: &K) -> Result, MapError> { - PerCpuHashMap::get(self, key, 0) + Self::get(self, key, 0) } } diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index d05ec2cf..dcdc443d 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -113,11 +113,11 @@ impl Clone for Key { unsafe impl Pod for Key {} impl, K: Pod, V: Pod> LpmTrie { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::, V>(data)?; - Ok(LpmTrie { + Ok(Self { inner: map, _k: PhantomData, _v: PhantomData, diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index cf39277d..0cd5386e 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -261,22 +261,22 @@ impl Map { /// Returns the low level map type. fn map_type(&self) -> u32 { match self { - Map::Array(map) => map.obj.map_type(), - Map::PerCpuArray(map) => map.obj.map_type(), - Map::ProgramArray(map) => map.obj.map_type(), - Map::HashMap(map) => map.obj.map_type(), - Map::LruHashMap(map) => map.obj.map_type(), - Map::PerCpuHashMap(map) => map.obj.map_type(), - Map::PerCpuLruHashMap(map) => map.obj.map_type(), - Map::PerfEventArray(map) => map.obj.map_type(), - Map::SockHash(map) => map.obj.map_type(), - Map::SockMap(map) => map.obj.map_type(), - Map::BloomFilter(map) => map.obj.map_type(), - Map::LpmTrie(map) => map.obj.map_type(), - Map::Stack(map) => map.obj.map_type(), - Map::StackTraceMap(map) => map.obj.map_type(), - Map::Queue(map) => map.obj.map_type(), - Map::Unsupported(map) => map.obj.map_type(), + Self::Array(map) => map.obj.map_type(), + Self::PerCpuArray(map) => map.obj.map_type(), + Self::ProgramArray(map) => map.obj.map_type(), + Self::HashMap(map) => map.obj.map_type(), + Self::LruHashMap(map) => map.obj.map_type(), + Self::PerCpuHashMap(map) => map.obj.map_type(), + Self::PerCpuLruHashMap(map) => map.obj.map_type(), + Self::PerfEventArray(map) => map.obj.map_type(), + Self::SockHash(map) => map.obj.map_type(), + Self::SockMap(map) => map.obj.map_type(), + Self::BloomFilter(map) => map.obj.map_type(), + Self::LpmTrie(map) => map.obj.map_type(), + Self::Stack(map) => map.obj.map_type(), + Self::StackTraceMap(map) => map.obj.map_type(), + Self::Queue(map) => map.obj.map_type(), + Self::Unsupported(map) => map.obj.map_type(), } } } @@ -500,9 +500,11 @@ impl MapData { } })?; + #[allow(trivial_numeric_casts)] + let fd = fd as RawFd; Ok(Self { obj, - fd: fd as RawFd, + fd, pinned: false, }) } @@ -537,7 +539,7 @@ impl MapData { } /// Loads a map from a pinned path in bpffs. - pub fn from_pin>(path: P) -> Result { + pub fn from_pin>(path: P) -> Result { let path_string = CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { MapError::PinError { @@ -555,7 +557,7 @@ impl MapData { let info = bpf_map_get_info_by_fd(fd.as_fd())?; - Ok(MapData { + Ok(Self { obj: parse_map_info(info, PinningType::ByName), fd: fd.into_raw_fd(), pinned: true, @@ -567,10 +569,10 @@ impl MapData { /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`](crate::maps::MapData::from_pin). /// This API is intended for cases where you have received a valid BPF FD from some other means. /// For example, you received an FD over Unix Domain Socket. - pub fn from_fd(fd: OwnedFd) -> Result { + pub fn from_fd(fd: OwnedFd) -> Result { let info = bpf_map_get_info_by_fd(fd.as_fd())?; - Ok(MapData { + Ok(Self { obj: parse_map_info(info, PinningType::None), fd: fd.into_raw_fd(), pinned: false, @@ -641,8 +643,8 @@ pub struct MapKeys<'coll, K: Pod> { } impl<'coll, K: Pod> MapKeys<'coll, K> { - fn new(map: &'coll MapData) -> MapKeys<'coll, K> { - MapKeys { + fn new(map: &'coll MapData) -> Self { + Self { map, err: false, key: None, @@ -685,8 +687,8 @@ pub struct MapIter<'coll, K: Pod, V, I: IterableMap> { } impl<'coll, K: Pod, V, I: IterableMap> MapIter<'coll, K, V, I> { - fn new(map: &'coll I) -> MapIter<'coll, K, V, I> { - MapIter { + fn new(map: &'coll I) -> Self { + Self { keys: MapKeys::new(map.map()), map, _v: PhantomData, @@ -761,7 +763,7 @@ impl TryFrom> for PerCpuValues { format!("not enough values ({}), nr_cpus: {}", values.len(), nr_cpus), )); } - Ok(PerCpuValues { + Ok(Self { values: values.into_boxed_slice(), }) } @@ -775,7 +777,7 @@ impl PerCpuValues { }) } - pub(crate) unsafe fn from_kernel_mem(mem: PerCpuKernelMem) -> PerCpuValues { + pub(crate) unsafe fn from_kernel_mem(mem: PerCpuKernelMem) -> Self { let mem_ptr = mem.bytes.as_ptr() as usize; let value_size = (mem::size_of::() + 7) & !7; let mut values = Vec::new(); @@ -785,13 +787,13 @@ impl PerCpuValues { offset += value_size; } - PerCpuValues { + Self { values: values.into_boxed_slice(), } } pub(crate) fn build_kernel_mem(&self) -> Result { - let mut mem = PerCpuValues::::alloc_kernel_mem()?; + let mut mem = Self::alloc_kernel_mem()?; let mem_ptr = mem.as_mut_ptr() as usize; let value_size = (mem::size_of::() + 7) & !7; for i in 0..self.values.len() { diff --git a/aya/src/maps/perf/async_perf_event_array.rs b/aya/src/maps/perf/async_perf_event_array.rs index 447df95d..7c942e26 100644 --- a/aya/src/maps/perf/async_perf_event_array.rs +++ b/aya/src/maps/perf/async_perf_event_array.rs @@ -52,7 +52,6 @@ use crate::maps::{ /// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::maps::perf::{AsyncPerfEventArray, PerfBufferError}; /// use aya::util::online_cpus; -/// use futures::future; /// use bytes::BytesMut; /// use tokio::task; // or async_std::task /// @@ -118,8 +117,8 @@ impl + Borrow> AsyncPerfEventArray { } impl> AsyncPerfEventArray { - pub(crate) fn new(map: T) -> Result, MapError> { - Ok(AsyncPerfEventArray { + pub(crate) fn new(map: T) -> Result { + Ok(Self { perf_map: PerfEventArray::new(map)?, }) } diff --git a/aya/src/maps/perf/perf_buffer.rs b/aya/src/maps/perf/perf_buffer.rs index 2a5bfe3d..898dd04b 100644 --- a/aya/src/maps/perf/perf_buffer.rs +++ b/aya/src/maps/perf/perf_buffer.rs @@ -96,7 +96,7 @@ impl PerfBuffer { cpu_id: u32, page_size: usize, page_count: usize, - ) -> Result { + ) -> Result { if !page_count.is_power_of_two() { return Err(PerfBufferError::InvalidPageCount { page_count }); } @@ -120,7 +120,7 @@ impl PerfBuffer { }); } - let perf_buf = PerfBuffer { + let perf_buf = Self { buf: AtomicPtr::new(buf as *mut perf_event_mmap_page), fd, size, @@ -305,15 +305,15 @@ unsafe fn mmap( #[repr(C)] struct Sample { header: perf_event_header, - pub size: u32, + size: u32, } #[repr(C)] #[derive(Debug)] struct LostSamples { header: perf_event_header, - pub id: u64, - pub count: u64, + id: u64, + count: u64, } #[cfg(test)] diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index 7d647164..bde255ed 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -161,8 +161,8 @@ pub struct PerfEventArray { } impl> PerfEventArray { - pub(crate) fn new(map: T) -> Result, MapError> { - Ok(PerfEventArray { + pub(crate) fn new(map: T) -> Result { + Ok(Self { map: Arc::new(map), page_size: page_size(), }) diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index 78b81ec2..6eebbf01 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -34,11 +34,11 @@ pub struct Queue { } impl, V: Pod> Queue { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::<(), V>(data)?; - Ok(Queue { + Ok(Self { inner: map, _v: PhantomData, }) diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 1904ec1e..503dcaae 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -69,11 +69,11 @@ pub struct SockHash { } impl, K: Pod> SockHash { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(SockHash { + Ok(Self { inner: map, _k: PhantomData, }) @@ -138,6 +138,6 @@ impl, K: Pod> IterableMap for SockHash { } fn get(&self, key: &K) -> Result { - SockHash::get(self, key, 0) + Self::get(self, key, 0) } } diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index 52574f23..8194cd71 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -45,11 +45,11 @@ pub struct SockMap { } impl> SockMap { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::(data)?; - Ok(SockMap { inner: map }) + Ok(Self { inner: map }) } /// An iterator over the indices of the array that point to a program. The iterator item type diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index 0cc9b1d8..c4afeebb 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -34,11 +34,11 @@ pub struct Stack { } impl, V: Pod> Stack { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); check_kv_size::<(), V>(data)?; - Ok(Stack { + Ok(Self { inner: map, _v: PhantomData, }) diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index 8f84a09e..07281a2b 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -72,7 +72,7 @@ pub struct StackTraceMap { } impl> StackTraceMap { - pub(crate) fn new(map: T) -> Result, MapError> { + pub(crate) fn new(map: T) -> Result { let data = map.borrow(); let expected = mem::size_of::(); let size = data.obj.key_size() as usize; @@ -90,7 +90,7 @@ impl> StackTraceMap { return Err(MapError::InvalidValueSize { size, expected }); } - Ok(StackTraceMap { + Ok(Self { inner: map, max_stack_depth, }) diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index 1244d27c..42ce1e17 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -129,15 +129,15 @@ impl Link for CgroupDeviceLinkInner { fn id(&self) -> Self::Id { match self { - CgroupDeviceLinkInner::Fd(fd) => CgroupDeviceLinkIdInner::Fd(fd.id()), - CgroupDeviceLinkInner::ProgAttach(p) => CgroupDeviceLinkIdInner::ProgAttach(p.id()), + Self::Fd(fd) => CgroupDeviceLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => CgroupDeviceLinkIdInner::ProgAttach(p.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - CgroupDeviceLinkInner::Fd(fd) => fd.detach(), - CgroupDeviceLinkInner::ProgAttach(p) => p.detach(), + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), } } } diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 684fd18e..4b815c15 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -179,15 +179,15 @@ impl Link for CgroupSkbLinkInner { fn id(&self) -> Self::Id { match self { - CgroupSkbLinkInner::Fd(fd) => CgroupSkbLinkIdInner::Fd(fd.id()), - CgroupSkbLinkInner::ProgAttach(p) => CgroupSkbLinkIdInner::ProgAttach(p.id()), + Self::Fd(fd) => CgroupSkbLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => CgroupSkbLinkIdInner::ProgAttach(p.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - CgroupSkbLinkInner::Fd(fd) => fd.detach(), - CgroupSkbLinkInner::ProgAttach(p) => p.detach(), + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), } } } diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index c906ee6c..57dfeaf0 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -151,15 +151,15 @@ impl Link for CgroupSockLinkInner { fn id(&self) -> Self::Id { match self { - CgroupSockLinkInner::Fd(fd) => CgroupSockLinkIdInner::Fd(fd.id()), - CgroupSockLinkInner::ProgAttach(p) => CgroupSockLinkIdInner::ProgAttach(p.id()), + Self::Fd(fd) => CgroupSockLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => CgroupSockLinkIdInner::ProgAttach(p.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - CgroupSockLinkInner::Fd(fd) => fd.detach(), - CgroupSockLinkInner::ProgAttach(p) => p.detach(), + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), } } } diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index 98d60eb1..2c2b4ac9 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -157,15 +157,15 @@ impl Link for CgroupSockAddrLinkInner { fn id(&self) -> Self::Id { match self { - CgroupSockAddrLinkInner::Fd(fd) => CgroupSockAddrLinkIdInner::Fd(fd.id()), - CgroupSockAddrLinkInner::ProgAttach(p) => CgroupSockAddrLinkIdInner::ProgAttach(p.id()), + Self::Fd(fd) => CgroupSockAddrLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => CgroupSockAddrLinkIdInner::ProgAttach(p.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - CgroupSockAddrLinkInner::Fd(fd) => fd.detach(), - CgroupSockAddrLinkInner::ProgAttach(p) => p.detach(), + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), } } } diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index c137d769..cbe8302e 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -152,15 +152,15 @@ impl Link for CgroupSockoptLinkInner { fn id(&self) -> Self::Id { match self { - CgroupSockoptLinkInner::Fd(fd) => CgroupSockoptLinkIdInner::Fd(fd.id()), - CgroupSockoptLinkInner::ProgAttach(p) => CgroupSockoptLinkIdInner::ProgAttach(p.id()), + Self::Fd(fd) => CgroupSockoptLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => CgroupSockoptLinkIdInner::ProgAttach(p.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - CgroupSockoptLinkInner::Fd(fd) => fd.detach(), - CgroupSockoptLinkInner::ProgAttach(p) => p.detach(), + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), } } } diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index d5325089..a1b158d7 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -132,15 +132,15 @@ impl Link for CgroupSysctlLinkInner { fn id(&self) -> Self::Id { match self { - CgroupSysctlLinkInner::Fd(fd) => CgroupSysctlLinkIdInner::Fd(fd.id()), - CgroupSysctlLinkInner::ProgAttach(p) => CgroupSysctlLinkIdInner::ProgAttach(p.id()), + Self::Fd(fd) => CgroupSysctlLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => CgroupSysctlLinkIdInner::ProgAttach(p.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - CgroupSysctlLinkInner::Fd(fd) => fd.detach(), - CgroupSysctlLinkInner::ProgAttach(p) => p.detach(), + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), } } } diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index f9cbb667..a0c8d2b4 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -139,7 +139,7 @@ impl TryFrom for KProbeLink { fn try_from(fd_link: FdLink) -> Result { let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?; if info.type_ == (bpf_link_type::BPF_LINK_TYPE_KPROBE_MULTI as u32) { - return Ok(KProbeLink::new(PerfLinkInner::FdLink(fd_link))); + return Ok(Self::new(PerfLinkInner::FdLink(fd_link))); } Err(LinkError::InvalidLink) } diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 52aa60de..77341adc 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -35,8 +35,8 @@ pub(crate) struct LinkMap { } impl LinkMap { - pub(crate) fn new() -> LinkMap { - LinkMap { + pub(crate) fn new() -> Self { + Self { links: HashMap::new(), } } @@ -112,8 +112,8 @@ pub struct FdLink { } impl FdLink { - pub(crate) fn new(fd: OwnedFd) -> FdLink { - FdLink { fd } + pub(crate) fn new(fd: OwnedFd) -> Self { + Self { fd } } /// Pins the link to a BPF file system. @@ -198,7 +198,7 @@ pub struct PinnedLink { impl PinnedLink { fn new(path: PathBuf, link: FdLink) -> Self { - PinnedLink { inner: link, path } + Self { inner: link, path } } /// Creates a [`crate::programs::links::PinnedLink`] from a valid path on bpffs. @@ -210,10 +210,7 @@ impl PinnedLink { io_error, }) })?; - Ok(PinnedLink::new( - path.as_ref().to_path_buf(), - FdLink::new(fd), - )) + Ok(Self::new(path.as_ref().to_path_buf(), FdLink::new(fd))) } /// Removes the pinned link from the filesystem and returns an [`FdLink`]. @@ -236,12 +233,8 @@ pub struct ProgAttachLink { } impl ProgAttachLink { - pub(crate) fn new( - prog_fd: RawFd, - target_fd: RawFd, - attach_type: bpf_attach_type, - ) -> ProgAttachLink { - ProgAttachLink { + pub(crate) fn new(prog_fd: RawFd, target_fd: RawFd, attach_type: bpf_attach_type) -> Self { + Self { prog_fd, target_fd: unsafe { dup(target_fd) }, attach_type, @@ -300,7 +293,7 @@ macro_rules! define_link_wrapper { } } - impl crate::programs::Link for $wrapper { + impl $crate::programs::Link for $wrapper { type Id = $wrapper_id; fn id(&self) -> Self::Id { @@ -359,8 +352,8 @@ mod tests { } impl TestLink { - fn new(a: u8, b: u8) -> TestLink { - TestLink { + fn new(a: u8, b: u8) -> Self { + Self { id: (a, b), detached: Rc::new(RefCell::new(0)), } diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 906eec96..0d34bfce 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -121,8 +121,8 @@ pub struct LircLink { } impl LircLink { - pub(crate) fn new(prog_fd: RawFd, target_fd: RawFd) -> LircLink { - LircLink { + pub(crate) fn new(prog_fd: RawFd, target_fd: RawFd) -> Self { + Self { prog_fd, target_fd: unsafe { dup(target_fd) }, } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index b79627a8..dcec8bf3 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -108,7 +108,7 @@ pub use xdp::{Xdp, XdpError, XdpFlags}; use crate::{ generated::{bpf_attach_type, bpf_link_info, bpf_prog_info, bpf_prog_type}, maps::MapError, - obj::{self, btf::BtfError, Function, VerifierLog}, + obj::{self, btf::BtfError, VerifierLog}, pin::PinError, programs::utils::{boot_time, get_fdinfo}, sys::{ @@ -292,90 +292,90 @@ impl Program { pub fn prog_type(&self) -> bpf_prog_type { use crate::generated::bpf_prog_type::*; match self { - Program::KProbe(_) => BPF_PROG_TYPE_KPROBE, - Program::UProbe(_) => BPF_PROG_TYPE_KPROBE, - Program::TracePoint(_) => BPF_PROG_TYPE_TRACEPOINT, - Program::SocketFilter(_) => BPF_PROG_TYPE_SOCKET_FILTER, - Program::Xdp(_) => BPF_PROG_TYPE_XDP, - Program::SkMsg(_) => BPF_PROG_TYPE_SK_MSG, - Program::SkSkb(_) => BPF_PROG_TYPE_SK_SKB, - Program::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS, - Program::SchedClassifier(_) => BPF_PROG_TYPE_SCHED_CLS, - Program::CgroupSkb(_) => BPF_PROG_TYPE_CGROUP_SKB, - Program::CgroupSysctl(_) => BPF_PROG_TYPE_CGROUP_SYSCTL, - Program::CgroupSockopt(_) => BPF_PROG_TYPE_CGROUP_SOCKOPT, - Program::LircMode2(_) => BPF_PROG_TYPE_LIRC_MODE2, - Program::PerfEvent(_) => BPF_PROG_TYPE_PERF_EVENT, - Program::RawTracePoint(_) => BPF_PROG_TYPE_RAW_TRACEPOINT, - Program::Lsm(_) => BPF_PROG_TYPE_LSM, - Program::BtfTracePoint(_) => BPF_PROG_TYPE_TRACING, - Program::FEntry(_) => BPF_PROG_TYPE_TRACING, - Program::FExit(_) => BPF_PROG_TYPE_TRACING, - Program::Extension(_) => BPF_PROG_TYPE_EXT, - Program::CgroupSockAddr(_) => BPF_PROG_TYPE_CGROUP_SOCK_ADDR, - Program::SkLookup(_) => BPF_PROG_TYPE_SK_LOOKUP, - Program::CgroupSock(_) => BPF_PROG_TYPE_CGROUP_SOCK, - Program::CgroupDevice(_) => BPF_PROG_TYPE_CGROUP_DEVICE, + Self::KProbe(_) => BPF_PROG_TYPE_KPROBE, + Self::UProbe(_) => BPF_PROG_TYPE_KPROBE, + Self::TracePoint(_) => BPF_PROG_TYPE_TRACEPOINT, + Self::SocketFilter(_) => BPF_PROG_TYPE_SOCKET_FILTER, + Self::Xdp(_) => BPF_PROG_TYPE_XDP, + Self::SkMsg(_) => BPF_PROG_TYPE_SK_MSG, + Self::SkSkb(_) => BPF_PROG_TYPE_SK_SKB, + Self::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS, + Self::SchedClassifier(_) => BPF_PROG_TYPE_SCHED_CLS, + Self::CgroupSkb(_) => BPF_PROG_TYPE_CGROUP_SKB, + Self::CgroupSysctl(_) => BPF_PROG_TYPE_CGROUP_SYSCTL, + Self::CgroupSockopt(_) => BPF_PROG_TYPE_CGROUP_SOCKOPT, + Self::LircMode2(_) => BPF_PROG_TYPE_LIRC_MODE2, + Self::PerfEvent(_) => BPF_PROG_TYPE_PERF_EVENT, + Self::RawTracePoint(_) => BPF_PROG_TYPE_RAW_TRACEPOINT, + Self::Lsm(_) => BPF_PROG_TYPE_LSM, + Self::BtfTracePoint(_) => BPF_PROG_TYPE_TRACING, + Self::FEntry(_) => BPF_PROG_TYPE_TRACING, + Self::FExit(_) => BPF_PROG_TYPE_TRACING, + Self::Extension(_) => BPF_PROG_TYPE_EXT, + Self::CgroupSockAddr(_) => BPF_PROG_TYPE_CGROUP_SOCK_ADDR, + Self::SkLookup(_) => BPF_PROG_TYPE_SK_LOOKUP, + Self::CgroupSock(_) => BPF_PROG_TYPE_CGROUP_SOCK, + Self::CgroupDevice(_) => BPF_PROG_TYPE_CGROUP_DEVICE, } } /// Pin the program to the provided path pub fn pin>(&mut self, path: P) -> Result<(), PinError> { match self { - Program::KProbe(p) => p.pin(path), - Program::UProbe(p) => p.pin(path), - Program::TracePoint(p) => p.pin(path), - Program::SocketFilter(p) => p.pin(path), - Program::Xdp(p) => p.pin(path), - Program::SkMsg(p) => p.pin(path), - Program::SkSkb(p) => p.pin(path), - Program::SockOps(p) => p.pin(path), - Program::SchedClassifier(p) => p.pin(path), - Program::CgroupSkb(p) => p.pin(path), - Program::CgroupSysctl(p) => p.pin(path), - Program::CgroupSockopt(p) => p.pin(path), - Program::LircMode2(p) => p.pin(path), - Program::PerfEvent(p) => p.pin(path), - Program::RawTracePoint(p) => p.pin(path), - Program::Lsm(p) => p.pin(path), - Program::BtfTracePoint(p) => p.pin(path), - Program::FEntry(p) => p.pin(path), - Program::FExit(p) => p.pin(path), - Program::Extension(p) => p.pin(path), - Program::CgroupSockAddr(p) => p.pin(path), - Program::SkLookup(p) => p.pin(path), - Program::CgroupSock(p) => p.pin(path), - Program::CgroupDevice(p) => p.pin(path), + Self::KProbe(p) => p.pin(path), + Self::UProbe(p) => p.pin(path), + Self::TracePoint(p) => p.pin(path), + Self::SocketFilter(p) => p.pin(path), + Self::Xdp(p) => p.pin(path), + Self::SkMsg(p) => p.pin(path), + Self::SkSkb(p) => p.pin(path), + Self::SockOps(p) => p.pin(path), + Self::SchedClassifier(p) => p.pin(path), + Self::CgroupSkb(p) => p.pin(path), + Self::CgroupSysctl(p) => p.pin(path), + Self::CgroupSockopt(p) => p.pin(path), + Self::LircMode2(p) => p.pin(path), + Self::PerfEvent(p) => p.pin(path), + Self::RawTracePoint(p) => p.pin(path), + Self::Lsm(p) => p.pin(path), + Self::BtfTracePoint(p) => p.pin(path), + Self::FEntry(p) => p.pin(path), + Self::FExit(p) => p.pin(path), + Self::Extension(p) => p.pin(path), + Self::CgroupSockAddr(p) => p.pin(path), + Self::SkLookup(p) => p.pin(path), + Self::CgroupSock(p) => p.pin(path), + Self::CgroupDevice(p) => p.pin(path), } } /// Unloads the program from the kernel. pub fn unload(self) -> Result<(), ProgramError> { match self { - Program::KProbe(mut p) => p.unload(), - Program::UProbe(mut p) => p.unload(), - Program::TracePoint(mut p) => p.unload(), - Program::SocketFilter(mut p) => p.unload(), - Program::Xdp(mut p) => p.unload(), - Program::SkMsg(mut p) => p.unload(), - Program::SkSkb(mut p) => p.unload(), - Program::SockOps(mut p) => p.unload(), - Program::SchedClassifier(mut p) => p.unload(), - Program::CgroupSkb(mut p) => p.unload(), - Program::CgroupSysctl(mut p) => p.unload(), - Program::CgroupSockopt(mut p) => p.unload(), - Program::LircMode2(mut p) => p.unload(), - Program::PerfEvent(mut p) => p.unload(), - Program::RawTracePoint(mut p) => p.unload(), - Program::Lsm(mut p) => p.unload(), - Program::BtfTracePoint(mut p) => p.unload(), - Program::FEntry(mut p) => p.unload(), - Program::FExit(mut p) => p.unload(), - Program::Extension(mut p) => p.unload(), - Program::CgroupSockAddr(mut p) => p.unload(), - Program::SkLookup(mut p) => p.unload(), - Program::CgroupSock(mut p) => p.unload(), - Program::CgroupDevice(mut p) => p.unload(), + Self::KProbe(mut p) => p.unload(), + Self::UProbe(mut p) => p.unload(), + Self::TracePoint(mut p) => p.unload(), + Self::SocketFilter(mut p) => p.unload(), + Self::Xdp(mut p) => p.unload(), + Self::SkMsg(mut p) => p.unload(), + Self::SkSkb(mut p) => p.unload(), + Self::SockOps(mut p) => p.unload(), + Self::SchedClassifier(mut p) => p.unload(), + Self::CgroupSkb(mut p) => p.unload(), + Self::CgroupSysctl(mut p) => p.unload(), + Self::CgroupSockopt(mut p) => p.unload(), + Self::LircMode2(mut p) => p.unload(), + Self::PerfEvent(mut p) => p.unload(), + Self::RawTracePoint(mut p) => p.unload(), + Self::Lsm(mut p) => p.unload(), + Self::BtfTracePoint(mut p) => p.unload(), + Self::FEntry(mut p) => p.unload(), + Self::FExit(mut p) => p.unload(), + Self::Extension(mut p) => p.unload(), + Self::CgroupSockAddr(mut p) => p.unload(), + Self::SkLookup(mut p) => p.unload(), + Self::CgroupSock(mut p) => p.unload(), + Self::CgroupDevice(mut p) => p.unload(), } } @@ -384,30 +384,30 @@ impl Program { /// Can be used to add a program to a [`crate::maps::ProgramArray`] or attach an [`Extension`] program. pub fn fd(&self) -> Result<&ProgramFd, ProgramError> { match self { - Program::KProbe(p) => p.fd(), - Program::UProbe(p) => p.fd(), - Program::TracePoint(p) => p.fd(), - Program::SocketFilter(p) => p.fd(), - Program::Xdp(p) => p.fd(), - Program::SkMsg(p) => p.fd(), - Program::SkSkb(p) => p.fd(), - Program::SockOps(p) => p.fd(), - Program::SchedClassifier(p) => p.fd(), - Program::CgroupSkb(p) => p.fd(), - Program::CgroupSysctl(p) => p.fd(), - Program::CgroupSockopt(p) => p.fd(), - Program::LircMode2(p) => p.fd(), - Program::PerfEvent(p) => p.fd(), - Program::RawTracePoint(p) => p.fd(), - Program::Lsm(p) => p.fd(), - Program::BtfTracePoint(p) => p.fd(), - Program::FEntry(p) => p.fd(), - Program::FExit(p) => p.fd(), - Program::Extension(p) => p.fd(), - Program::CgroupSockAddr(p) => p.fd(), - Program::SkLookup(p) => p.fd(), - Program::CgroupSock(p) => p.fd(), - Program::CgroupDevice(p) => p.fd(), + Self::KProbe(p) => p.fd(), + Self::UProbe(p) => p.fd(), + Self::TracePoint(p) => p.fd(), + Self::SocketFilter(p) => p.fd(), + Self::Xdp(p) => p.fd(), + Self::SkMsg(p) => p.fd(), + Self::SkSkb(p) => p.fd(), + Self::SockOps(p) => p.fd(), + Self::SchedClassifier(p) => p.fd(), + Self::CgroupSkb(p) => p.fd(), + Self::CgroupSysctl(p) => p.fd(), + Self::CgroupSockopt(p) => p.fd(), + Self::LircMode2(p) => p.fd(), + Self::PerfEvent(p) => p.fd(), + Self::RawTracePoint(p) => p.fd(), + Self::Lsm(p) => p.fd(), + Self::BtfTracePoint(p) => p.fd(), + Self::FEntry(p) => p.fd(), + Self::FExit(p) => p.fd(), + Self::Extension(p) => p.fd(), + Self::CgroupSockAddr(p) => p.fd(), + Self::SkLookup(p) => p.fd(), + Self::CgroupSock(p) => p.fd(), + Self::CgroupDevice(p) => p.fd(), } } } @@ -434,8 +434,8 @@ impl ProgramData { obj: (obj::Program, obj::Function), btf_fd: Option>, verifier_log_level: VerifierLogLevel, - ) -> ProgramData { - ProgramData { + ) -> Self { + Self { name, obj: Some(obj), fd: None, @@ -457,7 +457,7 @@ impl ProgramData { path: &Path, info: bpf_prog_info, verifier_log_level: VerifierLogLevel, - ) -> Result, ProgramError> { + ) -> Result { let attach_btf_id = if info.attach_btf_id > 0 { Some(info.attach_btf_id) } else { @@ -467,7 +467,7 @@ impl ProgramData { .then(|| bpf_btf_get_fd_by_id(info.attach_btf_obj_id)) .transpose()?; - Ok(ProgramData { + Ok(Self { name, obj: None, fd: Some(ProgramFd(fd)), @@ -486,7 +486,7 @@ impl ProgramData { pub(crate) fn from_pinned_path>( path: P, verifier_log_level: VerifierLogLevel, - ) -> Result, ProgramError> { + ) -> Result { let path_string = CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap(); @@ -497,7 +497,7 @@ impl ProgramData { let info = ProgramInfo::new_from_fd(fd.as_fd())?; let name = info.name_as_str().map(|s| s.to_string()); - ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info.0, verifier_log_level) + Self::from_bpf_prog_info(name, fd, path.as_ref(), info.0, verifier_log_level) } } @@ -571,7 +571,7 @@ fn load_program( kernel_version, .. }, - Function { + obj::Function { instructions, func_info, line_info, @@ -1072,7 +1072,7 @@ impl ProgramInfo { } /// Loads a program from a pinned path in bpffs. - pub fn from_pin>(path: P) -> Result { + pub fn from_pin>(path: P) -> Result { let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap(); let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_GET", @@ -1080,7 +1080,7 @@ impl ProgramInfo { })?; let info = bpf_prog_get_info_by_fd(fd.as_fd(), &mut [])?; - Ok(ProgramInfo(info)) + Ok(Self(info)) } } diff --git a/aya/src/programs/perf_attach.rs b/aya/src/programs/perf_attach.rs index e9be37d5..dd2f8831 100644 --- a/aya/src/programs/perf_attach.rs +++ b/aya/src/programs/perf_attach.rs @@ -28,15 +28,15 @@ impl Link for PerfLinkInner { fn id(&self) -> Self::Id { match self { - PerfLinkInner::FdLink(link) => PerfLinkIdInner::FdLinkId(link.id()), - PerfLinkInner::PerfLink(link) => PerfLinkIdInner::PerfLinkId(link.id()), + Self::FdLink(link) => PerfLinkIdInner::FdLinkId(link.id()), + Self::PerfLink(link) => PerfLinkIdInner::PerfLinkId(link.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - PerfLinkInner::FdLink(link) => link.detach(), - PerfLinkInner::PerfLink(link) => link.detach(), + Self::FdLink(link) => link.detach(), + Self::PerfLink(link) => link.detach(), } } } diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index bb60f082..36398967 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -213,7 +213,7 @@ impl TryFrom for PerfEventLink { fn try_from(fd_link: FdLink) -> Result { let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?; if info.type_ == (bpf_link_type::BPF_LINK_TYPE_PERF_EVENT as u32) { - return Ok(PerfEventLink::new(PerfLinkInner::FdLink(fd_link))); + return Ok(Self::new(PerfLinkInner::FdLink(fd_link))); } Err(LinkError::InvalidLink) } diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index 151c87ef..bff48612 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -36,8 +36,8 @@ pub enum ProbeKind { impl ProbeKind { fn pmu(&self) -> &'static str { match *self { - ProbeKind::KProbe | ProbeKind::KRetProbe => "kprobe", - ProbeKind::UProbe | ProbeKind::URetProbe => "uprobe", + Self::KProbe | Self::KRetProbe => "kprobe", + Self::UProbe | Self::URetProbe => "uprobe", } } } diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index e289e7d0..59a32ab2 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -95,9 +95,9 @@ pub enum TcError { impl TcAttachType { pub(crate) fn parent(&self) -> u32 { match self { - TcAttachType::Custom(parent) => *parent, - TcAttachType::Ingress => tc_handler_make(TC_H_CLSACT, TC_H_MIN_INGRESS), - TcAttachType::Egress => tc_handler_make(TC_H_CLSACT, TC_H_MIN_EGRESS), + Self::Custom(parent) => *parent, + Self::Ingress => tc_handler_make(TC_H_CLSACT, TC_H_MIN_INGRESS), + Self::Egress => tc_handler_make(TC_H_CLSACT, TC_H_MIN_EGRESS), } } } @@ -284,9 +284,9 @@ impl SchedClassifierLink { attach_type: TcAttachType, priority: u16, handle: u32, - ) -> Result { + ) -> Result { let if_index = ifindex_from_ifname(if_name)?; - Ok(SchedClassifierLink(Some(TcLink { + Ok(Self(Some(TcLink { if_index: if_index as i32, attach_type, priority, diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index 4c5d38db..8ed34eb4 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -140,7 +140,7 @@ impl TryFrom for TracePointLink { fn try_from(fd_link: FdLink) -> Result { let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?; if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) { - return Ok(TracePointLink::new(PerfLinkInner::FdLink(fd_link))); + return Ok(Self::new(PerfLinkInner::FdLink(fd_link))); } Err(LinkError::InvalidLink) } diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index e40bada2..5e30d174 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -28,7 +28,7 @@ use crate::{ const LD_SO_CACHE_FILE: &str = "/etc/ld.so.cache"; -lazy_static! { +lazy_static::lazy_static! { static ref LD_SO_CACHE: Result> = LdSoCache::load(LD_SO_CACHE_FILE).map_err(Arc::new); } @@ -204,7 +204,7 @@ impl TryFrom for UProbeLink { fn try_from(fd_link: FdLink) -> Result { let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?; if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) { - return Ok(UProbeLink::new(PerfLinkInner::FdLink(fd_link))); + return Ok(Self::new(PerfLinkInner::FdLink(fd_link))); } Err(LinkError::InvalidLink) } @@ -297,7 +297,7 @@ pub(crate) struct LdSoCache { } impl LdSoCache { - pub fn load>(path: T) -> Result { + fn load>(path: T) -> Result { let data = fs::read(path)?; Self::parse(&data) } @@ -386,10 +386,10 @@ impl LdSoCache { }) .collect::>()?; - Ok(LdSoCache { entries }) + Ok(Self { entries }) } - pub fn resolve(&self, lib: &str) -> Option<&str> { + fn resolve(&self, lib: &str) -> Option<&str> { let lib = if !lib.contains(".so") { lib.to_string() + ".so" } else { diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index beb9b5f5..c4e2e618 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -79,7 +79,7 @@ pub(crate) fn boot_time() -> SystemTime { } /// Get the specified information from a file descriptor's fdinfo. -pub(crate) fn get_fdinfo(fd: BorrowedFd, key: &str) -> Result { +pub(crate) fn get_fdinfo(fd: BorrowedFd<'_>, key: &str) -> Result { let info = File::open(format!("/proc/self/fdinfo/{}", fd.as_raw_fd()))?; let reader = BufReader::new(info); for line in reader.lines() { diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 36eec7d6..14db680c 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -14,11 +14,8 @@ use thiserror::Error; use crate::{ generated::{ - bpf_attach_type::{self, BPF_XDP}, - bpf_link_type, - bpf_prog_type::BPF_PROG_TYPE_XDP, - XDP_FLAGS_DRV_MODE, XDP_FLAGS_HW_MODE, XDP_FLAGS_REPLACE, XDP_FLAGS_SKB_MODE, - XDP_FLAGS_UPDATE_IF_NOEXIST, + bpf_attach_type, bpf_link_type, bpf_prog_type, XDP_FLAGS_DRV_MODE, XDP_FLAGS_HW_MODE, + XDP_FLAGS_REPLACE, XDP_FLAGS_SKB_MODE, XDP_FLAGS_UPDATE_IF_NOEXIST, }, programs::{ define_link_wrapper, load_program, FdLink, Link, LinkError, ProgramData, ProgramError, @@ -38,7 +35,7 @@ pub enum XdpError { }, } -bitflags! { +bitflags::bitflags! { /// Flags passed to [`Xdp::attach()`]. #[derive(Clone, Copy, Debug, Default)] pub struct XdpFlags: u32 { @@ -86,7 +83,7 @@ impl Xdp { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(bpf_attach_type::BPF_XDP); - load_program(BPF_PROG_TYPE_XDP, &mut self.data) + load_program(bpf_prog_type::BPF_PROG_TYPE_XDP, &mut self.data) } /// Attaches the program to the given `interface`. @@ -134,12 +131,17 @@ impl Xdp { let if_index = if_index as RawFd; if KernelVersion::current().unwrap() >= KernelVersion::new(5, 9, 0) { - let link_fd = bpf_link_create(prog_fd, if_index, BPF_XDP, None, flags.bits()).map_err( - |(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - }, - )?; + let link_fd = bpf_link_create( + prog_fd, + if_index, + bpf_attach_type::BPF_XDP, + None, + flags.bits(), + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd)))) @@ -257,15 +259,15 @@ impl Link for XdpLinkInner { fn id(&self) -> Self::Id { match self { - XdpLinkInner::FdLink(link) => XdpLinkIdInner::FdLinkId(link.id()), - XdpLinkInner::NlLink(link) => XdpLinkIdInner::NlLinkId(link.id()), + Self::FdLink(link) => XdpLinkIdInner::FdLinkId(link.id()), + Self::NlLink(link) => XdpLinkIdInner::NlLinkId(link.id()), } } fn detach(self) -> Result<(), ProgramError> { match self { - XdpLinkInner::FdLink(link) => link.detach(), - XdpLinkInner::NlLink(link) => link.detach(), + Self::FdLink(link) => link.detach(), + Self::NlLink(link) => link.detach(), } } } @@ -289,7 +291,7 @@ impl TryFrom for XdpLink { // unwrap of fd_link.fd will not panic since it's only None when being dropped. let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?; if info.type_ == (bpf_link_type::BPF_LINK_TYPE_XDP as u32) { - return Ok(XdpLink::new(XdpLinkInner::FdLink(fd_link))); + return Ok(Self::new(XdpLinkInner::FdLink(fd_link))); } Err(LinkError::InvalidLink) } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 23fcf8e3..e142c6c4 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -1,5 +1,5 @@ use std::{ - cmp::{self, min}, + cmp, ffi::{CStr, CString}, io, iter, mem::{self, MaybeUninit}, @@ -129,7 +129,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> { } pub(crate) fn bpf_load_program( - aya_attr: &BpfLoadProgramAttrs, + aya_attr: &BpfLoadProgramAttrs<'_>, log_buf: &mut [u8], verifier_log_level: VerifierLogLevel, ) -> SysResult { @@ -140,7 +140,7 @@ pub(crate) fn bpf_load_program( if let Some(prog_name) = &aya_attr.name { let mut name: [c_char; 16] = [0; 16]; let name_bytes = prog_name.to_bytes(); - let len = min(name.len(), name_bytes.len()); + let len = cmp::min(name.len(), name_bytes.len()); name[..len].copy_from_slice(unsafe { slice::from_raw_parts(name_bytes.as_ptr() as *const c_char, len) }); @@ -613,7 +613,7 @@ pub(crate) fn is_prog_name_supported() -> bool { let mut name: [c_char; 16] = [0; 16]; let cstring = CString::new("aya_name_check").unwrap(); let name_bytes = cstring.to_bytes(); - let len = min(name.len(), name_bytes.len()); + let len = cmp::min(name.len(), name_bytes.len()); name[..len].copy_from_slice(unsafe { slice::from_raw_parts(name_bytes.as_ptr() as *const c_char, len) }); @@ -980,7 +980,7 @@ pub(crate) fn retry_with_verifier_logs( f: impl Fn(&mut [u8]) -> SysResult, ) -> (SysResult, VerifierLog) { const MIN_LOG_BUF_SIZE: usize = 1024 * 10; - const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize; + const MAX_LOG_BUF_SIZE: usize = (u32::MAX >> 8) as usize; let mut log_buf = Vec::new(); let mut retries = 0; diff --git a/aya/src/sys/fake.rs b/aya/src/sys/fake.rs index 6cac51b6..df2deece 100644 --- a/aya/src/sys/fake.rs +++ b/aya/src/sys/fake.rs @@ -4,7 +4,7 @@ use libc::c_void; use super::{SysResult, Syscall}; -type SyscallFn = unsafe fn(Syscall) -> SysResult; +type SyscallFn = unsafe fn(Syscall<'_>) -> SysResult; #[cfg(test)] thread_local! { @@ -13,11 +13,11 @@ thread_local! { } #[cfg(test)] -unsafe fn test_syscall(_call: Syscall) -> SysResult { +unsafe fn test_syscall(_call: Syscall<'_>) -> SysResult { Err((-1, io::Error::from_raw_os_error(libc::EINVAL))) } #[cfg(test)] -pub(crate) fn override_syscall(call: unsafe fn(Syscall) -> SysResult) { +pub(crate) fn override_syscall(call: unsafe fn(Syscall<'_>) -> SysResult) { TEST_SYSCALL.with(|test_impl| *test_impl.borrow_mut() = call); } diff --git a/aya/src/sys/mod.rs b/aya/src/sys/mod.rs index ef2a0edf..239e68a9 100644 --- a/aya/src/sys/mod.rs +++ b/aya/src/sys/mod.rs @@ -85,7 +85,7 @@ impl std::fmt::Debug for Syscall<'_> { } } -fn syscall(call: Syscall) -> SysResult { +fn syscall(call: Syscall<'_>) -> SysResult { #[cfg(test)] return TEST_SYSCALL.with(|test_impl| unsafe { test_impl.borrow()(call) }); @@ -103,7 +103,10 @@ fn syscall(call: Syscall) -> SysResult { flags, } => libc::syscall(SYS_perf_event_open, &attr, pid, cpu, group, flags), Syscall::PerfEventIoctl { fd, request, arg } => { - libc::ioctl(fd.as_raw_fd(), request.try_into().unwrap(), arg) as libc::c_long + let int = libc::ioctl(fd.as_raw_fd(), request.try_into().unwrap(), arg); + #[allow(trivial_numeric_casts)] + let int = int as c_long; + int } } } { diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index 1dfae70d..ac302f50 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -286,7 +286,7 @@ struct NetlinkSocket { } impl NetlinkSocket { - fn open() -> Result { + fn open() -> Result { // Safety: libc wrapper let sock = unsafe { socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) }; if sock < 0 { @@ -315,7 +315,7 @@ impl NetlinkSocket { return Err(io::Error::last_os_error()); } - Ok(NetlinkSocket { + Ok(Self { sock, _nl_pid: addr.nl_pid, }) @@ -375,7 +375,7 @@ struct NetlinkMessage { } impl NetlinkMessage { - fn read(buf: &[u8]) -> Result { + fn read(buf: &[u8]) -> Result { if mem::size_of::() > buf.len() { return Err(io::Error::new( io::ErrorKind::Other, @@ -413,7 +413,7 @@ impl NetlinkMessage { (buf[data_offset..msg_len].to_vec(), None) }; - Ok(NetlinkMessage { + Ok(Self { header, data, error, @@ -443,8 +443,8 @@ struct NestedAttrs<'a> { } impl<'a> NestedAttrs<'a> { - fn new(buf: &mut [u8], top_attr_type: u16) -> NestedAttrs<'_> { - NestedAttrs { + fn new(buf: &'a mut [u8], top_attr_type: u16) -> Self { + Self { buf, top_attr_type, offset: NLA_HDR_LEN, @@ -528,8 +528,8 @@ struct NlAttrsIterator<'a> { } impl<'a> NlAttrsIterator<'a> { - fn new(attrs: &[u8]) -> NlAttrsIterator { - NlAttrsIterator { attrs, offset: 0 } + fn new(attrs: &'a [u8]) -> Self { + Self { attrs, offset: 0 } } } @@ -570,7 +570,7 @@ impl<'a> Iterator for NlAttrsIterator<'a> { } } -fn parse_attrs(buf: &[u8]) -> Result, NlAttrError> { +fn parse_attrs(buf: &[u8]) -> Result>, NlAttrError> { let mut attrs = HashMap::new(); for attr in NlAttrsIterator::new(buf) { let attr = attr?; @@ -595,8 +595,8 @@ enum NlAttrError { } impl From for io::Error { - fn from(e: NlAttrError) -> io::Error { - io::Error::new(io::ErrorKind::Other, e) + fn from(e: NlAttrError) -> Self { + Self::new(io::ErrorKind::Other, e) } } diff --git a/aya/src/util.rs b/aya/src/util.rs index 65bcb415..54c289b0 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -133,10 +133,10 @@ impl KernelVersion { } fn parse_kernel_version_string(s: &str) -> Result { - fn parse>(s: Option<&str>) -> Option { + fn parse>(s: Option<&str>) -> Option { match s.map(str::parse).transpose() { Ok(option) => option, - Err(std::num::ParseIntError { .. }) => None, + Err(ParseIntError { .. }) => None, } } let error = || CurrentKernelVersionError::ParseError(s.to_string()); diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index ebf7699f..d33436fb 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1227,8 +1227,8 @@ pub aya::maps::MapData::pinned: bool impl aya::maps::MapData pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option>) -> core::result::Result pub fn aya::maps::MapData::fd(&self) -> aya::maps::MapFd -pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result -pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result +pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result +pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result impl core::clone::Clone for aya::maps::MapData pub fn aya::maps::MapData::clone(&self) -> Self impl core::ops::drop::Drop for aya::maps::MapData @@ -3971,7 +3971,7 @@ impl core::convert::From for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::from(t: T) -> T pub struct aya::programs::tc::SchedClassifierLink(_) impl aya::programs::tc::SchedClassifierLink -pub fn aya::programs::tc::SchedClassifierLink::attached(if_name: &str, attach_type: aya::programs::tc::TcAttachType, priority: u16, handle: u32) -> core::result::Result +pub fn aya::programs::tc::SchedClassifierLink::attached(if_name: &str, attach_type: aya::programs::tc::TcAttachType, priority: u16, handle: u32) -> core::result::Result pub fn aya::programs::tc::SchedClassifierLink::handle(&self) -> u32 pub fn aya::programs::tc::SchedClassifierLink::priority(&self) -> u16 impl aya::programs::links::Link for aya::programs::tc::SchedClassifierLink @@ -6219,7 +6219,7 @@ pub struct aya::programs::ProgramInfo(_) impl aya::programs::ProgramInfo pub fn aya::programs::ProgramInfo::btf_id(&self) -> core::option::Option pub fn aya::programs::ProgramInfo::fd(&self) -> core::result::Result -pub fn aya::programs::ProgramInfo::from_pin>(path: P) -> core::result::Result +pub fn aya::programs::ProgramInfo::from_pin>(path: P) -> core::result::Result pub fn aya::programs::ProgramInfo::gpl_compatible(&self) -> bool pub fn aya::programs::ProgramInfo::id(&self) -> u32 pub fn aya::programs::ProgramInfo::loaded_at(&self) -> std::time::SystemTime @@ -7041,8 +7041,8 @@ impl core::convert::From for aya::BpfError pub fn aya::BpfError::from(t: T) -> T pub struct aya::Bpf impl aya::Bpf -pub fn aya::Bpf::load(data: &[u8]) -> core::result::Result -pub fn aya::Bpf::load_file>(path: P) -> core::result::Result +pub fn aya::Bpf::load(data: &[u8]) -> core::result::Result +pub fn aya::Bpf::load_file>(path: P) -> core::result::Result pub fn aya::Bpf::map(&self, name: &str) -> core::option::Option<&aya::maps::Map> pub fn aya::Bpf::map_mut(&mut self, name: &str) -> core::option::Option<&mut aya::maps::Map> pub fn aya::Bpf::maps(&self) -> impl core::iter::traits::iterator::Iterator @@ -7082,12 +7082,12 @@ pub fn aya::BpfLoader<'a>::extension(&mut self, name: &'a str) -> &mut aya::BpfL pub fn aya::BpfLoader<'a>::load(&mut self, data: &[u8]) -> core::result::Result pub fn aya::BpfLoader<'a>::load_file>(&mut self, path: P) -> core::result::Result pub fn aya::BpfLoader<'a>::map_pin_path>(&mut self, path: P) -> &mut aya::BpfLoader<'a> -pub fn aya::BpfLoader<'a>::new() -> aya::BpfLoader<'a> +pub fn aya::BpfLoader<'a>::new() -> Self pub fn aya::BpfLoader<'a>::set_global>>(&mut self, name: &'a str, value: T, must_exist: bool) -> &mut aya::BpfLoader<'a> pub fn aya::BpfLoader<'a>::set_max_entries(&mut self, name: &'a str, size: u32) -> &mut aya::BpfLoader<'a> pub fn aya::BpfLoader<'a>::verifier_log_level(&mut self, level: aya::VerifierLogLevel) -> &mut aya::BpfLoader<'a> -impl<'a> core::default::Default for aya::BpfLoader<'a> -pub fn aya::BpfLoader<'a>::default() -> Self +impl core::default::Default for aya::BpfLoader<'_> +pub fn aya::BpfLoader<'_>::default() -> Self impl<'a> core::fmt::Debug for aya::BpfLoader<'a> pub fn aya::BpfLoader<'a>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl<'a> core::marker::Send for aya::BpfLoader<'a> From ca2e43d318da6e903d211b4ca28c9f4df34e351c Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 22 Aug 2023 13:16:05 -0400 Subject: [PATCH 04/95] integration-test: Remove cargo symlink workaround https://github.com/rust-lang/cargo/pull/12369 fixed this bug and was picked up in https://github.com/rust-lang/rust/pull/114027. --- test/integration-ebpf/Cargo.toml | 1 + test/integration-ebpf/build.rs | 14 +++++--------- xtask/src/lib.rs | 30 +----------------------------- 3 files changed, 7 insertions(+), 38 deletions(-) diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index 38c097f3..12b04546 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -9,6 +9,7 @@ aya-bpf = { path = "../../bpf/aya-bpf" } aya-log-ebpf = { path = "../../bpf/aya-log-ebpf" } [build-dependencies] +which = { workspace = true } xtask = { path = "../../xtask" } [[bin]] diff --git a/test/integration-ebpf/build.rs b/test/integration-ebpf/build.rs index dd4a6501..d339e195 100644 --- a/test/integration-ebpf/build.rs +++ b/test/integration-ebpf/build.rs @@ -1,6 +1,7 @@ -use std::{env, path::PathBuf}; +use std::env; -use xtask::{create_symlink_to_binary, AYA_BUILD_INTEGRATION_BPF}; +use which::which; +use xtask::AYA_BUILD_INTEGRATION_BPF; /// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be /// better expressed by [artifact-dependencies][bindeps] but issues such as @@ -24,12 +25,7 @@ fn main() { .unwrap_or_default(); if build_integration_bpf { - let out_dir = env::var_os("OUT_DIR").unwrap(); - let out_dir = PathBuf::from(out_dir); - let bpf_linker_symlink = create_symlink_to_binary(&out_dir, "bpf-linker").unwrap(); - println!( - "cargo:rerun-if-changed={}", - bpf_linker_symlink.to_str().unwrap() - ); + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); } } diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 9e5c8737..18cf1b93 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -1,10 +1,5 @@ use anyhow::{bail, Context as _, Result}; -use std::{ - fs, - path::{Path, PathBuf}, - process::Command, -}; -use which::which; +use std::process::Command; pub const AYA_BUILD_INTEGRATION_BPF: &str = "AYA_BUILD_INTEGRATION_BPF"; pub const LIBBPF_DIR: &str = "xtask/libbpf"; @@ -18,26 +13,3 @@ pub fn exec(cmd: &mut Command) -> Result<()> { } Ok(()) } - -// Create a symlink in the out directory to work around the fact that cargo ignores anything -// in `$CARGO_HOME`, which is also where `cargo install` likes to place binaries. Cargo will -// stat through the symlink and discover that the binary has changed. -// -// This was introduced in https://github.com/rust-lang/cargo/commit/99f841c. -// -// TODO(https://github.com/rust-lang/cargo/pull/12369): Remove this when the fix is available. -pub fn create_symlink_to_binary(out_dir: &Path, binary_name: &str) -> Result { - let binary = which(binary_name).unwrap(); - let symlink = out_dir.join(binary_name); - match fs::remove_file(&symlink) { - Ok(()) => {} - Err(err) => { - if err.kind() != std::io::ErrorKind::NotFound { - return Err(err).context(format!("failed to remove symlink {}", symlink.display())); - } - } - } - std::os::unix::fs::symlink(binary, &symlink) - .with_context(|| format!("failed to create symlink {}", symlink.display()))?; - Ok(symlink) -} From 572d047e37111b732be49ef3ad6fb16f70aa4063 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 11 Aug 2023 10:20:38 -0400 Subject: [PATCH 05/95] test: avoid lossy string conversions We can be strict in tests. --- aya-obj/src/obj.rs | 43 ++++++++++++++++++------------------------ aya/src/sys/netlink.rs | 2 +- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 70375df2..73d87e68 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -1642,15 +1642,12 @@ mod tests { let prog_foo = obj.programs.get("foo").unwrap(); - assert_matches!( - prog_foo, - Program { - license, - kernel_version: None, - section: ProgramSection::KProbe { .. }, - .. - } if license.to_str().unwrap() == "GPL" - ); + assert_matches!(prog_foo, Program { + license, + kernel_version: None, + section: ProgramSection::KProbe { .. }, + .. + } => assert_eq!(license.to_str().unwrap(), "GPL")); assert_matches!( obj.functions.get(&prog_foo.function_key()), @@ -1704,14 +1701,12 @@ mod tests { let prog_bar = obj.programs.get("bar").unwrap(); let function_bar = obj.functions.get(&prog_bar.function_key()).unwrap(); - assert_matches!(prog_foo, - Program { - license, - kernel_version: None, - section: ProgramSection::KProbe { .. }, - .. - } if license.to_string_lossy() == "GPL" - ); + assert_matches!(prog_foo, Program { + license, + kernel_version: None, + section: ProgramSection::KProbe { .. }, + .. + } => assert_eq!(license.to_str().unwrap(), "GPL")); assert_matches!( function_foo, Function { @@ -1724,14 +1719,12 @@ mod tests { } if name == "foo" && instructions.len() == 1 ); - assert_matches!(prog_bar, - Program { - license, - kernel_version: None, - section: ProgramSection::KProbe { .. }, - .. - } if license.to_string_lossy() == "GPL" - ); + assert_matches!(prog_bar, Program { + license, + kernel_version: None, + section: ProgramSection::KProbe { .. }, + .. + } => assert_eq!(license.to_str().unwrap(), "GPL")); assert_matches!( function_bar, Function { diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index ac302f50..a7b24902 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -742,6 +742,6 @@ mod tests { TCA_BPF_NAME as u16 ); let name = CStr::from_bytes_with_nul(inner.data).unwrap(); - assert_eq!(name.to_string_lossy(), "foo"); + assert_eq!(name.to_str().unwrap(), "foo"); } } From 0bba9b14b02a01ca33dbb1fa4a910b77a73a4d65 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 10 Aug 2023 11:44:37 -0400 Subject: [PATCH 06/95] maps,programs: avoid path UTF-8 assumptions --- aya/src/bpf.rs | 12 -- aya/src/maps/mod.rs | 41 ++++-- aya/src/pin.rs | 10 +- aya/src/programs/kprobe.rs | 10 +- aya/src/programs/links.rs | 22 +-- aya/src/programs/mod.rs | 23 +-- aya/src/programs/probe.rs | 243 ++++++++++++++++++++++---------- aya/src/programs/tc.rs | 11 +- aya/src/programs/trace_point.rs | 4 +- aya/src/programs/uprobe.rs | 132 +++++++++-------- aya/src/programs/xdp.rs | 1 + aya/src/sys/perf_event.rs | 7 +- xtask/public-api/aya.txt | 13 +- 13 files changed, 325 insertions(+), 204 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index f8bf467c..f967c737 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -1,7 +1,6 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, - ffi::CString, fs, io, os::{ fd::{AsFd as _, OwnedFd}, @@ -608,10 +607,6 @@ impl<'a> BpfLoader<'a> { ProgramSection::SchedClassifier => { Program::SchedClassifier(SchedClassifier { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), - name: unsafe { - CString::from_vec_unchecked(Vec::from(name.clone())) - .into_boxed_c_str() - }, }) } ProgramSection::CgroupSkb => Program::CgroupSkb(CgroupSkb { @@ -960,13 +955,6 @@ pub enum BpfError { name: u32, }, - /// Invalid path - #[error("invalid path `{error}`")] - InvalidPath { - /// The error message - error: String, - }, - /// Error parsing BPF object #[error("error parsing BPF object: {0}")] ParseError(#[from] ParseError), diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 0cd5386e..dfa0949c 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -515,9 +515,19 @@ impl MapData { name: &str, btf_fd: Option>, ) -> Result { + use std::os::unix::ffi::OsStrExt as _; + // try to open map in case it's already pinned - let map_path = path.as_ref().join(name); - let path_string = CString::new(map_path.to_str().unwrap()).unwrap(); + let path = path.as_ref().join(name); + let path_string = match CString::new(path.as_os_str().as_bytes()) { + Ok(path) => path, + Err(error) => { + return Err(MapError::PinError { + name: Some(name.into()), + error: PinError::InvalidPinPath { path, error }, + }); + } + }; match bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_GET", io_error, @@ -540,14 +550,16 @@ impl MapData { /// Loads a map from a pinned path in bpffs. pub fn from_pin>(path: P) -> Result { + use std::os::unix::ffi::OsStrExt as _; + + let path = path.as_ref(); let path_string = - CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { - MapError::PinError { - name: None, - error: PinError::InvalidPinPath { - error: e.to_string(), - }, - } + CString::new(path.as_os_str().as_bytes()).map_err(|error| MapError::PinError { + name: None, + error: PinError::InvalidPinPath { + path: path.into(), + error, + }, })?; let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { @@ -580,16 +592,15 @@ impl MapData { } pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { + use std::os::unix::ffi::OsStrExt as _; + let Self { fd, pinned, obj: _ } = self; if *pinned { return Err(PinError::AlreadyPinned { name: name.into() }); } - let map_path = path.as_ref().join(name); - let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| { - PinError::InvalidPinPath { - error: e.to_string(), - } - })?; + let path = path.as_ref().join(name); + let path_string = CString::new(path.as_os_str().as_bytes()) + .map_err(|error| PinError::InvalidPinPath { path, error })?; bpf_pin_object(*fd, &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, diff --git a/aya/src/pin.rs b/aya/src/pin.rs index eda85bbc..743df95f 100644 --- a/aya/src/pin.rs +++ b/aya/src/pin.rs @@ -19,10 +19,14 @@ pub enum PinError { name: String, }, /// The path for the BPF object is not valid. - #[error("invalid pin path `{error}`")] + #[error("invalid pin path `{}`", path.display())] InvalidPinPath { - /// The error message. - error: String, + /// The path. + path: std::path::PathBuf, + + #[source] + /// The source error. + error: std::ffi::NulError, }, /// An error ocurred making a syscall. #[error(transparent)] diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index a0c8d2b4..ef34a3f4 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -1,5 +1,9 @@ //! Kernel space probes. -use std::{io, os::fd::AsFd as _, path::Path}; +use std::{ + io, + os::fd::AsFd as _, + path::{Path, PathBuf}, +}; use thiserror::Error; use crate::{ @@ -68,7 +72,7 @@ impl KProbe { /// /// The returned value can be used to detach from the given function, see [KProbe::detach]. pub fn attach(&mut self, fn_name: &str, offset: u64) -> Result { - attach(&mut self.data, self.kind, fn_name, offset, None) + attach(&mut self.data, self.kind, Path::new(fn_name), offset, None) } /// Detaches the program. @@ -114,7 +118,7 @@ pub enum KProbeError { #[error("`{filename}`")] FileError { /// The file name - filename: String, + filename: PathBuf, /// The [`io::Error`] returned from the file operation #[source] io_error: io::Error, diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 77341adc..71b0aba1 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -146,19 +146,22 @@ impl FdLink { /// # Ok::<(), Error>(()) /// ``` pub fn pin>(self, path: P) -> Result { - let path_string = - CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { - PinError::InvalidPinPath { - error: e.to_string(), - } - })?; + use std::os::unix::ffi::OsStrExt as _; + + let path = path.as_ref(); + let path_string = CString::new(path.as_os_str().as_bytes()).map_err(|error| { + PinError::InvalidPinPath { + path: path.into(), + error, + } + })?; bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| { SyscallError { call: "BPF_OBJ_PIN", io_error, } })?; - Ok(PinnedLink::new(PathBuf::from(path.as_ref()), self)) + Ok(PinnedLink::new(path.into(), self)) } } @@ -203,7 +206,10 @@ impl PinnedLink { /// Creates a [`crate::programs::links::PinnedLink`] from a valid path on bpffs. pub fn from_pin>(path: P) -> Result { - let path_string = CString::new(path.as_ref().to_string_lossy().to_string()).unwrap(); + use std::os::unix::ffi::OsStrExt as _; + + // TODO: avoid this unwrap by adding a new error variant. + let path_string = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap(); let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| { LinkError::SyscallError(SyscallError { call: "BPF_OBJ_GET", diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index dcec8bf3..07755307 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -487,9 +487,10 @@ impl ProgramData { path: P, verifier_log_level: VerifierLogLevel, ) -> Result { - let path_string = - CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap(); + use std::os::unix::ffi::OsStrExt as _; + // TODO: avoid this unwrap by adding a new error variant. + let path_string = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap(); let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { call: "bpf_obj_get", io_error, @@ -520,6 +521,8 @@ fn unload_program(data: &mut ProgramData) -> Result<(), ProgramError } fn pin_program>(data: &ProgramData, path: P) -> Result<(), PinError> { + use std::os::unix::ffi::OsStrExt as _; + let fd = data.fd.as_ref().ok_or(PinError::NoFd { name: data .name @@ -527,11 +530,12 @@ fn pin_program>(data: &ProgramData, path: P) -> Resul .unwrap_or("") .to_string(), })?; - let path_string = CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { - PinError::InvalidPinPath { - error: e.to_string(), - } - })?; + let path = path.as_ref(); + let path_string = + CString::new(path.as_os_str().as_bytes()).map_err(|error| PinError::InvalidPinPath { + path: path.into(), + error, + })?; bpf_pin_object(fd.as_fd().as_raw_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, @@ -1073,7 +1077,10 @@ impl ProgramInfo { /// Loads a program from a pinned path in bpffs. pub fn from_pin>(path: P) -> Result { - let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap(); + use std::os::unix::ffi::OsStrExt as _; + + // TODO: avoid this unwrap by adding a new error variant. + let path_string = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap(); let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_GET", io_error, diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index bff48612..ea0d59b5 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -1,10 +1,12 @@ use crate::util::KernelVersion; use libc::pid_t; use std::{ + ffi::{OsStr, OsString}, + fmt::Write as _, fs::{self, OpenOptions}, io::{self, Write}, os::fd::{AsFd as _, AsRawFd as _, OwnedFd}, - path::Path, + path::{Path, PathBuf}, process, sync::atomic::{AtomicUsize, Ordering}, }; @@ -42,16 +44,64 @@ impl ProbeKind { } } +pub(crate) fn lines(bytes: &[u8]) -> impl Iterator { + use std::os::unix::ffi::OsStrExt as _; + + bytes.as_ref().split(|b| b == &b'\n').map(|mut line| { + while let [stripped @ .., c] = line { + if c.is_ascii_whitespace() { + line = stripped; + continue; + } + break; + } + OsStr::from_bytes(line) + }) +} + +pub(crate) trait OsStringExt { + fn starts_with(&self, needle: &OsStr) -> bool; + fn ends_with(&self, needle: &OsStr) -> bool; + fn strip_prefix(&self, prefix: &OsStr) -> Option<&OsStr>; + fn strip_suffix(&self, suffix: &OsStr) -> Option<&OsStr>; +} + +impl OsStringExt for OsStr { + fn starts_with(&self, needle: &OsStr) -> bool { + use std::os::unix::ffi::OsStrExt as _; + self.as_bytes().starts_with(needle.as_bytes()) + } + + fn ends_with(&self, needle: &OsStr) -> bool { + use std::os::unix::ffi::OsStrExt as _; + self.as_bytes().ends_with(needle.as_bytes()) + } + + fn strip_prefix(&self, prefix: &OsStr) -> Option<&OsStr> { + use std::os::unix::ffi::OsStrExt as _; + self.as_bytes() + .strip_prefix(prefix.as_bytes()) + .map(Self::from_bytes) + } + + fn strip_suffix(&self, suffix: &OsStr) -> Option<&OsStr> { + use std::os::unix::ffi::OsStrExt as _; + self.as_bytes() + .strip_suffix(suffix.as_bytes()) + .map(Self::from_bytes) + } +} + #[derive(Debug)] pub(crate) struct ProbeEvent { kind: ProbeKind, - event_alias: String, + event_alias: OsString, } pub(crate) fn attach>( program_data: &mut ProgramData, kind: ProbeKind, - fn_name: &str, + fn_name: &Path, offset: u64, pid: Option, ) -> Result { @@ -90,7 +140,7 @@ pub(crate) fn detach_debug_fs(event: ProbeEvent) -> Result<(), ProgramError> { fn create_as_probe( kind: ProbeKind, - fn_name: &str, + fn_name: &Path, offset: u64, pid: Option, ) -> Result { @@ -126,10 +176,10 @@ fn create_as_probe( fn create_as_trace_point( kind: ProbeKind, - name: &str, + name: &Path, offset: u64, pid: Option, -) -> Result<(OwnedFd, String), ProgramError> { +) -> Result<(OwnedFd, OsString), ProgramError> { use ProbeKind::*; let tracefs = find_tracefs_path()?; @@ -142,7 +192,7 @@ fn create_as_trace_point( }; let category = format!("{}s", kind.pmu()); - let tpid = read_sys_fs_trace_point_id(tracefs, &category, &event_alias)?; + let tpid = read_sys_fs_trace_point_id(tracefs, &category, event_alias.as_ref())?; let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| SyscallError { call: "perf_event_open", io_error, @@ -154,9 +204,10 @@ fn create_as_trace_point( fn create_probe_event( tracefs: &Path, kind: ProbeKind, - fn_name: &str, + fn_name: &Path, offset: u64, -) -> Result { +) -> Result { + use std::os::unix::ffi::OsStrExt as _; use ProbeKind::*; let events_file_name = tracefs.join(format!("{}_events", kind.pmu())); @@ -165,93 +216,129 @@ fn create_probe_event( KRetProbe | URetProbe => 'r', }; - let fixed_fn_name = fn_name.replace(['.', '/', '-'], "_"); + let fn_name = fn_name.as_os_str(); - let event_alias = format!( - "aya_{}_{}_{}_{:#x}_{}", + let mut event_alias = OsString::new(); + write!( + &mut event_alias, + "aya_{}_{}_", process::id(), probe_type_prefix, - fixed_fn_name, + ) + .unwrap(); + for b in fn_name.as_bytes() { + let b = match *b { + b'.' | b'/' | b'-' => b'_', + b => b, + }; + event_alias.push(OsStr::from_bytes(&[b])); + } + write!( + &mut event_alias, + "_{:#x}_{}", offset, PROBE_NAME_INDEX.fetch_add(1, Ordering::AcqRel) - ); - let offset_suffix = match kind { - KProbe => format!("+{offset}"), - UProbe | URetProbe => format!(":{offset:#x}"), - _ => String::new(), + ) + .unwrap(); + + let mut probe = OsString::new(); + write!(&mut probe, "{}:{}s/", probe_type_prefix, kind.pmu(),).unwrap(); + probe.push(&event_alias); + probe.push(" "); + probe.push(fn_name); + match kind { + KProbe => write!(&mut probe, "+{offset}").unwrap(), + UProbe | URetProbe => write!(&mut probe, ":{offset:#x}").unwrap(), + _ => {} }; - let probe = format!( - "{}:{}s/{} {}{}\n", - probe_type_prefix, - kind.pmu(), - event_alias, - fn_name, - offset_suffix - ); + probe.push("\n"); - let mut events_file = OpenOptions::new() + OpenOptions::new() .append(true) .open(&events_file_name) - .map_err(|e| (events_file_name.display().to_string(), e))?; - - events_file - .write_all(probe.as_bytes()) - .map_err(|e| (events_file_name.display().to_string(), e))?; + .and_then(|mut events_file| events_file.write_all(probe.as_bytes())) + .map_err(|e| (events_file_name, e))?; Ok(event_alias) } -fn delete_probe_event(tracefs: &Path, event: ProbeEvent) -> Result<(), (String, io::Error)> { +fn delete_probe_event(tracefs: &Path, event: ProbeEvent) -> Result<(), (PathBuf, io::Error)> { + use std::os::unix::ffi::OsStrExt as _; + let ProbeEvent { kind, event_alias } = event; let events_file_name = tracefs.join(format!("{}_events", kind.pmu())); - let events = fs::read_to_string(&events_file_name) - .map_err(|e| (events_file_name.display().to_string(), e))?; - - let found = events.lines().any(|line| line.contains(&event_alias)); - - if found { - let mut events_file = OpenOptions::new() - .append(true) - .open(&events_file_name) - .map_err(|e| (events_file_name.display().to_string(), e))?; - - let rm = format!("-:{event_alias}\n"); - - events_file - .write_all(rm.as_bytes()) - .map_err(|e| (events_file_name.display().to_string(), e))?; - } - - Ok(()) + fs::read(&events_file_name) + .and_then(|events| { + let found = lines(&events).any(|line| { + let mut line = line.as_bytes(); + // See [`create_probe_event`] and the documentation: + // + // https://docs.kernel.org/trace/kprobetrace.html + // + // https://docs.kernel.org/trace/uprobetracer.html + loop { + match line.split_first() { + None => break false, + Some((b, rest)) => { + line = rest; + if *b == b'/' { + break line.starts_with(event_alias.as_bytes()); + } + } + } + } + }); + + if found { + OpenOptions::new() + .append(true) + .open(&events_file_name) + .and_then(|mut events_file| { + let mut rm = OsString::new(); + rm.push("-:"); + rm.push(event_alias); + rm.push("\n"); + + events_file.write_all(rm.as_bytes()) + }) + } else { + Ok(()) + } + }) + .map_err(|e| (events_file_name, e)) } -fn read_sys_fs_perf_type(pmu: &str) -> Result { - let file = format!("/sys/bus/event_source/devices/{pmu}/type"); - - let perf_ty = fs::read_to_string(&file).map_err(|e| (file.clone(), e))?; - let perf_ty = perf_ty - .trim() - .parse::() - .map_err(|e| (file, io::Error::new(io::ErrorKind::Other, e)))?; - - Ok(perf_ty) +fn read_sys_fs_perf_type(pmu: &str) -> Result { + let file = Path::new("/sys/bus/event_source/devices") + .join(pmu) + .join("type"); + + fs::read_to_string(&file) + .and_then(|perf_ty| { + perf_ty + .trim() + .parse::() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + }) + .map_err(|e| (file, e)) } -fn read_sys_fs_perf_ret_probe(pmu: &str) -> Result { - let file = format!("/sys/bus/event_source/devices/{pmu}/format/retprobe"); - - let data = fs::read_to_string(&file).map_err(|e| (file.clone(), e))?; - - let mut parts = data.trim().splitn(2, ':').skip(1); - let config = parts.next().ok_or_else(|| { - ( - file.clone(), - io::Error::new(io::ErrorKind::Other, "invalid format"), - ) - })?; - - config - .parse::() - .map_err(|e| (file, io::Error::new(io::ErrorKind::Other, e))) +fn read_sys_fs_perf_ret_probe(pmu: &str) -> Result { + let file = Path::new("/sys/bus/event_source/devices") + .join(pmu) + .join("format/retprobe"); + + fs::read_to_string(&file) + .and_then(|data| { + let mut parts = data.trim().splitn(2, ':').skip(1); + let config = parts + .next() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid format"))?; + + config + .parse::() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + }) + .map_err(|e| (file, e)) } diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index 59a32ab2..8cb73cea 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -74,7 +74,6 @@ pub enum TcAttachType { #[doc(alias = "BPF_PROG_TYPE_SCHED_CLS")] pub struct SchedClassifier { pub(crate) data: ProgramData, - pub(crate) name: Box, } /// Errors from TC programs @@ -158,12 +157,15 @@ impl SchedClassifier { let prog_fd = prog_fd.as_raw_fd(); let if_index = ifindex_from_ifname(interface) .map_err(|io_error| TcError::NetlinkError { io_error })?; + let name = self.data.name.as_deref().unwrap_or_default(); + // TODO: avoid this unwrap by adding a new error variant. + let name = CString::new(name).unwrap(); let (priority, handle) = unsafe { netlink_qdisc_attach( if_index as i32, &attach_type, prog_fd, - &self.name, + &name, options.priority, options.handle, ) @@ -204,10 +206,7 @@ impl SchedClassifier { /// the program being unloaded from the kernel if it is still pinned. pub fn from_pin>(path: P) -> Result { let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?; - let cname = CString::new(data.name.clone().unwrap_or_default()) - .unwrap() - .into_boxed_c_str(); - Ok(Self { data, name: cname }) + Ok(Self { data }) } } diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index 8ed34eb4..b9a4c5b1 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -86,7 +86,7 @@ impl TracePoint { let prog_fd = prog_fd.as_fd(); let prog_fd = prog_fd.as_raw_fd(); let tracefs = find_tracefs_path()?; - let id = read_sys_fs_trace_point_id(tracefs, category, name)?; + let id = read_sys_fs_trace_point_id(tracefs, category, name.as_ref())?; let fd = perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| SyscallError { call: "perf_event_open_trace_point", @@ -149,7 +149,7 @@ impl TryFrom for TracePointLink { pub(crate) fn read_sys_fs_trace_point_id( tracefs: &Path, category: &str, - name: &str, + name: &Path, ) -> Result { let file = tracefs.join("events").join(category).join(name).join("id"); diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 5e30d174..00d306ad 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -4,7 +4,7 @@ use object::{Object, ObjectSection, ObjectSymbol}; use std::{ borrow::Cow, error::Error, - ffi::CStr, + ffi::{CStr, OsStr, OsString}, fs, io::{self, BufRead, Cursor, Read}, mem, @@ -19,7 +19,7 @@ use crate::{ programs::{ define_link_wrapper, load_program, perf_attach::{PerfLinkIdInner, PerfLinkInner}, - probe::{attach, ProbeKind}, + probe::{attach, OsStringExt as _, ProbeKind}, FdLink, LinkError, ProgramData, ProgramError, }, sys::bpf_link_get_info_by_fd, @@ -83,7 +83,7 @@ impl UProbe { target: T, pid: Option, ) -> Result { - let path = resolve_attach_path(&target, pid)?; + let path = resolve_attach_path(target.as_ref(), pid)?; let sym_offset = if let Some(fn_name) = fn_name { resolve_symbol(&path, fn_name).map_err(|error| UProbeError::SymbolError { @@ -124,37 +124,33 @@ impl UProbe { } } -fn resolve_attach_path>( - target: &T, - pid: Option, -) -> Result, UProbeError> { +fn resolve_attach_path(target: &Path, pid: Option) -> Result, UProbeError> { // Look up the path for the target. If it there is a pid, and the target is a library name // that is in the process's memory map, use the path of that library. Otherwise, use the target as-is. - let target = target.as_ref(); - let invalid_target = || UProbeError::InvalidTarget { - path: target.to_owned(), - }; - let target_str = target.to_str().ok_or_else(invalid_target)?; pid.and_then(|pid| { - find_lib_in_proc_maps(pid, target_str) + find_lib_in_proc_maps(pid, target) .map_err(|io_error| UProbeError::FileError { - filename: format!("/proc/{pid}/maps"), + filename: Path::new("/proc").join(pid.to_string()).join("maps"), io_error, }) .map(|v| v.map(Cow::Owned)) .transpose() }) - .or_else(|| target.is_absolute().then(|| Ok(Cow::Borrowed(target_str)))) + .or_else(|| target.is_absolute().then(|| Ok(Cow::Borrowed(target)))) .or_else(|| { LD_SO_CACHE .as_ref() .map_err(|error| UProbeError::InvalidLdSoCache { io_error: error.clone(), }) - .map(|cache| cache.resolve(target_str).map(Cow::Borrowed)) + .map(|cache| cache.resolve(target).map(Cow::Borrowed)) .transpose() }) - .unwrap_or_else(|| Err(invalid_target())) + .unwrap_or_else(|| { + Err(UProbeError::InvalidTarget { + path: target.to_owned(), + }) + }) } // Only run this test on linux with glibc because only in that configuration do we know that we'll @@ -171,7 +167,8 @@ fn test_resolve_attach_path() { // Now let's resolve the path to libc. It should exist in the current process's memory map and // then in the ld.so.cache. - let libc_path = resolve_attach_path(&"libc", Some(pid)).unwrap(); + let libc_path = resolve_attach_path("libc".as_ref(), Some(pid)).unwrap(); + let libc_path = libc_path.to_str().unwrap(); // Make sure we got a path that contains libc. assert!(libc_path.contains("libc"), "libc_path: {}", libc_path); @@ -242,52 +239,60 @@ pub enum UProbeError { #[error("`{filename}`")] FileError { /// The file name - filename: String, + filename: PathBuf, /// The [`io::Error`] returned from the file operation #[source] io_error: io::Error, }, } -fn proc_maps_libs(pid: pid_t) -> Result, io::Error> { +fn proc_maps_libs(pid: pid_t) -> Result, io::Error> { + use std::os::unix::ffi::OsStrExt as _; + let maps_file = format!("/proc/{pid}/maps"); - let data = fs::read_to_string(maps_file)?; - - Ok(data - .lines() - .filter_map(|line| { - let line = line.split_whitespace().last()?; - if line.starts_with('/') { - let path = PathBuf::from(line); - let key = path.file_name().unwrap().to_string_lossy().into_owned(); - Some((key, path.to_string_lossy().to_string())) - } else { - None + let data = fs::read(maps_file)?; + + let libs = data + .split(|b| b == &b'\n') + .filter_map(|mut line| { + while let [stripped @ .., c] = line { + if c.is_ascii_whitespace() { + line = stripped; + continue; + } + break; } + let path = line.split(|b| b.is_ascii_whitespace()).last()?; + let path = Path::new(OsStr::from_bytes(path)); + path.is_absolute() + .then(|| { + path.file_name() + .map(|file_name| (file_name.to_owned(), path.to_owned())) + }) + .flatten() }) - .collect()) + .collect(); + Ok(libs) } -fn find_lib_in_proc_maps(pid: pid_t, lib: &str) -> Result, io::Error> { +fn find_lib_in_proc_maps(pid: pid_t, lib: &Path) -> Result, io::Error> { let libs = proc_maps_libs(pid)?; - let ret = if lib.contains(".so") { - libs.into_iter().find(|(k, _)| k.as_str().starts_with(lib)) - } else { - libs.into_iter().find(|(k, _)| { - k.strip_prefix(lib) - .map(|k| k.starts_with(".so") || k.starts_with('-')) - .unwrap_or_default() - }) - }; + let lib = lib.as_os_str(); + let lib = lib.strip_suffix(OsStr::new(".so")).unwrap_or(lib); - Ok(ret.map(|(_, v)| v)) + Ok(libs.into_iter().find_map(|(file_name, path)| { + file_name.strip_prefix(lib).and_then(|suffix| { + (suffix.starts_with(OsStr::new(".so")) || suffix.starts_with(OsStr::new("-"))) + .then_some(path) + }) + })) } #[derive(Debug)] pub(crate) struct CacheEntry { - key: String, - value: String, + key: OsString, + value: OsString, _flags: i32, } @@ -368,11 +373,16 @@ impl LdSoCache { } let read_str = |pos| { - unsafe { - CStr::from_ptr(cursor.get_ref()[offset + pos..].as_ptr() as *const c_char) - } - .to_string_lossy() - .into_owned() + use std::os::unix::ffi::OsStrExt as _; + OsStr::from_bytes( + unsafe { + CStr::from_ptr( + cursor.get_ref()[offset + pos..].as_ptr() as *const c_char + ) + } + .to_bytes(), + ) + .to_owned() }; let key = read_str(k_pos); @@ -389,16 +399,18 @@ impl LdSoCache { Ok(Self { entries }) } - fn resolve(&self, lib: &str) -> Option<&str> { - let lib = if !lib.contains(".so") { - lib.to_string() + ".so" - } else { - lib.to_string() - }; + fn resolve(&self, lib: &Path) -> Option<&Path> { + let lib = lib.as_os_str(); + let lib = lib.strip_suffix(OsStr::new(".so")).unwrap_or(lib); self.entries .iter() - .find(|entry| entry.key.starts_with(&lib)) - .map(|entry| entry.value.as_str()) + .find_map(|CacheEntry { key, value, _flags }| { + key.strip_prefix(lib).and_then(|suffix| { + suffix + .starts_with(OsStr::new(".so")) + .then_some(Path::new(value.as_os_str())) + }) + }) } } @@ -420,7 +432,7 @@ enum ResolveSymbolError { SectionFileRangeNone(String, Result), } -fn resolve_symbol(path: &str, symbol: &str) -> Result { +fn resolve_symbol(path: &Path, symbol: &str) -> Result { let data = fs::read(path)?; let obj = object::read::File::parse(&*data)?; diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 14db680c..22eb4f70 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -100,6 +100,7 @@ impl Xdp { /// [`XdpError::NetlinkError`] is returned for older /// kernels. pub fn attach(&mut self, interface: &str, flags: XdpFlags) -> Result { + // TODO: avoid this unwrap by adding a new error variant. let c_interface = CString::new(interface).unwrap(); let if_index = unsafe { if_nametoindex(c_interface.as_ptr()) }; if if_index == 0 { diff --git a/aya/src/sys/perf_event.rs b/aya/src/sys/perf_event.rs index dad86a45..000fecbc 100644 --- a/aya/src/sys/perf_event.rs +++ b/aya/src/sys/perf_event.rs @@ -2,6 +2,7 @@ use std::{ ffi::{c_long, CString}, io, mem, os::fd::{BorrowedFd, FromRawFd as _, OwnedFd}, + path::Path, }; use libc::{c_int, pid_t}; @@ -62,17 +63,19 @@ pub(crate) fn perf_event_open_bpf(cpu: c_int) -> SysResult { pub(crate) fn perf_event_open_probe( ty: u32, ret_bit: Option, - name: &str, + name: &Path, offset: u64, pid: Option, ) -> SysResult { + use std::os::unix::ffi::OsStrExt as _; + let mut attr = unsafe { mem::zeroed::() }; if let Some(ret_bit) = ret_bit { attr.config = 1 << ret_bit; } - let c_name = CString::new(name).unwrap(); + let c_name = CString::new(name.as_os_str().as_bytes()).unwrap(); attr.size = mem::size_of::() as u32; attr.type_ = ty; diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index d33436fb..1ef6c0c8 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1752,7 +1752,8 @@ pub enum aya::pin::PinError pub aya::pin::PinError::AlreadyPinned pub aya::pin::PinError::AlreadyPinned::name: alloc::string::String pub aya::pin::PinError::InvalidPinPath -pub aya::pin::PinError::InvalidPinPath::error: alloc::string::String +pub aya::pin::PinError::InvalidPinPath::error: alloc::ffi::c_str::NulError +pub aya::pin::PinError::InvalidPinPath::path: std::path::PathBuf pub aya::pin::PinError::NoFd pub aya::pin::PinError::NoFd::name: alloc::string::String pub aya::pin::PinError::SyscallError(crate::sys::SyscallError) @@ -2860,7 +2861,7 @@ pub fn aya::programs::fexit::FExitLinkId::from(t: T) -> T pub mod aya::programs::kprobe pub enum aya::programs::kprobe::KProbeError pub aya::programs::kprobe::KProbeError::FileError -pub aya::programs::kprobe::KProbeError::FileError::filename: alloc::string::String +pub aya::programs::kprobe::KProbeError::FileError::filename: std::path::PathBuf pub aya::programs::kprobe::KProbeError::FileError::io_error: std::io::error::Error impl core::convert::From for aya::programs::ProgramError pub fn aya::programs::ProgramError::from(source: aya::programs::kprobe::KProbeError) -> Self @@ -4330,7 +4331,7 @@ pub fn aya::programs::trace_point::TracePointLinkId::from(t: T) -> T pub mod aya::programs::uprobe pub enum aya::programs::uprobe::UProbeError pub aya::programs::uprobe::UProbeError::FileError -pub aya::programs::uprobe::UProbeError::FileError::filename: alloc::string::String +pub aya::programs::uprobe::UProbeError::FileError::filename: std::path::PathBuf pub aya::programs::uprobe::UProbeError::FileError::io_error: std::io::error::Error pub aya::programs::uprobe::UProbeError::InvalidLdSoCache pub aya::programs::uprobe::UProbeError::InvalidLdSoCache::io_error: alloc::sync::Arc @@ -4814,7 +4815,7 @@ impl core::convert::From for aya::programs::extension::ExtensionError pub fn aya::programs::extension::ExtensionError::from(t: T) -> T pub enum aya::programs::KProbeError pub aya::programs::KProbeError::FileError -pub aya::programs::KProbeError::FileError::filename: alloc::string::String +pub aya::programs::KProbeError::FileError::filename: std::path::PathBuf pub aya::programs::KProbeError::FileError::io_error: std::io::error::Error impl core::convert::From for aya::programs::ProgramError pub fn aya::programs::ProgramError::from(source: aya::programs::kprobe::KProbeError) -> Self @@ -5442,7 +5443,7 @@ impl core::convert::From for aya::programs::trace_point::TracePointError pub fn aya::programs::trace_point::TracePointError::from(t: T) -> T pub enum aya::programs::UProbeError pub aya::programs::UProbeError::FileError -pub aya::programs::UProbeError::FileError::filename: alloc::string::String +pub aya::programs::UProbeError::FileError::filename: std::path::PathBuf pub aya::programs::UProbeError::FileError::io_error: std::io::error::Error pub aya::programs::UProbeError::InvalidLdSoCache pub aya::programs::UProbeError::InvalidLdSoCache::io_error: alloc::sync::Arc @@ -6988,8 +6989,6 @@ pub aya::BpfError::BtfRelocationError(aya_obj::btf::relocation::BtfRelocationErr pub aya::BpfError::FileError pub aya::BpfError::FileError::error: std::io::error::Error pub aya::BpfError::FileError::path: std::path::PathBuf -pub aya::BpfError::InvalidPath -pub aya::BpfError::InvalidPath::error: alloc::string::String pub aya::BpfError::MapError(aya::maps::MapError) pub aya::BpfError::NoBTF pub aya::BpfError::NoPinPath From 1ccfdbc17577a5f132ba0af2eb9b754e6e19ddca Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 24 Aug 2023 11:17:52 -0400 Subject: [PATCH 07/95] aya: support non-UTF8 probing Fixes #751. --- aya/src/programs/kprobe.rs | 9 +++++++-- aya/src/programs/probe.rs | 16 ++++++++++------ aya/src/programs/uprobe.rs | 3 ++- aya/src/sys/perf_event.rs | 7 +++---- xtask/public-api/aya.txt | 4 ++-- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index ef34a3f4..c915136e 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -1,5 +1,6 @@ //! Kernel space probes. use std::{ + ffi::OsStr, io, os::fd::AsFd as _, path::{Path, PathBuf}, @@ -71,8 +72,12 @@ impl KProbe { /// target function. /// /// The returned value can be used to detach from the given function, see [KProbe::detach]. - pub fn attach(&mut self, fn_name: &str, offset: u64) -> Result { - attach(&mut self.data, self.kind, Path::new(fn_name), offset, None) + pub fn attach>( + &mut self, + fn_name: T, + offset: u64, + ) -> Result { + attach(&mut self.data, self.kind, fn_name.as_ref(), offset, None) } /// Detaches the program. diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index ea0d59b5..f8b53bae 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -101,7 +101,13 @@ pub(crate) struct ProbeEvent { pub(crate) fn attach>( program_data: &mut ProgramData, kind: ProbeKind, - fn_name: &Path, + // NB: the meaning of this argument is different for kprobe/kretprobe and uprobe/uretprobe; in + // the kprobe case it is the name of the function to attach to, in the uprobe case it is a path + // to the binary or library. + // + // TODO: consider encoding the type and the argument in the [`ProbeKind`] enum instead of a + // separate argument. + fn_name: &OsStr, offset: u64, pid: Option, ) -> Result { @@ -140,7 +146,7 @@ pub(crate) fn detach_debug_fs(event: ProbeEvent) -> Result<(), ProgramError> { fn create_as_probe( kind: ProbeKind, - fn_name: &Path, + fn_name: &OsStr, offset: u64, pid: Option, ) -> Result { @@ -176,7 +182,7 @@ fn create_as_probe( fn create_as_trace_point( kind: ProbeKind, - name: &Path, + name: &OsStr, offset: u64, pid: Option, ) -> Result<(OwnedFd, OsString), ProgramError> { @@ -204,7 +210,7 @@ fn create_as_trace_point( fn create_probe_event( tracefs: &Path, kind: ProbeKind, - fn_name: &Path, + fn_name: &OsStr, offset: u64, ) -> Result { use std::os::unix::ffi::OsStrExt as _; @@ -216,8 +222,6 @@ fn create_probe_event( KRetProbe | URetProbe => 'r', }; - let fn_name = fn_name.as_os_str(); - let mut event_alias = OsString::new(); write!( &mut event_alias, diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 00d306ad..d95f6b2c 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -94,7 +94,8 @@ impl UProbe { 0 }; - attach(&mut self.data, self.kind, &path, sym_offset + offset, pid) + let fn_name = path.as_os_str(); + attach(&mut self.data, self.kind, fn_name, sym_offset + offset, pid) } /// Detaches the program. diff --git a/aya/src/sys/perf_event.rs b/aya/src/sys/perf_event.rs index 000fecbc..1659778a 100644 --- a/aya/src/sys/perf_event.rs +++ b/aya/src/sys/perf_event.rs @@ -1,8 +1,7 @@ use std::{ - ffi::{c_long, CString}, + ffi::{c_long, CString, OsStr}, io, mem, os::fd::{BorrowedFd, FromRawFd as _, OwnedFd}, - path::Path, }; use libc::{c_int, pid_t}; @@ -63,7 +62,7 @@ pub(crate) fn perf_event_open_bpf(cpu: c_int) -> SysResult { pub(crate) fn perf_event_open_probe( ty: u32, ret_bit: Option, - name: &Path, + name: &OsStr, offset: u64, pid: Option, ) -> SysResult { @@ -75,7 +74,7 @@ pub(crate) fn perf_event_open_probe( attr.config = 1 << ret_bit; } - let c_name = CString::new(name.as_os_str().as_bytes()).unwrap(); + let c_name = CString::new(name.as_bytes()).unwrap(); attr.size = mem::size_of::() as u32; attr.type_ = ty; diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 1ef6c0c8..4c06ccf6 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -2896,7 +2896,7 @@ impl core::convert::From for aya::programs::kprobe::KProbeError pub fn aya::programs::kprobe::KProbeError::from(t: T) -> T pub struct aya::programs::kprobe::KProbe impl aya::programs::kprobe::KProbe -pub fn aya::programs::kprobe::KProbe::attach(&mut self, fn_name: &str, offset: u64) -> core::result::Result +pub fn aya::programs::kprobe::KProbe::attach>(&mut self, fn_name: T, offset: u64) -> core::result::Result pub fn aya::programs::kprobe::KProbe::detach(&mut self, link_id: aya::programs::kprobe::KProbeLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::kprobe::KProbe::from_pin>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result pub fn aya::programs::kprobe::KProbe::kind(&self) -> aya::programs::ProbeKind @@ -5997,7 +5997,7 @@ impl core::convert::From for aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::from(t: T) -> T pub struct aya::programs::KProbe impl aya::programs::kprobe::KProbe -pub fn aya::programs::kprobe::KProbe::attach(&mut self, fn_name: &str, offset: u64) -> core::result::Result +pub fn aya::programs::kprobe::KProbe::attach>(&mut self, fn_name: T, offset: u64) -> core::result::Result pub fn aya::programs::kprobe::KProbe::detach(&mut self, link_id: aya::programs::kprobe::KProbeLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::kprobe::KProbe::from_pin>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result pub fn aya::programs::kprobe::KProbe::kind(&self) -> aya::programs::ProbeKind From c0bc1866d82c23e2bcbf3c6b05708e324ebadd98 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 25 Aug 2023 10:53:16 -0400 Subject: [PATCH 08/95] github: update 6.4.0 URLs Seems the previous spin was pulled. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6deec21..5df61008 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -222,7 +222,7 @@ jobs: # linux-image-5.10.0-23-cloud-arm64-unsigned_5.10.179-3_arm64.deb \ printf '%s\0' \ linux-image-6.1.0-10-cloud-arm64-unsigned_6.1.38-2_arm64.deb \ - linux-image-6.4.0-2-cloud-arm64-unsigned_6.4.4-3_arm64.deb \ + linux-image-6.4.0-3-cloud-arm64-unsigned_6.4.11-1_arm64.deb \ | xargs -0 -t -P0 -I {} wget -nd -nv -P test/.tmp/debian-kernels/arm64 ftp://ftp.us.debian.org/debian/pool/main/l/linux/{} - name: Download debian kernels @@ -235,7 +235,7 @@ jobs: # linux-image-5.10.0-23-cloud-amd64-unsigned_5.10.179-3_amd64.deb \ printf '%s\0' \ linux-image-6.1.0-10-cloud-amd64-unsigned_6.1.38-2_amd64.deb \ - linux-image-6.4.0-2-cloud-amd64-unsigned_6.4.4-3_amd64.deb \ + linux-image-6.4.0-3-cloud-amd64-unsigned_6.4.11-1_amd64.deb \ | xargs -0 -t -P0 -I {} wget -nd -nv -P test/.tmp/debian-kernels/amd64 ftp://ftp.us.debian.org/debian/pool/main/l/linux/{} - name: Extract debian kernels From 782eb85d4af056e45c2ffae6f0074bc8303c4b03 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 25 Aug 2023 11:07:21 -0400 Subject: [PATCH 09/95] xtask: extract `Errors` type This produces better errors in `cargo xtask public-api` because before this change we'd print errors as display, which didn't show context. Before: ``` Error: public API errors: aya failed to check public API: public_api::Builder::build aya-obj failed to check public API: public_api::Builder::build aya-log failed to check public API: public_api::Builder::build aya-log-common failed to check public API: public_api::Builder::build aya-log-parser failed to check public API: public_api::Builder::build aya-tool failed to check public API: public_api::Builder::build aya-bpf failed to check public API: public_api::Builder::build aya-bpf-bindings failed to check public API: public_api::Builder::build aya-bpf-cty failed to check public API: public_api::Builder::build aya-bpf-macros failed to check public API: public_api::Builder::build aya-log-ebpf-macros failed to check public API: public_api::Builder::build ``` After: ``` Error: aya failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 3082463 aya-obj failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `union`, `struct`, `struct_field`, `enum`, `variant`, `function`, `trait`, `trait_alias`, `impl`, `typedef`, `opaque_ty`, `constant`, `static`, `foreign_type`, `macro`, `proc_macro`, `primitive`, `assoc_const`, `assoc_type` at line 1 column 129355 aya-log failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 311910 aya-log-common failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `union`, `struct`, `struct_field`, `enum`, `variant`, `function`, `trait`, `trait_alias`, `impl`, `typedef`, `opaque_ty`, `constant`, `static`, `foreign_type`, `macro`, `proc_macro`, `primitive`, `assoc_const`, `assoc_type` at line 1 column 130456 aya-log-parser failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 204930 aya-tool failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 234519 aya-bpf failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 741697 aya-bpf-bindings failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `union`, `struct`, `struct_field`, `enum`, `variant`, `function`, `trait`, `trait_alias`, `impl`, `typedef`, `opaque_ty`, `constant`, `static`, `foreign_type`, `macro`, `proc_macro`, `primitive`, `assoc_const`, `assoc_type` at line 1 column 112445 aya-bpf-cty failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `union`, `struct`, `struct_field`, `enum`, `variant`, `function`, `trait`, `trait_alias`, `impl`, `typedef`, `opaque_ty`, `constant`, `static`, `foreign_type`, `macro`, `proc_macro`, `primitive`, `assoc_const`, `assoc_type` at line 1 column 315 aya-bpf-macros failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 186226 aya-log-ebpf-macros failed to check public API Caused by: 0: public_api::Builder::build 1: unknown variant `type_alias`, expected one of `module`, `extern_crate`, `import`, `struct`, `struct_field`, `union`, `enum`, `variant`, `function`, `typedef`, `opaque_ty`, `constant`, `trait`, `trait_alias`, `impl`, `static`, `foreign_type`, `macro`, `proc_attribute`, `proc_derive`, `assoc_const`, `assoc_type`, `primitive`, `keyword` at line 1 column 158055 ``` --- xtask/src/lib.rs | 27 +++++++++++++++++++++++ xtask/src/public_api.rs | 49 ++++++++++++++++++++++------------------- xtask/src/run.rs | 22 ++---------------- 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 18cf1b93..84e8c3bc 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -13,3 +13,30 @@ pub fn exec(cmd: &mut Command) -> Result<()> { } Ok(()) } + +#[derive(Debug)] +pub struct Errors(Vec); + +impl Errors { + pub fn new(errors: Vec) -> Self { + Self(errors) + } +} + +impl std::fmt::Display for Errors +where + E: std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self(errors) = self; + for (i, error) in errors.iter().enumerate() { + if i != 0 { + writeln!(f)?; + } + write!(f, "{:?}", error)?; + } + Ok(()) + } +} + +impl std::error::Error for Errors where E: std::fmt::Debug {} diff --git a/xtask/src/public_api.rs b/xtask/src/public_api.rs index b5b58f07..0ca83f65 100644 --- a/xtask/src/public_api.rs +++ b/xtask/src/public_api.rs @@ -10,6 +10,7 @@ use cargo_metadata::{Metadata, Package}; use clap::Parser; use dialoguer::{theme::ColorfulTheme, Confirm}; use diff::{lines, Result as Diff}; +use xtask::Errors; #[derive(Debug, Parser)] pub struct Options { @@ -37,34 +38,36 @@ pub fn public_api(options: Options, metadata: Metadata) -> Result<()> { workspace_root, packages, .. - } = &metadata; + } = metadata; - let errors = packages - .iter() - .fold(String::new(), |mut buf, Package { name, publish, .. }| { - if !matches!(publish, Some(publish) if publish.is_empty()) { - match check_package_api(name, toolchain, bless, workspace_root.as_std_path()) { - Ok(diff) => { - if !diff.is_empty() { - writeln!( - &mut buf, - "{name} public API changed; re-run with --bless. diff:\n{diff}" - ) - .unwrap(); - } - } - Err(err) => { - writeln!(&mut buf, "{name} failed to check public API: {err}").unwrap(); - } + let errors: Vec<_> = packages + .into_iter() + .map(|Package { name, publish, .. }| { + if matches!(publish, Some(publish) if publish.is_empty()) { + Ok(()) + } else { + let diff = check_package_api(&name, toolchain, bless, workspace_root.as_std_path()) + .with_context(|| format!("{name} failed to check public API"))?; + if diff.is_empty() { + Ok(()) + } else { + Err(anyhow::anyhow!( + "{name} public API changed; re-run with --bless. diff:\n{diff}" + )) } } - buf - }); + }) + .filter_map(|result| match result { + Ok(()) => None, + Err(err) => Some(err), + }) + .collect(); - if !errors.is_empty() { - bail!("public API errors:\n{errors}") + if errors.is_empty() { + Ok(()) + } else { + Err(Errors::new(errors).into()) } - Ok(()) } fn check_package_api( diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 15ee7035..2deca1ad 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -13,7 +13,7 @@ use std::{ use anyhow::{anyhow, bail, Context as _, Result}; use cargo_metadata::{Artifact, CompilerMessage, Message, Target}; use clap::Parser; -use xtask::{exec, AYA_BUILD_INTEGRATION_BPF}; +use xtask::{exec, Errors, AYA_BUILD_INTEGRATION_BPF}; #[derive(Parser)] enum Environment { @@ -104,24 +104,6 @@ where Ok(executables) } -#[derive(Debug)] -struct Errors(Vec); - -impl std::fmt::Display for Errors { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self(errors) = self; - for (i, error) in errors.iter().enumerate() { - if i != 0 { - writeln!(f)?; - } - write!(f, "{:?}", error)?; - } - Ok(()) - } -} - -impl std::error::Error for Errors {} - /// Build and run the project. pub fn run(opts: Options) -> Result<()> { let Options { @@ -547,7 +529,7 @@ pub fn run(opts: Options) -> Result<()> { if errors.is_empty() { Ok(()) } else { - Err(Errors(errors).into()) + Err(Errors::new(errors).into()) } } } From f988e97b5fa34558a1e2ef490a712703fe83a3ac Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 25 Aug 2023 11:21:51 -0400 Subject: [PATCH 10/95] Upgrade public-api This fixes `cargo xtask public-api` by picking up https://github.com/aDotInTheVoid/rustdoc-types/commit/577a774c2433beda6. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1eb34af9..25d26237 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ num_enum = { version = "0.7", default-features = false } object = { version = "0.32", default-features = false } proc-macro-error = { version = "1.0", default-features = false } proc-macro2 = { version = "1", default-features = false } -public-api = { version = "0.31.2", default-features = false } +public-api = { version = "0.32.0", default-features = false } quote = { version = "1", default-features = false } rbpf = { version = "0.2.0", default-features = false } rustdoc-json = { version = "0.8.6", default-features = false } From 7803db22a062be3cdce760cd6ff7e54b121117ed Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 25 Aug 2023 13:51:30 -0400 Subject: [PATCH 11/95] github: remove symlinks to apple-provided python See https://github.com/actions/setup-python/issues/577. --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5df61008..23fda7fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -198,9 +198,10 @@ jobs: run: | set -euxo pipefail brew update - brew install dpkg findutils gnu-tar llvm pkg-config - # Workaround for https://github.com/Homebrew/homebrew-core/pull/139492. - brew reinstall qemu + # https://github.com/actions/setup-python/issues/577 + find /usr/local/bin -type l -exec sh -c 'readlink -f "$1" \ + | grep -q ^/Library/Frameworks/Python.framework/Versions/' _ {} \; -exec rm -v {} \; + brew install dpkg findutils gnu-tar llvm pkg-config qemu echo /usr/local/opt/findutils/libexec/gnubin >> $GITHUB_PATH echo /usr/local/opt/gnu-tar/libexec/gnubin >> $GITHUB_PATH echo /usr/local/opt/llvm/bin >> $GITHUB_PATH From c139627f8f180638b786b5e3cd48b8473d96fe56 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 25 Aug 2023 10:04:57 -0400 Subject: [PATCH 12/95] aya-obj: reduce indirection in section parsing Remove repetition of permitted cgroup attach types. Make optionality of name more explicit rather than pretending both kind and name are equal to section. --- aya-obj/src/obj.rs | 202 +++++++++++------------ aya-obj/src/programs/cgroup_sock.rs | 21 --- aya-obj/src/programs/cgroup_sock_addr.rs | 29 ---- aya-obj/src/programs/cgroup_sockopt.rs | 19 --- 4 files changed, 92 insertions(+), 179 deletions(-) diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 73d87e68..deadeeaf 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -266,10 +266,15 @@ impl FromStr for ProgramSection { // parse the common case, eg "xdp/program_name" or // "sk_skb/stream_verdict/program_name" - let (kind, name) = match section.rsplit_once('/') { - None => (section, section), - Some((kind, name)) => (kind, name), + let mut pieces = section.split('/'); + let mut next = || { + pieces + .next() + .ok_or_else(|| ParseError::InvalidProgramSection { + section: section.to_owned(), + }) }; + let kind = next()?; Ok(match kind { "kprobe" => KProbe, @@ -281,128 +286,105 @@ impl FromStr for ProgramSection { "xdp" => Xdp { frags: false }, "xdp.frags" => Xdp { frags: true }, "tp_btf" => BtfTracePoint, - kind if kind.starts_with("tracepoint") || kind.starts_with("tp") => TracePoint, + "tracepoint" | "tp" => TracePoint, "socket" => SocketFilter, "sk_msg" => SkMsg, - "sk_skb" => match name { - "stream_parser" => SkSkbStreamParser, - "stream_verdict" => SkSkbStreamVerdict, - _ => { - return Err(ParseError::InvalidProgramSection { - section: section.to_owned(), - }) - } - }, - "sk_skb/stream_parser" => SkSkbStreamParser, - "sk_skb/stream_verdict" => SkSkbStreamVerdict, - "sockops" => SockOps, - "classifier" => SchedClassifier, - "cgroup_skb" => match name { - "ingress" => CgroupSkbIngress, - "egress" => CgroupSkbEgress, - _ => { - return Err(ParseError::InvalidProgramSection { - section: section.to_owned(), - }) - } - }, - "cgroup_skb/ingress" => CgroupSkbIngress, - "cgroup_skb/egress" => CgroupSkbEgress, - "cgroup/skb" => CgroupSkb, - "cgroup/sock" => CgroupSock { - attach_type: CgroupSockAttachType::default(), - }, - "cgroup/sysctl" => CgroupSysctl, - "cgroup/dev" => CgroupDevice, - "cgroup/getsockopt" => CgroupSockopt { - attach_type: CgroupSockoptAttachType::Get, - }, - "cgroup/setsockopt" => CgroupSockopt { - attach_type: CgroupSockoptAttachType::Set, - }, - "cgroup" => match name { - "skb" => CgroupSkb, - "sysctl" => CgroupSysctl, - "dev" => CgroupDevice, - "getsockopt" | "setsockopt" => { - if let Ok(attach_type) = CgroupSockoptAttachType::try_from(name) { - CgroupSockopt { attach_type } - } else { + "sk_skb" => { + let name = next()?; + match name { + "stream_parser" => SkSkbStreamParser, + "stream_verdict" => SkSkbStreamVerdict, + _ => { return Err(ParseError::InvalidProgramSection { section: section.to_owned(), - }); + }) } } - "sock" => CgroupSock { - attach_type: CgroupSockAttachType::default(), - }, - "post_bind4" | "post_bind6" | "sock_create" | "sock_release" => { - if let Ok(attach_type) = CgroupSockAttachType::try_from(name) { - CgroupSock { attach_type } - } else { + } + "sockops" => SockOps, + "classifier" => SchedClassifier, + "cgroup_skb" => { + let name = next()?; + match name { + "ingress" => CgroupSkbIngress, + "egress" => CgroupSkbEgress, + _ => { return Err(ParseError::InvalidProgramSection { section: section.to_owned(), - }); + }) } } - name => { - if let Ok(attach_type) = CgroupSockAddrAttachType::try_from(name) { - CgroupSockAddr { attach_type } - } else { + } + "cgroup" => { + let name = next()?; + match name { + "skb" => CgroupSkb, + "sysctl" => CgroupSysctl, + "dev" => CgroupDevice, + "getsockopt" => CgroupSockopt { + attach_type: CgroupSockoptAttachType::Get, + }, + "setsockopt" => CgroupSockopt { + attach_type: CgroupSockoptAttachType::Set, + }, + "sock" => CgroupSock { + attach_type: CgroupSockAttachType::default(), + }, + "post_bind4" => CgroupSock { + attach_type: CgroupSockAttachType::PostBind4, + }, + "post_bind6" => CgroupSock { + attach_type: CgroupSockAttachType::PostBind6, + }, + "sock_create" => CgroupSock { + attach_type: CgroupSockAttachType::SockCreate, + }, + "sock_release" => CgroupSock { + attach_type: CgroupSockAttachType::SockRelease, + }, + "bind4" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::Bind4, + }, + "bind6" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::Bind6, + }, + "connect4" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::Connect4, + }, + "connect6" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::Connect6, + }, + "getpeername4" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::GetPeerName4, + }, + "getpeername6" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::GetPeerName6, + }, + "getsockname4" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::GetSockName4, + }, + "getsockname6" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::GetSockName6, + }, + "sendmsg4" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::UDPSendMsg4, + }, + "sendmsg6" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::UDPSendMsg6, + }, + "recvmsg4" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::UDPRecvMsg4, + }, + "recvmsg6" => CgroupSockAddr { + attach_type: CgroupSockAddrAttachType::UDPRecvMsg6, + }, + _ => { return Err(ParseError::InvalidProgramSection { section: section.to_owned(), }); } } - }, - "cgroup/post_bind4" => CgroupSock { - attach_type: CgroupSockAttachType::PostBind4, - }, - "cgroup/post_bind6" => CgroupSock { - attach_type: CgroupSockAttachType::PostBind6, - }, - "cgroup/sock_create" => CgroupSock { - attach_type: CgroupSockAttachType::SockCreate, - }, - "cgroup/sock_release" => CgroupSock { - attach_type: CgroupSockAttachType::SockRelease, - }, - "cgroup/bind4" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::Bind4, - }, - "cgroup/bind6" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::Bind6, - }, - "cgroup/connect4" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::Connect4, - }, - "cgroup/connect6" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::Connect6, - }, - "cgroup/getpeername4" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::GetPeerName4, - }, - "cgroup/getpeername6" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::GetPeerName6, - }, - "cgroup/getsockname4" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::GetSockName4, - }, - "cgroup/getsockname6" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::GetSockName6, - }, - "cgroup/sendmsg4" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::UDPSendMsg4, - }, - "cgroup/sendmsg6" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::UDPSendMsg6, - }, - "cgroup/recvmsg4" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::UDPRecvMsg4, - }, - "cgroup/recvmsg6" => CgroupSockAddr { - attach_type: CgroupSockAddrAttachType::UDPRecvMsg6, - }, + } "lirc_mode2" => LircMode2, "perf_event" => PerfEvent, "raw_tp" | "raw_tracepoint" => RawTracePoint, diff --git a/aya-obj/src/programs/cgroup_sock.rs b/aya-obj/src/programs/cgroup_sock.rs index 227e26d5..545dee2e 100644 --- a/aya-obj/src/programs/cgroup_sock.rs +++ b/aya-obj/src/programs/cgroup_sock.rs @@ -1,11 +1,6 @@ //! Cgroup socket programs. -use alloc::{borrow::ToOwned, string::String}; - use crate::generated::bpf_attach_type; -#[cfg(not(feature = "std"))] -use crate::std; - /// Defines where to attach a `CgroupSock` program. #[derive(Copy, Clone, Debug, Default)] pub enum CgroupSockAttachType { @@ -30,19 +25,3 @@ impl From for bpf_attach_type { } } } - -#[derive(Debug, thiserror::Error)] -#[error("{0} is not a valid attach type for a CGROUP_SOCK program")] -pub(crate) struct InvalidAttachType(String); - -impl CgroupSockAttachType { - pub(crate) fn try_from(value: &str) -> Result { - match value { - "post_bind4" => Ok(CgroupSockAttachType::PostBind4), - "post_bind6" => Ok(CgroupSockAttachType::PostBind6), - "sock_create" => Ok(CgroupSockAttachType::SockCreate), - "sock_release" => Ok(CgroupSockAttachType::SockRelease), - _ => Err(InvalidAttachType(value.to_owned())), - } - } -} diff --git a/aya-obj/src/programs/cgroup_sock_addr.rs b/aya-obj/src/programs/cgroup_sock_addr.rs index 6bd4070e..13d5c1c5 100644 --- a/aya-obj/src/programs/cgroup_sock_addr.rs +++ b/aya-obj/src/programs/cgroup_sock_addr.rs @@ -1,11 +1,6 @@ //! Cgroup socket address programs. -use alloc::{borrow::ToOwned, string::String}; - use crate::generated::bpf_attach_type; -#[cfg(not(feature = "std"))] -use crate::std; - /// Defines where to attach a `CgroupSockAddr` program. #[derive(Copy, Clone, Debug)] pub enum CgroupSockAddrAttachType { @@ -53,27 +48,3 @@ impl From for bpf_attach_type { } } } - -#[derive(Debug, thiserror::Error)] -#[error("{0} is not a valid attach type for a CGROUP_SOCK_ADDR program")] -pub(crate) struct InvalidAttachType(String); - -impl CgroupSockAddrAttachType { - pub(crate) fn try_from(value: &str) -> Result { - match value { - "bind4" => Ok(CgroupSockAddrAttachType::Bind4), - "bind6" => Ok(CgroupSockAddrAttachType::Bind6), - "connect4" => Ok(CgroupSockAddrAttachType::Connect4), - "connect6" => Ok(CgroupSockAddrAttachType::Connect6), - "getpeername4" => Ok(CgroupSockAddrAttachType::GetPeerName4), - "getpeername6" => Ok(CgroupSockAddrAttachType::GetPeerName6), - "getsockname4" => Ok(CgroupSockAddrAttachType::GetSockName4), - "getsockname6" => Ok(CgroupSockAddrAttachType::GetSockName6), - "sendmsg4" => Ok(CgroupSockAddrAttachType::UDPSendMsg4), - "sendmsg6" => Ok(CgroupSockAddrAttachType::UDPSendMsg6), - "recvmsg4" => Ok(CgroupSockAddrAttachType::UDPRecvMsg4), - "recvmsg6" => Ok(CgroupSockAddrAttachType::UDPRecvMsg6), - _ => Err(InvalidAttachType(value.to_owned())), - } - } -} diff --git a/aya-obj/src/programs/cgroup_sockopt.rs b/aya-obj/src/programs/cgroup_sockopt.rs index e3495728..3794c8cc 100644 --- a/aya-obj/src/programs/cgroup_sockopt.rs +++ b/aya-obj/src/programs/cgroup_sockopt.rs @@ -1,11 +1,6 @@ //! Cgroup socket option programs. -use alloc::{borrow::ToOwned, string::String}; - use crate::generated::bpf_attach_type; -#[cfg(not(feature = "std"))] -use crate::std; - /// Defines where to attach a `CgroupSockopt` program. #[derive(Copy, Clone, Debug)] pub enum CgroupSockoptAttachType { @@ -23,17 +18,3 @@ impl From for bpf_attach_type { } } } - -#[derive(Debug, thiserror::Error)] -#[error("{0} is not a valid attach type for a CGROUP_SOCKOPT program")] -pub(crate) struct InvalidAttachType(String); - -impl CgroupSockoptAttachType { - pub(crate) fn try_from(value: &str) -> Result { - match value { - "getsockopt" => Ok(CgroupSockoptAttachType::Get), - "setsockopt" => Ok(CgroupSockoptAttachType::Set), - _ => Err(InvalidAttachType(value.to_owned())), - } - } -} From a38dc057b4fab56a64999ebd62ab10a02a4833bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:25:29 +0000 Subject: [PATCH 13/95] build(deps): update nix requirement from 0.26.2 to 0.27.0 Updates the requirements on [nix](https://github.com/nix-rust/nix) to permit the latest version. - [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md) - [Commits](https://github.com/nix-rust/nix/compare/v0.26.2...v0.26.3) --- updated-dependencies: - dependency-name: nix dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 25d26237..8ad69dfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ lazy_static = { version = "1", default-features = false } libc = { version = "0.2.105", default-features = false } log = { version = "0.4", default-features = false } netns-rs = { version = "0.1", default-features = false } -nix = { version = "0.26.2", default-features = false } +nix = { version = "0.27.0", default-features = false } num_enum = { version = "0.7", default-features = false } object = { version = "0.32", default-features = false } proc-macro-error = { version = "1.0", default-features = false } From d2e74e562dfa601397b3570ece1a51f5013b9928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Medina?= Date: Wed, 16 Aug 2023 18:07:23 -0700 Subject: [PATCH 14/95] aya: Use BorrowedFd when using the program fd in sys/bpf.rs This commit reveals but does not address a file descriptor leak in LircLink2::query. This function returns a list of `LircLink`s where each of them have a program file descriptor that is not going to be closed. This commit does not add this leak; it merely makes it louder in the code. --- aya/src/programs/cgroup_device.rs | 1 - aya/src/programs/cgroup_skb.rs | 1 - aya/src/programs/cgroup_sock.rs | 1 - aya/src/programs/cgroup_sock_addr.rs | 1 - aya/src/programs/cgroup_sockopt.rs | 1 - aya/src/programs/cgroup_sysctl.rs | 1 - aya/src/programs/extension.rs | 2 -- aya/src/programs/links.rs | 9 +++++++-- aya/src/programs/lirc_mode2.rs | 17 ++++++++++++++--- aya/src/programs/perf_attach.rs | 19 +++++++++++-------- aya/src/programs/perf_event.rs | 3 +-- aya/src/programs/probe.rs | 3 +-- aya/src/programs/sk_lookup.rs | 1 - aya/src/programs/sk_msg.rs | 1 - aya/src/programs/sk_skb.rs | 1 - aya/src/programs/sock_ops.rs | 1 - aya/src/programs/tc.rs | 3 +-- aya/src/programs/trace_point.rs | 7 +------ aya/src/programs/utils.rs | 1 - aya/src/programs/xdp.rs | 17 +++++++++++------ aya/src/sys/bpf.rs | 20 +++++++++++--------- aya/src/sys/netlink.rs | 17 +++++++++++++---- 22 files changed, 71 insertions(+), 57 deletions(-) diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index 42ce1e17..08757ff3 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -63,7 +63,6 @@ impl CgroupDevice { pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 4b815c15..55a6f85e 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -94,7 +94,6 @@ impl CgroupSkb { ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); let attach_type = match attach_type { diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index 57dfeaf0..217386d6 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -73,7 +73,6 @@ impl CgroupSock { pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index 2c2b4ac9..b1b162ee 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -74,7 +74,6 @@ impl CgroupSockAddr { pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index cbe8302e..1016d49f 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -71,7 +71,6 @@ impl CgroupSockopt { pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index a1b158d7..8582906a 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -65,7 +65,6 @@ impl CgroupSysctl { pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index e1aab2c2..bca94cde 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -88,7 +88,6 @@ impl Extension { pub fn attach(&mut self) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let target_fd = self .data .attach_prog_fd @@ -128,7 +127,6 @@ impl Extension { let (_, btf_id) = get_btf_info(target_fd, func_name)?; let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); // the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS let link_fd = bpf_link_create( prog_fd, diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 71b0aba1..3ebca47c 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -6,7 +6,7 @@ use std::{ collections::{hash_map::Entry, HashMap}, ffi::CString, io, - os::fd::{AsRawFd as _, OwnedFd, RawFd}, + os::fd::{AsRawFd as _, BorrowedFd, OwnedFd, RawFd}, path::{Path, PathBuf}, }; @@ -239,7 +239,12 @@ pub struct ProgAttachLink { } impl ProgAttachLink { - pub(crate) fn new(prog_fd: RawFd, target_fd: RawFd, attach_type: bpf_attach_type) -> Self { + pub(crate) fn new( + prog_fd: BorrowedFd<'_>, + target_fd: RawFd, + attach_type: bpf_attach_type, + ) -> Self { + let prog_fd = prog_fd.as_raw_fd(); Self { prog_fd, target_fd: unsafe { dup(target_fd) }, diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 0d34bfce..c1054eb0 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -63,7 +63,6 @@ impl LircMode2 { pub fn attach(&mut self, lircdev: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let lircdev_fd = lircdev.as_raw_fd(); bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| { @@ -104,7 +103,18 @@ impl LircMode2 { Ok(prog_fds .into_iter() - .map(|prog_fd| LircLink::new(prog_fd.into_raw_fd(), target_fd.as_raw_fd())) + .map(|prog_fd| { + LircLink::new( + // SAFETY: The file descriptor will stay valid because + // we are leaking it. We cannot use `OwnedFd` in here + // because LircMode2::attach also uses LircLink::new + // but with a borrowed file descriptor (of the loaded + // program) without duplicating. TODO(#612): Fix API + // or internals so this file descriptor isn't leaked + unsafe { BorrowedFd::borrow_raw(prog_fd.into_raw_fd()) }, + target_fd.as_raw_fd(), + ) + }) .collect()) } } @@ -121,7 +131,8 @@ pub struct LircLink { } impl LircLink { - pub(crate) fn new(prog_fd: RawFd, target_fd: RawFd) -> Self { + pub(crate) fn new(prog_fd: BorrowedFd<'_>, target_fd: RawFd) -> Self { + let prog_fd = prog_fd.as_raw_fd(); Self { prog_fd, target_fd: unsafe { dup(target_fd) }, diff --git a/aya/src/programs/perf_attach.rs b/aya/src/programs/perf_attach.rs index dd2f8831..c48bf97e 100644 --- a/aya/src/programs/perf_attach.rs +++ b/aya/src/programs/perf_attach.rs @@ -1,5 +1,5 @@ //! Perf attach links. -use std::os::fd::{AsFd as _, AsRawFd as _, OwnedFd, RawFd}; +use std::os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, OwnedFd, RawFd}; use crate::{ generated::bpf_attach_type::BPF_PERF_EVENT, @@ -70,7 +70,10 @@ impl Link for PerfLink { } } -pub(crate) fn perf_attach(prog_fd: RawFd, fd: OwnedFd) -> Result { +pub(crate) fn perf_attach( + prog_fd: BorrowedFd<'_>, + fd: OwnedFd, +) -> Result { if FEATURES.bpf_perf_link() { let link_fd = bpf_link_create(prog_fd, fd.as_raw_fd(), BPF_PERF_EVENT, None, 0).map_err( |(_, io_error)| SyscallError { @@ -85,7 +88,7 @@ pub(crate) fn perf_attach(prog_fd: RawFd, fd: OwnedFd) -> Result, fd: OwnedFd, event: ProbeEvent, ) -> Result { @@ -93,16 +96,16 @@ pub(crate) fn perf_attach_debugfs( } fn perf_attach_either( - prog_fd: RawFd, + prog_fd: BorrowedFd<'_>, fd: OwnedFd, event: Option, ) -> Result { - perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_SET_BPF, prog_fd).map_err(|(_, io_error)| { - SyscallError { + perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_SET_BPF, prog_fd.as_raw_fd()).map_err( + |(_, io_error)| SyscallError { call: "PERF_EVENT_IOC_SET_BPF", io_error, - } - })?; + }, + )?; perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_ENABLE, 0).map_err(|(_, io_error)| { SyscallError { call: "PERF_EVENT_IOC_ENABLE", diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 36398967..150bda24 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -1,6 +1,6 @@ //! Perf event programs. -use std::os::fd::{AsFd as _, AsRawFd as _}; +use std::os::fd::AsFd as _; pub use crate::generated::{ perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids, @@ -148,7 +148,6 @@ impl PerfEvent { ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let (sample_period, sample_frequency) = match sample_policy { SamplePolicy::Period(period) => (period, None), SamplePolicy::Frequency(frequency) => (0, Some(frequency)), diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index f8b53bae..6d9082ca 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -5,7 +5,7 @@ use std::{ fmt::Write as _, fs::{self, OpenOptions}, io::{self, Write}, - os::fd::{AsFd as _, AsRawFd as _, OwnedFd}, + os::fd::{AsFd as _, OwnedFd}, path::{Path, PathBuf}, process, sync::atomic::{AtomicUsize, Ordering}, @@ -115,7 +115,6 @@ pub(crate) fn attach>( // Use debugfs to create probe let prog_fd = program_data.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let link = if KernelVersion::current().unwrap() < KernelVersion::new(4, 17, 0) { let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?; perf_attach_debugfs(prog_fd, fd, ProbeEvent { kind, event_alias }) diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index bbcdc3a3..ab322daa 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -63,7 +63,6 @@ impl SkLookup { pub fn attach(&mut self, netns: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let netns_fd = netns.as_raw_fd(); let link_fd = bpf_link_create(prog_fd, netns_fd, BPF_SK_LOOKUP, None, 0).map_err( diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index 7a03b8e3..e7776d5d 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -81,7 +81,6 @@ impl SkMsg { pub fn attach(&mut self, map: SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let map_fd = map.as_raw_fd(); bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT).map_err(|(_, io_error)| { diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index a4c5de63..79ac0c23 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -77,7 +77,6 @@ impl SkSkb { pub fn attach(&mut self, map: SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let map_fd = map.as_raw_fd(); let attach_type = match self.kind { diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index 2a469048..a44d7058 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -61,7 +61,6 @@ impl SockOps { pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let cgroup_fd = cgroup.as_raw_fd(); bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| { diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index 8cb73cea..bdf15ed2 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -4,7 +4,7 @@ use thiserror::Error; use std::{ ffi::{CStr, CString}, io, - os::fd::{AsFd as _, AsRawFd as _}, + os::fd::AsFd as _, path::Path, }; @@ -154,7 +154,6 @@ impl SchedClassifier { ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let if_index = ifindex_from_ifname(interface) .map_err(|io_error| TcError::NetlinkError { io_error })?; let name = self.data.name.as_deref().unwrap_or_default(); diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index b9a4c5b1..adb50621 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -1,9 +1,5 @@ //! Tracepoint programs. -use std::{ - fs, io, - os::fd::{AsFd as _, AsRawFd as _}, - path::Path, -}; +use std::{fs, io, os::fd::AsFd as _, path::Path}; use thiserror::Error; use crate::{ @@ -84,7 +80,6 @@ impl TracePoint { pub fn attach(&mut self, category: &str, name: &str) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let tracefs = find_tracefs_path()?; let id = read_sys_fs_trace_point_id(tracefs, category, name.as_ref())?; let fd = diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index c4e2e618..0f8f61ae 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -20,7 +20,6 @@ pub(crate) fn attach_raw_tracepoint>( ) -> Result { let prog_fd = program_data.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let pfd = bpf_raw_tracepoint_open(tp_name, prog_fd).map_err(|(_code, io_error)| SyscallError { call: "bpf_raw_tracepoint_open", diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 22eb4f70..39ca3cf9 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -128,7 +128,6 @@ impl Xdp { ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); let if_index = if_index as RawFd; if KernelVersion::current().unwrap() >= KernelVersion::new(5, 9, 0) { @@ -147,9 +146,10 @@ impl Xdp { .links .insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd)))) } else { - unsafe { netlink_set_xdp_fd(if_index, prog_fd, None, flags.bits()) } + unsafe { netlink_set_xdp_fd(if_index, Some(prog_fd), None, flags.bits()) } .map_err(|io_error| XdpError::NetlinkError { io_error })?; + let prog_fd = prog_fd.as_raw_fd(); self.data .links .insert(XdpLink::new(XdpLinkInner::NlLink(NlLink { @@ -181,7 +181,6 @@ impl Xdp { pub fn attach_to_link(&mut self, link: XdpLink) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let prog_fd = prog_fd.as_raw_fd(); match link.into_inner() { XdpLinkInner::FdLink(fd_link) => { let link_fd = fd_link.fd; @@ -202,10 +201,16 @@ impl Xdp { let flags = nl_link.flags; let replace_flags = flags | XdpFlags::REPLACE; unsafe { - netlink_set_xdp_fd(if_index, prog_fd, Some(old_prog_fd), replace_flags.bits()) - .map_err(|io_error| XdpError::NetlinkError { io_error })?; + netlink_set_xdp_fd( + if_index, + Some(prog_fd), + Some(old_prog_fd), + replace_flags.bits(), + ) + .map_err(|io_error| XdpError::NetlinkError { io_error })?; } + let prog_fd = prog_fd.as_raw_fd(); self.data .links .insert(XdpLink::new(XdpLinkInner::NlLink(NlLink { @@ -238,7 +243,7 @@ impl Link for NlLink { } else { self.flags.bits() }; - let _ = unsafe { netlink_set_xdp_fd(self.if_index, -1, Some(self.prog_fd), flags) }; + let _ = unsafe { netlink_set_xdp_fd(self.if_index, None, Some(self.prog_fd), flags) }; Ok(()) } } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index e142c6c4..8656c04b 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -367,7 +367,7 @@ pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult { // since kernel 5.7 pub(crate) fn bpf_link_create( - prog_fd: RawFd, + prog_fd: BorrowedFd<'_>, target_fd: RawFd, attach_type: bpf_attach_type, btf_id: Option, @@ -375,7 +375,7 @@ pub(crate) fn bpf_link_create( ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; - attr.link_create.__bindgen_anon_1.prog_fd = prog_fd as u32; + attr.link_create.__bindgen_anon_1.prog_fd = prog_fd.as_raw_fd() as u32; attr.link_create.__bindgen_anon_2.target_fd = target_fd as u32; attr.link_create.attach_type = attach_type as u32; attr.link_create.flags = flags; @@ -390,14 +390,14 @@ pub(crate) fn bpf_link_create( // since kernel 5.7 pub(crate) fn bpf_link_update( link_fd: BorrowedFd<'_>, - new_prog_fd: RawFd, + new_prog_fd: BorrowedFd<'_>, old_prog_fd: Option, flags: u32, ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; attr.link_update.link_fd = link_fd.as_raw_fd() as u32; - attr.link_update.__bindgen_anon_1.new_prog_fd = new_prog_fd as u32; + attr.link_update.__bindgen_anon_1.new_prog_fd = new_prog_fd.as_raw_fd() as u32; if let Some(fd) = old_prog_fd { attr.link_update.__bindgen_anon_2.old_prog_fd = fd as u32; attr.link_update.flags = flags | BPF_F_REPLACE; @@ -409,13 +409,13 @@ pub(crate) fn bpf_link_update( } pub(crate) fn bpf_prog_attach( - prog_fd: RawFd, + prog_fd: BorrowedFd<'_>, target_fd: RawFd, attach_type: bpf_attach_type, ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; - attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32; + attr.__bindgen_anon_5.attach_bpf_fd = prog_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.target_fd = target_fd as u32; attr.__bindgen_anon_5.attach_type = attach_type as u32; @@ -547,14 +547,17 @@ pub(crate) fn btf_obj_get_info_by_fd( }) } -pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> SysResult { +pub(crate) fn bpf_raw_tracepoint_open( + name: Option<&CStr>, + prog_fd: BorrowedFd<'_>, +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; attr.raw_tracepoint.name = match name { Some(n) => n.as_ptr() as u64, None => 0, }; - attr.raw_tracepoint.prog_fd = prog_fd as u32; + attr.raw_tracepoint.prog_fd = prog_fd.as_raw_fd() as u32; // SAFETY: BPF_RAW_TRACEPOINT_OPEN returns a new file descriptor. unsafe { fd_sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &mut attr) } @@ -678,7 +681,6 @@ pub(crate) fn is_perf_link_supported() -> bool { if let Ok(fd) = bpf_prog_load(&mut attr) { let fd = fd.as_fd(); - let fd = fd.as_raw_fd(); matches!( // Uses an invalid target FD so we get EBADF if supported. bpf_link_create(fd, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0), diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index a7b24902..3643e95b 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -1,4 +1,10 @@ -use std::{collections::HashMap, ffi::CStr, io, mem, os::fd::RawFd, ptr, slice}; +use std::{ + collections::HashMap, + ffi::CStr, + io, mem, + os::fd::{AsRawFd as _, BorrowedFd, RawFd}, + ptr, slice, +}; use thiserror::Error; use libc::{ @@ -25,7 +31,7 @@ const NLA_HDR_LEN: usize = align_to(mem::size_of::(), NLA_ALIGNTO as usi // netlink alignments pub(crate) unsafe fn netlink_set_xdp_fd( if_index: i32, - fd: RawFd, + fd: Option>, old_fd: Option, flags: u32, ) -> Result<(), io::Error> { @@ -48,7 +54,10 @@ pub(crate) unsafe fn netlink_set_xdp_fd( // write the attrs let attrs_buf = request_attributes(&mut req, nlmsg_len); let mut attrs = NestedAttrs::new(attrs_buf, IFLA_XDP); - attrs.write_attr(IFLA_XDP_FD as u16, fd)?; + attrs.write_attr( + IFLA_XDP_FD as u16, + fd.map(|fd| fd.as_raw_fd()).unwrap_or(-1), + )?; if flags > 0 { attrs.write_attr(IFLA_XDP_FLAGS as u16, flags)?; @@ -101,7 +110,7 @@ pub(crate) unsafe fn netlink_qdisc_add_clsact(if_index: i32) -> Result<(), io::E pub(crate) unsafe fn netlink_qdisc_attach( if_index: i32, attach_type: &TcAttachType, - prog_fd: RawFd, + prog_fd: BorrowedFd<'_>, prog_name: &CStr, priority: u16, handle: u32, From 6895b1e2ede8d571e7f7069a109932e917fd3ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Medina?= Date: Wed, 16 Aug 2023 18:09:55 -0700 Subject: [PATCH 15/95] aya: Use AsFd when attaching fds to programs This is a breaking change but adds another level of safety to ensure the file descriptor we receive is valid. Additionally, this allows aya to internally easily duplicate this file descriptor using std library methods instead of manually calling `dup` which doesn't duplicate with the CLOSE_ON_EXEC flag that is standard pratice to avoid leaking the file descriptor when exec'ing. --- aya/src/maps/sock/mod.rs | 11 +++-- aya/src/programs/cgroup_device.rs | 37 +++++++-------- aya/src/programs/cgroup_skb.rs | 32 ++++--------- aya/src/programs/cgroup_sock.rs | 32 ++++--------- aya/src/programs/cgroup_sock_addr.rs | 34 ++++---------- aya/src/programs/cgroup_sockopt.rs | 30 ++++-------- aya/src/programs/cgroup_sysctl.rs | 39 ++++++++-------- aya/src/programs/extension.rs | 26 +++++++---- aya/src/programs/links.rs | 39 ++++++++++------ aya/src/programs/lirc_mode2.rs | 69 +++++++++++++--------------- aya/src/programs/mod.rs | 6 +-- aya/src/programs/perf_attach.rs | 9 ++-- aya/src/programs/sk_lookup.rs | 15 +++--- aya/src/programs/sk_msg.rs | 17 ++----- aya/src/programs/sk_skb.rs | 20 ++------ aya/src/programs/sock_ops.rs | 20 ++------ aya/src/programs/socket_filter.rs | 8 ++-- aya/src/programs/xdp.rs | 9 ++-- aya/src/sys/bpf.rs | 27 ++++++++--- xtask/public-api/aya.txt | 42 ++++++++--------- 20 files changed, 234 insertions(+), 288 deletions(-) diff --git a/aya/src/maps/sock/mod.rs b/aya/src/maps/sock/mod.rs index 1b9f00e9..05fe112c 100644 --- a/aya/src/maps/sock/mod.rs +++ b/aya/src/maps/sock/mod.rs @@ -5,14 +5,17 @@ mod sock_map; pub use sock_hash::SockHash; pub use sock_map::SockMap; -use std::os::fd::{AsRawFd, RawFd}; +use std::os::fd::{AsFd, BorrowedFd, RawFd}; /// A socket map file descriptor. #[derive(Copy, Clone)] pub struct SockMapFd(RawFd); -impl AsRawFd for SockMapFd { - fn as_raw_fd(&self) -> RawFd { - self.0 +impl AsFd for SockMapFd { + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: This isn't necessarily safe, we need to find ways + // to enforce that the file descriptor is still + // valid. TODO(#612) + unsafe { BorrowedFd::borrow_raw(self.0) } } } diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index 08757ff3..180d3757 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -1,14 +1,14 @@ //! Cgroup device programs. -use crate::util::KernelVersion; -use std::os::fd::{AsFd as _, AsRawFd}; +use std::os::fd::AsFd; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE}, programs::{ define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_prog_attach, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, }; /// A program used to watch or prevent device interaction from a cgroup. @@ -60,34 +60,35 @@ impl CgroupDevice { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupDevice::detach] - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); + let cgroup_fd = cgroup.as_fd(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, None, 0).map_err( - |(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - }, - )?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + BPF_CGROUP_DEVICE, + None, + 0, + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE)?; + self.data .links .insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE), + link, ))) } } diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 55a6f85e..1f99835c 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -1,11 +1,6 @@ //! Cgroup skb programs. -use crate::util::KernelVersion; -use std::{ - hash::Hash, - os::fd::{AsFd as _, AsRawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsFd, path::Path}; use crate::{ generated::{ @@ -15,7 +10,8 @@ use crate::{ programs::{ define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_prog_attach, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, VerifierLogLevel, }; @@ -87,44 +83,36 @@ impl CgroupSkb { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSkb::detach]. - pub fn attach( + pub fn attach( &mut self, cgroup: T, attach_type: CgroupSkbAttachType, ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); + let cgroup_fd = cgroup.as_fd(); let attach_type = match attach_type { CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS, CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS, }; if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| SyscallError { + let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) + .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", io_error, - }, - )?; + })?; self.data .links .insert(CgroupSkbLink::new(CgroupSkbLinkInner::Fd(FdLink::new( link_fd, )))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; self.data .links - .insert(CgroupSkbLink::new(CgroupSkbLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), - ))) + .insert(CgroupSkbLink::new(CgroupSkbLinkInner::ProgAttach(link))) } } diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index 217386d6..1ea6284c 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -2,19 +2,15 @@ pub use aya_obj::programs::CgroupSockAttachType; -use crate::util::KernelVersion; -use std::{ - hash::Hash, - os::fd::{AsFd as _, AsRawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsFd, path::Path}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK, programs::{ define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_prog_attach, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, VerifierLogLevel, }; @@ -70,36 +66,28 @@ impl CgroupSock { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSock::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); + let cgroup_fd = cgroup.as_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| SyscallError { + let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) + .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", io_error, - }, - )?; + })?; self.data .links .insert(CgroupSockLink::new(CgroupSockLinkInner::Fd(FdLink::new( link_fd, )))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; self.data .links - .insert(CgroupSockLink::new(CgroupSockLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), - ))) + .insert(CgroupSockLink::new(CgroupSockLinkInner::ProgAttach(link))) } } diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index b1b162ee..cab1b7c5 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -2,19 +2,15 @@ pub use aya_obj::programs::CgroupSockAddrAttachType; -use crate::util::KernelVersion; -use std::{ - hash::Hash, - os::fd::{AsFd as _, AsRawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsFd, path::Path}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR, programs::{ define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_prog_attach, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, VerifierLogLevel, }; @@ -71,37 +67,27 @@ impl CgroupSockAddr { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSockAddr::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); + let cgroup_fd = cgroup.as_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| SyscallError { + let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) + .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", io_error, - }, - )?; + })?; self.data .links .insert(CgroupSockAddrLink::new(CgroupSockAddrLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; self.data.links.insert(CgroupSockAddrLink::new( - CgroupSockAddrLinkInner::ProgAttach(ProgAttachLink::new( - prog_fd, - cgroup_fd, - attach_type, - )), + CgroupSockAddrLinkInner::ProgAttach(link), )) } } diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index 1016d49f..72ec868f 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -2,19 +2,15 @@ pub use aya_obj::programs::CgroupSockoptAttachType; -use crate::util::KernelVersion; -use std::{ - hash::Hash, - os::fd::{AsFd as _, AsRawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsFd, path::Path}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT, programs::{ define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_prog_attach, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, VerifierLogLevel, }; @@ -68,35 +64,29 @@ impl CgroupSockopt { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSockopt::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); + let cgroup_fd = cgroup.as_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| SyscallError { + let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) + .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", io_error, - }, - )?; + })?; self.data .links .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; self.data .links .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), + link, ))) } } diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index 8582906a..80c1e028 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -1,17 +1,14 @@ //! Cgroup sysctl programs. -use crate::util::KernelVersion; -use std::{ - hash::Hash, - os::fd::{AsFd as _, AsRawFd}, -}; +use std::{hash::Hash, os::fd::AsFd}; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL}, programs::{ define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_prog_attach, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, }; /// A program used to watch for sysctl changes. @@ -62,35 +59,35 @@ impl CgroupSysctl { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSysctl::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); + let cgroup_fd = cgroup.as_fd(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL, None, 0).map_err( - |(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - }, - )?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + BPF_CGROUP_SYSCTL, + None, + 0, + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL)?; self.data .links .insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL), + link, ))) } } diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index bca94cde..3785a57c 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -1,8 +1,9 @@ //! Extension programs. -use std::os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, OwnedFd}; -use thiserror::Error; + +use std::os::fd::{AsFd as _, BorrowedFd, OwnedFd}; use object::Endianness; +use thiserror::Error; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_INET_INGRESS, bpf_prog_type::BPF_PROG_TYPE_EXT}, @@ -10,7 +11,7 @@ use crate::{ programs::{ define_link_wrapper, load_program, FdLink, FdLinkId, ProgramData, ProgramError, ProgramFd, }, - sys::{self, bpf_link_create, SyscallError}, + sys::{self, bpf_link_create, LinkTarget, SyscallError}, Btf, }; @@ -94,14 +95,19 @@ impl Extension { .as_ref() .ok_or(ProgramError::NotLoaded)?; let target_fd = target_fd.as_fd(); - let target_fd = target_fd.as_raw_fd(); let btf_id = self.data.attach_btf_id.ok_or(ProgramError::NotLoaded)?; // the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS - let link_fd = bpf_link_create(prog_fd, target_fd, BPF_CGROUP_INET_INGRESS, Some(btf_id), 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - })?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(target_fd), + BPF_CGROUP_INET_INGRESS, + Some(btf_id), + 0, + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(ExtensionLink::new(FdLink::new(link_fd))) @@ -130,7 +136,7 @@ impl Extension { // the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS let link_fd = bpf_link_create( prog_fd, - target_fd.as_raw_fd(), + LinkTarget::Fd(target_fd), BPF_CGROUP_INET_INGRESS, Some(btf_id), 0, diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 3ebca47c..619ebef6 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -1,12 +1,11 @@ //! Program links. -use libc::{close, dup}; use thiserror::Error; use std::{ collections::{hash_map::Entry, HashMap}, ffi::CString, io, - os::fd::{AsRawFd as _, BorrowedFd, OwnedFd, RawFd}, + os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, OwnedFd, RawFd}, path::{Path, PathBuf}, }; @@ -14,7 +13,9 @@ use crate::{ generated::bpf_attach_type, pin::PinError, programs::ProgramError, - sys::{bpf_get_object, bpf_pin_object, bpf_prog_detach, SyscallError}, + sys::{ + bpf_get_object, bpf_pin_object, bpf_prog_attach, bpf_prog_detach, SysResult, SyscallError, + }, }; /// A Link. @@ -234,22 +235,34 @@ pub struct ProgAttachLinkId(RawFd, RawFd, bpf_attach_type); #[derive(Debug)] pub struct ProgAttachLink { prog_fd: RawFd, - target_fd: RawFd, + target_fd: OwnedFd, attach_type: bpf_attach_type, } impl ProgAttachLink { - pub(crate) fn new( + pub(crate) fn attach( prog_fd: BorrowedFd<'_>, - target_fd: RawFd, + target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, - ) -> Self { + ) -> Result { + // The link is going to own this new file descriptor so we are + // going to need a duplicate whose lifetime we manage. Let's + // duplicate it prior to attaching it so the new file + // descriptor is closed at drop in case it fails to attach. + let target_fd = target_fd.try_clone_to_owned()?; + bpf_prog_attach(prog_fd, target_fd.as_fd(), attach_type).map_err(|(_, io_error)| { + SyscallError { + call: "bpf_prog_attach", + io_error, + } + })?; + let prog_fd = prog_fd.as_raw_fd(); - Self { + Ok(Self { prog_fd, - target_fd: unsafe { dup(target_fd) }, + target_fd, attach_type, - } + }) } } @@ -257,12 +270,12 @@ impl Link for ProgAttachLink { type Id = ProgAttachLinkId; fn id(&self) -> Self::Id { - ProgAttachLinkId(self.prog_fd, self.target_fd, self.attach_type) + ProgAttachLinkId(self.prog_fd, self.target_fd.as_raw_fd(), self.attach_type) } fn detach(self) -> Result<(), ProgramError> { - let _ = bpf_prog_detach(self.prog_fd, self.target_fd, self.attach_type); - unsafe { close(self.target_fd) }; + let _: SysResult<_> = + bpf_prog_detach(self.prog_fd, self.target_fd.as_fd(), self.attach_type); Ok(()) } } diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index c1054eb0..7b0d886f 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -1,14 +1,12 @@ //! Lirc programs. -use std::os::fd::{AsFd as _, AsRawFd, BorrowedFd, IntoRawFd as _, RawFd}; +use std::os::fd::{AsFd, AsRawFd, BorrowedFd, IntoRawFd as _, OwnedFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2}, programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo}, - sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, SyscallError}, + sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, SysResult, SyscallError}, }; -use libc::{close, dup}; - /// A program used to decode IR into key events for a lirc device. /// /// [`LircMode2`] programs can be used to inspect infrared pulses, spaces, @@ -60,12 +58,17 @@ impl LircMode2 { /// Attaches the program to the given lirc device. /// /// The returned value can be used to detach, see [LircMode2::detach]. - pub fn attach(&mut self, lircdev: T) -> Result { + pub fn attach(&mut self, lircdev: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let lircdev_fd = lircdev.as_raw_fd(); - bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| { + // The link is going to own this new file descriptor so we are + // going to need a duplicate whose lifetime we manage. Let's + // duplicate it prior to attaching it so the new file + // descriptor is closed at drop in case it fails to attach. + let lircdev_fd = lircdev.as_fd().try_clone_to_owned()?; + + bpf_prog_attach(prog_fd, lircdev_fd.as_fd(), BPF_LIRC_MODE2).map_err(|(_, io_error)| { SyscallError { call: "bpf_prog_attach", io_error, @@ -91,31 +94,25 @@ impl LircMode2 { } /// Queries the lirc device for attached programs. - pub fn query(target_fd: T) -> Result, ProgramError> { - let prog_ids = query(target_fd.as_raw_fd(), BPF_LIRC_MODE2, 0, &mut None)?; - - let mut prog_fds = Vec::with_capacity(prog_ids.len()); - - for id in prog_ids { - let fd = bpf_prog_get_fd_by_id(id)?; - prog_fds.push(fd); - } + pub fn query(target_fd: T) -> Result, ProgramError> { + let target_fd = target_fd.as_fd(); + let prog_ids = query(target_fd, BPF_LIRC_MODE2, 0, &mut None)?; - Ok(prog_fds + prog_ids .into_iter() - .map(|prog_fd| { - LircLink::new( - // SAFETY: The file descriptor will stay valid because - // we are leaking it. We cannot use `OwnedFd` in here - // because LircMode2::attach also uses LircLink::new - // but with a borrowed file descriptor (of the loaded - // program) without duplicating. TODO(#612): Fix API - // or internals so this file descriptor isn't leaked - unsafe { BorrowedFd::borrow_raw(prog_fd.into_raw_fd()) }, - target_fd.as_raw_fd(), - ) + .map(|prog_id| { + let prog_fd = bpf_prog_get_fd_by_id(prog_id)?; + let target_fd = target_fd.try_clone_to_owned()?; + // SAFETY: The file descriptor will stay valid because + // we are leaking it. We cannot use `OwnedFd` in here + // because LircMode2::attach also uses LircLink::new + // but with a borrowed file descriptor (of the loaded + // program) without duplicating. TODO(#612): Fix API + // or internals so this file descriptor isn't leaked + let prog_fd = unsafe { BorrowedFd::borrow_raw(prog_fd.into_raw_fd()) }; + Ok(LircLink::new(prog_fd, target_fd)) }) - .collect()) + .collect() } } @@ -127,16 +124,13 @@ pub struct LircLinkId(RawFd, RawFd); /// An LircMode2 Link pub struct LircLink { prog_fd: RawFd, - target_fd: RawFd, + target_fd: OwnedFd, } impl LircLink { - pub(crate) fn new(prog_fd: BorrowedFd<'_>, target_fd: RawFd) -> Self { + pub(crate) fn new(prog_fd: BorrowedFd<'_>, target_fd: OwnedFd) -> Self { let prog_fd = prog_fd.as_raw_fd(); - Self { - prog_fd, - target_fd: unsafe { dup(target_fd) }, - } + Self { prog_fd, target_fd } } /// Get ProgramInfo from this link @@ -151,12 +145,11 @@ impl Link for LircLink { type Id = LircLinkId; fn id(&self) -> Self::Id { - LircLinkId(self.prog_fd, self.target_fd) + LircLinkId(self.prog_fd, self.target_fd.as_raw_fd()) } fn detach(self) -> Result<(), ProgramError> { - let _ = bpf_prog_detach(self.prog_fd, self.target_fd, BPF_LIRC_MODE2); - unsafe { close(self.target_fd) }; + let _: SysResult<_> = bpf_prog_detach(self.prog_fd, self.target_fd.as_fd(), BPF_LIRC_MODE2); Ok(()) } } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 07755307..616244e0 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -640,8 +640,8 @@ fn load_program( } } -pub(crate) fn query( - target_fd: T, +pub(crate) fn query( + target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, query_flags: u32, attach_flags: &mut Option, @@ -653,7 +653,7 @@ pub(crate) fn query( loop { match bpf_prog_query( - target_fd.as_raw_fd(), + target_fd.as_fd().as_raw_fd(), attach_type, query_flags, attach_flags.as_mut(), diff --git a/aya/src/programs/perf_attach.rs b/aya/src/programs/perf_attach.rs index c48bf97e..8cf04871 100644 --- a/aya/src/programs/perf_attach.rs +++ b/aya/src/programs/perf_attach.rs @@ -7,7 +7,7 @@ use crate::{ probe::{detach_debug_fs, ProbeEvent}, FdLink, Link, ProgramError, }, - sys::{bpf_link_create, perf_event_ioctl, SysResult, SyscallError}, + sys::{bpf_link_create, perf_event_ioctl, LinkTarget, SysResult, SyscallError}, FEATURES, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF, }; @@ -75,12 +75,11 @@ pub(crate) fn perf_attach( fd: OwnedFd, ) -> Result { if FEATURES.bpf_perf_link() { - let link_fd = bpf_link_create(prog_fd, fd.as_raw_fd(), BPF_PERF_EVENT, None, 0).map_err( - |(_, io_error)| SyscallError { + let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(fd.as_fd()), BPF_PERF_EVENT, None, 0) + .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", io_error, - }, - )?; + })?; Ok(PerfLinkInner::FdLink(FdLink::new(link_fd))) } else { perf_attach_either(prog_fd, fd, None) diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index ab322daa..eb386187 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -1,9 +1,9 @@ -use std::os::fd::{AsFd as _, AsRawFd}; +use std::os::fd::AsFd; use crate::{ generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP}, programs::{define_link_wrapper, load_program, FdLinkId, ProgramData, ProgramError}, - sys::{bpf_link_create, SyscallError}, + sys::{bpf_link_create, LinkTarget, SyscallError}, }; use super::links::FdLink; @@ -60,17 +60,16 @@ impl SkLookup { /// Attaches the program to the given network namespace. /// /// The returned value can be used to detach, see [SkLookup::detach]. - pub fn attach(&mut self, netns: T) -> Result { + pub fn attach(&mut self, netns: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let netns_fd = netns.as_raw_fd(); + let netns_fd = netns.as_fd(); - let link_fd = bpf_link_create(prog_fd, netns_fd, BPF_SK_LOOKUP, None, 0).map_err( - |(_, io_error)| SyscallError { + let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(netns_fd), BPF_SK_LOOKUP, None, 0) + .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", io_error, - }, - )?; + })?; self.data .links .insert(SkLookupLink::new(FdLink::new(link_fd))) diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index e7776d5d..554c3e86 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -1,6 +1,6 @@ //! Skmsg programs. -use std::os::fd::{AsFd as _, AsRawFd as _}; +use std::os::fd::AsFd as _; use crate::{ generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG}, @@ -9,7 +9,6 @@ use crate::{ define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData, ProgramError, }, - sys::{bpf_prog_attach, SyscallError}, }; /// A program used to intercept messages sent with `sendmsg()`/`sendfile()`. @@ -81,19 +80,9 @@ impl SkMsg { pub fn attach(&mut self, map: SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let map_fd = map.as_raw_fd(); + let link = ProgAttachLink::attach(prog_fd, map.as_fd(), BPF_SK_MSG_VERDICT)?; - bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; - self.data.links.insert(SkMsgLink::new(ProgAttachLink::new( - prog_fd, - map_fd, - BPF_SK_MSG_VERDICT, - ))) + self.data.links.insert(SkMsgLink::new(link)) } /// Detaches the program from a sockmap. diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 79ac0c23..dac5ba3f 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -1,9 +1,6 @@ //! Skskb programs. -use std::{ - os::fd::{AsFd as _, AsRawFd as _}, - path::Path, -}; +use std::{os::fd::AsFd as _, path::Path}; use crate::{ generated::{ @@ -15,7 +12,6 @@ use crate::{ define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData, ProgramError, }, - sys::{bpf_prog_attach, SyscallError}, VerifierLogLevel, }; @@ -77,21 +73,15 @@ impl SkSkb { pub fn attach(&mut self, map: SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let map_fd = map.as_raw_fd(); let attach_type = match self.kind { SkSkbKind::StreamParser => BPF_SK_SKB_STREAM_PARSER, SkSkbKind::StreamVerdict => BPF_SK_SKB_STREAM_VERDICT, }; - bpf_prog_attach(prog_fd, map_fd, attach_type).map_err(|(_, io_error)| SyscallError { - call: "bpf_prog_attach", - io_error, - })?; - self.data.links.insert(SkSkbLink::new(ProgAttachLink::new( - prog_fd, - map_fd, - attach_type, - ))) + + let link = ProgAttachLink::attach(prog_fd, map.as_fd(), attach_type)?; + + self.data.links.insert(SkSkbLink::new(link)) } /// Detaches the program. diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index a44d7058..d8cb1383 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -1,5 +1,5 @@ //! Socket option programs. -use std::os::fd::{AsFd as _, AsRawFd}; +use std::os::fd::AsFd; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, @@ -7,7 +7,6 @@ use crate::{ define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData, ProgramError, }, - sys::{bpf_prog_attach, SyscallError}, }; /// A program used to work with sockets. @@ -58,22 +57,11 @@ impl SockOps { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [SockOps::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.fd()?; - let prog_fd = prog_fd.as_fd(); - let cgroup_fd = cgroup.as_raw_fd(); - bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; - self.data.links.insert(SockOpsLink::new(ProgAttachLink::new( - prog_fd, - cgroup_fd, - BPF_CGROUP_SOCK_OPS, - ))) + let link = ProgAttachLink::attach(prog_fd.as_fd(), cgroup.as_fd(), BPF_CGROUP_SOCK_OPS)?; + self.data.links.insert(SockOpsLink::new(link)) } /// Detaches the program. diff --git a/aya/src/programs/socket_filter.rs b/aya/src/programs/socket_filter.rs index e737d8ae..014b6475 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -2,7 +2,7 @@ use libc::{setsockopt, SOL_SOCKET}; use std::{ io, mem, - os::fd::{AsFd as _, AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, }; use thiserror::Error; @@ -48,13 +48,12 @@ pub enum SocketFilterError { /// # } /// # let mut bpf = aya::Bpf::load(&[])?; /// use std::net::TcpStream; -/// use std::os::fd::AsRawFd; /// use aya::programs::SocketFilter; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let prog: &mut SocketFilter = bpf.program_mut("filter_packets").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(client.as_raw_fd())?; +/// prog.attach(&client)?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -72,10 +71,11 @@ impl SocketFilter { /// Attaches the filter on the given socket. /// /// The returned value can be used to detach from the socket, see [SocketFilter::detach]. - pub fn attach(&mut self, socket: T) -> Result { + pub fn attach(&mut self, socket: T) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let prog_fd = prog_fd.as_raw_fd(); + let socket = socket.as_fd(); let socket = socket.as_raw_fd(); let ret = unsafe { diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 39ca3cf9..499b2b38 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -1,6 +1,9 @@ //! eXpress Data Path (XDP) programs. -use crate::{sys::SyscallError, util::KernelVersion}; +use crate::{ + sys::{LinkTarget, SyscallError}, + util::KernelVersion, +}; use bitflags; use libc::if_nametoindex; use std::{ @@ -128,12 +131,11 @@ impl Xdp { ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); - let if_index = if_index as RawFd; if KernelVersion::current().unwrap() >= KernelVersion::new(5, 9, 0) { let link_fd = bpf_link_create( prog_fd, - if_index, + LinkTarget::IfIndex(if_index), bpf_attach_type::BPF_XDP, None, flags.bits(), @@ -146,6 +148,7 @@ impl Xdp { .links .insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd)))) } else { + let if_index = if_index as i32; unsafe { netlink_set_xdp_fd(if_index, Some(prog_fd), None, flags.bits()) } .map_err(|io_error| XdpError::NetlinkError { io_error })?; diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 8656c04b..41f6fd6f 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -365,10 +365,15 @@ pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult { sys_bpf(bpf_cmd::BPF_MAP_FREEZE, &mut attr) } +pub(crate) enum LinkTarget<'f> { + Fd(BorrowedFd<'f>), + IfIndex(u32), +} + // since kernel 5.7 pub(crate) fn bpf_link_create( prog_fd: BorrowedFd<'_>, - target_fd: RawFd, + target: LinkTarget<'_>, attach_type: bpf_attach_type, btf_id: Option, flags: u32, @@ -376,7 +381,15 @@ pub(crate) fn bpf_link_create( let mut attr = unsafe { mem::zeroed::() }; attr.link_create.__bindgen_anon_1.prog_fd = prog_fd.as_raw_fd() as u32; - attr.link_create.__bindgen_anon_2.target_fd = target_fd as u32; + + match target { + LinkTarget::Fd(fd) => { + attr.link_create.__bindgen_anon_2.target_fd = fd.as_raw_fd() as u32; + } + LinkTarget::IfIndex(ifindex) => { + attr.link_create.__bindgen_anon_2.target_ifindex = ifindex; + } + }; attr.link_create.attach_type = attach_type as u32; attr.link_create.flags = flags; if let Some(btf_id) = btf_id { @@ -410,13 +423,13 @@ pub(crate) fn bpf_link_update( pub(crate) fn bpf_prog_attach( prog_fd: BorrowedFd<'_>, - target_fd: RawFd, + target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; attr.__bindgen_anon_5.attach_bpf_fd = prog_fd.as_raw_fd() as u32; - attr.__bindgen_anon_5.target_fd = target_fd as u32; + attr.__bindgen_anon_5.target_fd = target_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.attach_type = attach_type as u32; sys_bpf(bpf_cmd::BPF_PROG_ATTACH, &mut attr) @@ -424,13 +437,13 @@ pub(crate) fn bpf_prog_attach( pub(crate) fn bpf_prog_detach( prog_fd: RawFd, - map_fd: RawFd, + target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32; - attr.__bindgen_anon_5.target_fd = map_fd as u32; + attr.__bindgen_anon_5.target_fd = target_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.attach_type = attach_type as u32; sys_bpf(bpf_cmd::BPF_PROG_DETACH, &mut attr) @@ -683,7 +696,7 @@ pub(crate) fn is_perf_link_supported() -> bool { let fd = fd.as_fd(); matches!( // Uses an invalid target FD so we get EBADF if supported. - bpf_link_create(fd, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0), + bpf_link_create(fd, LinkTarget::IfIndex(u32::MAX), bpf_attach_type::BPF_PERF_EVENT, None, 0), // Returns EINVAL if unsupported. EBADF if supported. Err((_, e)) if e.raw_os_error() == Some(libc::EBADF), ) diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 4c06ccf6..388024ce 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -637,8 +637,8 @@ pub fn aya::maps::SockMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::SockMap pub fn aya::maps::SockMap::from(t: T) -> T pub struct aya::maps::sock::SockMapFd(_) -impl std::os::fd::raw::AsRawFd for aya::maps::sock::SockMapFd -pub fn aya::maps::sock::SockMapFd::as_raw_fd(&self) -> std::os::fd::raw::RawFd +impl std::os::fd::owned::AsFd for aya::maps::sock::SockMapFd +pub fn aya::maps::sock::SockMapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> impl core::clone::Clone for aya::maps::sock::SockMapFd pub fn aya::maps::sock::SockMapFd::clone(&self) -> aya::maps::sock::SockMapFd impl core::marker::Copy for aya::maps::sock::SockMapFd @@ -1793,7 +1793,7 @@ pub use aya::programs::CgroupSockoptAttachType pub mod aya::programs::cgroup_device pub struct aya::programs::cgroup_device::CgroupDevice impl aya::programs::cgroup_device::CgroupDevice -pub fn aya::programs::cgroup_device::CgroupDevice::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_device::CgroupDevice::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_device::CgroupDevice::detach(&mut self, link_id: aya::programs::cgroup_device::CgroupDeviceLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_device::CgroupDevice::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_device::CgroupDevice::take_link(&mut self, link_id: aya::programs::cgroup_device::CgroupDeviceLinkId) -> core::result::Result @@ -1936,7 +1936,7 @@ impl core::convert::From for aya::programs::cgroup_skb::CgroupSkbAttachTyp pub fn aya::programs::cgroup_skb::CgroupSkbAttachType::from(t: T) -> T pub struct aya::programs::cgroup_skb::CgroupSkb impl aya::programs::cgroup_skb::CgroupSkb -pub fn aya::programs::cgroup_skb::CgroupSkb::attach(&mut self, cgroup: T, attach_type: aya::programs::cgroup_skb::CgroupSkbAttachType) -> core::result::Result +pub fn aya::programs::cgroup_skb::CgroupSkb::attach(&mut self, cgroup: T, attach_type: aya::programs::cgroup_skb::CgroupSkbAttachType) -> core::result::Result pub fn aya::programs::cgroup_skb::CgroupSkb::detach(&mut self, link_id: aya::programs::cgroup_skb::CgroupSkbLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_skb::CgroupSkb::expected_attach_type(&self) -> &core::option::Option pub fn aya::programs::cgroup_skb::CgroupSkb::from_pin>(path: P, expected_attach_type: aya::programs::cgroup_skb::CgroupSkbAttachType) -> core::result::Result @@ -2047,7 +2047,7 @@ pub mod aya::programs::cgroup_sock pub use aya::programs::cgroup_sock::CgroupSockAttachType pub struct aya::programs::cgroup_sock::CgroupSock impl aya::programs::cgroup_sock::CgroupSock -pub fn aya::programs::cgroup_sock::CgroupSock::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sock::CgroupSock::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sock::CgroupSock::detach(&mut self, link_id: aya::programs::cgroup_sock::CgroupSockLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sock::CgroupSock::from_pin>(path: P, attach_type: aya_obj::programs::cgroup_sock::CgroupSockAttachType) -> core::result::Result pub fn aya::programs::cgroup_sock::CgroupSock::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -2157,7 +2157,7 @@ pub mod aya::programs::cgroup_sock_addr pub use aya::programs::cgroup_sock_addr::CgroupSockAddrAttachType pub struct aya::programs::cgroup_sock_addr::CgroupSockAddr impl aya::programs::cgroup_sock_addr::CgroupSockAddr -pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::detach(&mut self, link_id: aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::from_pin>(path: P, attach_type: aya_obj::programs::cgroup_sock_addr::CgroupSockAddrAttachType) -> core::result::Result pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -2267,7 +2267,7 @@ pub mod aya::programs::cgroup_sockopt pub use aya::programs::cgroup_sockopt::CgroupSockoptAttachType pub struct aya::programs::cgroup_sockopt::CgroupSockopt impl aya::programs::cgroup_sockopt::CgroupSockopt -pub fn aya::programs::cgroup_sockopt::CgroupSockopt::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sockopt::CgroupSockopt::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sockopt::CgroupSockopt::detach(&mut self, link_id: aya::programs::cgroup_sockopt::CgroupSockoptLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sockopt::CgroupSockopt::from_pin>(path: P, attach_type: aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType) -> core::result::Result pub fn aya::programs::cgroup_sockopt::CgroupSockopt::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -2376,7 +2376,7 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockoptLinkId::from(t: T) -> T pub mod aya::programs::cgroup_sysctl pub struct aya::programs::cgroup_sysctl::CgroupSysctl impl aya::programs::cgroup_sysctl::CgroupSysctl -pub fn aya::programs::cgroup_sysctl::CgroupSysctl::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sysctl::CgroupSysctl::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sysctl::CgroupSysctl::detach(&mut self, link_id: aya::programs::cgroup_sysctl::CgroupSysctlLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::take_link(&mut self, link_id: aya::programs::cgroup_sysctl::CgroupSysctlLinkId) -> core::result::Result @@ -3395,10 +3395,10 @@ impl core::convert::From for aya::programs::lirc_mode2::LircLinkId pub fn aya::programs::lirc_mode2::LircLinkId::from(t: T) -> T pub struct aya::programs::lirc_mode2::LircMode2 impl aya::programs::lirc_mode2::LircMode2 -pub fn aya::programs::lirc_mode2::LircMode2::attach(&mut self, lircdev: T) -> core::result::Result +pub fn aya::programs::lirc_mode2::LircMode2::attach(&mut self, lircdev: T) -> core::result::Result pub fn aya::programs::lirc_mode2::LircMode2::detach(&mut self, link_id: aya::programs::lirc_mode2::LircLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::lirc_mode2::LircMode2::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> -pub fn aya::programs::lirc_mode2::LircMode2::query(target_fd: T) -> core::result::Result, aya::programs::ProgramError> +pub fn aya::programs::lirc_mode2::LircMode2::query(target_fd: T) -> core::result::Result, aya::programs::ProgramError> pub fn aya::programs::lirc_mode2::LircMode2::take_link(&mut self, link_id: aya::programs::lirc_mode2::LircLinkId) -> core::result::Result impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> @@ -5567,7 +5567,7 @@ impl core::convert::From for aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::from(t: T) -> T pub struct aya::programs::CgroupDevice impl aya::programs::cgroup_device::CgroupDevice -pub fn aya::programs::cgroup_device::CgroupDevice::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_device::CgroupDevice::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_device::CgroupDevice::detach(&mut self, link_id: aya::programs::cgroup_device::CgroupDeviceLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_device::CgroupDevice::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_device::CgroupDevice::take_link(&mut self, link_id: aya::programs::cgroup_device::CgroupDeviceLinkId) -> core::result::Result @@ -5615,7 +5615,7 @@ impl core::convert::From for aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::from(t: T) -> T pub struct aya::programs::CgroupSkb impl aya::programs::cgroup_skb::CgroupSkb -pub fn aya::programs::cgroup_skb::CgroupSkb::attach(&mut self, cgroup: T, attach_type: aya::programs::cgroup_skb::CgroupSkbAttachType) -> core::result::Result +pub fn aya::programs::cgroup_skb::CgroupSkb::attach(&mut self, cgroup: T, attach_type: aya::programs::cgroup_skb::CgroupSkbAttachType) -> core::result::Result pub fn aya::programs::cgroup_skb::CgroupSkb::detach(&mut self, link_id: aya::programs::cgroup_skb::CgroupSkbLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_skb::CgroupSkb::expected_attach_type(&self) -> &core::option::Option pub fn aya::programs::cgroup_skb::CgroupSkb::from_pin>(path: P, expected_attach_type: aya::programs::cgroup_skb::CgroupSkbAttachType) -> core::result::Result @@ -5663,7 +5663,7 @@ impl core::convert::From for aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::from(t: T) -> T pub struct aya::programs::CgroupSock impl aya::programs::cgroup_sock::CgroupSock -pub fn aya::programs::cgroup_sock::CgroupSock::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sock::CgroupSock::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sock::CgroupSock::detach(&mut self, link_id: aya::programs::cgroup_sock::CgroupSockLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sock::CgroupSock::from_pin>(path: P, attach_type: aya_obj::programs::cgroup_sock::CgroupSockAttachType) -> core::result::Result pub fn aya::programs::cgroup_sock::CgroupSock::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -5710,7 +5710,7 @@ impl core::convert::From for aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::from(t: T) -> T pub struct aya::programs::CgroupSockAddr impl aya::programs::cgroup_sock_addr::CgroupSockAddr -pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::detach(&mut self, link_id: aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::from_pin>(path: P, attach_type: aya_obj::programs::cgroup_sock_addr::CgroupSockAddrAttachType) -> core::result::Result pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -5757,7 +5757,7 @@ impl core::convert::From for aya::programs::cgroup_sock_addr::CgroupSockAd pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::from(t: T) -> T pub struct aya::programs::CgroupSockopt impl aya::programs::cgroup_sockopt::CgroupSockopt -pub fn aya::programs::cgroup_sockopt::CgroupSockopt::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sockopt::CgroupSockopt::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sockopt::CgroupSockopt::detach(&mut self, link_id: aya::programs::cgroup_sockopt::CgroupSockoptLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sockopt::CgroupSockopt::from_pin>(path: P, attach_type: aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType) -> core::result::Result pub fn aya::programs::cgroup_sockopt::CgroupSockopt::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -5804,7 +5804,7 @@ impl core::convert::From for aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::from(t: T) -> T pub struct aya::programs::CgroupSysctl impl aya::programs::cgroup_sysctl::CgroupSysctl -pub fn aya::programs::cgroup_sysctl::CgroupSysctl::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::cgroup_sysctl::CgroupSysctl::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::cgroup_sysctl::CgroupSysctl::detach(&mut self, link_id: aya::programs::cgroup_sysctl::CgroupSysctlLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::take_link(&mut self, link_id: aya::programs::cgroup_sysctl::CgroupSysctlLinkId) -> core::result::Result @@ -6045,10 +6045,10 @@ impl core::convert::From for aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::from(t: T) -> T pub struct aya::programs::LircMode2 impl aya::programs::lirc_mode2::LircMode2 -pub fn aya::programs::lirc_mode2::LircMode2::attach(&mut self, lircdev: T) -> core::result::Result +pub fn aya::programs::lirc_mode2::LircMode2::attach(&mut self, lircdev: T) -> core::result::Result pub fn aya::programs::lirc_mode2::LircMode2::detach(&mut self, link_id: aya::programs::lirc_mode2::LircLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::lirc_mode2::LircMode2::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> -pub fn aya::programs::lirc_mode2::LircMode2::query(target_fd: T) -> core::result::Result, aya::programs::ProgramError> +pub fn aya::programs::lirc_mode2::LircMode2::query(target_fd: T) -> core::result::Result, aya::programs::ProgramError> pub fn aya::programs::lirc_mode2::LircMode2::take_link(&mut self, link_id: aya::programs::lirc_mode2::LircLinkId) -> core::result::Result impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> @@ -6354,7 +6354,7 @@ impl core::convert::From for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::from(t: T) -> T pub struct aya::programs::SkLookup impl aya::programs::SkLookup -pub fn aya::programs::SkLookup::attach(&mut self, netns: T) -> core::result::Result +pub fn aya::programs::SkLookup::attach(&mut self, netns: T) -> core::result::Result pub fn aya::programs::SkLookup::detach(&mut self, link_id: SkLookupLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkLookup::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkLookup::take_link(&mut self, link_id: SkLookupLinkId) -> core::result::Result @@ -6497,7 +6497,7 @@ impl core::convert::From for aya::programs::SkSkb pub fn aya::programs::SkSkb::from(t: T) -> T pub struct aya::programs::SockOps impl aya::programs::SockOps -pub fn aya::programs::SockOps::attach(&mut self, cgroup: T) -> core::result::Result +pub fn aya::programs::SockOps::attach(&mut self, cgroup: T) -> core::result::Result pub fn aya::programs::SockOps::detach(&mut self, link_id: SockOpsLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SockOps::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SockOps::take_link(&mut self, link_id: SockOpsLinkId) -> core::result::Result @@ -6545,7 +6545,7 @@ impl core::convert::From for aya::programs::SockOps pub fn aya::programs::SockOps::from(t: T) -> T pub struct aya::programs::SocketFilter impl aya::programs::SocketFilter -pub fn aya::programs::SocketFilter::attach(&mut self, socket: T) -> core::result::Result +pub fn aya::programs::SocketFilter::attach(&mut self, socket: T) -> core::result::Result pub fn aya::programs::SocketFilter::detach(&mut self, link_id: SocketFilterLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SocketFilter::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SocketFilter::take_link(&mut self, link_id: SocketFilterLinkId) -> core::result::Result From cee0265b5291acb747cf3a9532cfbf61c455f398 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 29 Aug 2023 17:38:55 -0400 Subject: [PATCH 16/95] netlink: use OwnedFd Updates #612. --- aya/src/programs/xdp.rs | 8 +++++-- aya/src/sys/netlink.rs | 51 ++++++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 499b2b38..89574328 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -11,7 +11,7 @@ use std::{ ffi::CString, hash::Hash, io, - os::fd::{AsFd as _, AsRawFd as _, RawFd}, + os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, RawFd}, }; use thiserror::Error; @@ -201,6 +201,8 @@ impl Xdp { XdpLinkInner::NlLink(nl_link) => { let if_index = nl_link.if_index; let old_prog_fd = nl_link.prog_fd; + // SAFETY: TODO(https://github.com/aya-rs/aya/issues/612): make this safe by not holding `RawFd`s. + let old_prog_fd = unsafe { BorrowedFd::borrow_raw(old_prog_fd) }; let flags = nl_link.flags; let replace_flags = flags | XdpFlags::REPLACE; unsafe { @@ -246,7 +248,9 @@ impl Link for NlLink { } else { self.flags.bits() }; - let _ = unsafe { netlink_set_xdp_fd(self.if_index, None, Some(self.prog_fd), flags) }; + // SAFETY: TODO(https://github.com/aya-rs/aya/issues/612): make this safe by not holding `RawFd`s. + let prog_fd = unsafe { BorrowedFd::borrow_raw(self.prog_fd) }; + let _ = unsafe { netlink_set_xdp_fd(self.if_index, None, Some(prog_fd), flags) }; Ok(()) } } diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index 3643e95b..c4679aab 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -2,13 +2,13 @@ use std::{ collections::HashMap, ffi::CStr, io, mem, - os::fd::{AsRawFd as _, BorrowedFd, RawFd}, + os::fd::{AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd}, ptr, slice, }; use thiserror::Error; use libc::{ - close, getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl, socket, + getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl, socket, AF_NETLINK, AF_UNSPEC, ETH_P_ALL, IFF_UP, IFLA_XDP, NETLINK_EXT_ACK, NETLINK_ROUTE, NLA_ALIGNTO, NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_DONE, NLMSG_ERROR, NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP, NLM_F_ECHO, NLM_F_EXCL, NLM_F_MULTI, NLM_F_REQUEST, RTM_DELTFILTER, RTM_GETTFILTER, @@ -32,7 +32,7 @@ const NLA_HDR_LEN: usize = align_to(mem::size_of::(), NLA_ALIGNTO as usi pub(crate) unsafe fn netlink_set_xdp_fd( if_index: i32, fd: Option>, - old_fd: Option, + old_fd: Option>, flags: u32, ) -> Result<(), io::Error> { let sock = NetlinkSocket::open()?; @@ -64,7 +64,10 @@ pub(crate) unsafe fn netlink_set_xdp_fd( } if flags & XDP_FLAGS_REPLACE != 0 { - attrs.write_attr(IFLA_XDP_EXPECTED_FD as u16, old_fd.unwrap())?; + attrs.write_attr( + IFLA_XDP_EXPECTED_FD as u16, + old_fd.map(|fd| fd.as_raw_fd()).unwrap(), + )?; } let nla_len = attrs.finish()?; @@ -290,7 +293,7 @@ struct TcRequest { } struct NetlinkSocket { - sock: RawFd, + sock: OwnedFd, _nl_pid: u32, } @@ -301,12 +304,14 @@ impl NetlinkSocket { if sock < 0 { return Err(io::Error::last_os_error()); } + // SAFETY: `socket` returns a file descriptor. + let sock = unsafe { OwnedFd::from_raw_fd(sock) }; let enable = 1i32; // Safety: libc wrapper unsafe { setsockopt( - sock, + sock.as_raw_fd(), SOL_NETLINK, NETLINK_EXT_ACK, &enable as *const _ as *const _, @@ -319,7 +324,13 @@ impl NetlinkSocket { addr.nl_family = AF_NETLINK as u16; let mut addr_len = mem::size_of::() as u32; // Safety: libc wrapper - if unsafe { getsockname(sock, &mut addr as *mut _ as *mut _, &mut addr_len as *mut _) } < 0 + if unsafe { + getsockname( + sock.as_raw_fd(), + &mut addr as *mut _ as *mut _, + &mut addr_len as *mut _, + ) + } < 0 { return Err(io::Error::last_os_error()); } @@ -331,7 +342,15 @@ impl NetlinkSocket { } fn send(&self, msg: &[u8]) -> Result<(), io::Error> { - if unsafe { send(self.sock, msg.as_ptr() as *const _, msg.len(), 0) } < 0 { + if unsafe { + send( + self.sock.as_raw_fd(), + msg.as_ptr() as *const _, + msg.len(), + 0, + ) + } < 0 + { return Err(io::Error::last_os_error()); } Ok(()) @@ -344,7 +363,14 @@ impl NetlinkSocket { 'out: while multipart { multipart = false; // Safety: libc wrapper - let len = unsafe { recv(self.sock, buf.as_mut_ptr() as *mut _, buf.len(), 0) }; + let len = unsafe { + recv( + self.sock.as_raw_fd(), + buf.as_mut_ptr() as *mut _, + buf.len(), + 0, + ) + }; if len < 0 { return Err(io::Error::last_os_error()); } @@ -430,13 +456,6 @@ impl NetlinkMessage { } } -impl Drop for NetlinkSocket { - fn drop(&mut self) { - // Safety: libc wrapper - unsafe { close(self.sock) }; - } -} - const fn align_to(v: usize, align: usize) -> usize { (v + (align - 1)) & !(align - 1) } From 204d02022a94dab441029855e5d39d5143444204 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 29 Aug 2023 17:52:58 -0400 Subject: [PATCH 17/95] programs: ProgAttachLink and LircLink hold owned FDs Updates #612. --- aya/src/programs/links.rs | 33 +++++++++++++------------- aya/src/programs/lirc_mode2.rs | 42 +++++++++++++--------------------- aya/src/sys/bpf.rs | 28 ++++++++++++++++++----- 3 files changed, 55 insertions(+), 48 deletions(-) diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 619ebef6..d06a62e4 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -12,10 +12,8 @@ use std::{ use crate::{ generated::bpf_attach_type, pin::PinError, - programs::ProgramError, - sys::{ - bpf_get_object, bpf_pin_object, bpf_prog_attach, bpf_prog_detach, SysResult, SyscallError, - }, + programs::{ProgramError, ProgramFd}, + sys::{bpf_get_object, bpf_pin_object, bpf_prog_attach, bpf_prog_detach, SyscallError}, }; /// A Link. @@ -234,7 +232,7 @@ pub struct ProgAttachLinkId(RawFd, RawFd, bpf_attach_type); /// The Link type used by programs that are attached with `bpf_prog_attach`. #[derive(Debug)] pub struct ProgAttachLink { - prog_fd: RawFd, + prog_fd: ProgramFd, target_fd: OwnedFd, attach_type: bpf_attach_type, } @@ -249,15 +247,11 @@ impl ProgAttachLink { // going to need a duplicate whose lifetime we manage. Let's // duplicate it prior to attaching it so the new file // descriptor is closed at drop in case it fails to attach. + let prog_fd = prog_fd.try_clone_to_owned()?; let target_fd = target_fd.try_clone_to_owned()?; - bpf_prog_attach(prog_fd, target_fd.as_fd(), attach_type).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + bpf_prog_attach(prog_fd.as_fd(), target_fd.as_fd(), attach_type)?; - let prog_fd = prog_fd.as_raw_fd(); + let prog_fd = ProgramFd(prog_fd); Ok(Self { prog_fd, target_fd, @@ -270,13 +264,20 @@ impl Link for ProgAttachLink { type Id = ProgAttachLinkId; fn id(&self) -> Self::Id { - ProgAttachLinkId(self.prog_fd, self.target_fd.as_raw_fd(), self.attach_type) + ProgAttachLinkId( + self.prog_fd.as_fd().as_raw_fd(), + self.target_fd.as_raw_fd(), + self.attach_type, + ) } fn detach(self) -> Result<(), ProgramError> { - let _: SysResult<_> = - bpf_prog_detach(self.prog_fd, self.target_fd.as_fd(), self.attach_type); - Ok(()) + bpf_prog_detach( + self.prog_fd.as_fd(), + self.target_fd.as_fd(), + self.attach_type, + ) + .map_err(Into::into) } } diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 7b0d886f..6e62ce60 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -1,10 +1,10 @@ //! Lirc programs. -use std::os::fd::{AsFd, AsRawFd, BorrowedFd, IntoRawFd as _, OwnedFd, RawFd}; +use std::os::fd::{AsFd, AsRawFd as _, OwnedFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2}, - programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo}, - sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, SysResult, SyscallError}, + programs::{load_program, query, Link, ProgramData, ProgramError, ProgramFd, ProgramInfo}, + sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id}, }; /// A program used to decode IR into key events for a lirc device. @@ -60,20 +60,15 @@ impl LircMode2 { /// The returned value can be used to detach, see [LircMode2::detach]. pub fn attach(&mut self, lircdev: T) -> Result { let prog_fd = self.fd()?; - let prog_fd = prog_fd.as_fd(); // The link is going to own this new file descriptor so we are // going to need a duplicate whose lifetime we manage. Let's // duplicate it prior to attaching it so the new file // descriptor is closed at drop in case it fails to attach. + let prog_fd = prog_fd.try_clone()?; let lircdev_fd = lircdev.as_fd().try_clone_to_owned()?; - bpf_prog_attach(prog_fd, lircdev_fd.as_fd(), BPF_LIRC_MODE2).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_prog_attach", - io_error, - } - })?; + bpf_prog_attach(prog_fd.as_fd(), lircdev_fd.as_fd(), BPF_LIRC_MODE2)?; self.data.links.insert(LircLink::new(prog_fd, lircdev_fd)) } @@ -103,13 +98,7 @@ impl LircMode2 { .map(|prog_id| { let prog_fd = bpf_prog_get_fd_by_id(prog_id)?; let target_fd = target_fd.try_clone_to_owned()?; - // SAFETY: The file descriptor will stay valid because - // we are leaking it. We cannot use `OwnedFd` in here - // because LircMode2::attach also uses LircLink::new - // but with a borrowed file descriptor (of the loaded - // program) without duplicating. TODO(#612): Fix API - // or internals so this file descriptor isn't leaked - let prog_fd = unsafe { BorrowedFd::borrow_raw(prog_fd.into_raw_fd()) }; + let prog_fd = ProgramFd(prog_fd); Ok(LircLink::new(prog_fd, target_fd)) }) .collect() @@ -123,21 +112,22 @@ pub struct LircLinkId(RawFd, RawFd); #[derive(Debug)] /// An LircMode2 Link pub struct LircLink { - prog_fd: RawFd, + prog_fd: ProgramFd, target_fd: OwnedFd, } impl LircLink { - pub(crate) fn new(prog_fd: BorrowedFd<'_>, target_fd: OwnedFd) -> Self { - let prog_fd = prog_fd.as_raw_fd(); + pub(crate) fn new(prog_fd: ProgramFd, target_fd: OwnedFd) -> Self { Self { prog_fd, target_fd } } /// Get ProgramInfo from this link pub fn info(&self) -> Result { - // SAFETY: TODO(https://github.com/aya-rs/aya/issues/612): make this safe by not holding `RawFd`s. - let prog_fd = unsafe { BorrowedFd::borrow_raw(self.prog_fd) }; - ProgramInfo::new_from_fd(prog_fd) + let Self { + prog_fd, + target_fd: _, + } = self; + ProgramInfo::new_from_fd(prog_fd.as_fd()) } } @@ -145,11 +135,11 @@ impl Link for LircLink { type Id = LircLinkId; fn id(&self) -> Self::Id { - LircLinkId(self.prog_fd, self.target_fd.as_raw_fd()) + LircLinkId(self.prog_fd.as_fd().as_raw_fd(), self.target_fd.as_raw_fd()) } fn detach(self) -> Result<(), ProgramError> { - let _: SysResult<_> = bpf_prog_detach(self.prog_fd, self.target_fd.as_fd(), BPF_LIRC_MODE2); - Ok(()) + bpf_prog_detach(self.prog_fd.as_fd(), self.target_fd.as_fd(), BPF_LIRC_MODE2) + .map_err(Into::into) } } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 41f6fd6f..801ea48d 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -425,28 +425,44 @@ pub(crate) fn bpf_prog_attach( prog_fd: BorrowedFd<'_>, target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, -) -> SysResult { +) -> Result<(), SyscallError> { let mut attr = unsafe { mem::zeroed::() }; attr.__bindgen_anon_5.attach_bpf_fd = prog_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.target_fd = target_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.attach_type = attach_type as u32; - sys_bpf(bpf_cmd::BPF_PROG_ATTACH, &mut attr) + let ret = sys_bpf(bpf_cmd::BPF_PROG_ATTACH, &mut attr).map_err(|(code, io_error)| { + assert_eq!(code, -1); + SyscallError { + call: "bpf_prog_attach", + io_error, + } + })?; + assert_eq!(ret, 0); + Ok(()) } pub(crate) fn bpf_prog_detach( - prog_fd: RawFd, + prog_fd: BorrowedFd<'_>, target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, -) -> SysResult { +) -> Result<(), SyscallError> { let mut attr = unsafe { mem::zeroed::() }; - attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32; + attr.__bindgen_anon_5.attach_bpf_fd = prog_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.target_fd = target_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.attach_type = attach_type as u32; - sys_bpf(bpf_cmd::BPF_PROG_DETACH, &mut attr) + let ret = sys_bpf(bpf_cmd::BPF_PROG_DETACH, &mut attr).map_err(|(code, io_error)| { + assert_eq!(code, -1); + SyscallError { + call: "bpf_prog_detach", + io_error, + } + })?; + assert_eq!(ret, 0); + Ok(()) } pub(crate) fn bpf_prog_query( From 8b0c7f12046c2ebadcee5e7ab813d5a34ddc08c6 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 31 Aug 2023 12:21:49 -0400 Subject: [PATCH 18/95] async_perf_event_array: access inner through async Avoid holding onto raw file descriptors. Remove some implied bounds (BorrowMut implies Borrow). --- aya/src/maps/perf/async_perf_event_array.rs | 52 +++++++++------------ aya/src/maps/perf/perf_event_array.rs | 7 ++- xtask/public-api/aya.txt | 16 +++---- 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/aya/src/maps/perf/async_perf_event_array.rs b/aya/src/maps/perf/async_perf_event_array.rs index 7c942e26..83e9484a 100644 --- a/aya/src/maps/perf/async_perf_event_array.rs +++ b/aya/src/maps/perf/async_perf_event_array.rs @@ -1,8 +1,5 @@ use bytes::BytesMut; -use std::{ - borrow::{Borrow, BorrowMut}, - os::fd::{AsRawFd as _, RawFd}, -}; +use std::borrow::{Borrow, BorrowMut}; // See https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features. // @@ -92,7 +89,7 @@ pub struct AsyncPerfEventArray { perf_map: PerfEventArray, } -impl + Borrow> AsyncPerfEventArray { +impl> AsyncPerfEventArray { /// Opens the perf buffer at the given index. /// /// The returned buffer will receive all the events eBPF programs send at the given index. @@ -103,16 +100,11 @@ impl + Borrow> AsyncPerfEventArray { ) -> Result, PerfBufferError> { let Self { perf_map } = self; let buf = perf_map.open(index, page_count)?; - let fd = buf.as_raw_fd(); - Ok(AsyncPerfEventArrayBuffer { - buf, - - #[cfg(feature = "async_tokio")] - async_tokio_fd: AsyncFd::new(fd)?, - - #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))] - async_std_fd: Async::new(fd)?, - }) + #[cfg(feature = "async_tokio")] + let buf = AsyncFd::new(buf)?; + #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))] + let buf = Async::new(buf)?; + Ok(AsyncPerfEventArrayBuffer { buf }) } } @@ -131,17 +123,18 @@ impl> AsyncPerfEventArray { /// /// See the [`AsyncPerfEventArray` documentation](AsyncPerfEventArray) for an overview of how to /// use perf buffers. -pub struct AsyncPerfEventArrayBuffer { +pub struct AsyncPerfEventArrayBuffer> { + #[cfg(not(any(feature = "async_tokio", feature = "async_std")))] buf: PerfEventArrayBuffer, #[cfg(feature = "async_tokio")] - async_tokio_fd: AsyncFd, + buf: AsyncFd>, #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))] - async_std_fd: Async, + buf: Async>, } -impl + Borrow> AsyncPerfEventArrayBuffer { +impl> AsyncPerfEventArrayBuffer { /// Reads events from the buffer. /// /// This method reads events into the provided slice of buffers, filling @@ -155,21 +148,20 @@ impl + Borrow> AsyncPerfEventArrayBuffer { &mut self, buffers: &mut [BytesMut], ) -> Result { - let Self { - buf, - #[cfg(feature = "async_tokio")] - async_tokio_fd, - #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))] - async_std_fd, - } = self; + let Self { buf } = self; loop { #[cfg(feature = "async_tokio")] - let mut guard = async_tokio_fd.readable_mut().await?; + let mut guard = buf.readable_mut().await?; + #[cfg(feature = "async_tokio")] + let buf = guard.get_inner_mut(); #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))] - if !buf.readable() { - async_std_fd.readable().await?; - } + let buf = { + if !buf.get_ref().readable() { + buf.readable().await?; + } + buf.get_mut() + }; let events = buf.read_events(buffers)?; const EMPTY: Events = Events { read: 0, lost: 0 }; diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index bde255ed..1d19d373 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -31,7 +31,7 @@ pub struct PerfEventArrayBuffer { buf: PerfBuffer, } -impl + Borrow> PerfEventArrayBuffer { +impl> PerfEventArrayBuffer { /// Returns true if the buffer contains events that haven't been read. pub fn readable(&self) -> bool { self.buf.readable() @@ -55,7 +55,7 @@ impl + Borrow> PerfEventArrayBuffer { } } -impl + Borrow> AsRawFd for PerfEventArrayBuffer { +impl> AsRawFd for PerfEventArrayBuffer { fn as_raw_fd(&self) -> RawFd { self.buf.as_raw_fd() } @@ -169,7 +169,7 @@ impl> PerfEventArray { } } -impl + Borrow> PerfEventArray { +impl> PerfEventArray { /// Opens the perf buffer at the given index. /// /// The returned buffer will receive all the events eBPF programs send at the given index. @@ -180,7 +180,6 @@ impl + Borrow> PerfEventArray { ) -> Result, PerfBufferError> { // FIXME: keep track of open buffers - // this cannot fail as new() checks that the fd is open let map_data: &MapData = self.map.deref().borrow(); let map_fd = map_data.fd; let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?; diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 388024ce..ae3c865a 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -372,7 +372,7 @@ pub fn aya::maps::perf::PerfBufferError::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::perf::PerfBufferError pub fn aya::maps::perf::PerfBufferError::from(t: T) -> T pub struct aya::maps::perf::AsyncPerfEventArray -impl + core::borrow::Borrow> aya::maps::perf::AsyncPerfEventArray +impl> aya::maps::perf::AsyncPerfEventArray pub fn aya::maps::perf::AsyncPerfEventArray::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError @@ -404,8 +404,8 @@ impl core::borrow::BorrowMut for aya::maps::perf::AsyncPerfEventArray w pub fn aya::maps::perf::AsyncPerfEventArray::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::perf::AsyncPerfEventArray pub fn aya::maps::perf::AsyncPerfEventArray::from(t: T) -> T -pub struct aya::maps::perf::AsyncPerfEventArrayBuffer -impl + core::borrow::Borrow> aya::maps::perf::AsyncPerfEventArrayBuffer +pub struct aya::maps::perf::AsyncPerfEventArrayBuffer> +impl> aya::maps::perf::AsyncPerfEventArrayBuffer pub async fn aya::maps::perf::AsyncPerfEventArrayBuffer::read_events(&mut self, buffers: &mut [bytes::bytes_mut::BytesMut]) -> core::result::Result impl core::marker::Send for aya::maps::perf::AsyncPerfEventArrayBuffer where T: core::marker::Send + core::marker::Sync impl core::marker::Sync for aya::maps::perf::AsyncPerfEventArrayBuffer where T: core::marker::Send + core::marker::Sync @@ -460,7 +460,7 @@ pub fn aya::maps::perf::Events::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::perf::Events pub fn aya::maps::perf::Events::from(t: T) -> T pub struct aya::maps::perf::PerfEventArray -impl + core::borrow::Borrow> aya::maps::perf::PerfEventArray +impl> aya::maps::perf::PerfEventArray pub fn aya::maps::perf::PerfEventArray::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::PerfEventArray pub type aya::maps::perf::PerfEventArray::Error = aya::maps::MapError @@ -493,10 +493,10 @@ pub fn aya::maps::perf::PerfEventArray::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::perf::PerfEventArray pub fn aya::maps::perf::PerfEventArray::from(t: T) -> T pub struct aya::maps::perf::PerfEventArrayBuffer -impl + core::borrow::Borrow> aya::maps::perf::PerfEventArrayBuffer +impl> aya::maps::perf::PerfEventArrayBuffer pub fn aya::maps::perf::PerfEventArrayBuffer::read_events(&mut self, out_bufs: &mut [bytes::bytes_mut::BytesMut]) -> core::result::Result pub fn aya::maps::perf::PerfEventArrayBuffer::readable(&self) -> bool -impl + core::borrow::Borrow> std::os::fd::raw::AsRawFd for aya::maps::perf::PerfEventArrayBuffer +impl> std::os::fd::raw::AsRawFd for aya::maps::perf::PerfEventArrayBuffer pub fn aya::maps::perf::PerfEventArrayBuffer::as_raw_fd(&self) -> std::os::fd::raw::RawFd impl core::marker::Send for aya::maps::perf::PerfEventArrayBuffer where T: core::marker::Send + core::marker::Sync impl core::marker::Sync for aya::maps::perf::PerfEventArrayBuffer where T: core::marker::Send + core::marker::Sync @@ -1067,7 +1067,7 @@ pub fn aya::maps::array::Array::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::array::Array pub fn aya::maps::array::Array::from(t: T) -> T pub struct aya::maps::AsyncPerfEventArray -impl + core::borrow::Borrow> aya::maps::perf::AsyncPerfEventArray +impl> aya::maps::perf::AsyncPerfEventArray pub fn aya::maps::perf::AsyncPerfEventArray::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError @@ -1460,7 +1460,7 @@ pub fn aya::maps::PerCpuValues::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::PerCpuValues pub fn aya::maps::PerCpuValues::from(t: T) -> T pub struct aya::maps::PerfEventArray -impl + core::borrow::Borrow> aya::maps::perf::PerfEventArray +impl> aya::maps::perf::PerfEventArray pub fn aya::maps::perf::PerfEventArray::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::PerfEventArray pub type aya::maps::perf::PerfEventArray::Error = aya::maps::MapError From 2a1bf609b2b1239c9a789f1a1c814dfa888dfd1d Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Thu, 31 Aug 2023 21:32:56 -0400 Subject: [PATCH 19/95] aya/maps: rework TryFrom macros The old macros were repetitive and inflexible. This unifies the various macros used to generate TryFrom implementations for map implementations from the relevant map enum variants. Cleanup in anticipation of fixing #636. The API changes are just about renaming the return to Self and Self::Error; they are not real changes. --- aya/src/maps/mod.rs | 209 ++++++++--------------- xtask/public-api/aya.txt | 360 +++++++++++++++++++-------------------- 2 files changed, 248 insertions(+), 321 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index dfa0949c..cd082530 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -281,155 +281,82 @@ impl Map { } } +// Implements TryFrom for different map implementations. Different map implementations can be +// constructed from different variants of the map enum. Also, the implementation may have type +// parameters (which we assume all have the bound `Pod` and nothing else). macro_rules! impl_try_from_map { - ($($tx:ident from Map::$ty:ident),+ $(,)?) => { - $( - impl<'a> TryFrom<&'a Map> for $tx<&'a MapData> { - type Error = MapError; - - fn try_from(map: &'a Map) -> Result<$tx<&'a MapData>, MapError> { - match map { - Map::$ty(m) => { - $tx::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - - impl<'a,> TryFrom<&'a mut Map> for $tx<&'a mut MapData> { - type Error = MapError; - - fn try_from(map: &'a mut Map) -> Result<$tx<&'a mut MapData>, MapError> { - match map { - Map::$ty(m) => { - $tx::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - - impl TryFrom for $tx { - type Error = MapError; - - fn try_from(map: Map) -> Result<$tx, MapError> { - match map { - Map::$ty(m) => { - $tx::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } + // At the root the type parameters are marked as a single token tree which will be pasted into + // the invocation for each type. Note that the later patterns require that the token tree be + // zero or more comma separated idents wrapped in parens. Note that the tt metavar is used here + // rather than the repeated idents used later because the macro language does not allow one + // repetition to be pasted inside another. + ($ty_param:tt { + $($ty:ident $(from $variant:ident)?),+ $(,)? + }) => { + $(impl_try_from_map!(<$ty_param> $ty $(from $variant)?);)+ + }; + // Add the "from $variant" using $ty as the default if it is missing. + (<$ty_param:tt> $ty:ident) => { + impl_try_from_map!(<$ty_param> $ty from $ty); + }; + // Dispatch for each of the lifetimes. + ( + <($($ty_param:ident),*)> $ty:ident from $variant:ident + ) => { + impl_try_from_map!(<'a> ($($ty_param),*) $ty from $variant); + impl_try_from_map!(<'a mut> ($($ty_param),*) $ty from $variant); + impl_try_from_map!(<> ($($ty_param),*) $ty from $variant); + }; + // An individual impl. + ( + <$($l:lifetime $($m:ident)?)?> + ($($ty_param:ident),*) + $ty:ident from $variant:ident + ) => { + impl<$($l,)? $($ty_param: Pod),*> TryFrom<$(&$l $($m)?)? Map> + for $ty<$(&$l $($m)?)? MapData, $($ty_param),*> + { + type Error = MapError; + + fn try_from(map: $(&$l $($m)?)? Map) -> Result { + match map { + Map::$variant(map_data) => Self::new(map_data), + map => Err(MapError::InvalidMapType { + map_type: map.map_type() + }), } } - )+ - } + } + }; } -impl_try_from_map!( - ProgramArray from Map::ProgramArray, - SockMap from Map::SockMap, - PerfEventArray from Map::PerfEventArray, - StackTraceMap from Map::StackTraceMap, -); +impl_try_from_map!(() { + ProgramArray, + SockMap, + PerfEventArray, + StackTraceMap, +}); #[cfg(any(feature = "async_tokio", feature = "async_std"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "async_tokio", feature = "async_std"))))] -impl_try_from_map!( - AsyncPerfEventArray from Map::PerfEventArray, -); - -macro_rules! impl_try_from_map_generic_key_or_value { - ($($ty:ident),+ $(,)?) => { - $( - impl<'a, V:Pod> TryFrom<&'a Map> for $ty<&'a MapData, V> { - type Error = MapError; - - fn try_from(map: &'a Map) -> Result<$ty<&'a MapData , V>, MapError> { - match map { - Map::$ty(m) => { - $ty::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - - impl<'a,V: Pod> TryFrom<&'a mut Map> for $ty<&'a mut MapData, V> { - type Error = MapError; - - fn try_from(map: &'a mut Map) -> Result<$ty<&'a mut MapData, V>, MapError> { - match map { - Map::$ty(m) => { - $ty::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - - impl TryFrom for $ty { - type Error = MapError; - - fn try_from(map: Map) -> Result<$ty, MapError> { - match map { - Map::$ty(m) => { - $ty::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - )+ - } -} - -impl_try_from_map_generic_key_or_value!(Array, PerCpuArray, SockHash, BloomFilter, Queue, Stack,); - -macro_rules! impl_try_from_map_generic_key_and_value { - ($($ty:ident),+ $(,)?) => { - $( - impl<'a, V: Pod, K: Pod> TryFrom<&'a Map> for $ty<&'a MapData, V, K> { - type Error = MapError; - - fn try_from(map: &'a Map) -> Result<$ty<&'a MapData,V,K>, MapError> { - match map { - Map::$ty(m) => { - $ty::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - - impl<'a,V: Pod,K: Pod> TryFrom<&'a mut Map> for $ty<&'a mut MapData, V, K> { - type Error = MapError; - - fn try_from(map: &'a mut Map) -> Result<$ty<&'a mut MapData, V, K>, MapError> { - match map { - Map::$ty(m) => { - $ty::new(m) - }, - _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}), - } - } - } - - impl TryFrom for $ty { - type Error = MapError; - - fn try_from(map: Map) -> Result<$ty, MapError> { - match map { - Map::$ty(m) => $ty::new(m), - _ => Err(MapError::InvalidMapType { map_type: map.map_type() }), - } - } - } - )+ - } -} - -impl_try_from_map_generic_key_and_value!(HashMap, PerCpuHashMap, LpmTrie); +impl_try_from_map!(() { + AsyncPerfEventArray from PerfEventArray, +}); + +impl_try_from_map!((V) { + Array, + PerCpuArray, + SockHash, + BloomFilter, + Queue, + Stack, +}); + +impl_try_from_map!((K, V) { + HashMap, + PerCpuHashMap, + LpmTrie, +}); pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> { let max_entries = map.obj.max_entries(); diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 388024ce..9991dd35 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -15,16 +15,16 @@ impl, V: aya::Pod> aya::maps::arr pub fn aya::maps::array::Array::set(&mut self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V> pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::array::Array<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::array::Array<&'a mut aya::maps::MapData, V> pub type aya::maps::array::Array<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::array::Array<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl, V: aya::Pod> aya::maps::IterableMap for aya::maps::array::Array pub fn aya::maps::array::Array::get(&self, index: &u32) -> core::result::Result pub fn aya::maps::array::Array::map(&self) -> &aya::maps::MapData impl core::convert::TryFrom for aya::maps::array::Array pub type aya::maps::array::Array::Error = aya::maps::MapError -pub fn aya::maps::array::Array::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::array::Array where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::array::Array where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::array::Array where T: core::marker::Unpin, V: core::marker::Unpin @@ -55,16 +55,16 @@ impl, V: aya::Pod> aya::maps::Per pub fn aya::maps::PerCpuArray::set(&mut self, index: u32, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl, V: aya::Pod> aya::maps::IterableMap> for aya::maps::PerCpuArray pub fn aya::maps::PerCpuArray::get(&self, index: &u32) -> core::result::Result, aya::maps::MapError> pub fn aya::maps::PerCpuArray::map(&self) -> &aya::maps::MapData impl core::convert::TryFrom for aya::maps::PerCpuArray pub type aya::maps::PerCpuArray::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::PerCpuArray where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::PerCpuArray where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::PerCpuArray where T: core::marker::Unpin, V: core::marker::Unpin @@ -94,13 +94,13 @@ pub fn aya::maps::ProgramArray::clear_index(&mut self, index: &u32) -> core:: pub fn aya::maps::ProgramArray::set(&mut self, index: u32, program: &aya::programs::ProgramFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ProgramArray<&'a aya::maps::MapData> pub type aya::maps::ProgramArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ProgramArray<&'a mut aya::maps::MapData> pub type aya::maps::ProgramArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::ProgramArray where T: core::marker::Send impl core::marker::Sync for aya::maps::ProgramArray where T: core::marker::Sync impl core::marker::Unpin for aya::maps::ProgramArray where T: core::marker::Unpin @@ -130,13 +130,13 @@ impl, V: aya::Pod> aya::maps::blo pub fn aya::maps::bloom_filter::BloomFilter::insert(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::bloom_filter::BloomFilter pub type aya::maps::bloom_filter::BloomFilter::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter::try_from(map: aya::maps::Map) -> core::result::Result impl core::fmt::Debug for aya::maps::bloom_filter::BloomFilter pub fn aya::maps::bloom_filter::BloomFilter::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::bloom_filter::BloomFilter where T: core::marker::Send, V: core::marker::Send @@ -169,18 +169,18 @@ pub fn aya::maps::hash_map::HashMap::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::insert(&mut self, key: impl core::borrow::Borrow, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::HashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K> -pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V> +pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::hash_map::HashMap +pub type aya::maps::hash_map::HashMap::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap::try_from(map: aya::maps::Map) -> core::result::Result impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap for aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::get(&self, key: &K) -> core::result::Result pub fn aya::maps::hash_map::HashMap::map(&self) -> &aya::maps::MapData -impl core::convert::TryFrom for aya::maps::hash_map::HashMap -pub type aya::maps::hash_map::HashMap::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> impl core::fmt::Debug for aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::hash_map::HashMap where K: core::marker::Send, T: core::marker::Send, V: core::marker::Send @@ -212,18 +212,18 @@ pub fn aya::maps::hash_map::PerCpuHashMap::keys(&self) -> aya::maps::Ma impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::insert(&mut self, key: impl core::borrow::Borrow, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::PerCpuHashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K> -pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V> +pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::hash_map::PerCpuHashMap +pub type aya::maps::hash_map::PerCpuHashMap::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap::try_from(map: aya::maps::Map) -> core::result::Result impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap> for aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::get(&self, key: &K) -> core::result::Result, aya::maps::MapError> pub fn aya::maps::hash_map::PerCpuHashMap::map(&self) -> &aya::maps::MapData -impl core::convert::TryFrom for aya::maps::hash_map::PerCpuHashMap -pub type aya::maps::hash_map::PerCpuHashMap::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> impl core::marker::Send for aya::maps::hash_map::PerCpuHashMap where K: core::marker::Send, T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::hash_map::PerCpuHashMap where K: core::marker::Sync, T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::hash_map::PerCpuHashMap where K: core::marker::Unpin, T: core::marker::Unpin, V: core::marker::Unpin @@ -291,18 +291,18 @@ pub fn aya::maps::lpm_trie::LpmTrie::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::insert(&mut self, key: &aya::maps::lpm_trie::Key, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::lpm_trie::LpmTrie::remove(&mut self, key: &aya::maps::lpm_trie::Key) -> core::result::Result<(), aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K> -pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V> +pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::lpm_trie::LpmTrie +pub type aya::maps::lpm_trie::LpmTrie::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie::try_from(map: aya::maps::Map) -> core::result::Result impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap, V> for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::get(&self, key: &aya::maps::lpm_trie::Key) -> core::result::Result pub fn aya::maps::lpm_trie::LpmTrie::map(&self) -> &aya::maps::MapData -impl core::convert::TryFrom for aya::maps::lpm_trie::LpmTrie -pub type aya::maps::lpm_trie::LpmTrie::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> impl core::fmt::Debug for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::lpm_trie::LpmTrie where K: core::marker::Send, T: core::marker::Send, V: core::marker::Send @@ -376,13 +376,13 @@ impl + core::borrow::Borrow::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::perf::AsyncPerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Sync for aya::maps::perf::AsyncPerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Unpin for aya::maps::perf::AsyncPerfEventArray @@ -464,13 +464,13 @@ impl + core::borrow::Borrow::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::PerfEventArray pub type aya::maps::perf::PerfEventArray::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::perf::PerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Sync for aya::maps::perf::PerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Unpin for aya::maps::perf::PerfEventArray @@ -528,13 +528,13 @@ pub fn aya::maps::queue::Queue::pop(&mut self, flags: u64) -> core::result pub fn aya::maps::queue::Queue::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V> pub type aya::maps::queue::Queue<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::queue::Queue<&'a mut aya::maps::MapData, V> pub type aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::queue::Queue pub type aya::maps::queue::Queue::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::queue::Queue where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::queue::Queue where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::queue::Queue where T: core::marker::Unpin, V: core::marker::Unpin @@ -568,16 +568,16 @@ pub fn aya::maps::SockHash::insert(&mut self pub fn aya::maps::SockHash::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V> pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockHash<&'a mut aya::maps::MapData, V> pub type aya::maps::SockHash<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::SockHash<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl, K: aya::Pod> aya::maps::IterableMap for aya::maps::SockHash pub fn aya::maps::SockHash::get(&self, key: &K) -> core::result::Result pub fn aya::maps::SockHash::map(&self) -> &aya::maps::MapData impl core::convert::TryFrom for aya::maps::SockHash pub type aya::maps::SockHash::Error = aya::maps::MapError -pub fn aya::maps::SockHash::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::SockHash where K: core::marker::Send, T: core::marker::Send impl core::marker::Sync for aya::maps::SockHash where K: core::marker::Sync, T: core::marker::Sync impl core::marker::Unpin for aya::maps::SockHash where K: core::marker::Unpin, T: core::marker::Unpin @@ -608,13 +608,13 @@ pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::resul pub fn aya::maps::SockMap::set(&mut self, index: u32, socket: &I, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError -pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockMap<&'a aya::maps::MapData> pub type aya::maps::SockMap<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockMap<&'a mut aya::maps::MapData> pub type aya::maps::SockMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::SockMap where T: core::marker::Send impl core::marker::Sync for aya::maps::SockMap where T: core::marker::Sync impl core::marker::Unpin for aya::maps::SockMap where T: core::marker::Unpin @@ -676,13 +676,13 @@ pub fn aya::maps::stack::Stack::pop(&mut self, flags: u64) -> core::result pub fn aya::maps::stack::Stack::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack::Stack<&'a mut aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::stack::Stack pub type aya::maps::stack::Stack::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::stack::Stack where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::stack::Stack where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::stack::Stack where T: core::marker::Unpin, V: core::marker::Unpin @@ -763,17 +763,17 @@ pub fn aya::maps::stack_trace::StackTraceMap::iter(&self) -> aya::maps::MapIt pub fn aya::maps::stack_trace::StackTraceMap::stack_ids(&self) -> aya::maps::MapKeys<'_, u32> impl core::convert::TryFrom for aya::maps::stack_trace::StackTraceMap pub type aya::maps::stack_trace::StackTraceMap::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result impl<'a, T: core::borrow::Borrow> core::iter::traits::collect::IntoIterator for &'a aya::maps::stack_trace::StackTraceMap pub type &'a aya::maps::stack_trace::StackTraceMap::IntoIter = aya::maps::MapIter<'a, u32, aya::maps::stack_trace::StackTrace, aya::maps::stack_trace::StackTraceMap> pub type &'a aya::maps::stack_trace::StackTraceMap::Item = core::result::Result<(u32, aya::maps::stack_trace::StackTrace), aya::maps::MapError> pub fn &'a aya::maps::stack_trace::StackTraceMap::into_iter(self) -> Self::IntoIter impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl> aya::maps::IterableMap for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core::result::Result pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData @@ -819,130 +819,130 @@ pub aya::maps::Map::StackTraceMap(aya::maps::MapData) pub aya::maps::Map::Unsupported(aya::maps::MapData) impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError -pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::perf::PerfEventArray pub type aya::maps::perf::PerfEventArray::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::stack_trace::StackTraceMap pub type aya::maps::stack_trace::StackTraceMap::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K> -pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K> -pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K> -pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V> +pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V> +pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V> +pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V> pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V> pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::array::Array<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V> pub type aya::maps::queue::Queue<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockHash<&'a mut aya::maps::MapData, V> pub type aya::maps::SockHash<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::SockHash<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::array::Array<&'a mut aya::maps::MapData, V> pub type aya::maps::array::Array<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::array::Array<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::queue::Queue<&'a mut aya::maps::MapData, V> pub type aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack::Stack<&'a mut aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ProgramArray<&'a aya::maps::MapData> pub type aya::maps::ProgramArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockMap<&'a aya::maps::MapData> pub type aya::maps::SockMap<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ProgramArray<&'a mut aya::maps::MapData> pub type aya::maps::ProgramArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockMap<&'a mut aya::maps::MapData> pub type aya::maps::SockMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl core::convert::TryFrom for aya::maps::hash_map::HashMap -pub type aya::maps::hash_map::HashMap::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl core::convert::TryFrom for aya::maps::hash_map::PerCpuHashMap -pub type aya::maps::hash_map::PerCpuHashMap::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl core::convert::TryFrom for aya::maps::lpm_trie::LpmTrie -pub type aya::maps::lpm_trie::LpmTrie::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::hash_map::HashMap +pub type aya::maps::hash_map::HashMap::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::hash_map::PerCpuHashMap +pub type aya::maps::hash_map::PerCpuHashMap::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::lpm_trie::LpmTrie +pub type aya::maps::lpm_trie::LpmTrie::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::PerCpuArray pub type aya::maps::PerCpuArray::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::SockHash pub type aya::maps::SockHash::Error = aya::maps::MapError -pub fn aya::maps::SockHash::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::array::Array pub type aya::maps::array::Array::Error = aya::maps::MapError -pub fn aya::maps::array::Array::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::bloom_filter::BloomFilter pub type aya::maps::bloom_filter::BloomFilter::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::queue::Queue pub type aya::maps::queue::Queue::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::stack::Stack pub type aya::maps::stack::Stack::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack::try_from(map: aya::maps::Map) -> core::result::Result impl core::fmt::Debug for aya::maps::Map pub fn aya::maps::Map::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::Map @@ -1035,16 +1035,16 @@ impl, V: aya::Pod> aya::maps::arr pub fn aya::maps::array::Array::set(&mut self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V> pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::array::Array<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::array::Array<&'a mut aya::maps::MapData, V> pub type aya::maps::array::Array<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::array::Array<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl, V: aya::Pod> aya::maps::IterableMap for aya::maps::array::Array pub fn aya::maps::array::Array::get(&self, index: &u32) -> core::result::Result pub fn aya::maps::array::Array::map(&self) -> &aya::maps::MapData impl core::convert::TryFrom for aya::maps::array::Array pub type aya::maps::array::Array::Error = aya::maps::MapError -pub fn aya::maps::array::Array::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::array::Array::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::array::Array where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::array::Array where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::array::Array where T: core::marker::Unpin, V: core::marker::Unpin @@ -1071,13 +1071,13 @@ impl + core::borrow::Borrow::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::perf::AsyncPerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Sync for aya::maps::perf::AsyncPerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Unpin for aya::maps::perf::AsyncPerfEventArray @@ -1106,13 +1106,13 @@ impl, V: aya::Pod> aya::maps::blo pub fn aya::maps::bloom_filter::BloomFilter::insert(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::bloom_filter::BloomFilter pub type aya::maps::bloom_filter::BloomFilter::Error = aya::maps::MapError -pub fn aya::maps::bloom_filter::BloomFilter::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::bloom_filter::BloomFilter::try_from(map: aya::maps::Map) -> core::result::Result impl core::fmt::Debug for aya::maps::bloom_filter::BloomFilter pub fn aya::maps::bloom_filter::BloomFilter::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::bloom_filter::BloomFilter where T: core::marker::Send, V: core::marker::Send @@ -1144,18 +1144,18 @@ pub fn aya::maps::hash_map::HashMap::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::insert(&mut self, key: impl core::borrow::Borrow, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::HashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K> -pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V> +pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::hash_map::HashMap +pub type aya::maps::hash_map::HashMap::Error = aya::maps::MapError +pub fn aya::maps::hash_map::HashMap::try_from(map: aya::maps::Map) -> core::result::Result impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap for aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::get(&self, key: &K) -> core::result::Result pub fn aya::maps::hash_map::HashMap::map(&self) -> &aya::maps::MapData -impl core::convert::TryFrom for aya::maps::hash_map::HashMap -pub type aya::maps::hash_map::HashMap::Error = aya::maps::MapError -pub fn aya::maps::hash_map::HashMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> impl core::fmt::Debug for aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::hash_map::HashMap where K: core::marker::Send, T: core::marker::Send, V: core::marker::Send @@ -1187,18 +1187,18 @@ pub fn aya::maps::lpm_trie::LpmTrie::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::insert(&mut self, key: &aya::maps::lpm_trie::Key, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::lpm_trie::LpmTrie::remove(&mut self, key: &aya::maps::lpm_trie::Key) -> core::result::Result<(), aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K> -pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V> +pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::lpm_trie::LpmTrie +pub type aya::maps::lpm_trie::LpmTrie::Error = aya::maps::MapError +pub fn aya::maps::lpm_trie::LpmTrie::try_from(map: aya::maps::Map) -> core::result::Result impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap, V> for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::get(&self, key: &aya::maps::lpm_trie::Key) -> core::result::Result pub fn aya::maps::lpm_trie::LpmTrie::map(&self) -> &aya::maps::MapData -impl core::convert::TryFrom for aya::maps::lpm_trie::LpmTrie -pub type aya::maps::lpm_trie::LpmTrie::Error = aya::maps::MapError -pub fn aya::maps::lpm_trie::LpmTrie::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> impl core::fmt::Debug for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::lpm_trie::LpmTrie where K: core::marker::Send, T: core::marker::Send, V: core::marker::Send @@ -1351,16 +1351,16 @@ impl, V: aya::Pod> aya::maps::Per pub fn aya::maps::PerCpuArray::set(&mut self, index: u32, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl, V: aya::Pod> aya::maps::IterableMap> for aya::maps::PerCpuArray pub fn aya::maps::PerCpuArray::get(&self, index: &u32) -> core::result::Result, aya::maps::MapError> pub fn aya::maps::PerCpuArray::map(&self) -> &aya::maps::MapData impl core::convert::TryFrom for aya::maps::PerCpuArray pub type aya::maps::PerCpuArray::Error = aya::maps::MapError -pub fn aya::maps::PerCpuArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::PerCpuArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::PerCpuArray where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::PerCpuArray where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::PerCpuArray where T: core::marker::Unpin, V: core::marker::Unpin @@ -1390,18 +1390,18 @@ pub fn aya::maps::hash_map::PerCpuHashMap::keys(&self) -> aya::maps::Ma impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::insert(&mut self, key: impl core::borrow::Borrow, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::PerCpuHashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K> -pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, V, K>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> -impl<'a, V: aya::Pod, K: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K> -pub type aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K>::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, V, K>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V> +pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V> +pub type aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V>::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap<&'a mut aya::maps::MapData, K, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::hash_map::PerCpuHashMap +pub type aya::maps::hash_map::PerCpuHashMap::Error = aya::maps::MapError +pub fn aya::maps::hash_map::PerCpuHashMap::try_from(map: aya::maps::Map) -> core::result::Result impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap> for aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::get(&self, key: &K) -> core::result::Result, aya::maps::MapError> pub fn aya::maps::hash_map::PerCpuHashMap::map(&self) -> &aya::maps::MapData -impl core::convert::TryFrom for aya::maps::hash_map::PerCpuHashMap -pub type aya::maps::hash_map::PerCpuHashMap::Error = aya::maps::MapError -pub fn aya::maps::hash_map::PerCpuHashMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> impl core::marker::Send for aya::maps::hash_map::PerCpuHashMap where K: core::marker::Send, T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::hash_map::PerCpuHashMap where K: core::marker::Sync, T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::hash_map::PerCpuHashMap where K: core::marker::Unpin, T: core::marker::Unpin, V: core::marker::Unpin @@ -1464,13 +1464,13 @@ impl + core::borrow::Borrow::open(&mut self, index: u32, page_count: core::option::Option) -> core::result::Result, aya::maps::perf::PerfBufferError> impl core::convert::TryFrom for aya::maps::perf::PerfEventArray pub type aya::maps::perf::PerfEventArray::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::perf::PerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Sync for aya::maps::perf::PerfEventArray where T: core::marker::Send + core::marker::Sync impl core::marker::Unpin for aya::maps::perf::PerfEventArray @@ -1500,13 +1500,13 @@ pub fn aya::maps::ProgramArray::clear_index(&mut self, index: &u32) -> core:: pub fn aya::maps::ProgramArray::set(&mut self, index: u32, program: &aya::programs::ProgramFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ProgramArray<&'a aya::maps::MapData> pub type aya::maps::ProgramArray<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ProgramArray<&'a mut aya::maps::MapData> pub type aya::maps::ProgramArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::ProgramArray where T: core::marker::Send impl core::marker::Sync for aya::maps::ProgramArray where T: core::marker::Sync impl core::marker::Unpin for aya::maps::ProgramArray where T: core::marker::Unpin @@ -1536,13 +1536,13 @@ pub fn aya::maps::queue::Queue::pop(&mut self, flags: u64) -> core::result pub fn aya::maps::queue::Queue::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V> pub type aya::maps::queue::Queue<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::queue::Queue<&'a mut aya::maps::MapData, V> pub type aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::queue::Queue pub type aya::maps::queue::Queue::Error = aya::maps::MapError -pub fn aya::maps::queue::Queue::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::queue::Queue::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::queue::Queue where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::queue::Queue where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::queue::Queue where T: core::marker::Unpin, V: core::marker::Unpin @@ -1575,16 +1575,16 @@ pub fn aya::maps::SockHash::insert(&mut self pub fn aya::maps::SockHash::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V> pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockHash<&'a mut aya::maps::MapData, V> pub type aya::maps::SockHash<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::SockHash<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl, K: aya::Pod> aya::maps::IterableMap for aya::maps::SockHash pub fn aya::maps::SockHash::get(&self, key: &K) -> core::result::Result pub fn aya::maps::SockHash::map(&self) -> &aya::maps::MapData impl core::convert::TryFrom for aya::maps::SockHash pub type aya::maps::SockHash::Error = aya::maps::MapError -pub fn aya::maps::SockHash::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockHash::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::SockHash where K: core::marker::Send, T: core::marker::Send impl core::marker::Sync for aya::maps::SockHash where K: core::marker::Sync, T: core::marker::Sync impl core::marker::Unpin for aya::maps::SockHash where K: core::marker::Unpin, T: core::marker::Unpin @@ -1615,13 +1615,13 @@ pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::resul pub fn aya::maps::SockMap::set(&mut self, index: u32, socket: &I, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError -pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockMap<&'a aya::maps::MapData> pub type aya::maps::SockMap<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockMap<&'a mut aya::maps::MapData> pub type aya::maps::SockMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::SockMap where T: core::marker::Send impl core::marker::Sync for aya::maps::SockMap where T: core::marker::Sync impl core::marker::Unpin for aya::maps::SockMap where T: core::marker::Unpin @@ -1651,13 +1651,13 @@ pub fn aya::maps::stack::Stack::pop(&mut self, flags: u64) -> core::result pub fn aya::maps::stack::Stack::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack::Stack<&'a mut aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::stack::Stack pub type aya::maps::stack::Stack::Error = aya::maps::MapError -pub fn aya::maps::stack::Stack::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack::Stack::try_from(map: aya::maps::Map) -> core::result::Result impl core::marker::Send for aya::maps::stack::Stack where T: core::marker::Send, V: core::marker::Send impl core::marker::Sync for aya::maps::stack::Stack where T: core::marker::Sync, V: core::marker::Sync impl core::marker::Unpin for aya::maps::stack::Stack where T: core::marker::Unpin, V: core::marker::Unpin @@ -1686,17 +1686,17 @@ pub fn aya::maps::stack_trace::StackTraceMap::iter(&self) -> aya::maps::MapIt pub fn aya::maps::stack_trace::StackTraceMap::stack_ids(&self) -> aya::maps::MapKeys<'_, u32> impl core::convert::TryFrom for aya::maps::stack_trace::StackTraceMap pub type aya::maps::stack_trace::StackTraceMap::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result impl<'a, T: core::borrow::Borrow> core::iter::traits::collect::IntoIterator for &'a aya::maps::stack_trace::StackTraceMap pub type &'a aya::maps::stack_trace::StackTraceMap::IntoIter = aya::maps::MapIter<'a, u32, aya::maps::stack_trace::StackTrace, aya::maps::stack_trace::StackTraceMap> pub type &'a aya::maps::stack_trace::StackTraceMap::Item = core::result::Result<(u32, aya::maps::stack_trace::StackTrace), aya::maps::MapError> pub fn &'a aya::maps::stack_trace::StackTraceMap::into_iter(self) -> Self::IntoIter impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError -pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result, aya::maps::MapError> +pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl> aya::maps::IterableMap for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core::result::Result pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData From 172859c66b25fbfa0d6d2af38ba7dd3f8e99d999 Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Fri, 1 Sep 2023 10:40:36 -0400 Subject: [PATCH 20/95] aya/maps: support TryFrom for LRU hash maps The macro to implement TryFrom for MapData didn't have the ability to specify that more than one variant of MapData can be valid for a single map implementation. Support for new syntax was added to the macro so that the implementation can succeed for both valid variants in the HashMap and PerCpuHashMap impl. Fixes #636 --- aya/src/maps/hash_map/hash_map.rs | 54 +++++------------------ aya/src/maps/hash_map/mod.rs | 38 ++++++++++++++++ aya/src/maps/hash_map/per_cpu_hash_map.rs | 27 ++++++++++++ aya/src/maps/mod.rs | 20 ++++----- 4 files changed, 86 insertions(+), 53 deletions(-) diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 1f8a2f9c..8d091582 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -108,43 +108,22 @@ mod tests { use libc::{EFAULT, ENOENT}; use crate::{ - bpf_map_def, generated::{ bpf_attr, bpf_cmd, bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH}, }, - maps::{Map, MapData}, - obj::{self, maps::LegacyMap, BpfSectionKind}, + maps::Map, + obj, sys::{override_syscall, SysResult, Syscall}, }; - use super::*; + use super::{ + super::test_utils::{self, new_map}, + *, + }; fn new_obj_map() -> obj::Map { - obj::Map::Legacy(LegacyMap { - def: bpf_map_def { - map_type: BPF_MAP_TYPE_HASH as u32, - key_size: 4, - value_size: 4, - max_entries: 1024, - ..Default::default() - }, - section_index: 0, - section_kind: BpfSectionKind::Maps, - data: Vec::new(), - symbol_index: None, - }) - } - - fn new_map(obj: obj::Map) -> MapData { - override_syscall(|call| match call { - Syscall::Bpf { - cmd: bpf_cmd::BPF_MAP_CREATE, - .. - } => Ok(1337), - call => panic!("unexpected syscall {:?}", call), - }); - MapData::create(obj, "foo", None).unwrap() + test_utils::new_obj_map(BPF_MAP_TYPE_HASH) } fn sys_error(value: i32) -> SysResult { @@ -213,21 +192,10 @@ mod tests { #[test] fn test_try_from_ok_lru() { - let map = new_map(obj::Map::Legacy(LegacyMap { - def: bpf_map_def { - map_type: BPF_MAP_TYPE_LRU_HASH as u32, - key_size: 4, - value_size: 4, - max_entries: 1024, - ..Default::default() - }, - section_index: 0, - section_kind: BpfSectionKind::Maps, - symbol_index: None, - data: Vec::new(), - })); - let map = Map::HashMap(map); - + let map_data = || new_map(test_utils::new_obj_map(BPF_MAP_TYPE_LRU_HASH)); + let map = Map::HashMap(map_data()); + assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok()); + let map = Map::LruHashMap(map_data()); assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok()) } diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index 87fc0d70..5e18cb19 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -41,3 +41,41 @@ pub(crate) fn remove(map: &MapData, key: &K) -> Result<(), MapError> { .into() }) } + +#[cfg(test)] +mod test_utils { + use crate::{ + bpf_map_def, + generated::{bpf_cmd, bpf_map_type}, + maps::MapData, + obj::{self, maps::LegacyMap, BpfSectionKind}, + sys::{override_syscall, Syscall}, + }; + + pub(super) fn new_map(obj: obj::Map) -> MapData { + override_syscall(|call| match call { + Syscall::Bpf { + cmd: bpf_cmd::BPF_MAP_CREATE, + .. + } => Ok(1337), + call => panic!("unexpected syscall {:?}", call), + }); + MapData::create(obj, "foo", None).unwrap() + } + + pub(super) fn new_obj_map(map_type: bpf_map_type) -> obj::Map { + obj::Map::Legacy(LegacyMap { + def: bpf_map_def { + map_type: map_type as u32, + key_size: 4, + value_size: 4, + max_entries: 1024, + ..Default::default() + }, + section_index: 0, + section_kind: BpfSectionKind::Maps, + data: Vec::new(), + symbol_index: None, + }) + } +} diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index 5ae177f2..aabc71f6 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -146,3 +146,30 @@ impl, K: Pod, V: Pod> IterableMap> Self::get(self, key, 0) } } + +#[cfg(test)] +mod tests { + use crate::{ + generated::bpf_map_type::{BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH}, + maps::Map, + }; + + use super::{super::test_utils, *}; + + #[test] + fn test_try_from_ok() { + let map = Map::PerCpuHashMap(test_utils::new_map(test_utils::new_obj_map( + BPF_MAP_TYPE_PERCPU_HASH, + ))); + assert!(PerCpuHashMap::<_, u32, u32>::try_from(&map).is_ok()) + } + #[test] + fn test_try_from_ok_lru() { + let map_data = + || test_utils::new_map(test_utils::new_obj_map(BPF_MAP_TYPE_LRU_PERCPU_HASH)); + let map = Map::PerCpuHashMap(map_data()); + assert!(PerCpuHashMap::<_, u32, u32>::try_from(&map).is_ok()); + let map = Map::PerCpuLruHashMap(map_data()); + assert!(PerCpuHashMap::<_, u32, u32>::try_from(&map).is_ok()) + } +} diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index cd082530..4d8183e9 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -291,9 +291,9 @@ macro_rules! impl_try_from_map { // rather than the repeated idents used later because the macro language does not allow one // repetition to be pasted inside another. ($ty_param:tt { - $($ty:ident $(from $variant:ident)?),+ $(,)? + $($ty:ident $(from $($variant:ident)|+)?),+ $(,)? }) => { - $(impl_try_from_map!(<$ty_param> $ty $(from $variant)?);)+ + $(impl_try_from_map!(<$ty_param> $ty $(from $($variant)|+)?);)+ }; // Add the "from $variant" using $ty as the default if it is missing. (<$ty_param:tt> $ty:ident) => { @@ -301,17 +301,17 @@ macro_rules! impl_try_from_map { }; // Dispatch for each of the lifetimes. ( - <($($ty_param:ident),*)> $ty:ident from $variant:ident + <($($ty_param:ident),*)> $ty:ident from $($variant:ident)|+ ) => { - impl_try_from_map!(<'a> ($($ty_param),*) $ty from $variant); - impl_try_from_map!(<'a mut> ($($ty_param),*) $ty from $variant); - impl_try_from_map!(<> ($($ty_param),*) $ty from $variant); + impl_try_from_map!(<'a> ($($ty_param),*) $ty from $($variant)|+); + impl_try_from_map!(<'a mut> ($($ty_param),*) $ty from $($variant)|+); + impl_try_from_map!(<> ($($ty_param),*) $ty from $($variant)|+); }; // An individual impl. ( <$($l:lifetime $($m:ident)?)?> ($($ty_param:ident),*) - $ty:ident from $variant:ident + $ty:ident from $($variant:ident)|+ ) => { impl<$($l,)? $($ty_param: Pod),*> TryFrom<$(&$l $($m)?)? Map> for $ty<$(&$l $($m)?)? MapData, $($ty_param),*> @@ -320,7 +320,7 @@ macro_rules! impl_try_from_map { fn try_from(map: $(&$l $($m)?)? Map) -> Result { match map { - Map::$variant(map_data) => Self::new(map_data), + $(Map::$variant(map_data) => Self::new(map_data),)+ map => Err(MapError::InvalidMapType { map_type: map.map_type() }), @@ -353,8 +353,8 @@ impl_try_from_map!((V) { }); impl_try_from_map!((K, V) { - HashMap, - PerCpuHashMap, + HashMap from HashMap|LruHashMap, + PerCpuHashMap from PerCpuHashMap|PerCpuLruHashMap, LpmTrie, }); From 385b04c12be47ff5afbb7275f8e0648d1286c43b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:05:17 +0000 Subject: [PATCH 21/95] build(deps): bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/gen.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23fda7fa..281a0d82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: @@ -66,7 +66,7 @@ jobs: - riscv64gc-unknown-linux-gnu runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: @@ -119,7 +119,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: @@ -151,7 +151,7 @@ jobs: - ubuntu-22.04 runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/gen.yml b/.github/workflows/gen.yml index 37506c6a..30763c41 100644 --- a/.github/workflows/gen.yml +++ b/.github/workflows/gen.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 096442cf..6cea2982 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 From 1aa1dc53db5bc6380c0b6ddfcc9519c94bcaff1e Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 5 Sep 2023 11:59:01 -0400 Subject: [PATCH 22/95] README: fix build badge Make it a link while I'm here. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de31ec77..9b4e2b42 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,15 @@ [![Crates.io][crates-badge]][crates-url] ![License][license-badge] -![Build status][build-badge] +[![Build status][build-badge]][build-url] [![Book][book-badge]][book-url] [crates-badge]: https://img.shields.io/crates/v/aya.svg?style=for-the-badge&logo=rust [crates-url]: https://crates.io/crates/aya [license-badge]: https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=for-the-badge -[build-badge]: https://img.shields.io/github/actions/workflow/status/aya-rs/aya/build-aya.yml?branch=main&style=for-the-badge +[build-badge]: https://img.shields.io/github/actions/workflow/status/aya-rs/aya/ci.yml?style=for-the-badge +[build-url]: https://github.com/aya-rs/aya/actions/workflows/ci.yml [book-badge]: https://img.shields.io/badge/read%20the-book-9cf.svg?style=for-the-badge&logo=mdbook [book-url]: https://aya-rs.dev/book From 81f634abc688fc72dafd2ee379d763a663d0d33d Mon Sep 17 00:00:00 2001 From: astoycos Date: Mon, 11 Sep 2023 09:54:03 -0400 Subject: [PATCH 23/95] aya/ci: fixup broken debian kernel image url Signed-off-by: astoycos --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 281a0d82..491fa966 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -236,7 +236,7 @@ jobs: # linux-image-5.10.0-23-cloud-amd64-unsigned_5.10.179-3_amd64.deb \ printf '%s\0' \ linux-image-6.1.0-10-cloud-amd64-unsigned_6.1.38-2_amd64.deb \ - linux-image-6.4.0-3-cloud-amd64-unsigned_6.4.11-1_amd64.deb \ + linux-image-6.4.0-4-cloud-amd64-unsigned_6.4.13-1_amd64.deb \ | xargs -0 -t -P0 -I {} wget -nd -nv -P test/.tmp/debian-kernels/amd64 ftp://ftp.us.debian.org/debian/pool/main/l/linux/{} - name: Extract debian kernels From 0a144a0e69bc136fd8c1aa9f3712a37855be545a Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 11 Sep 2023 10:37:57 -0400 Subject: [PATCH 24/95] integration-test: remove all sleeps --- test/integration-test/bpf/multimap-btf.bpf.c | 2 +- test/integration-test/src/tests/load.rs | 13 ++++++++++--- test/integration-test/src/tests/rbpf.rs | 2 +- test/integration-test/src/tests/relocations.rs | 4 ---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/test/integration-test/bpf/multimap-btf.bpf.c b/test/integration-test/bpf/multimap-btf.bpf.c index 2bd7978b..f6d34bcf 100644 --- a/test/integration-test/bpf/multimap-btf.bpf.c +++ b/test/integration-test/bpf/multimap-btf.bpf.c @@ -17,7 +17,7 @@ struct { __uint(max_entries, 1); } map_2 SEC(".maps"); -SEC("tracepoint") +SEC("uprobe") int bpf_prog(void *ctx) { __u32 key = 0; __u64 twenty_four = 24; diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 0b0d1532..4c99a008 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -36,11 +36,12 @@ fn multiple_btf_maps() { let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); - let prog: &mut TracePoint = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); + let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); prog.load().unwrap(); - prog.attach("sched", "sched_switch").unwrap(); + prog.attach(Some("trigger_bpf_program"), 0, "/proc/self/exe", None) + .unwrap(); - thread::sleep(time::Duration::from_secs(3)); + trigger_bpf_program(); let key = 0; let val_1 = map_1.get(&key, 0).unwrap(); @@ -50,6 +51,12 @@ fn multiple_btf_maps() { assert_eq!(val_2, 42); } +#[no_mangle] +#[inline(never)] +pub extern "C" fn trigger_bpf_program() { + core::hint::black_box(trigger_bpf_program); +} + fn poll_loaded_program_id(name: &str) -> impl Iterator> + '_ { std::iter::once(true) .chain(std::iter::repeat(false)) diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index 0a85adbf..da44863f 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -40,7 +40,7 @@ fn use_map_with_rbpf() { assert_eq!(object.programs.len(), 1); assert_matches!( object.programs["bpf_prog"].section, - ProgramSection::TracePoint { .. } + ProgramSection::UProbe { .. } ); // Initialize maps: diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 1b550e9f..9e7d5719 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,5 +1,3 @@ -use std::time::Duration; - use aya::{programs::UProbe, Bpf}; #[test] @@ -7,7 +5,6 @@ fn relocations() { let bpf = load_and_attach("test_64_32_call_relocs", crate::RELOCATIONS); trigger_relocations_program(); - std::thread::sleep(Duration::from_millis(100)); let m = aya::maps::Array::<_, u64>::try_from(bpf.map("RESULTS").unwrap()).unwrap(); assert_eq!(m.get(&0, 0).unwrap(), 1); @@ -24,7 +21,6 @@ fn text_64_64_reloc() { m.set(1, 2, 0).unwrap(); trigger_relocations_program(); - std::thread::sleep(Duration::from_millis(100)); assert_eq!(m.get(&0, 0).unwrap(), 2); assert_eq!(m.get(&1, 0).unwrap(), 3); From 968609228086a90794b5af1a0493c0aec0cb1c79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:50:26 +0000 Subject: [PATCH 25/95] build(deps): update bindgen requirement from 0.66 to 0.68 Updates the requirements on [bindgen](https://github.com/rust-lang/rust-bindgen) to permit the latest version. - [Release notes](https://github.com/rust-lang/rust-bindgen/releases) - [Changelog](https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.66.0...v0.66.1) --- updated-dependencies: - dependency-name: bindgen dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8ad69dfc..e31471aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ aya-log-common = { path = "aya-log-common", version = "0.1.13", default-features aya-log-parser = { path = "aya-log-parser", default-features = false } aya-obj = { path = "aya-obj", version = "0.1.0", default-features = false } aya-tool = { path = "aya-tool", default-features = false } -bindgen = { version = "0.66", default-features = false } +bindgen = { version = "0.68", default-features = false } bitflags = { version = "2.2.1", default-features = false } bytes = { version = "1", default-features = false } cargo_metadata = { version = "0.17.0", default-features = false } From 6ab7475fa66d1b8155487dfc548645e2b8ee20c6 Mon Sep 17 00:00:00 2001 From: astoycos Date: Thu, 7 Sep 2023 14:32:33 -0400 Subject: [PATCH 26/95] aya: add program_info() api to program Add a new api to the outer level `Program` structure which allows users to get the program's kernel info before casting it to an explicit program variant. Signed-off-by: astoycos --- aya/src/programs/mod.rs | 39 ++++++++- xtask/public-api/aya.txt | 169 ++++++++++++++++++++------------------- 2 files changed, 121 insertions(+), 87 deletions(-) diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 616244e0..4b620561 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -410,6 +410,39 @@ impl Program { Self::CgroupDevice(p) => p.fd(), } } + + /// Returns information about a loaded program with the [`ProgramInfo`] structure. + /// + /// This information is populated at load time by the kernel and can be used + /// to get kernel details for a given [`Program`]. + pub fn info(&self) -> Result { + match self { + Self::KProbe(p) => p.info(), + Self::UProbe(p) => p.info(), + Self::TracePoint(p) => p.info(), + Self::SocketFilter(p) => p.info(), + Self::Xdp(p) => p.info(), + Self::SkMsg(p) => p.info(), + Self::SkSkb(p) => p.info(), + Self::SockOps(p) => p.info(), + Self::SchedClassifier(p) => p.info(), + Self::CgroupSkb(p) => p.info(), + Self::CgroupSysctl(p) => p.info(), + Self::CgroupSockopt(p) => p.info(), + Self::LircMode2(p) => p.info(), + Self::PerfEvent(p) => p.info(), + Self::RawTracePoint(p) => p.info(), + Self::Lsm(p) => p.info(), + Self::BtfTracePoint(p) => p.info(), + Self::FEntry(p) => p.info(), + Self::FExit(p) => p.info(), + Self::Extension(p) => p.info(), + Self::CgroupSockAddr(p) => p.info(), + Self::SkLookup(p) => p.info(), + Self::CgroupSock(p) => p.info(), + Self::CgroupDevice(p) => p.info(), + } + } } #[derive(Debug)] @@ -923,12 +956,12 @@ impl_try_from_program!( /// This information is populated at load time by the kernel and can be used /// to correlate a given [`Program`] to it's corresponding [`ProgramInfo`] /// metadata. -macro_rules! impl_program_info { +macro_rules! impl_info { ($($struct_name:ident),+ $(,)?) => { $( impl $struct_name { /// Returns the file descriptor of this Program. - pub fn program_info(&self) -> Result { + pub fn info(&self) -> Result { let ProgramFd(fd) = self.fd()?; ProgramInfo::new_from_fd(fd.as_fd()) @@ -938,7 +971,7 @@ macro_rules! impl_program_info { } } -impl_program_info!( +impl_info!( KProbe, UProbe, TracePoint, diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index dfbdde83..6c99b7d8 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1802,11 +1802,11 @@ pub fn aya::programs::cgroup_device::CgroupDevice::fd(&self) -> core::result::Re impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_device::CgroupDevice +pub fn aya::programs::cgroup_device::CgroupDevice::info(&self) -> core::result::Result +impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_device::CgroupDevice::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_device::CgroupDevice -pub fn aya::programs::cgroup_device::CgroupDevice::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::drop(&mut self) @@ -1945,11 +1945,11 @@ pub fn aya::programs::cgroup_skb::CgroupSkb::take_link(&mut self, link_id: aya:: impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_skb::CgroupSkb +pub fn aya::programs::cgroup_skb::CgroupSkb::info(&self) -> core::result::Result +impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_skb::CgroupSkb::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_skb::CgroupSkb -pub fn aya::programs::cgroup_skb::CgroupSkb::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::drop(&mut self) @@ -2055,11 +2055,11 @@ pub fn aya::programs::cgroup_sock::CgroupSock::take_link(&mut self, link_id: aya impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock::CgroupSock +pub fn aya::programs::cgroup_sock::CgroupSock::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock::CgroupSock::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock::CgroupSock -pub fn aya::programs::cgroup_sock::CgroupSock::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::drop(&mut self) @@ -2165,11 +2165,11 @@ pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::take_link(&mut self, lin impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock_addr::CgroupSockAddr +pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock_addr::CgroupSockAddr -pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::drop(&mut self) @@ -2275,11 +2275,11 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockopt::take_link(&mut self, link_i impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sockopt::CgroupSockopt +pub fn aya::programs::cgroup_sockopt::CgroupSockopt::info(&self) -> core::result::Result +impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sockopt::CgroupSockopt -pub fn aya::programs::cgroup_sockopt::CgroupSockopt::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::drop(&mut self) @@ -2385,11 +2385,11 @@ pub fn aya::programs::cgroup_sysctl::CgroupSysctl::fd(&self) -> core::result::Re impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_sysctl::CgroupSysctl +pub fn aya::programs::cgroup_sysctl::CgroupSysctl::info(&self) -> core::result::Result +impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sysctl::CgroupSysctl -pub fn aya::programs::cgroup_sysctl::CgroupSysctl::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::drop(&mut self) @@ -2528,11 +2528,11 @@ pub fn aya::programs::extension::Extension::fd(&self) -> core::result::Result<&a impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::from_pin>(path: P) -> core::result::Result impl aya::programs::extension::Extension +pub fn aya::programs::extension::Extension::info(&self) -> core::result::Result +impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::extension::Extension::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::extension::Extension -pub fn aya::programs::extension::Extension::program_info(&self) -> core::result::Result -impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::extension::Extension pub fn aya::programs::extension::Extension::drop(&mut self) @@ -2642,11 +2642,11 @@ pub fn aya::programs::fentry::FEntry::fd(&self) -> core::result::Result<&aya::pr impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::from_pin>(path: P) -> core::result::Result impl aya::programs::fentry::FEntry +pub fn aya::programs::fentry::FEntry::info(&self) -> core::result::Result +impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fentry::FEntry::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fentry::FEntry -pub fn aya::programs::fentry::FEntry::program_info(&self) -> core::result::Result -impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::drop(&mut self) @@ -2756,11 +2756,11 @@ pub fn aya::programs::fexit::FExit::fd(&self) -> core::result::Result<&aya::prog impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::from_pin>(path: P) -> core::result::Result impl aya::programs::fexit::FExit +pub fn aya::programs::fexit::FExit::info(&self) -> core::result::Result +impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fexit::FExit::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fexit::FExit -pub fn aya::programs::fexit::FExit::program_info(&self) -> core::result::Result -impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::drop(&mut self) @@ -2905,11 +2905,11 @@ pub fn aya::programs::kprobe::KProbe::take_link(&mut self, link_id: aya::program impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::kprobe::KProbe +pub fn aya::programs::kprobe::KProbe::info(&self) -> core::result::Result +impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::kprobe::KProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::kprobe::KProbe -pub fn aya::programs::kprobe::KProbe::program_info(&self) -> core::result::Result -impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::drop(&mut self) @@ -3405,11 +3405,11 @@ pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<& impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::from_pin>(path: P) -> core::result::Result impl aya::programs::lirc_mode2::LircMode2 +pub fn aya::programs::lirc_mode2::LircMode2::info(&self) -> core::result::Result +impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lirc_mode2::LircMode2::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lirc_mode2::LircMode2 -pub fn aya::programs::lirc_mode2::LircMode2::program_info(&self) -> core::result::Result -impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::drop(&mut self) @@ -3454,11 +3454,11 @@ pub fn aya::programs::lsm::Lsm::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::from_pin>(path: P) -> core::result::Result impl aya::programs::lsm::Lsm +pub fn aya::programs::lsm::Lsm::info(&self) -> core::result::Result +impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lsm::Lsm::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lsm::Lsm -pub fn aya::programs::lsm::Lsm::program_info(&self) -> core::result::Result -impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::drop(&mut self) @@ -3741,11 +3741,11 @@ pub fn aya::programs::perf_event::PerfEvent::fd(&self) -> core::result::Result<& impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::from_pin>(path: P) -> core::result::Result impl aya::programs::perf_event::PerfEvent +pub fn aya::programs::perf_event::PerfEvent::info(&self) -> core::result::Result +impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::perf_event::PerfEvent::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::perf_event::PerfEvent -pub fn aya::programs::perf_event::PerfEvent::program_info(&self) -> core::result::Result -impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::drop(&mut self) @@ -3933,11 +3933,11 @@ pub fn aya::programs::tc::SchedClassifier::take_link(&mut self, link_id: aya::pr impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::tc::SchedClassifier +pub fn aya::programs::tc::SchedClassifier::info(&self) -> core::result::Result +impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tc::SchedClassifier::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tc::SchedClassifier -pub fn aya::programs::tc::SchedClassifier::program_info(&self) -> core::result::Result -impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::drop(&mut self) @@ -4075,11 +4075,11 @@ pub fn aya::programs::tp_btf::BtfTracePoint::fd(&self) -> core::result::Result<& impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::tp_btf::BtfTracePoint +pub fn aya::programs::tp_btf::BtfTracePoint::info(&self) -> core::result::Result +impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tp_btf::BtfTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tp_btf::BtfTracePoint -pub fn aya::programs::tp_btf::BtfTracePoint::program_info(&self) -> core::result::Result -impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::drop(&mut self) @@ -4224,11 +4224,11 @@ pub fn aya::programs::trace_point::TracePoint::fd(&self) -> core::result::Result impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::trace_point::TracePoint +pub fn aya::programs::trace_point::TracePoint::info(&self) -> core::result::Result +impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::trace_point::TracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::trace_point::TracePoint -pub fn aya::programs::trace_point::TracePoint::program_info(&self) -> core::result::Result -impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::drop(&mut self) @@ -4382,11 +4382,11 @@ pub fn aya::programs::uprobe::UProbe::take_link(&mut self, link_id: aya::program impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::uprobe::UProbe +pub fn aya::programs::uprobe::UProbe::info(&self) -> core::result::Result +impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::uprobe::UProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::uprobe::UProbe -pub fn aya::programs::uprobe::UProbe::program_info(&self) -> core::result::Result -impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::drop(&mut self) @@ -4534,11 +4534,11 @@ pub fn aya::programs::xdp::Xdp::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::from_pin>(path: P) -> core::result::Result impl aya::programs::xdp::Xdp +pub fn aya::programs::xdp::Xdp::info(&self) -> core::result::Result +impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::xdp::Xdp::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::program_info(&self) -> core::result::Result -impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::drop(&mut self) @@ -4986,6 +4986,7 @@ pub aya::programs::Program::UProbe(aya::programs::uprobe::UProbe) pub aya::programs::Program::Xdp(aya::programs::xdp::Xdp) impl aya::programs::Program pub fn aya::programs::Program::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> +pub fn aya::programs::Program::info(&self) -> core::result::Result pub fn aya::programs::Program::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::Program::prog_type(&self) -> aya_obj::generated::linux_bindings_x86_64::bpf_prog_type pub fn aya::programs::Program::unload(self) -> core::result::Result<(), aya::programs::ProgramError> @@ -5528,11 +5529,11 @@ pub fn aya::programs::tp_btf::BtfTracePoint::fd(&self) -> core::result::Result<& impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::tp_btf::BtfTracePoint +pub fn aya::programs::tp_btf::BtfTracePoint::info(&self) -> core::result::Result +impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tp_btf::BtfTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tp_btf::BtfTracePoint -pub fn aya::programs::tp_btf::BtfTracePoint::program_info(&self) -> core::result::Result -impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::drop(&mut self) @@ -5576,11 +5577,11 @@ pub fn aya::programs::cgroup_device::CgroupDevice::fd(&self) -> core::result::Re impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_device::CgroupDevice +pub fn aya::programs::cgroup_device::CgroupDevice::info(&self) -> core::result::Result +impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_device::CgroupDevice::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_device::CgroupDevice -pub fn aya::programs::cgroup_device::CgroupDevice::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::drop(&mut self) @@ -5624,11 +5625,11 @@ pub fn aya::programs::cgroup_skb::CgroupSkb::take_link(&mut self, link_id: aya:: impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_skb::CgroupSkb +pub fn aya::programs::cgroup_skb::CgroupSkb::info(&self) -> core::result::Result +impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_skb::CgroupSkb::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_skb::CgroupSkb -pub fn aya::programs::cgroup_skb::CgroupSkb::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::drop(&mut self) @@ -5671,11 +5672,11 @@ pub fn aya::programs::cgroup_sock::CgroupSock::take_link(&mut self, link_id: aya impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock::CgroupSock +pub fn aya::programs::cgroup_sock::CgroupSock::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock::CgroupSock::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock::CgroupSock -pub fn aya::programs::cgroup_sock::CgroupSock::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::drop(&mut self) @@ -5718,11 +5719,11 @@ pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::take_link(&mut self, lin impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock_addr::CgroupSockAddr +pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock_addr::CgroupSockAddr -pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::drop(&mut self) @@ -5765,11 +5766,11 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockopt::take_link(&mut self, link_i impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sockopt::CgroupSockopt +pub fn aya::programs::cgroup_sockopt::CgroupSockopt::info(&self) -> core::result::Result +impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sockopt::CgroupSockopt -pub fn aya::programs::cgroup_sockopt::CgroupSockopt::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::drop(&mut self) @@ -5813,11 +5814,11 @@ pub fn aya::programs::cgroup_sysctl::CgroupSysctl::fd(&self) -> core::result::Re impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_sysctl::CgroupSysctl +pub fn aya::programs::cgroup_sysctl::CgroupSysctl::info(&self) -> core::result::Result +impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sysctl::CgroupSysctl -pub fn aya::programs::cgroup_sysctl::CgroupSysctl::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::drop(&mut self) @@ -5862,11 +5863,11 @@ pub fn aya::programs::extension::Extension::fd(&self) -> core::result::Result<&a impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::from_pin>(path: P) -> core::result::Result impl aya::programs::extension::Extension +pub fn aya::programs::extension::Extension::info(&self) -> core::result::Result +impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::extension::Extension::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::extension::Extension -pub fn aya::programs::extension::Extension::program_info(&self) -> core::result::Result -impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::extension::Extension pub fn aya::programs::extension::Extension::drop(&mut self) @@ -5910,11 +5911,11 @@ pub fn aya::programs::fentry::FEntry::fd(&self) -> core::result::Result<&aya::pr impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::from_pin>(path: P) -> core::result::Result impl aya::programs::fentry::FEntry +pub fn aya::programs::fentry::FEntry::info(&self) -> core::result::Result +impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fentry::FEntry::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fentry::FEntry -pub fn aya::programs::fentry::FEntry::program_info(&self) -> core::result::Result -impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::drop(&mut self) @@ -5958,11 +5959,11 @@ pub fn aya::programs::fexit::FExit::fd(&self) -> core::result::Result<&aya::prog impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::from_pin>(path: P) -> core::result::Result impl aya::programs::fexit::FExit +pub fn aya::programs::fexit::FExit::info(&self) -> core::result::Result +impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fexit::FExit::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fexit::FExit -pub fn aya::programs::fexit::FExit::program_info(&self) -> core::result::Result -impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::drop(&mut self) @@ -6006,11 +6007,11 @@ pub fn aya::programs::kprobe::KProbe::take_link(&mut self, link_id: aya::program impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::kprobe::KProbe +pub fn aya::programs::kprobe::KProbe::info(&self) -> core::result::Result +impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::kprobe::KProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::kprobe::KProbe -pub fn aya::programs::kprobe::KProbe::program_info(&self) -> core::result::Result -impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::drop(&mut self) @@ -6055,11 +6056,11 @@ pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<& impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::from_pin>(path: P) -> core::result::Result impl aya::programs::lirc_mode2::LircMode2 +pub fn aya::programs::lirc_mode2::LircMode2::info(&self) -> core::result::Result +impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lirc_mode2::LircMode2::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lirc_mode2::LircMode2 -pub fn aya::programs::lirc_mode2::LircMode2::program_info(&self) -> core::result::Result -impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::drop(&mut self) @@ -6103,11 +6104,11 @@ pub fn aya::programs::lsm::Lsm::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::from_pin>(path: P) -> core::result::Result impl aya::programs::lsm::Lsm +pub fn aya::programs::lsm::Lsm::info(&self) -> core::result::Result +impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lsm::Lsm::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lsm::Lsm -pub fn aya::programs::lsm::Lsm::program_info(&self) -> core::result::Result -impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::drop(&mut self) @@ -6151,11 +6152,11 @@ pub fn aya::programs::perf_event::PerfEvent::fd(&self) -> core::result::Result<& impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::from_pin>(path: P) -> core::result::Result impl aya::programs::perf_event::PerfEvent +pub fn aya::programs::perf_event::PerfEvent::info(&self) -> core::result::Result +impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::perf_event::PerfEvent::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::perf_event::PerfEvent -pub fn aya::programs::perf_event::PerfEvent::program_info(&self) -> core::result::Result -impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::drop(&mut self) @@ -6267,11 +6268,11 @@ pub fn aya::programs::RawTracePoint::fd(&self) -> core::result::Result<&aya::pro impl aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::RawTracePoint +pub fn aya::programs::RawTracePoint::info(&self) -> core::result::Result +impl aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::RawTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::RawTracePoint -pub fn aya::programs::RawTracePoint::program_info(&self) -> core::result::Result -impl aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::drop(&mut self) @@ -6315,11 +6316,11 @@ pub fn aya::programs::tc::SchedClassifier::take_link(&mut self, link_id: aya::pr impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::tc::SchedClassifier +pub fn aya::programs::tc::SchedClassifier::info(&self) -> core::result::Result +impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tc::SchedClassifier::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tc::SchedClassifier -pub fn aya::programs::tc::SchedClassifier::program_info(&self) -> core::result::Result -impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::drop(&mut self) @@ -6363,11 +6364,11 @@ pub fn aya::programs::SkLookup::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::SkLookup pub fn aya::programs::SkLookup::from_pin>(path: P) -> core::result::Result impl aya::programs::SkLookup +pub fn aya::programs::SkLookup::info(&self) -> core::result::Result +impl aya::programs::SkLookup pub fn aya::programs::SkLookup::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SkLookup::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SkLookup -pub fn aya::programs::SkLookup::program_info(&self) -> core::result::Result -impl aya::programs::SkLookup pub fn aya::programs::SkLookup::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SkLookup pub fn aya::programs::SkLookup::drop(&mut self) @@ -6411,11 +6412,11 @@ pub fn aya::programs::SkMsg::fd(&self) -> core::result::Result<&aya::programs::P impl aya::programs::SkMsg pub fn aya::programs::SkMsg::from_pin>(path: P) -> core::result::Result impl aya::programs::SkMsg +pub fn aya::programs::SkMsg::info(&self) -> core::result::Result +impl aya::programs::SkMsg pub fn aya::programs::SkMsg::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SkMsg::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SkMsg -pub fn aya::programs::SkMsg::program_info(&self) -> core::result::Result -impl aya::programs::SkMsg pub fn aya::programs::SkMsg::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SkMsg pub fn aya::programs::SkMsg::drop(&mut self) @@ -6458,11 +6459,11 @@ pub fn aya::programs::SkSkb::take_link(&mut self, link_id: SkSkbLinkId) -> core: impl aya::programs::SkSkb pub fn aya::programs::SkSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::SkSkb +pub fn aya::programs::SkSkb::info(&self) -> core::result::Result +impl aya::programs::SkSkb pub fn aya::programs::SkSkb::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SkSkb::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SkSkb -pub fn aya::programs::SkSkb::program_info(&self) -> core::result::Result -impl aya::programs::SkSkb pub fn aya::programs::SkSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SkSkb pub fn aya::programs::SkSkb::drop(&mut self) @@ -6506,11 +6507,11 @@ pub fn aya::programs::SockOps::fd(&self) -> core::result::Result<&aya::programs: impl aya::programs::SockOps pub fn aya::programs::SockOps::from_pin>(path: P) -> core::result::Result impl aya::programs::SockOps +pub fn aya::programs::SockOps::info(&self) -> core::result::Result +impl aya::programs::SockOps pub fn aya::programs::SockOps::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SockOps::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SockOps -pub fn aya::programs::SockOps::program_info(&self) -> core::result::Result -impl aya::programs::SockOps pub fn aya::programs::SockOps::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SockOps pub fn aya::programs::SockOps::drop(&mut self) @@ -6554,11 +6555,11 @@ pub fn aya::programs::SocketFilter::fd(&self) -> core::result::Result<&aya::prog impl aya::programs::SocketFilter pub fn aya::programs::SocketFilter::from_pin>(path: P) -> core::result::Result impl aya::programs::SocketFilter +pub fn aya::programs::SocketFilter::info(&self) -> core::result::Result +impl aya::programs::SocketFilter pub fn aya::programs::SocketFilter::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SocketFilter::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SocketFilter -pub fn aya::programs::SocketFilter::program_info(&self) -> core::result::Result -impl aya::programs::SocketFilter pub fn aya::programs::SocketFilter::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SocketFilter pub fn aya::programs::SocketFilter::drop(&mut self) @@ -6602,11 +6603,11 @@ pub fn aya::programs::trace_point::TracePoint::fd(&self) -> core::result::Result impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::trace_point::TracePoint +pub fn aya::programs::trace_point::TracePoint::info(&self) -> core::result::Result +impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::trace_point::TracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::trace_point::TracePoint -pub fn aya::programs::trace_point::TracePoint::program_info(&self) -> core::result::Result -impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::drop(&mut self) @@ -6650,11 +6651,11 @@ pub fn aya::programs::uprobe::UProbe::take_link(&mut self, link_id: aya::program impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::uprobe::UProbe +pub fn aya::programs::uprobe::UProbe::info(&self) -> core::result::Result +impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::uprobe::UProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::uprobe::UProbe -pub fn aya::programs::uprobe::UProbe::program_info(&self) -> core::result::Result -impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::drop(&mut self) @@ -6700,11 +6701,11 @@ pub fn aya::programs::xdp::Xdp::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::from_pin>(path: P) -> core::result::Result impl aya::programs::xdp::Xdp +pub fn aya::programs::xdp::Xdp::info(&self) -> core::result::Result +impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::xdp::Xdp::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::program_info(&self) -> core::result::Result -impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::drop(&mut self) From e0880316c3f8000b32530df8799dd7379b4a3e85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:03:57 +0000 Subject: [PATCH 27/95] build(deps): update cargo_metadata requirement from 0.17.0 to 0.18.0 Updates the requirements on [cargo_metadata](https://github.com/oli-obk/cargo_metadata) to permit the latest version. - [Release notes](https://github.com/oli-obk/cargo_metadata/releases) - [Changelog](https://github.com/oli-obk/cargo_metadata/blob/main/CHANGELOG.md) - [Commits](https://github.com/oli-obk/cargo_metadata/compare/0.17.0...0.17.0) --- updated-dependencies: - dependency-name: cargo_metadata dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e31471aa..cfbb91ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ aya-tool = { path = "aya-tool", default-features = false } bindgen = { version = "0.68", default-features = false } bitflags = { version = "2.2.1", default-features = false } bytes = { version = "1", default-features = false } -cargo_metadata = { version = "0.17.0", default-features = false } +cargo_metadata = { version = "0.18.0", default-features = false } clap = { version = "4", default-features = false } core-error = { version = "0.0.0", default-features = false } dialoguer = { version = "0.10", default-features = false } From f41592663cda156082255b93db145cfdd19378e5 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 29 Aug 2023 17:19:20 -0400 Subject: [PATCH 28/95] maps: `MapFd` and `SockMapFd` are owned `MapData::fd` is now a `MapFd`. This means that `MapData` now closes the file descriptor on drop. In the future we might consider making `MapFd` hold a `BorrowedFd` but this requires API design work due to overlapping borrows. Since `SockMapFd` is no longer `Copy`, attach methods to take it by reference to allow callers to use it multiple times as they are accustomed to doing. `SockMapFd` implements `try_clone`. `MapFd` and `SockMapFd` are now returned by reference to allow callers to avoid file descriptor cloning when desired. This is an API breaking change. Updates #612. --- aya-obj/src/lib.rs | 6 ++ aya-obj/src/relocation.rs | 6 +- aya/src/bpf.rs | 14 ++-- aya/src/maps/array/array.rs | 5 +- aya/src/maps/array/per_cpu_array.rs | 5 +- aya/src/maps/array/program_array.rs | 4 +- aya/src/maps/bloom_filter.rs | 5 +- aya/src/maps/hash_map/hash_map.rs | 3 +- aya/src/maps/hash_map/mod.rs | 5 +- aya/src/maps/hash_map/per_cpu_hash_map.rs | 5 +- aya/src/maps/lpm_trie.rs | 7 +- aya/src/maps/mod.rs | 94 +++++++++++------------ aya/src/maps/perf/perf_event_array.rs | 4 +- aya/src/maps/queue.rs | 5 +- aya/src/maps/sock/mod.rs | 26 +++++-- aya/src/maps/sock/sock_hash.rs | 18 +++-- aya/src/maps/sock/sock_map.rs | 32 +++++--- aya/src/maps/stack.rs | 5 +- aya/src/maps/stack_trace.rs | 4 +- aya/src/programs/links.rs | 8 +- aya/src/programs/mod.rs | 7 +- aya/src/programs/sk_msg.rs | 6 +- aya/src/programs/sk_skb.rs | 19 ++++- aya/src/programs/utils.rs | 2 +- aya/src/sys/bpf.rs | 55 +++++++------ test/integration-test/src/tests/rbpf.rs | 2 +- xtask/public-api/aya-obj.txt | 4 +- xtask/public-api/aya.txt | 41 ++++------ 28 files changed, 222 insertions(+), 175 deletions(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index d6d2a8a5..ea0e5670 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -77,6 +77,12 @@ mod std { pub use core_error::Error; } pub use core::*; + + pub mod os { + pub mod fd { + pub type RawFd = core::ffi::c_int; + } + } } pub mod btf; diff --git a/aya-obj/src/relocation.rs b/aya-obj/src/relocation.rs index 8269f6ca..83879fc8 100644 --- a/aya-obj/src/relocation.rs +++ b/aya-obj/src/relocation.rs @@ -105,7 +105,7 @@ pub(crate) struct Symbol { impl Object { /// Relocates the map references - pub fn relocate_maps<'a, I: Iterator>( + pub fn relocate_maps<'a, I: Iterator>( &mut self, maps: I, text_sections: &HashSet, @@ -178,8 +178,8 @@ impl Object { fn relocate_maps<'a, I: Iterator>( fun: &mut Function, relocations: I, - maps_by_section: &HashMap, - maps_by_symbol: &HashMap, + maps_by_section: &HashMap, + maps_by_symbol: &HashMap, symbol_table: &HashMap, text_sections: &HashSet, ) -> Result<(), RelocationError> { diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index f967c737..d81007c7 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, fs, io, os::{ - fd::{AsFd as _, OwnedFd}, + fd::{AsFd as _, AsRawFd as _, OwnedFd}, raw::c_int, }, path::{Path, PathBuf}, @@ -482,17 +482,17 @@ impl<'a> BpfLoader<'a> { MapData::create_pinned(path, obj, &name, btf_fd)? } }; - let fd = map.fd; - if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss { - bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0) + let MapData { obj, fd, pinned: _ } = &mut map; + if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss { + bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0) .map_err(|(_, io_error)| SyscallError { call: "bpf_map_update_elem", io_error, }) .map_err(MapError::from)?; } - if map.obj.section_kind() == BpfSectionKind::Rodata { - bpf_map_freeze(fd) + if obj.section_kind() == BpfSectionKind::Rodata { + bpf_map_freeze(fd.as_fd()) .map_err(|(_, io_error)| SyscallError { call: "bpf_map_freeze", io_error, @@ -510,7 +510,7 @@ impl<'a> BpfLoader<'a> { obj.relocate_maps( maps.iter() - .map(|(s, data)| (s.as_str(), data.fd, &data.obj)), + .map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), &data.obj)), &text_sections, )?; obj.relocate_calls(&text_sections)?; diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 64454a3c..5d137d05 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -61,7 +62,7 @@ impl, V: Pod> Array { pub fn get(&self, index: &u32, flags: u64) -> Result { let data = self.inner.borrow(); check_bounds(data, *index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| SyscallError { @@ -88,7 +89,7 @@ impl, V: Pod> Array { pub fn set(&mut self, index: u32, value: impl Borrow, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index db6169bd..f384b713 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -80,7 +81,7 @@ impl, V: Pod> PerCpuArray { pub fn get(&self, index: &u32, flags: u64) -> Result, MapError> { let data = self.inner.borrow(); check_bounds(data, *index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| { SyscallError { @@ -108,7 +109,7 @@ impl, V: Pod> PerCpuArray { pub fn set(&mut self, index: u32, values: PerCpuValues, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| { SyscallError { diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index a38ce023..48bb6b9d 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -74,7 +74,7 @@ impl> ProgramArray { pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); let prog_fd = program.as_fd(); let prog_fd = prog_fd.as_raw_fd(); @@ -94,7 +94,7 @@ impl> ProgramArray { pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, *index)?; - let fd = self.inner.borrow_mut().fd; + let fd = data.fd().as_fd(); bpf_map_delete_elem(fd, index) .map(|_| ()) diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index 0396d0f6..dfe4d2cb 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -52,7 +53,7 @@ impl, V: Pod> BloomFilter { /// Query the existence of the element. pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_lookup_elem_ptr::(fd, None, &mut value, flags) .map_err(|(_, io_error)| SyscallError { @@ -67,7 +68,7 @@ impl, V: Pod> BloomFilter { impl, V: Pod> BloomFilter { /// Inserts a value into the map. pub fn insert(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow_mut().fd; + let fd = self.inner.borrow_mut().fd().as_fd(); bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_push_elem", io_error, diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 8d091582..9d587b33 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -52,7 +53,7 @@ impl, K: Pod, V: Pod> HashMap { /// Returns a copy of the value associated with the key. pub fn get(&self, key: &K, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index 5e18cb19..40c171ce 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -4,6 +4,7 @@ use crate::{ sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError}, Pod, }; +use std::os::fd::AsFd as _; #[allow(clippy::module_inception)] mod hash_map; @@ -20,7 +21,7 @@ pub(crate) fn insert( value: &V, flags: u64, ) -> Result<(), MapError> { - let fd = map.fd; + let fd = map.fd().as_fd(); bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_update_elem", io_error, @@ -30,7 +31,7 @@ pub(crate) fn insert( } pub(crate) fn remove(map: &MapData, key: &K) -> Result<(), MapError> { - let fd = map.fd; + let fd = map.fd().as_fd(); bpf_map_delete_elem(fd, key) .map(|_| ()) .map_err(|(_, io_error)| { diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index aabc71f6..56fc2ae2 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -61,7 +62,7 @@ impl, K: Pod, V: Pod> PerCpuHashMap { /// Returns a slice of values - one for each CPU - associated with the key. pub fn get(&self, key: &K, flags: u64) -> Result, MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", @@ -118,7 +119,7 @@ impl, K: Pod, V: Pod> PerCpuHashMap { values: PerCpuValues, flags: u64, ) -> Result<(), MapError> { - let fd = self.inner.borrow_mut().fd; + let fd = self.inner.borrow_mut().fd().as_fd(); bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err( |(_, io_error)| SyscallError { call: "bpf_map_update_elem", diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index dcdc443d..d4e1e678 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -126,7 +127,7 @@ impl, K: Pod, V: Pod> LpmTrie { /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie. pub fn get(&self, key: &Key, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, @@ -155,7 +156,7 @@ impl, K: Pod, V: Pod> LpmTrie { value: impl Borrow, flags: u64, ) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", @@ -170,7 +171,7 @@ impl, K: Pod, V: Pod> LpmTrie { /// /// Both the prefix and data must match exactly - this method does not do a longest prefix match. pub fn remove(&mut self, key: &Key) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_delete_elem(fd, key) .map(|_| ()) .map_err(|(_, io_error)| { diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 4d8183e9..85ba5d94 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -18,17 +18,28 @@ //! the [`TryFrom`] or [`TryInto`] trait. For example: //! //! ```no_run +//! # #[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(&[])?; //! use aya::maps::SockMap; //! use aya::programs::SkMsg; //! //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; -//! let map_fd = intercept_egress.fd()?; +//! let map_fd = intercept_egress.fd().try_clone()?; //! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; //! prog.load()?; -//! prog.attach(map_fd)?; +//! prog.attach(&map_fd)?; //! -//! # Ok::<(), aya::BpfError>(()) +//! # Ok::<(), Error>(()) //! ``` //! //! # Maps and `Pod` values @@ -42,7 +53,7 @@ use std::{ marker::PhantomData, mem, ops::Deref, - os::fd::{AsFd as _, AsRawFd, BorrowedFd, IntoRawFd as _, OwnedFd, RawFd}, + os::fd::{AsFd, BorrowedFd, OwnedFd}, path::Path, ptr, }; @@ -177,11 +188,13 @@ pub enum MapError { } /// A map file descriptor. -pub struct MapFd(RawFd); +#[derive(Debug)] +pub struct MapFd(OwnedFd); -impl AsRawFd for MapFd { - fn as_raw_fd(&self) -> RawFd { - self.0 +impl AsFd for MapFd { + fn as_fd(&self) -> BorrowedFd<'_> { + let Self(fd) = self; + fd.as_fd() } } @@ -396,7 +409,7 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { #[derive(Debug)] pub struct MapData { pub(crate) obj: obj::Map, - pub(crate) fd: RawFd, + pub(crate) fd: MapFd, /// Indicates if this map has been pinned to bpffs pub pinned: bool, } @@ -426,9 +439,7 @@ impl MapData { io_error, } })?; - - #[allow(trivial_numeric_casts)] - let fd = fd as RawFd; + let fd = MapFd(fd); Ok(Self { obj, fd, @@ -459,11 +470,14 @@ impl MapData { call: "BPF_OBJ_GET", io_error, }) { - Ok(fd) => Ok(Self { - obj, - fd: fd.into_raw_fd(), - pinned: false, - }), + Ok(fd) => { + let fd = MapFd(fd); + Ok(Self { + obj, + fd, + pinned: false, + }) + } Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; map.pin(name, path).map_err(|error| MapError::PinError { @@ -493,12 +507,13 @@ impl MapData { call: "BPF_OBJ_GET", io_error, })?; + let fd = MapFd(fd); let info = bpf_map_get_info_by_fd(fd.as_fd())?; Ok(Self { obj: parse_map_info(info, PinningType::ByName), - fd: fd.into_raw_fd(), + fd, pinned: true, }) } @@ -511,9 +526,10 @@ impl MapData { pub fn from_fd(fd: OwnedFd) -> Result { let info = bpf_map_get_info_by_fd(fd.as_fd())?; + let fd = MapFd(fd); Ok(Self { obj: parse_map_info(info, PinningType::None), - fd: fd.into_raw_fd(), + fd, pinned: false, }) } @@ -528,7 +544,7 @@ impl MapData { let path = path.as_ref().join(name); let path_string = CString::new(path.as_os_str().as_bytes()) .map_err(|error| PinError::InvalidPinPath { path, error })?; - bpf_pin_object(*fd, &path_string).map_err(|(_, io_error)| SyscallError { + bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, })?; @@ -537,30 +553,13 @@ impl MapData { } /// Returns the file descriptor of the map. - /// - /// Can be converted to [`RawFd`] using [`AsRawFd`]. - pub fn fd(&self) -> MapFd { - MapFd(self.fd) - } -} - -impl Drop for MapData { - fn drop(&mut self) { - // TODO: Replace this with an OwnedFd once that is stabilized. - // - // SAFETY: `drop` is only called once. - unsafe { libc::close(self.fd) }; - } -} - -impl Clone for MapData { - fn clone(&self) -> Self { - let Self { obj, fd, pinned } = self; - Self { - obj: obj.clone(), - fd: unsafe { libc::dup(*fd) }, - pinned: *pinned, - } + pub fn fd(&self) -> &MapFd { + let Self { + obj: _, + fd, + pinned: _, + } = self; + fd } } @@ -598,7 +597,7 @@ impl Iterator for MapKeys<'_, K> { return None; } - let fd = self.map.fd; + let fd = self.map.fd().as_fd(); let key = bpf_map_get_next_key(fd, self.key.as_ref()).map_err(|(_, io_error)| SyscallError { call: "bpf_map_get_next_key", @@ -754,6 +753,7 @@ impl Deref for PerCpuValues { mod tests { use assert_matches::assert_matches; use libc::EFAULT; + use std::os::fd::AsRawFd as _; use crate::{ bpf_map_def, @@ -795,9 +795,9 @@ mod tests { MapData::create(new_obj_map(), "foo", None), Ok(MapData { obj: _, - fd: 42, + fd, pinned: false - }) + }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) ); } diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index 1d19d373..ebeef672 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -4,7 +4,7 @@ use std::{ borrow::{Borrow, BorrowMut}, ops::Deref, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd as _, AsRawFd, RawFd}, sync::Arc, }; @@ -181,7 +181,7 @@ impl> PerfEventArray { // FIXME: keep track of open buffers let map_data: &MapData = self.map.deref().borrow(); - let map_fd = map_data.fd; + let map_fd = map_data.fd().as_fd(); let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?; bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0) .map_err(|(_, io_error)| io_error)?; diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index 6eebbf01..31c44633 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -60,7 +61,7 @@ impl, V: Pod> Queue { /// Returns [`MapError::ElementNotFound`] if the queue is empty, [`MapError::SyscallError`] /// if `bpf_map_lookup_and_delete_elem` fails. pub fn pop(&mut self, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( |(_, io_error)| SyscallError { @@ -77,7 +78,7 @@ impl, V: Pod> Queue { /// /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_push_elem", io_error, diff --git a/aya/src/maps/sock/mod.rs b/aya/src/maps/sock/mod.rs index 05fe112c..0c3262a2 100644 --- a/aya/src/maps/sock/mod.rs +++ b/aya/src/maps/sock/mod.rs @@ -5,17 +5,29 @@ mod sock_map; pub use sock_hash::SockHash; pub use sock_map::SockMap; -use std::os::fd::{AsFd, BorrowedFd, RawFd}; +use std::{ + io, + os::fd::{AsFd, BorrowedFd}, +}; /// A socket map file descriptor. -#[derive(Copy, Clone)] -pub struct SockMapFd(RawFd); +#[repr(transparent)] +pub struct SockMapFd(super::MapFd); + +impl SockMapFd { + /// Creates a new instance that shares the same underlying file description as [`self`]. + pub fn try_clone(&self) -> io::Result { + let Self(inner) = self; + let super::MapFd(inner) = inner; + let inner = inner.try_clone()?; + let inner = super::MapFd(inner); + Ok(Self(inner)) + } +} impl AsFd for SockMapFd { fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: This isn't necessarily safe, we need to find ways - // to enforce that the file descriptor is still - // valid. TODO(#612) - unsafe { BorrowedFd::borrow_raw(self.0) } + let Self(fd) = self; + fd.as_fd() } } diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 503dcaae..99d0f871 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -1,12 +1,13 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd as _, AsRawFd, RawFd}, }; use crate::{ maps::{ - check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapIter, MapKeys, + check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapFd, MapIter, + MapKeys, }, sys::{bpf_map_lookup_elem, SyscallError}, Pod, @@ -47,11 +48,11 @@ use crate::{ /// use aya::programs::SkMsg; /// /// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?; -/// let map_fd = intercept_egress.fd()?; +/// let map_fd = intercept_egress.fd().try_clone()?; /// /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; @@ -81,7 +82,7 @@ impl, K: Pod> SockHash { /// Returns the fd of the socket stored at the given key. pub fn get(&self, key: &K, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, @@ -105,8 +106,11 @@ impl, K: Pod> SockHash { /// /// The returned file descriptor can be used to attach programs that work with /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). - pub fn fd(&self) -> Result { - Ok(SockMapFd(self.inner.borrow().fd)) + pub fn fd(&self) -> &SockMapFd { + let fd: &MapFd = self.inner.borrow().fd(); + // TODO(https://github.com/rust-lang/rfcs/issues/3066): avoid this unsafe. + // SAFETY: `SockMapFd` is #[repr(transparent)] over `MapFd`. + unsafe { std::mem::transmute(fd) } } } diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index 8194cd71..42246c8b 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -2,11 +2,11 @@ use std::{ borrow::{Borrow, BorrowMut}, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd as _, AsRawFd, RawFd}, }; use crate::{ - maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapKeys}, + maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapFd, MapKeys}, sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError}, }; @@ -26,18 +26,29 @@ use crate::{ /// # Examples /// /// ```no_run +/// # #[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(&[])?; /// use aya::maps::SockMap; /// use aya::programs::SkSkb; /// /// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?; -/// let map_fd = intercept_ingress.fd()?; +/// let map_fd = intercept_ingress.fd().try_clone()?; /// /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// -/// # Ok::<(), aya::BpfError>(()) +/// # Ok::<(), Error>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_SOCKMAP")] pub struct SockMap { @@ -62,8 +73,11 @@ impl> SockMap { /// /// The returned file descriptor can be used to attach programs that work with /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). - pub fn fd(&self) -> Result { - Ok(SockMapFd(self.inner.borrow().fd)) + pub fn fd(&self) -> &SockMapFd { + let fd: &MapFd = self.inner.borrow().fd(); + // TODO(https://github.com/rust-lang/rfcs/issues/3066): avoid this unsafe. + // SAFETY: `SockMapFd` is #[repr(transparent)] over `MapFd`. + unsafe { std::mem::transmute(&fd) } } } @@ -71,7 +85,7 @@ impl> SockMap { /// Stores a socket into the map. pub fn set(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); - let fd = data.fd; + let fd = data.fd().as_fd(); check_bounds(data, index)?; bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err( |(_, io_error)| SyscallError { @@ -85,7 +99,7 @@ impl> SockMap { /// Removes the socket stored at `index` from the map. pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { let data = self.inner.borrow_mut(); - let fd = data.fd; + let fd = data.fd().as_fd(); check_bounds(data, *index)?; bpf_map_delete_elem(fd, index) .map(|_| ()) diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index c4afeebb..ac1453cd 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -60,7 +61,7 @@ impl, V: Pod> Stack { /// Returns [`MapError::ElementNotFound`] if the stack is empty, [`MapError::SyscallError`] /// if `bpf_map_lookup_and_delete_elem` fails. pub fn pop(&mut self, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( |(_, io_error)| SyscallError { @@ -77,7 +78,7 @@ impl, V: Pod> Stack { /// /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index 07281a2b..fdf1d937 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -1,7 +1,7 @@ //! A hash map of kernel or user space stack traces. //! //! See [`StackTraceMap`] for documentation and examples. -use std::{borrow::Borrow, fs, io, mem, path::Path, str::FromStr}; +use std::{borrow::Borrow, fs, io, mem, os::fd::AsFd as _, path::Path, str::FromStr}; use crate::{ maps::{IterableMap, MapData, MapError, MapIter, MapKeys}, @@ -103,7 +103,7 @@ impl> StackTraceMap { /// Returns [`MapError::KeyNotFound`] if there is no stack trace with the /// given `stack_id`, or [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. pub fn get(&self, stack_id: &u32, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let mut frames = vec![0; self.max_stack_depth]; bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags) diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index d06a62e4..e8eeb417 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -154,11 +154,9 @@ impl FdLink { error, } })?; - bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| { - SyscallError { - call: "BPF_OBJ_PIN", - io_error, - } + bpf_pin_object(self.fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { + call: "BPF_OBJ_PIN", + io_error, })?; Ok(PinnedLink::new(path.into(), self)) } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 616244e0..e41bdeed 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -218,9 +218,8 @@ pub enum ProgramError { pub struct ProgramFd(OwnedFd); impl ProgramFd { - /// Creates a new `ProgramFd` instance that shares the same underlying file - /// description as the existing `ProgramFd` instance. - pub fn try_clone(&self) -> Result { + /// Creates a new instance that shares the same underlying file description as [`self`]. + pub fn try_clone(&self) -> io::Result { let Self(inner) = self; let inner = inner.try_clone()?; Ok(Self(inner)) @@ -536,7 +535,7 @@ fn pin_program>(data: &ProgramData, path: P) -> Resul path: path.into(), error, })?; - bpf_pin_object(fd.as_fd().as_raw_fd(), &path_string).map_err(|(_, io_error)| SyscallError { + bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, })?; diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index 554c3e86..f169447b 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -43,11 +43,11 @@ use crate::{ /// use aya::programs::SkMsg; /// /// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?; -/// let map_fd = intercept_egress.fd()?; +/// let map_fd = intercept_egress.fd().try_clone()?; /// /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut intercept_egress: SockHash<_, u32> = bpf.map_mut("INTERCEPT_EGRESS").unwrap().try_into()?; @@ -77,7 +77,7 @@ impl SkMsg { /// Attaches the program to the given sockmap. /// /// The returned value can be used to detach, see [SkMsg::detach]. - pub fn attach(&mut self, map: SockMapFd) -> Result { + pub fn attach(&mut self, map: &SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let link = ProgAttachLink::attach(prog_fd, map.as_fd(), BPF_SK_MSG_VERDICT)?; diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index dac5ba3f..81bc9534 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -37,18 +37,29 @@ pub enum SkSkbKind { /// # Examples /// /// ```no_run +/// # #[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(&[])?; /// use aya::maps::SockMap; /// use aya::programs::SkSkb; /// /// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?; -/// let map_fd = intercept_ingress.fd()?; +/// let map_fd = intercept_ingress.fd().try_clone()?; /// /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// -/// # Ok::<(), aya::BpfError>(()) +/// # Ok::<(), Error>(()) /// ``` /// /// [socket maps]: crate::maps::sock @@ -70,7 +81,7 @@ impl SkSkb { /// Attaches the program to the given socket map. /// /// The returned value can be used to detach, see [SkSkb::detach]. - pub fn attach(&mut self, map: SockMapFd) -> Result { + pub fn attach(&mut self, map: &SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index 0f8f61ae..a32d9f93 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -82,7 +82,7 @@ pub(crate) fn get_fdinfo(fd: BorrowedFd<'_>, key: &str) -> Result>, kernel_version: KernelVersion, -) -> SysResult { +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_1 }; @@ -91,13 +91,14 @@ pub(crate) fn bpf_create_map( .copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) }); } - sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) + // SAFETY: BPF_MAP_CREATE returns a new file descriptor. + unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) } } -pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult { +pub(crate) fn bpf_pin_object(fd: BorrowedFd<'_>, path: &CStr) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_4 }; - u.bpf_fd = fd as u32; + u.bpf_fd = fd.as_raw_fd() as u32; u.pathname = path.as_ptr() as u64; sys_bpf(bpf_cmd::BPF_OBJ_PIN, &mut attr) } @@ -194,7 +195,7 @@ pub(crate) fn bpf_load_program( } fn lookup( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, flags: u64, cmd: bpf_cmd, @@ -203,7 +204,7 @@ fn lookup( let mut value = MaybeUninit::zeroed(); let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -218,7 +219,7 @@ fn lookup( } pub(crate) fn bpf_map_lookup_elem( - fd: RawFd, + fd: BorrowedFd<'_>, key: &K, flags: u64, ) -> Result, (c_long, io::Error)> { @@ -226,7 +227,7 @@ pub(crate) fn bpf_map_lookup_elem( } pub(crate) fn bpf_map_lookup_and_delete_elem( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, flags: u64, ) -> Result, (c_long, io::Error)> { @@ -234,7 +235,7 @@ pub(crate) fn bpf_map_lookup_and_delete_elem( } pub(crate) fn bpf_map_lookup_elem_per_cpu( - fd: RawFd, + fd: BorrowedFd<'_>, key: &K, flags: u64, ) -> Result>, (c_long, io::Error)> { @@ -247,7 +248,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu( } pub(crate) fn bpf_map_lookup_elem_ptr( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, value: *mut V, flags: u64, @@ -255,7 +256,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr( let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -270,7 +271,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr( } pub(crate) fn bpf_map_update_elem( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, value: &V, flags: u64, @@ -278,7 +279,7 @@ pub(crate) fn bpf_map_update_elem( let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -288,11 +289,15 @@ pub(crate) fn bpf_map_update_elem( sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr) } -pub(crate) fn bpf_map_push_elem(fd: RawFd, value: &V, flags: u64) -> SysResult { +pub(crate) fn bpf_map_push_elem( + fd: BorrowedFd<'_>, + value: &V, + flags: u64, +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; u.__bindgen_anon_1.value = value as *const _ as u64; u.flags = flags; @@ -300,7 +305,7 @@ pub(crate) fn bpf_map_push_elem(fd: RawFd, value: &V, flags: u64) -> Sys } pub(crate) fn bpf_map_update_elem_ptr( - fd: RawFd, + fd: BorrowedFd<'_>, key: *const K, value: *mut V, flags: u64, @@ -308,7 +313,7 @@ pub(crate) fn bpf_map_update_elem_ptr( let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; u.key = key as u64; u.__bindgen_anon_1.value = value as u64; u.flags = flags; @@ -317,7 +322,7 @@ pub(crate) fn bpf_map_update_elem_ptr( } pub(crate) fn bpf_map_update_elem_per_cpu( - fd: RawFd, + fd: BorrowedFd<'_>, key: &K, values: &PerCpuValues, flags: u64, @@ -326,25 +331,25 @@ pub(crate) fn bpf_map_update_elem_per_cpu( bpf_map_update_elem_ptr(fd, key, mem.as_mut_ptr(), flags) } -pub(crate) fn bpf_map_delete_elem(fd: RawFd, key: &K) -> SysResult { +pub(crate) fn bpf_map_delete_elem(fd: BorrowedFd<'_>, key: &K) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; u.key = key as *const _ as u64; sys_bpf(bpf_cmd::BPF_MAP_DELETE_ELEM, &mut attr) } pub(crate) fn bpf_map_get_next_key( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, ) -> Result, (c_long, io::Error)> { let mut attr = unsafe { mem::zeroed::() }; let mut next_key = MaybeUninit::uninit(); let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -358,10 +363,10 @@ pub(crate) fn bpf_map_get_next_key( } // since kernel 5.2 -pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult { +pub(crate) fn bpf_map_freeze(fd: BorrowedFd<'_>) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; sys_bpf(bpf_cmd::BPF_MAP_FREEZE, &mut attr) } @@ -754,7 +759,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { ); if let Ok(map) = map { - insns[0].imm = map.fd; + insns[0].imm = map.fd().as_fd().as_raw_fd(); let gpl = b"GPL\0"; u.license = gpl.as_ptr() as u64; diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index da44863f..9caab94c 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -58,7 +58,7 @@ fn use_map_with_rbpf() { ); let map_id = if name == "map_1" { 0 } else { 1 }; - let fd = map_id as i32 | 0xCAFE00; + let fd = map_id as std::os::fd::RawFd | 0xCAFE00; maps.insert(name.to_owned(), (fd, map.clone())); unsafe { diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index 574862f4..c6dea1ba 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -5972,7 +5972,7 @@ impl aya_obj::Object pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError> impl aya_obj::Object pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> -pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> +pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> impl core::clone::Clone for aya_obj::Object pub fn aya_obj::Object::clone(&self) -> aya_obj::Object impl core::fmt::Debug for aya_obj::Object @@ -6684,7 +6684,7 @@ impl aya_obj::Object pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError> impl aya_obj::Object pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> -pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> +pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> impl core::clone::Clone for aya_obj::Object pub fn aya_obj::Object::clone(&self) -> aya_obj::Object impl core::fmt::Debug for aya_obj::Object diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index dfbdde83..3f6dfad6 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -559,7 +559,7 @@ pub fn aya::maps::queue::Queue::from(t: T) -> T pub mod aya::maps::sock pub struct aya::maps::sock::SockHash impl, K: aya::Pod> aya::maps::SockHash -pub fn aya::maps::SockHash::fd(&self) -> core::result::Result +pub fn aya::maps::SockHash::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockHash::get(&self, key: &K, flags: u64) -> core::result::Result pub fn aya::maps::SockHash::iter(&self) -> aya::maps::MapIter<'_, K, std::os::fd::raw::RawFd, Self> pub fn aya::maps::SockHash::keys(&self) -> aya::maps::MapKeys<'_, K> @@ -601,7 +601,7 @@ impl core::convert::From for aya::maps::SockHash pub fn aya::maps::SockHash::from(t: T) -> T pub struct aya::maps::sock::SockMap impl> aya::maps::SockMap -pub fn aya::maps::SockMap::fd(&self) -> core::result::Result +pub fn aya::maps::SockMap::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockMap::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::SockMap pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> @@ -636,12 +636,11 @@ impl core::borrow::BorrowMut for aya::maps::SockMap where T: core::mark pub fn aya::maps::SockMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::SockMap pub fn aya::maps::SockMap::from(t: T) -> T -pub struct aya::maps::sock::SockMapFd(_) +#[repr(transparent)] pub struct aya::maps::sock::SockMapFd(_) +impl aya::maps::sock::SockMapFd +pub fn aya::maps::sock::SockMapFd::try_clone(&self) -> std::io::error::Result impl std::os::fd::owned::AsFd for aya::maps::sock::SockMapFd pub fn aya::maps::sock::SockMapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> -impl core::clone::Clone for aya::maps::sock::SockMapFd -pub fn aya::maps::sock::SockMapFd::clone(&self) -> aya::maps::sock::SockMapFd -impl core::marker::Copy for aya::maps::sock::SockMapFd impl core::marker::Send for aya::maps::sock::SockMapFd impl core::marker::Sync for aya::maps::sock::SockMapFd impl core::marker::Unpin for aya::maps::sock::SockMapFd @@ -655,10 +654,6 @@ pub fn aya::maps::sock::SockMapFd::try_from(value: U) -> core::result::Result core::convert::TryInto for aya::maps::sock::SockMapFd where U: core::convert::TryFrom pub type aya::maps::sock::SockMapFd::Error = >::Error pub fn aya::maps::sock::SockMapFd::try_into(self) -> core::result::Result>::Error> -impl alloc::borrow::ToOwned for aya::maps::sock::SockMapFd where T: core::clone::Clone -pub type aya::maps::sock::SockMapFd::Owned = T -pub fn aya::maps::sock::SockMapFd::clone_into(&self, target: &mut T) -pub fn aya::maps::sock::SockMapFd::to_owned(&self) -> T impl core::any::Any for aya::maps::sock::SockMapFd where T: 'static + core::marker::Sized pub fn aya::maps::sock::SockMapFd::type_id(&self) -> core::any::TypeId impl core::borrow::Borrow for aya::maps::sock::SockMapFd where T: core::marker::Sized @@ -1226,13 +1221,9 @@ pub struct aya::maps::MapData pub aya::maps::MapData::pinned: bool impl aya::maps::MapData pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option>) -> core::result::Result -pub fn aya::maps::MapData::fd(&self) -> aya::maps::MapFd +pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result -impl core::clone::Clone for aya::maps::MapData -pub fn aya::maps::MapData::clone(&self) -> Self -impl core::ops::drop::Drop for aya::maps::MapData -pub fn aya::maps::MapData::drop(&mut self) impl core::fmt::Debug for aya::maps::MapData pub fn aya::maps::MapData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::MapData @@ -1248,10 +1239,6 @@ pub fn aya::maps::MapData::try_from(value: U) -> core::result::Result core::convert::TryInto for aya::maps::MapData where U: core::convert::TryFrom pub type aya::maps::MapData::Error = >::Error pub fn aya::maps::MapData::try_into(self) -> core::result::Result>::Error> -impl alloc::borrow::ToOwned for aya::maps::MapData where T: core::clone::Clone -pub type aya::maps::MapData::Owned = T -pub fn aya::maps::MapData::clone_into(&self, target: &mut T) -pub fn aya::maps::MapData::to_owned(&self) -> T impl core::any::Any for aya::maps::MapData where T: 'static + core::marker::Sized pub fn aya::maps::MapData::type_id(&self) -> core::any::TypeId impl core::borrow::Borrow for aya::maps::MapData where T: core::marker::Sized @@ -1261,8 +1248,10 @@ pub fn aya::maps::MapData::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::MapData pub fn aya::maps::MapData::from(t: T) -> T pub struct aya::maps::MapFd(_) -impl std::os::fd::raw::AsRawFd for aya::maps::MapFd -pub fn aya::maps::MapFd::as_raw_fd(&self) -> std::os::fd::raw::RawFd +impl std::os::fd::owned::AsFd for aya::maps::MapFd +pub fn aya::maps::MapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> +impl core::fmt::Debug for aya::maps::MapFd +pub fn aya::maps::MapFd::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::MapFd impl core::marker::Sync for aya::maps::MapFd impl core::marker::Unpin for aya::maps::MapFd @@ -1566,7 +1555,7 @@ impl core::convert::From for aya::maps::queue::Queue pub fn aya::maps::queue::Queue::from(t: T) -> T pub struct aya::maps::SockHash impl, K: aya::Pod> aya::maps::SockHash -pub fn aya::maps::SockHash::fd(&self) -> core::result::Result +pub fn aya::maps::SockHash::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockHash::get(&self, key: &K, flags: u64) -> core::result::Result pub fn aya::maps::SockHash::iter(&self) -> aya::maps::MapIter<'_, K, std::os::fd::raw::RawFd, Self> pub fn aya::maps::SockHash::keys(&self) -> aya::maps::MapKeys<'_, K> @@ -1608,7 +1597,7 @@ impl core::convert::From for aya::maps::SockHash pub fn aya::maps::SockHash::from(t: T) -> T pub struct aya::maps::SockMap impl> aya::maps::SockMap -pub fn aya::maps::SockMap::fd(&self) -> core::result::Result +pub fn aya::maps::SockMap::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockMap::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::SockMap pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> @@ -6190,7 +6179,7 @@ impl core::convert::From for aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::from(t: T) -> T pub struct aya::programs::ProgramFd(_) impl aya::programs::ProgramFd -pub fn aya::programs::ProgramFd::try_clone(&self) -> core::result::Result +pub fn aya::programs::ProgramFd::try_clone(&self) -> std::io::error::Result impl std::os::fd::owned::AsFd for aya::programs::ProgramFd pub fn aya::programs::ProgramFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> impl core::fmt::Debug for aya::programs::ProgramFd @@ -6402,7 +6391,7 @@ impl core::convert::From for aya::programs::SkLookup pub fn aya::programs::SkLookup::from(t: T) -> T pub struct aya::programs::SkMsg impl aya::programs::SkMsg -pub fn aya::programs::SkMsg::attach(&mut self, map: aya::maps::sock::SockMapFd) -> core::result::Result +pub fn aya::programs::SkMsg::attach(&mut self, map: &aya::maps::sock::SockMapFd) -> core::result::Result pub fn aya::programs::SkMsg::detach(&mut self, link_id: SkMsgLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkMsg::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkMsg::take_link(&mut self, link_id: SkMsgLinkId) -> core::result::Result @@ -6450,7 +6439,7 @@ impl core::convert::From for aya::programs::SkMsg pub fn aya::programs::SkMsg::from(t: T) -> T pub struct aya::programs::SkSkb impl aya::programs::SkSkb -pub fn aya::programs::SkSkb::attach(&mut self, map: aya::maps::sock::SockMapFd) -> core::result::Result +pub fn aya::programs::SkSkb::attach(&mut self, map: &aya::maps::sock::SockMapFd) -> core::result::Result pub fn aya::programs::SkSkb::detach(&mut self, link_id: SkSkbLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkSkb::from_pin>(path: P, kind: aya::programs::SkSkbKind) -> core::result::Result pub fn aya::programs::SkSkb::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> From b4d5a1e8dbb82fc6fca543ad3b6e2f8175ae83b6 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 1 Sep 2023 13:53:03 -0400 Subject: [PATCH 29/95] maps: MapData::{obj, fd} are private --- aya/src/bpf.rs | 33 ++++++++------------------------- aya/src/maps/mod.rs | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index d81007c7..a5fb9273 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -36,12 +36,11 @@ use crate::{ SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp, }, sys::{ - bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_bpf_cookie_supported, - is_bpf_global_data_supported, is_btf_datasec_supported, is_btf_decl_tag_supported, - is_btf_enum64_supported, is_btf_float_supported, is_btf_func_global_supported, - is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported, + bpf_load_btf, is_bpf_cookie_supported, is_bpf_global_data_supported, + is_btf_datasec_supported, is_btf_decl_tag_supported, is_btf_enum64_supported, + is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported, + is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported, is_probe_read_kernel_supported, is_prog_name_supported, retry_with_verifier_logs, - SyscallError, }, util::{bytes_of, bytes_of_slice, possible_cpus, POSSIBLE_CPUS}, }; @@ -482,23 +481,7 @@ impl<'a> BpfLoader<'a> { MapData::create_pinned(path, obj, &name, btf_fd)? } }; - let MapData { obj, fd, pinned: _ } = &mut map; - if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss { - bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_map_update_elem", - io_error, - }) - .map_err(MapError::from)?; - } - if obj.section_kind() == BpfSectionKind::Rodata { - bpf_map_freeze(fd.as_fd()) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_map_freeze", - io_error, - }) - .map_err(MapError::from)?; - } + map.finalize()?; maps.insert(name, map); } @@ -510,7 +493,7 @@ impl<'a> BpfLoader<'a> { obj.relocate_maps( maps.iter() - .map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), &data.obj)), + .map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), data.obj())), &text_sections, )?; obj.relocate_calls(&text_sections)?; @@ -691,7 +674,7 @@ impl<'a> BpfLoader<'a> { if !*allow_unsupported_maps { maps.iter().try_for_each(|(_, x)| match x { Map::Unsupported(map) => Err(BpfError::MapError(MapError::Unsupported { - map_type: map.obj.map_type(), + map_type: map.obj().map_type(), })), _ => Ok(()), })?; @@ -705,7 +688,7 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { let name = data.0; let map = data.1; let map_type = - bpf_map_type::try_from(map.obj.map_type()).map_err(|e| MapError::InvalidMapType { + bpf_map_type::try_from(map.obj().map_type()).map_err(|e| MapError::InvalidMapType { map_type: e.map_type, })?; let map = match map_type { diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 85ba5d94..f5052ed5 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -64,11 +64,11 @@ use log::warn; use thiserror::Error; use crate::{ - obj::{self, parse_map_info}, + obj::{self, parse_map_info, BpfSectionKind}, pin::PinError, sys::{ - bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key, - bpf_pin_object, SyscallError, + bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_info_by_fd, + bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, SyscallError, }, util::nr_cpus, PinningType, Pod, @@ -408,8 +408,8 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { /// You should never need to use this unless you're implementing a new map type. #[derive(Debug)] pub struct MapData { - pub(crate) obj: obj::Map, - pub(crate) fd: MapFd, + obj: obj::Map, + fd: MapFd, /// Indicates if this map has been pinned to bpffs pub pinned: bool, } @@ -489,6 +489,27 @@ impl MapData { } } + pub(crate) fn finalize(&mut self) -> Result<(), MapError> { + let Self { obj, fd, pinned: _ } = self; + if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss { + bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_update_elem", + io_error, + }) + .map_err(MapError::from)?; + } + if obj.section_kind() == BpfSectionKind::Rodata { + bpf_map_freeze(fd.as_fd()) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_freeze", + io_error, + }) + .map_err(MapError::from)?; + } + Ok(()) + } + /// Loads a map from a pinned path in bpffs. pub fn from_pin>(path: P) -> Result { use std::os::unix::ffi::OsStrExt as _; @@ -561,6 +582,15 @@ impl MapData { } = self; fd } + + pub(crate) fn obj(&self) -> &obj::Map { + let Self { + obj, + fd: _, + pinned: _, + } = self; + obj + } } /// An iterable map From 0dacb34d449f71b1998b0a23cd58c0023277c2ef Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 1 Sep 2023 13:40:43 -0400 Subject: [PATCH 30/95] maps: fix typos, avoid fallible conversions --- aya/src/maps/mod.rs | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index f5052ed5..163ce127 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -59,7 +59,7 @@ use std::{ }; use crate::util::KernelVersion; -use libc::{getrlimit, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; +use libc::{getrlimit, rlim_t, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; use log::warn; use thiserror::Error; @@ -198,20 +198,6 @@ impl AsFd for MapFd { } } -#[derive(PartialEq, Eq, PartialOrd, Ord)] -struct RlimitSize(usize); -impl fmt::Display for RlimitSize { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0 < 1024 { - write!(f, "{} bytes", self.0) - } else if self.0 < 1024 * 1024 { - write!(f, "{} KiB", self.0 / 1024) - } else { - write!(f, "{} MiB", self.0 / 1024 / 1024) - } - } -} - /// Raises a warning about rlimit. Should be used only if creating a map was not /// successful. fn maybe_warn_rlimit() { @@ -220,15 +206,28 @@ fn maybe_warn_rlimit() { if ret == 0 { let limit = unsafe { limit.assume_init() }; - let limit: RlimitSize = RlimitSize(limit.rlim_cur.try_into().unwrap()); - if limit.0 == RLIM_INFINITY.try_into().unwrap() { + if limit.rlim_cur == RLIM_INFINITY { return; } + struct HumanSize(rlim_t); + + impl fmt::Display for HumanSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let &Self(size) = self; + if size < 1024 { + write!(f, "{} bytes", size) + } else if size < 1024 * 1024 { + write!(f, "{} KiB", size / 1024) + } else { + write!(f, "{} MiB", size / 1024 / 1024) + } + } + } warn!( - "RLIMIT_MEMLOCK value is {}, not RLIM_INFNITY; if experiencing problems with creating \ - maps, try raising RMILIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \ - for size of your maps", - limit + "RLIMIT_MEMLOCK value is {}, not RLIM_INFINITY; if experiencing problems with creating \ + maps, try raising RLIMIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \ + for the size of your maps", + HumanSize(limit.rlim_cur) ); } } From 0f4021ec89ef2dc5c28355ecfde4b2c53b4b6429 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Mon, 18 Sep 2023 17:32:37 +0100 Subject: [PATCH 31/95] aya: Remove MapData::pinned BPF objects can be pinned multiple times, to multiple different places. Tracking whether or not a map is pinned in a bool is therefore not sufficient. We could track this in a HashSet, but there is really no reason to track it at all. Signed-off-by: Dave Tucker --- aya/src/maps/mod.rs | 45 +++++++++++----------------------------- aya/src/pin.rs | 6 ------ xtask/public-api/aya.txt | 3 --- 3 files changed, 12 insertions(+), 42 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 163ce127..6331e3a4 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -409,8 +409,6 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { pub struct MapData { obj: obj::Map, fd: MapFd, - /// Indicates if this map has been pinned to bpffs - pub pinned: bool, } impl MapData { @@ -439,11 +437,7 @@ impl MapData { } })?; let fd = MapFd(fd); - Ok(Self { - obj, - fd, - pinned: false, - }) + Ok(Self { obj, fd }) } pub(crate) fn create_pinned>( @@ -471,11 +465,7 @@ impl MapData { }) { Ok(fd) => { let fd = MapFd(fd); - Ok(Self { - obj, - fd, - pinned: false, - }) + Ok(Self { obj, fd }) } Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; @@ -489,7 +479,7 @@ impl MapData { } pub(crate) fn finalize(&mut self) -> Result<(), MapError> { - let Self { obj, fd, pinned: _ } = self; + let Self { obj, fd } = self; if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss { bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0) .map_err(|(_, io_error)| SyscallError { @@ -534,7 +524,6 @@ impl MapData { Ok(Self { obj: parse_map_info(info, PinningType::ByName), fd, - pinned: true, }) } @@ -550,44 +539,35 @@ impl MapData { Ok(Self { obj: parse_map_info(info, PinningType::None), fd, - pinned: false, }) } pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { use std::os::unix::ffi::OsStrExt as _; - let Self { fd, pinned, obj: _ } = self; - if *pinned { - return Err(PinError::AlreadyPinned { name: name.into() }); - } + let Self { fd, obj: _ } = self; let path = path.as_ref().join(name); - let path_string = CString::new(path.as_os_str().as_bytes()) - .map_err(|error| PinError::InvalidPinPath { path, error })?; + let path_string = CString::new(path.as_os_str().as_bytes()).map_err(|error| { + PinError::InvalidPinPath { + path: path.clone(), + error, + } + })?; bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, })?; - *pinned = true; Ok(()) } /// Returns the file descriptor of the map. pub fn fd(&self) -> &MapFd { - let Self { - obj: _, - fd, - pinned: _, - } = self; + let Self { obj: _, fd } = self; fd } pub(crate) fn obj(&self) -> &obj::Map { - let Self { - obj, - fd: _, - pinned: _, - } = self; + let Self { obj, fd: _ } = self; obj } } @@ -825,7 +805,6 @@ mod tests { Ok(MapData { obj: _, fd, - pinned: false }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) ); } diff --git a/aya/src/pin.rs b/aya/src/pin.rs index 743df95f..43e197ff 100644 --- a/aya/src/pin.rs +++ b/aya/src/pin.rs @@ -6,12 +6,6 @@ use thiserror::Error; /// An error ocurred working with a pinned BPF object. #[derive(Error, Debug)] pub enum PinError { - /// The object has already been pinned. - #[error("the BPF object `{name}` has already been pinned")] - AlreadyPinned { - /// Object name. - name: String, - }, /// The object FD is not known by Aya. #[error("the BPF object `{name}`'s FD is not known")] NoFd { diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 3f6dfad6..59711f67 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1218,7 +1218,6 @@ pub fn aya::maps::lpm_trie::LpmTrie::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::from(t: T) -> T pub struct aya::maps::MapData -pub aya::maps::MapData::pinned: bool impl aya::maps::MapData pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option>) -> core::result::Result pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd @@ -1738,8 +1737,6 @@ pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData pub mod aya::pin pub enum aya::pin::PinError -pub aya::pin::PinError::AlreadyPinned -pub aya::pin::PinError::AlreadyPinned::name: alloc::string::String pub aya::pin::PinError::InvalidPinPath pub aya::pin::PinError::InvalidPinPath::error: alloc::ffi::c_str::NulError pub aya::pin::PinError::InvalidPinPath::path: std::path::PathBuf From 938f979fe7a82f6d31c3b7e926682864c507e381 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Tue, 19 Sep 2023 13:38:20 +0100 Subject: [PATCH 32/95] aya: Make MapData::pin pub This is to solve a use-case where a user (in this case bpfd) may want to: - MapData::from_pin to open a pinned map from bpffs - MapData::pin to pin that object into another bpffs Both operations should be easily accomplished without needing to cast a MapData into a concrete Map type - e.g aya::maps::HashMap. Signed-off-by: Dave Tucker --- aya/src/maps/mod.rs | 33 +++++++++++++++++++++++++++++---- xtask/public-api/aya.txt | 1 + 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 6331e3a4..191c5883 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -469,7 +469,8 @@ impl MapData { } Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; - map.pin(name, path).map_err(|error| MapError::PinError { + let path = path.join(name); + map.pin(&path).map_err(|error| MapError::PinError { name: Some(name.into()), error, })?; @@ -542,14 +543,38 @@ impl MapData { }) } - pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { + /// Allows the map to be pinned to the provided path. + /// + /// Any directories in the the path provided should have been created by the caller. + /// The path must be on a BPF filesystem. + /// + /// # Errors + /// + /// Returns a [`PinError::SyscallError`] if the underlying syscall fails. + /// This may also happen if the path already exists, in which case the wrapped + /// [`std::io::Error`] kind will be [`std::io::ErrorKind::AlreadyExists`]. + /// Returns a [`PinError::InvalidPinPath`] if the path provided cannot be + /// converted to a [`CString`]. + /// + /// # Example + /// + /// ```no_run + /// # let mut bpf = aya::Bpf::load(&[])?; + /// # use aya::maps::MapData; + /// + /// let mut map = MapData::from_pin("/sys/fs/bpf/my_map")?; + /// map.pin("/sys/fs/bpf/my_map2")?; + /// + /// # Ok::<(), Box>(()) + /// ``` + pub fn pin>(&mut self, path: P) -> Result<(), PinError> { use std::os::unix::ffi::OsStrExt as _; let Self { fd, obj: _ } = self; - let path = path.as_ref().join(name); + let path = path.as_ref(); let path_string = CString::new(path.as_os_str().as_bytes()).map_err(|error| { PinError::InvalidPinPath { - path: path.clone(), + path: path.to_path_buf(), error, } })?; diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 59711f67..1cf6eb5c 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1223,6 +1223,7 @@ pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: c pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result +pub fn aya::maps::MapData::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::fmt::Debug for aya::maps::MapData pub fn aya::maps::MapData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::MapData From ec8293ab8644cbf8f1c4e7b1c44b286bc0ae969a Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Mon, 30 May 2022 11:43:38 +0100 Subject: [PATCH 33/95] aya: Implement XDP Map Types This commit adds implementations for: - xskmap - devmap - devmap_hash - cpumap Which can all be used to redirect XDP packets to various different locations Signed-off-by: Dave Tucker --- aya/src/maps/mod.rs | 2 + aya/src/maps/xdp/cpu_map.rs | 120 +++++++++++++++++++++++++++++++ aya/src/maps/xdp/dev_map.rs | 117 ++++++++++++++++++++++++++++++ aya/src/maps/xdp/dev_map_hash.rs | 118 ++++++++++++++++++++++++++++++ aya/src/maps/xdp/mod.rs | 10 +++ aya/src/maps/xdp/xsk_map.rs | 118 ++++++++++++++++++++++++++++++ 6 files changed, 485 insertions(+) create mode 100644 aya/src/maps/xdp/cpu_map.rs create mode 100644 aya/src/maps/xdp/dev_map.rs create mode 100644 aya/src/maps/xdp/dev_map_hash.rs create mode 100644 aya/src/maps/xdp/mod.rs create mode 100644 aya/src/maps/xdp/xsk_map.rs diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 191c5883..190d8c67 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -83,6 +83,7 @@ pub mod queue; pub mod sock; pub mod stack; pub mod stack_trace; +pub mod xdp; pub use array::{Array, PerCpuArray, ProgramArray}; pub use bloom_filter::BloomFilter; @@ -96,6 +97,7 @@ pub use queue::Queue; pub use sock::{SockHash, SockMap}; pub use stack::Stack; pub use stack_trace::StackTraceMap; +pub use xdp::XskMap; #[derive(Error, Debug)] /// Errors occuring from working with Maps diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs new file mode 100644 index 00000000..2b6ba3cb --- /dev/null +++ b/aya/src/maps/xdp/cpu_map.rs @@ -0,0 +1,120 @@ +//! An array of available CPUs. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_CPUMAP, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of available CPUs. +/// +/// XDP programs can use this map to redirect packets to a target +/// CPU for processing. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::CpuMap; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS")?)?; +/// let flags = 0; +/// let queue_size = 2048; +/// for i in 0u32..8u32 { +/// cpumap.set(i, queue_size, flags); +/// } +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_CPUMAP")] +pub struct CpuMap> { + inner: T, +} + +impl> CpuMap { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_CPUMAP as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + let size = map.obj.def.value_size as usize; + if size != expected { + return Err(MapError::InvalidValueSize { size, expected }); + } + let _fd = map.fd_or_err()?; + + Ok(CpuMap { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.max_entries + } + + fn check_bounds(&self, index: u32) -> Result<(), MapError> { + let max_entries = self.inner.obj.def.max_entries; + if index >= self.inner.obj.def.max_entries { + Err(MapError::OutOfBounds { index, max_entries }) + } else { + Ok(()) + } + } +} + +impl + DerefMut> CpuMap { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + let fd = self.inner.fd_or_err()?; + self.check_bounds(index)?; + bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { + MapError::SyscallError { + call: "bpf_map_update_elem".to_owned(), + code, + io_error, + } + })?; + Ok(()) + } +} + +impl TryFrom for CpuMap { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + CpuMap::new(a) + } +} + +impl TryFrom for CpuMap { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + CpuMap::new(a) + } +} diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs new file mode 100644 index 00000000..365a5b1e --- /dev/null +++ b/aya/src/maps/xdp/dev_map.rs @@ -0,0 +1,117 @@ +//! An array of network devices. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of network devices. +/// +/// XDP programs can use this map to redirect to other network +/// devices. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::DevMap; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES")?)?; +/// let ifindex = 32u32; +/// devmap.set(ifindex, ifindex, 0); +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_DEVMAP")] +pub struct DevMap> { + inner: T, +} + +impl> DevMap { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_DEVMAP as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + let size = map.obj.def.value_size as usize; + if size != expected { + return Err(MapError::InvalidValueSize { size, expected }); + } + let _fd = map.fd_or_err()?; + + Ok(DevMap { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.max_entries + } + + fn check_bounds(&self, index: u32) -> Result<(), MapError> { + let max_entries = self.inner.obj.def.max_entries; + if index >= self.inner.obj.def.max_entries { + Err(MapError::OutOfBounds { index, max_entries }) + } else { + Ok(()) + } + } +} + +impl + DerefMut> DevMap { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + let fd = self.inner.fd_or_err()?; + self.check_bounds(index)?; + bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { + MapError::SyscallError { + call: "bpf_map_update_elem".to_owned(), + code, + io_error, + } + })?; + Ok(()) + } +} + +impl TryFrom for DevMap { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + DevMap::new(a) + } +} + +impl TryFrom for DevMap { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + DevMap::new(a) + } +} diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs new file mode 100644 index 00000000..4cf16762 --- /dev/null +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -0,0 +1,118 @@ +//! An array of network devices. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of network devices. +/// +/// XDP programs can use this map to redirect to other network +/// devices. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::DevMapHash; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES")?)?; +/// let flags = 0; +/// let ifindex = 32u32; +/// devmap.set(ifindex, ifindex, flags); +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] +pub struct DevMapHash> { + inner: T, +} + +impl> DevMapHash { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_DEVMAP_HASH as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + let size = map.obj.def.value_size as usize; + if size != expected { + return Err(MapError::InvalidValueSize { size, expected }); + } + let _fd = map.fd_or_err()?; + + Ok(DevMapHash { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.max_entries + } + + fn check_bounds(&self, index: u32) -> Result<(), MapError> { + let max_entries = self.inner.obj.def.max_entries; + if index >= self.inner.obj.def.max_entries { + Err(MapError::OutOfBounds { index, max_entries }) + } else { + Ok(()) + } + } +} + +impl + DerefMut> DevMapHash { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + let fd = self.inner.fd_or_err()?; + self.check_bounds(index)?; + bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { + MapError::SyscallError { + call: "bpf_map_update_elem".to_owned(), + code, + io_error, + } + })?; + Ok(()) + } +} + +impl TryFrom for DevMapHash { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + DevMapHash::new(a) + } +} + +impl TryFrom for DevMapHash { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + DevMapHash::new(a) + } +} diff --git a/aya/src/maps/xdp/mod.rs b/aya/src/maps/xdp/mod.rs new file mode 100644 index 00000000..6120dc90 --- /dev/null +++ b/aya/src/maps/xdp/mod.rs @@ -0,0 +1,10 @@ +//! XDP maps. +mod cpu_map; +mod dev_map; +mod dev_map_hash; +mod xsk_map; + +pub use cpu_map::CpuMap; +pub use dev_map::DevMap; +pub use dev_map_hash::DevMapHash; +pub use xsk_map::XskMap; diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs new file mode 100644 index 00000000..239c908c --- /dev/null +++ b/aya/src/maps/xdp/xsk_map.rs @@ -0,0 +1,118 @@ +//! An array of AF_XDP sockets. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, + os::unix::prelude::{AsRawFd, RawFd}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_XSKMAP, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of AF_XDP sockets. +/// +/// XDP programs can use this map to redirect packets to a target +/// AF_XDP socket using the `XDP_REDIRECT` action. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// # let socket_fd = 1; +/// use aya::maps::XskMap; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS")?)?; +/// // socket_fd is the RawFd of an AF_XDP socket +/// xskmap.set(0, socket_fd, 0); +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_XSKMAP")] +pub struct XskMap> { + inner: T, +} + +impl> XskMap { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_XSKMAP as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + let size = map.obj.def.value_size as usize; + if size != expected { + return Err(MapError::InvalidValueSize { size, expected }); + } + let _fd = map.fd_or_err()?; + + Ok(XskMap { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.max_entries + } + + fn check_bounds(&self, index: u32) -> Result<(), MapError> { + let max_entries = self.inner.obj.def.max_entries; + if index >= self.inner.obj.def.max_entries { + Err(MapError::OutOfBounds { index, max_entries }) + } else { + Ok(()) + } + } +} + +impl + DerefMut> XskMap { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { + let fd = self.inner.fd_or_err()?; + self.check_bounds(index)?; + bpf_map_update_elem(fd, &index, &value.as_raw_fd(), flags).map_err( + |(code, io_error)| MapError::SyscallError { + call: "bpf_map_update_elem".to_owned(), + code, + io_error, + }, + )?; + Ok(()) + } +} + +impl TryFrom for XskMap { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + XskMap::new(a) + } +} + +impl TryFrom for XskMap { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + XskMap::new(a) + } +} From e90d521a21ebea7129de140ab8ae84707b03cd65 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Mon, 30 May 2022 11:58:59 +0100 Subject: [PATCH 34/95] bpf: Implement XDP maps Signed-off-by: Dave Tucker --- bpf/aya-bpf/src/maps/mod.rs | 2 + bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 55 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/dev_map.rs | 55 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 55 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/mod.rs | 9 ++++ bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 55 ++++++++++++++++++++++++ 6 files changed, 231 insertions(+) create mode 100644 bpf/aya-bpf/src/maps/xdp/cpu_map.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/dev_map.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/mod.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/xsk_map.rs diff --git a/bpf/aya-bpf/src/maps/mod.rs b/bpf/aya-bpf/src/maps/mod.rs index 8fa375dd..b46bf084 100644 --- a/bpf/aya-bpf/src/maps/mod.rs +++ b/bpf/aya-bpf/src/maps/mod.rs @@ -17,6 +17,7 @@ pub mod sock_hash; pub mod sock_map; pub mod stack; pub mod stack_trace; +pub mod xdp; pub use array::Array; pub use bloom_filter::BloomFilter; @@ -30,3 +31,4 @@ pub use sock_hash::SockHash; pub use sock_map::SockMap; pub use stack::Stack; pub use stack_trace::StackTrace; +pub use xdp::{CpuMap, DevMap, DevMapHash, XskMap}; diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs new file mode 100644 index 00000000..bc16c271 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct CpuMap { + def: bpf_map_def, +} + +impl CpuMap { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> CpuMap { + CpuMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_CPUMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> CpuMap { + CpuMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_CPUMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs new file mode 100644 index 00000000..8a9415ec --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct DevMap { + def: bpf_map_def, +} + +impl DevMap { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMap { + DevMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> DevMap { + DevMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs new file mode 100644 index 00000000..6a0b1903 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct DevMapHash { + def: bpf_map_def, +} + +impl DevMapHash { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMapHash { + DevMapHash { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP_HASH, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> DevMapHash { + DevMapHash { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP_HASH, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/mod.rs b/bpf/aya-bpf/src/maps/xdp/mod.rs new file mode 100644 index 00000000..b7ced7b5 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/mod.rs @@ -0,0 +1,9 @@ +mod cpu_map; +mod dev_map; +mod dev_map_hash; +mod xsk_map; + +pub use cpu_map::CpuMap; +pub use dev_map::DevMap; +pub use dev_map_hash::DevMapHash; +pub use xsk_map::XskMap; diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs new file mode 100644 index 00000000..39fba557 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_XSKMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct XskMap { + def: bpf_map_def, +} + +impl XskMap { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> XskMap { + XskMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_XSKMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> XskMap { + XskMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_XSKMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} From ede3e91014075de01af02da624cad99861da2dad Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:15:37 +0200 Subject: [PATCH 35/95] aya: Update XDP maps implementations Map impls changed since this was first written. Fixes: 2b726c8 ("aya: Implement XDP Map Types") --- aya/src/bpf.rs | 4 + aya/src/maps/mod.rs | 18 ++++- aya/src/maps/xdp/cpu_map.rs | 111 +++++++++++++-------------- aya/src/maps/xdp/dev_map.rs | 112 ++++++++++++--------------- aya/src/maps/xdp/dev_map_hash.rs | 127 +++++++++++++------------------ aya/src/maps/xdp/xsk_map.rs | 87 +++++---------------- 6 files changed, 197 insertions(+), 262 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index a5fb9273..999271ec 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -707,6 +707,10 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { BPF_MAP_TYPE_STACK => Map::Stack(map), BPF_MAP_TYPE_STACK_TRACE => Map::StackTraceMap(map), BPF_MAP_TYPE_QUEUE => Map::Queue(map), + BPF_MAP_TYPE_CPUMAP => Map::CpuMap(map), + BPF_MAP_TYPE_DEVMAP => Map::DevMap(map), + BPF_MAP_TYPE_DEVMAP_HASH => Map::DevMapHash(map), + BPF_MAP_TYPE_XSKMAP => Map::XskMap(map), m => { warn!("The map {name} is of type {:#?} which is currently unsupported in Aya, use `allow_unsupported_maps()` to load it anyways", m); Map::Unsupported(map) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 190d8c67..2f7c556f 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -97,7 +97,7 @@ pub use queue::Queue; pub use sock::{SockHash, SockMap}; pub use stack::Stack; pub use stack_trace::StackTraceMap; -pub use xdp::XskMap; +pub use xdp::{CpuMap, DevMap, DevMapHash, XskMap}; #[derive(Error, Debug)] /// Errors occuring from working with Maps @@ -267,6 +267,14 @@ pub enum Map { StackTraceMap(MapData), /// A [`Queue`] map Queue(MapData), + /// A [`CpuMap`] map + CpuMap(MapData), + /// A [`DevMap`] map + DevMap(MapData), + /// A [`DevMapHash`] map + DevMapHash(MapData), + /// A [`XskMap`] map + XskMap(MapData), /// An unsupported map type Unsupported(MapData), } @@ -290,6 +298,10 @@ impl Map { Self::Stack(map) => map.obj.map_type(), Self::StackTraceMap(map) => map.obj.map_type(), Self::Queue(map) => map.obj.map_type(), + Self::CpuMap(map) => map.obj.map_type(), + Self::DevMap(map) => map.obj.map_type(), + Self::DevMapHash(map) => map.obj.map_type(), + Self::XskMap(map) => map.obj.map_type(), Self::Unsupported(map) => map.obj.map_type(), } } @@ -349,6 +361,10 @@ impl_try_from_map!(() { SockMap, PerfEventArray, StackTraceMap, + CpuMap, + DevMap, + DevMapHash, + XskMap, }); #[cfg(any(feature = "async_tokio", feature = "async_std"))] diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index 2b6ba3cb..cb6fbe45 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -1,15 +1,10 @@ //! An array of available CPUs. -use std::{ - convert::TryFrom, - mem, - ops::{Deref, DerefMut}, -}; +use std::borrow::{Borrow, BorrowMut}; use crate::{ - generated::bpf_map_type::BPF_MAP_TYPE_CPUMAP, - maps::{Map, MapError, MapRef, MapRefMut}, - sys::bpf_map_update_elem, + maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, + sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, }; /// An array of available CPUs. @@ -19,15 +14,18 @@ use crate::{ /// /// # Minimum kernel version /// -/// The minimum kernel version required to use this feature is 4.2. +/// The minimum kernel version required to use this feature is 4.15. /// /// # Examples /// ```no_run -/// # let bpf = aya::Bpf::load(&[])?; +/// # let elf_bytes = &[]; /// use aya::maps::xdp::CpuMap; -/// use std::convert::{TryFrom, TryInto}; /// -/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS")?)?; +/// let mut bpf = aya::BpfLoader::new() +/// .set_max_entries("CPUS", aya::util::nr_cpus().unwrap() as u32) +/// .load(elf_bytes) +/// .unwrap(); +/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS").unwrap())?; /// let flags = 0; /// let queue_size = 2048; /// for i in 0u32..8u32 { @@ -37,52 +35,51 @@ use crate::{ /// # Ok::<(), aya::BpfError>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_CPUMAP")] -pub struct CpuMap> { +pub struct CpuMap { inner: T, } -impl> CpuMap { - fn new(map: T) -> Result, MapError> { - let map_type = map.obj.def.map_type; - if map_type != BPF_MAP_TYPE_CPUMAP as u32 { - return Err(MapError::InvalidMapType { - map_type: map_type as u32, - }); - } - let expected = mem::size_of::(); - let size = map.obj.def.key_size as usize; - if size != expected { - return Err(MapError::InvalidKeySize { size, expected }); - } - - let expected = mem::size_of::(); - let size = map.obj.def.value_size as usize; - if size != expected { - return Err(MapError::InvalidValueSize { size, expected }); - } - let _fd = map.fd_or_err()?; +impl> CpuMap { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + check_kv_size::(data)?; - Ok(CpuMap { inner: map }) + Ok(Self { inner: map }) } /// Returns the number of elements in the array. /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. pub fn len(&self) -> u32 { - self.inner.obj.def.max_entries + self.inner.borrow().obj.max_entries() } - fn check_bounds(&self, index: u32) -> Result<(), MapError> { - let max_entries = self.inner.obj.def.max_entries; - if index >= self.inner.obj.def.max_entries { - Err(MapError::OutOfBounds { index, max_entries }) - } else { - Ok(()) - } + /// Returns the value stored at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_lookup_elem` fails. + pub fn get(&self, index: u32, flags: u64) -> Result { + let data = self.inner.borrow(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + + let value = + bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })?; + value.ok_or(MapError::KeyNotFound) + } + + /// An iterator over the elements of the map. + pub fn iter(&self) -> impl Iterator> + '_ { + (0..self.len()).map(move |i| self.get(i, 0)) } } -impl + DerefMut> CpuMap { +impl> CpuMap { /// Sets the value of the element at the given index. /// /// # Errors @@ -90,12 +87,12 @@ impl + DerefMut> CpuMap { /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { - let fd = self.inner.fd_or_err()?; - self.check_bounds(index)?; - bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { - MapError::SyscallError { - call: "bpf_map_update_elem".to_owned(), - code, + let data = self.inner.borrow_mut(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { + SyscallError { + call: "bpf_map_update_elem", io_error, } })?; @@ -103,18 +100,12 @@ impl + DerefMut> CpuMap { } } -impl TryFrom for CpuMap { - type Error = MapError; - - fn try_from(a: MapRef) -> Result, MapError> { - CpuMap::new(a) +impl> IterableMap for CpuMap { + fn map(&self) -> &MapData { + self.inner.borrow() } -} - -impl TryFrom for CpuMap { - type Error = MapError; - fn try_from(a: MapRefMut) -> Result, MapError> { - CpuMap::new(a) + fn get(&self, key: &u32) -> Result { + self.get(*key, 0) } } diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index 365a5b1e..b8fad587 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -1,15 +1,10 @@ //! An array of network devices. -use std::{ - convert::TryFrom, - mem, - ops::{Deref, DerefMut}, -}; +use std::borrow::{Borrow, BorrowMut}; use crate::{ - generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP, - maps::{Map, MapError, MapRef, MapRefMut}, - sys::bpf_map_update_elem, + maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, + sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, }; /// An array of network devices. @@ -19,67 +14,66 @@ use crate::{ /// /// # Minimum kernel version /// -/// The minimum kernel version required to use this feature is 4.2. +/// The minimum kernel version required to use this feature is 4.14. /// /// # Examples /// ```no_run -/// # let bpf = aya::Bpf::load(&[])?; +/// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::maps::xdp::DevMap; -/// use std::convert::{TryFrom, TryInto}; /// -/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES")?)?; -/// let ifindex = 32u32; -/// devmap.set(ifindex, ifindex, 0); +/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?; +/// let source = 32u32; +/// let dest = 42u32; +/// devmap.set(source, dest, 0); /// /// # Ok::<(), aya::BpfError>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_DEVMAP")] -pub struct DevMap> { +pub struct DevMap { inner: T, } -impl> DevMap { - fn new(map: T) -> Result, MapError> { - let map_type = map.obj.def.map_type; - if map_type != BPF_MAP_TYPE_DEVMAP as u32 { - return Err(MapError::InvalidMapType { - map_type: map_type as u32, - }); - } - let expected = mem::size_of::(); - let size = map.obj.def.key_size as usize; - if size != expected { - return Err(MapError::InvalidKeySize { size, expected }); - } - - let expected = mem::size_of::(); - let size = map.obj.def.value_size as usize; - if size != expected { - return Err(MapError::InvalidValueSize { size, expected }); - } - let _fd = map.fd_or_err()?; +impl> DevMap { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + check_kv_size::(data)?; - Ok(DevMap { inner: map }) + Ok(Self { inner: map }) } /// Returns the number of elements in the array. /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. pub fn len(&self) -> u32 { - self.inner.obj.def.max_entries + self.inner.borrow().obj.max_entries() } - fn check_bounds(&self, index: u32) -> Result<(), MapError> { - let max_entries = self.inner.obj.def.max_entries; - if index >= self.inner.obj.def.max_entries { - Err(MapError::OutOfBounds { index, max_entries }) - } else { - Ok(()) - } + /// Returns the value stored at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_lookup_elem` fails. + pub fn get(&self, index: u32, flags: u64) -> Result { + let data = self.inner.borrow(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + + let value = + bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })?; + value.ok_or(MapError::KeyNotFound) + } + + /// An iterator over the elements of the array. + pub fn iter(&self) -> impl Iterator> + '_ { + (0..self.len()).map(move |i| self.get(i, 0)) } } -impl + DerefMut> DevMap { +impl> DevMap { /// Sets the value of the element at the given index. /// /// # Errors @@ -87,12 +81,12 @@ impl + DerefMut> DevMap { /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { - let fd = self.inner.fd_or_err()?; - self.check_bounds(index)?; - bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { - MapError::SyscallError { - call: "bpf_map_update_elem".to_owned(), - code, + let data = self.inner.borrow_mut(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { + SyscallError { + call: "bpf_map_update_elem", io_error, } })?; @@ -100,18 +94,12 @@ impl + DerefMut> DevMap { } } -impl TryFrom for DevMap { - type Error = MapError; - - fn try_from(a: MapRef) -> Result, MapError> { - DevMap::new(a) +impl> IterableMap for DevMap { + fn map(&self) -> &MapData { + self.inner.borrow() } -} - -impl TryFrom for DevMap { - type Error = MapError; - fn try_from(a: MapRefMut) -> Result, MapError> { - DevMap::new(a) + fn get(&self, key: &u32) -> Result { + self.get(*key, 0) } } diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 4cf16762..47eed67d 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -1,118 +1,99 @@ -//! An array of network devices. +//! An hashmap of network devices. -use std::{ - convert::TryFrom, - mem, - ops::{Deref, DerefMut}, -}; +use std::borrow::{Borrow, BorrowMut}; use crate::{ - generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH, - maps::{Map, MapError, MapRef, MapRefMut}, - sys::bpf_map_update_elem, + maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, + sys::{bpf_map_lookup_elem, SyscallError}, }; -/// An array of network devices. +/// An hashmap of network devices. /// /// XDP programs can use this map to redirect to other network /// devices. /// /// # Minimum kernel version /// -/// The minimum kernel version required to use this feature is 4.2. +/// The minimum kernel version required to use this feature is 5.4. /// /// # Examples /// ```no_run -/// # let bpf = aya::Bpf::load(&[])?; +/// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::maps::xdp::DevMapHash; -/// use std::convert::{TryFrom, TryInto}; /// -/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES")?)?; +/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?; /// let flags = 0; /// let ifindex = 32u32; -/// devmap.set(ifindex, ifindex, flags); +/// devmap.insert(ifindex, ifindex, flags); /// /// # Ok::<(), aya::BpfError>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] -pub struct DevMapHash> { +pub struct DevMapHash { inner: T, } -impl> DevMapHash { - fn new(map: T) -> Result, MapError> { - let map_type = map.obj.def.map_type; - if map_type != BPF_MAP_TYPE_DEVMAP_HASH as u32 { - return Err(MapError::InvalidMapType { - map_type: map_type as u32, - }); - } - let expected = mem::size_of::(); - let size = map.obj.def.key_size as usize; - if size != expected { - return Err(MapError::InvalidKeySize { size, expected }); - } - - let expected = mem::size_of::(); - let size = map.obj.def.value_size as usize; - if size != expected { - return Err(MapError::InvalidValueSize { size, expected }); - } - let _fd = map.fd_or_err()?; +impl> DevMapHash { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + check_kv_size::(data)?; - Ok(DevMapHash { inner: map }) + Ok(Self { inner: map }) } - /// Returns the number of elements in the array. + /// Returns the value stored at the given index. + /// + /// # Errors /// - /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. - pub fn len(&self) -> u32 { - self.inner.obj.def.max_entries + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_lookup_elem` fails. + pub fn get(&self, index: u32, flags: u64) -> Result { + let fd = self.inner.borrow().fd().as_fd(); + let value = + bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })?; + value.ok_or(MapError::KeyNotFound) + } + + /// An iterator over the elements of the devmap in arbitrary order. + pub fn iter(&self) -> MapIter<'_, u32, u32, Self> { + MapIter::new(self) } - fn check_bounds(&self, index: u32) -> Result<(), MapError> { - let max_entries = self.inner.obj.def.max_entries; - if index >= self.inner.obj.def.max_entries { - Err(MapError::OutOfBounds { index, max_entries }) - } else { - Ok(()) - } + /// An iterator visiting all keys in arbitrary order. + pub fn keys(&self) -> MapKeys<'_, u32> { + MapKeys::new(self.inner.borrow()) } } -impl + DerefMut> DevMapHash { - /// Sets the value of the element at the given index. +impl> DevMapHash { + /// Inserts a value in the map. /// /// # Errors /// - /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] - /// if `bpf_map_update_elem` fails. - pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { - let fd = self.inner.fd_or_err()?; - self.check_bounds(index)?; - bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { - MapError::SyscallError { - call: "bpf_map_update_elem".to_owned(), - code, - io_error, - } - })?; - Ok(()) + /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails. + pub fn insert(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + hash_map::insert(self.inner.borrow_mut(), &index, &value, flags) } -} - -impl TryFrom for DevMapHash { - type Error = MapError; - fn try_from(a: MapRef) -> Result, MapError> { - DevMapHash::new(a) + /// Remove a value from the map. + /// + /// # Errors + /// + /// Returns [`MapError::SyscallError`] if `bpf_map_delete_elem` fails. + pub fn remove(&mut self, key: u32) -> Result<(), MapError> { + hash_map::remove(self.inner.borrow_mut(), &key) } } -impl TryFrom for DevMapHash { - type Error = MapError; +impl> IterableMap for DevMapHash { + fn map(&self) -> &MapData { + self.inner.borrow() + } - fn try_from(a: MapRefMut) -> Result, MapError> { - DevMapHash::new(a) + fn get(&self, key: &u32) -> Result { + self.get(*key, 0) } } diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs index 239c908c..133173c0 100644 --- a/aya/src/maps/xdp/xsk_map.rs +++ b/aya/src/maps/xdp/xsk_map.rs @@ -1,16 +1,13 @@ //! An array of AF_XDP sockets. use std::{ - convert::TryFrom, - mem, - ops::{Deref, DerefMut}, - os::unix::prelude::{AsRawFd, RawFd}, + borrow::{Borrow, BorrowMut}, + os::fd::{AsFd, AsRawFd, RawFd}, }; use crate::{ - generated::bpf_map_type::BPF_MAP_TYPE_XSKMAP, - maps::{Map, MapError, MapRef, MapRefMut}, - sys::bpf_map_update_elem, + maps::{check_bounds, check_kv_size, MapData, MapError}, + sys::{bpf_map_update_elem, SyscallError}, }; /// An array of AF_XDP sockets. @@ -20,67 +17,41 @@ use crate::{ /// /// # Minimum kernel version /// -/// The minimum kernel version required to use this feature is 4.2. +/// The minimum kernel version required to use this feature is 4.18. /// /// # Examples /// ```no_run -/// # let bpf = aya::Bpf::load(&[])?; +/// # let mut bpf = aya::Bpf::load(&[])?; /// # let socket_fd = 1; /// use aya::maps::XskMap; -/// use std::convert::{TryFrom, TryInto}; /// -/// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS")?)?; +/// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS").unwrap())?; /// // socket_fd is the RawFd of an AF_XDP socket /// xskmap.set(0, socket_fd, 0); /// # Ok::<(), aya::BpfError>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_XSKMAP")] -pub struct XskMap> { +pub struct XskMap { inner: T, } -impl> XskMap { - fn new(map: T) -> Result, MapError> { - let map_type = map.obj.def.map_type; - if map_type != BPF_MAP_TYPE_XSKMAP as u32 { - return Err(MapError::InvalidMapType { - map_type: map_type as u32, - }); - } - let expected = mem::size_of::(); - let size = map.obj.def.key_size as usize; - if size != expected { - return Err(MapError::InvalidKeySize { size, expected }); - } +impl> XskMap { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + check_kv_size::(data)?; - let expected = mem::size_of::(); - let size = map.obj.def.value_size as usize; - if size != expected { - return Err(MapError::InvalidValueSize { size, expected }); - } - let _fd = map.fd_or_err()?; - - Ok(XskMap { inner: map }) + Ok(Self { inner: map }) } /// Returns the number of elements in the array. /// /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. pub fn len(&self) -> u32 { - self.inner.obj.def.max_entries - } - - fn check_bounds(&self, index: u32) -> Result<(), MapError> { - let max_entries = self.inner.obj.def.max_entries; - if index >= self.inner.obj.def.max_entries { - Err(MapError::OutOfBounds { index, max_entries }) - } else { - Ok(()) - } + self.inner.borrow().obj.max_entries() } } -impl + DerefMut> XskMap { +impl> XskMap { /// Sets the value of the element at the given index. /// /// # Errors @@ -88,31 +59,15 @@ impl + DerefMut> XskMap { /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { - let fd = self.inner.fd_or_err()?; - self.check_bounds(index)?; - bpf_map_update_elem(fd, &index, &value.as_raw_fd(), flags).map_err( - |(code, io_error)| MapError::SyscallError { - call: "bpf_map_update_elem".to_owned(), - code, + let data = self.inner.borrow_mut(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + bpf_map_update_elem(fd, Some(&index), &value.as_raw_fd(), flags).map_err( + |(_, io_error)| SyscallError { + call: "bpf_map_update_elem", io_error, }, )?; Ok(()) } } - -impl TryFrom for XskMap { - type Error = MapError; - - fn try_from(a: MapRef) -> Result, MapError> { - XskMap::new(a) - } -} - -impl TryFrom for XskMap { - type Error = MapError; - - fn try_from(a: MapRefMut) -> Result, MapError> { - XskMap::new(a) - } -} From ad3087d7eb4f235c161dead521431ed1a5a6b500 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:15:41 +0200 Subject: [PATCH 36/95] bpf: Update XDP maps implementation The implementation changed since the original commit was written, and some mistakes went in: - missing bpf_redirect_map wrapper - extra bpf_map_lookup_elem on maps for which it is forbidden --- bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 33 +++++++++---------- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 36 +++++++++++++------- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 41 ++++++++++++++--------- bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 42 +++++++++++++++--------- 4 files changed, 93 insertions(+), 59 deletions(-) diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs index bc16c271..3cf970e5 100644 --- a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -1,22 +1,22 @@ -use core::{mem, ptr::NonNull}; - -use aya_bpf_cty::c_void; +use core::{cell::UnsafeCell, mem}; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, - helpers::bpf_map_lookup_elem, + helpers::bpf_redirect_map, maps::PinningType, }; #[repr(transparent)] pub struct CpuMap { - def: bpf_map_def, + def: UnsafeCell, } +unsafe impl Sync for CpuMap {} + impl CpuMap { pub const fn with_max_entries(max_entries: u32, flags: u32) -> CpuMap { CpuMap { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_CPUMAP, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, @@ -24,32 +24,31 @@ impl CpuMap { map_flags: flags, id: 0, pinning: PinningType::None as u32, - }, + }), } } pub const fn pinned(max_entries: u32, flags: u32) -> CpuMap { CpuMap { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_CPUMAP, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, - pinning: PinningType::None as u32, - }, + pinning: PinningType::ByName as u32, + }), } } - pub fn get(&mut self, index: u32) -> Option<&u32> { + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> u32 { unsafe { - let value = bpf_map_lookup_elem( - &mut self.def as *mut _ as *mut _, - &index as *const _ as *const c_void, - ); - // FIXME: alignment - NonNull::new(value as *mut u32).map(|p| p.as_ref()) + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags + // argument on error. Thus I have no idea why it returns a long (i64) instead of + // something saner, hence the unsigned_abs. + bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 } } } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index 8a9415ec..968deb69 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -1,22 +1,24 @@ -use core::{mem, ptr::NonNull}; +use core::{cell::UnsafeCell, mem, ptr::NonNull}; use aya_bpf_cty::c_void; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP}, - helpers::bpf_map_lookup_elem, + helpers::{bpf_map_lookup_elem, bpf_redirect_map}, maps::PinningType, }; #[repr(transparent)] pub struct DevMap { - def: bpf_map_def, + def: UnsafeCell, } +unsafe impl Sync for DevMap {} + impl DevMap { pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMap { DevMap { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, @@ -24,32 +26,42 @@ impl DevMap { map_flags: flags, id: 0, pinning: PinningType::None as u32, - }, + }), } } pub const fn pinned(max_entries: u32, flags: u32) -> DevMap { DevMap { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, - pinning: PinningType::None as u32, - }, + pinning: PinningType::ByName as u32, + }), } } - pub fn get(&mut self, index: u32) -> Option<&u32> { + #[inline(always)] + pub fn get(&self, index: u32) -> Option { unsafe { let value = bpf_map_lookup_elem( - &mut self.def as *mut _ as *mut _, + self.def.get() as *mut _, &index as *const _ as *const c_void, ); - // FIXME: alignment - NonNull::new(value as *mut u32).map(|p| p.as_ref()) + NonNull::new(value as *mut u32).map(|p| *p.as_ref()) + } + } + + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> u32 { + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags + // argument on error. Thus I have no idea why it returns a long (i64) instead of + // something saner, hence the unsigned_abs. + unsafe { + bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 } } } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index 6a0b1903..4933146b 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -1,22 +1,25 @@ -use core::{mem, ptr::NonNull}; +use core::{cell::UnsafeCell, mem, ptr::NonNull}; +use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_cty::c_void; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH}, - helpers::bpf_map_lookup_elem, + helpers::{bpf_map_lookup_elem, bpf_redirect_map}, maps::PinningType, }; #[repr(transparent)] pub struct DevMapHash { - def: bpf_map_def, + def: UnsafeCell, } +unsafe impl Sync for DevMapHash {} + impl DevMapHash { pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMapHash { DevMapHash { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP_HASH, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, @@ -24,32 +27,40 @@ impl DevMapHash { map_flags: flags, id: 0, pinning: PinningType::None as u32, - }, + }), } } pub const fn pinned(max_entries: u32, flags: u32) -> DevMapHash { DevMapHash { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP_HASH, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, - pinning: PinningType::None as u32, - }, + pinning: PinningType::ByName as u32, + }), } } - pub fn get(&mut self, index: u32) -> Option<&u32> { + #[inline(always)] + pub unsafe fn get(&self, index: u32) -> Option<&bpf_devmap_val> { + let value = bpf_map_lookup_elem( + self.def.get() as *mut _, + &index as *const _ as *const c_void, + ); + NonNull::new(value as *mut bpf_devmap_val).map(|p| p.as_ref()) + } + + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> u32 { unsafe { - let value = bpf_map_lookup_elem( - &mut self.def as *mut _ as *mut _, - &index as *const _ as *const c_void, - ); - // FIXME: alignment - NonNull::new(value as *mut u32).map(|p| p.as_ref()) + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags + // argument on error. Thus I have no idea why it returns a long (i64) instead of + // something saner, hence the unsigned_abs. + bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 } } } diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs index 39fba557..362f258e 100644 --- a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -1,22 +1,25 @@ -use core::{mem, ptr::NonNull}; +use core::{cell::UnsafeCell, mem, ptr::NonNull}; +use aya_bpf_bindings::bindings::bpf_xdp_sock; use aya_bpf_cty::c_void; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_XSKMAP}, - helpers::bpf_map_lookup_elem, + helpers::{bpf_map_lookup_elem, bpf_redirect_map}, maps::PinningType, }; #[repr(transparent)] pub struct XskMap { - def: bpf_map_def, + def: UnsafeCell, } +unsafe impl Sync for XskMap {} + impl XskMap { pub const fn with_max_entries(max_entries: u32, flags: u32) -> XskMap { XskMap { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_XSKMAP, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, @@ -24,32 +27,41 @@ impl XskMap { map_flags: flags, id: 0, pinning: PinningType::None as u32, - }, + }), } } pub const fn pinned(max_entries: u32, flags: u32) -> XskMap { XskMap { - def: bpf_map_def { + def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_XSKMAP, key_size: mem::size_of::() as u32, value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, - pinning: PinningType::None as u32, - }, + pinning: PinningType::ByName as u32, + }), } } - pub fn get(&mut self, index: u32) -> Option<&u32> { + #[inline(always)] + pub unsafe fn get(&self, index: u32) -> Option<&bpf_xdp_sock> { + let value = bpf_map_lookup_elem( + self.def.get() as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut bpf_xdp_sock).map(|p| p.as_ref()) + } + + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> u32 { unsafe { - let value = bpf_map_lookup_elem( - &mut self.def as *mut _ as *mut _, - &index as *const _ as *const c_void, - ); - // FIXME: alignment - NonNull::new(value as *mut u32).map(|p| p.as_ref()) + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags + // argument on error. Thus I have no idea why it returns a long (i64) instead of + // something saner, hence the unsigned_abs. + bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 } } } From 4452364c41c73943d4603fce4bab24ce70a2eff2 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:15:44 +0200 Subject: [PATCH 37/95] macros: add 'map' option to xdp macro This option allows to place the program in the specific sections to chain programs with devmaps and cpumaps. --- aya-bpf-macros/src/xdp.rs | 157 +++++++++++++++++++++++-- test/integration-ebpf/Cargo.toml | 8 ++ test/integration-ebpf/src/redirect.rs | 44 +++++++ test/integration-ebpf/src/xdp_sec.rs | 26 ++++ test/integration-test/src/lib.rs | 2 + test/integration-test/src/tests.rs | 1 + test/integration-test/src/tests/xdp.rs | 35 ++++++ 7 files changed, 264 insertions(+), 9 deletions(-) create mode 100644 test/integration-ebpf/src/redirect.rs create mode 100644 test/integration-ebpf/src/xdp_sec.rs create mode 100644 test/integration-test/src/tests/xdp.rs diff --git a/aya-bpf-macros/src/xdp.rs b/aya-bpf-macros/src/xdp.rs index 9a5ff36a..6a8f61e7 100644 --- a/aya-bpf-macros/src/xdp.rs +++ b/aya-bpf-macros/src/xdp.rs @@ -1,31 +1,52 @@ -use std::borrow::Cow; - use proc_macro2::TokenStream; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{Error, ItemFn, Result}; -use crate::args::{err_on_unknown_args, pop_bool_arg, Args}; +use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg, Args}; pub(crate) struct Xdp { item: ItemFn, frags: bool, + map: Option, +} + +#[derive(Clone, Copy)] +pub(crate) enum XdpMap { + CpuMap, + DevMap, } impl Xdp { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; let mut args: Args = syn::parse2(attrs)?; + let frags = pop_bool_arg(&mut args, "frags"); + let map = match pop_string_arg(&mut args, "map").as_deref() { + Some("cpumap") => Some(XdpMap::CpuMap), + Some("devmap") => Some(XdpMap::DevMap), + Some(name) => { + return Err(Error::new_spanned( + "map", + format!("invalid value. expected 'cpumap' or 'devmap', found '{name}'"), + )) + } + None => None, + }; + err_on_unknown_args(&args)?; - Ok(Xdp { item, frags }) + Ok(Xdp { item, frags, map }) } pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = if self.frags { - "xdp.frags".into() - } else { - "xdp".into() + let mut section_name = vec![if self.frags { "xdp.frags" } else { "xdp" }]; + match self.map { + Some(XdpMap::CpuMap) => section_name.push("cpumap"), + Some(XdpMap::DevMap) => section_name.push("devmap"), + None => (), }; + let section_name = section_name.join("/"); + let fn_vis = &self.item.vis; let fn_name = self.item.sig.ident.clone(); let item = &self.item; @@ -97,4 +118,122 @@ mod tests { }; assert_eq!(expected.to_string(), expanded.to_string()); } + + #[test] + fn test_xdp_cpumap() { + let prog = Xdp::parse( + parse_quote! { map = "cpumap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp/cpumap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } + + #[test] + fn test_xdp_devmap() { + let prog = Xdp::parse( + parse_quote! { map = "devmap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp/devmap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } + + #[test] + #[should_panic(expected = "Invalid value. Expected 'cpumap' or 'devmap', found 'badmap'")] + fn test_xdp_bad_map() { + Xdp::parse( + parse_quote! { map = "badmap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + } + + #[test] + fn test_xdp_frags_cpumap() { + let prog = Xdp::parse( + parse_quote! { frags, map = "cpumap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp.frags/cpumap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } + + #[test] + fn test_xdp_frags_devmap() { + let prog = Xdp::parse( + parse_quote! { frags, map = "devmap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp.frags/devmap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } } diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index 12b04546..e72e0a87 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -43,3 +43,11 @@ path = "src/bpf_probe_read.rs" [[bin]] name = "two_progs" path = "src/two_progs.rs" + +[[bin]] +name = "redirect" +path = "src/redirect.rs" + +[[bin]] +name = "xdp_sec" +path = "src/xdp_sec.rs" diff --git a/test/integration-ebpf/src/redirect.rs b/test/integration-ebpf/src/redirect.rs new file mode 100644 index 00000000..827ea451 --- /dev/null +++ b/test/integration-ebpf/src/redirect.rs @@ -0,0 +1,44 @@ +#![no_std] +#![no_main] + +use aya_bpf::{ + bindings::xdp_action, + macros::{map, xdp}, + maps::{CpuMap, DevMap, DevMapHash, XskMap}, + programs::XdpContext, +}; + +#[map] +static SOCKS: XskMap = XskMap::with_max_entries(1, 0); +#[map] +static DEVS: DevMap = DevMap::with_max_entries(1, 0); +#[map] +static DEVS_HASH: DevMapHash = DevMapHash::with_max_entries(1, 0); +#[map] +static CPUS: CpuMap = CpuMap::with_max_entries(1, 0); + +#[xdp] +pub fn redirect_sock(_ctx: XdpContext) -> u32 { + SOCKS.redirect(0, xdp_action::XDP_ABORTED as u64) +} + +#[xdp] +pub fn redirect_dev(_ctx: XdpContext) -> u32 { + DEVS.redirect(0, xdp_action::XDP_ABORTED as u64) +} + +#[xdp] +pub fn redirect_dev_hash(_ctx: XdpContext) -> u32 { + DEVS_HASH.redirect(10, xdp_action::XDP_ABORTED as u64) +} + +#[xdp] +pub fn redirect_cpu(_ctx: XdpContext) -> u32 { + CPUS.redirect(0, xdp_action::XDP_ABORTED as u64) +} + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/test/integration-ebpf/src/xdp_sec.rs b/test/integration-ebpf/src/xdp_sec.rs new file mode 100644 index 00000000..5e64f56a --- /dev/null +++ b/test/integration-ebpf/src/xdp_sec.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] + +use aya_bpf::{bindings::xdp_action::XDP_PASS, macros::xdp, programs::XdpContext}; + +macro_rules! probe { + ($name:ident, ($($arg:ident $(= $value:literal)?),*) ) => { + #[xdp($($arg $(= $value)?),*)] + pub fn $name(_ctx: XdpContext) -> u32 { + XDP_PASS + } + }; +} + +probe!(xdp_plain, ()); +probe!(xdp_frags, (frags)); +probe!(xdp_cpumap, (map = "cpumap")); +probe!(xdp_devmap, (map = "devmap")); +probe!(xdp_frags_cpumap, (frags, map = "cpumap")); +probe!(xdp_frags_devmap, (frags, map = "devmap")); + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 08911a4e..79be5fd3 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -19,6 +19,8 @@ pub const RELOCATIONS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), " pub const TWO_PROGS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/two_progs")); pub const BPF_PROBE_READ: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/bpf_probe_read")); +pub const REDIRECT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/redirect")); +pub const XDP_SEC: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/xdp_sec")); #[cfg(test)] mod tests; diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index dd8565b0..3a995180 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -6,3 +6,4 @@ mod log; mod rbpf; mod relocations; mod smoke; +mod xdp; diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs new file mode 100644 index 00000000..0c2f56da --- /dev/null +++ b/test/integration-test/src/tests/xdp.rs @@ -0,0 +1,35 @@ +use object::{Object, ObjectSection, ObjectSymbol, SymbolSection}; + +#[test] +fn prog_sections() { + let obj_file = object::File::parse(crate::XDP_SEC).unwrap(); + + ensure_symbol(&obj_file, "xdp", "xdp_plain"); + ensure_symbol(&obj_file, "xdp.frags", "xdp_frags"); + ensure_symbol(&obj_file, "xdp/cpumap", "xdp_cpumap"); + ensure_symbol(&obj_file, "xdp/devmap", "xdp_devmap"); + ensure_symbol(&obj_file, "xdp.frags/cpumap", "xdp_frags_cpumap"); + ensure_symbol(&obj_file, "xdp.frags/devmap", "xdp_frags_devmap"); +} + +#[track_caller] +fn ensure_symbol(obj_file: &object::File, sec_name: &str, sym_name: &str) { + let sec = obj_file.section_by_name(sec_name).unwrap_or_else(|| { + let secs = obj_file + .sections() + .flat_map(|sec| sec.name().ok().map(|name| name.to_owned())) + .collect::>(); + panic!("section {sec_name} not found. available sections: {secs:?}"); + }); + let sec = SymbolSection::Section(sec.index()); + + let syms = obj_file + .symbols() + .filter(|sym| sym.section() == sec) + .filter_map(|sym| sym.name().ok()) + .collect::>(); + assert!( + syms.contains(&sym_name), + "symbol not found. available symbols in section: {syms:?}" + ); +} From 139f3826383daba9a10dc7aacc079f31d28980fc Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:15:49 +0200 Subject: [PATCH 38/95] aya: add support for map-bound XDP programs Such programs are to be bound to cpumap or devmap instead of the usual network interfaces. --- aya-obj/src/obj.rs | 23 +++++++++++----- aya-obj/src/programs/mod.rs | 2 ++ aya-obj/src/programs/xdp.rs | 24 +++++++++++++++++ aya/src/bpf.rs | 14 +++++++--- aya/src/programs/mod.rs | 1 - aya/src/programs/xdp.rs | 35 ++++++++++++++++++++++--- test/integration-test/src/tests/load.rs | 6 +++-- test/integration-test/src/tests/rbpf.rs | 7 +++-- test/integration-test/src/tests/xdp.rs | 13 +++++++++ 9 files changed, 107 insertions(+), 18 deletions(-) create mode 100644 aya-obj/src/programs/xdp.rs diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index deadeeaf..ce599d3c 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -19,6 +19,7 @@ use crate::{ btf::BtfFeatures, generated::{BPF_CALL, BPF_JMP, BPF_K}, maps::{BtfMap, LegacyMap, Map, MINIMUM_MAP_SIZE}, + programs::XdpAttachType, relocation::*, util::HashMap, }; @@ -204,8 +205,6 @@ pub struct Function { /// - `struct_ops+` /// - `fmod_ret+`, `fmod_ret.s+` /// - `iter+`, `iter.s+` -/// - `xdp.frags/cpumap`, `xdp/cpumap` -/// - `xdp.frags/devmap`, `xdp/devmap` #[derive(Debug, Clone)] #[allow(missing_docs)] pub enum ProgramSection { @@ -221,6 +220,7 @@ pub enum ProgramSection { SocketFilter, Xdp { frags: bool, + attach_type: XdpAttachType, }, SkMsg, SkSkbStreamParser, @@ -283,8 +283,19 @@ impl FromStr for ProgramSection { "uprobe.s" => UProbe { sleepable: true }, "uretprobe" => URetProbe { sleepable: false }, "uretprobe.s" => URetProbe { sleepable: true }, - "xdp" => Xdp { frags: false }, - "xdp.frags" => Xdp { frags: true }, + "xdp" | "xdp.frags" => Xdp { + frags: kind == "xdp.frags", + attach_type: match pieces.next() { + None => XdpAttachType::Interface, + Some("cpumap") => XdpAttachType::CpuMap, + Some("devmap") => XdpAttachType::DevMap, + Some(_) => { + return Err(ParseError::InvalidProgramSection { + section: section.to_owned(), + }) + } + }, + }, "tp_btf" => BtfTracePoint, "tracepoint" | "tp" => TracePoint, "socket" => SocketFilter, @@ -2012,7 +2023,7 @@ mod tests { assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, - "xdp/foo", + "xdp", bytes_of(&fake_ins()), None )), @@ -2035,7 +2046,7 @@ mod tests { assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, - "xdp.frags/foo", + "xdp.frags", bytes_of(&fake_ins()), None )), diff --git a/aya-obj/src/programs/mod.rs b/aya-obj/src/programs/mod.rs index 4f76211a..6b66b005 100644 --- a/aya-obj/src/programs/mod.rs +++ b/aya-obj/src/programs/mod.rs @@ -3,7 +3,9 @@ pub mod cgroup_sock; pub mod cgroup_sock_addr; pub mod cgroup_sockopt; +pub mod xdp; pub use cgroup_sock::CgroupSockAttachType; pub use cgroup_sock_addr::CgroupSockAddrAttachType; pub use cgroup_sockopt::CgroupSockoptAttachType; +pub use xdp::XdpAttachType; diff --git a/aya-obj/src/programs/xdp.rs b/aya-obj/src/programs/xdp.rs new file mode 100644 index 00000000..17fab6ab --- /dev/null +++ b/aya-obj/src/programs/xdp.rs @@ -0,0 +1,24 @@ +//! XDP programs. + +use crate::generated::bpf_attach_type; + +/// Defines where to attach an `XDP` program. +#[derive(Copy, Clone, Debug)] +pub enum XdpAttachType { + /// Attach to a network interface. + Interface, + /// Attach to a cpumap. Requires kernel 5.9 or later. + CpuMap, + /// Attach to a devmap. Requires kernel 5.8 or later. + DevMap, +} + +impl From for bpf_attach_type { + fn from(value: XdpAttachType) -> Self { + match value { + XdpAttachType::Interface => bpf_attach_type::BPF_XDP, + XdpAttachType::CpuMap => bpf_attach_type::BPF_XDP_CPUMAP, + XdpAttachType::DevMap => bpf_attach_type::BPF_XDP_DEVMAP, + } + } +} diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 999271ec..0140886d 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -412,7 +412,10 @@ impl<'a> BpfLoader<'a> { | ProgramSection::URetProbe { sleepable: _ } | ProgramSection::TracePoint | ProgramSection::SocketFilter - | ProgramSection::Xdp { frags: _ } + | ProgramSection::Xdp { + frags: _, + attach_type: _, + } | ProgramSection::SkMsg | ProgramSection::SkSkbStreamParser | ProgramSection::SkSkbStreamVerdict @@ -556,13 +559,18 @@ impl<'a> BpfLoader<'a> { ProgramSection::SocketFilter => Program::SocketFilter(SocketFilter { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), - ProgramSection::Xdp { frags, .. } => { + ProgramSection::Xdp { + frags, attach_type, .. + } => { let mut data = ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); if *frags { data.flags = BPF_F_XDP_HAS_FRAGS; } - Program::Xdp(Xdp { data }) + Program::Xdp(Xdp { + data, + attach_type: *attach_type, + }) } ProgramSection::SkMsg => Program::SkMsg(SkMsg { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 0952a348..bb9622fe 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -879,7 +879,6 @@ macro_rules! impl_from_pin { impl_from_pin!( TracePoint, SocketFilter, - Xdp, SkMsg, CgroupSysctl, LircMode2, diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 89574328..481d95d9 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -12,18 +12,21 @@ use std::{ hash::Hash, io, os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, RawFd}, + path::Path, }; use thiserror::Error; use crate::{ generated::{ - bpf_attach_type, bpf_link_type, bpf_prog_type, XDP_FLAGS_DRV_MODE, XDP_FLAGS_HW_MODE, - XDP_FLAGS_REPLACE, XDP_FLAGS_SKB_MODE, XDP_FLAGS_UPDATE_IF_NOEXIST, + bpf_link_type, bpf_prog_type, XDP_FLAGS_DRV_MODE, XDP_FLAGS_HW_MODE, XDP_FLAGS_REPLACE, + XDP_FLAGS_SKB_MODE, XDP_FLAGS_UPDATE_IF_NOEXIST, }, + obj::programs::XdpAttachType, programs::{ define_link_wrapper, load_program, FdLink, Link, LinkError, ProgramData, ProgramError, }, sys::{bpf_link_create, bpf_link_get_info_by_fd, bpf_link_update, netlink_set_xdp_fd}, + VerifierLogLevel, }; /// The type returned when attaching an [`Xdp`] program fails on kernels `< 5.9`. @@ -80,12 +83,13 @@ bitflags::bitflags! { #[doc(alias = "BPF_PROG_TYPE_XDP")] pub struct Xdp { pub(crate) data: ProgramData, + pub(crate) attach_type: XdpAttachType, } impl Xdp { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - self.data.expected_attach_type = Some(bpf_attach_type::BPF_XDP); + self.data.expected_attach_type = Some(self.attach_type.into()); load_program(bpf_prog_type::BPF_PROG_TYPE_XDP, &mut self.data) } @@ -133,10 +137,18 @@ impl Xdp { let prog_fd = prog_fd.as_fd(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 9, 0) { + // Unwrap safety: the function starts with `self.fd()?` that will succeed if and only + // if the program has been loaded, i.e. there is an fd. We get one by: + // - Using `Xdp::from_pin` that sets `expected_attach_type` + // - Calling `Xdp::attach` that sets `expected_attach_type`, as geting an `Xdp` + // instance trhough `Xdp:try_from(Program)` does not set any fd. + // So, in all cases where we have an fd, we have an expected_attach_type. Thus, if we + // reach this point, expected_attach_type is guaranteed to be Some(_). + let attach_type = self.data.expected_attach_type.unwrap(); let link_fd = bpf_link_create( prog_fd, LinkTarget::IfIndex(if_index), - bpf_attach_type::BPF_XDP, + attach_type, None, flags.bits(), ) @@ -163,6 +175,21 @@ impl Xdp { } } + /// Creates a program from a pinned entry on a bpffs. + /// + /// Existing links will not be populated. To work with existing links you should use [`crate::programs::links::PinnedLink`]. + /// + /// On drop, any managed links are detached and the program is unloaded. This will not result in + /// the program being unloaded from the kernel if it is still pinned. + pub fn from_pin>( + path: P, + attach_type: XdpAttachType, + ) -> Result { + let mut data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?; + data.expected_attach_type = Some(attach_type.into()); + Ok(Self { data, attach_type }) + } + /// Detaches the program. /// /// See [Xdp::attach]. diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 4c99a008..d444b95d 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -9,6 +9,7 @@ use aya::{ util::KernelVersion, Bpf, }; +use aya_obj::programs::XdpAttachType; const MAX_RETRIES: usize = 100; const RETRY_DURATION: time::Duration = time::Duration::from_millis(10); @@ -283,7 +284,7 @@ fn pin_lifecycle() { // 2. Load program from bpffs but don't attach it { - let _ = Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); + let _ = Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); } // should still be loaded since prog was pinned @@ -291,7 +292,8 @@ fn pin_lifecycle() { // 3. Load program from bpffs and attach { - let mut prog = Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); + let mut prog = + Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index 9caab94c..3d2c0c97 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -2,7 +2,7 @@ use core::{mem::size_of, ptr::null_mut, slice::from_raw_parts}; use std::collections::HashMap; use assert_matches::assert_matches; -use aya_obj::{generated::bpf_insn, Object, ProgramSection}; +use aya_obj::{generated::bpf_insn, programs::XdpAttachType, Object, ProgramSection}; #[test] fn run_with_rbpf() { @@ -11,7 +11,10 @@ fn run_with_rbpf() { assert_eq!(object.programs.len(), 1); assert_matches!( object.programs["pass"].section, - ProgramSection::Xdp { frags: true } + ProgramSection::Xdp { + frags: true, + attach_type: XdpAttachType::Interface + } ); let instructions = &object diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index 0c2f56da..566ca5e5 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -1,3 +1,4 @@ +use aya::Bpf; use object::{Object, ObjectSection, ObjectSymbol, SymbolSection}; #[test] @@ -33,3 +34,15 @@ fn ensure_symbol(obj_file: &object::File, sec_name: &str, sym_name: &str) { "symbol not found. available symbols in section: {syms:?}" ); } + +#[test] +fn map_load() { + let bpf = Bpf::load(crate::XDP_SEC).unwrap(); + + bpf.program("xdp_plain").unwrap(); + bpf.program("xdp_frags").unwrap(); + bpf.program("xdp_cpumap").unwrap(); + bpf.program("xdp_devmap").unwrap(); + bpf.program("xdp_frags_cpumap").unwrap(); + bpf.program("xdp_frags_devmap").unwrap(); +} From 0647927e32333de662c6a065d5f5b9761c429e68 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:10 +0200 Subject: [PATCH 39/95] xdp: add support for chained xdp programs in {cpu,dev}map set/insert functions can now take an optional bpf program fd to run once the packet has been redirected from the main probe --- aya/src/maps/xdp/cpu_map.rs | 55 +++++++++++++++++++---- aya/src/maps/xdp/dev_map.rs | 56 ++++++++++++++++++++---- aya/src/maps/xdp/dev_map_hash.rs | 48 ++++++++++++++++---- bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 6 ++- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 5 ++- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 4 +- test/integration-ebpf/src/redirect.rs | 31 ++++++++++++- test/integration-test/src/tests/xdp.rs | 52 +++++++++++++++++++++- 8 files changed, 222 insertions(+), 35 deletions(-) diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index cb6fbe45..b01fc050 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -1,10 +1,17 @@ //! An array of available CPUs. -use std::borrow::{Borrow, BorrowMut}; +use std::{ + borrow::{Borrow, BorrowMut}, + num::NonZeroU32, + os::fd::AsRawFd, +}; + +use aya_obj::generated::{bpf_cpumap_val, bpf_cpumap_val__bindgen_ty_1}; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, + Pod, }; /// An array of available CPUs. @@ -29,7 +36,7 @@ use crate::{ /// let flags = 0; /// let queue_size = 2048; /// for i in 0u32..8u32 { -/// cpumap.set(i, queue_size, flags); +/// cpumap.set(i, queue_size, None::, flags); /// } /// /// # Ok::<(), aya::BpfError>(()) @@ -42,7 +49,7 @@ pub struct CpuMap { impl> CpuMap { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - check_kv_size::(data)?; + check_kv_size::(data)?; Ok(Self { inner: map }) } @@ -60,7 +67,7 @@ impl> CpuMap { /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_lookup_elem` fails. - pub fn get(&self, index: u32, flags: u64) -> Result { + pub fn get(&self, index: u32, flags: u64) -> Result { let data = self.inner.borrow(); check_bounds(data, index)?; let fd = data.fd().as_fd(); @@ -70,11 +77,18 @@ impl> CpuMap { call: "bpf_map_lookup_elem", io_error, })?; - value.ok_or(MapError::KeyNotFound) + let value: bpf_cpumap_val = value.ok_or(MapError::KeyNotFound)?; + + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241 + Ok(CpuMapValue { + qsize: value.qsize, + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) } /// An iterator over the elements of the map. - pub fn iter(&self) -> impl Iterator> + '_ { + pub fn iter(&self) -> impl Iterator> + '_ { (0..self.len()).map(move |i| self.get(i, 0)) } } @@ -86,10 +100,25 @@ impl> CpuMap { /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. - pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + pub fn set( + &mut self, + index: u32, + value: u32, + program: Option, + flags: u64, + ) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; let fd = data.fd().as_fd(); + + let value = bpf_cpumap_val { + qsize: value, + bpf_prog: bpf_cpumap_val__bindgen_ty_1 { + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 + fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), + }, + }; bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", @@ -100,12 +129,20 @@ impl> CpuMap { } } -impl> IterableMap for CpuMap { +impl> IterableMap for CpuMap { fn map(&self) -> &MapData { self.inner.borrow() } - fn get(&self, key: &u32) -> Result { + fn get(&self, key: &u32) -> Result { self.get(*key, 0) } } + +unsafe impl Pod for bpf_cpumap_val {} + +#[derive(Clone, Copy, Debug)] +pub struct CpuMapValue { + pub qsize: u32, + pub prog_id: Option, +} diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index b8fad587..44c1d27a 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -1,10 +1,17 @@ //! An array of network devices. -use std::borrow::{Borrow, BorrowMut}; +use std::{ + borrow::{Borrow, BorrowMut}, + num::NonZeroU32, + os::fd::AsRawFd, +}; + +use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, + Pod, }; /// An array of network devices. @@ -24,7 +31,7 @@ use crate::{ /// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?; /// let source = 32u32; /// let dest = 42u32; -/// devmap.set(source, dest, 0); +/// devmap.set(source, dest, None::, 0); /// /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -36,7 +43,7 @@ pub struct DevMap { impl> DevMap { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - check_kv_size::(data)?; + check_kv_size::(data)?; Ok(Self { inner: map }) } @@ -54,7 +61,7 @@ impl> DevMap { /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_lookup_elem` fails. - pub fn get(&self, index: u32, flags: u64) -> Result { + pub fn get(&self, index: u32, flags: u64) -> Result { let data = self.inner.borrow(); check_bounds(data, index)?; let fd = data.fd().as_fd(); @@ -64,11 +71,18 @@ impl> DevMap { call: "bpf_map_lookup_elem", io_error, })?; - value.ok_or(MapError::KeyNotFound) + let value: bpf_devmap_val = value.ok_or(MapError::KeyNotFound)?; + + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 + Ok(DevMapValue { + ifindex: value.ifindex, + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) } /// An iterator over the elements of the array. - pub fn iter(&self) -> impl Iterator> + '_ { + pub fn iter(&self) -> impl Iterator> + '_ { (0..self.len()).map(move |i| self.get(i, 0)) } } @@ -80,10 +94,26 @@ impl> DevMap { /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. - pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + pub fn set( + &mut self, + index: u32, + value: u32, + program: Option, + flags: u64, + ) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; let fd = data.fd().as_fd(); + + let value = bpf_devmap_val { + ifindex: value, + bpf_prog: bpf_devmap_val__bindgen_ty_1 { + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), + }, + }; bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", @@ -94,12 +124,20 @@ impl> DevMap { } } -impl> IterableMap for DevMap { +impl> IterableMap for DevMap { fn map(&self) -> &MapData { self.inner.borrow() } - fn get(&self, key: &u32) -> Result { + fn get(&self, key: &u32) -> Result { self.get(*key, 0) } } + +unsafe impl Pod for bpf_devmap_val {} + +#[derive(Clone, Copy, Debug)] +pub struct DevMapValue { + pub ifindex: u32, + pub prog_id: Option, +} diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 47eed67d..06d53258 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -1,12 +1,20 @@ //! An hashmap of network devices. -use std::borrow::{Borrow, BorrowMut}; +use std::{ + borrow::{Borrow, BorrowMut}, + num::NonZeroU32, + os::fd::AsRawFd, +}; + +use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; use crate::{ maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, sys::{bpf_map_lookup_elem, SyscallError}, }; +use super::dev_map::DevMapValue; + /// An hashmap of network devices. /// /// XDP programs can use this map to redirect to other network @@ -24,7 +32,7 @@ use crate::{ /// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?; /// let flags = 0; /// let ifindex = 32u32; -/// devmap.insert(ifindex, ifindex, flags); +/// devmap.insert(ifindex, ifindex, None::, flags); /// /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -36,7 +44,7 @@ pub struct DevMapHash { impl> DevMapHash { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - check_kv_size::(data)?; + check_kv_size::(data)?; Ok(Self { inner: map }) } @@ -47,18 +55,25 @@ impl> DevMapHash { /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_lookup_elem` fails. - pub fn get(&self, index: u32, flags: u64) -> Result { + pub fn get(&self, index: u32, flags: u64) -> Result { let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, })?; - value.ok_or(MapError::KeyNotFound) + let value: bpf_devmap_val = value.ok_or(MapError::KeyNotFound)?; + + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 + Ok(DevMapValue { + ifindex: value.ifindex, + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) } /// An iterator over the elements of the devmap in arbitrary order. - pub fn iter(&self) -> MapIter<'_, u32, u32, Self> { + pub fn iter(&self) -> MapIter<'_, u32, DevMapValue, Self> { MapIter::new(self) } @@ -74,7 +89,22 @@ impl> DevMapHash { /// # Errors /// /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails. - pub fn insert(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + pub fn insert( + &mut self, + index: u32, + value: u32, + program: Option, + flags: u64, + ) -> Result<(), MapError> { + let value = bpf_devmap_val { + ifindex: value, + bpf_prog: bpf_devmap_val__bindgen_ty_1 { + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), + }, + }; hash_map::insert(self.inner.borrow_mut(), &index, &value, flags) } @@ -88,12 +118,12 @@ impl> DevMapHash { } } -impl> IterableMap for DevMapHash { +impl> IterableMap for DevMapHash { fn map(&self) -> &MapData { self.inner.borrow() } - fn get(&self, key: &u32) -> Result { + fn get(&self, key: &u32) -> Result { self.get(*key, 0) } } diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs index 3cf970e5..f1d224b3 100644 --- a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -1,5 +1,7 @@ use core::{cell::UnsafeCell, mem}; +use aya_bpf_bindings::bindings::bpf_cpumap_val; + use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, helpers::bpf_redirect_map, @@ -19,7 +21,7 @@ impl CpuMap { def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_CPUMAP, key_size: mem::size_of::() as u32, - value_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, @@ -33,7 +35,7 @@ impl CpuMap { def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_CPUMAP, key_size: mem::size_of::() as u32, - value_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index 968deb69..85064141 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -1,5 +1,6 @@ use core::{cell::UnsafeCell, mem, ptr::NonNull}; +use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_cty::c_void; use crate::{ @@ -21,7 +22,7 @@ impl DevMap { def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP, key_size: mem::size_of::() as u32, - value_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, @@ -35,7 +36,7 @@ impl DevMap { def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP, key_size: mem::size_of::() as u32, - value_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index 4933146b..6560bfc8 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -22,7 +22,7 @@ impl DevMapHash { def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP_HASH, key_size: mem::size_of::() as u32, - value_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, @@ -36,7 +36,7 @@ impl DevMapHash { def: UnsafeCell::new(bpf_map_def { type_: BPF_MAP_TYPE_DEVMAP_HASH, key_size: mem::size_of::() as u32, - value_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, max_entries, map_flags: flags, id: 0, diff --git a/test/integration-ebpf/src/redirect.rs b/test/integration-ebpf/src/redirect.rs index 827ea451..5817b418 100644 --- a/test/integration-ebpf/src/redirect.rs +++ b/test/integration-ebpf/src/redirect.rs @@ -4,7 +4,7 @@ use aya_bpf::{ bindings::xdp_action, macros::{map, xdp}, - maps::{CpuMap, DevMap, DevMapHash, XskMap}, + maps::{Array, CpuMap, DevMap, DevMapHash, XskMap}, programs::XdpContext, }; @@ -17,6 +17,13 @@ static DEVS_HASH: DevMapHash = DevMapHash::with_max_entries(1, 0); #[map] static CPUS: CpuMap = CpuMap::with_max_entries(1, 0); +/// Hits of a probe, used to test program chaining through CpuMap/DevMap. +/// The first slot counts how many times the "raw" xdp program got executed, while the second slot +/// counts how many times the map programs got executed. +/// This allows the test harness to assert that a specific step got executed. +#[map] +static mut HITS: Array = Array::with_max_entries(2, 0); + #[xdp] pub fn redirect_sock(_ctx: XdpContext) -> u32 { SOCKS.redirect(0, xdp_action::XDP_ABORTED as u64) @@ -24,19 +31,41 @@ pub fn redirect_sock(_ctx: XdpContext) -> u32 { #[xdp] pub fn redirect_dev(_ctx: XdpContext) -> u32 { + inc_hit(0); DEVS.redirect(0, xdp_action::XDP_ABORTED as u64) } #[xdp] pub fn redirect_dev_hash(_ctx: XdpContext) -> u32 { + inc_hit(0); DEVS_HASH.redirect(10, xdp_action::XDP_ABORTED as u64) } #[xdp] pub fn redirect_cpu(_ctx: XdpContext) -> u32 { + inc_hit(0); CPUS.redirect(0, xdp_action::XDP_ABORTED as u64) } +#[xdp(map = "cpumap")] +pub fn redirect_cpu_chain(_ctx: XdpContext) -> u32 { + inc_hit(1); + xdp_action::XDP_PASS +} + +#[xdp(map = "devmap")] +pub fn redirect_dev_chain(_ctx: XdpContext) -> u32 { + inc_hit(1); + xdp_action::XDP_PASS +} + +#[inline(always)] +fn inc_hit(index: u32) { + if let Some(hit) = unsafe { HITS.get_ptr_mut(index) } { + unsafe { *hit += 1 }; + } +} + #[cfg(not(test))] #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index 566ca5e5..b0c25bff 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -1,6 +1,14 @@ -use aya::Bpf; +use std::{net::UdpSocket, os::fd::AsFd, time::Duration}; + +use aya::{ + maps::{Array, CpuMap}, + programs::{Xdp, XdpFlags}, + Bpf, +}; use object::{Object, ObjectSection, ObjectSymbol, SymbolSection}; +use crate::utils::NetNsGuard; + #[test] fn prog_sections() { let obj_file = object::File::parse(crate::XDP_SEC).unwrap(); @@ -46,3 +54,45 @@ fn map_load() { bpf.program("xdp_frags_cpumap").unwrap(); bpf.program("xdp_frags_devmap").unwrap(); } + +#[test] +fn cpumap_chain() { + let _netns = NetNsGuard::new(); + + let mut bpf = Bpf::load(crate::REDIRECT).unwrap(); + + // Load our cpumap and our canary map + let mut cpus: CpuMap<_> = bpf.take_map("CPUS").unwrap().try_into().unwrap(); + let hits: Array<_, u32> = bpf.take_map("HITS").unwrap().try_into().unwrap(); + + let xdp_chain_fd = { + // Load the chained program to run on the target CPU + let xdp: &mut Xdp = bpf + .program_mut("redirect_cpu_chain") + .unwrap() + .try_into() + .unwrap(); + xdp.load().unwrap(); + xdp.fd().unwrap() + }; + cpus.set(0, 2048, Some(xdp_chain_fd.as_fd()), 0).unwrap(); + + // Load the main program + let xdp: &mut Xdp = bpf.program_mut("redirect_cpu").unwrap().try_into().unwrap(); + xdp.load().unwrap(); + xdp.attach("lo", XdpFlags::default()).unwrap(); + + let sock = UdpSocket::bind("127.0.0.1:1777").unwrap(); + sock.set_read_timeout(Some(Duration::from_millis(1))) + .unwrap(); + sock.send_to(b"hello cpumap", "127.0.0.1:1777").unwrap(); + + // Read back the packet to ensure it wenth through the entire network stack, including our two + // probes. + let mut buf = vec![0u8; 1000]; + let n = sock.recv(&mut buf).unwrap(); + + assert_eq!(&buf[..n], b"hello cpumap"); + assert_eq!(hits.get(&0, 0).unwrap(), 1); + assert_eq!(hits.get(&1, 0).unwrap(), 1); +} From f7fbbcd0e5cad297ddc5407e201580f878b4c5ee Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:16 +0200 Subject: [PATCH 40/95] aya: fix docstring missing trailing period --- aya/src/maps/mod.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 2f7c556f..e0d2e0ff 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -237,43 +237,43 @@ fn maybe_warn_rlimit() { /// eBPF map types. #[derive(Debug)] pub enum Map { - /// A [`Array`] map + /// An [`Array`] map. Array(MapData), - /// A [`PerCpuArray`] map + /// A [`PerCpuArray`] map. PerCpuArray(MapData), - /// A [`ProgramArray`] map + /// A [`ProgramArray`] map. ProgramArray(MapData), - /// A [`HashMap`] map + /// A [`HashMap`] map. HashMap(MapData), - /// A [`PerCpuHashMap`] map + /// A [`PerCpuHashMap`] map. PerCpuHashMap(MapData), /// A [`HashMap`] map that uses a LRU eviction policy. LruHashMap(MapData), /// A [`PerCpuHashMap`] map that uses a LRU eviction policy. PerCpuLruHashMap(MapData), - /// A [`PerfEventArray`] map + /// A [`PerfEventArray`] map. PerfEventArray(MapData), - /// A [`SockMap`] map + /// A [`SockMap`] map. SockMap(MapData), - /// A [`SockHash`] map + /// A [`SockHash`] map. SockHash(MapData), - /// A [`BloomFilter`] map + /// A [`BloomFilter`] map. BloomFilter(MapData), - /// A [`LpmTrie`] map + /// A [`LpmTrie`] map. LpmTrie(MapData), - /// A [`Stack`] map + /// A [`Stack`] map. Stack(MapData), - /// A [`StackTraceMap`] map + /// A [`StackTraceMap`] map. StackTraceMap(MapData), - /// A [`Queue`] map + /// A [`Queue`] map. Queue(MapData), - /// A [`CpuMap`] map + /// A [`CpuMap`] map. CpuMap(MapData), - /// A [`DevMap`] map + /// A [`DevMap`] map. DevMap(MapData), - /// A [`DevMapHash`] map + /// A [`DevMapHash`] map. DevMapHash(MapData), - /// A [`XskMap`] map + /// A [`XskMap`] map. XskMap(MapData), /// An unsupported map type Unsupported(MapData), From db496330737c387cb7a8ff49b0228813ccb5bee3 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:18 +0200 Subject: [PATCH 41/95] bpf: make xdp maps functions safe Values in those map are small enough to return copied values instead of reference to values. --- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 4 ++-- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 16 ++++++++-------- bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 15 ++++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index 85064141..ca54da42 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -46,13 +46,13 @@ impl DevMap { } #[inline(always)] - pub fn get(&self, index: u32) -> Option { + pub fn get(&self, index: u32) -> Option { unsafe { let value = bpf_map_lookup_elem( self.def.get() as *mut _, &index as *const _ as *const c_void, ); - NonNull::new(value as *mut u32).map(|p| *p.as_ref()) + NonNull::new(value as *mut bpf_devmap_val).map(|p| *p.as_ref()) } } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index 6560bfc8..87a61299 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -46,21 +46,21 @@ impl DevMapHash { } #[inline(always)] - pub unsafe fn get(&self, index: u32) -> Option<&bpf_devmap_val> { - let value = bpf_map_lookup_elem( - self.def.get() as *mut _, - &index as *const _ as *const c_void, - ); - NonNull::new(value as *mut bpf_devmap_val).map(|p| p.as_ref()) + pub fn get(&self, key: u32) -> Option { + unsafe { + let value = + bpf_map_lookup_elem(self.def.get() as *mut _, &key as *const _ as *const c_void); + NonNull::new(value as *mut bpf_devmap_val).map(|p| *p.as_ref()) + } } #[inline(always)] - pub fn redirect(&self, index: u32, flags: u64) -> u32 { + pub fn redirect(&self, key: u32, flags: u64) -> u32 { unsafe { // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // argument on error. Thus I have no idea why it returns a long (i64) instead of // something saner, hence the unsigned_abs. - bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 + bpf_redirect_map(self.def.get() as *mut _, key.into(), flags).unsigned_abs() as u32 } } } diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs index 362f258e..a5e12767 100644 --- a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -46,13 +46,14 @@ impl XskMap { } #[inline(always)] - pub unsafe fn get(&self, index: u32) -> Option<&bpf_xdp_sock> { - let value = bpf_map_lookup_elem( - self.def.get() as *mut _, - &index as *const _ as *const c_void, - ); - // FIXME: alignment - NonNull::new(value as *mut bpf_xdp_sock).map(|p| p.as_ref()) + pub fn get(&self, index: u32) -> Option { + unsafe { + let value = bpf_map_lookup_elem( + self.def.get() as *mut _, + &index as *const _ as *const c_void, + ); + NonNull::new(value as *mut bpf_xdp_sock).map(|p| p.as_ref().queue_id) + } } #[inline(always)] From 9ed1d3d2811db89dc7314914d92922c54032382c Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:22 +0200 Subject: [PATCH 42/95] bpf: add documentation for XDP maps --- aya-bpf-macros/src/lib.rs | 29 +++++++ aya/src/maps/xdp/cpu_map.rs | 35 ++++++--- aya/src/maps/xdp/dev_map.rs | 18 ++++- aya/src/maps/xdp/dev_map_hash.rs | 37 +++++---- aya/src/maps/xdp/xsk_map.rs | 10 ++- bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 68 ++++++++++++++++ bpf/aya-bpf/src/maps/xdp/dev_map.rs | 76 ++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 78 +++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 99 ++++++++++++++++++++++++ 9 files changed, 416 insertions(+), 34 deletions(-) diff --git a/aya-bpf-macros/src/lib.rs b/aya-bpf-macros/src/lib.rs index 5696b82d..bdac2795 100644 --- a/aya-bpf-macros/src/lib.rs +++ b/aya-bpf-macros/src/lib.rs @@ -128,6 +128,35 @@ pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream { } } +/// Marks a function as an eBPF XDP program that can be attached to a network interface. +/// +/// On some NIC drivers, XDP probes are compatible with jumbo frames through the use of +/// multi-buffer packets. Programs can opt-in this support by passing the `frags` argument. +/// +/// XDP programs can also be chained through the use of CPU maps and dev maps, but must opt-in +/// with the `map = "cpumap"` or `map = "devmap"` arguments. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.8. +/// +/// # Examples +/// +/// ```no_run +/// use aya_bpf::{bindings::xdp_action::XDP_PASS, macros::xdp, programs::XdpContext}; +/// +/// #[xdp(frags)] +/// pub fn xdp(ctx: XdpContext) -> u32 { +/// match unsafe { try_xdp(ctx) } { +/// Ok(ret) => ret, +/// Err(ret) => ret, +/// } +/// } +/// +/// unsafe fn try_xdp(_ctx: XdpContext) -> Result { +/// Ok(XDP_PASS) +/// } +/// ``` #[proc_macro_error] #[proc_macro_attribute] pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream { diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index b01fc050..3fb4934f 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -61,19 +61,19 @@ impl> CpuMap { self.inner.borrow().obj.max_entries() } - /// Returns the value stored at the given index. + /// Returns the queue size and possible program for a given CPU index. /// /// # Errors /// - /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] - /// if `bpf_map_lookup_elem` fails. - pub fn get(&self, index: u32, flags: u64) -> Result { + /// Returns [`MapError::OutOfBounds`] if `cpu_index` is out of bounds, + /// [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. + pub fn get(&self, cpu_index: u32, flags: u64) -> Result { let data = self.inner.borrow(); - check_bounds(data, index)?; + check_bounds(data, cpu_index)?; let fd = data.fd().as_fd(); let value = - bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { + bpf_map_lookup_elem(fd, &cpu_index, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, })?; @@ -94,7 +94,18 @@ impl> CpuMap { } impl> CpuMap { - /// Sets the value of the element at the given index. + /// Sets the queue size at the given CPU index, and optionally a chained program. + /// + /// When sending the packet to the CPU at the given index, the kernel will queue up to + /// `queue_size` packets before dropping them. + /// + /// Another XDP program can be passed in that will be run on the target CPU, instead of the CPU + /// that receives the packets. This allows to perform minimal computations on CPUs that + /// directly handle packets from a NIC's RX queues, and perform possibly heavier ones in other, + /// less busy CPUs. + /// + /// Note that only XDP programs with the `map = "cpumap"` argument can be passed. See the + /// kernel-space `aya_bpf::xdp` for more information. /// /// # Errors /// @@ -102,24 +113,24 @@ impl> CpuMap { /// if `bpf_map_update_elem` fails. pub fn set( &mut self, - index: u32, - value: u32, + cpu_index: u32, + queue_size: u32, program: Option, flags: u64, ) -> Result<(), MapError> { let data = self.inner.borrow_mut(); - check_bounds(data, index)?; + check_bounds(data, cpu_index)?; let fd = data.fd().as_fd(); let value = bpf_cpumap_val { - qsize: value, + qsize: queue_size, bpf_prog: bpf_cpumap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), }, }; - bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { + bpf_map_update_elem(fd, Some(&cpu_index), &value, flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", io_error, diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index 44c1d27a..2a2797e8 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -55,7 +55,7 @@ impl> DevMap { self.inner.borrow().obj.max_entries() } - /// Returns the value stored at the given index. + /// Returns the target ifindex and possible program at a given index. /// /// # Errors /// @@ -88,7 +88,17 @@ impl> DevMap { } impl> DevMap { - /// Sets the value of the element at the given index. + /// Sets the target ifindex at index, and optionally a chained program. + /// + /// When redirecting using `index`, packets will be transmitted by the interface with + /// `ifindex`. + /// + /// Another XDP program can be passed in that will be run before actual transmission. It can be + /// used to modify the packet before transmission with NIC specific data (MAC address update, + /// checksum computations, etc) or other purposes. + /// + /// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the + /// kernel-space `aya_bpf::xdp` for more information. /// /// # Errors /// @@ -97,7 +107,7 @@ impl> DevMap { pub fn set( &mut self, index: u32, - value: u32, + ifindex: u32, program: Option, flags: u64, ) -> Result<(), MapError> { @@ -106,7 +116,7 @@ impl> DevMap { let fd = data.fd().as_fd(); let value = bpf_devmap_val { - ifindex: value, + ifindex, bpf_prog: bpf_devmap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 06d53258..34ad39ac 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -49,19 +49,17 @@ impl> DevMapHash { Ok(Self { inner: map }) } - /// Returns the value stored at the given index. + /// Returns the target ifindex and possible program for a given key. /// /// # Errors /// - /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] - /// if `bpf_map_lookup_elem` fails. - pub fn get(&self, index: u32, flags: u64) -> Result { + /// Returns [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. + pub fn get(&self, key: u32, flags: u64) -> Result { let fd = self.inner.borrow().fd().as_fd(); - let value = - bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { - call: "bpf_map_lookup_elem", - io_error, - })?; + let value = bpf_map_lookup_elem(fd, &key, flags).map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })?; let value: bpf_devmap_val = value.ok_or(MapError::KeyNotFound)?; // SAFETY: map writes use fd, map reads use id. @@ -84,20 +82,29 @@ impl> DevMapHash { } impl> DevMapHash { - /// Inserts a value in the map. + /// Inserts an ifindex and optionally a chained program in the map. + /// + /// When redirecting using `key`, packets will be transmitted by the interface with `ifindex`. + /// + /// Another XDP program can be passed in that will be run before actual transmission. It can be + /// used to modify the packet before transmission with NIC specific data (MAC address update, + /// checksum computations, etc) or other purposes. + /// + /// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the + /// kernel-space `aya_bpf::xdp` for more information. /// /// # Errors /// /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn insert( &mut self, - index: u32, - value: u32, + key: u32, + ifindex: u32, program: Option, flags: u64, ) -> Result<(), MapError> { let value = bpf_devmap_val { - ifindex: value, + ifindex, bpf_prog: bpf_devmap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 @@ -105,10 +112,10 @@ impl> DevMapHash { fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), }, }; - hash_map::insert(self.inner.borrow_mut(), &index, &value, flags) + hash_map::insert(self.inner.borrow_mut(), &key, &value, flags) } - /// Remove a value from the map. + /// Removes a value from the map. /// /// # Errors /// diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs index 133173c0..99477dbd 100644 --- a/aya/src/maps/xdp/xsk_map.rs +++ b/aya/src/maps/xdp/xsk_map.rs @@ -52,17 +52,21 @@ impl> XskMap { } impl> XskMap { - /// Sets the value of the element at the given index. + /// Sets the `AF_XDP` socket at a given index. + /// + /// When redirecting a packet, the `AF_XDP` socket at `index` will recieve the packet. Note + /// that it will do so only if the socket is bound to the same queue the packet was recieved + /// on. /// /// # Errors /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. - pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { + pub fn set(&mut self, index: u32, socket_fd: impl AsRawFd, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; let fd = data.fd().as_fd(); - bpf_map_update_elem(fd, Some(&index), &value.as_raw_fd(), flags).map_err( + bpf_map_update_elem(fd, Some(&index), &socket_fd.as_raw_fd(), flags).map_err( |(_, io_error)| SyscallError { call: "bpf_map_update_elem", io_error, diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs index f1d224b3..df1a32d2 100644 --- a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -8,6 +8,28 @@ use crate::{ maps::PinningType, }; +/// An array of available CPUs. +/// +/// XDP programs can use this map to redirect packets to a target CPU for processing. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.15. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::CpuMap, programs::XdpContext}; +/// +/// #[map] +/// static MAP: CpuMap = CpuMap::with_max_entries(8, 0); +/// +/// #[xdp] +/// fn xdp(_ctx: XdpContext) -> i32 { +/// // Redirect to CPU 7 or drop packet if no entry found. +/// MAP.redirect(7, xdp_action::XDP_DROP as u64) +/// } +/// ``` #[repr(transparent)] pub struct CpuMap { def: UnsafeCell, @@ -16,6 +38,20 @@ pub struct CpuMap { unsafe impl Sync for CpuMap {} impl CpuMap { + /// Creates a [`CpuMap`] with a set maximum number of elements. + /// + /// In a CPU Map, an entry represents a CPU core. Thus there should be as many entries as there + /// are CPU cores on the system. It can be set to zero here, and updated by userspace at + /// runtime. Refer to the userspace documentation for more information. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::CpuMap}; + /// + /// #[map] + /// static MAP: CpuMap = CpuMap::with_max_entries(8, 0); + /// ``` pub const fn with_max_entries(max_entries: u32, flags: u32) -> CpuMap { CpuMap { def: UnsafeCell::new(bpf_map_def { @@ -30,6 +66,19 @@ impl CpuMap { } } + /// Creates a [`CpuMap`] with a set maximum number of elements that can be pinned to the BPF + /// File System (bpffs). + /// + /// See [`CpuMap::with_max_entries`] for more information. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::CpuMap}; + /// + /// #[map] + /// static MAP: CpuMap = CpuMap::pinned(8, 0); + /// ``` pub const fn pinned(max_entries: u32, flags: u32) -> CpuMap { CpuMap { def: UnsafeCell::new(bpf_map_def { @@ -44,6 +93,25 @@ impl CpuMap { } } + /// Redirects the current packet on the CPU at `index`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a CPU cannot be found. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::CpuMap, programs::XdpContext}; + /// + /// #[map] + /// static MAP: CpuMap = CpuMap::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(_ctx: XdpContext) -> u32 { + /// // Redirect to CPU 7 or drop packet if no entry found. + /// MAP.redirect(7, xdp_action::XDP_DROP as u64) + /// } + /// ``` #[inline(always)] pub fn redirect(&self, index: u32, flags: u64) -> u32 { unsafe { diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index ca54da42..66103758 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -9,6 +9,27 @@ use crate::{ maps::PinningType, }; +/// An array of network devices. +/// +/// XDP programs can use this map to redirect packets to other network deviecs. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.14. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMap, programs::XdpContext}; +/// +/// #[map] +/// static MAP: DevMap = DevMap::with_max_entries(1, 0); +/// +/// #[xdp] +/// fn xdp(_ctx: XdpContext) -> i32 { +/// MAP.redirect(0, xdp_action::XDP_PASS as u64) +/// } +/// ``` #[repr(transparent)] pub struct DevMap { def: UnsafeCell, @@ -17,6 +38,16 @@ pub struct DevMap { unsafe impl Sync for DevMap {} impl DevMap { + /// Creates a [`DevMap`] with a set maximum number of elements. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMap}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::with_max_entries(8, 0); + /// ``` pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMap { DevMap { def: UnsafeCell::new(bpf_map_def { @@ -31,6 +62,17 @@ impl DevMap { } } + /// Creates a [`DevMap`] with a set maximum number of elements that can be pinned to the BPF + /// File System (bpffs). + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMap}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::pinned(8, 0); + /// ``` pub const fn pinned(max_entries: u32, flags: u32) -> DevMap { DevMap { def: UnsafeCell::new(bpf_map_def { @@ -45,6 +87,22 @@ impl DevMap { } } + /// Retrieves the interface index at `index` in the array. + /// + /// To actually redirect a packet, see [`DevMap::redirect`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMap}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::with_max_entries(1, 0); + /// + /// let ifindex = MAP.get(0); + /// + /// // redirect to ifindex + /// ``` #[inline(always)] pub fn get(&self, index: u32) -> Option { unsafe { @@ -56,6 +114,24 @@ impl DevMap { } } + /// Redirects the current packet on the interface at `index`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a CPU cannot be found. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMap, programs::XdpContext}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(_ctx: XdpContext) -> i32 { + /// MAP.redirect(7, xdp_action::XDP_PASS as u64) + /// } + /// ``` #[inline(always)] pub fn redirect(&self, index: u32, flags: u64) -> u32 { // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index 87a61299..600aa9df 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -9,6 +9,29 @@ use crate::{ maps::PinningType, }; +/// A map of network devices. +/// +/// XDP programs can use this map to redirect packets to other network devices. It is similar to +/// [`DevMap`](super::DevMap), but is an hash map rather than an array. Keys do not need to be +/// contiguous nor start at zero, but there is a hashing cost to every lookup. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 5.4. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMapHash, programs::XdpContext}; +/// +/// #[map] +/// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0); +/// +/// #[xdp] +/// fn xdp(_ctx: XdpContext) -> i32 { +/// MAP.redirect(42, xdp_action::XDP_PASS as u64) +/// } +/// ``` #[repr(transparent)] pub struct DevMapHash { def: UnsafeCell, @@ -17,6 +40,16 @@ pub struct DevMapHash { unsafe impl Sync for DevMapHash {} impl DevMapHash { + /// Creates a [`DevMapHash`] with a set maximum number of elements. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMapHash}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0); + /// ``` pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMapHash { DevMapHash { def: UnsafeCell::new(bpf_map_def { @@ -31,6 +64,17 @@ impl DevMapHash { } } + /// Creates a [`DevMapHash`] with a set maximum number of elements that can be pinned to the BPF + /// File System (bpffs). + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMapHash}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::pinned(8, 0); + /// ``` pub const fn pinned(max_entries: u32, flags: u32) -> DevMapHash { DevMapHash { def: UnsafeCell::new(bpf_map_def { @@ -45,6 +89,22 @@ impl DevMapHash { } } + /// Retrieves the interface index with `key` in the map. + /// + /// To actually redirect a packet, see [`DevMapHash::redirect`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMapHash}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0); + /// + /// let ifindex = MAP.get(42); + /// + /// // redirect to ifindex + /// ``` #[inline(always)] pub fn get(&self, key: u32) -> Option { unsafe { @@ -54,6 +114,24 @@ impl DevMapHash { } } + /// Redirects the current packet on the interface at `key`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a CPU cannot be found. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMapHash, programs::XdpContext}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(_ctx: XdpContext) -> i32 { + /// MAP.redirect(7, xdp_action::XDP_PASS as u64) + /// } + /// ``` #[inline(always)] pub fn redirect(&self, key: u32, flags: u64) -> u32 { unsafe { diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs index a5e12767..ee766fa5 100644 --- a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -9,6 +9,48 @@ use crate::{ maps::PinningType, }; +/// An array of AF_XDP sockets. +/// +/// XDP programs can use this map to redirect packets to a target AF_XDP socket using the +/// `XDP_REDIRECT` action. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.18. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::XskMap, programs::XdpContext}; +/// +/// #[map] +/// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); +/// +/// #[xdp] +/// fn xdp(ctx, XdpContext) -> i32 { +/// let queue_id = unsafe { (*ctx.ctx).rx_queue_index }; +/// MAP.redirect(queue_id, xdp_action::XDP_DROP as u64) +/// } +/// ``` +/// +/// # Queue management +/// +/// Packets received on a RX queue can only be redirected to sockets bound on the same queue. Most +/// hardware NICs have multiple RX queue to spread the load across multiple CPU cores using RSS. +/// +/// Three strategies are possible: +/// +/// - Reduce the RX queue count to a single one. This option is great for development, but is +/// detrimental for performance as the single CPU core recieving packets will get overwhelmed. +/// Setting the queue count for a NIC can be achieved using `ethtool -L combined 1`. +/// - Create a socket for every RX queue. Most modern NICs will have an RX queue per CPU thread, so +/// a socket per CPU thread is best for performance. To dynamically size the map depending on the +/// recieve queue count, see the userspace documentation of `CpuMap`. +/// - Create a single socket and use a [`CpuMap`](super::CpuMap) to redirect the packet to the +/// correct CPU core. This way, the packet is sent to another CPU, and a chained XDP program can +/// the redirect to the AF_XDP socket. Using a single socket simplifies the userspace code but +/// will not perform great unless not a lot of traffic is redirected to the socket. Regular +/// traffic however will not be impacted, contrary to reducing the queue count. #[repr(transparent)] pub struct XskMap { def: UnsafeCell, @@ -17,6 +59,16 @@ pub struct XskMap { unsafe impl Sync for XskMap {} impl XskMap { + /// Creates a [`XskMap`] with a set maximum number of elements. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::XskMap}; + /// + /// #[map] + /// static SOCKS: XskMap::with_max_entries(8, 0); + /// ``` pub const fn with_max_entries(max_entries: u32, flags: u32) -> XskMap { XskMap { def: UnsafeCell::new(bpf_map_def { @@ -31,6 +83,17 @@ impl XskMap { } } + /// Creates a [`XskMap`] with a set maximum number of elements that can be pinned to the BPF + /// filesystem (bpffs). + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::XskMap}; + /// + /// #[map] + /// static SOCKS: XskMap::pinned(8, 0); + /// ``` pub const fn pinned(max_entries: u32, flags: u32) -> XskMap { XskMap { def: UnsafeCell::new(bpf_map_def { @@ -45,6 +108,20 @@ impl XskMap { } } + /// Retrieves the queue to which the socket is bound at `index` in the array. + /// + /// To actually redirect a packet, see [`XskMap::redirect`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::XskMap}; + /// + /// #[map] + /// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); + /// + /// let queue_id = SOCKS.get(0); + /// ``` #[inline(always)] pub fn get(&self, index: u32) -> Option { unsafe { @@ -56,6 +133,28 @@ impl XskMap { } } + /// Redirects the current packet to the AF_XDP socket at `index`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a matching socket cannot be found. + /// + /// However, if the socket at `index` is bound to a RX queue which is not the current RX queue, + /// the packet will be dropped. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::XskMap, programs::XdpContext}; + /// + /// #[map] + /// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(ctx, XdpContext) -> i32 { + /// let queue_id = unsafe { (*ctx.ctx).rx_queue_index }; + /// MAP.redirect(queue_id, xdp_action::XDP_DROP as u64) + /// } + /// ``` #[inline(always)] pub fn redirect(&self, index: u32, flags: u64) -> u32 { unsafe { From c6754c614ed3aca142bb27fae4e8d488aff72019 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:35 +0200 Subject: [PATCH 43/95] maps/xdp: use ProgramFd instead of impl AsRawFd Not having a generic here allows to pass `None` without specifying the actual type you don't care about. --- aya/src/maps/xdp/cpu_map.rs | 11 +++++++---- aya/src/maps/xdp/dev_map.rs | 11 +++++++---- aya/src/maps/xdp/dev_map_hash.rs | 11 +++++++---- test/integration-test/src/tests/xdp.rs | 4 ++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index 3fb4934f..a3c0a585 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -3,13 +3,14 @@ use std::{ borrow::{Borrow, BorrowMut}, num::NonZeroU32, - os::fd::AsRawFd, + os::fd::{AsFd, AsRawFd}, }; use aya_obj::generated::{bpf_cpumap_val, bpf_cpumap_val__bindgen_ty_1}; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, + programs::ProgramFd, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, Pod, }; @@ -36,7 +37,7 @@ use crate::{ /// let flags = 0; /// let queue_size = 2048; /// for i in 0u32..8u32 { -/// cpumap.set(i, queue_size, None::, flags); +/// cpumap.set(i, queue_size, None, flags); /// } /// /// # Ok::<(), aya::BpfError>(()) @@ -115,7 +116,7 @@ impl> CpuMap { &mut self, cpu_index: u32, queue_size: u32, - program: Option, + program: Option<&ProgramFd>, flags: u64, ) -> Result<(), MapError> { let data = self.inner.borrow_mut(); @@ -127,7 +128,9 @@ impl> CpuMap { bpf_prog: bpf_cpumap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 - fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), + fd: program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(), }, }; bpf_map_update_elem(fd, Some(&cpu_index), &value, flags).map_err(|(_, io_error)| { diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index 2a2797e8..e7a487d4 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -3,13 +3,14 @@ use std::{ borrow::{Borrow, BorrowMut}, num::NonZeroU32, - os::fd::AsRawFd, + os::fd::{AsFd, AsRawFd}, }; use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, + programs::ProgramFd, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, Pod, }; @@ -31,7 +32,7 @@ use crate::{ /// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?; /// let source = 32u32; /// let dest = 42u32; -/// devmap.set(source, dest, None::, 0); +/// devmap.set(source, dest, None, 0); /// /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -108,7 +109,7 @@ impl> DevMap { &mut self, index: u32, ifindex: u32, - program: Option, + program: Option<&ProgramFd>, flags: u64, ) -> Result<(), MapError> { let data = self.inner.borrow_mut(); @@ -121,7 +122,9 @@ impl> DevMap { // Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 - fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), + fd: program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(), }, }; bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 34ad39ac..e5c91dde 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -3,13 +3,14 @@ use std::{ borrow::{Borrow, BorrowMut}, num::NonZeroU32, - os::fd::AsRawFd, + os::fd::{AsFd, AsRawFd}, }; use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; use crate::{ maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, + programs::ProgramFd, sys::{bpf_map_lookup_elem, SyscallError}, }; @@ -32,7 +33,7 @@ use super::dev_map::DevMapValue; /// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?; /// let flags = 0; /// let ifindex = 32u32; -/// devmap.insert(ifindex, ifindex, None::, flags); +/// devmap.insert(ifindex, ifindex, None, flags); /// /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -100,7 +101,7 @@ impl> DevMapHash { &mut self, key: u32, ifindex: u32, - program: Option, + program: Option<&ProgramFd>, flags: u64, ) -> Result<(), MapError> { let value = bpf_devmap_val { @@ -109,7 +110,9 @@ impl> DevMapHash { // Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 - fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), + fd: program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(), }, }; hash_map::insert(self.inner.borrow_mut(), &key, &value, flags) diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index b0c25bff..88423fe9 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -1,4 +1,4 @@ -use std::{net::UdpSocket, os::fd::AsFd, time::Duration}; +use std::{net::UdpSocket, time::Duration}; use aya::{ maps::{Array, CpuMap}, @@ -75,7 +75,7 @@ fn cpumap_chain() { xdp.load().unwrap(); xdp.fd().unwrap() }; - cpus.set(0, 2048, Some(xdp_chain_fd.as_fd()), 0).unwrap(); + cpus.set(0, 2048, Some(xdp_chain_fd), 0).unwrap(); // Load the main program let xdp: &mut Xdp = bpf.program_mut("redirect_cpu").unwrap().try_into().unwrap(); From 63ce2f013a299c26ae01d729a7df47960af1f608 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:40 +0200 Subject: [PATCH 44/95] bpf/devmap: don't expose `bpf_devmap_value` Use our own type that: - is stable as not from bindgen - does not have an union inside --- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 15 +++++++++++++-- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 11 +++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index 66103758..18a76790 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -104,13 +104,18 @@ impl DevMap { /// // redirect to ifindex /// ``` #[inline(always)] - pub fn get(&self, index: u32) -> Option { + pub fn get(&self, index: u32) -> Option { unsafe { let value = bpf_map_lookup_elem( self.def.get() as *mut _, &index as *const _ as *const c_void, ); - NonNull::new(value as *mut bpf_devmap_val).map(|p| *p.as_ref()) + NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { + ifindex: p.as_ref().ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 + prog_id: p.as_ref().bpf_prog.id, + }) } } @@ -142,3 +147,9 @@ impl DevMap { } } } + +#[derive(Clone, Copy)] +pub struct DevMapValue { + pub ifindex: u32, + pub prog_id: u32, +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index 600aa9df..a6533e76 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -9,6 +9,8 @@ use crate::{ maps::PinningType, }; +use super::dev_map::DevMapValue; + /// A map of network devices. /// /// XDP programs can use this map to redirect packets to other network devices. It is similar to @@ -106,11 +108,16 @@ impl DevMapHash { /// // redirect to ifindex /// ``` #[inline(always)] - pub fn get(&self, key: u32) -> Option { + pub fn get(&self, key: u32) -> Option { unsafe { let value = bpf_map_lookup_elem(self.def.get() as *mut _, &key as *const _ as *const c_void); - NonNull::new(value as *mut bpf_devmap_val).map(|p| *p.as_ref()) + NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { + ifindex: p.as_ref().ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 + prog_id: p.as_ref().bpf_prog.id, + }) } } From 00dc7a5bd4468b7d86d7f167a49e78d89016e2ac Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Sat, 5 Aug 2023 00:16:43 +0200 Subject: [PATCH 45/95] maps/xdp: make maps work on kernels not supporting ProgIds On startup, the kernel is probed for support of chained program ids for CpuMap, DevMap and DevMapHash, and will patch maps at load time to have the proper size. Then, at runtime, the support is checked and will error out if a program id is passed when the kernel does not support it. --- aya-obj/src/maps.rs | 8 ++++ aya-obj/src/obj.rs | 25 ++++++++++ aya/Cargo.toml | 2 +- aya/src/bpf.rs | 18 ++++++- aya/src/maps/mod.rs | 4 ++ aya/src/maps/xdp/cpu_map.rs | 79 ++++++++++++++++++++----------- aya/src/maps/xdp/dev_map.rs | 81 ++++++++++++++++++++------------ aya/src/maps/xdp/dev_map_hash.rs | 79 +++++++++++++++++++++---------- aya/src/sys/bpf.rs | 47 ++++++++++++++++++ 9 files changed, 258 insertions(+), 85 deletions(-) diff --git a/aya-obj/src/maps.rs b/aya-obj/src/maps.rs index dbffed0c..aede3cfe 100644 --- a/aya-obj/src/maps.rs +++ b/aya-obj/src/maps.rs @@ -176,6 +176,14 @@ impl Map { } } + /// Set the value size in bytes + pub fn set_value_size(&mut self, size: u32) { + match self { + Map::Legacy(m) => m.def.value_size = size, + Map::Btf(m) => m.def.value_size = size, + } + } + /// Returns the max entry number pub fn max_entries(&self) -> u32 { match self { diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index ce599d3c..6909a229 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -48,17 +48,24 @@ pub struct Features { bpf_perf_link: bool, bpf_global_data: bool, bpf_cookie: bool, + cpumap_prog_id: bool, + devmap_prog_id: bool, + devmap_hash_prog_id: bool, btf: Option, } impl Features { #[doc(hidden)] + #[allow(clippy::too_many_arguments)] pub fn new( bpf_name: bool, bpf_probe_read_kernel: bool, bpf_perf_link: bool, bpf_global_data: bool, bpf_cookie: bool, + cpumap_prog_id: bool, + devmap_prog_id: bool, + devmap_hash_prog_id: bool, btf: Option, ) -> Self { Self { @@ -67,6 +74,9 @@ impl Features { bpf_perf_link, bpf_global_data, bpf_cookie, + cpumap_prog_id, + devmap_prog_id, + devmap_hash_prog_id, btf, } } @@ -96,6 +106,21 @@ impl Features { self.bpf_cookie } + /// Returns whether XDP CPU Maps support chained program IDs. + pub fn cpumap_prog_id(&self) -> bool { + self.cpumap_prog_id + } + + /// Returns whether XDP Device Maps support chained program IDs. + pub fn devmap_prog_id(&self) -> bool { + self.devmap_prog_id + } + + /// Returns whether XDP Hash Device Maps support chained program IDs. + pub fn devmap_hash_prog_id(&self) -> bool { + self.devmap_hash_prog_id + } + /// If BTF is supported, returns which BTF features are supported. pub fn btf(&self) -> Option<&BtfFeatures> { self.btf.as_ref() diff --git a/aya/Cargo.toml b/aya/Cargo.toml index 59025b2d..9cdae143 100644 --- a/aya/Cargo.toml +++ b/aya/Cargo.toml @@ -12,6 +12,7 @@ edition = "2021" rust-version = "1.66" [dependencies] +assert_matches = { workspace = true } async-io = { workspace = true, optional = true } aya-obj = { workspace = true, features = ["std"] } bitflags = { workspace = true } @@ -28,7 +29,6 @@ thiserror = { workspace = true } tokio = { workspace = true, features = ["rt"], optional = true } [dev-dependencies] -assert_matches = { workspace = true } tempfile = { workspace = true } [features] diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 0140886d..181d971f 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -40,7 +40,8 @@ use crate::{ is_btf_datasec_supported, is_btf_decl_tag_supported, is_btf_enum64_supported, is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported, - is_probe_read_kernel_supported, is_prog_name_supported, retry_with_verifier_logs, + is_probe_read_kernel_supported, is_prog_id_supported, is_prog_name_supported, + retry_with_verifier_logs, }, util::{bytes_of, bytes_of_slice, possible_cpus, POSSIBLE_CPUS}, }; @@ -93,6 +94,9 @@ fn detect_features() -> Features { is_perf_link_supported(), is_bpf_global_data_supported(), is_bpf_cookie_supported(), + is_prog_id_supported(BPF_MAP_TYPE_CPUMAP), + is_prog_id_supported(BPF_MAP_TYPE_DEVMAP), + is_prog_id_supported(BPF_MAP_TYPE_DEVMAP_HASH), btf, ); debug!("BPF Feature Detection: {:#?}", f); @@ -476,6 +480,18 @@ impl<'a> BpfLoader<'a> { } } } + match obj.map_type().try_into() { + Ok(BPF_MAP_TYPE_CPUMAP) => { + obj.set_value_size(if FEATURES.cpumap_prog_id() { 8 } else { 4 }) + } + Ok(BPF_MAP_TYPE_DEVMAP) => { + obj.set_value_size(if FEATURES.devmap_prog_id() { 8 } else { 4 }) + } + Ok(BPF_MAP_TYPE_DEVMAP_HASH) => { + obj.set_value_size(if FEATURES.devmap_hash_prog_id() { 8 } else { 4 }) + } + _ => (), + } let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); let mut map = match obj.pinning() { PinningType::None => MapData::create(obj, &name, btf_fd)?, diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index e0d2e0ff..d41600fe 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -181,6 +181,10 @@ pub enum MapError { error: PinError, }, + /// Program IDs are not supported + #[error("program ids are not supported by the current kernel")] + ProgIdNotSupported, + /// Unsupported Map type #[error("Unsupported map type found {map_type}")] Unsupported { diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index a3c0a585..e6349163 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -12,7 +12,7 @@ use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, programs::ProgramFd, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, - Pod, + Pod, FEATURES, }; /// An array of available CPUs. @@ -50,7 +50,12 @@ pub struct CpuMap { impl> CpuMap { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - check_kv_size::(data)?; + + if FEATURES.cpumap_prog_id() { + check_kv_size::(data)?; + } else { + check_kv_size::(data)?; + } Ok(Self { inner: map }) } @@ -73,19 +78,29 @@ impl> CpuMap { check_bounds(data, cpu_index)?; let fd = data.fd().as_fd(); - let value = - bpf_map_lookup_elem(fd, &cpu_index, flags).map_err(|(_, io_error)| SyscallError { + let value = if FEATURES.cpumap_prog_id() { + bpf_map_lookup_elem::<_, bpf_cpumap_val>(fd, &cpu_index, flags).map(|value| { + value.map(|value| CpuMapValue { + qsize: value.qsize, + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241 + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) + }) + } else { + bpf_map_lookup_elem::<_, u32>(fd, &cpu_index, flags).map(|value| { + value.map(|qsize| CpuMapValue { + qsize, + prog_id: None, + }) + }) + }; + value + .map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, - })?; - let value: bpf_cpumap_val = value.ok_or(MapError::KeyNotFound)?; - - // SAFETY: map writes use fd, map reads use id. - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241 - Ok(CpuMapValue { - qsize: value.qsize, - prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), - }) + })? + .ok_or(MapError::KeyNotFound) } /// An iterator over the elements of the map. @@ -111,7 +126,8 @@ impl> CpuMap { /// # Errors /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] - /// if `bpf_map_update_elem` fails. + /// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not + /// support program ids and one is provided. pub fn set( &mut self, cpu_index: u32, @@ -123,21 +139,28 @@ impl> CpuMap { check_bounds(data, cpu_index)?; let fd = data.fd().as_fd(); - let value = bpf_cpumap_val { - qsize: queue_size, - bpf_prog: bpf_cpumap_val__bindgen_ty_1 { - // Default is valid as the kernel will only consider fd > 0: - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 - fd: program - .map(|prog| prog.as_fd().as_raw_fd()) - .unwrap_or_default(), - }, - }; - bpf_map_update_elem(fd, Some(&cpu_index), &value, flags).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_map_update_elem", - io_error, + let res = if FEATURES.cpumap_prog_id() { + let value = bpf_cpumap_val { + qsize: queue_size, + bpf_prog: bpf_cpumap_val__bindgen_ty_1 { + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 + fd: program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(), + }, + }; + bpf_map_update_elem(fd, Some(&cpu_index), &value, flags) + } else { + if program.is_some() { + return Err(MapError::ProgIdNotSupported); } + bpf_map_update_elem(fd, Some(&cpu_index), &queue_size, flags) + }; + + res.map_err(|(_, io_error)| SyscallError { + call: "bpf_map_update_elem", + io_error, })?; Ok(()) } diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index e7a487d4..df43461c 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -12,7 +12,7 @@ use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, programs::ProgramFd, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, - Pod, + Pod, FEATURES, }; /// An array of network devices. @@ -44,7 +44,12 @@ pub struct DevMap { impl> DevMap { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - check_kv_size::(data)?; + + if FEATURES.devmap_prog_id() { + check_kv_size::(data)?; + } else { + check_kv_size::(data)?; + } Ok(Self { inner: map }) } @@ -67,19 +72,29 @@ impl> DevMap { check_bounds(data, index)?; let fd = data.fd().as_fd(); - let value = - bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { + let value = if FEATURES.devmap_prog_id() { + bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &index, flags).map(|value| { + value.map(|value| DevMapValue { + ifindex: value.ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) + }) + } else { + bpf_map_lookup_elem::<_, u32>(fd, &index, flags).map(|value| { + value.map(|ifindex| DevMapValue { + ifindex, + prog_id: None, + }) + }) + }; + value + .map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, - })?; - let value: bpf_devmap_val = value.ok_or(MapError::KeyNotFound)?; - - // SAFETY: map writes use fd, map reads use id. - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 - Ok(DevMapValue { - ifindex: value.ifindex, - prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), - }) + })? + .ok_or(MapError::KeyNotFound) } /// An iterator over the elements of the array. @@ -104,7 +119,8 @@ impl> DevMap { /// # Errors /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] - /// if `bpf_map_update_elem` fails. + /// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not + /// support program ids and one is provided. pub fn set( &mut self, index: u32, @@ -116,22 +132,29 @@ impl> DevMap { check_bounds(data, index)?; let fd = data.fd().as_fd(); - let value = bpf_devmap_val { - ifindex, - bpf_prog: bpf_devmap_val__bindgen_ty_1 { - // Default is valid as the kernel will only consider fd > 0: - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 - fd: program - .map(|prog| prog.as_fd().as_raw_fd()) - .unwrap_or_default(), - }, - }; - bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { - SyscallError { - call: "bpf_map_update_elem", - io_error, + let res = if FEATURES.devmap_prog_id() { + let value = bpf_devmap_val { + ifindex, + bpf_prog: bpf_devmap_val__bindgen_ty_1 { + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + fd: program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(), + }, + }; + bpf_map_update_elem(fd, Some(&index), &value, flags) + } else { + if program.is_some() { + return Err(MapError::ProgIdNotSupported); } + bpf_map_update_elem(fd, Some(&index), &ifindex, flags) + }; + + res.map_err(|(_, io_error)| SyscallError { + call: "bpf_map_update_elem", + io_error, })?; Ok(()) } diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index e5c91dde..8311a29b 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -12,6 +12,7 @@ use crate::{ maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, programs::ProgramFd, sys::{bpf_map_lookup_elem, SyscallError}, + FEATURES, }; use super::dev_map::DevMapValue; @@ -45,7 +46,12 @@ pub struct DevMapHash { impl> DevMapHash { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - check_kv_size::(data)?; + + if FEATURES.devmap_hash_prog_id() { + check_kv_size::(data)?; + } else { + check_kv_size::(data)?; + } Ok(Self { inner: map }) } @@ -57,18 +63,30 @@ impl> DevMapHash { /// Returns [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. pub fn get(&self, key: u32, flags: u64) -> Result { let fd = self.inner.borrow().fd().as_fd(); - let value = bpf_map_lookup_elem(fd, &key, flags).map_err(|(_, io_error)| SyscallError { - call: "bpf_map_lookup_elem", - io_error, - })?; - let value: bpf_devmap_val = value.ok_or(MapError::KeyNotFound)?; - - // SAFETY: map writes use fd, map reads use id. - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 - Ok(DevMapValue { - ifindex: value.ifindex, - prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), - }) + + let value = if FEATURES.devmap_hash_prog_id() { + bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &key, flags).map(|value| { + value.map(|value| DevMapValue { + ifindex: value.ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) + }) + } else { + bpf_map_lookup_elem::<_, u32>(fd, &key, flags).map(|value| { + value.map(|ifindex| DevMapValue { + ifindex, + prog_id: None, + }) + }) + }; + value + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })? + .ok_or(MapError::KeyNotFound) } /// An iterator over the elements of the devmap in arbitrary order. @@ -96,7 +114,9 @@ impl> DevMapHash { /// /// # Errors /// - /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails. + /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails, + /// [`MapError::ProgIdNotSupported`] if the kernel does not support program ids and one is + /// provided. pub fn insert( &mut self, key: u32, @@ -104,18 +124,25 @@ impl> DevMapHash { program: Option<&ProgramFd>, flags: u64, ) -> Result<(), MapError> { - let value = bpf_devmap_val { - ifindex, - bpf_prog: bpf_devmap_val__bindgen_ty_1 { - // Default is valid as the kernel will only consider fd > 0: - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 - fd: program - .map(|prog| prog.as_fd().as_raw_fd()) - .unwrap_or_default(), - }, - }; - hash_map::insert(self.inner.borrow_mut(), &key, &value, flags) + if FEATURES.devmap_hash_prog_id() { + let value = bpf_devmap_val { + ifindex, + bpf_prog: bpf_devmap_val__bindgen_ty_1 { + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + fd: program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(), + }, + }; + hash_map::insert(self.inner.borrow_mut(), &key, &value, flags) + } else { + if program.is_some() { + return Err(MapError::ProgIdNotSupported); + } + hash_map::insert(self.inner.borrow_mut(), &key, &ifindex, flags) + } } /// Removes a value from the map. diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index d3cca3ee..cf41b74a 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -8,6 +8,7 @@ use std::{ }; use crate::util::KernelVersion; +use assert_matches::assert_matches; use libc::{c_char, c_long, ENOENT, ENOSPC}; use obj::{ btf::{BtfEnum64, Enum64}, @@ -793,6 +794,28 @@ pub(crate) fn is_bpf_cookie_supported() -> bool { bpf_prog_load(&mut attr).is_ok() } +/// Tests whether CpuMap, DevMap and DevMapHash support program ids +pub(crate) fn is_prog_id_supported(map_type: bpf_map_type) -> bool { + assert_matches!( + map_type, + bpf_map_type::BPF_MAP_TYPE_CPUMAP + | bpf_map_type::BPF_MAP_TYPE_DEVMAP + | bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH + ); + + let mut attr = unsafe { mem::zeroed::() }; + let u = unsafe { &mut attr.__bindgen_anon_1 }; + + u.map_type = map_type as u32; + u.key_size = 4; + u.value_size = 8; // 4 for CPU ID, 8 for CPU ID + prog ID + u.max_entries = 1; + u.map_flags = 0; + + // SAFETY: BPF_MAP_CREATE returns a new file descriptor. + unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) }.is_ok() +} + pub(crate) fn is_btf_supported() -> bool { let mut btf = Btf::new(); let name_offset = btf.add_string("int"); @@ -1072,4 +1095,28 @@ mod tests { let supported = is_perf_link_supported(); assert!(!supported); } + + #[test] + fn test_prog_id_supported() { + override_syscall(|_call| Ok(42)); + + // Ensure that the three map types we can check are accepted + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_CPUMAP); + assert!(supported); + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_DEVMAP); + assert!(supported); + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH); + assert!(supported); + + override_syscall(|_call| Err((-1, io::Error::from_raw_os_error(EINVAL)))); + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_CPUMAP); + assert!(!supported); + } + + #[test] + #[should_panic = "assertion failed: `BPF_MAP_TYPE_HASH` does not match `bpf_map_type::BPF_MAP_TYPE_CPUMAP | bpf_map_type::BPF_MAP_TYPE_DEVMAP | +bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH`"] + fn test_prog_id_supported_reject_types() { + is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_HASH); + } } From 46551de3e74a25229ce3bddd095f0b40e72fa770 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Thu, 17 Aug 2023 19:32:21 +0200 Subject: [PATCH 46/95] xtask: bless public-api --- xtask/public-api/aya-bpf.txt | 215 ++++++++++++++++++++ xtask/public-api/aya-obj.txt | 83 ++++++++ xtask/public-api/aya.txt | 380 ++++++++++++++++++++++++++++++++++- 3 files changed, 674 insertions(+), 4 deletions(-) diff --git a/xtask/public-api/aya-bpf.txt b/xtask/public-api/aya-bpf.txt index 4d4aa0f7..b7de5541 100644 --- a/xtask/public-api/aya-bpf.txt +++ b/xtask/public-api/aya-bpf.txt @@ -563,6 +563,114 @@ impl core::borrow::BorrowMut for aya_bpf::maps::stack_trace::StackTrace wh pub fn aya_bpf::maps::stack_trace::StackTrace::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::stack_trace::StackTrace pub fn aya_bpf::maps::stack_trace::StackTrace::from(t: T) -> T +pub mod aya_bpf::maps::xdp +#[repr(transparent)] pub struct aya_bpf::maps::xdp::CpuMap +impl aya_bpf::maps::CpuMap +pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +impl core::marker::Sync for aya_bpf::maps::CpuMap +impl core::marker::Send for aya_bpf::maps::CpuMap +impl core::marker::Unpin for aya_bpf::maps::CpuMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::CpuMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::CpuMap +impl core::convert::Into for aya_bpf::maps::CpuMap where U: core::convert::From +pub fn aya_bpf::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::CpuMap where U: core::convert::Into +pub type aya_bpf::maps::CpuMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::CpuMap where U: core::convert::TryFrom +pub type aya_bpf::maps::CpuMap::Error = >::Error +pub fn aya_bpf::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::xdp::DevMap +impl aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +impl core::marker::Sync for aya_bpf::maps::DevMap +impl core::marker::Send for aya_bpf::maps::DevMap +impl core::marker::Unpin for aya_bpf::maps::DevMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMap +impl core::convert::Into for aya_bpf::maps::DevMap where U: core::convert::From +pub fn aya_bpf::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMap where U: core::convert::Into +pub type aya_bpf::maps::DevMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMap where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMap::Error = >::Error +pub fn aya_bpf::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::xdp::DevMapHash +impl aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +impl core::marker::Sync for aya_bpf::maps::DevMapHash +impl core::marker::Send for aya_bpf::maps::DevMapHash +impl core::marker::Unpin for aya_bpf::maps::DevMapHash +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMapHash +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMapHash +impl core::convert::Into for aya_bpf::maps::DevMapHash where U: core::convert::From +pub fn aya_bpf::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMapHash where U: core::convert::Into +pub type aya_bpf::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMapHash where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMapHash::Error = >::Error +pub fn aya_bpf::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::xdp::XskMap +impl aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +impl core::marker::Sync for aya_bpf::maps::XskMap +impl core::marker::Send for aya_bpf::maps::XskMap +impl core::marker::Unpin for aya_bpf::maps::XskMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::XskMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::XskMap +impl core::convert::Into for aya_bpf::maps::XskMap where U: core::convert::From +pub fn aya_bpf::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::XskMap where U: core::convert::Into +pub type aya_bpf::maps::XskMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::XskMap where U: core::convert::TryFrom +pub type aya_bpf::maps::XskMap::Error = >::Error +pub fn aya_bpf::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::from(t: T) -> T #[repr(transparent)] pub struct aya_bpf::maps::Array impl aya_bpf::maps::array::Array pub fn aya_bpf::maps::array::Array::get(&self, index: u32) -> core::option::Option<&T> @@ -618,6 +726,86 @@ impl core::borrow::BorrowMut for aya_bpf::maps::bloom_filter::BloomFilter< pub fn aya_bpf::maps::bloom_filter::BloomFilter::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::bloom_filter::BloomFilter pub fn aya_bpf::maps::bloom_filter::BloomFilter::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::CpuMap +impl aya_bpf::maps::CpuMap +pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +impl core::marker::Sync for aya_bpf::maps::CpuMap +impl core::marker::Send for aya_bpf::maps::CpuMap +impl core::marker::Unpin for aya_bpf::maps::CpuMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::CpuMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::CpuMap +impl core::convert::Into for aya_bpf::maps::CpuMap where U: core::convert::From +pub fn aya_bpf::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::CpuMap where U: core::convert::Into +pub type aya_bpf::maps::CpuMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::CpuMap where U: core::convert::TryFrom +pub type aya_bpf::maps::CpuMap::Error = >::Error +pub fn aya_bpf::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::DevMap +impl aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +impl core::marker::Sync for aya_bpf::maps::DevMap +impl core::marker::Send for aya_bpf::maps::DevMap +impl core::marker::Unpin for aya_bpf::maps::DevMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMap +impl core::convert::Into for aya_bpf::maps::DevMap where U: core::convert::From +pub fn aya_bpf::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMap where U: core::convert::Into +pub type aya_bpf::maps::DevMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMap where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMap::Error = >::Error +pub fn aya_bpf::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::DevMapHash +impl aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +impl core::marker::Sync for aya_bpf::maps::DevMapHash +impl core::marker::Send for aya_bpf::maps::DevMapHash +impl core::marker::Unpin for aya_bpf::maps::DevMapHash +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMapHash +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMapHash +impl core::convert::Into for aya_bpf::maps::DevMapHash where U: core::convert::From +pub fn aya_bpf::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMapHash where U: core::convert::Into +pub type aya_bpf::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMapHash where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMapHash::Error = >::Error +pub fn aya_bpf::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::from(t: T) -> T #[repr(transparent)] pub struct aya_bpf::maps::HashMap impl aya_bpf::maps::hash_map::HashMap pub unsafe fn aya_bpf::maps::hash_map::HashMap::get(&self, key: &K) -> core::option::Option<&V> @@ -1014,6 +1202,33 @@ impl core::borrow::BorrowMut for aya_bpf::maps::stack_trace::StackTrace wh pub fn aya_bpf::maps::stack_trace::StackTrace::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::stack_trace::StackTrace pub fn aya_bpf::maps::stack_trace::StackTrace::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::XskMap +impl aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> u32 +pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +impl core::marker::Sync for aya_bpf::maps::XskMap +impl core::marker::Send for aya_bpf::maps::XskMap +impl core::marker::Unpin for aya_bpf::maps::XskMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::XskMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::XskMap +impl core::convert::Into for aya_bpf::maps::XskMap where U: core::convert::From +pub fn aya_bpf::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::XskMap where U: core::convert::Into +pub type aya_bpf::maps::XskMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::XskMap where U: core::convert::TryFrom +pub type aya_bpf::maps::XskMap::Error = >::Error +pub fn aya_bpf::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::from(t: T) -> T pub mod aya_bpf::programs pub mod aya_bpf::programs::device pub struct aya_bpf::programs::device::DeviceContext diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index c6dea1ba..5c361372 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -1342,6 +1342,8 @@ impl core::convert::From aya_obj::generated::bpf_attach_type impl core::convert::From for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::from(s: aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType) -> aya_obj::generated::bpf_attach_type +impl core::convert::From for aya_obj::generated::bpf_attach_type +pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp::XdpAttachType) -> Self impl core::clone::Clone for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::clone(&self) -> aya_obj::generated::bpf_attach_type impl core::cmp::Eq for aya_obj::generated::bpf_attach_type @@ -5411,6 +5413,7 @@ pub fn aya_obj::maps::Map::pinning(&self) -> aya_obj::maps::PinningType pub fn aya_obj::maps::Map::section_index(&self) -> usize pub fn aya_obj::maps::Map::section_kind(&self) -> aya_obj::BpfSectionKind pub fn aya_obj::maps::Map::set_max_entries(&mut self, v: u32) +pub fn aya_obj::maps::Map::set_value_size(&mut self, size: u32) pub fn aya_obj::maps::Map::symbol_index(&self) -> core::option::Option pub fn aya_obj::maps::Map::value_size(&self) -> u32 impl core::clone::Clone for aya_obj::maps::Map @@ -5848,6 +5851,7 @@ pub aya_obj::obj::ProgramSection::UProbe::sleepable: bool pub aya_obj::obj::ProgramSection::URetProbe pub aya_obj::obj::ProgramSection::URetProbe::sleepable: bool pub aya_obj::obj::ProgramSection::Xdp +pub aya_obj::obj::ProgramSection::Xdp::attach_type: aya_obj::programs::xdp::XdpAttachType pub aya_obj::obj::ProgramSection::Xdp::frags: bool impl core::str::traits::FromStr for aya_obj::ProgramSection pub type aya_obj::ProgramSection::Err = aya_obj::ParseError @@ -5889,6 +5893,8 @@ pub fn aya_obj::Features::bpf_name(&self) -> bool pub fn aya_obj::Features::bpf_perf_link(&self) -> bool pub fn aya_obj::Features::bpf_probe_read_kernel(&self) -> bool pub fn aya_obj::Features::btf(&self) -> core::option::Option<&aya_obj::btf::BtfFeatures> +pub fn aya_obj::Features::cpumap_prog_id(&self) -> bool +pub fn aya_obj::Features::devmap_prog_id(&self) -> bool impl core::default::Default for aya_obj::Features pub fn aya_obj::Features::default() -> aya_obj::Features impl core::fmt::Debug for aya_obj::Features @@ -6164,6 +6170,43 @@ impl core::borrow::BorrowMut for aya_obj::programs::cgroup_sockopt::Cgroup pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::from(t: T) -> T +pub mod aya_obj::programs::xdp +pub enum aya_obj::programs::xdp::XdpAttachType +pub aya_obj::programs::xdp::XdpAttachType::CpuMap +pub aya_obj::programs::xdp::XdpAttachType::DevMap +pub aya_obj::programs::xdp::XdpAttachType::Interface +impl core::convert::From for aya_obj::generated::bpf_attach_type +pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp::XdpAttachType) -> Self +impl core::clone::Clone for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::clone(&self) -> aya_obj::programs::xdp::XdpAttachType +impl core::fmt::Debug for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Send for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Sync for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Unpin for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::RefUnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::UnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::convert::Into for aya_obj::programs::xdp::XdpAttachType where U: core::convert::From +pub fn aya_obj::programs::xdp::XdpAttachType::into(self) -> U +impl core::convert::TryFrom for aya_obj::programs::xdp::XdpAttachType where U: core::convert::Into +pub type aya_obj::programs::xdp::XdpAttachType::Error = core::convert::Infallible +pub fn aya_obj::programs::xdp::XdpAttachType::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_obj::programs::xdp::XdpAttachType where U: core::convert::TryFrom +pub type aya_obj::programs::xdp::XdpAttachType::Error = >::Error +pub fn aya_obj::programs::xdp::XdpAttachType::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya_obj::programs::xdp::XdpAttachType where T: core::clone::Clone +pub type aya_obj::programs::xdp::XdpAttachType::Owned = T +pub fn aya_obj::programs::xdp::XdpAttachType::clone_into(&self, target: &mut T) +pub fn aya_obj::programs::xdp::XdpAttachType::to_owned(&self) -> T +impl core::any::Any for aya_obj::programs::xdp::XdpAttachType where T: 'static + core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::from(t: T) -> T pub enum aya_obj::programs::CgroupSockAddrAttachType pub aya_obj::programs::CgroupSockAddrAttachType::Bind4 pub aya_obj::programs::CgroupSockAddrAttachType::Bind6 @@ -6283,6 +6326,42 @@ impl core::borrow::BorrowMut for aya_obj::programs::cgroup_sockopt::Cgroup pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::from(t: T) -> T +pub enum aya_obj::programs::XdpAttachType +pub aya_obj::programs::XdpAttachType::CpuMap +pub aya_obj::programs::XdpAttachType::DevMap +pub aya_obj::programs::XdpAttachType::Interface +impl core::convert::From for aya_obj::generated::bpf_attach_type +pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp::XdpAttachType) -> Self +impl core::clone::Clone for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::clone(&self) -> aya_obj::programs::xdp::XdpAttachType +impl core::fmt::Debug for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Send for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Sync for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Unpin for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::RefUnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::UnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::convert::Into for aya_obj::programs::xdp::XdpAttachType where U: core::convert::From +pub fn aya_obj::programs::xdp::XdpAttachType::into(self) -> U +impl core::convert::TryFrom for aya_obj::programs::xdp::XdpAttachType where U: core::convert::Into +pub type aya_obj::programs::xdp::XdpAttachType::Error = core::convert::Infallible +pub fn aya_obj::programs::xdp::XdpAttachType::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_obj::programs::xdp::XdpAttachType where U: core::convert::TryFrom +pub type aya_obj::programs::xdp::XdpAttachType::Error = >::Error +pub fn aya_obj::programs::xdp::XdpAttachType::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya_obj::programs::xdp::XdpAttachType where T: core::clone::Clone +pub type aya_obj::programs::xdp::XdpAttachType::Owned = T +pub fn aya_obj::programs::xdp::XdpAttachType::clone_into(&self, target: &mut T) +pub fn aya_obj::programs::xdp::XdpAttachType::to_owned(&self) -> T +impl core::any::Any for aya_obj::programs::xdp::XdpAttachType where T: 'static + core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::from(t: T) -> T pub mod aya_obj::relocation pub enum aya_obj::relocation::RelocationError pub aya_obj::relocation::RelocationError::InvalidRelocationOffset @@ -6420,6 +6499,7 @@ pub fn aya_obj::maps::Map::pinning(&self) -> aya_obj::maps::PinningType pub fn aya_obj::maps::Map::section_index(&self) -> usize pub fn aya_obj::maps::Map::section_kind(&self) -> aya_obj::BpfSectionKind pub fn aya_obj::maps::Map::set_max_entries(&mut self, v: u32) +pub fn aya_obj::maps::Map::set_value_size(&mut self, size: u32) pub fn aya_obj::maps::Map::symbol_index(&self) -> core::option::Option pub fn aya_obj::maps::Map::value_size(&self) -> u32 impl core::clone::Clone for aya_obj::maps::Map @@ -6560,6 +6640,7 @@ pub aya_obj::ProgramSection::UProbe::sleepable: bool pub aya_obj::ProgramSection::URetProbe pub aya_obj::ProgramSection::URetProbe::sleepable: bool pub aya_obj::ProgramSection::Xdp +pub aya_obj::ProgramSection::Xdp::attach_type: aya_obj::programs::xdp::XdpAttachType pub aya_obj::ProgramSection::Xdp::frags: bool impl core::str::traits::FromStr for aya_obj::ProgramSection pub type aya_obj::ProgramSection::Err = aya_obj::ParseError @@ -6601,6 +6682,8 @@ pub fn aya_obj::Features::bpf_name(&self) -> bool pub fn aya_obj::Features::bpf_perf_link(&self) -> bool pub fn aya_obj::Features::bpf_probe_read_kernel(&self) -> bool pub fn aya_obj::Features::btf(&self) -> core::option::Option<&aya_obj::btf::BtfFeatures> +pub fn aya_obj::Features::cpumap_prog_id(&self) -> bool +pub fn aya_obj::Features::devmap_prog_id(&self) -> bool impl core::default::Default for aya_obj::Features pub fn aya_obj::Features::default() -> aya_obj::Features impl core::fmt::Debug for aya_obj::Features diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 8c1b0b9c..86221498 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -795,9 +795,194 @@ impl core::borrow::BorrowMut for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::from(t: T) -> T +pub mod aya::maps::xdp +pub enum aya::maps::xdp::XdpMapError +pub aya::maps::xdp::XdpMapError::ChainedProgramNotSupported +pub aya::maps::xdp::XdpMapError::MapError(aya::maps::MapError) +impl core::convert::From for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::from(source: aya::maps::MapError) -> Self +impl core::error::Error for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +impl core::fmt::Display for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::fmt(&self, __formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Debug for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Send for aya::maps::xdp::XdpMapError +impl core::marker::Sync for aya::maps::xdp::XdpMapError +impl core::marker::Unpin for aya::maps::xdp::XdpMapError +impl !core::panic::unwind_safe::RefUnwindSafe for aya::maps::xdp::XdpMapError +impl !core::panic::unwind_safe::UnwindSafe for aya::maps::xdp::XdpMapError +impl core::convert::Into for aya::maps::xdp::XdpMapError where U: core::convert::From +pub fn aya::maps::xdp::XdpMapError::into(self) -> U +impl core::convert::TryFrom for aya::maps::xdp::XdpMapError where U: core::convert::Into +pub type aya::maps::xdp::XdpMapError::Error = core::convert::Infallible +pub fn aya::maps::xdp::XdpMapError::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::xdp::XdpMapError where U: core::convert::TryFrom +pub type aya::maps::xdp::XdpMapError::Error = >::Error +pub fn aya::maps::xdp::XdpMapError::try_into(self) -> core::result::Result>::Error> +impl alloc::string::ToString for aya::maps::xdp::XdpMapError where T: core::fmt::Display + core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::to_string(&self) -> alloc::string::String +impl core::any::Any for aya::maps::xdp::XdpMapError where T: 'static + core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::xdp::XdpMapError where T: core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::xdp::XdpMapError where T: core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::from(t: T) -> T +pub struct aya::maps::xdp::CpuMap +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::get(&self, cpu_index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::CpuMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::CpuMap::len(&self) -> u32 +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::CpuMap +pub type aya::maps::CpuMap::Error = aya::maps::MapError +pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::CpuMap<&'a aya::maps::MapData> +pub type aya::maps::CpuMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::CpuMap<&'a mut aya::maps::MapData> +pub type aya::maps::CpuMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::CpuMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::CpuMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::CpuMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::CpuMap where U: core::convert::From +pub fn aya::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::CpuMap where U: core::convert::Into +pub type aya::maps::CpuMap::Error = core::convert::Infallible +pub fn aya::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::CpuMap where U: core::convert::TryFrom +pub type aya::maps::CpuMap::Error = >::Error +pub fn aya::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::CpuMap +pub fn aya::maps::CpuMap::from(t: T) -> T +pub struct aya::maps::xdp::DevMap +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::get(&self, index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::DevMap::len(&self) -> u32 +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::DevMap +pub type aya::maps::DevMap::Error = aya::maps::MapError +pub fn aya::maps::DevMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMap<&'a aya::maps::MapData> +pub type aya::maps::DevMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMap<&'a mut aya::maps::MapData> +pub type aya::maps::DevMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMap where U: core::convert::From +pub fn aya::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMap where U: core::convert::Into +pub type aya::maps::DevMap::Error = core::convert::Infallible +pub fn aya::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMap where U: core::convert::TryFrom +pub type aya::maps::DevMap::Error = >::Error +pub fn aya::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMap +pub fn aya::maps::DevMap::from(t: T) -> T +pub struct aya::maps::xdp::DevMapHash +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::get(&self, key: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMapHash::iter(&self) -> aya::maps::MapIter<'_, u32, DevMapValue, Self> +pub fn aya::maps::DevMapHash::keys(&self) -> aya::maps::MapKeys<'_, u32> +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +pub fn aya::maps::DevMapHash::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::DevMapHash +pub type aya::maps::DevMapHash::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMapHash<&'a aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMapHash<&'a mut aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMapHash where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMapHash where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMapHash where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMapHash where U: core::convert::From +pub fn aya::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMapHash where U: core::convert::Into +pub type aya::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMapHash where U: core::convert::TryFrom +pub type aya::maps::DevMapHash::Error = >::Error +pub fn aya::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::from(t: T) -> T +pub struct aya::maps::xdp::XskMap +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::len(&self) -> u32 +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::XskMap +pub type aya::maps::XskMap::Error = aya::maps::MapError +pub fn aya::maps::XskMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::XskMap<&'a aya::maps::MapData> +pub type aya::maps::XskMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::XskMap<&'a mut aya::maps::MapData> +pub type aya::maps::XskMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::XskMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::XskMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::XskMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::XskMap where U: core::convert::From +pub fn aya::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::XskMap where U: core::convert::Into +pub type aya::maps::XskMap::Error = core::convert::Infallible +pub fn aya::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::XskMap where U: core::convert::TryFrom +pub type aya::maps::XskMap::Error = >::Error +pub fn aya::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::XskMap +pub fn aya::maps::XskMap::from(t: T) -> T pub enum aya::maps::Map pub aya::maps::Map::Array(aya::maps::MapData) pub aya::maps::Map::BloomFilter(aya::maps::MapData) +pub aya::maps::Map::CpuMap(aya::maps::MapData) +pub aya::maps::Map::DevMap(aya::maps::MapData) +pub aya::maps::Map::DevMapHash(aya::maps::MapData) pub aya::maps::Map::HashMap(aya::maps::MapData) pub aya::maps::Map::LpmTrie(aya::maps::MapData) pub aya::maps::Map::LruHashMap(aya::maps::MapData) @@ -812,12 +997,25 @@ pub aya::maps::Map::SockMap(aya::maps::MapData) pub aya::maps::Map::Stack(aya::maps::MapData) pub aya::maps::Map::StackTraceMap(aya::maps::MapData) pub aya::maps::Map::Unsupported(aya::maps::MapData) +pub aya::maps::Map::XskMap(aya::maps::MapData) +impl core::convert::TryFrom for aya::maps::CpuMap +pub type aya::maps::CpuMap::Error = aya::maps::MapError +pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::DevMap +pub type aya::maps::DevMap::Error = aya::maps::MapError +pub fn aya::maps::DevMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::DevMapHash +pub type aya::maps::DevMapHash::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::XskMap +pub type aya::maps::XskMap::Error = aya::maps::MapError +pub fn aya::maps::XskMap::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result @@ -881,12 +1079,24 @@ pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack::Stack<&'a mut aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::CpuMap<&'a aya::maps::MapData> +pub type aya::maps::CpuMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMap<&'a aya::maps::MapData> +pub type aya::maps::DevMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMapHash<&'a aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ProgramArray<&'a aya::maps::MapData> pub type aya::maps::ProgramArray<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockMap<&'a aya::maps::MapData> pub type aya::maps::SockMap<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::XskMap<&'a aya::maps::MapData> +pub type aya::maps::XskMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -896,12 +1106,24 @@ pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &' impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::CpuMap<&'a mut aya::maps::MapData> +pub type aya::maps::CpuMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMap<&'a mut aya::maps::MapData> +pub type aya::maps::DevMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMapHash<&'a mut aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ProgramArray<&'a mut aya::maps::MapData> pub type aya::maps::ProgramArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockMap<&'a mut aya::maps::MapData> pub type aya::maps::SockMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::XskMap<&'a mut aya::maps::MapData> +pub type aya::maps::XskMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result @@ -984,12 +1206,15 @@ pub aya::maps::MapError::OutOfBounds::max_entries: u32 pub aya::maps::MapError::PinError pub aya::maps::MapError::PinError::error: aya::pin::PinError pub aya::maps::MapError::PinError::name: core::option::Option +pub aya::maps::MapError::ProgIdNotSupported pub aya::maps::MapError::ProgramNotLoaded pub aya::maps::MapError::SyscallError(crate::sys::SyscallError) pub aya::maps::MapError::Unsupported pub aya::maps::MapError::Unsupported::map_type: u32 impl core::convert::From for aya::BpfError pub fn aya::BpfError::from(source: aya::maps::MapError) -> Self +impl core::convert::From for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::from(source: aya::maps::MapError) -> Self impl core::convert::From for aya::programs::ProgramError pub fn aya::programs::ProgramError::from(source: aya::maps::MapError) -> Self impl core::error::Error for aya::maps::MapError @@ -1131,6 +1356,118 @@ impl core::borrow::BorrowMut for aya::maps::bloom_filter::BloomFilter::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::bloom_filter::BloomFilter pub fn aya::maps::bloom_filter::BloomFilter::from(t: T) -> T +pub struct aya::maps::CpuMap +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::get(&self, cpu_index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::CpuMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::CpuMap::len(&self) -> u32 +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::CpuMap +pub type aya::maps::CpuMap::Error = aya::maps::MapError +pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::CpuMap<&'a aya::maps::MapData> +pub type aya::maps::CpuMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::CpuMap<&'a mut aya::maps::MapData> +pub type aya::maps::CpuMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::CpuMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::CpuMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::CpuMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::CpuMap where U: core::convert::From +pub fn aya::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::CpuMap where U: core::convert::Into +pub type aya::maps::CpuMap::Error = core::convert::Infallible +pub fn aya::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::CpuMap where U: core::convert::TryFrom +pub type aya::maps::CpuMap::Error = >::Error +pub fn aya::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::CpuMap +pub fn aya::maps::CpuMap::from(t: T) -> T +pub struct aya::maps::DevMap +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::get(&self, index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::DevMap::len(&self) -> u32 +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::DevMap +pub type aya::maps::DevMap::Error = aya::maps::MapError +pub fn aya::maps::DevMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMap<&'a aya::maps::MapData> +pub type aya::maps::DevMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMap<&'a mut aya::maps::MapData> +pub type aya::maps::DevMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMap where U: core::convert::From +pub fn aya::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMap where U: core::convert::Into +pub type aya::maps::DevMap::Error = core::convert::Infallible +pub fn aya::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMap where U: core::convert::TryFrom +pub type aya::maps::DevMap::Error = >::Error +pub fn aya::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMap +pub fn aya::maps::DevMap::from(t: T) -> T +pub struct aya::maps::DevMapHash +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::get(&self, key: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMapHash::iter(&self) -> aya::maps::MapIter<'_, u32, DevMapValue, Self> +pub fn aya::maps::DevMapHash::keys(&self) -> aya::maps::MapKeys<'_, u32> +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +pub fn aya::maps::DevMapHash::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::DevMapHash +pub type aya::maps::DevMapHash::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMapHash<&'a aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMapHash<&'a mut aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMapHash where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMapHash where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMapHash where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMapHash where U: core::convert::From +pub fn aya::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMapHash where U: core::convert::Into +pub type aya::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMapHash where U: core::convert::TryFrom +pub type aya::maps::DevMapHash::Error = >::Error +pub fn aya::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::from(t: T) -> T pub struct aya::maps::HashMap impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::get(&self, key: &K, flags: u64) -> core::result::Result @@ -1712,6 +2049,41 @@ impl core::borrow::BorrowMut for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::from(t: T) -> T +pub struct aya::maps::XskMap +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::len(&self) -> u32 +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::XskMap +pub type aya::maps::XskMap::Error = aya::maps::MapError +pub fn aya::maps::XskMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::XskMap<&'a aya::maps::MapData> +pub type aya::maps::XskMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::XskMap<&'a mut aya::maps::MapData> +pub type aya::maps::XskMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::XskMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::XskMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::XskMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::XskMap where U: core::convert::From +pub fn aya::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::XskMap where U: core::convert::Into +pub type aya::maps::XskMap::Error = core::convert::Infallible +pub fn aya::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::XskMap where U: core::convert::TryFrom +pub type aya::maps::XskMap::Error = >::Error +pub fn aya::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::XskMap +pub fn aya::maps::XskMap::from(t: T) -> T pub trait aya::maps::IterableMap pub fn aya::maps::IterableMap::get(&self, key: &K) -> core::result::Result pub fn aya::maps::IterableMap::map(&self) -> &aya::maps::MapData @@ -4514,13 +4886,12 @@ pub fn aya::programs::xdp::Xdp::attach(&mut self, interface: &str, flags: aya::p pub fn aya::programs::xdp::Xdp::attach_to_if_index(&mut self, if_index: u32, flags: aya::programs::xdp::XdpFlags) -> core::result::Result pub fn aya::programs::xdp::Xdp::attach_to_link(&mut self, link: aya::programs::xdp::XdpLink) -> core::result::Result pub fn aya::programs::xdp::Xdp::detach(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::xdp::Xdp::from_pin>(path: P, attach_type: aya_obj::programs::xdp::XdpAttachType) -> core::result::Result pub fn aya::programs::xdp::Xdp::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::xdp::Xdp::take_link(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::from_pin>(path: P) -> core::result::Result -impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::info(&self) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> @@ -6681,13 +7052,12 @@ pub fn aya::programs::xdp::Xdp::attach(&mut self, interface: &str, flags: aya::p pub fn aya::programs::xdp::Xdp::attach_to_if_index(&mut self, if_index: u32, flags: aya::programs::xdp::XdpFlags) -> core::result::Result pub fn aya::programs::xdp::Xdp::attach_to_link(&mut self, link: aya::programs::xdp::XdpLink) -> core::result::Result pub fn aya::programs::xdp::Xdp::detach(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::xdp::Xdp::from_pin>(path: P, attach_type: aya_obj::programs::xdp::XdpAttachType) -> core::result::Result pub fn aya::programs::xdp::Xdp::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::xdp::Xdp::take_link(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::from_pin>(path: P) -> core::result::Result -impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::info(&self) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> @@ -7234,6 +7604,8 @@ pub fn aya::VerifierLogLevel::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::VerifierLogLevel pub fn aya::VerifierLogLevel::from(t: T) -> T pub unsafe trait aya::Pod: core::marker::Copy + 'static +impl aya::Pod for aya_obj::generated::linux_bindings_x86_64::bpf_cpumap_val +impl aya::Pod for aya_obj::generated::linux_bindings_x86_64::bpf_devmap_val impl aya::Pod for i128 impl aya::Pod for i16 impl aya::Pod for i32 From dffff1ce6b6c4500b970dec53b57b7eb9c3ec717 Mon Sep 17 00:00:00 2001 From: astoycos Date: Mon, 28 Aug 2023 17:28:27 -0400 Subject: [PATCH 47/95] integration-test: fix load time and add test Time since boot is defined as the UNIX_EPOCH plus the duration since boot. which is realtime - boottime NOT boottime - realtime. Add a integration test to ensure this doesn't happen again. Signed-off-by: astoycos --- aya/src/programs/utils.rs | 2 +- test/integration-test/src/tests/load.rs | 30 +++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index a32d9f93..0930e62b 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -74,7 +74,7 @@ pub(crate) fn boot_time() -> SystemTime { }; let since_boot = get_time(libc::CLOCK_BOOTTIME); let since_epoch = get_time(libc::CLOCK_REALTIME); - UNIX_EPOCH + since_boot - since_epoch + UNIX_EPOCH + since_epoch - since_boot } /// Get the specified information from a file descriptor's fdinfo. diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 4c99a008..761a9e89 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -1,4 +1,8 @@ -use std::{convert::TryInto as _, thread, time}; +use std::{ + convert::TryInto as _, + thread, + time::{Duration, SystemTime}, +}; use aya::{ maps::Array, @@ -11,7 +15,7 @@ use aya::{ }; const MAX_RETRIES: usize = 100; -const RETRY_DURATION: time::Duration = time::Duration::from_millis(10); +const RETRY_DURATION: Duration = Duration::from_millis(10); #[test] fn long_name() { @@ -145,6 +149,28 @@ fn unload_xdp() { assert_unloaded("pass"); } +#[test] +fn test_loaded_at() { + let mut bpf = Bpf::load(crate::TEST).unwrap(); + let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let t1 = SystemTime::now(); + prog.load().unwrap(); + let t2 = SystemTime::now(); + assert_loaded("pass"); + + let loaded_at = prog.info().unwrap().loaded_at(); + + let range = t1..t2; + assert!( + range.contains(&loaded_at), + "{range:?}.contains({loaded_at:?})" + ); + + prog.unload().unwrap(); + + assert_unloaded("pass"); +} + #[test] fn unload_kprobe() { let mut bpf = Bpf::load(crate::TEST).unwrap(); From 579e3cee22ae8e932efb0894ca7fd9ceb91ca7fa Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Mon, 18 Sep 2023 16:16:27 +0200 Subject: [PATCH 48/95] aya, bpf: misc fixes following review comments --- aya-bpf-macros/src/lib.rs | 9 +-- aya-bpf-macros/src/xdp.rs | 2 +- aya-obj/src/obj.rs | 8 --- aya/src/bpf.rs | 6 +- aya/src/maps/mod.rs | 2 +- aya/src/maps/xdp/cpu_map.rs | 70 ++++++++++++---------- aya/src/maps/xdp/dev_map.rs | 76 +++++++++++++----------- aya/src/maps/xdp/dev_map_hash.rs | 68 +++++++++++---------- aya/src/maps/xdp/mod.rs | 15 +++++ aya/src/maps/xdp/xsk_map.rs | 4 ++ bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 18 +++--- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 37 +++++++----- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 22 +++---- bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 14 +++-- test/integration-ebpf/src/redirect.rs | 8 +-- xtask/public-api/aya-bpf.txt | 16 ++--- 16 files changed, 203 insertions(+), 172 deletions(-) diff --git a/aya-bpf-macros/src/lib.rs b/aya-bpf-macros/src/lib.rs index bdac2795..f29b725f 100644 --- a/aya-bpf-macros/src/lib.rs +++ b/aya-bpf-macros/src/lib.rs @@ -147,14 +147,7 @@ pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream { /// /// #[xdp(frags)] /// pub fn xdp(ctx: XdpContext) -> u32 { -/// match unsafe { try_xdp(ctx) } { -/// Ok(ret) => ret, -/// Err(ret) => ret, -/// } -/// } -/// -/// unsafe fn try_xdp(_ctx: XdpContext) -> Result { -/// Ok(XDP_PASS) +/// XDP_PASS /// } /// ``` #[proc_macro_error] diff --git a/aya-bpf-macros/src/xdp.rs b/aya-bpf-macros/src/xdp.rs index 6a8f61e7..61f8c014 100644 --- a/aya-bpf-macros/src/xdp.rs +++ b/aya-bpf-macros/src/xdp.rs @@ -28,7 +28,7 @@ impl Xdp { Some(name) => { return Err(Error::new_spanned( "map", - format!("invalid value. expected 'cpumap' or 'devmap', found '{name}'"), + format!("Invalid value. Expected 'cpumap' or 'devmap', found '{name}'"), )) } None => None, diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 6909a229..38221f96 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -50,7 +50,6 @@ pub struct Features { bpf_cookie: bool, cpumap_prog_id: bool, devmap_prog_id: bool, - devmap_hash_prog_id: bool, btf: Option, } @@ -65,7 +64,6 @@ impl Features { bpf_cookie: bool, cpumap_prog_id: bool, devmap_prog_id: bool, - devmap_hash_prog_id: bool, btf: Option, ) -> Self { Self { @@ -76,7 +74,6 @@ impl Features { bpf_cookie, cpumap_prog_id, devmap_prog_id, - devmap_hash_prog_id, btf, } } @@ -116,11 +113,6 @@ impl Features { self.devmap_prog_id } - /// Returns whether XDP Hash Device Maps support chained program IDs. - pub fn devmap_hash_prog_id(&self) -> bool { - self.devmap_hash_prog_id - } - /// If BTF is supported, returns which BTF features are supported. pub fn btf(&self) -> Option<&BtfFeatures> { self.btf.as_ref() diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 181d971f..2272bc52 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -96,7 +96,6 @@ fn detect_features() -> Features { is_bpf_cookie_supported(), is_prog_id_supported(BPF_MAP_TYPE_CPUMAP), is_prog_id_supported(BPF_MAP_TYPE_DEVMAP), - is_prog_id_supported(BPF_MAP_TYPE_DEVMAP_HASH), btf, ); debug!("BPF Feature Detection: {:#?}", f); @@ -484,12 +483,9 @@ impl<'a> BpfLoader<'a> { Ok(BPF_MAP_TYPE_CPUMAP) => { obj.set_value_size(if FEATURES.cpumap_prog_id() { 8 } else { 4 }) } - Ok(BPF_MAP_TYPE_DEVMAP) => { + Ok(BPF_MAP_TYPE_DEVMAP | BPF_MAP_TYPE_DEVMAP_HASH) => { obj.set_value_size(if FEATURES.devmap_prog_id() { 8 } else { 4 }) } - Ok(BPF_MAP_TYPE_DEVMAP_HASH) => { - obj.set_value_size(if FEATURES.devmap_hash_prog_id() { 8 } else { 4 }) - } _ => (), } let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index d41600fe..1a590791 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -279,7 +279,7 @@ pub enum Map { DevMapHash(MapData), /// A [`XskMap`] map. XskMap(MapData), - /// An unsupported map type + /// An unsupported map type. Unsupported(MapData), } diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index e6349163..d9cc7d19 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -6,7 +6,7 @@ use std::{ os::fd::{AsFd, AsRawFd}, }; -use aya_obj::generated::{bpf_cpumap_val, bpf_cpumap_val__bindgen_ty_1}; +use aya_obj::generated::bpf_cpumap_val; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, @@ -15,6 +15,8 @@ use crate::{ Pod, FEATURES, }; +use super::XdpMapError; + /// An array of available CPUs. /// /// XDP programs can use this map to redirect packets to a target @@ -29,19 +31,24 @@ use crate::{ /// # let elf_bytes = &[]; /// use aya::maps::xdp::CpuMap; /// +/// let ncpus = aya::util::nr_cpus().unwrap() as u32; /// let mut bpf = aya::BpfLoader::new() -/// .set_max_entries("CPUS", aya::util::nr_cpus().unwrap() as u32) +/// .set_max_entries("CPUS", ncpus) /// .load(elf_bytes) /// .unwrap(); /// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS").unwrap())?; /// let flags = 0; /// let queue_size = 2048; -/// for i in 0u32..8u32 { +/// for i in 0..ncpus { /// cpumap.set(i, queue_size, None, flags); /// } /// /// # Ok::<(), aya::BpfError>(()) /// ``` +/// +/// # See also +/// +/// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_CPUMAP")] pub struct CpuMap { inner: T, @@ -67,7 +74,7 @@ impl> CpuMap { self.inner.borrow().obj.max_entries() } - /// Returns the queue size and possible program for a given CPU index. + /// Returns the queue size and optional program for a given CPU index. /// /// # Errors /// @@ -81,7 +88,7 @@ impl> CpuMap { let value = if FEATURES.cpumap_prog_id() { bpf_map_lookup_elem::<_, bpf_cpumap_val>(fd, &cpu_index, flags).map(|value| { value.map(|value| CpuMapValue { - qsize: value.qsize, + queue_size: value.qsize, // SAFETY: map writes use fd, map reads use id. // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241 prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), @@ -90,7 +97,7 @@ impl> CpuMap { } else { bpf_map_lookup_elem::<_, u32>(fd, &cpu_index, flags).map(|value| { value.map(|qsize| CpuMapValue { - qsize, + queue_size: qsize, prog_id: None, }) }) @@ -115,52 +122,52 @@ impl> CpuMap { /// When sending the packet to the CPU at the given index, the kernel will queue up to /// `queue_size` packets before dropping them. /// - /// Another XDP program can be passed in that will be run on the target CPU, instead of the CPU - /// that receives the packets. This allows to perform minimal computations on CPUs that - /// directly handle packets from a NIC's RX queues, and perform possibly heavier ones in other, - /// less busy CPUs. + /// Starting from Linux kernel 5.9, another XDP program can be passed in that will be run on the + /// target CPU, instead of the CPU that receives the packets. This allows to perform minimal + /// computations on CPUs that directly handle packets from a NIC's RX queues, and perform + /// possibly heavier ones in other, less busy CPUs. /// - /// Note that only XDP programs with the `map = "cpumap"` argument can be passed. See the - /// kernel-space `aya_bpf::xdp` for more information. + /// The chained program must be loaded with the `BPF_XDP_CPUMAP` attach type. When using + /// `aya-ebpf`, that means XDP programs that specify the `map = "cpumap"` argument. See the + /// kernel-space `aya_ebpf::xdp` for more information. /// /// # Errors /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] - /// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not - /// support program ids and one is provided. + /// if `bpf_map_update_elem` fails, [`XdpMapError::ChainedProgramNotSupported`] if the kernel + /// does not support chained programs and one is provided. pub fn set( &mut self, cpu_index: u32, queue_size: u32, program: Option<&ProgramFd>, flags: u64, - ) -> Result<(), MapError> { + ) -> Result<(), XdpMapError> { let data = self.inner.borrow_mut(); check_bounds(data, cpu_index)?; let fd = data.fd().as_fd(); let res = if FEATURES.cpumap_prog_id() { - let value = bpf_cpumap_val { - qsize: queue_size, - bpf_prog: bpf_cpumap_val__bindgen_ty_1 { - // Default is valid as the kernel will only consider fd > 0: - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 - fd: program - .map(|prog| prog.as_fd().as_raw_fd()) - .unwrap_or_default(), - }, - }; + let mut value = unsafe { std::mem::zeroed::() }; + value.qsize = queue_size; + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 + value.bpf_prog.fd = program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(); bpf_map_update_elem(fd, Some(&cpu_index), &value, flags) } else { if program.is_some() { - return Err(MapError::ProgIdNotSupported); + return Err(XdpMapError::ChainedProgramNotSupported); } bpf_map_update_elem(fd, Some(&cpu_index), &queue_size, flags) }; - res.map_err(|(_, io_error)| SyscallError { - call: "bpf_map_update_elem", - io_error, + res.map_err(|(_, io_error)| { + MapError::from(SyscallError { + call: "bpf_map_update_elem", + io_error, + }) })?; Ok(()) } @@ -179,7 +186,10 @@ impl> IterableMap for CpuMap { unsafe impl Pod for bpf_cpumap_val {} #[derive(Clone, Copy, Debug)] +/// The value of a CPU map. pub struct CpuMapValue { - pub qsize: u32, + /// Size of the for the CPU. + pub queue_size: u32, + /// Chained XDP program ID. pub prog_id: Option, } diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index df43461c..3c4240f5 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -6,7 +6,7 @@ use std::{ os::fd::{AsFd, AsRawFd}, }; -use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; +use aya_obj::generated::bpf_devmap_val; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, @@ -15,6 +15,8 @@ use crate::{ Pod, FEATURES, }; +use super::XdpMapError; + /// An array of network devices. /// /// XDP programs can use this map to redirect to other network @@ -30,12 +32,15 @@ use crate::{ /// use aya::maps::xdp::DevMap; /// /// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?; -/// let source = 32u32; -/// let dest = 42u32; -/// devmap.set(source, dest, None, 0); +/// // Lookups at index 2 will redirect packets to interface with index 3 (e.g. eth1) +/// devmap.set(2, 3, None, 0); /// /// # Ok::<(), aya::BpfError>(()) /// ``` +/// +/// # See also +/// +/// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_DEVMAP")] pub struct DevMap { inner: T, @@ -61,7 +66,7 @@ impl> DevMap { self.inner.borrow().obj.max_entries() } - /// Returns the target ifindex and possible program at a given index. + /// Returns the target interface index and optional program at a given index. /// /// # Errors /// @@ -75,7 +80,7 @@ impl> DevMap { let value = if FEATURES.devmap_prog_id() { bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &index, flags).map(|value| { value.map(|value| DevMapValue { - ifindex: value.ifindex, + if_index: value.ifindex, // SAFETY: map writes use fd, map reads use id. // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), @@ -84,7 +89,7 @@ impl> DevMap { } else { bpf_map_lookup_elem::<_, u32>(fd, &index, flags).map(|value| { value.map(|ifindex| DevMapValue { - ifindex, + if_index: ifindex, prog_id: None, }) }) @@ -104,57 +109,57 @@ impl> DevMap { } impl> DevMap { - /// Sets the target ifindex at index, and optionally a chained program. + /// Sets the target interface index at index, and optionally a chained program. /// /// When redirecting using `index`, packets will be transmitted by the interface with - /// `ifindex`. + /// `target_if_index`. /// - /// Another XDP program can be passed in that will be run before actual transmission. It can be - /// used to modify the packet before transmission with NIC specific data (MAC address update, - /// checksum computations, etc) or other purposes. + /// Starting from Linux kernel 5.8, another XDP program can be passed in that will be run before + /// actual transmission. It can be used to modify the packet before transmission with NIC + /// specific data (MAC address update, checksum computations, etc) or other purposes. /// - /// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the - /// kernel-space `aya_bpf::xdp` for more information. + /// The chained program must be loaded with the `BPF_XDP_DEVMAP` attach type. When using + /// `aya-ebpf`, that means XDP programs that specify the `map = "devmap"` argument. See the + /// kernel-space `aya_ebpf::xdp` for more information. /// /// # Errors /// /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not - /// support program ids and one is provided. + /// support chained programs and one is provided. pub fn set( &mut self, index: u32, - ifindex: u32, + target_if_index: u32, program: Option<&ProgramFd>, flags: u64, - ) -> Result<(), MapError> { + ) -> Result<(), XdpMapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; let fd = data.fd().as_fd(); let res = if FEATURES.devmap_prog_id() { - let value = bpf_devmap_val { - ifindex, - bpf_prog: bpf_devmap_val__bindgen_ty_1 { - // Default is valid as the kernel will only consider fd > 0: - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 - fd: program - .map(|prog| prog.as_fd().as_raw_fd()) - .unwrap_or_default(), - }, - }; + let mut value = unsafe { std::mem::zeroed::() }; + value.ifindex = target_if_index; + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + value.bpf_prog.fd = program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(); bpf_map_update_elem(fd, Some(&index), &value, flags) } else { if program.is_some() { - return Err(MapError::ProgIdNotSupported); + return Err(XdpMapError::ChainedProgramNotSupported); } - bpf_map_update_elem(fd, Some(&index), &ifindex, flags) + bpf_map_update_elem(fd, Some(&index), &target_if_index, flags) }; - res.map_err(|(_, io_error)| SyscallError { - call: "bpf_map_update_elem", - io_error, + res.map_err(|(_, io_error)| { + MapError::from(SyscallError { + call: "bpf_map_update_elem", + io_error, + }) })?; Ok(()) } @@ -173,7 +178,10 @@ impl> IterableMap for DevMap { unsafe impl Pod for bpf_devmap_val {} #[derive(Clone, Copy, Debug)] +/// The value of a device map. pub struct DevMapValue { - pub ifindex: u32, + /// Target interface index to redirect to. + pub if_index: u32, + /// Chained XDP program ID. pub prog_id: Option, } diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 8311a29b..469c8420 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -6,7 +6,7 @@ use std::{ os::fd::{AsFd, AsRawFd}, }; -use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; +use aya_obj::generated::bpf_devmap_val; use crate::{ maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, @@ -15,7 +15,7 @@ use crate::{ FEATURES, }; -use super::dev_map::DevMapValue; +use super::{dev_map::DevMapValue, XdpMapError}; /// An hashmap of network devices. /// @@ -32,12 +32,15 @@ use super::dev_map::DevMapValue; /// use aya::maps::xdp::DevMapHash; /// /// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?; -/// let flags = 0; -/// let ifindex = 32u32; -/// devmap.insert(ifindex, ifindex, None, flags); +/// // Lookups with key 2 will redirect packets to interface with index 3 (e.g. eth1) +/// devmap.insert(2, 3, None, 0); /// /// # Ok::<(), aya::BpfError>(()) /// ``` +/// +/// # See also +/// +/// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] pub struct DevMapHash { inner: T, @@ -47,7 +50,7 @@ impl> DevMapHash { pub(crate) fn new(map: T) -> Result { let data = map.borrow(); - if FEATURES.devmap_hash_prog_id() { + if FEATURES.devmap_prog_id() { check_kv_size::(data)?; } else { check_kv_size::(data)?; @@ -56,7 +59,7 @@ impl> DevMapHash { Ok(Self { inner: map }) } - /// Returns the target ifindex and possible program for a given key. + /// Returns the target interface index and optional program for a given key. /// /// # Errors /// @@ -64,10 +67,10 @@ impl> DevMapHash { pub fn get(&self, key: u32, flags: u64) -> Result { let fd = self.inner.borrow().fd().as_fd(); - let value = if FEATURES.devmap_hash_prog_id() { + let value = if FEATURES.devmap_prog_id() { bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &key, flags).map(|value| { value.map(|value| DevMapValue { - ifindex: value.ifindex, + if_index: value.ifindex, // SAFETY: map writes use fd, map reads use id. // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), @@ -76,7 +79,7 @@ impl> DevMapHash { } else { bpf_map_lookup_elem::<_, u32>(fd, &key, flags).map(|value| { value.map(|ifindex| DevMapValue { - ifindex, + if_index: ifindex, prog_id: None, }) }) @@ -105,44 +108,43 @@ impl> DevMapHash { /// /// When redirecting using `key`, packets will be transmitted by the interface with `ifindex`. /// - /// Another XDP program can be passed in that will be run before actual transmission. It can be - /// used to modify the packet before transmission with NIC specific data (MAC address update, - /// checksum computations, etc) or other purposes. + /// Starting from Linux kernel 5.8, another XDP program can be passed in that will be run before + /// actual transmission. It can be used to modify the packet before transmission with NIC + /// specific data (MAC address update, checksum computations, etc) or other purposes. /// - /// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the - /// kernel-space `aya_bpf::xdp` for more information. + /// The chained program must be loaded with the `BPF_XDP_DEVMAP` attach type. When using + /// `aya-ebpf`, that means XDP programs that specify the `map = "devmap"` argument. See the + /// kernel-space `aya_ebpf::xdp` for more information. /// /// # Errors /// /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails, - /// [`MapError::ProgIdNotSupported`] if the kernel does not support program ids and one is + /// [`MapError::ProgIdNotSupported`] if the kernel does not support chained programs and one is /// provided. pub fn insert( &mut self, key: u32, - ifindex: u32, + target_if_index: u32, program: Option<&ProgramFd>, flags: u64, - ) -> Result<(), MapError> { - if FEATURES.devmap_hash_prog_id() { - let value = bpf_devmap_val { - ifindex, - bpf_prog: bpf_devmap_val__bindgen_ty_1 { - // Default is valid as the kernel will only consider fd > 0: - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 - // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 - fd: program - .map(|prog| prog.as_fd().as_raw_fd()) - .unwrap_or_default(), - }, - }; - hash_map::insert(self.inner.borrow_mut(), &key, &value, flags) + ) -> Result<(), XdpMapError> { + if FEATURES.devmap_prog_id() { + let mut value = unsafe { std::mem::zeroed::() }; + value.ifindex = target_if_index; + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + value.bpf_prog.fd = program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(); + hash_map::insert(self.inner.borrow_mut(), &key, &value, flags)?; } else { if program.is_some() { - return Err(MapError::ProgIdNotSupported); + return Err(XdpMapError::ChainedProgramNotSupported); } - hash_map::insert(self.inner.borrow_mut(), &key, &ifindex, flags) + hash_map::insert(self.inner.borrow_mut(), &key, &target_if_index, flags)?; } + Ok(()) } /// Removes a value from the map. diff --git a/aya/src/maps/xdp/mod.rs b/aya/src/maps/xdp/mod.rs index 6120dc90..0faa41bb 100644 --- a/aya/src/maps/xdp/mod.rs +++ b/aya/src/maps/xdp/mod.rs @@ -8,3 +8,18 @@ pub use cpu_map::CpuMap; pub use dev_map::DevMap; pub use dev_map_hash::DevMapHash; pub use xsk_map::XskMap; + +use super::MapError; +use thiserror::Error; + +#[derive(Error, Debug)] +/// Errors occuring from working with XDP maps. +pub enum XdpMapError { + /// Chained programs are not supported. + #[error("chained programs are not supported by the current kernel")] + ChainedProgramNotSupported, + + /// Map operation failed. + #[error(transparent)] + MapError(#[from] MapError), +} diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs index 99477dbd..5382ae4c 100644 --- a/aya/src/maps/xdp/xsk_map.rs +++ b/aya/src/maps/xdp/xsk_map.rs @@ -30,6 +30,10 @@ use crate::{ /// xskmap.set(0, socket_fd, 0); /// # Ok::<(), aya::BpfError>(()) /// ``` +/// +/// # See also +/// +/// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_XSKMAP")] pub struct XskMap { inner: T, diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs index df1a32d2..0179382c 100644 --- a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -1,6 +1,6 @@ use core::{cell::UnsafeCell, mem}; -use aya_bpf_bindings::bindings::bpf_cpumap_val; +use aya_bpf_bindings::bindings::{bpf_cpumap_val, xdp_action::XDP_REDIRECT}; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, @@ -40,9 +40,9 @@ unsafe impl Sync for CpuMap {} impl CpuMap { /// Creates a [`CpuMap`] with a set maximum number of elements. /// - /// In a CPU Map, an entry represents a CPU core. Thus there should be as many entries as there - /// are CPU cores on the system. It can be set to zero here, and updated by userspace at - /// runtime. Refer to the userspace documentation for more information. + /// In a CPU map, an entry represents a CPU core. Thus there should be as many entries as there + /// are CPU cores on the system. `max_entries` can be set to zero here, and updated by userspace + /// at runtime. Refer to the userspace documentation for more information. /// /// # Examples /// @@ -109,16 +109,18 @@ impl CpuMap { /// #[xdp] /// fn xdp(_ctx: XdpContext) -> u32 { /// // Redirect to CPU 7 or drop packet if no entry found. - /// MAP.redirect(7, xdp_action::XDP_DROP as u64) + /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP) /// } /// ``` #[inline(always)] - pub fn redirect(&self, index: u32, flags: u64) -> u32 { - unsafe { + pub fn redirect(&self, index: u32, flags: u64) -> Result { + let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; + match ret.unsigned_abs() as u32 { + XDP_REDIRECT => Ok(XDP_REDIRECT), // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // argument on error. Thus I have no idea why it returns a long (i64) instead of // something saner, hence the unsigned_abs. - bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 + ret => Err(ret), } } } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index 18a76790..6142d151 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -1,6 +1,6 @@ -use core::{cell::UnsafeCell, mem, ptr::NonNull}; +use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; -use aya_bpf_bindings::bindings::bpf_devmap_val; +use aya_bpf_bindings::bindings::{bpf_devmap_val, xdp_action::XDP_REDIRECT}; use aya_bpf_cty::c_void; use crate::{ @@ -99,9 +99,9 @@ impl DevMap { /// #[map] /// static MAP: DevMap = DevMap::with_max_entries(1, 0); /// - /// let ifindex = MAP.get(0); + /// let target_if_index = MAP.get(0).target_if_index; /// - /// // redirect to ifindex + /// // redirect to if_index /// ``` #[inline(always)] pub fn get(&self, index: u32) -> Option { @@ -111,10 +111,10 @@ impl DevMap { &index as *const _ as *const c_void, ); NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { - ifindex: p.as_ref().ifindex, + if_index: p.as_ref().ifindex, // SAFETY: map writes use fd, map reads use id. // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 - prog_id: p.as_ref().bpf_prog.id, + prog_id: NonZeroU32::new(p.as_ref().bpf_prog.id), }) } } @@ -133,23 +133,28 @@ impl DevMap { /// static MAP: DevMap = DevMap::with_max_entries(8, 0); /// /// #[xdp] - /// fn xdp(_ctx: XdpContext) -> i32 { - /// MAP.redirect(7, xdp_action::XDP_PASS as u64) + /// fn xdp(_ctx: XdpContext) -> u32 { + /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP) /// } /// ``` #[inline(always)] - pub fn redirect(&self, index: u32, flags: u64) -> u32 { - // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags - // argument on error. Thus I have no idea why it returns a long (i64) instead of - // something saner, hence the unsigned_abs. - unsafe { - bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 + pub fn redirect(&self, index: u32, flags: u64) -> Result { + let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; + match ret.unsigned_abs() as u32 { + XDP_REDIRECT => Ok(XDP_REDIRECT), + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags + // argument on error. Thus I have no idea why it returns a long (i64) instead of + // something saner, hence the unsigned_abs. + ret => Err(ret), } } } #[derive(Clone, Copy)] +/// The value of a device map. pub struct DevMapValue { - pub ifindex: u32, - pub prog_id: u32, + /// Target interface index to redirect to. + pub if_index: u32, + /// Chained XDP program ID. + pub prog_id: Option, } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index a6533e76..eb65b105 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -1,6 +1,6 @@ -use core::{cell::UnsafeCell, mem, ptr::NonNull}; +use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; -use aya_bpf_bindings::bindings::bpf_devmap_val; +use aya_bpf_bindings::bindings::{bpf_devmap_val, xdp_action::XDP_REDIRECT}; use aya_bpf_cty::c_void; use crate::{ @@ -103,7 +103,7 @@ impl DevMapHash { /// #[map] /// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0); /// - /// let ifindex = MAP.get(42); + /// let target_if_index = MAP.get(42).target_if_index; /// /// // redirect to ifindex /// ``` @@ -113,10 +113,10 @@ impl DevMapHash { let value = bpf_map_lookup_elem(self.def.get() as *mut _, &key as *const _ as *const c_void); NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { - ifindex: p.as_ref().ifindex, + if_index: p.as_ref().ifindex, // SAFETY: map writes use fd, map reads use id. // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 - prog_id: p.as_ref().bpf_prog.id, + prog_id: NonZeroU32::new(p.as_ref().bpf_prog.id), }) } } @@ -135,17 +135,19 @@ impl DevMapHash { /// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0); /// /// #[xdp] - /// fn xdp(_ctx: XdpContext) -> i32 { - /// MAP.redirect(7, xdp_action::XDP_PASS as u64) + /// fn xdp(_ctx: XdpContext) -> u32 { + /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP) /// } /// ``` #[inline(always)] - pub fn redirect(&self, key: u32, flags: u64) -> u32 { - unsafe { + pub fn redirect(&self, index: u32, flags: u64) -> Result { + let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; + match ret.unsigned_abs() as u32 { + XDP_REDIRECT => Ok(XDP_REDIRECT), // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // argument on error. Thus I have no idea why it returns a long (i64) instead of // something saner, hence the unsigned_abs. - bpf_redirect_map(self.def.get() as *mut _, key.into(), flags).unsigned_abs() as u32 + ret => Err(ret), } } } diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs index ee766fa5..f4546edb 100644 --- a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -1,6 +1,6 @@ use core::{cell::UnsafeCell, mem, ptr::NonNull}; -use aya_bpf_bindings::bindings::bpf_xdp_sock; +use aya_bpf_bindings::bindings::{bpf_xdp_sock, xdp_action::XDP_REDIRECT}; use aya_bpf_cty::c_void; use crate::{ @@ -150,18 +150,20 @@ impl XskMap { /// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); /// /// #[xdp] - /// fn xdp(ctx, XdpContext) -> i32 { + /// fn xdp(ctx, XdpContext) -> u32 { /// let queue_id = unsafe { (*ctx.ctx).rx_queue_index }; - /// MAP.redirect(queue_id, xdp_action::XDP_DROP as u64) + /// MAP.redirect(queue_id, 0).unwrap_or(xdp_action::XDP_DROP) /// } /// ``` #[inline(always)] - pub fn redirect(&self, index: u32, flags: u64) -> u32 { - unsafe { + pub fn redirect(&self, index: u32, flags: u64) -> Result { + let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; + match ret.unsigned_abs() as u32 { + XDP_REDIRECT => Ok(XDP_REDIRECT), // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // argument on error. Thus I have no idea why it returns a long (i64) instead of // something saner, hence the unsigned_abs. - bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 + ret => Err(ret), } } } diff --git a/test/integration-ebpf/src/redirect.rs b/test/integration-ebpf/src/redirect.rs index 5817b418..41812cd0 100644 --- a/test/integration-ebpf/src/redirect.rs +++ b/test/integration-ebpf/src/redirect.rs @@ -26,25 +26,25 @@ static mut HITS: Array = Array::with_max_entries(2, 0); #[xdp] pub fn redirect_sock(_ctx: XdpContext) -> u32 { - SOCKS.redirect(0, xdp_action::XDP_ABORTED as u64) + SOCKS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED) } #[xdp] pub fn redirect_dev(_ctx: XdpContext) -> u32 { inc_hit(0); - DEVS.redirect(0, xdp_action::XDP_ABORTED as u64) + DEVS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED) } #[xdp] pub fn redirect_dev_hash(_ctx: XdpContext) -> u32 { inc_hit(0); - DEVS_HASH.redirect(10, xdp_action::XDP_ABORTED as u64) + DEVS_HASH.redirect(10, 0).unwrap_or(xdp_action::XDP_ABORTED) } #[xdp] pub fn redirect_cpu(_ctx: XdpContext) -> u32 { inc_hit(0); - CPUS.redirect(0, xdp_action::XDP_ABORTED as u64) + CPUS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED) } #[xdp(map = "cpumap")] diff --git a/xtask/public-api/aya-bpf.txt b/xtask/public-api/aya-bpf.txt index b7de5541..4121839f 100644 --- a/xtask/public-api/aya-bpf.txt +++ b/xtask/public-api/aya-bpf.txt @@ -567,7 +567,7 @@ pub mod aya_bpf::maps::xdp #[repr(transparent)] pub struct aya_bpf::maps::xdp::CpuMap impl aya_bpf::maps::CpuMap pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap -pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap impl core::marker::Sync for aya_bpf::maps::CpuMap impl core::marker::Send for aya_bpf::maps::CpuMap @@ -594,7 +594,7 @@ pub fn aya_bpf::maps::CpuMap::from(t: T) -> T impl aya_bpf::maps::DevMap pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap -pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap impl core::marker::Sync for aya_bpf::maps::DevMap impl core::marker::Send for aya_bpf::maps::DevMap @@ -621,7 +621,7 @@ pub fn aya_bpf::maps::DevMap::from(t: T) -> T impl aya_bpf::maps::DevMapHash pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash -pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::DevMapHash::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash impl core::marker::Sync for aya_bpf::maps::DevMapHash impl core::marker::Send for aya_bpf::maps::DevMapHash @@ -648,7 +648,7 @@ pub fn aya_bpf::maps::DevMapHash::from(t: T) -> T impl aya_bpf::maps::XskMap pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap -pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap impl core::marker::Sync for aya_bpf::maps::XskMap impl core::marker::Send for aya_bpf::maps::XskMap @@ -729,7 +729,7 @@ pub fn aya_bpf::maps::bloom_filter::BloomFilter::from(t: T) -> T #[repr(transparent)] pub struct aya_bpf::maps::CpuMap impl aya_bpf::maps::CpuMap pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap -pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap impl core::marker::Sync for aya_bpf::maps::CpuMap impl core::marker::Send for aya_bpf::maps::CpuMap @@ -756,7 +756,7 @@ pub fn aya_bpf::maps::CpuMap::from(t: T) -> T impl aya_bpf::maps::DevMap pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap -pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap impl core::marker::Sync for aya_bpf::maps::DevMap impl core::marker::Send for aya_bpf::maps::DevMap @@ -783,7 +783,7 @@ pub fn aya_bpf::maps::DevMap::from(t: T) -> T impl aya_bpf::maps::DevMapHash pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash -pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::DevMapHash::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash impl core::marker::Sync for aya_bpf::maps::DevMapHash impl core::marker::Send for aya_bpf::maps::DevMapHash @@ -1206,7 +1206,7 @@ pub fn aya_bpf::maps::stack_trace::StackTrace::from(t: T) -> T impl aya_bpf::maps::XskMap pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap -pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> u32 +pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap impl core::marker::Sync for aya_bpf::maps::XskMap impl core::marker::Send for aya_bpf::maps::XskMap From 0edc13b4d4b87809b41b1a14101962a7defba65e Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Mon, 25 Sep 2023 00:33:17 +0200 Subject: [PATCH 49/95] bpf: add a shared try_redirect_map function for XDP maps --- bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 14 ++++---------- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 15 +++++---------- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 17 +++++------------ bpf/aya-bpf/src/maps/xdp/mod.rs | 24 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 15 +++++---------- xtask/public-api/aya-bpf.txt | 4 ++-- 6 files changed, 45 insertions(+), 44 deletions(-) diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs index 0179382c..133be94b 100644 --- a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -1,13 +1,14 @@ use core::{cell::UnsafeCell, mem}; -use aya_bpf_bindings::bindings::{bpf_cpumap_val, xdp_action::XDP_REDIRECT}; +use aya_bpf_bindings::bindings::bpf_cpumap_val; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, - helpers::bpf_redirect_map, maps::PinningType, }; +use super::try_redirect_map; + /// An array of available CPUs. /// /// XDP programs can use this map to redirect packets to a target CPU for processing. @@ -114,13 +115,6 @@ impl CpuMap { /// ``` #[inline(always)] pub fn redirect(&self, index: u32, flags: u64) -> Result { - let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; - match ret.unsigned_abs() as u32 { - XDP_REDIRECT => Ok(XDP_REDIRECT), - // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags - // argument on error. Thus I have no idea why it returns a long (i64) instead of - // something saner, hence the unsigned_abs. - ret => Err(ret), - } + try_redirect_map(&self.def, index, flags) } } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index 6142d151..cfa44cb3 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -1,14 +1,16 @@ use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; -use aya_bpf_bindings::bindings::{bpf_devmap_val, xdp_action::XDP_REDIRECT}; +use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_cty::c_void; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP}, - helpers::{bpf_map_lookup_elem, bpf_redirect_map}, + helpers::bpf_map_lookup_elem, maps::PinningType, }; +use super::try_redirect_map; + /// An array of network devices. /// /// XDP programs can use this map to redirect packets to other network deviecs. @@ -139,14 +141,7 @@ impl DevMap { /// ``` #[inline(always)] pub fn redirect(&self, index: u32, flags: u64) -> Result { - let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; - match ret.unsigned_abs() as u32 { - XDP_REDIRECT => Ok(XDP_REDIRECT), - // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags - // argument on error. Thus I have no idea why it returns a long (i64) instead of - // something saner, hence the unsigned_abs. - ret => Err(ret), - } + try_redirect_map(&self.def, index, flags) } } diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index eb65b105..cbec50bb 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -1,15 +1,15 @@ use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; -use aya_bpf_bindings::bindings::{bpf_devmap_val, xdp_action::XDP_REDIRECT}; +use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_cty::c_void; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH}, - helpers::{bpf_map_lookup_elem, bpf_redirect_map}, + helpers::bpf_map_lookup_elem, maps::PinningType, }; -use super::dev_map::DevMapValue; +use super::{dev_map::DevMapValue, try_redirect_map}; /// A map of network devices. /// @@ -140,14 +140,7 @@ impl DevMapHash { /// } /// ``` #[inline(always)] - pub fn redirect(&self, index: u32, flags: u64) -> Result { - let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; - match ret.unsigned_abs() as u32 { - XDP_REDIRECT => Ok(XDP_REDIRECT), - // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags - // argument on error. Thus I have no idea why it returns a long (i64) instead of - // something saner, hence the unsigned_abs. - ret => Err(ret), - } + pub fn redirect(&self, key: u32, flags: u64) -> Result { + try_redirect_map(&self.def, key, flags) } } diff --git a/bpf/aya-bpf/src/maps/xdp/mod.rs b/bpf/aya-bpf/src/maps/xdp/mod.rs index b7ced7b5..5c8df0e5 100644 --- a/bpf/aya-bpf/src/maps/xdp/mod.rs +++ b/bpf/aya-bpf/src/maps/xdp/mod.rs @@ -3,7 +3,31 @@ mod dev_map; mod dev_map_hash; mod xsk_map; +use core::cell::UnsafeCell; + +use aya_bpf_bindings::{ + bindings::{bpf_map_def, xdp_action::XDP_REDIRECT}, + helpers::bpf_redirect_map, +}; pub use cpu_map::CpuMap; pub use dev_map::DevMap; pub use dev_map_hash::DevMapHash; pub use xsk_map::XskMap; + +/// Wrapper aroung the `bpf_redirect_map` function. +/// +/// # Return value +/// +/// - `Ok(XDP_REDIRECT)` on success. +/// - `Err(_)` of the lowest two bits of `flags` on failure. +#[inline(always)] +fn try_redirect_map(def: &UnsafeCell, key: u32, flags: u64) -> Result { + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags argument on + // error. Thus I have no idea why it returns a long (i64) instead of something saner, hence the + // unsigned_abs. + let ret = unsafe { bpf_redirect_map(def.get() as *mut _, key.into(), flags) }; + match ret.unsigned_abs() as u32 { + XDP_REDIRECT => Ok(XDP_REDIRECT), + ret => Err(ret), + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs index f4546edb..455dfc84 100644 --- a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -1,14 +1,16 @@ use core::{cell::UnsafeCell, mem, ptr::NonNull}; -use aya_bpf_bindings::bindings::{bpf_xdp_sock, xdp_action::XDP_REDIRECT}; +use aya_bpf_bindings::bindings::bpf_xdp_sock; use aya_bpf_cty::c_void; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_XSKMAP}, - helpers::{bpf_map_lookup_elem, bpf_redirect_map}, + helpers::bpf_map_lookup_elem, maps::PinningType, }; +use super::try_redirect_map; + /// An array of AF_XDP sockets. /// /// XDP programs can use this map to redirect packets to a target AF_XDP socket using the @@ -157,13 +159,6 @@ impl XskMap { /// ``` #[inline(always)] pub fn redirect(&self, index: u32, flags: u64) -> Result { - let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) }; - match ret.unsigned_abs() as u32 { - XDP_REDIRECT => Ok(XDP_REDIRECT), - // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags - // argument on error. Thus I have no idea why it returns a long (i64) instead of - // something saner, hence the unsigned_abs. - ret => Err(ret), - } + try_redirect_map(&self.def, index, flags) } } diff --git a/xtask/public-api/aya-bpf.txt b/xtask/public-api/aya-bpf.txt index 4121839f..e221d2cc 100644 --- a/xtask/public-api/aya-bpf.txt +++ b/xtask/public-api/aya-bpf.txt @@ -621,7 +621,7 @@ pub fn aya_bpf::maps::DevMap::from(t: T) -> T impl aya_bpf::maps::DevMapHash pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash -pub fn aya_bpf::maps::DevMapHash::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash impl core::marker::Sync for aya_bpf::maps::DevMapHash impl core::marker::Send for aya_bpf::maps::DevMapHash @@ -783,7 +783,7 @@ pub fn aya_bpf::maps::DevMap::from(t: T) -> T impl aya_bpf::maps::DevMapHash pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash -pub fn aya_bpf::maps::DevMapHash::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> core::result::Result pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash impl core::marker::Sync for aya_bpf::maps::DevMapHash impl core::marker::Send for aya_bpf::maps::DevMapHash From 9680f50c08c3b8160e25631287e926ac7aa1b0f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:52:19 +0000 Subject: [PATCH 50/95] build(deps): update dialoguer requirement from 0.10 to 0.11 Updates the requirements on [dialoguer](https://github.com/console-rs/dialoguer) to permit the latest version. - [Changelog](https://github.com/console-rs/dialoguer/blob/master/CHANGELOG.md) - [Commits](https://github.com/console-rs/dialoguer/compare/v0.10.0...v0.10.4) --- updated-dependencies: - dependency-name: dialoguer dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cfbb91ef..b534f567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ bytes = { version = "1", default-features = false } cargo_metadata = { version = "0.18.0", default-features = false } clap = { version = "4", default-features = false } core-error = { version = "0.0.0", default-features = false } -dialoguer = { version = "0.10", default-features = false } +dialoguer = { version = "0.11", default-features = false } diff = { version = "0.1.13", default-features = false } env_logger = { version = "0.10", default-features = false } hashbrown = { version = "0.14", default-features = false } From 6190696346b3d079687c6caa3f5c1f9bbb23050c Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 26 Sep 2023 13:43:52 -0400 Subject: [PATCH 51/95] .github: remove 6.4.x kernel tests These images keep getting pulled, better to get off the treadmill. --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 491fa966..089bfc6a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -223,7 +223,6 @@ jobs: # linux-image-5.10.0-23-cloud-arm64-unsigned_5.10.179-3_arm64.deb \ printf '%s\0' \ linux-image-6.1.0-10-cloud-arm64-unsigned_6.1.38-2_arm64.deb \ - linux-image-6.4.0-3-cloud-arm64-unsigned_6.4.11-1_arm64.deb \ | xargs -0 -t -P0 -I {} wget -nd -nv -P test/.tmp/debian-kernels/arm64 ftp://ftp.us.debian.org/debian/pool/main/l/linux/{} - name: Download debian kernels @@ -236,7 +235,6 @@ jobs: # linux-image-5.10.0-23-cloud-amd64-unsigned_5.10.179-3_amd64.deb \ printf '%s\0' \ linux-image-6.1.0-10-cloud-amd64-unsigned_6.1.38-2_amd64.deb \ - linux-image-6.4.0-4-cloud-amd64-unsigned_6.4.13-1_amd64.deb \ | xargs -0 -t -P0 -I {} wget -nd -nv -P test/.tmp/debian-kernels/amd64 ftp://ftp.us.debian.org/debian/pool/main/l/linux/{} - name: Extract debian kernels From f01845a379c8e624e250317f8294732f3548bdd9 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 26 Sep 2023 13:44:18 -0400 Subject: [PATCH 52/95] .github: run tests nightly This should help us catch breakages more quickly. --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 089bfc6a..39ab82de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,9 @@ on: branches: - main + schedule: + - cron: 00 4 * * * + env: CARGO_TERM_COLOR: always From cbe9cd9133a0efdd5d7f5cc0c22e03c7736d43d9 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Sep 2023 11:31:03 -0400 Subject: [PATCH 53/95] xtask: appease new clippy warning ``` warning: unnecessary hashes around raw string literal --> xtask/src/docs.rs:70:17 | 70 | indoc! {r#" | _________________^ 71 | | User-Agent:* 72 | | Disallow: / 73 | | "#}, | |______^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes = note: `#[warn(clippy::needless_raw_string_hashes)]` on by default help: remove all the hashes around the literal | 70 ~ indoc! {r" 71 | User-Agent:* 72 | Disallow: / 73 ~ "}, | ``` This false negative was fixed in https://github.com/rust-lang/rust-clippy/pull/11518 (the title incorrectly says false positive). --- xtask/src/docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xtask/src/docs.rs b/xtask/src/docs.rs index 0fb13d35..2e8abc96 100644 --- a/xtask/src/docs.rs +++ b/xtask/src/docs.rs @@ -67,10 +67,10 @@ pub fn docs(metadata: Metadata) -> Result<()> { fs::write( site.join("robots.txt"), - indoc! {r#" + indoc! {r" User-Agent:* Disallow: / - "#}, + "}, ) .context("can't write robots.txt")?; From fe13b2eb4117d89a9f47004489e3c3f6e9526618 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Sep 2023 11:39:02 -0400 Subject: [PATCH 54/95] xtask: remove useless copy /tmp/initrd.img is unused. --- xtask/src/run.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 2deca1ad..a9ba17f4 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -345,8 +345,6 @@ pub fn run(opts: Options) -> Result<()> { bail!("{gen_init_cpio:?} failed: {output:?}") } - copy(&initrd_image, "/tmp/initrd.img").context("copy failed")?; - let mut qemu = Command::new(format!("qemu-system-{guest_arch}")); if let Some(machine) = machine { qemu.args(["-machine", machine]); From 0a6a2674fa6cbfda986b20d76f64802f0f65c2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Medina?= Date: Thu, 21 Sep 2023 21:02:20 -0700 Subject: [PATCH 55/95] aya: Fix program loading on kernels with a patch > 255 --- aya/src/programs/mod.rs | 10 ++------- aya/src/util.rs | 48 +++++++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index bb9622fe..0f2ebdd6 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -617,14 +617,8 @@ fn load_program( }, ) = obj; - let target_kernel_version = kernel_version.unwrap_or_else(|| { - let KernelVersion { - major, - minor, - patch, - } = KernelVersion::current().unwrap(); - (u32::from(major) << 16) + (u32::from(minor) << 8) + u32::from(patch) - }); + let target_kernel_version = + kernel_version.unwrap_or_else(|| KernelVersion::current().unwrap().code()); let prog_name = if let Some(name) = name { let mut name = name.clone(); diff --git a/aya/src/util.rs b/aya/src/util.rs index 54c289b0..b7a80006 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -49,23 +49,43 @@ impl KernelVersion { /// Returns the kernel version of the currently running kernel. pub fn current() -> Result { - let kernel_version = Self::get_kernel_version(); + Self::get_kernel_version() + } - // The kernel version is clamped to 4.19.255 on kernels 4.19.222 and above. - // - // See https://github.com/torvalds/linux/commit/a256aac. - const CLAMPED_KERNEL_MAJOR: u8 = 4; - const CLAMPED_KERNEL_MINOR: u8 = 19; - if let Ok(Self { - major: CLAMPED_KERNEL_MAJOR, - minor: CLAMPED_KERNEL_MINOR, - patch: 222.., - }) = kernel_version - { - return Ok(Self::new(CLAMPED_KERNEL_MAJOR, CLAMPED_KERNEL_MINOR, 255)); + /// The equivalent of LINUX_VERSION_CODE. + pub(crate) fn code(self) -> u32 { + let Self { + major, + minor, + mut patch, + } = self; + + // Certain LTS kernels went above the "max" 255 patch so + // backports were done to cap the patch version + let max_patch = match (major, minor) { + // On 4.4 + 4.9, any patch 257 or above was hardcoded to 255. + // See: https://github.com/torvalds/linux/commit/a15813a + + // https://github.com/torvalds/linux/commit/42efb098 + (4, 4 | 9) => 257, + // On 4.14, any patch 252 or above was hardcoded to 255. + // See: https://github.com/torvalds/linux/commit/e131e0e + (4, 14) => 252, + // On 4.19, any patch 222 or above was hardcoded to 255. + // See: https://github.com/torvalds/linux/commit/a256aac + (4, 19) => 222, + // For other kernels (i.e., newer LTS kernels as other + // ones won't reach 255+ patches) clamp it to 255. See: + // https://github.com/torvalds/linux/commit/9b82f13e + _ => 255, + }; + + // anything greater or equal to `max_patch` is hardcoded to + // 255. + if patch >= max_patch { + patch = 255; } - kernel_version + (u32::from(major) << 16) + (u32::from(minor) << 8) + u32::from(patch) } // This is ported from https://github.com/torvalds/linux/blob/3f01e9f/tools/lib/bpf/libbpf_probes.c#L21-L101. From 8cee3f8b015cd741841b6b16950f8b4dec5a5744 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Sep 2023 12:15:05 -0400 Subject: [PATCH 56/95] integration-test: distinguish between success and noop These tests previously produced the same result on certain failures as they did on success. --- test/integration-ebpf/src/bpf_probe_read.rs | 22 ++++++------------- .../src/tests/bpf_probe_read.rs | 12 +++++----- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/test/integration-ebpf/src/bpf_probe_read.rs b/test/integration-ebpf/src/bpf_probe_read.rs index 02728767..64d56311 100644 --- a/test/integration-ebpf/src/bpf_probe_read.rs +++ b/test/integration-ebpf/src/bpf_probe_read.rs @@ -15,11 +15,11 @@ macro_rules! read_str_bytes { let Some(ptr) = RESULT.get_ptr_mut(0) else { return; }; - let TestResult { - did_error, - len, - buf, - } = unsafe { &mut *ptr }; + let dst = unsafe { ptr.as_mut() }; + let Some(TestResult { buf, len }) = dst else { + return; + }; + *len = None; // $len comes from ctx.arg(1) so it's dynamic and the verifier // doesn't see any bounds. We do $len.min(RESULT_BUF_LEN) here to @@ -35,22 +35,14 @@ macro_rules! read_str_bytes { return; }; - match unsafe { $fun($ptr, buf) } { - Ok(s) => { - *len = s.len(); - } - Err(_) => { - *did_error = 1; - } - } + *len = Some(unsafe { $fun($ptr, buf) }.map(<[_]>::len)); }; } #[repr(C)] struct TestResult { - did_error: u64, - len: usize, buf: [u8; RESULT_BUF_LEN], + len: Option>, } #[map] diff --git a/test/integration-test/src/tests/bpf_probe_read.rs b/test/integration-test/src/tests/bpf_probe_read.rs index bf91f271..4c425507 100644 --- a/test/integration-test/src/tests/bpf_probe_read.rs +++ b/test/integration-test/src/tests/bpf_probe_read.rs @@ -5,9 +5,8 @@ const RESULT_BUF_LEN: usize = 1024; #[derive(Copy, Clone)] #[repr(C)] struct TestResult { - did_error: u64, - len: usize, buf: [u8; RESULT_BUF_LEN], + len: Option>, } unsafe impl aya::Pod for TestResult {} @@ -96,11 +95,12 @@ fn set_kernel_buffer_element(bpf: &mut Bpf, bytes: &[u8]) { #[track_caller] fn result_bytes(bpf: &Bpf) -> Vec { let m = Array::<_, TestResult>::try_from(bpf.map("RESULT").unwrap()).unwrap(); - let result = m.get(&0, 0).unwrap(); - assert_eq!(result.did_error, 0); + let TestResult { buf, len } = m.get(&0, 0).unwrap(); + let len = len.unwrap(); + let len = len.unwrap(); // assert that the buffer is always null terminated - assert_eq!(result.buf[result.len], 0); - result.buf[..result.len].to_vec() + assert_eq!(buf[len], 0); + buf[..len].to_vec() } fn load_and_attach_uprobe(prog_name: &str, func_name: &str, bytes: &[u8]) -> Bpf { From ad460879ef84b25c93f77b7bfb8bf04b6d33ec08 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Sep 2023 12:31:25 -0400 Subject: [PATCH 57/95] integration-test: replace macro with function There's just no need for a macro here. --- test/integration-ebpf/src/bpf_probe_read.rs | 85 ++++++++++----------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/test/integration-ebpf/src/bpf_probe_read.rs b/test/integration-ebpf/src/bpf_probe_read.rs index 64d56311..d86a6bba 100644 --- a/test/integration-ebpf/src/bpf_probe_read.rs +++ b/test/integration-ebpf/src/bpf_probe_read.rs @@ -10,33 +10,41 @@ use aya_bpf::{ const RESULT_BUF_LEN: usize = 1024; -macro_rules! read_str_bytes { - ($fun:ident, $ptr:expr, $len:expr $(,)?) => { - let Some(ptr) = RESULT.get_ptr_mut(0) else { - return; - }; - let dst = unsafe { ptr.as_mut() }; - let Some(TestResult { buf, len }) = dst else { - return; - }; - *len = None; - - // $len comes from ctx.arg(1) so it's dynamic and the verifier - // doesn't see any bounds. We do $len.min(RESULT_BUF_LEN) here to - // ensure that the verifier can see the upper bound, or you get: - // - // 18: (79) r7 = *(u64 *)(r7 +8) ; R7_w=scalar() - // [snip] - // 27: (bf) r2 = r7 ; - // R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip] - // 28: (85) call bpf_probe_read_user_str#114 - // R2 unbounded memory access, use 'var &= const' or 'if (var < const)' - let Some(buf) = buf.get_mut(..$len) else { - return; - }; +fn read_str_bytes( + fun: unsafe fn(*const u8, &mut [u8]) -> Result<&[u8], i64>, + iptr: Option<*const u8>, + ilen: Option, +) { + let Some(iptr) = iptr else { + return; + }; + let Some(ilen) = ilen else { + return; + }; + let Some(ptr) = RESULT.get_ptr_mut(0) else { + return; + }; + let dst = unsafe { ptr.as_mut() }; + let Some(TestResult { buf, len }) = dst else { + return; + }; + *len = None; - *len = Some(unsafe { $fun($ptr, buf) }.map(<[_]>::len)); + // len comes from ctx.arg(1) so it's dynamic and the verifier + // doesn't see any bounds. We do len.min(RESULT_BUF_LEN) here to + // ensure that the verifier can see the upper bound, or you get: + // + // 18: (79) r7 = *(u64 *)(r7 +8) ; R7_w=scalar() + // [snip] + // 27: (bf) r2 = r7 ; + // R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip] + // 28: (85) call bpf_probe_read_user_str#114 + // R2 unbounded memory access, use 'var &= const' or 'if (var < const)' + let Some(buf) = buf.get_mut(..ilen) else { + return; }; + + *len = Some(unsafe { fun(iptr, buf) }.map(<[_]>::len)); } #[repr(C)] @@ -53,31 +61,22 @@ static KERNEL_BUFFER: Array<[u8; RESULT_BUF_LEN]> = Array::with_max_entries(1, 0 #[uprobe] pub fn test_bpf_probe_read_user_str_bytes(ctx: ProbeContext) { - read_str_bytes!( + read_str_bytes( bpf_probe_read_user_str_bytes, - match ctx.arg::<*const u8>(0) { - Some(p) => p, - _ => return, - }, - match ctx.arg::(1) { - Some(p) => p, - _ => return, - }, + ctx.arg::<*const u8>(0), + ctx.arg::(1), ); } #[uprobe] pub fn test_bpf_probe_read_kernel_str_bytes(ctx: ProbeContext) { - read_str_bytes!( + read_str_bytes( bpf_probe_read_kernel_str_bytes, - match KERNEL_BUFFER.get_ptr(0) { - Some(p) => p as *const u8, - _ => return, - }, - match ctx.arg::(0) { - Some(p) => p, - _ => return, - }, + KERNEL_BUFFER + .get_ptr(0) + .and_then(|ptr| unsafe { ptr.as_ref() }) + .map(|buf| buf.as_ptr()), + ctx.arg::(0), ); } From 15de14383d7f194430a1a4fc8d373d7c10f25244 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Sep 2023 13:21:58 -0400 Subject: [PATCH 58/95] integration-test: build eBPF for the proper arch Prior to this change we neglected to build integration-ebpf for the correct target architecture, resulting in test failures on arm64. --- test/integration-test/build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration-test/build.rs b/test/integration-test/build.rs index fec40483..1aee5fea 100644 --- a/test/integration-test/build.rs +++ b/test/integration-test/build.rs @@ -107,7 +107,7 @@ fn main() { } else if arch == "aarch64" { target_arch.push("arm64"); } else { - target_arch.push(arch); + target_arch.push(&arch); }; // NB: libbpf's documentation suggests that vmlinux.h be generated by running `bpftool btf @@ -198,6 +198,8 @@ fn main() { &target, ]); + cmd.env("CARGO_CFG_BPF_TARGET_ARCH", arch); + // Workaround to make sure that the rust-toolchain.toml is respected. for key in ["RUSTUP_TOOLCHAIN", "RUSTC"] { cmd.env_remove(key); From d16e607fd4b6258b516913071fdacafeb2bbbff9 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Sep 2023 16:36:03 -0400 Subject: [PATCH 59/95] rustfmt: group_imports = "StdExternalCrate" High time we stop debating this; let the robots do the work. --- aya-bpf-macros/src/btf_tracepoint.rs | 3 +- aya-bpf-macros/src/cgroup_device.rs | 3 +- aya-bpf-macros/src/cgroup_skb.rs | 3 +- aya-bpf-macros/src/cgroup_sock.rs | 3 +- aya-bpf-macros/src/cgroup_sock_addr.rs | 3 +- aya-bpf-macros/src/cgroup_sockopt.rs | 3 +- aya-bpf-macros/src/cgroup_sysctl.rs | 3 +- aya-bpf-macros/src/fentry.rs | 3 +- aya-bpf-macros/src/fexit.rs | 3 +- aya-bpf-macros/src/kprobe.rs | 4 +-- aya-bpf-macros/src/lib.rs | 3 +- aya-bpf-macros/src/lsm.rs | 3 +- aya-bpf-macros/src/map.rs | 7 ++-- aya-bpf-macros/src/perf_event.rs | 3 +- aya-bpf-macros/src/raw_tracepoint.rs | 4 +-- aya-bpf-macros/src/sk_lookup.rs | 3 +- aya-bpf-macros/src/sk_msg.rs | 3 +- aya-bpf-macros/src/sk_skb.rs | 3 +- aya-bpf-macros/src/sock_ops.rs | 3 +- aya-bpf-macros/src/socket_filter.rs | 3 +- aya-bpf-macros/src/tc.rs | 3 +- aya-bpf-macros/src/tracepoint.rs | 3 +- aya-bpf-macros/src/uprobe.rs | 3 +- aya-bpf-macros/src/xdp.rs | 3 +- aya-log-ebpf-macros/src/expand.rs | 5 ++- aya-log/src/lib.rs | 16 ++++----- aya-obj/src/btf/btf.rs | 13 ++++--- aya-obj/src/btf/info.rs | 1 + aya-obj/src/btf/relocation.rs | 9 +++-- aya-obj/src/btf/types.rs | 5 +-- aya-obj/src/generated/mod.rs | 12 +++---- aya-obj/src/maps.rs | 5 ++- aya-obj/src/obj.rs | 34 +++++++++---------- aya-obj/src/relocation.rs | 10 +++--- aya-obj/src/util.rs | 9 +++-- aya-tool/src/bin/aya-tool.rs | 3 +- aya-tool/src/generate.rs | 1 - aya/src/maps/bloom_filter.rs | 8 +++-- aya/src/maps/hash_map/hash_map.rs | 9 +++-- aya/src/maps/hash_map/mod.rs | 3 +- aya/src/maps/hash_map/per_cpu_hash_map.rs | 3 +- aya/src/maps/lpm_trie.rs | 8 +++-- aya/src/maps/mod.rs | 9 +++-- aya/src/maps/perf/async_perf_event_array.rs | 3 +- aya/src/maps/perf/perf_buffer.rs | 6 ++-- aya/src/maps/sock/mod.rs | 6 ++-- aya/src/maps/xdp/cpu_map.rs | 3 +- aya/src/maps/xdp/dev_map.rs | 3 +- aya/src/maps/xdp/dev_map_hash.rs | 3 +- aya/src/maps/xdp/mod.rs | 2 +- aya/src/pin.rs | 3 +- aya/src/programs/cgroup_sock.rs | 4 +-- aya/src/programs/cgroup_sock_addr.rs | 4 +-- aya/src/programs/cgroup_sockopt.rs | 4 +-- aya/src/programs/kprobe.rs | 1 + aya/src/programs/links.rs | 10 +++--- aya/src/programs/mod.rs | 4 +-- aya/src/programs/perf_event.rs | 1 - aya/src/programs/probe.rs | 6 ++-- aya/src/programs/sk_lookup.rs | 3 +- aya/src/programs/socket_filter.rs | 3 +- aya/src/programs/tc.rs | 4 +-- aya/src/programs/trace_point.rs | 1 + aya/src/programs/uprobe.rs | 5 +-- aya/src/programs/xdp.rs | 15 ++++---- aya/src/sys/bpf.rs | 5 +-- aya/src/sys/mod.rs | 4 +-- aya/src/sys/netlink.rs | 2 +- aya/src/sys/perf_event.rs | 3 +- aya/src/util.rs | 7 ++-- bpf/aya-bpf-bindings/src/lib.rs | 11 +++--- bpf/aya-bpf/src/args.rs | 5 +-- bpf/aya-bpf/src/lib.rs | 7 ++-- bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 3 +- bpf/aya-bpf/src/maps/xdp/dev_map.rs | 3 +- bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 3 +- bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 3 +- bpf/aya-bpf/src/programs/perf_event.rs | 3 +- bpf/aya-bpf/src/programs/probe.rs | 5 +-- bpf/aya-bpf/src/programs/tracepoint.rs | 3 +- rustfmt.toml | 5 +-- .../src/tests/btf_relocations.rs | 3 +- xtask/src/codegen/aya.rs | 2 +- xtask/src/codegen/aya_bpf_bindings.rs | 6 ++-- xtask/src/docs.rs | 3 +- xtask/src/lib.rs | 3 +- xtask/src/main.rs | 3 +- 87 files changed, 215 insertions(+), 212 deletions(-) diff --git a/aya-bpf-macros/src/btf_tracepoint.rs b/aya-bpf-macros/src/btf_tracepoint.rs index d6148abd..1e9faa8f 100644 --- a/aya-bpf-macros/src/btf_tracepoint.rs +++ b/aya-bpf-macros/src/btf_tracepoint.rs @@ -45,9 +45,10 @@ impl BtfTracePoint { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_btf_tracepoint() { let prog = BtfTracePoint::parse( diff --git a/aya-bpf-macros/src/cgroup_device.rs b/aya-bpf-macros/src/cgroup_device.rs index 6acfa537..88311cbc 100644 --- a/aya-bpf-macros/src/cgroup_device.rs +++ b/aya-bpf-macros/src/cgroup_device.rs @@ -34,9 +34,10 @@ impl CgroupDevice { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_cgroup_device() { let prog = CgroupDevice::parse( diff --git a/aya-bpf-macros/src/cgroup_skb.rs b/aya-bpf-macros/src/cgroup_skb.rs index 606eb7b5..15b5a122 100644 --- a/aya-bpf-macros/src/cgroup_skb.rs +++ b/aya-bpf-macros/src/cgroup_skb.rs @@ -48,9 +48,10 @@ impl CgroupSkb { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn cgroup_skb() { let prog = CgroupSkb::parse( diff --git a/aya-bpf-macros/src/cgroup_sock.rs b/aya-bpf-macros/src/cgroup_sock.rs index 8facb9c1..015df836 100644 --- a/aya-bpf-macros/src/cgroup_sock.rs +++ b/aya-bpf-macros/src/cgroup_sock.rs @@ -46,9 +46,10 @@ impl CgroupSock { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn cgroup_sock_post_bind4() { let prog = CgroupSock::parse( diff --git a/aya-bpf-macros/src/cgroup_sock_addr.rs b/aya-bpf-macros/src/cgroup_sock_addr.rs index 43870c54..bc5d2477 100644 --- a/aya-bpf-macros/src/cgroup_sock_addr.rs +++ b/aya-bpf-macros/src/cgroup_sock_addr.rs @@ -48,9 +48,10 @@ impl CgroupSockAddr { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn cgroup_sock_addr_connect4() { let prog = CgroupSockAddr::parse( diff --git a/aya-bpf-macros/src/cgroup_sockopt.rs b/aya-bpf-macros/src/cgroup_sockopt.rs index b5bba0dd..f26c6417 100644 --- a/aya-bpf-macros/src/cgroup_sockopt.rs +++ b/aya-bpf-macros/src/cgroup_sockopt.rs @@ -46,9 +46,10 @@ impl CgroupSockopt { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn cgroup_sockopt_getsockopt() { let prog = CgroupSockopt::parse( diff --git a/aya-bpf-macros/src/cgroup_sysctl.rs b/aya-bpf-macros/src/cgroup_sysctl.rs index e3b11223..7542d1ea 100644 --- a/aya-bpf-macros/src/cgroup_sysctl.rs +++ b/aya-bpf-macros/src/cgroup_sysctl.rs @@ -34,9 +34,10 @@ impl CgroupSysctl { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_cgroup_sysctl() { let prog = CgroupSysctl::parse( diff --git a/aya-bpf-macros/src/fentry.rs b/aya-bpf-macros/src/fentry.rs index c8158dc8..d15094dc 100644 --- a/aya-bpf-macros/src/fentry.rs +++ b/aya-bpf-macros/src/fentry.rs @@ -51,9 +51,10 @@ impl FEntry { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_fentry() { let prog = FEntry::parse( diff --git a/aya-bpf-macros/src/fexit.rs b/aya-bpf-macros/src/fexit.rs index 7c7b17e1..4c345b0f 100644 --- a/aya-bpf-macros/src/fexit.rs +++ b/aya-bpf-macros/src/fexit.rs @@ -51,9 +51,10 @@ impl FExit { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_fexit() { let prog = FExit::parse( diff --git a/aya-bpf-macros/src/kprobe.rs b/aya-bpf-macros/src/kprobe.rs index 4fb9895f..a8c38d70 100644 --- a/aya-bpf-macros/src/kprobe.rs +++ b/aya-bpf-macros/src/kprobe.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use proc_macro2::TokenStream; - use quote::quote; use syn::{ItemFn, Result}; @@ -79,9 +78,10 @@ impl KProbe { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_kprobe() { let kprobe = KProbe::parse( diff --git a/aya-bpf-macros/src/lib.rs b/aya-bpf-macros/src/lib.rs index f29b725f..4393ab95 100644 --- a/aya-bpf-macros/src/lib.rs +++ b/aya-bpf-macros/src/lib.rs @@ -44,10 +44,9 @@ use sk_msg::SkMsg; use sk_skb::{SkSkb, SkSkbKind}; use sock_ops::SockOps; use socket_filter::SocketFilter; -use uprobe::{UProbe, UProbeKind}; - use tc::SchedClassifier; use tracepoint::TracePoint; +use uprobe::{UProbe, UProbeKind}; use xdp::Xdp; #[proc_macro_error] #[proc_macro_attribute] diff --git a/aya-bpf-macros/src/lsm.rs b/aya-bpf-macros/src/lsm.rs index 88a66b9b..430795eb 100644 --- a/aya-bpf-macros/src/lsm.rs +++ b/aya-bpf-macros/src/lsm.rs @@ -53,9 +53,10 @@ impl Lsm { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_lsm_sleepable() { let prog = Lsm::parse( diff --git a/aya-bpf-macros/src/map.rs b/aya-bpf-macros/src/map.rs index 21f9a8fa..e50f45b9 100644 --- a/aya-bpf-macros/src/map.rs +++ b/aya-bpf-macros/src/map.rs @@ -2,11 +2,9 @@ use std::borrow::Cow; use proc_macro2::TokenStream; use quote::quote; -use syn::Result; +use syn::{ItemStatic, Result}; use crate::args::name_arg; - -use syn::ItemStatic; pub(crate) struct Map { item: ItemStatic, name: String, @@ -34,9 +32,10 @@ impl Map { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_map_with_name() { let map = Map::parse( diff --git a/aya-bpf-macros/src/perf_event.rs b/aya-bpf-macros/src/perf_event.rs index 3756959d..8022d8b2 100644 --- a/aya-bpf-macros/src/perf_event.rs +++ b/aya-bpf-macros/src/perf_event.rs @@ -35,9 +35,10 @@ impl PerfEvent { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_perf_event() { let prog = PerfEvent::parse( diff --git a/aya-bpf-macros/src/raw_tracepoint.rs b/aya-bpf-macros/src/raw_tracepoint.rs index 9bb7b658..87f97988 100644 --- a/aya-bpf-macros/src/raw_tracepoint.rs +++ b/aya-bpf-macros/src/raw_tracepoint.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use proc_macro2::TokenStream; - use quote::quote; use syn::{ItemFn, Result}; @@ -45,9 +44,10 @@ impl RawTracePoint { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_raw_tracepoint() { let prog = RawTracePoint::parse( diff --git a/aya-bpf-macros/src/sk_lookup.rs b/aya-bpf-macros/src/sk_lookup.rs index ddeae3e8..e1d6fc92 100644 --- a/aya-bpf-macros/src/sk_lookup.rs +++ b/aya-bpf-macros/src/sk_lookup.rs @@ -34,9 +34,10 @@ impl SkLookup { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_sk_lookup() { let prog = SkLookup::parse( diff --git a/aya-bpf-macros/src/sk_msg.rs b/aya-bpf-macros/src/sk_msg.rs index bfb6be8a..b0e2cc4c 100644 --- a/aya-bpf-macros/src/sk_msg.rs +++ b/aya-bpf-macros/src/sk_msg.rs @@ -34,9 +34,10 @@ impl SkMsg { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_sk_msg() { let prog = SkMsg::parse( diff --git a/aya-bpf-macros/src/sk_skb.rs b/aya-bpf-macros/src/sk_skb.rs index 72f57ff7..5056ced6 100644 --- a/aya-bpf-macros/src/sk_skb.rs +++ b/aya-bpf-macros/src/sk_skb.rs @@ -56,9 +56,10 @@ impl SkSkb { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_stream_parser() { let prog = SkSkb::parse( diff --git a/aya-bpf-macros/src/sock_ops.rs b/aya-bpf-macros/src/sock_ops.rs index b47ead9c..62e2b739 100644 --- a/aya-bpf-macros/src/sock_ops.rs +++ b/aya-bpf-macros/src/sock_ops.rs @@ -34,9 +34,10 @@ impl SockOps { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_sock_ops() { let prog = SockOps::parse( diff --git a/aya-bpf-macros/src/socket_filter.rs b/aya-bpf-macros/src/socket_filter.rs index 6511d635..2ebc3edf 100644 --- a/aya-bpf-macros/src/socket_filter.rs +++ b/aya-bpf-macros/src/socket_filter.rs @@ -34,9 +34,10 @@ impl SocketFilter { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_socket_filter() { let prog = SocketFilter::parse( diff --git a/aya-bpf-macros/src/tc.rs b/aya-bpf-macros/src/tc.rs index 9db12ccd..56d3940a 100644 --- a/aya-bpf-macros/src/tc.rs +++ b/aya-bpf-macros/src/tc.rs @@ -34,9 +34,10 @@ impl SchedClassifier { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_sched_classifier() { let prog = SchedClassifier::parse( diff --git a/aya-bpf-macros/src/tracepoint.rs b/aya-bpf-macros/src/tracepoint.rs index 0e2a7cf6..e7675b33 100644 --- a/aya-bpf-macros/src/tracepoint.rs +++ b/aya-bpf-macros/src/tracepoint.rs @@ -52,9 +52,10 @@ impl TracePoint { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_tracepoint() { let prog = TracePoint::parse( diff --git a/aya-bpf-macros/src/uprobe.rs b/aya-bpf-macros/src/uprobe.rs index 7144f30f..1684cd6d 100644 --- a/aya-bpf-macros/src/uprobe.rs +++ b/aya-bpf-macros/src/uprobe.rs @@ -104,9 +104,10 @@ impl UProbe { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn uprobe() { let uprobe = UProbe::parse( diff --git a/aya-bpf-macros/src/xdp.rs b/aya-bpf-macros/src/xdp.rs index 61f8c014..9e0f1a5a 100644 --- a/aya-bpf-macros/src/xdp.rs +++ b/aya-bpf-macros/src/xdp.rs @@ -64,9 +64,10 @@ impl Xdp { #[cfg(test)] mod tests { - use super::*; use syn::parse_quote; + use super::*; + #[test] fn test_xdp() { let prog = Xdp::parse( diff --git a/aya-log-ebpf-macros/src/expand.rs b/aya-log-ebpf-macros/src/expand.rs index ffbe3dbe..efc1a943 100644 --- a/aya-log-ebpf-macros/src/expand.rs +++ b/aya-log-ebpf-macros/src/expand.rs @@ -1,3 +1,5 @@ +use aya_log_common::DisplayHint; +use aya_log_parser::{parse, Fragment}; use proc_macro2::TokenStream; use quote::quote; use syn::{ @@ -6,9 +8,6 @@ use syn::{ Error, Expr, LitStr, Result, Token, }; -use aya_log_common::DisplayHint; -use aya_log_parser::{parse, Fragment}; - pub(crate) struct LogArgs { pub(crate) ctx: Expr, pub(crate) target: Option, diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index 88068cbe..afd80653 100644 --- a/aya-log/src/lib.rs +++ b/aya-log/src/lib.rs @@ -59,13 +59,6 @@ use std::{ const MAP_NAME: &str = "AYA_LOGS"; -use aya_log_common::{ - Argument, DisplayHint, Level, LogValueLength, RecordField, LOG_BUF_CAPACITY, LOG_FIELDS, -}; -use bytes::BytesMut; -use log::{error, Log, Record}; -use thiserror::Error; - use aya::{ maps::{ perf::{AsyncPerfEventArray, Events, PerfBufferError}, @@ -74,6 +67,12 @@ use aya::{ util::online_cpus, Bpf, Pod, }; +use aya_log_common::{ + Argument, DisplayHint, Level, LogValueLength, RecordField, LOG_BUF_CAPACITY, LOG_FIELDS, +}; +use bytes::BytesMut; +use log::{error, Log, Record}; +use thiserror::Error; #[derive(Copy, Clone)] #[repr(transparent)] @@ -563,10 +562,11 @@ fn try_read(mut buf: &[u8]) -> Result<(T, &[u8], &[u8]), ()> { #[cfg(test)] mod test { - use super::*; use aya_log_common::{write_record_header, WriteToBuf}; use log::{logger, Level}; + use super::*; + fn new_log(args: usize) -> Option<(usize, Vec)> { let mut buf = vec![0; 8192]; let len = write_record_header( diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index 02976569..de9e54e4 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -1,5 +1,3 @@ -use core::{ffi::CStr, mem, ptr}; - use alloc::{ borrow::{Cow, ToOwned as _}, format, @@ -7,11 +5,14 @@ use alloc::{ vec, vec::Vec, }; -use bytes::BufMut; +use core::{ffi::CStr, mem, ptr}; +use bytes::BufMut; use log::debug; use object::{Endianness, SectionIndex}; +#[cfg(not(feature = "std"))] +use crate::std; use crate::{ btf::{ info::{FuncSecInfo, LineSecInfo}, @@ -24,9 +25,6 @@ use crate::{ Object, }; -#[cfg(not(feature = "std"))] -use crate::std; - pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32; pub(crate) const MAX_SPEC_LEN: usize = 64; @@ -1102,12 +1100,13 @@ pub(crate) struct SecInfo<'a> { #[cfg(test)] mod tests { + use assert_matches::assert_matches; + use super::*; use crate::btf::{ BtfEnum64, BtfParam, DataSec, DataSecEntry, DeclTag, Enum64, Float, Func, FuncProto, Ptr, TypeTag, Var, }; - use assert_matches::assert_matches; #[test] fn test_parse_header() { diff --git a/aya-obj/src/btf/info.rs b/aya-obj/src/btf/info.rs index 27982807..aa5a025f 100644 --- a/aya-obj/src/btf/info.rs +++ b/aya-obj/src/btf/info.rs @@ -1,4 +1,5 @@ use alloc::{string::String, vec, vec::Vec}; + use bytes::BufMut; use object::Endianness; diff --git a/aya-obj/src/btf/relocation.rs b/aya-obj/src/btf/relocation.rs index 898c4e44..c23bee75 100644 --- a/aya-obj/src/btf/relocation.rs +++ b/aya-obj/src/btf/relocation.rs @@ -1,5 +1,3 @@ -use core::{mem, ops::Bound::Included, ptr}; - use alloc::{ borrow::{Cow, ToOwned as _}, collections::BTreeMap, @@ -8,8 +6,12 @@ use alloc::{ vec, vec::Vec, }; +use core::{mem, ops::Bound::Included, ptr}; + use object::SectionIndex; +#[cfg(not(feature = "std"))] +use crate::std; use crate::{ btf::{ fields_are_compatible, types_are_compatible, Array, Btf, BtfError, BtfMember, BtfType, @@ -23,9 +25,6 @@ use crate::{ Function, Object, }; -#[cfg(not(feature = "std"))] -use crate::std; - /// The error type returned by [`Object::relocate_btf`]. #[derive(thiserror::Error, Debug)] #[error("error relocating `{section}`")] diff --git a/aya-obj/src/btf/types.rs b/aya-obj/src/btf/types.rs index 895484df..89b1713b 100644 --- a/aya-obj/src/btf/types.rs +++ b/aya-obj/src/btf/types.rs @@ -1,8 +1,8 @@ #![allow(missing_docs)] +use alloc::{string::ToString, vec, vec::Vec}; use core::{fmt::Display, mem, ptr}; -use alloc::{string::ToString, vec, vec::Vec}; use object::Endianness; use crate::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH}; @@ -1570,9 +1570,10 @@ fn bytes_of(val: &T) -> &[u8] { } #[cfg(test)] mod tests { - use super::*; use assert_matches::assert_matches; + use super::*; + #[test] fn test_read_btf_type_int() { let endianness = Endianness::default(); diff --git a/aya-obj/src/generated/mod.rs b/aya-obj/src/generated/mod.rs index 943c2703..f9097937 100644 --- a/aya-obj/src/generated/mod.rs +++ b/aya-obj/src/generated/mod.rs @@ -21,15 +21,11 @@ mod linux_bindings_x86_64; // don't re-export __u8 __u16 etc which are already exported by the // linux_bindings_* module pub use btf_internal_bindings::{bpf_core_relo, bpf_core_relo_kind, btf_ext_header}; - -#[cfg(target_arch = "x86_64")] -pub use linux_bindings_x86_64::*; - -#[cfg(target_arch = "arm")] -pub use linux_bindings_armv7::*; - #[cfg(target_arch = "aarch64")] pub use linux_bindings_aarch64::*; - +#[cfg(target_arch = "arm")] +pub use linux_bindings_armv7::*; #[cfg(target_arch = "riscv64")] pub use linux_bindings_riscv64::*; +#[cfg(target_arch = "x86_64")] +pub use linux_bindings_x86_64::*; diff --git a/aya-obj/src/maps.rs b/aya-obj/src/maps.rs index aede3cfe..c4cf5c32 100644 --- a/aya-obj/src/maps.rs +++ b/aya-obj/src/maps.rs @@ -1,12 +1,11 @@ //! Map struct and type bindings. -use core::mem; - -use crate::BpfSectionKind; use alloc::vec::Vec; +use core::mem; #[cfg(not(feature = "std"))] use crate::std; +use crate::BpfSectionKind; /// Invalid map type encontered pub struct InvalidMapTypeError { diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 38221f96..1776b3ca 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -7,7 +7,8 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::{ffi::CStr, mem, ptr, str::FromStr}; +use core::{ffi::CStr, mem, ptr, slice::from_raw_parts_mut, str::FromStr}; + use log::debug; use object::{ read::{Object as ElfObject, ObjectSection, Section as ObjSection}, @@ -15,27 +16,23 @@ use object::{ SymbolKind, }; -use crate::{ - btf::BtfFeatures, - generated::{BPF_CALL, BPF_JMP, BPF_K}, - maps::{BtfMap, LegacyMap, Map, MINIMUM_MAP_SIZE}, - programs::XdpAttachType, - relocation::*, - util::HashMap, -}; - #[cfg(not(feature = "std"))] use crate::std; - use crate::{ - btf::{Btf, BtfError, BtfExt, BtfType}, - generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG}, - maps::{bpf_map_def, BtfMapDef, PinningType}, - programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType}, + btf::{ + Array, Btf, BtfError, BtfExt, BtfFeatures, BtfType, DataSecEntry, FuncSecInfo, LineSecInfo, + }, + generated::{ + bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_CALL, BPF_F_RDONLY_PROG, + BPF_JMP, BPF_K, + }, + maps::{bpf_map_def, BtfMap, BtfMapDef, LegacyMap, Map, PinningType, MINIMUM_MAP_SIZE}, + programs::{ + CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType, XdpAttachType, + }, + relocation::*, + util::HashMap, }; -use core::slice::from_raw_parts_mut; - -use crate::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo}; const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE; @@ -1395,6 +1392,7 @@ fn get_func_and_line_info( #[cfg(test)] mod tests { use alloc::vec; + use assert_matches::assert_matches; use object::Endianness; diff --git a/aya-obj/src/relocation.rs b/aya-obj/src/relocation.rs index 83879fc8..54039465 100644 --- a/aya-obj/src/relocation.rs +++ b/aya-obj/src/relocation.rs @@ -1,11 +1,13 @@ //! Program relocation handling. +use alloc::{borrow::ToOwned, collections::BTreeMap, string::String}; use core::mem; -use alloc::{borrow::ToOwned, collections::BTreeMap, string::String}; use log::debug; use object::{SectionIndex, SymbolKind}; +#[cfg(not(feature = "std"))] +use crate::std; use crate::{ generated::{ bpf_insn, BPF_CALL, BPF_JMP, BPF_K, BPF_PSEUDO_CALL, BPF_PSEUDO_FUNC, BPF_PSEUDO_MAP_FD, @@ -17,9 +19,6 @@ use crate::{ BpfSectionKind, }; -#[cfg(not(feature = "std"))] -use crate::std; - pub(crate) const INS_SIZE: usize = mem::size_of::(); /// The error type returned by [`Object::relocate_maps`] and [`Object::relocate_calls`] @@ -498,13 +497,12 @@ fn insn_is_call(ins: &bpf_insn) -> bool { mod test { use alloc::{string::ToString, vec, vec::Vec}; + use super::*; use crate::{ maps::{BtfMap, LegacyMap, Map}, BpfSectionKind, }; - use super::*; - fn fake_sym(index: usize, section_index: usize, address: u64, name: &str, size: u64) -> Symbol { Symbol { index, diff --git a/aya-obj/src/util.rs b/aya-obj/src/util.rs index 53209444..80d0179d 100644 --- a/aya-obj/src/util.rs +++ b/aya-obj/src/util.rs @@ -1,14 +1,13 @@ use core::{mem, slice}; - -#[cfg(not(feature = "std"))] -pub(crate) use hashbrown::HashMap; #[cfg(feature = "std")] pub(crate) use std::collections::HashMap; +#[cfg(feature = "std")] +pub(crate) use std::collections::HashSet; +#[cfg(not(feature = "std"))] +pub(crate) use hashbrown::HashMap; #[cfg(not(feature = "std"))] pub(crate) use hashbrown::HashSet; -#[cfg(feature = "std")] -pub(crate) use std::collections::HashSet; /// bytes_of converts a to a byte slice pub(crate) unsafe fn bytes_of(val: &T) -> &[u8] { diff --git a/aya-tool/src/bin/aya-tool.rs b/aya-tool/src/bin/aya-tool.rs index 4e12a020..759131d3 100644 --- a/aya-tool/src/bin/aya-tool.rs +++ b/aya-tool/src/bin/aya-tool.rs @@ -1,7 +1,6 @@ -use aya_tool::generate::{generate, InputFile}; - use std::{path::PathBuf, process::exit}; +use aya_tool::generate::{generate, InputFile}; use clap::Parser; #[derive(Parser)] diff --git a/aya-tool/src/generate.rs b/aya-tool/src/generate.rs index c8b97f6a..69658a04 100644 --- a/aya-tool/src/generate.rs +++ b/aya-tool/src/generate.rs @@ -7,7 +7,6 @@ use std::{ }; use tempfile::tempdir; - use thiserror::Error; use crate::bindgen; diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index dfe4d2cb..d038e35f 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -79,6 +79,11 @@ impl, V: Pod> BloomFilter { #[cfg(test)] mod tests { + use std::{ffi::c_long, io}; + + use assert_matches::assert_matches; + use libc::{EFAULT, ENOENT}; + use super::*; use crate::{ bpf_map_def, @@ -90,9 +95,6 @@ mod tests { obj::{self, maps::LegacyMap, BpfSectionKind}, sys::{override_syscall, SysResult, Syscall}, }; - use assert_matches::assert_matches; - use libc::{EFAULT, ENOENT}; - use std::{ffi::c_long, io}; fn new_obj_map() -> obj::Map { obj::Map::Legacy(LegacyMap { diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 9d587b33..bfc96845 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -108,6 +108,10 @@ mod tests { use assert_matches::assert_matches; use libc::{EFAULT, ENOENT}; + use super::{ + super::test_utils::{self, new_map}, + *, + }; use crate::{ generated::{ bpf_attr, bpf_cmd, @@ -118,11 +122,6 @@ mod tests { sys::{override_syscall, SysResult, Syscall}, }; - use super::{ - super::test_utils::{self, new_map}, - *, - }; - fn new_obj_map() -> obj::Map { test_utils::new_obj_map(BPF_MAP_TYPE_HASH) } diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index 40c171ce..31e0bc8b 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -1,10 +1,11 @@ //! Hash map types. +use std::os::fd::AsFd as _; + use crate::{ maps::MapError, sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError}, Pod, }; -use std::os::fd::AsFd as _; #[allow(clippy::module_inception)] mod hash_map; diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index 56fc2ae2..b1985390 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -150,13 +150,12 @@ impl, K: Pod, V: Pod> IterableMap> #[cfg(test)] mod tests { + use super::{super::test_utils, *}; use crate::{ generated::bpf_map_type::{BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH}, maps::Map, }; - use super::{super::test_utils, *}; - #[test] fn test_try_from_ok() { let map = Map::PerCpuHashMap(test_utils::new_map(test_utils::new_obj_map( diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index d4e1e678..181a2f57 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -196,6 +196,11 @@ impl, K: Pod, V: Pod> IterableMap, V> for LpmTrie obj::Map { obj::Map::Legacy(LegacyMap { diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 1a590791..84971419 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -58,7 +58,6 @@ use std::{ ptr, }; -use crate::util::KernelVersion; use libc::{getrlimit, rlim_t, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; use log::warn; use thiserror::Error; @@ -70,7 +69,7 @@ use crate::{ bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_info_by_fd, bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, SyscallError, }, - util::nr_cpus, + util::{nr_cpus, KernelVersion}, PinningType, Pod, }; @@ -807,10 +806,12 @@ impl Deref for PerCpuValues { #[cfg(test)] mod tests { + use std::os::fd::AsRawFd as _; + use assert_matches::assert_matches; use libc::EFAULT; - use std::os::fd::AsRawFd as _; + use super::*; use crate::{ bpf_map_def, generated::{bpf_cmd, bpf_map_type::BPF_MAP_TYPE_HASH}, @@ -819,8 +820,6 @@ mod tests { sys::{override_syscall, Syscall}, }; - use super::*; - fn new_obj_map() -> obj::Map { obj::Map::Legacy(LegacyMap { def: bpf_map_def { diff --git a/aya/src/maps/perf/async_perf_event_array.rs b/aya/src/maps/perf/async_perf_event_array.rs index 83e9484a..4b7d097e 100644 --- a/aya/src/maps/perf/async_perf_event_array.rs +++ b/aya/src/maps/perf/async_perf_event_array.rs @@ -1,4 +1,3 @@ -use bytes::BytesMut; use std::borrow::{Borrow, BorrowMut}; // See https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features. @@ -7,7 +6,7 @@ use std::borrow::{Borrow, BorrowMut}; // "async-async-std". Presently we arbitrarily choose tokio over async-std when both are requested. #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))] use async_io::Async; - +use bytes::BytesMut; #[cfg(feature = "async_tokio")] use tokio::io::unix::AsyncFd; diff --git a/aya/src/maps/perf/perf_buffer.rs b/aya/src/maps/perf/perf_buffer.rs index 898dd04b..17742320 100644 --- a/aya/src/maps/perf/perf_buffer.rs +++ b/aya/src/maps/perf/perf_buffer.rs @@ -318,13 +318,15 @@ struct LostSamples { #[cfg(test)] mod tests { + use std::{fmt::Debug, mem}; + + use assert_matches::assert_matches; + use super::*; use crate::{ generated::perf_event_mmap_page, sys::{override_syscall, Syscall, TEST_MMAP_RET}, }; - use assert_matches::assert_matches; - use std::{fmt::Debug, mem}; const PAGE_SIZE: usize = 4096; union MMappedBuf { diff --git a/aya/src/maps/sock/mod.rs b/aya/src/maps/sock/mod.rs index 0c3262a2..067e9d03 100644 --- a/aya/src/maps/sock/mod.rs +++ b/aya/src/maps/sock/mod.rs @@ -2,14 +2,14 @@ mod sock_hash; mod sock_map; -pub use sock_hash::SockHash; -pub use sock_map::SockMap; - use std::{ io, os::fd::{AsFd, BorrowedFd}, }; +pub use sock_hash::SockHash; +pub use sock_map::SockMap; + /// A socket map file descriptor. #[repr(transparent)] pub struct SockMapFd(super::MapFd); diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index d9cc7d19..f48fcdc2 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -8,6 +8,7 @@ use std::{ use aya_obj::generated::bpf_cpumap_val; +use super::XdpMapError; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, programs::ProgramFd, @@ -15,8 +16,6 @@ use crate::{ Pod, FEATURES, }; -use super::XdpMapError; - /// An array of available CPUs. /// /// XDP programs can use this map to redirect packets to a target diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index 3c4240f5..6b6cd545 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -8,6 +8,7 @@ use std::{ use aya_obj::generated::bpf_devmap_val; +use super::XdpMapError; use crate::{ maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, programs::ProgramFd, @@ -15,8 +16,6 @@ use crate::{ Pod, FEATURES, }; -use super::XdpMapError; - /// An array of network devices. /// /// XDP programs can use this map to redirect to other network diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 469c8420..65b00ee4 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -8,6 +8,7 @@ use std::{ use aya_obj::generated::bpf_devmap_val; +use super::{dev_map::DevMapValue, XdpMapError}; use crate::{ maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, programs::ProgramFd, @@ -15,8 +16,6 @@ use crate::{ FEATURES, }; -use super::{dev_map::DevMapValue, XdpMapError}; - /// An hashmap of network devices. /// /// XDP programs can use this map to redirect to other network diff --git a/aya/src/maps/xdp/mod.rs b/aya/src/maps/xdp/mod.rs index 0faa41bb..2f00492c 100644 --- a/aya/src/maps/xdp/mod.rs +++ b/aya/src/maps/xdp/mod.rs @@ -7,10 +7,10 @@ mod xsk_map; pub use cpu_map::CpuMap; pub use dev_map::DevMap; pub use dev_map_hash::DevMapHash; +use thiserror::Error; pub use xsk_map::XskMap; use super::MapError; -use thiserror::Error; #[derive(Error, Debug)] /// Errors occuring from working with XDP maps. diff --git a/aya/src/pin.rs b/aya/src/pin.rs index 43e197ff..28ff03c4 100644 --- a/aya/src/pin.rs +++ b/aya/src/pin.rs @@ -1,8 +1,9 @@ //! Pinning BPF objects to the BPF filesystem. -use crate::sys::SyscallError; use thiserror::Error; +use crate::sys::SyscallError; + /// An error ocurred working with a pinned BPF object. #[derive(Error, Debug)] pub enum PinError { diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index 1ea6284c..971ef9e9 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -1,9 +1,9 @@ //! Cgroup socket programs. -pub use aya_obj::programs::CgroupSockAttachType; - use std::{hash::Hash, os::fd::AsFd, path::Path}; +pub use aya_obj::programs::CgroupSockAttachType; + use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK, programs::{ diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index cab1b7c5..f9a2fb7f 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -1,9 +1,9 @@ //! Cgroup socket address programs. -pub use aya_obj::programs::CgroupSockAddrAttachType; - use std::{hash::Hash, os::fd::AsFd, path::Path}; +pub use aya_obj::programs::CgroupSockAddrAttachType; + use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR, programs::{ diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index 72ec868f..33ac84fe 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -1,9 +1,9 @@ //! Cgroup socket option programs. -pub use aya_obj::programs::CgroupSockoptAttachType; - use std::{hash::Hash, os::fd::AsFd, path::Path}; +pub use aya_obj::programs::CgroupSockoptAttachType; + use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT, programs::{ diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index c915136e..8902c9eb 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -5,6 +5,7 @@ use std::{ os::fd::AsFd as _, path::{Path, PathBuf}, }; + use thiserror::Error; use crate::{ diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index e8eeb417..d947d64f 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -1,6 +1,4 @@ //! Program links. -use thiserror::Error; - use std::{ collections::{hash_map::Entry, HashMap}, ffi::CString, @@ -9,6 +7,8 @@ use std::{ path::{Path, PathBuf}, }; +use thiserror::Error; + use crate::{ generated::bpf_attach_type, pin::PinError, @@ -357,13 +357,13 @@ pub enum LinkError { #[cfg(test)] mod tests { - use assert_matches::assert_matches; use std::{cell::RefCell, fs::File, rc::Rc}; - use tempfile::tempdir; - use crate::{programs::ProgramError, sys::override_syscall}; + use assert_matches::assert_matches; + use tempfile::tempdir; use super::{FdLink, Link, LinkMap}; + use crate::{programs::ProgramError, sys::override_syscall}; #[derive(Debug, Hash, Eq, PartialEq)] struct TestLinkId(u8, u8); diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 0f2ebdd6..64da0fdf 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -64,7 +64,6 @@ pub mod uprobe; mod utils; pub mod xdp; -use libc::ENOSPC; use std::{ ffi::CString, io, @@ -74,7 +73,6 @@ use std::{ sync::Arc, time::{Duration, SystemTime}, }; -use thiserror::Error; pub use cgroup_device::CgroupDevice; pub use cgroup_skb::{CgroupSkb, CgroupSkbAttachType}; @@ -86,6 +84,7 @@ pub use extension::{Extension, ExtensionError}; pub use fentry::FEntry; pub use fexit::FExit; pub use kprobe::{KProbe, KProbeError}; +use libc::ENOSPC; pub use links::Link; use links::*; pub use lirc_mode2::LircMode2; @@ -100,6 +99,7 @@ pub use sk_skb::{SkSkb, SkSkbKind}; pub use sock_ops::SockOps; pub use socket_filter::{SocketFilter, SocketFilterError}; pub use tc::{SchedClassifier, TcAttachType, TcError}; +use thiserror::Error; pub use tp_btf::BtfTracePoint; pub use trace_point::{TracePoint, TracePointError}; pub use uprobe::{UProbe, UProbeError}; diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 150bda24..b7b233cf 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -5,7 +5,6 @@ use std::os::fd::AsFd as _; pub use crate::generated::{ perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids, }; - use crate::{ generated::{ bpf_link_type, diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index 6d9082ca..f36c8cf9 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -1,5 +1,3 @@ -use crate::util::KernelVersion; -use libc::pid_t; use std::{ ffi::{OsStr, OsString}, fmt::Write as _, @@ -11,6 +9,8 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; +use libc::pid_t; + use crate::{ programs::{ kprobe::KProbeError, perf_attach, perf_attach::PerfLinkInner, perf_attach_debugfs, @@ -18,6 +18,7 @@ use crate::{ Link, ProgramData, ProgramError, }, sys::{perf_event_open_probe, perf_event_open_trace_point, SyscallError}, + util::KernelVersion, }; static PROBE_NAME_INDEX: AtomicUsize = AtomicUsize::new(0); @@ -213,6 +214,7 @@ fn create_probe_event( offset: u64, ) -> Result { use std::os::unix::ffi::OsStrExt as _; + use ProbeKind::*; let events_file_name = tracefs.join(format!("{}_events", kind.pmu())); diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index eb386187..42feb33d 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -1,13 +1,12 @@ use std::os::fd::AsFd; +use super::links::FdLink; use crate::{ generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP}, programs::{define_link_wrapper, load_program, FdLinkId, ProgramData, ProgramError}, sys::{bpf_link_create, LinkTarget, SyscallError}, }; -use super::links::FdLink; - /// A program used to redirect incoming packets to a local socket. /// /// [`SkLookup`] programs are attached to network namespaces to provide programmable diff --git a/aya/src/programs/socket_filter.rs b/aya/src/programs/socket_filter.rs index 014b6475..abf6e7ed 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -1,9 +1,10 @@ //! Socket filter programs. -use libc::{setsockopt, SOL_SOCKET}; use std::{ io, mem, os::fd::{AsFd, AsRawFd, RawFd}, }; + +use libc::{setsockopt, SOL_SOCKET}; use thiserror::Error; use crate::{ diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index bdf15ed2..92cc1699 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -1,6 +1,4 @@ //! Network traffic control programs. -use thiserror::Error; - use std::{ ffi::{CStr, CString}, io, @@ -8,6 +6,8 @@ use std::{ path::Path, }; +use thiserror::Error; + use crate::{ generated::{ bpf_prog_type::BPF_PROG_TYPE_SCHED_CLS, TC_H_CLSACT, TC_H_MIN_EGRESS, TC_H_MIN_INGRESS, diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index adb50621..2096f1cb 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -1,5 +1,6 @@ //! Tracepoint programs. use std::{fs, io, os::fd::AsFd as _, path::Path}; + use thiserror::Error; use crate::{ diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index d95f6b2c..1c0a0ce0 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -1,6 +1,4 @@ //! User space probes. -use libc::pid_t; -use object::{Object, ObjectSection, ObjectSymbol}; use std::{ borrow::Cow, error::Error, @@ -12,6 +10,9 @@ use std::{ path::{Path, PathBuf}, sync::Arc, }; + +use libc::pid_t; +use object::{Object, ObjectSection, ObjectSymbol}; use thiserror::Error; use crate::{ diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 481d95d9..c9efb062 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -1,11 +1,5 @@ //! eXpress Data Path (XDP) programs. -use crate::{ - sys::{LinkTarget, SyscallError}, - util::KernelVersion, -}; -use bitflags; -use libc::if_nametoindex; use std::{ convert::TryFrom, ffi::CString, @@ -14,6 +8,9 @@ use std::{ os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, RawFd}, path::Path, }; + +use bitflags; +use libc::if_nametoindex; use thiserror::Error; use crate::{ @@ -25,7 +22,11 @@ use crate::{ programs::{ define_link_wrapper, load_program, FdLink, Link, LinkError, ProgramData, ProgramError, }, - sys::{bpf_link_create, bpf_link_get_info_by_fd, bpf_link_update, netlink_set_xdp_fd}, + sys::{ + bpf_link_create, bpf_link_get_info_by_fd, bpf_link_update, netlink_set_xdp_fd, LinkTarget, + SyscallError, + }, + util::KernelVersion, VerifierLogLevel, }; diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index cf41b74a..fdcddd07 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -7,7 +7,6 @@ use std::{ slice, }; -use crate::util::KernelVersion; use assert_matches::assert_matches; use libc::{c_char, c_long, ENOENT, ENOSPC}; use obj::{ @@ -31,6 +30,7 @@ use crate::{ copy_instructions, }, sys::{syscall, SysResult, Syscall, SyscallError}, + util::KernelVersion, Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN, }; @@ -1069,9 +1069,10 @@ pub(crate) fn retry_with_verifier_logs( #[cfg(test)] mod tests { + use libc::{EBADF, EINVAL}; + use super::*; use crate::sys::override_syscall; - use libc::{EBADF, EINVAL}; #[test] fn test_perf_link_supported() { diff --git a/aya/src/sys/mod.rs b/aya/src/sys/mod.rs index 239e68a9..641c25ce 100644 --- a/aya/src/sys/mod.rs +++ b/aya/src/sys/mod.rs @@ -5,20 +5,20 @@ mod perf_event; #[cfg(test)] mod fake; -use libc::{c_int, c_long, pid_t, SYS_bpf, SYS_perf_event_open}; use std::{ io, mem, os::fd::{AsRawFd as _, BorrowedFd}, }; -use thiserror::Error; pub(crate) use bpf::*; #[cfg(test)] pub(crate) use fake::*; +use libc::{c_int, c_long, pid_t, SYS_bpf, SYS_perf_event_open}; #[doc(hidden)] pub use netlink::netlink_set_link_up; pub(crate) use netlink::*; pub(crate) use perf_event::*; +use thiserror::Error; use crate::generated::{bpf_attr, bpf_cmd, perf_event_attr}; diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index c4679aab..96c4f01a 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -5,7 +5,6 @@ use std::{ os::fd::{AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd}, ptr, slice, }; -use thiserror::Error; use libc::{ getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl, socket, @@ -14,6 +13,7 @@ use libc::{ NLM_F_DUMP, NLM_F_ECHO, NLM_F_EXCL, NLM_F_MULTI, NLM_F_REQUEST, RTM_DELTFILTER, RTM_GETTFILTER, RTM_NEWQDISC, RTM_NEWTFILTER, RTM_SETLINK, SOCK_RAW, SOL_NETLINK, }; +use thiserror::Error; use crate::{ generated::{ diff --git a/aya/src/sys/perf_event.rs b/aya/src/sys/perf_event.rs index 1659778a..ebfcc4a5 100644 --- a/aya/src/sys/perf_event.rs +++ b/aya/src/sys/perf_event.rs @@ -6,6 +6,7 @@ use std::{ use libc::{c_int, pid_t}; +use super::{syscall, SysResult, Syscall}; use crate::generated::{ perf_event_attr, perf_event_sample_format::PERF_SAMPLE_RAW, @@ -14,8 +15,6 @@ use crate::generated::{ PERF_FLAG_FD_CLOEXEC, }; -use super::{syscall, SysResult, Syscall}; - #[allow(clippy::too_many_arguments)] pub(crate) fn perf_event_open( perf_type: u32, diff --git a/aya/src/util.rs b/aya/src/util.rs index b7a80006..a0cc357d 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -11,13 +11,13 @@ use std::{ str::{FromStr, Utf8Error}, }; +use libc::{if_nametoindex, sysconf, uname, utsname, _SC_PAGESIZE}; + use crate::{ generated::{TC_H_MAJ_MASK, TC_H_MIN_MASK}, Pod, }; -use libc::{if_nametoindex, sysconf, uname, utsname, _SC_PAGESIZE}; - /// Represents a kernel version, in major.minor.release version. // Adapted from https://docs.rs/procfs/latest/procfs/sys/kernel/struct.Version.html. #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd)] @@ -359,9 +359,10 @@ pub(crate) fn bytes_of_slice(val: &[T]) -> &[u8] { #[cfg(test)] mod tests { - use super::*; use assert_matches::assert_matches; + use super::*; + #[test] fn test_parse_kernel_version_string() { // WSL. diff --git a/bpf/aya-bpf-bindings/src/lib.rs b/bpf/aya-bpf-bindings/src/lib.rs index 1528e4f8..1129fa75 100644 --- a/bpf/aya-bpf-bindings/src/lib.rs +++ b/bpf/aya-bpf-bindings/src/lib.rs @@ -14,17 +14,14 @@ mod aarch64; mod riscv64; mod gen { - #[cfg(bpf_target_arch = "x86_64")] - pub use super::x86_64::*; - - #[cfg(bpf_target_arch = "arm")] - pub use super::armv7::*; - #[cfg(bpf_target_arch = "aarch64")] pub use super::aarch64::*; - + #[cfg(bpf_target_arch = "arm")] + pub use super::armv7::*; #[cfg(bpf_target_arch = "riscv64")] pub use super::riscv64::*; + #[cfg(bpf_target_arch = "x86_64")] + pub use super::x86_64::*; } pub use gen::helpers; diff --git a/bpf/aya-bpf/src/args.rs b/bpf/aya-bpf/src/args.rs index 437fe329..7cee97a8 100644 --- a/bpf/aya-bpf/src/args.rs +++ b/bpf/aya-bpf/src/args.rs @@ -1,14 +1,11 @@ -use crate::{cty::c_void, helpers::bpf_probe_read}; - // aarch64 uses user_pt_regs instead of pt_regs #[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] use crate::bindings::pt_regs; - #[cfg(bpf_target_arch = "aarch64")] use crate::bindings::user_pt_regs as pt_regs; - #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; +use crate::{cty::c_void, helpers::bpf_probe_read}; /// A trait that indicates a valid type for an argument which can be coerced from a BTF /// context. diff --git a/bpf/aya-bpf/src/lib.rs b/bpf/aya-bpf/src/lib.rs index 517e23fa..a10833a3 100644 --- a/bpf/aya-bpf/src/lib.rs +++ b/bpf/aya-bpf/src/lib.rs @@ -22,13 +22,12 @@ pub mod helpers; pub mod maps; pub mod programs; -pub use aya_bpf_cty as cty; - use core::ffi::c_void; -use cty::{c_int, c_long}; -use helpers::{bpf_get_current_comm, bpf_get_current_pid_tgid, bpf_get_current_uid_gid}; +pub use aya_bpf_cty as cty; pub use aya_bpf_macros as macros; +use cty::{c_int, c_long}; +use helpers::{bpf_get_current_comm, bpf_get_current_pid_tgid, bpf_get_current_uid_gid}; pub const TASK_COMM_LEN: usize = 16; diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs index 133be94b..0ada7010 100644 --- a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -2,13 +2,12 @@ use core::{cell::UnsafeCell, mem}; use aya_bpf_bindings::bindings::bpf_cpumap_val; +use super::try_redirect_map; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, maps::PinningType, }; -use super::try_redirect_map; - /// An array of available CPUs. /// /// XDP programs can use this map to redirect packets to a target CPU for processing. diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs index cfa44cb3..d7e62dd0 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -3,14 +3,13 @@ use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_cty::c_void; +use super::try_redirect_map; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP}, helpers::bpf_map_lookup_elem, maps::PinningType, }; -use super::try_redirect_map; - /// An array of network devices. /// /// XDP programs can use this map to redirect packets to other network deviecs. diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs index cbec50bb..809215aa 100644 --- a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -3,14 +3,13 @@ use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_cty::c_void; +use super::{dev_map::DevMapValue, try_redirect_map}; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH}, helpers::bpf_map_lookup_elem, maps::PinningType, }; -use super::{dev_map::DevMapValue, try_redirect_map}; - /// A map of network devices. /// /// XDP programs can use this map to redirect packets to other network devices. It is similar to diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs index 455dfc84..934785c1 100644 --- a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -3,14 +3,13 @@ use core::{cell::UnsafeCell, mem, ptr::NonNull}; use aya_bpf_bindings::bindings::bpf_xdp_sock; use aya_bpf_cty::c_void; +use super::try_redirect_map; use crate::{ bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_XSKMAP}, helpers::bpf_map_lookup_elem, maps::PinningType, }; -use super::try_redirect_map; - /// An array of AF_XDP sockets. /// /// XDP programs can use this map to redirect packets to a target AF_XDP socket using the diff --git a/bpf/aya-bpf/src/programs/perf_event.rs b/bpf/aya-bpf/src/programs/perf_event.rs index d24ed737..f303b28d 100644 --- a/bpf/aya-bpf/src/programs/perf_event.rs +++ b/bpf/aya-bpf/src/programs/perf_event.rs @@ -1,6 +1,7 @@ -use crate::BpfContext; use core::ffi::c_void; +use crate::BpfContext; + pub struct PerfEventContext { ctx: *mut c_void, } diff --git a/bpf/aya-bpf/src/programs/probe.rs b/bpf/aya-bpf/src/programs/probe.rs index 25694845..9566c814 100644 --- a/bpf/aya-bpf/src/programs/probe.rs +++ b/bpf/aya-bpf/src/programs/probe.rs @@ -1,15 +1,12 @@ use core::ffi::c_void; -use crate::{args::FromPtRegs, BpfContext}; - #[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] use crate::bindings::pt_regs; - #[cfg(bpf_target_arch = "aarch64")] use crate::bindings::user_pt_regs as pt_regs; - #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; +use crate::{args::FromPtRegs, BpfContext}; pub struct ProbeContext { pub regs: *mut pt_regs, diff --git a/bpf/aya-bpf/src/programs/tracepoint.rs b/bpf/aya-bpf/src/programs/tracepoint.rs index 29db68b4..4087b7b8 100644 --- a/bpf/aya-bpf/src/programs/tracepoint.rs +++ b/bpf/aya-bpf/src/programs/tracepoint.rs @@ -1,6 +1,7 @@ -use crate::{helpers::bpf_probe_read, BpfContext}; use core::ffi::c_void; +use crate::{helpers::bpf_probe_read, BpfContext}; + pub struct TracePointContext { ctx: *mut c_void, } diff --git a/rustfmt.toml b/rustfmt.toml index 1cdefeb0..53f7b6d7 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,4 @@ -unstable_features = true -reorder_imports = true +group_imports = "StdExternalCrate" imports_granularity = "Crate" +reorder_imports = true +unstable_features = true diff --git a/test/integration-test/src/tests/btf_relocations.rs b/test/integration-test/src/tests/btf_relocations.rs index 79eb3e52..c149d43e 100644 --- a/test/integration-test/src/tests/btf_relocations.rs +++ b/test/integration-test/src/tests/btf_relocations.rs @@ -1,6 +1,5 @@ -use test_case::test_case; - use aya::{maps::Array, programs::UProbe, util::KernelVersion, BpfLoader, Btf, Endianness}; +use test_case::test_case; #[test_case("enum_signed_32", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0x7AAAAAAAi32 as u64)] #[test_case("enum_signed_32", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0x7BBBBBBBi32 as u64)] diff --git a/xtask/src/codegen/aya.rs b/xtask/src/codegen/aya.rs index 950b862c..7556cab6 100644 --- a/xtask/src/codegen/aya.rs +++ b/xtask/src/codegen/aya.rs @@ -1,6 +1,6 @@ -use anyhow::anyhow; use std::path::{Path, PathBuf}; +use anyhow::anyhow; use aya_tool::{bindgen, write_to_file}; use crate::codegen::{Architecture, SysrootOptions}; diff --git a/xtask/src/codegen/aya_bpf_bindings.rs b/xtask/src/codegen/aya_bpf_bindings.rs index d594a5fe..8e417445 100644 --- a/xtask/src/codegen/aya_bpf_bindings.rs +++ b/xtask/src/codegen/aya_bpf_bindings.rs @@ -1,9 +1,9 @@ -use anyhow::anyhow; -use proc_macro2::TokenStream; -use quote::ToTokens; use std::path::{Path, PathBuf}; +use anyhow::anyhow; use aya_tool::{bindgen, write_to_file_fmt}; +use proc_macro2::TokenStream; +use quote::ToTokens; use syn::{parse_str, Item}; use crate::codegen::{ diff --git a/xtask/src/docs.rs b/xtask/src/docs.rs index 2e8abc96..4acc6df1 100644 --- a/xtask/src/docs.rs +++ b/xtask/src/docs.rs @@ -1,7 +1,8 @@ +use std::{ffi::OsString, fs, io::Write as _, process::Command}; + use anyhow::{Context as _, Result}; use cargo_metadata::Metadata; use indoc::{indoc, writedoc}; -use std::{ffi::OsString, fs, io::Write as _, process::Command}; use xtask::exec; pub fn docs(metadata: Metadata) -> Result<()> { diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 84e8c3bc..47c6c56c 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -1,6 +1,7 @@ -use anyhow::{bail, Context as _, Result}; use std::process::Command; +use anyhow::{bail, Context as _, Result}; + pub const AYA_BUILD_INTEGRATION_BPF: &str = "AYA_BUILD_INTEGRATION_BPF"; pub const LIBBPF_DIR: &str = "xtask/libbpf"; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 01105c00..9060f16e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -3,10 +3,11 @@ mod docs; mod public_api; mod run; +use std::process::Command; + use anyhow::{Context as _, Result}; use cargo_metadata::{Metadata, MetadataCommand}; use clap::Parser; -use std::process::Command; use xtask::{exec, LIBBPF_DIR}; #[derive(Parser)] From 5392f9821d2a4abd14c93e21486a6adf8023675e Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 28 Sep 2023 13:31:05 -0400 Subject: [PATCH 60/95] xtask: terminate QEMU on "BUG: soft lockup" See https://github.com/aya-rs/aya/actions/runs/6329828507/job/17190931752. Unlike on kernel panic this message prints periodically so it is permitted to print twice before QEMU is killed. --- xtask/src/run.rs | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/xtask/src/run.rs b/xtask/src/run.rs index a9ba17f4..64114620 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -456,20 +456,30 @@ pub fn run(opts: Options) -> Result<()> { let stderr = stderr.take().unwrap(); let stderr = BufReader::new(stderr); - fn terminate_if_contains_kernel_panic( - line: &str, - stdin: &Arc>, - ) -> anyhow::Result<()> { - if line.contains("end Kernel panic") { - println!("kernel panic detected; terminating QEMU"); - let mut stdin = stdin.lock().unwrap(); - stdin - .write_all(&[0x01, b'x']) - .context("failed to write to stdin")?; - println!("waiting for QEMU to terminate"); - } - Ok(()) - } + const TERMINATE_AFTER_COUNT: &[(&str, usize)] = + &[("end Kernel panic", 0), ("watchdog: BUG: soft lockup", 1)]; + let mut counts = [0; TERMINATE_AFTER_COUNT.len()]; + + let mut terminate_if_kernel_hang = + move |line: &str, stdin: &Arc>| -> anyhow::Result<()> { + if let Some(i) = TERMINATE_AFTER_COUNT + .iter() + .position(|(marker, _)| line.contains(marker)) + { + counts[i] += 1; + + let (marker, max) = TERMINATE_AFTER_COUNT[i]; + if counts[i] > max { + println!("{marker} detected > {max} times; terminating QEMU"); + let mut stdin = stdin.lock().unwrap(); + stdin + .write_all(&[0x01, b'x']) + .context("failed to write to stdin")?; + println!("waiting for QEMU to terminate"); + } + } + Ok(()) + }; let stderr = { let stdin = stdin.clone(); @@ -478,8 +488,7 @@ pub fn run(opts: Options) -> Result<()> { for line in stderr.lines() { let line = line.context("failed to read line from stderr")?; eprintln!("{}", line); - // Try to get QEMU to exit on kernel panic; otherwise it might hang indefinitely. - terminate_if_contains_kernel_panic(&line, &stdin)?; + terminate_if_kernel_hang(&line, &stdin)?; } anyhow::Ok(()) }) @@ -490,8 +499,7 @@ pub fn run(opts: Options) -> Result<()> { for line in stdout.lines() { let line = line.context("failed to read line from stdout")?; println!("{}", line); - // Try to get QEMU to exit on kernel panic; otherwise it might hang indefinitely. - terminate_if_contains_kernel_panic(&line, &stdin)?; + terminate_if_kernel_hang(&line, &stdin)?; // The init program will print "init: success" or "init: failure" to indicate // the outcome of running the binaries it found in /bin. if let Some(line) = line.strip_prefix("init: ") { From da832e479d79b5225ef58abbac9d512c0315b274 Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Thu, 28 Sep 2023 13:15:54 -0400 Subject: [PATCH 61/95] integration-test: deflake test_loaded_at The test could fail due to the lack of clock monotonicity. This PR deflakes the test by adding retries. See https://github.com/aya-rs/aya/actions/runs/6340369670/job/17221591723. --- test/integration-test/src/tests/load.rs | 38 +++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 795f396d..5e193dbf 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -154,22 +154,36 @@ fn unload_xdp() { fn test_loaded_at() { let mut bpf = Bpf::load(crate::TEST).unwrap(); let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); - let t1 = SystemTime::now(); - prog.load().unwrap(); - let t2 = SystemTime::now(); - assert_loaded("pass"); - - let loaded_at = prog.info().unwrap().loaded_at(); - let range = t1..t2; + // SystemTime is not monotonic, which can cause this test to flake. We don't expect the clock + // timestamp to continuously jump around, so we add some retries. If the test is ever correct, + // we know that the value returned by loaded_at() was reasonable relative to SystemTime::now(). + let mut failures = Vec::new(); + for _ in 0..5 { + let t1 = SystemTime::now(); + prog.load().unwrap(); + let t2 = SystemTime::now(); + let loaded_at = prog.info().unwrap().loaded_at(); + prog.unload().unwrap(); + let range = t1..t2; + if range.contains(&loaded_at) { + failures.clear(); + break; + } + failures.push(LoadedAtRange(loaded_at, range)); + } assert!( - range.contains(&loaded_at), - "{range:?}.contains({loaded_at:?})" + failures.is_empty(), + "loaded_at was not in range: {failures:?}", ); - prog.unload().unwrap(); - - assert_unloaded("pass"); + struct LoadedAtRange(SystemTime, std::ops::Range); + impl std::fmt::Debug for LoadedAtRange { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self(loaded_at, range) = self; + write!(f, "{range:?}.contains({loaded_at:?})") + } + } } #[test] From 64d9799efcc33b934ff0980c2215a9a023d78cca Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 2 Oct 2023 16:07:33 -0400 Subject: [PATCH 62/95] integration/xdp: reduce repetition --- test/integration-test/src/tests/xdp.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index 88423fe9..e66b497f 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -82,17 +82,19 @@ fn cpumap_chain() { xdp.load().unwrap(); xdp.attach("lo", XdpFlags::default()).unwrap(); + const PAYLOAD: &str = "hello cpumap"; + let sock = UdpSocket::bind("127.0.0.1:1777").unwrap(); sock.set_read_timeout(Some(Duration::from_millis(1))) .unwrap(); - sock.send_to(b"hello cpumap", "127.0.0.1:1777").unwrap(); + sock.send_to(PAYLOAD.as_bytes(), "127.0.0.1:1777").unwrap(); - // Read back the packet to ensure it wenth through the entire network stack, including our two + // Read back the packet to ensure it went through the entire network stack, including our two // probes. - let mut buf = vec![0u8; 1000]; + let mut buf = [0u8; PAYLOAD.len() + 1]; let n = sock.recv(&mut buf).unwrap(); - assert_eq!(&buf[..n], b"hello cpumap"); + assert_eq!(&buf[..n], PAYLOAD.as_bytes()); assert_eq!(hits.get(&0, 0).unwrap(), 1); assert_eq!(hits.get(&1, 0).unwrap(), 1); } From 062ebfdc68146b4b705c44a2c76cd6624f8c3730 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 2 Oct 2023 16:09:03 -0400 Subject: [PATCH 63/95] integration/xdp: use kernel-allocated port --- test/integration-test/src/tests/xdp.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index e66b497f..780fe465 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -84,10 +84,11 @@ fn cpumap_chain() { const PAYLOAD: &str = "hello cpumap"; - let sock = UdpSocket::bind("127.0.0.1:1777").unwrap(); + let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); + let addr = sock.local_addr().unwrap(); sock.set_read_timeout(Some(Duration::from_millis(1))) .unwrap(); - sock.send_to(PAYLOAD.as_bytes(), "127.0.0.1:1777").unwrap(); + sock.send_to(PAYLOAD.as_bytes(), addr).unwrap(); // Read back the packet to ensure it went through the entire network stack, including our two // probes. From 81268b7ac1ca325a740076e0d00c2ff5af1a20b7 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 2 Oct 2023 16:09:52 -0400 Subject: [PATCH 64/95] integration/xdp: increase timeout to 60 seconds There's absolutely no reason to have a short timeout here. This has resulted in at least one flake: https://github.com/aya-rs/bpf-linker/actions/runs/6384472390/job/17327196576. --- test/integration-test/src/tests/xdp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index 780fe465..092f280e 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -86,7 +86,7 @@ fn cpumap_chain() { let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); let addr = sock.local_addr().unwrap(); - sock.set_read_timeout(Some(Duration::from_millis(1))) + sock.set_read_timeout(Some(Duration::from_secs(60))) .unwrap(); sock.send_to(PAYLOAD.as_bytes(), addr).unwrap(); From bd6ba3ad8bae0537eee9eb78d20620592daa3c76 Mon Sep 17 00:00:00 2001 From: Mike Rostecki Date: Wed, 4 Oct 2023 14:27:47 +0100 Subject: [PATCH 65/95] util: Deprecate `syscall_prefix` Using the prefix only for the host architecture is often not enough, kernels usually provide symbols for more architectures, which are used by multilib applications. Handling them might or might not be necessary depending on the use case. Due to that complexity, we decided to let the callers to handle prefixes the way they prefer. --- aya/src/util.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aya/src/util.rs b/aya/src/util.rs index a0cc357d..3184dae4 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -265,6 +265,13 @@ fn parse_kernel_symbols(reader: impl BufRead) -> Result, i /// # Errors /// /// Returns [`std::io::ErrorKind::NotFound`] if the prefix can't be guessed. Returns other [`std::io::Error`] kinds if `/proc/kallsyms` can't be opened or is somehow invalid. +#[deprecated( + since = "0.12.0", + note = "On some systems - commonly on 64 bit kernels that support running \ + 32 bit applications - the syscall prefix depends on what architecture an \ + application is compiled for, therefore attaching to only one prefix is \ + incorrect and can lead to security issues." +)] pub fn syscall_prefix() -> Result<&'static str, io::Error> { const PREFIXES: [&str; 7] = [ "sys_", From 0bf97eba64b44835300d8291cd4f78c220c3ad48 Mon Sep 17 00:00:00 2001 From: astoycos Date: Thu, 21 Sep 2023 13:50:21 -0400 Subject: [PATCH 66/95] aya/maps: fix libbpf_pin_by_name Aligns with libbpf for the special LIBBPF_PIN_BY_NAME map flag. Specifically if the flag is provided without a pin path default to "/sys/fs/bpf". Signed-off-by: astoycos --- aya/src/bpf.rs | 13 +++++++------ aya/src/maps/mod.rs | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 2272bc52..7e03a12a 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -492,8 +492,13 @@ impl<'a> BpfLoader<'a> { let mut map = match obj.pinning() { PinningType::None => MapData::create(obj, &name, btf_fd)?, PinningType::ByName => { - let path = map_pin_path.as_ref().ok_or(BpfError::NoPinPath)?; - MapData::create_pinned(path, obj, &name, btf_fd)? + // pin maps in /sys/fs/bpf by default to align with libbpf + // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161. + let path = map_pin_path + .as_deref() + .unwrap_or_else(|| Path::new("/sys/fs/bpf")); + + MapData::create_pinned_by_name(path, obj, &name, btf_fd)? } }; map.finalize()?; @@ -951,10 +956,6 @@ pub enum BpfError { error: io::Error, }, - /// Pinning requested but no path provided - #[error("pinning requested but no path provided")] - NoPinPath, - /// Unexpected pinning type #[error("unexpected pinning type {name}")] UnexpectedPinningType { diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 84971419..af9ec868 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -461,7 +461,7 @@ impl MapData { Ok(Self { obj, fd }) } - pub(crate) fn create_pinned>( + pub(crate) fn create_pinned_by_name>( path: P, obj: obj::Map, name: &str, @@ -490,7 +490,6 @@ impl MapData { } Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; - let path = path.join(name); map.pin(&path).map_err(|error| MapError::PinError { name: Some(name.into()), error, From 7b71c7e1cd8d6948764d02afb0279151c6eae437 Mon Sep 17 00:00:00 2001 From: astoycos Date: Fri, 22 Sep 2023 10:35:19 -0400 Subject: [PATCH 67/95] aya/maps: add pin() api - Adds new `maps_mut()` API to the BpfManager to allow us to iterate though and pin all of maps at the same time. - Adds new pin(Path)/unpin(Path) api to Maps so they can be generically pinned AFTER load. - Adds macro for pinning explicit map types in aya. Convert all explicit map types "inner" field to be pub crate in order to facilitate this. Signed-off-by: astoycos --- aya/src/bpf.rs | 25 ++++++- aya/src/maps/array/array.rs | 2 +- aya/src/maps/array/per_cpu_array.rs | 2 +- aya/src/maps/array/program_array.rs | 2 +- aya/src/maps/bloom_filter.rs | 2 +- aya/src/maps/hash_map/hash_map.rs | 2 +- aya/src/maps/hash_map/per_cpu_hash_map.rs | 2 +- aya/src/maps/lpm_trie.rs | 2 +- aya/src/maps/mod.rs | 86 ++++++++++++++++++++++- aya/src/maps/queue.rs | 2 +- aya/src/maps/sock/sock_hash.rs | 2 +- aya/src/maps/stack.rs | 2 +- aya/src/maps/stack_trace.rs | 2 +- aya/src/maps/xdp/cpu_map.rs | 2 +- aya/src/maps/xdp/dev_map.rs | 2 +- aya/src/maps/xdp/dev_map_hash.rs | 2 +- aya/src/maps/xdp/xsk_map.rs | 2 +- xtask/public-api/aya.txt | 68 +++++++++++++++++- 18 files changed, 190 insertions(+), 19 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 7e03a12a..57162163 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -398,7 +398,7 @@ impl<'a> BpfLoader<'a> { if let Some(btf) = obj.fixup_and_sanitize_btf(features)? { match load_btf(btf.to_bytes(), *verifier_log_level) { Ok(btf_fd) => Some(Arc::new(btf_fd)), - // Only report an error here if the BTF is truely needed, otherwise proceed without. + // Only report an error here if the BTF is truly needed, otherwise proceed without. Err(err) => { for program in obj.programs.values() { match program.section { @@ -861,6 +861,29 @@ impl Bpf { self.maps.iter().map(|(name, map)| (name.as_str(), map)) } + /// A mutable iterator over all the maps. + /// + /// # Examples + /// ```no_run + /// # use std::path::Path; + /// # #[derive(thiserror::Error, Debug)] + /// # enum Error { + /// # #[error(transparent)] + /// # Bpf(#[from] aya::BpfError), + /// # #[error(transparent)] + /// # Pin(#[from] aya::pin::PinError) + /// # } + /// # let mut bpf = aya::Bpf::load(&[])?; + /// # let pin_path = Path::new("/tmp/pin_path"); + /// for (_, map) in bpf.maps_mut() { + /// map.pin(pin_path)?; + /// } + /// # Ok::<(), Error>(()) + /// ``` + pub fn maps_mut(&mut self) -> impl Iterator { + self.maps.iter_mut().map(|(name, map)| (name.as_str(), map)) + } + /// 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 diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 5d137d05..9fdc91e3 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -31,7 +31,7 @@ use crate::{ /// ``` #[doc(alias = "BPF_MAP_TYPE_ARRAY")] pub struct Array { - inner: T, + pub(crate) inner: T, _v: PhantomData, } diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index f384b713..9c261f0c 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -50,7 +50,7 @@ use crate::{ /// ``` #[doc(alias = "BPF_MAP_TYPE_PERCPU_ARRAY")] pub struct PerCpuArray { - inner: T, + pub(crate) inner: T, _v: PhantomData, } diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index 48bb6b9d..513bf77f 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -48,7 +48,7 @@ use crate::{ /// ``` #[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")] pub struct ProgramArray { - inner: T, + pub(crate) inner: T, } impl> ProgramArray { diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index d038e35f..5c547fb0 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -36,7 +36,7 @@ use crate::{ #[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")] #[derive(Debug)] pub struct BloomFilter { - inner: T, + pub(crate) inner: T, _v: PhantomData, } diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index bfc96845..72c81b95 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -34,7 +34,7 @@ use crate::{ #[doc(alias = "BPF_MAP_TYPE_LRU_HASH")] #[derive(Debug)] pub struct HashMap { - inner: T, + pub(crate) inner: T, _k: PhantomData, _v: PhantomData, } diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index b1985390..fe404ce0 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -43,7 +43,7 @@ use crate::{ #[doc(alias = "BPF_MAP_TYPE_LRU_PERCPU_HASH")] #[doc(alias = "BPF_MAP_TYPE_PERCPU_HASH")] pub struct PerCpuHashMap { - inner: T, + pub(crate) inner: T, _k: PhantomData, _v: PhantomData, } diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index 181a2f57..139a9cb9 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -48,7 +48,7 @@ use crate::{ #[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")] #[derive(Debug)] pub struct LpmTrie { - inner: T, + pub(crate) inner: T, _k: PhantomData, _v: PhantomData, } diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index af9ec868..771486c2 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -48,6 +48,7 @@ //! versa. Because of that, all map values must be plain old data and therefore //! implement the [Pod] trait. use std::{ + borrow::BorrowMut, ffi::CString, fmt, io, marker::PhantomData, @@ -170,8 +171,8 @@ pub enum MapError { #[error(transparent)] SyscallError(#[from] SyscallError), - /// Could not pin map by name - #[error("map `{name:?}` requested pinning by name. pinning failed")] + /// Could not pin map + #[error("map `{name:?}` requested pinning. pinning failed")] PinError { /// The map name name: Option, @@ -308,8 +309,89 @@ impl Map { Self::Unsupported(map) => map.obj.map_type(), } } + + /// Pins the map to a BPF filesystem. + /// + /// When a map is pinned it will remain loaded until the corresponding file + /// is deleted. All parent directories in the given `path` must already exist. + pub fn pin>(&mut self, path: P) -> Result<(), PinError> { + match self { + Self::Array(map) => map.pin(path), + Self::PerCpuArray(map) => map.pin(path), + Self::ProgramArray(map) => map.pin(path), + Self::HashMap(map) => map.pin(path), + Self::LruHashMap(map) => map.pin(path), + Self::PerCpuHashMap(map) => map.pin(path), + Self::PerCpuLruHashMap(map) => map.pin(path), + Self::PerfEventArray(map) => map.pin(path), + Self::SockHash(map) => map.pin(path), + Self::SockMap(map) => map.pin(path), + Self::BloomFilter(map) => map.pin(path), + Self::LpmTrie(map) => map.pin(path), + Self::Stack(map) => map.pin(path), + Self::StackTraceMap(map) => map.pin(path), + Self::Queue(map) => map.pin(path), + Self::CpuMap(map) => map.pin(path), + Self::DevMap(map) => map.pin(path), + Self::DevMapHash(map) => map.pin(path), + Self::XskMap(map) => map.pin(path), + Self::Unsupported(map) => map.pin(path), + } + } +} + +// Implements map pinning for different map implementations +// TODO add support for PerfEventArrays and AsyncPerfEventArrays +macro_rules! impl_map_pin { + ($ty_param:tt { + $($ty:ident),+ $(,)? + }) => { + $(impl_map_pin!(<$ty_param> $ty);)+ + }; + ( + <($($ty_param:ident),*)> + $ty:ident + ) => { + impl, $($ty_param: Pod),*> $ty + { + /// Pins the map to a BPF filesystem. + /// + /// When a map is pinned it will remain loaded until the corresponding file + /// is deleted. All parent directories in the given `path` must already exist. + pub fn pin>(&mut self, path: P) -> Result<(), PinError> { + let data = self.inner.borrow_mut(); + data.pin(path) + } + } + + }; } +impl_map_pin!(() { + ProgramArray, + SockMap, + StackTraceMap, + CpuMap, + DevMap, + DevMapHash, + XskMap, +}); + +impl_map_pin!((V) { + Array, + PerCpuArray, + SockHash, + BloomFilter, + Queue, + Stack, +}); + +impl_map_pin!((K, V) { + HashMap, + PerCpuHashMap, + LpmTrie, +}); + // Implements TryFrom for different map implementations. Different map implementations can be // constructed from different variants of the map enum. Also, the implementation may have type // parameters (which we assume all have the bound `Pod` and nothing else). diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index 31c44633..b9177b24 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -30,7 +30,7 @@ use crate::{ /// ``` #[doc(alias = "BPF_MAP_TYPE_QUEUE")] pub struct Queue { - inner: T, + pub(crate) inner: T, _v: PhantomData, } diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 99d0f871..e3074be8 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -65,7 +65,7 @@ use crate::{ /// ``` #[doc(alias = "BPF_MAP_TYPE_SOCKHASH")] pub struct SockHash { - inner: T, + pub(crate) inner: T, _k: PhantomData, } diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index ac1453cd..a85fe14d 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -30,7 +30,7 @@ use crate::{ /// ``` #[doc(alias = "BPF_MAP_TYPE_STACK")] pub struct Stack { - inner: T, + pub(crate) inner: T, _v: PhantomData, } diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index fdf1d937..389b28f7 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -67,7 +67,7 @@ use crate::{ #[derive(Debug)] #[doc(alias = "BPF_MAP_TYPE_STACK_TRACE")] pub struct StackTraceMap { - inner: T, + pub(crate) inner: T, max_stack_depth: usize, } diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index f48fcdc2..85f9e679 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/aya/src/maps/xdp/cpu_map.rs @@ -50,7 +50,7 @@ use crate::{ /// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_CPUMAP")] pub struct CpuMap { - inner: T, + pub(crate) inner: T, } impl> CpuMap { diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs index 6b6cd545..31e9b3ac 100644 --- a/aya/src/maps/xdp/dev_map.rs +++ b/aya/src/maps/xdp/dev_map.rs @@ -42,7 +42,7 @@ use crate::{ /// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_DEVMAP")] pub struct DevMap { - inner: T, + pub(crate) inner: T, } impl> DevMap { diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs index 65b00ee4..63a93b02 100644 --- a/aya/src/maps/xdp/dev_map_hash.rs +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -42,7 +42,7 @@ use crate::{ /// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] pub struct DevMapHash { - inner: T, + pub(crate) inner: T, } impl> DevMapHash { diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs index 5382ae4c..43924abf 100644 --- a/aya/src/maps/xdp/xsk_map.rs +++ b/aya/src/maps/xdp/xsk_map.rs @@ -36,7 +36,7 @@ use crate::{ /// Kernel documentation: #[doc(alias = "BPF_MAP_TYPE_XSKMAP")] pub struct XskMap { - inner: T, + pub(crate) inner: T, } impl> XskMap { diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 86221498..81fa16ec 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -12,6 +12,8 @@ pub fn aya::maps::array::Array::get(&self, index: &u32, flags: u64) -> cor pub fn aya::maps::array::Array::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ pub fn aya::maps::array::Array::len(&self) -> u32 impl, V: aya::Pod> aya::maps::array::Array +pub fn aya::maps::array::Array::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::array::Array pub fn aya::maps::array::Array::set(&mut self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V> pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError @@ -52,6 +54,8 @@ pub fn aya::maps::PerCpuArray::get(&self, index: &u32, flags: u64) -> core pub fn aya::maps::PerCpuArray::iter(&self) -> impl core::iter::traits::iterator::Iterator, aya::maps::MapError>> + '_ pub fn aya::maps::PerCpuArray::len(&self) -> u32 impl, V: aya::Pod> aya::maps::PerCpuArray +pub fn aya::maps::PerCpuArray::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::PerCpuArray pub fn aya::maps::PerCpuArray::set(&mut self, index: u32, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError @@ -92,6 +96,8 @@ pub fn aya::maps::ProgramArray::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::ProgramArray pub fn aya::maps::ProgramArray::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::ProgramArray::set(&mut self, index: u32, program: &aya::programs::ProgramFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl> aya::maps::ProgramArray +pub fn aya::maps::ProgramArray::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result @@ -128,6 +134,8 @@ impl, V: aya::Pod> aya::maps::bloom_ pub fn aya::maps::bloom_filter::BloomFilter::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl, V: aya::Pod> aya::maps::bloom_filter::BloomFilter pub fn aya::maps::bloom_filter::BloomFilter::insert(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl, V: aya::Pod> aya::maps::bloom_filter::BloomFilter +pub fn aya::maps::bloom_filter::BloomFilter::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -169,6 +177,8 @@ pub fn aya::maps::hash_map::HashMap::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::insert(&mut self, key: impl core::borrow::Borrow, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::HashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> +impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap +pub fn aya::maps::hash_map::HashMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V> pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -212,6 +222,8 @@ pub fn aya::maps::hash_map::PerCpuHashMap::keys(&self) -> aya::maps::Ma impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::insert(&mut self, key: impl core::borrow::Borrow, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::PerCpuHashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> +impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap +pub fn aya::maps::hash_map::PerCpuHashMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V> pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -291,6 +303,8 @@ pub fn aya::maps::lpm_trie::LpmTrie::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::insert(&mut self, key: &aya::maps::lpm_trie::Key, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::lpm_trie::LpmTrie::remove(&mut self, key: &aya::maps::lpm_trie::Key) -> core::result::Result<(), aya::maps::MapError> +impl, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie +pub fn aya::maps::lpm_trie::LpmTrie::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V> pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -524,6 +538,8 @@ pub struct aya::maps::queue::Queue impl, V: aya::Pod> aya::maps::queue::Queue pub fn aya::maps::queue::Queue::capacity(&self) -> u32 impl, V: aya::Pod> aya::maps::queue::Queue +pub fn aya::maps::queue::Queue::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::queue::Queue pub fn aya::maps::queue::Queue::pop(&mut self, flags: u64) -> core::result::Result pub fn aya::maps::queue::Queue::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V> @@ -566,6 +582,8 @@ pub fn aya::maps::SockHash::keys(&self) -> aya::maps::MapKeys<'_, K> impl, K: aya::Pod> aya::maps::SockHash pub fn aya::maps::SockHash::insert(&mut self, key: impl core::borrow::Borrow, value: I, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::SockHash::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> +impl, V: aya::Pod> aya::maps::SockHash +pub fn aya::maps::SockHash::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V> pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -606,6 +624,8 @@ pub fn aya::maps::SockMap::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::SockMap pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::SockMap::set(&mut self, index: u32, socket: &I, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl> aya::maps::SockMap +pub fn aya::maps::SockMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result @@ -667,6 +687,8 @@ pub struct aya::maps::stack::Stack impl, V: aya::Pod> aya::maps::stack::Stack pub fn aya::maps::stack::Stack::capacity(&self) -> u32 impl, V: aya::Pod> aya::maps::stack::Stack +pub fn aya::maps::stack::Stack::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::stack::Stack pub fn aya::maps::stack::Stack::pop(&mut self, flags: u64) -> core::result::Result pub fn aya::maps::stack::Stack::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V> @@ -756,6 +778,8 @@ impl> aya::maps::stack_trace::StackT pub fn aya::maps::stack_trace::StackTraceMap::get(&self, stack_id: &u32, flags: u64) -> core::result::Result pub fn aya::maps::stack_trace::StackTraceMap::iter(&self) -> aya::maps::MapIter<'_, u32, aya::maps::stack_trace::StackTrace, Self> pub fn aya::maps::stack_trace::StackTraceMap::stack_ids(&self) -> aya::maps::MapKeys<'_, u32> +impl> aya::maps::stack_trace::StackTraceMap +pub fn aya::maps::stack_trace::StackTraceMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::stack_trace::StackTraceMap pub type aya::maps::stack_trace::StackTraceMap::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result @@ -836,6 +860,8 @@ pub fn aya::maps::CpuMap::get(&self, cpu_index: u32, flags: u64) -> core::res pub fn aya::maps::CpuMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ pub fn aya::maps::CpuMap::len(&self) -> u32 impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl> aya::maps::CpuMap pub fn aya::maps::CpuMap::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> impl core::convert::TryFrom for aya::maps::CpuMap pub type aya::maps::CpuMap::Error = aya::maps::MapError @@ -873,6 +899,8 @@ pub fn aya::maps::DevMap::get(&self, index: u32, flags: u64) -> core::result: pub fn aya::maps::DevMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ pub fn aya::maps::DevMap::len(&self) -> u32 impl> aya::maps::DevMap +pub fn aya::maps::DevMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl> aya::maps::DevMap pub fn aya::maps::DevMap::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> impl core::convert::TryFrom for aya::maps::DevMap pub type aya::maps::DevMap::Error = aya::maps::MapError @@ -912,6 +940,8 @@ pub fn aya::maps::DevMapHash::keys(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::DevMapHash pub fn aya::maps::DevMapHash::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> pub fn aya::maps::DevMapHash::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError> +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::DevMapHash pub type aya::maps::DevMapHash::Error = aya::maps::MapError pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result @@ -946,6 +976,8 @@ pub struct aya::maps::xdp::XskMap impl> aya::maps::XskMap pub fn aya::maps::XskMap::len(&self) -> u32 impl> aya::maps::XskMap +pub fn aya::maps::XskMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl> aya::maps::XskMap pub fn aya::maps::XskMap::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl core::convert::TryFrom for aya::maps::XskMap pub type aya::maps::XskMap::Error = aya::maps::MapError @@ -998,6 +1030,8 @@ pub aya::maps::Map::Stack(aya::maps::MapData) pub aya::maps::Map::StackTraceMap(aya::maps::MapData) pub aya::maps::Map::Unsupported(aya::maps::MapData) pub aya::maps::Map::XskMap(aya::maps::MapData) +impl aya::maps::Map +pub fn aya::maps::Map::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::CpuMap pub type aya::maps::CpuMap::Error = aya::maps::MapError pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result @@ -1252,6 +1286,8 @@ pub fn aya::maps::array::Array::get(&self, index: &u32, flags: u64) -> cor pub fn aya::maps::array::Array::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ pub fn aya::maps::array::Array::len(&self) -> u32 impl, V: aya::Pod> aya::maps::array::Array +pub fn aya::maps::array::Array::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::array::Array pub fn aya::maps::array::Array::set(&mut self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V> pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError @@ -1324,6 +1360,8 @@ impl, V: aya::Pod> aya::maps::bloom_ pub fn aya::maps::bloom_filter::BloomFilter::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl, V: aya::Pod> aya::maps::bloom_filter::BloomFilter pub fn aya::maps::bloom_filter::BloomFilter::insert(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl, V: aya::Pod> aya::maps::bloom_filter::BloomFilter +pub fn aya::maps::bloom_filter::BloomFilter::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V> pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -1362,6 +1400,8 @@ pub fn aya::maps::CpuMap::get(&self, cpu_index: u32, flags: u64) -> core::res pub fn aya::maps::CpuMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ pub fn aya::maps::CpuMap::len(&self) -> u32 impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl> aya::maps::CpuMap pub fn aya::maps::CpuMap::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> impl core::convert::TryFrom for aya::maps::CpuMap pub type aya::maps::CpuMap::Error = aya::maps::MapError @@ -1399,6 +1439,8 @@ pub fn aya::maps::DevMap::get(&self, index: u32, flags: u64) -> core::result: pub fn aya::maps::DevMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ pub fn aya::maps::DevMap::len(&self) -> u32 impl> aya::maps::DevMap +pub fn aya::maps::DevMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl> aya::maps::DevMap pub fn aya::maps::DevMap::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> impl core::convert::TryFrom for aya::maps::DevMap pub type aya::maps::DevMap::Error = aya::maps::MapError @@ -1438,6 +1480,8 @@ pub fn aya::maps::DevMapHash::keys(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::DevMapHash pub fn aya::maps::DevMapHash::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> pub fn aya::maps::DevMapHash::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError> +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::DevMapHash pub type aya::maps::DevMapHash::Error = aya::maps::MapError pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result @@ -1476,6 +1520,8 @@ pub fn aya::maps::hash_map::HashMap::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::insert(&mut self, key: impl core::borrow::Borrow, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::HashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> +impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap +pub fn aya::maps::hash_map::HashMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V> pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -1519,6 +1565,8 @@ pub fn aya::maps::lpm_trie::LpmTrie::keys(&self) -> aya::maps::MapKeys< impl, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::insert(&mut self, key: &aya::maps::lpm_trie::Key, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::lpm_trie::LpmTrie::remove(&mut self, key: &aya::maps::lpm_trie::Key) -> core::result::Result<(), aya::maps::MapError> +impl, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie +pub fn aya::maps::lpm_trie::LpmTrie::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V> pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -1674,6 +1722,8 @@ pub fn aya::maps::PerCpuArray::get(&self, index: &u32, flags: u64) -> core pub fn aya::maps::PerCpuArray::iter(&self) -> impl core::iter::traits::iterator::Iterator, aya::maps::MapError>> + '_ pub fn aya::maps::PerCpuArray::len(&self) -> u32 impl, V: aya::Pod> aya::maps::PerCpuArray +pub fn aya::maps::PerCpuArray::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::PerCpuArray pub fn aya::maps::PerCpuArray::set(&mut self, index: u32, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V> pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError @@ -1716,6 +1766,8 @@ pub fn aya::maps::hash_map::PerCpuHashMap::keys(&self) -> aya::maps::Ma impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::insert(&mut self, key: impl core::borrow::Borrow, values: aya::maps::PerCpuValues, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::hash_map::PerCpuHashMap::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> +impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap +pub fn aya::maps::hash_map::PerCpuHashMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V> pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -1824,6 +1876,8 @@ pub fn aya::maps::ProgramArray::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::ProgramArray pub fn aya::maps::ProgramArray::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::ProgramArray::set(&mut self, index: u32, program: &aya::programs::ProgramFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl> aya::maps::ProgramArray +pub fn aya::maps::ProgramArray::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result @@ -1858,6 +1912,8 @@ pub struct aya::maps::Queue impl, V: aya::Pod> aya::maps::queue::Queue pub fn aya::maps::queue::Queue::capacity(&self) -> u32 impl, V: aya::Pod> aya::maps::queue::Queue +pub fn aya::maps::queue::Queue::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::queue::Queue pub fn aya::maps::queue::Queue::pop(&mut self, flags: u64) -> core::result::Result pub fn aya::maps::queue::Queue::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V> @@ -1899,6 +1955,8 @@ pub fn aya::maps::SockHash::keys(&self) -> aya::maps::MapKeys<'_, K> impl, K: aya::Pod> aya::maps::SockHash pub fn aya::maps::SockHash::insert(&mut self, key: impl core::borrow::Borrow, value: I, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::SockHash::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError> +impl, V: aya::Pod> aya::maps::SockHash +pub fn aya::maps::SockHash::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V> pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -1939,6 +1997,8 @@ pub fn aya::maps::SockMap::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::SockMap pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::SockMap::set(&mut self, index: u32, socket: &I, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl> aya::maps::SockMap +pub fn aya::maps::SockMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result @@ -1973,6 +2033,8 @@ pub struct aya::maps::Stack impl, V: aya::Pod> aya::maps::stack::Stack pub fn aya::maps::stack::Stack::capacity(&self) -> u32 impl, V: aya::Pod> aya::maps::stack::Stack +pub fn aya::maps::stack::Stack::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl, V: aya::Pod> aya::maps::stack::Stack pub fn aya::maps::stack::Stack::pop(&mut self, flags: u64) -> core::result::Result pub fn aya::maps::stack::Stack::push(&mut self, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V> @@ -2010,6 +2072,8 @@ impl> aya::maps::stack_trace::StackT pub fn aya::maps::stack_trace::StackTraceMap::get(&self, stack_id: &u32, flags: u64) -> core::result::Result pub fn aya::maps::stack_trace::StackTraceMap::iter(&self) -> aya::maps::MapIter<'_, u32, aya::maps::stack_trace::StackTrace, Self> pub fn aya::maps::stack_trace::StackTraceMap::stack_ids(&self) -> aya::maps::MapKeys<'_, u32> +impl> aya::maps::stack_trace::StackTraceMap +pub fn aya::maps::stack_trace::StackTraceMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::convert::TryFrom for aya::maps::stack_trace::StackTraceMap pub type aya::maps::stack_trace::StackTraceMap::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result @@ -2053,6 +2117,8 @@ pub struct aya::maps::XskMap impl> aya::maps::XskMap pub fn aya::maps::XskMap::len(&self) -> u32 impl> aya::maps::XskMap +pub fn aya::maps::XskMap::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +impl> aya::maps::XskMap pub fn aya::maps::XskMap::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> impl core::convert::TryFrom for aya::maps::XskMap pub type aya::maps::XskMap::Error = aya::maps::MapError @@ -7349,7 +7415,6 @@ pub aya::BpfError::FileError::error: std::io::error::Error pub aya::BpfError::FileError::path: std::path::PathBuf pub aya::BpfError::MapError(aya::maps::MapError) pub aya::BpfError::NoBTF -pub aya::BpfError::NoPinPath pub aya::BpfError::ParseError(aya_obj::obj::ParseError) pub aya::BpfError::ProgramError(aya::programs::ProgramError) pub aya::BpfError::RelocationError(aya_obj::relocation::BpfRelocationError) @@ -7403,6 +7468,7 @@ pub fn aya::Bpf::load_file>(path: P) -> pub fn aya::Bpf::map(&self, name: &str) -> core::option::Option<&aya::maps::Map> pub fn aya::Bpf::map_mut(&mut self, name: &str) -> core::option::Option<&mut aya::maps::Map> pub fn aya::Bpf::maps(&self) -> impl core::iter::traits::iterator::Iterator +pub fn aya::Bpf::maps_mut(&mut self) -> impl core::iter::traits::iterator::Iterator pub fn aya::Bpf::program(&self, name: &str) -> core::option::Option<&aya::programs::Program> pub fn aya::Bpf::program_mut(&mut self, name: &str) -> core::option::Option<&mut aya::programs::Program> pub fn aya::Bpf::programs(&self) -> impl core::iter::traits::iterator::Iterator From 82039144bdf7d46d536b62d94d29268990180294 Mon Sep 17 00:00:00 2001 From: astoycos Date: Fri, 22 Sep 2023 10:37:57 -0400 Subject: [PATCH 68/95] integration-test: Add map pinning coverage Add coverage to the new public api's for map pinning (pin and unpin) which can be called on the generic aya::Map type OR explit map types. Additionally add coverage for the new libbpf LIBBPF_PIN_BY_NAME behavior. Signed-off-by: astoycos --- test/integration-test/bpf/multimap-btf.bpf.c | 11 +++ test/integration-test/src/tests/load.rs | 70 ++++++++++++++++++++ test/integration-test/src/tests/rbpf.rs | 24 ++++--- 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/test/integration-test/bpf/multimap-btf.bpf.c b/test/integration-test/bpf/multimap-btf.bpf.c index f6d34bcf..9e595165 100644 --- a/test/integration-test/bpf/multimap-btf.bpf.c +++ b/test/integration-test/bpf/multimap-btf.bpf.c @@ -17,13 +17,24 @@ struct { __uint(max_entries, 1); } map_2 SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, __u32); + __type(value, __u64); + __uint(max_entries, 1); + __uint(pinning, LIBBPF_PIN_BY_NAME); +} map_pin_by_name SEC(".maps"); + SEC("uprobe") int bpf_prog(void *ctx) { __u32 key = 0; __u64 twenty_four = 24; __u64 forty_two = 42; + __u64 forty_four = 44; + bpf_map_update_elem(&map_1, &key, &twenty_four, BPF_ANY); bpf_map_update_elem(&map_2, &key, &forty_two, BPF_ANY); + bpf_map_update_elem(&map_pin_by_name, &key, &forty_four, BPF_ANY); return 0; } diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 5e193dbf..685867e9 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -1,5 +1,7 @@ use std::{ convert::TryInto as _, + fs::remove_file, + path::Path, thread, time::{Duration, SystemTime}, }; @@ -40,6 +42,8 @@ fn multiple_btf_maps() { let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); + let map_pin_by_name: Array<_, u64> = + bpf.take_map("map_pin_by_name").unwrap().try_into().unwrap(); let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); prog.load().unwrap(); @@ -51,9 +55,75 @@ fn multiple_btf_maps() { let key = 0; let val_1 = map_1.get(&key, 0).unwrap(); let val_2 = map_2.get(&key, 0).unwrap(); + let val_3 = map_pin_by_name.get(&key, 0).unwrap(); assert_eq!(val_1, 24); assert_eq!(val_2, 42); + assert_eq!(val_3, 44); + let map_pin = Path::new("/sys/fs/bpf/map_pin_by_name"); + assert!(&map_pin.exists()); + + remove_file(map_pin).unwrap(); +} + +#[test] +fn pin_lifecycle_multiple_btf_maps() { + let mut bpf = Bpf::load(crate::MULTIMAP_BTF).unwrap(); + + // "map_pin_by_name" should already be pinned, unpin and pin again later + let map_pin_by_name_path = Path::new("/sys/fs/bpf/map_pin_by_name"); + + assert!(map_pin_by_name_path.exists()); + remove_file(map_pin_by_name_path).unwrap(); + + // pin and unpin all maps before casting to explicit types + for (i, (name, map)) in bpf.maps_mut().enumerate() { + // Don't pin system maps or the map that's already pinned by name. + if name.contains(".rodata") || name.contains(".bss") { + continue; + } + let map_pin_path = &Path::new("/sys/fs/bpf/").join(i.to_string()); + + map.pin(map_pin_path).unwrap(); + + assert!(map_pin_path.exists()); + remove_file(map_pin_path).unwrap(); + } + + let mut map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); + let mut map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); + let mut map_pin_by_name: Array<_, u64> = + bpf.take_map("map_pin_by_name").unwrap().try_into().unwrap(); + + let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); + prog.load().unwrap(); + prog.attach(Some("trigger_bpf_program"), 0, "/proc/self/exe", None) + .unwrap(); + + trigger_bpf_program(); + + let key = 0; + let val_1 = map_1.get(&key, 0).unwrap(); + let val_2 = map_2.get(&key, 0).unwrap(); + let val_3 = map_pin_by_name.get(&key, 0).unwrap(); + + assert_eq!(val_1, 24); + assert_eq!(val_2, 42); + assert_eq!(val_3, 44); + + let map_1_pin_path = Path::new("/sys/fs/bpf/map_1"); + let map_2_pin_path = Path::new("/sys/fs/bpf/map_2"); + + map_1.pin(map_1_pin_path).unwrap(); + map_2.pin(map_2_pin_path).unwrap(); + map_pin_by_name.pin(map_pin_by_name_path).unwrap(); + assert!(map_1_pin_path.exists()); + assert!(map_2_pin_path.exists()); + assert!(map_pin_by_name_path.exists()); + + remove_file(map_1_pin_path).unwrap(); + remove_file(map_2_pin_path).unwrap(); + remove_file(map_pin_by_name_path).unwrap(); } #[no_mangle] diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index 3d2c0c97..d2aeafd8 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -34,7 +34,7 @@ fn run_with_rbpf() { assert_eq!(vm.execute_program().unwrap(), XDP_PASS); } -static mut MULTIMAP_MAPS: [*mut Vec; 2] = [null_mut(), null_mut()]; +static mut MULTIMAP_MAPS: [*mut Vec; 3] = [null_mut(); 3]; #[test] fn use_map_with_rbpf() { @@ -47,11 +47,11 @@ fn use_map_with_rbpf() { ); // Initialize maps: - // - fd: 0xCAFE00 or 0xCAFE01 (the 0xCAFE00 part is used to distinguish fds from indices), + // - fd: Bitwise OR of the map_id with 0xCAFE00 (used to distinguish fds from indices), // - Note that rbpf does not convert fds into real pointers, // so we keeps the pointers to our maps in MULTIMAP_MAPS, to be used in helpers. let mut maps = HashMap::new(); - let mut map_instances = vec![vec![0u64], vec![0u64]]; + let mut map_instances = vec![vec![0u64], vec![0u64], vec![0u64]]; for (name, map) in object.maps.iter() { assert_eq!(map.key_size(), size_of::() as u32); assert_eq!(map.value_size(), size_of::() as u32); @@ -60,8 +60,14 @@ fn use_map_with_rbpf() { aya_obj::generated::bpf_map_type::BPF_MAP_TYPE_ARRAY as u32 ); - let map_id = if name == "map_1" { 0 } else { 1 }; - let fd = map_id as std::os::fd::RawFd | 0xCAFE00; + let map_id = match name.as_str() { + "map_1" => 0, + "map_2" => 1, + "map_pin_by_name" => 2, + n => panic!("Unexpected map: {n}"), + }; + + let fd = map_id as i32 | 0xCAFE00; maps.insert(name.to_owned(), (fd, map.clone())); unsafe { @@ -102,18 +108,16 @@ fn use_map_with_rbpf() { .expect("Helper failed"); assert_eq!(vm.execute_program().unwrap(), 0); - assert_eq!(map_instances[0][0], 24); - assert_eq!(map_instances[1][0], 42); + assert_eq!(map_instances, [[24], [42], [44]]); unsafe { - MULTIMAP_MAPS[0] = null_mut(); - MULTIMAP_MAPS[1] = null_mut(); + MULTIMAP_MAPS.iter_mut().for_each(|v| *v = null_mut()); } } #[track_caller] fn bpf_map_update_elem_multimap(map: u64, key: u64, value: u64, _: u64, _: u64) -> u64 { - assert_matches!(map, 0xCAFE00 | 0xCAFE01); + assert_matches!(map, 0xCAFE00 | 0xCAFE01 | 0xCAFE02); let key = *unsafe { (key as usize as *const u32).as_ref().unwrap() }; let value = *unsafe { (value as usize as *const u64).as_ref().unwrap() }; assert_eq!(key, 0); From cc48523347c2be5520779ef8eeadc6d3a68649d0 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 18 Sep 2023 11:46:01 -0400 Subject: [PATCH 69/95] Cargo.toml: remove redundant keys `default-features = false` is already in the root Cargo.toml. --- aya-obj/Cargo.toml | 7 ++----- aya/Cargo.toml | 6 +----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/aya-obj/Cargo.toml b/aya-obj/Cargo.toml index ec830e8d..992793f6 100644 --- a/aya-obj/Cargo.toml +++ b/aya-obj/Cargo.toml @@ -15,11 +15,8 @@ bytes = { workspace = true } core-error = { workspace = true, default-features = true } hashbrown = { workspace = true, default-features = true } log = { workspace = true } -object = { workspace = true, default-features = false, features = [ - "elf", - "read_core", -] } -thiserror = { workspace = true, default-features = false } +object = { workspace = true, features = ["elf", "read_core"] } +thiserror = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } diff --git a/aya/Cargo.toml b/aya/Cargo.toml index 9cdae143..cec83a0f 100644 --- a/aya/Cargo.toml +++ b/aya/Cargo.toml @@ -20,11 +20,7 @@ bytes = { workspace = true } lazy_static = { workspace = true } libc = { workspace = true } log = { workspace = true } -object = { workspace = true, default-features = false, features = [ - "elf", - "read_core", - "std", -] } +object = { workspace = true, features = ["elf", "read_core", "std"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["rt"], optional = true } From 5e637071c130fece2b26f6a7246bdef5f782fced Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 18 Sep 2023 11:46:18 -0400 Subject: [PATCH 70/95] maps: sort variants --- aya/src/maps/mod.rs | 76 ++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 771486c2..02656afa 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -243,44 +243,44 @@ fn maybe_warn_rlimit() { pub enum Map { /// An [`Array`] map. Array(MapData), - /// A [`PerCpuArray`] map. - PerCpuArray(MapData), - /// A [`ProgramArray`] map. - ProgramArray(MapData), + /// A [`BloomFilter`] map. + BloomFilter(MapData), + /// A [`CpuMap`] map. + CpuMap(MapData), + /// A [`DevMap`] map. + DevMap(MapData), + /// A [`DevMapHash`] map. + DevMapHash(MapData), /// A [`HashMap`] map. HashMap(MapData), - /// A [`PerCpuHashMap`] map. - PerCpuHashMap(MapData), + /// A [`LpmTrie`] map. + LpmTrie(MapData), /// A [`HashMap`] map that uses a LRU eviction policy. LruHashMap(MapData), + /// A [`PerCpuArray`] map. + PerCpuArray(MapData), + /// A [`PerCpuHashMap`] map. + PerCpuHashMap(MapData), /// A [`PerCpuHashMap`] map that uses a LRU eviction policy. PerCpuLruHashMap(MapData), /// A [`PerfEventArray`] map. PerfEventArray(MapData), - /// A [`SockMap`] map. - SockMap(MapData), + /// A [`ProgramArray`] map. + ProgramArray(MapData), + /// A [`Queue`] map. + Queue(MapData), /// A [`SockHash`] map. SockHash(MapData), - /// A [`BloomFilter`] map. - BloomFilter(MapData), - /// A [`LpmTrie`] map. - LpmTrie(MapData), + /// A [`SockMap`] map. + SockMap(MapData), /// A [`Stack`] map. Stack(MapData), /// A [`StackTraceMap`] map. StackTraceMap(MapData), - /// A [`Queue`] map. - Queue(MapData), - /// A [`CpuMap`] map. - CpuMap(MapData), - /// A [`DevMap`] map. - DevMap(MapData), - /// A [`DevMapHash`] map. - DevMapHash(MapData), - /// A [`XskMap`] map. - XskMap(MapData), /// An unsupported map type. Unsupported(MapData), + /// A [`XskMap`] map. + XskMap(MapData), } impl Map { @@ -288,25 +288,25 @@ impl Map { fn map_type(&self) -> u32 { match self { Self::Array(map) => map.obj.map_type(), - Self::PerCpuArray(map) => map.obj.map_type(), - Self::ProgramArray(map) => map.obj.map_type(), + Self::BloomFilter(map) => map.obj.map_type(), + Self::CpuMap(map) => map.obj.map_type(), + Self::DevMap(map) => map.obj.map_type(), + Self::DevMapHash(map) => map.obj.map_type(), Self::HashMap(map) => map.obj.map_type(), + Self::LpmTrie(map) => map.obj.map_type(), Self::LruHashMap(map) => map.obj.map_type(), + Self::PerCpuArray(map) => map.obj.map_type(), Self::PerCpuHashMap(map) => map.obj.map_type(), Self::PerCpuLruHashMap(map) => map.obj.map_type(), Self::PerfEventArray(map) => map.obj.map_type(), + Self::ProgramArray(map) => map.obj.map_type(), + Self::Queue(map) => map.obj.map_type(), Self::SockHash(map) => map.obj.map_type(), Self::SockMap(map) => map.obj.map_type(), - Self::BloomFilter(map) => map.obj.map_type(), - Self::LpmTrie(map) => map.obj.map_type(), Self::Stack(map) => map.obj.map_type(), Self::StackTraceMap(map) => map.obj.map_type(), - Self::Queue(map) => map.obj.map_type(), - Self::CpuMap(map) => map.obj.map_type(), - Self::DevMap(map) => map.obj.map_type(), - Self::DevMapHash(map) => map.obj.map_type(), - Self::XskMap(map) => map.obj.map_type(), Self::Unsupported(map) => map.obj.map_type(), + Self::XskMap(map) => map.obj.map_type(), } } @@ -442,13 +442,13 @@ macro_rules! impl_try_from_map { } impl_try_from_map!(() { - ProgramArray, - SockMap, - PerfEventArray, - StackTraceMap, CpuMap, DevMap, DevMapHash, + PerfEventArray, + ProgramArray, + SockMap, + StackTraceMap, XskMap, }); @@ -460,17 +460,17 @@ impl_try_from_map!(() { impl_try_from_map!((V) { Array, - PerCpuArray, - SockHash, BloomFilter, + PerCpuArray, Queue, + SockHash, Stack, }); impl_try_from_map!((K, V) { HashMap from HashMap|LruHashMap, - PerCpuHashMap from PerCpuHashMap|PerCpuLruHashMap, LpmTrie, + PerCpuHashMap from PerCpuHashMap|PerCpuLruHashMap, }); pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> { From 5cdd1baf291f7d98128257a6a73cf8df2c144908 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 11 Oct 2023 10:57:23 -0400 Subject: [PATCH 71/95] aya: import types from std::ffi rather than libc --- aya/src/maps/mod.rs | 4 ++-- aya/src/maps/perf/perf_buffer.rs | 4 ++-- aya/src/sys/bpf.rs | 4 ++-- aya/src/sys/fake.rs | 8 +++++--- aya/src/sys/mod.rs | 3 ++- aya/src/sys/perf_event.rs | 4 ++-- xtask/public-api/aya.txt | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 771486c2..c643ccd6 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -49,7 +49,7 @@ //! implement the [Pod] trait. use std::{ borrow::BorrowMut, - ffi::CString, + ffi::{c_long, CString}, fmt, io, marker::PhantomData, mem, @@ -122,7 +122,7 @@ pub enum MapError { /// Map name name: String, /// Error code - code: libc::c_long, + code: c_long, #[source] /// Original io::Error io_error: io::Error, diff --git a/aya/src/maps/perf/perf_buffer.rs b/aya/src/maps/perf/perf_buffer.rs index 17742320..c3248ab9 100644 --- a/aya/src/maps/perf/perf_buffer.rs +++ b/aya/src/maps/perf/perf_buffer.rs @@ -1,5 +1,5 @@ use std::{ - ffi::c_void, + ffi::{c_int, c_void}, io, mem, os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}, ptr, slice, @@ -7,7 +7,7 @@ use std::{ }; use bytes::BytesMut; -use libc::{c_int, munmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE}; +use libc::{munmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE}; use thiserror::Error; use crate::{ diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index fdcddd07..dd42120a 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -1,6 +1,6 @@ use std::{ cmp, - ffi::{CStr, CString}, + ffi::{c_char, c_long, CStr, CString}, io, iter, mem::{self, MaybeUninit}, os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd, RawFd}, @@ -8,7 +8,7 @@ use std::{ }; use assert_matches::assert_matches; -use libc::{c_char, c_long, ENOENT, ENOSPC}; +use libc::{ENOENT, ENOSPC}; use obj::{ btf::{BtfEnum64, Enum64}, maps::{bpf_map_def, LegacyMap}, diff --git a/aya/src/sys/fake.rs b/aya/src/sys/fake.rs index df2deece..cfd06e4d 100644 --- a/aya/src/sys/fake.rs +++ b/aya/src/sys/fake.rs @@ -1,6 +1,8 @@ -use std::{cell::RefCell, ffi::c_long, io, ptr}; - -use libc::c_void; +use std::{ + cell::RefCell, + ffi::{c_long, c_void}, + io, ptr, +}; use super::{SysResult, Syscall}; diff --git a/aya/src/sys/mod.rs b/aya/src/sys/mod.rs index 641c25ce..b7aac263 100644 --- a/aya/src/sys/mod.rs +++ b/aya/src/sys/mod.rs @@ -6,6 +6,7 @@ mod perf_event; mod fake; use std::{ + ffi::{c_int, c_long}, io, mem, os::fd::{AsRawFd as _, BorrowedFd}, }; @@ -13,7 +14,7 @@ use std::{ pub(crate) use bpf::*; #[cfg(test)] pub(crate) use fake::*; -use libc::{c_int, c_long, pid_t, SYS_bpf, SYS_perf_event_open}; +use libc::{pid_t, SYS_bpf, SYS_perf_event_open}; #[doc(hidden)] pub use netlink::netlink_set_link_up; pub(crate) use netlink::*; diff --git a/aya/src/sys/perf_event.rs b/aya/src/sys/perf_event.rs index ebfcc4a5..b06f4fba 100644 --- a/aya/src/sys/perf_event.rs +++ b/aya/src/sys/perf_event.rs @@ -1,10 +1,10 @@ use std::{ - ffi::{c_long, CString, OsStr}, + ffi::{c_int, c_long, CString, OsStr}, io, mem, os::fd::{BorrowedFd, FromRawFd as _, OwnedFd}, }; -use libc::{c_int, pid_t}; +use libc::pid_t; use super::{syscall, SysResult, Syscall}; use crate::generated::{ diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 81fa16ec..fb3f5b58 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1219,7 +1219,7 @@ impl core::convert::From for aya::maps::Map pub fn aya::maps::Map::from(t: T) -> T pub enum aya::maps::MapError pub aya::maps::MapError::CreateError -pub aya::maps::MapError::CreateError::code: libc::unix::linux_like::linux::gnu::b64::x86_64::not_x32::c_long +pub aya::maps::MapError::CreateError::code: core::ffi::c_long pub aya::maps::MapError::CreateError::io_error: std::io::error::Error pub aya::maps::MapError::CreateError::name: alloc::string::String pub aya::maps::MapError::ElementNotFound From 8462b69716d5918a599933bb9688fa7f57b8ee1d Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 18 Sep 2023 11:46:18 -0400 Subject: [PATCH 72/95] maps: sort variants Missed in 5e637071c130fece2b26f6a7246bdef5f782fced due to merge skew with 7b71c7e1cd8d6948764d02afb0279151c6eae437. --- aya/src/maps/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index f9416b30..45d5a921 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -317,25 +317,25 @@ impl Map { pub fn pin>(&mut self, path: P) -> Result<(), PinError> { match self { Self::Array(map) => map.pin(path), - Self::PerCpuArray(map) => map.pin(path), - Self::ProgramArray(map) => map.pin(path), + Self::BloomFilter(map) => map.pin(path), + Self::CpuMap(map) => map.pin(path), + Self::DevMap(map) => map.pin(path), + Self::DevMapHash(map) => map.pin(path), Self::HashMap(map) => map.pin(path), + Self::LpmTrie(map) => map.pin(path), Self::LruHashMap(map) => map.pin(path), + Self::PerCpuArray(map) => map.pin(path), Self::PerCpuHashMap(map) => map.pin(path), Self::PerCpuLruHashMap(map) => map.pin(path), Self::PerfEventArray(map) => map.pin(path), + Self::ProgramArray(map) => map.pin(path), + Self::Queue(map) => map.pin(path), Self::SockHash(map) => map.pin(path), Self::SockMap(map) => map.pin(path), - Self::BloomFilter(map) => map.pin(path), - Self::LpmTrie(map) => map.pin(path), Self::Stack(map) => map.pin(path), Self::StackTraceMap(map) => map.pin(path), - Self::Queue(map) => map.pin(path), - Self::CpuMap(map) => map.pin(path), - Self::DevMap(map) => map.pin(path), - Self::DevMapHash(map) => map.pin(path), - Self::XskMap(map) => map.pin(path), Self::Unsupported(map) => map.pin(path), + Self::XskMap(map) => map.pin(path), } } } From b73c0a46f572a77d6d05d96d65f638848ac9b132 Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Tue, 11 Jul 2023 11:37:47 -0400 Subject: [PATCH 73/95] aya: impl From for MapTypeError --- aya/src/bpf.rs | 8 ++------ aya/src/maps/mod.rs | 11 +++++++++++ xtask/public-api/aya.txt | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 57162163..540da073 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -710,12 +710,8 @@ impl<'a> BpfLoader<'a> { } fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { - let name = data.0; - let map = data.1; - let map_type = - bpf_map_type::try_from(map.obj().map_type()).map_err(|e| MapError::InvalidMapType { - map_type: e.map_type, - })?; + let (name, map) = data; + let map_type = bpf_map_type::try_from(map.obj().map_type()).map_err(MapError::from)?; let map = match map_type { BPF_MAP_TYPE_ARRAY => Map::Array(map), BPF_MAP_TYPE_PERCPU_ARRAY => Map::PerCpuArray(map), diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 45d5a921..ee6acb82 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -61,6 +61,7 @@ use std::{ use libc::{getrlimit, rlim_t, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; use log::warn; +use obj::maps::InvalidMapTypeError; use thiserror::Error; use crate::{ @@ -193,6 +194,16 @@ pub enum MapError { }, } +// Note that this is not just derived using #[from] because InvalidMapTypeError cannot implement +// Error due the the fact that aya-obj is no_std and error_in_core is not stabilized +// (https://github.com/rust-lang/rust/issues/103765). +impl From for MapError { + fn from(e: InvalidMapTypeError) -> Self { + let InvalidMapTypeError { map_type } = e; + Self::InvalidMapType { map_type } + } +} + /// A map file descriptor. #[derive(Debug)] pub struct MapFd(OwnedFd); diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index fb3f5b58..6891b279 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1251,6 +1251,8 @@ impl core::convert::From for aya::maps::xdp::XdpMapError pub fn aya::maps::xdp::XdpMapError::from(source: aya::maps::MapError) -> Self impl core::convert::From for aya::programs::ProgramError pub fn aya::programs::ProgramError::from(source: aya::maps::MapError) -> Self +impl core::convert::From for aya::maps::MapError +pub fn aya::maps::MapError::from(e: aya_obj::maps::InvalidMapTypeError) -> Self impl core::error::Error for aya::maps::MapError pub fn aya::maps::MapError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> impl core::fmt::Display for aya::maps::MapError From 4af9d1bd3ea8dd638bddeb2ae2a8ccea6d11b249 Mon Sep 17 00:00:00 2001 From: William Findlay Date: Fri, 22 Oct 2021 11:33:38 -0400 Subject: [PATCH 74/95] aya: move mmap from perf_buffer.rs to sys/mod.rs mmap() is needed for the ring buffer implementation, so move it to a common module --- aya/src/maps/perf/perf_buffer.rs | 23 ++--------------------- aya/src/sys/mod.rs | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/aya/src/maps/perf/perf_buffer.rs b/aya/src/maps/perf/perf_buffer.rs index c3248ab9..c50bbb86 100644 --- a/aya/src/maps/perf/perf_buffer.rs +++ b/aya/src/maps/perf/perf_buffer.rs @@ -1,5 +1,5 @@ use std::{ - ffi::{c_int, c_void}, + ffi::c_void, io, mem, os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}, ptr, slice, @@ -15,7 +15,7 @@ use crate::{ perf_event_header, perf_event_mmap_page, perf_event_type::{PERF_RECORD_LOST, PERF_RECORD_SAMPLE}, }, - sys::{perf_event_ioctl, perf_event_open_bpf, SysResult}, + sys::{mmap, perf_event_ioctl, perf_event_open_bpf, SysResult}, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, }; @@ -282,25 +282,6 @@ impl Drop for PerfBuffer { } } -#[cfg_attr(test, allow(unused_variables))] -unsafe fn mmap( - addr: *mut c_void, - len: usize, - prot: c_int, - flags: c_int, - fd: BorrowedFd<'_>, - offset: libc::off_t, -) -> *mut c_void { - #[cfg(not(test))] - return libc::mmap(addr, len, prot, flags, fd.as_raw_fd(), offset); - - #[cfg(test)] - use crate::sys::TEST_MMAP_RET; - - #[cfg(test)] - TEST_MMAP_RET.with(|ret| *ret.borrow()) -} - #[derive(Debug)] #[repr(C)] struct Sample { diff --git a/aya/src/sys/mod.rs b/aya/src/sys/mod.rs index b7aac263..0b22463a 100644 --- a/aya/src/sys/mod.rs +++ b/aya/src/sys/mod.rs @@ -6,7 +6,7 @@ mod perf_event; mod fake; use std::{ - ffi::{c_int, c_long}, + ffi::{c_int, c_long, c_void}, io, mem, os::fd::{AsRawFd as _, BorrowedFd}, }; @@ -115,3 +115,19 @@ fn syscall(call: Syscall<'_>) -> SysResult { ret => Err((ret, io::Error::last_os_error())), } } + +#[cfg_attr(test, allow(unused_variables))] +pub(crate) unsafe fn mmap( + addr: *mut c_void, + len: usize, + prot: c_int, + flags: c_int, + fd: BorrowedFd<'_>, + offset: libc::off_t, +) -> *mut c_void { + #[cfg(not(test))] + return libc::mmap(addr, len, prot, flags, fd.as_raw_fd(), offset); + + #[cfg(test)] + TEST_MMAP_RET.with(|ret| *ret.borrow()) +} From e2cf734490bc188bcedb1eac92d23d81123e42cd Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Tue, 11 Jul 2023 11:30:01 -0400 Subject: [PATCH 75/95] aya: Implement RingBuf This implements the userspace binding for RingBuf. Instead of streaming the samples as heap buffers, the process_ring function takes a callback to which we pass the event's byte region, roughly following [libbpf]'s API design. This avoids a copy and allows marking the consumer pointer in a timely manner. [libbpf]: https://github.com/libbpf/libbpf/blob/master/src/ringbuf.c Additionally, integration tests are added to demonstrate the usage of the new APIs and to ensure that they work end-to-end. Co-authored-by: William Findlay Co-authored-by: Tatsuyuki Ishi --- Cargo.toml | 4 + aya/src/bpf.rs | 136 +++++- aya/src/maps/mod.rs | 9 +- aya/src/maps/ring_buf.rs | 458 ++++++++++++++++++++ bpf/aya-bpf/Cargo.toml | 8 + bpf/aya-bpf/src/lib.rs | 5 + bpf/aya-bpf/src/maps/mod.rs | 2 + bpf/aya-bpf/src/maps/ring_buf.rs | 163 +++++++ test/integration-ebpf/Cargo.toml | 4 + test/integration-ebpf/src/ring_buf.rs | 59 +++ test/integration-test/Cargo.toml | 7 +- test/integration-test/src/lib.rs | 1 + test/integration-test/src/tests.rs | 1 + test/integration-test/src/tests/ring_buf.rs | 441 +++++++++++++++++++ xtask/public-api/aya-bpf.txt | 87 ++++ xtask/public-api/aya.txt | 110 +++++ 16 files changed, 1474 insertions(+), 21 deletions(-) create mode 100644 aya/src/maps/ring_buf.rs create mode 100644 bpf/aya-bpf/src/maps/ring_buf.rs create mode 100644 test/integration-ebpf/src/ring_buf.rs create mode 100644 test/integration-test/src/tests/ring_buf.rs diff --git a/Cargo.toml b/Cargo.toml index b534f567..cfda2f5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,10 +62,13 @@ bitflags = { version = "2.2.1", default-features = false } bytes = { version = "1", default-features = false } cargo_metadata = { version = "0.18.0", default-features = false } clap = { version = "4", default-features = false } +const-assert = { version = "1.0.1", default-features = false } core-error = { version = "0.0.0", default-features = false } dialoguer = { version = "0.11", default-features = false } diff = { version = "0.1.13", default-features = false } env_logger = { version = "0.10", default-features = false } +epoll = { version = "4.3.3", default-features = false } +futures = { version = "0.3.28", default-features = false } hashbrown = { version = "0.14", default-features = false } indoc = { version = "2.0", default-features = false } integration-ebpf = { path = "test/integration-ebpf", default-features = false } @@ -80,6 +83,7 @@ proc-macro-error = { version = "1.0", default-features = false } proc-macro2 = { version = "1", default-features = false } public-api = { version = "0.32.0", default-features = false } quote = { version = "1", default-features = false } +rand = { version = "0.8", default-features = false } rbpf = { version = "0.2.0", default-features = false } rustdoc-json = { version = "0.8.6", default-features = false } rustup-toolchain = { version = "0.1.5", default-features = false } diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 540da073..6086dfa3 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -43,7 +43,7 @@ use crate::{ is_probe_read_kernel_supported, is_prog_id_supported, is_prog_name_supported, retry_with_verifier_logs, }, - util::{bytes_of, bytes_of_slice, possible_cpus, POSSIBLE_CPUS}, + util::{bytes_of, bytes_of_slice, page_size, possible_cpus, POSSIBLE_CPUS}, }; pub(crate) const BPF_OBJ_NAME_LEN: usize = 16; @@ -461,23 +461,23 @@ impl<'a> BpfLoader<'a> { { continue; } - - match max_entries.get(name.as_str()) { - Some(size) => obj.set_max_entries(*size), - None => { - if obj.map_type() == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 - && obj.max_entries() == 0 - { - obj.set_max_entries( - possible_cpus() - .map_err(|error| BpfError::FileError { - path: PathBuf::from(POSSIBLE_CPUS), - error, - })? - .len() as u32, - ); - } - } + let num_cpus = || -> Result { + Ok(possible_cpus() + .map_err(|error| BpfError::FileError { + path: PathBuf::from(POSSIBLE_CPUS), + error, + })? + .len() as u32) + }; + let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; + if let Some(max_entries) = max_entries_override( + map_type, + max_entries.get(name.as_str()).copied(), + || obj.max_entries(), + num_cpus, + || page_size() as u32, + )? { + obj.set_max_entries(max_entries) } match obj.map_type().try_into() { Ok(BPF_MAP_TYPE_CPUMAP) => { @@ -721,6 +721,7 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { BPF_MAP_TYPE_PERCPU_HASH => Map::PerCpuHashMap(map), BPF_MAP_TYPE_LRU_PERCPU_HASH => Map::PerCpuLruHashMap(map), BPF_MAP_TYPE_PERF_EVENT_ARRAY => Map::PerfEventArray(map), + BPF_MAP_TYPE_RINGBUF => Map::RingBuf(map), BPF_MAP_TYPE_SOCKHASH => Map::SockHash(map), BPF_MAP_TYPE_SOCKMAP => Map::SockMap(map), BPF_MAP_TYPE_BLOOM_FILTER => Map::BloomFilter(map), @@ -741,6 +742,105 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { Ok((name, map)) } +/// Computes the value which should be used to override the max_entries value of the map +/// based on the user-provided override and the rules for that map type. +fn max_entries_override( + map_type: bpf_map_type, + user_override: Option, + current_value: impl Fn() -> u32, + num_cpus: impl Fn() -> Result, + page_size: impl Fn() -> u32, +) -> Result, BpfError> { + let max_entries = || user_override.unwrap_or_else(¤t_value); + Ok(match map_type { + BPF_MAP_TYPE_PERF_EVENT_ARRAY if max_entries() == 0 => Some(num_cpus()?), + BPF_MAP_TYPE_RINGBUF => Some(adjust_to_page_size(max_entries(), page_size())) + .filter(|adjusted| *adjusted != max_entries()) + .or(user_override), + _ => user_override, + }) +} + +// Adjusts the byte size of a RingBuf map to match a power-of-two multiple of the page size. +// +// This mirrors the logic used by libbpf. +// See https://github.com/libbpf/libbpf/blob/ec6f716eda43/src/libbpf.c#L2461-L2463 +fn adjust_to_page_size(byte_size: u32, page_size: u32) -> u32 { + // If the byte_size is zero, return zero and let the verifier reject the map + // when it is loaded. This is the behavior of libbpf. + if byte_size == 0 { + return 0; + } + // TODO: Replace with primitive method when int_roundings (https://github.com/rust-lang/rust/issues/88581) + // is stabilized. + fn div_ceil(n: u32, rhs: u32) -> u32 { + let d = n / rhs; + let r = n % rhs; + if r > 0 && rhs > 0 { + d + 1 + } else { + d + } + } + let pages_needed = div_ceil(byte_size, page_size); + page_size * pages_needed.next_power_of_two() +} + +#[cfg(test)] +mod tests { + use crate::generated::bpf_map_type::*; + + const PAGE_SIZE: u32 = 4096; + const NUM_CPUS: u32 = 4; + + #[test] + fn test_adjust_to_page_size() { + use super::adjust_to_page_size; + [ + (0, 0), + (4096, 1), + (4096, 4095), + (4096, 4096), + (8192, 4097), + (8192, 8192), + (16384, 8193), + ] + .into_iter() + .for_each(|(exp, input)| assert_eq!(exp, adjust_to_page_size(input, PAGE_SIZE))) + } + + #[test] + fn test_max_entries_override() { + use super::max_entries_override; + [ + (BPF_MAP_TYPE_RINGBUF, Some(1), 1, Some(PAGE_SIZE)), + (BPF_MAP_TYPE_RINGBUF, None, 1, Some(PAGE_SIZE)), + (BPF_MAP_TYPE_RINGBUF, None, PAGE_SIZE, None), + (BPF_MAP_TYPE_PERF_EVENT_ARRAY, None, 1, None), + (BPF_MAP_TYPE_PERF_EVENT_ARRAY, Some(42), 1, Some(42)), + (BPF_MAP_TYPE_PERF_EVENT_ARRAY, Some(0), 1, Some(NUM_CPUS)), + (BPF_MAP_TYPE_PERF_EVENT_ARRAY, None, 0, Some(NUM_CPUS)), + (BPF_MAP_TYPE_PERF_EVENT_ARRAY, None, 42, None), + (BPF_MAP_TYPE_ARRAY, None, 1, None), + (BPF_MAP_TYPE_ARRAY, Some(2), 1, Some(2)), + ] + .into_iter() + .for_each(|(map_type, user_override, current_value, exp)| { + assert_eq!( + exp, + max_entries_override( + map_type, + user_override, + || { current_value }, + || Ok(NUM_CPUS), + || PAGE_SIZE + ) + .unwrap() + ) + }) + } +} + impl Default for BpfLoader<'_> { fn default() -> Self { BpfLoader::new() diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index ee6acb82..a934d361 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -81,6 +81,7 @@ pub mod hash_map; pub mod lpm_trie; pub mod perf; pub mod queue; +pub mod ring_buf; pub mod sock; pub mod stack; pub mod stack_trace; @@ -95,6 +96,7 @@ pub use lpm_trie::LpmTrie; pub use perf::AsyncPerfEventArray; pub use perf::PerfEventArray; pub use queue::Queue; +pub use ring_buf::RingBuf; pub use sock::{SockHash, SockMap}; pub use stack::Stack; pub use stack_trace::StackTraceMap; @@ -280,7 +282,9 @@ pub enum Map { ProgramArray(MapData), /// A [`Queue`] map. Queue(MapData), - /// A [`SockHash`] map. + /// A [`RingBuf`] map. + RingBuf(MapData), + /// A [`SockHash`] map SockHash(MapData), /// A [`SockMap`] map. SockMap(MapData), @@ -312,6 +316,7 @@ impl Map { Self::PerfEventArray(map) => map.obj.map_type(), Self::ProgramArray(map) => map.obj.map_type(), Self::Queue(map) => map.obj.map_type(), + Self::RingBuf(map) => map.obj.map_type(), Self::SockHash(map) => map.obj.map_type(), Self::SockMap(map) => map.obj.map_type(), Self::Stack(map) => map.obj.map_type(), @@ -341,6 +346,7 @@ impl Map { Self::PerfEventArray(map) => map.pin(path), Self::ProgramArray(map) => map.pin(path), Self::Queue(map) => map.pin(path), + Self::RingBuf(map) => map.pin(path), Self::SockHash(map) => map.pin(path), Self::SockMap(map) => map.pin(path), Self::Stack(map) => map.pin(path), @@ -458,6 +464,7 @@ impl_try_from_map!(() { DevMapHash, PerfEventArray, ProgramArray, + RingBuf, SockMap, StackTraceMap, XskMap, diff --git a/aya/src/maps/ring_buf.rs b/aya/src/maps/ring_buf.rs new file mode 100644 index 00000000..16f4c175 --- /dev/null +++ b/aya/src/maps/ring_buf.rs @@ -0,0 +1,458 @@ +//! A [ring buffer map][ringbuf] that may be used to receive events from eBPF programs. +//! As of Linux 5.8, this is the preferred way to transfer per-event data from eBPF +//! programs to userspace. +//! +//! [ringbuf]: https://www.kernel.org/doc/html/latest/bpf/ringbuf.html + +use std::{ + borrow::Borrow, + ffi::{c_int, c_void}, + fmt::{self, Debug, Formatter}, + io, mem, + ops::Deref, + os::fd::{AsFd as _, AsRawFd, BorrowedFd, RawFd}, + ptr, + ptr::NonNull, + slice, + sync::atomic::{AtomicU32, AtomicUsize, Ordering}, +}; + +use libc::{munmap, off_t, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE}; + +use crate::{ + generated::{BPF_RINGBUF_BUSY_BIT, BPF_RINGBUF_DISCARD_BIT, BPF_RINGBUF_HDR_SZ}, + maps::{MapData, MapError}, + sys::{mmap, SyscallError}, + util::page_size, +}; + +/// A map that can be used to receive events from eBPF programs. +/// +/// This is similar to [`crate::maps::PerfEventArray`], but different in a few ways: +/// * It's shared across all CPUs, which allows a strong ordering between events. +/// * Data notifications are delivered precisely instead of being sampled for every N events; the +/// eBPF program can also control notification delivery if sampling is desired for performance +/// reasons. By default, a notification will be sent if the consumer is caught up at the time of +/// committing. The eBPF program can use the `BPF_RB_NO_WAKEUP` or `BPF_RB_FORCE_WAKEUP` flags to +/// control this behavior. +/// * On the eBPF side, it supports the reverse-commit pattern where the event can be directly +/// written into the ring without copying from a temporary location. +/// * Dropped sample notifications go to the eBPF program as the return value of `reserve`/`output`, +/// and not the userspace reader. This might require extra code to handle, but allows for more +/// flexible schemes to handle dropped samples. +/// +/// To receive events you need to: +/// * Construct [`RingBuf`] using [`RingBuf::try_from`]. +/// * Call [`RingBuf::next`] to poll events from the [`RingBuf`]. +/// +/// To receive async notifications of data availability, you may construct an +/// [`tokio::io::unix::AsyncFd`] from the [`RingBuf`]'s file descriptor and poll it for readiness. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 5.8. +/// +/// # Examples +/// +/// ```no_run +/// # struct PollFd(T); +/// # fn poll_fd(t: T) -> PollFd { PollFd(t) } +/// # impl PollFd { +/// # fn readable(&mut self) -> Guard<'_, T> { Guard(self) } +/// # } +/// # struct Guard<'a, T>(&'a mut PollFd); +/// # impl Guard<'_, T> { +/// # fn inner_mut(&mut self) -> &mut T { +/// # let Guard(PollFd(t)) = self; +/// # t +/// # } +/// # fn clear_ready(&mut self) {} +/// # } +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::RingBuf; +/// use std::convert::TryFrom; +/// +/// let ring_buf = RingBuf::try_from(bpf.map_mut("ARRAY")?)?; +/// let poll = poll_fd(ring_buf); +/// loop { +/// let mut guard = poll.readable()?; +/// let ring_buf = guard.inner_mut() +/// while let Some(item) = ring_buf.next() { +/// println!("Received: {:?}", item); +/// } +/// guard.clear_ready(); +/// } +/// # Ok::<(), aya::BpfError>(()) +/// ``` +/// +/// # Polling +/// +/// In the example above the implementations of poll(), poll.readable(), guard.inner_mut(), and +/// guard.clear_ready() are not given. RingBuf implements the AsRawFd trait, so you can implement +/// polling using any crate that can poll file descriptors, like epoll, mio etc. The above example +/// API is motivated by that of [`tokio::io::unix::AsyncFd`]. +#[doc(alias = "BPF_MAP_TYPE_RINGBUF")] +pub struct RingBuf { + map: T, + consumer: ConsumerPos, + producer: ProducerData, +} + +impl> RingBuf { + pub(crate) fn new(map: T) -> Result { + let data: &MapData = map.borrow(); + let page_size = page_size(); + let map_fd = data.fd().as_fd(); + let byte_size = data.obj.max_entries(); + let consumer_metadata = ConsumerMetadata::new(map_fd, 0, page_size)?; + let consumer = ConsumerPos::new(consumer_metadata); + let producer = ProducerData::new(map_fd, page_size, page_size, byte_size)?; + Ok(Self { + map, + consumer, + producer, + }) + } +} + +impl RingBuf { + /// Try to take a new entry from the ringbuf. + /// + /// Returns `Some(item)` if the ringbuf is not empty. Returns `None` if the ringbuf is empty, in + /// which case the caller may register for availability notifications through `epoll` or other + /// APIs. Only one RingBufItem may be outstanding at a time. + // + // This is not an implementation of `Iterator` because we need to be able to refer to the + // lifetime of the iterator in the returned `RingBufItem`. If the Iterator::Item leveraged GATs, + // one could imagine an implementation of `Iterator` that would work. GATs are stabilized in + // Rust 1.65, but there's not yet a trait that the community seems to have standardized around. + #[allow(clippy::should_implement_trait)] + pub fn next(&mut self) -> Option> { + let Self { + consumer, producer, .. + } = self; + producer.next(consumer) + } +} + +/// Access to the RawFd can be used to construct an AsyncFd for use with epoll. +impl> AsRawFd for RingBuf { + fn as_raw_fd(&self) -> RawFd { + let Self { + map, + consumer: _, + producer: _, + } = self; + map.borrow().fd().as_fd().as_raw_fd() + } +} + +/// The current outstanding item read from the ringbuf. +pub struct RingBufItem<'a> { + data: &'a [u8], + consumer: &'a mut ConsumerPos, +} + +impl Deref for RingBufItem<'_> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + let Self { data, .. } = self; + data + } +} + +impl Drop for RingBufItem<'_> { + fn drop(&mut self) { + let Self { consumer, data } = self; + consumer.consume(data.len()) + } +} + +impl Debug for RingBufItem<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let Self { + data, + consumer: + ConsumerPos { + pos, + metadata: ConsumerMetadata { mmap: _ }, + }, + } = self; + // In general Relaxed here is sufficient, for debugging, it certainly is. + f.debug_struct("RingBufItem") + .field("pos", pos) + .field("len", &data.len()) + .finish() + } +} + +struct ConsumerMetadata { + mmap: MMap, +} + +impl ConsumerMetadata { + fn new(fd: BorrowedFd<'_>, offset: usize, page_size: usize) -> Result { + let mmap = MMap::new( + fd, + page_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + offset.try_into().unwrap(), + )?; + Ok(Self { mmap }) + } +} + +impl AsRef for ConsumerMetadata { + fn as_ref(&self) -> &AtomicUsize { + let Self { + mmap: MMap { ptr, .. }, + } = self; + unsafe { ptr.cast::().as_ref() } + } +} + +struct ConsumerPos { + pos: usize, + metadata: ConsumerMetadata, +} + +impl ConsumerPos { + fn new(metadata: ConsumerMetadata) -> Self { + // Load the initial value of the consumer position. SeqCst is used to be safe given we don't + // have any claims about memory synchronization performed by some previous writer. + let pos = metadata.as_ref().load(Ordering::SeqCst); + Self { pos, metadata } + } + + fn consume(&mut self, len: usize) { + let Self { pos, metadata } = self; + + // TODO: Use primitive method when https://github.com/rust-lang/rust/issues/88581 is stabilized. + fn next_multiple_of(n: usize, multiple: usize) -> usize { + match n % multiple { + 0 => n, + rem => n + (multiple - rem), + } + } + *pos += next_multiple_of(usize::try_from(BPF_RINGBUF_HDR_SZ).unwrap() + len, 8); + + // Write operation needs to be properly ordered with respect to the producer committing new + // data to the ringbuf. The producer uses xchg (SeqCst) to commit new data [1]. The producer + // reads the consumer offset after clearing the busy bit on a new entry [2]. By using SeqCst + // here we ensure that either a subsequent read by the consumer to consume messages will see + // an available message, or the producer in the kernel will see the updated consumer offset + // that is caught up. + // + // [1]: https://github.com/torvalds/linux/blob/2772d7df/kernel/bpf/ringbuf.c#L487-L488 + // [2]: https://github.com/torvalds/linux/blob/2772d7df/kernel/bpf/ringbuf.c#L494 + metadata.as_ref().store(*pos, Ordering::SeqCst); + } +} + +struct ProducerData { + mmap: MMap, + + // Offset in the mmap where the data starts. + data_offset: usize, + + // A cache of the value of the producer position. It is used to avoid re-reading the producer + // position when we know there is more data to consume. + pos_cache: usize, + + // A bitmask which truncates u32 values to the domain of valid offsets in the ringbuf. + mask: u32, +} + +impl ProducerData { + fn new( + fd: BorrowedFd<'_>, + offset: usize, + page_size: usize, + byte_size: u32, + ) -> Result { + // The producer pages have one page of metadata and then the data pages, all mapped + // read-only. Note that the length of the mapping includes the data pages twice as the + // kernel will map them two time consecutively to avoid special handling of entries that + // cross over the end of the ring buffer. + // + // The kernel diagram below shows the layout of the ring buffer. It references "meta pages", + // but we only map exactly one producer meta page read-only. The consumer meta page is mapped + // read-write elsewhere, and is taken into consideration via the offset parameter. + // + // From kernel/bpf/ringbuf.c[0]: + // + // Each data page is mapped twice to allow "virtual" + // continuous read of samples wrapping around the end of ring + // buffer area: + // ------------------------------------------------------ + // | meta pages | real data pages | same data pages | + // ------------------------------------------------------ + // | | 1 2 3 4 5 6 7 8 9 | 1 2 3 4 5 6 7 8 9 | + // ------------------------------------------------------ + // | | TA DA | TA DA | + // ------------------------------------------------------ + // ^^^^^^^ + // | + // Here, no need to worry about special handling of wrapped-around + // data due to double-mapped data pages. This works both in kernel and + // when mmap()'ed in user-space, simplifying both kernel and + // user-space implementations significantly. + // + // [0]: https://github.com/torvalds/linux/blob/3f01e9fe/kernel/bpf/ringbuf.c#L108-L124 + let len = page_size + 2 * usize::try_from(byte_size).unwrap(); + let mmap = MMap::new(fd, len, PROT_READ, MAP_SHARED, offset.try_into().unwrap())?; + + // byte_size is required to be a power of two multiple of page_size (which implicitly is a + // power of 2), so subtracting one will create a bitmask for values less than byte_size. + debug_assert!(byte_size.is_power_of_two()); + let mask = byte_size - 1; + Ok(Self { + mmap, + data_offset: page_size, + pos_cache: 0, + mask, + }) + } + + fn next<'a>(&'a mut self, consumer: &'a mut ConsumerPos) -> Option> { + let Self { + ref mmap, + data_offset, + pos_cache, + mask, + } = self; + let pos = unsafe { mmap.ptr.cast().as_ref() }; + let mmap_data = mmap.as_ref(); + let data_pages = mmap_data.get(*data_offset..).unwrap_or_else(|| { + panic!( + "offset {} out of bounds, data len {}", + data_offset, + mmap_data.len() + ) + }); + while data_available(pos, pos_cache, consumer) { + match read_item(data_pages, *mask, consumer) { + Item::Busy => return None, + Item::Discard { len } => consumer.consume(len), + Item::Data(data) => return Some(RingBufItem { data, consumer }), + } + } + return None; + + enum Item<'a> { + Busy, + Discard { len: usize }, + Data(&'a [u8]), + } + + fn data_available( + producer: &AtomicUsize, + cache: &mut usize, + consumer: &ConsumerPos, + ) -> bool { + let ConsumerPos { pos: consumer, .. } = consumer; + if consumer == cache { + // This value is written using Release by the kernel [1], and should be read with + // Acquire to ensure that the prior writes to the entry header are visible. + // + // [1]: https://github.com/torvalds/linux/blob/eb26cbb1/kernel/bpf/ringbuf.c#L447-L448 + *cache = producer.load(Ordering::Acquire); + } + + // Note that we don't compare the order of the values because the producer position may + // overflow u32 and wrap around to 0. Instead we just compare equality and assume that + // the consumer position is always logically less than the producer position. + // + // Note also that the kernel, at the time of writing [1], doesn't seem to handle this + // overflow correctly at all, and it's not clear that one can produce events after the + // producer position has wrapped around. + // + // [1]: https://github.com/torvalds/linux/blob/4b810bf0/kernel/bpf/ringbuf.c#L434-L440 + consumer != cache + } + + fn read_item<'data>(data: &'data [u8], mask: u32, pos: &ConsumerPos) -> Item<'data> { + let ConsumerPos { pos, .. } = pos; + let offset = pos & usize::try_from(mask).unwrap(); + let must_get_data = |offset, len| { + data.get(offset..offset + len).unwrap_or_else(|| { + panic!("{:?} not in {:?}", offset..offset + len, 0..data.len()) + }) + }; + let header_ptr = + must_get_data(offset, mem::size_of::()).as_ptr() as *const AtomicU32; + // Pair the kernel's SeqCst write (implies Release) [1] with an Acquire load. This + // ensures data written by the producer will be visible. + // + // [1]: https://github.com/torvalds/linux/blob/eb26cbb1/kernel/bpf/ringbuf.c#L488 + let header = unsafe { &*header_ptr }.load(Ordering::Acquire); + if header & BPF_RINGBUF_BUSY_BIT != 0 { + Item::Busy + } else { + let len = usize::try_from(header & mask).unwrap(); + if header & BPF_RINGBUF_DISCARD_BIT != 0 { + Item::Discard { len } + } else { + let data_offset = offset + usize::try_from(BPF_RINGBUF_HDR_SZ).unwrap(); + let data = must_get_data(data_offset, len); + Item::Data(data) + } + } + } + } +} + +// MMap corresponds to a memory-mapped region. +// +// The data is unmapped in Drop. +struct MMap { + ptr: NonNull, + len: usize, +} + +impl MMap { + fn new( + fd: BorrowedFd<'_>, + len: usize, + prot: c_int, + flags: c_int, + offset: off_t, + ) -> Result { + match unsafe { mmap(ptr::null_mut(), len, prot, flags, fd, offset) } { + MAP_FAILED => Err(MapError::SyscallError(SyscallError { + call: "mmap", + io_error: io::Error::last_os_error(), + })), + ptr => Ok(Self { + ptr: ptr::NonNull::new(ptr).ok_or( + // This should never happen, but to be paranoid, and so we never need to talk + // about a null pointer, we check it anyway. + MapError::SyscallError(SyscallError { + call: "mmap", + io_error: io::Error::new( + io::ErrorKind::Other, + "mmap returned null pointer", + ), + }), + )?, + len, + }), + } + } +} + +impl AsRef<[u8]> for MMap { + fn as_ref(&self) -> &[u8] { + let Self { ptr, len } = self; + unsafe { slice::from_raw_parts(ptr.as_ptr().cast(), *len) } + } +} + +impl Drop for MMap { + fn drop(&mut self) { + let Self { ptr, len } = *self; + unsafe { munmap(ptr.as_ptr(), len) }; + } +} diff --git a/bpf/aya-bpf/Cargo.toml b/bpf/aya-bpf/Cargo.toml index 0af23767..b586d9c5 100644 --- a/bpf/aya-bpf/Cargo.toml +++ b/bpf/aya-bpf/Cargo.toml @@ -8,6 +8,14 @@ edition = "2021" aya-bpf-cty = { path = "../aya-bpf-cty" } aya-bpf-macros = { path = "../../aya-bpf-macros" } aya-bpf-bindings = { path = "../aya-bpf-bindings" } +const-assert = { workspace = true, optional = true } [build-dependencies] rustversion = { workspace = true } + +[features] +default = [] +# TODO(https://github.com/rust-lang/rust/issues/76560): Always utilize the +# logic gated behind this feature. This is not currently possible because the +# underlying `const_generic_exprs` language feature is still incomplete. +const_assert = ["const-assert"] diff --git a/bpf/aya-bpf/src/lib.rs b/bpf/aya-bpf/src/lib.rs index a10833a3..d482de0c 100644 --- a/bpf/aya-bpf/src/lib.rs +++ b/bpf/aya-bpf/src/lib.rs @@ -8,6 +8,11 @@ html_logo_url = "https://aya-rs.dev/assets/images/crabby.svg", html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg" )] +#![cfg_attr( + feature = "const_assert", + allow(incomplete_features), + feature(generic_const_exprs) +)] #![cfg_attr(unstable, feature(never_type))] #![cfg_attr(target_arch = "bpf", feature(asm_experimental_arch))] #![allow(clippy::missing_safety_doc)] diff --git a/bpf/aya-bpf/src/maps/mod.rs b/bpf/aya-bpf/src/maps/mod.rs index b46bf084..ead24dc3 100644 --- a/bpf/aya-bpf/src/maps/mod.rs +++ b/bpf/aya-bpf/src/maps/mod.rs @@ -13,6 +13,7 @@ pub mod per_cpu_array; pub mod perf; pub mod program_array; pub mod queue; +pub mod ring_buf; pub mod sock_hash; pub mod sock_map; pub mod stack; @@ -27,6 +28,7 @@ pub use per_cpu_array::PerCpuArray; pub use perf::{PerfEventArray, PerfEventByteArray}; pub use program_array::ProgramArray; pub use queue::Queue; +pub use ring_buf::RingBuf; pub use sock_hash::SockHash; pub use sock_map::SockMap; pub use stack::Stack; diff --git a/bpf/aya-bpf/src/maps/ring_buf.rs b/bpf/aya-bpf/src/maps/ring_buf.rs new file mode 100644 index 00000000..ee544efe --- /dev/null +++ b/bpf/aya-bpf/src/maps/ring_buf.rs @@ -0,0 +1,163 @@ +use core::{ + cell::UnsafeCell, + mem, + mem::MaybeUninit, + ops::{Deref, DerefMut}, +}; + +#[cfg(feature = "const_assert")] +use const_assert::{Assert, IsTrue}; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_RINGBUF}, + helpers::{ + bpf_ringbuf_discard, bpf_ringbuf_output, bpf_ringbuf_query, bpf_ringbuf_reserve, + bpf_ringbuf_submit, + }, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct RingBuf { + def: UnsafeCell, +} + +unsafe impl Sync for RingBuf {} + +/// A ring buffer entry, returned from [`RingBuf::reserve`]. +/// +/// You must [`submit`] or [`discard`] this entry before it gets dropped. +/// +/// [`submit`]: RingBufEntry::submit +/// [`discard`]: RingBufEntry::discard +#[must_use = "eBPF verifier requires ring buffer entries to be either submitted or discarded"] +pub struct RingBufEntry(&'static mut MaybeUninit); + +impl Deref for RingBufEntry { + type Target = MaybeUninit; + + fn deref(&self) -> &Self::Target { + self.0 + } +} + +impl DerefMut for RingBufEntry { + fn deref_mut(&mut self) -> &mut Self::Target { + self.0 + } +} + +impl RingBufEntry { + /// Discard this ring buffer entry. The entry will be skipped by the userspace reader. + pub fn discard(self, flags: u64) { + unsafe { bpf_ringbuf_discard(self.0.as_mut_ptr() as *mut _, flags) }; + } + + /// Commit this ring buffer entry. The entry will be made visible to the userspace reader. + pub fn submit(self, flags: u64) { + unsafe { bpf_ringbuf_submit(self.0.as_mut_ptr() as *mut _, flags) }; + } +} + +impl RingBuf { + /// Declare an eBPF ring buffer. + /// + /// The linux kernel requires that `byte_size` be a power-of-2 multiple of the page size. The + /// loading program may coerce the size when loading the map. + pub const fn with_byte_size(byte_size: u32, flags: u32) -> Self { + Self::new(byte_size, flags, PinningType::None) + } + + /// Declare a pinned eBPF ring buffer. + /// + /// The linux kernel requires that `byte_size` be a power-of-2 multiple of the page size. The + /// loading program may coerce the size when loading the map. + pub const fn pinned(byte_size: u32, flags: u32) -> Self { + Self::new(byte_size, flags, PinningType::ByName) + } + + const fn new(byte_size: u32, flags: u32, pinning_type: PinningType) -> Self { + Self { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_RINGBUF, + key_size: 0, + value_size: 0, + max_entries: byte_size, + map_flags: flags, + id: 0, + pinning: pinning_type as u32, + }), + } + } + + /// Reserve memory in the ring buffer that can fit `T`. + /// + /// Returns `None` if the ring buffer is full. + #[cfg(feature = "const_assert")] + pub fn reserve(&self, flags: u64) -> Option> + where + Assert<{ 8 % mem::align_of::() == 0 }>: IsTrue, + { + self.reserve_impl(flags) + } + + /// Reserve memory in the ring buffer that can fit `T`. + /// + /// Returns `None` if the ring buffer is full. + /// + /// The kernel will reserve memory at an 8-bytes aligned boundary, so `mem::align_of()` must + /// be equal or smaller than 8. If you use this with a `T` that isn't properly aligned, this + /// function will be compiled to a panic; depending on your panic_handler, this may make + /// the eBPF program fail to load, or it may make it have undefined behavior. + #[cfg(not(feature = "const_assert"))] + pub fn reserve(&self, flags: u64) -> Option> { + assert_eq!(8 % mem::align_of::(), 0); + self.reserve_impl(flags) + } + + fn reserve_impl(&self, flags: u64) -> Option> { + let ptr = unsafe { + bpf_ringbuf_reserve(self.def.get() as *mut _, mem::size_of::() as _, flags) + } as *mut MaybeUninit; + unsafe { ptr.as_mut() }.map(|ptr| RingBufEntry(ptr)) + } + + /// Copy `data` to the ring buffer output. + /// + /// Consider using [`reserve`] and [`submit`] if `T` is statically sized and you want to save a + /// copy from either a map buffer or the stack. + /// + /// Unlike [`reserve`], this function can handle dynamically sized types (which is hard to + /// create in eBPF but still possible, e.g. by slicing an array). + /// + /// Note: `T` must be aligned to no more than 8 bytes; it's not possible to fulfill larger + /// alignment requests. If you use this with a `T` that isn't properly aligned, this function will + /// be compiled to a panic and silently make your eBPF program fail to load. + /// See [here](https://github.com/torvalds/linux/blob/3f01e9fed/kernel/bpf/ringbuf.c#L418). + /// + /// [`reserve`]: RingBuf::reserve + /// [`submit`]: RingBufEntry::submit + pub fn output(&self, data: &T, flags: u64) -> Result<(), i64> { + assert_eq!(8 % mem::align_of_val(data), 0); + let ret = unsafe { + bpf_ringbuf_output( + self.def.get() as *mut _, + data as *const _ as *mut _, + mem::size_of_val(data) as _, + flags, + ) + }; + if ret < 0 { + Err(ret) + } else { + Ok(()) + } + } + + /// Query various information about the ring buffer. + /// + /// Consult `bpf_ringbuf_query` documentation for a list of allowed flags. + pub fn query(&self, flags: u64) -> u64 { + unsafe { bpf_ringbuf_query(self.def.get() as *mut _, flags) } + } +} diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index e72e0a87..d471acf3 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -51,3 +51,7 @@ path = "src/redirect.rs" [[bin]] name = "xdp_sec" path = "src/xdp_sec.rs" + +[[bin]] +name = "ring_buf" +path = "src/ring_buf.rs" diff --git a/test/integration-ebpf/src/ring_buf.rs b/test/integration-ebpf/src/ring_buf.rs new file mode 100644 index 00000000..ff9a21a0 --- /dev/null +++ b/test/integration-ebpf/src/ring_buf.rs @@ -0,0 +1,59 @@ +#![no_std] +#![no_main] + +use aya_bpf::{ + macros::{map, uprobe}, + maps::{PerCpuArray, RingBuf}, + programs::ProbeContext, +}; + +#[map] +static RING_BUF: RingBuf = RingBuf::with_byte_size(0, 0); + +// This structure's definition is duplicated in userspace. +#[repr(C)] +struct Registers { + dropped: u64, + rejected: u64, +} + +// Use a PerCpuArray to store the registers so that we can update the values from multiple CPUs +// without needing synchronization. Atomics exist [1], but aren't exposed. +// +// [1]: https://lwn.net/Articles/838884/ +#[map] +static REGISTERS: PerCpuArray = PerCpuArray::with_max_entries(1, 0); + +#[uprobe] +pub fn ring_buf_test(ctx: ProbeContext) { + let Registers { dropped, rejected } = match REGISTERS.get_ptr_mut(0) { + Some(regs) => unsafe { &mut *regs }, + None => return, + }; + let mut entry = match RING_BUF.reserve::(0) { + Some(entry) => entry, + None => { + *dropped += 1; + return; + } + }; + // Write the first argument to the function back out to RING_BUF if it is even, + // otherwise increment the counter in REJECTED. This exercises discarding data. + let arg: u64 = match ctx.arg(0) { + Some(arg) => arg, + None => return, + }; + if arg % 2 == 0 { + entry.write(arg); + entry.submit(0); + } else { + *rejected += 1; + entry.discard(0); + } +} + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml index 4d1a466b..4db38be6 100644 --- a/test/integration-test/Cargo.toml +++ b/test/integration-test/Cargo.toml @@ -10,13 +10,16 @@ assert_matches = { workspace = true } aya = { workspace = true } aya-log = { workspace = true } aya-obj = { workspace = true } +epoll = { workspace = true } +futures = { workspace = true, features = ["std"] } libc = { workspace = true } log = { workspace = true } netns-rs = { workspace = true } -object = { workspace = true } +object = { workspace = true, features = ["elf", "read_core", "std"] } +rand = { workspace = true, features = ["std", "std_rng"] } rbpf = { workspace = true } test-case = { workspace = true } -tokio = { workspace = true, features = ["macros", "time"] } +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } [build-dependencies] cargo_metadata = { workspace = true } diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 79be5fd3..d4708033 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -21,6 +21,7 @@ pub const BPF_PROBE_READ: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/bpf_probe_read")); pub const REDIRECT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/redirect")); pub const XDP_SEC: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/xdp_sec")); +pub const RING_BUF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/ring_buf")); #[cfg(test)] mod tests; diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index 3a995180..f37d54bb 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -5,5 +5,6 @@ mod load; mod log; mod rbpf; mod relocations; +mod ring_buf; mod smoke; mod xdp; diff --git a/test/integration-test/src/tests/ring_buf.rs b/test/integration-test/src/tests/ring_buf.rs new file mode 100644 index 00000000..ca222848 --- /dev/null +++ b/test/integration-test/src/tests/ring_buf.rs @@ -0,0 +1,441 @@ +use std::{ + mem, + os::fd::AsRawFd as _, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread, +}; + +use anyhow::Context as _; +use assert_matches::assert_matches; +use aya::{ + maps::{array::PerCpuArray, ring_buf::RingBuf, MapData}, + programs::UProbe, + Bpf, BpfLoader, Pod, +}; +use aya_obj::generated::BPF_RINGBUF_HDR_SZ; +use rand::Rng as _; +use tokio::{ + io::unix::AsyncFd, + time::{sleep, Duration}, +}; + +// This structure's definition is duplicated in the probe. +#[repr(C)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)] +struct Registers { + dropped: u64, + rejected: u64, +} + +impl std::ops::Add for Registers { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + Self { + dropped: self.dropped + rhs.dropped, + rejected: self.rejected + rhs.rejected, + } + } +} + +impl<'a> std::iter::Sum<&'a Registers> for Registers { + fn sum>(iter: I) -> Self { + iter.fold(Default::default(), |a, b| a + *b) + } +} + +unsafe impl Pod for Registers {} + +struct RingBufTest { + _bpf: Bpf, + ring_buf: RingBuf, + regs: PerCpuArray, +} + +// Note that it is important for this test that RING_BUF_MAX_ENTRIES ends up creating a ring buffer +// that is exactly a power-of-two multiple of the page size. The synchronous test will fail if +// that's not the case because the actual size will be rounded up, and fewer entries will be dropped +// than expected. +const RING_BUF_MAX_ENTRIES: usize = 512; + +impl RingBufTest { + fn new() -> Self { + const RING_BUF_BYTE_SIZE: u32 = + (RING_BUF_MAX_ENTRIES * (mem::size_of::() + BPF_RINGBUF_HDR_SZ as usize)) as u32; + + // Use the loader API to control the size of the ring_buf. + let mut bpf = BpfLoader::new() + .set_max_entries("RING_BUF", RING_BUF_BYTE_SIZE) + .load(crate::RING_BUF) + .unwrap(); + let ring_buf = bpf.take_map("RING_BUF").unwrap(); + let ring_buf = RingBuf::try_from(ring_buf).unwrap(); + let regs = bpf.take_map("REGISTERS").unwrap(); + let regs = PerCpuArray::<_, Registers>::try_from(regs).unwrap(); + let prog: &mut UProbe = bpf + .program_mut("ring_buf_test") + .unwrap() + .try_into() + .unwrap(); + prog.load().unwrap(); + prog.attach( + Some("ring_buf_trigger_ebpf_program"), + 0, + "/proc/self/exe", + None, + ) + .unwrap(); + + Self { + _bpf: bpf, + ring_buf, + regs, + } + } +} + +struct WithData(RingBufTest, Vec); + +impl WithData { + fn new(n: usize) -> Self { + Self(RingBufTest::new(), { + let mut rng = rand::thread_rng(); + std::iter::repeat_with(|| rng.gen()).take(n).collect() + }) + } +} + +#[test_case::test_case(0; "write zero items")] +#[test_case::test_case(1; "write one item")] +#[test_case::test_case(RING_BUF_MAX_ENTRIES / 2; "write half the capacity items")] +#[test_case::test_case(RING_BUF_MAX_ENTRIES - 1; "write one less than capacity items")] +#[test_case::test_case(RING_BUF_MAX_ENTRIES * 8; "write more items than capacity")] +fn ring_buf(n: usize) { + let WithData( + RingBufTest { + mut ring_buf, + regs, + _bpf, + }, + data, + ) = WithData::new(n); + + // Note that after expected_capacity has been submitted, reserve calls in the probe will fail + // and the probe will give up. + let expected_capacity = RING_BUF_MAX_ENTRIES - 1; + + // Call the function that the uprobe is attached to with the data. + let mut expected = Vec::new(); + let mut expected_rejected = 0u64; + let mut expected_dropped = 0u64; + for (i, &v) in data.iter().enumerate() { + ring_buf_trigger_ebpf_program(v); + if i >= expected_capacity { + expected_dropped += 1; + } else if v % 2 == 0 { + expected.push(v); + } else { + expected_rejected += 1; + } + } + + let mut seen = Vec::::new(); + while seen.len() < expected.len() { + if let Some(read) = ring_buf.next() { + let read: [u8; 8] = (*read) + .try_into() + .with_context(|| format!("data: {:?}", read.len())) + .unwrap(); + let arg = u64::from_ne_bytes(read); + assert_eq!(arg % 2, 0, "got {arg} from probe"); + seen.push(arg); + } + } + + // Make sure that there is nothing else in the ring_buf. + assert_matches!(ring_buf.next(), None); + + // Ensure that the data that was read matches what was passed, and the rejected count was set + // properly. + assert_eq!(seen, expected); + let Registers { dropped, rejected } = regs.get(&0, 0).unwrap().iter().sum(); + assert_eq!(dropped, expected_dropped); + assert_eq!(rejected, expected_rejected); +} + +#[no_mangle] +#[inline(never)] +pub extern "C" fn ring_buf_trigger_ebpf_program(arg: u64) { + std::hint::black_box(arg); +} + +// This test differs from the other async test in that it's possible for the producer +// to fill the ring_buf. We just ensure that the number of events we see is sane given +// what the producer sees, and that the logic does not hang. This exercises interleaving +// discards, successful commits, and drops due to the ring_buf being full. +#[tokio::test(flavor = "multi_thread")] +async fn ring_buf_async_with_drops() { + let WithData( + RingBufTest { + ring_buf, + regs, + _bpf, + }, + data, + ) = WithData::new(RING_BUF_MAX_ENTRIES * 8); + + let mut async_fd = AsyncFd::new(ring_buf).unwrap(); + + // Spawn the writer which internally will spawn many parallel writers. + // Construct an AsyncFd from the RingBuf in order to receive readiness notifications. + let mut seen = 0; + let mut process_ring_buf = |ring_buf: &mut RingBuf<_>| { + while let Some(read) = ring_buf.next() { + let read: [u8; 8] = (*read) + .try_into() + .with_context(|| format!("data: {:?}", read.len())) + .unwrap(); + let arg = u64::from_ne_bytes(read); + assert_eq!(arg % 2, 0, "got {arg} from probe"); + seen += 1; + } + }; + use futures::future::{ + select, + Either::{Left, Right}, + }; + let writer = futures::future::try_join_all(data.chunks(8).map(ToOwned::to_owned).map(|v| { + tokio::spawn(async { + for value in v { + ring_buf_trigger_ebpf_program(value); + } + }) + })); + let readable = { + let mut writer = writer; + loop { + let readable = Box::pin(async_fd.readable_mut()); + writer = match select(readable, writer).await { + Left((guard, writer)) => { + let mut guard = guard.unwrap(); + process_ring_buf(guard.get_inner_mut()); + guard.clear_ready(); + writer + } + Right((writer, readable)) => { + writer.unwrap(); + break readable; + } + } + } + }; + + // If there's more to read, we should receive a readiness notification in a timely manner. + // If we don't then, then assert that there's nothing else to read. Note that it's important + // to wait some time before attempting to read, otherwise we may catch up with the producer + // before epoll has an opportunity to send a notification; our consumer thread can race + // with the kernel epoll check. + let sleep_fut = sleep(Duration::from_millis(10)); + tokio::pin!(sleep_fut); + match select(sleep_fut, readable).await { + Left(((), _)) => {} + Right((guard, _)) => { + let mut guard = guard.unwrap(); + process_ring_buf(guard.get_inner_mut()); + guard.clear_ready(); + } + } + + // Make sure that there is nothing else in the ring_buf. + assert_matches!(async_fd.into_inner().next(), None); + + let max_dropped: u64 = u64::try_from( + data.len() + .checked_sub(RING_BUF_MAX_ENTRIES - 1) + .unwrap_or_default(), + ) + .unwrap(); + let max_seen = u64::try_from(data.iter().filter(|v| *v % 2 == 0).count()).unwrap(); + let max_rejected = u64::try_from(data.len()).unwrap() - max_seen; + let Registers { dropped, rejected } = regs.get(&0, 0).unwrap().iter().sum(); + let total = u64::try_from(data.len()).unwrap(); + let min_seen = max_seen.checked_sub(max_dropped).unwrap_or_default(); + let min_rejected = max_rejected.checked_sub(dropped).unwrap_or_default(); + let facts = format!( + "seen={seen}, rejected={rejected}, dropped={dropped}, total={total}, max_seen={max_seen}, \ + max_rejected={max_rejected}, max_dropped={max_dropped}", + ); + assert_eq!(seen + rejected + dropped, total, "{facts}",); + assert!( + (0u64..=max_dropped).contains(&dropped), + "dropped={dropped} not in 0..={max_dropped}; {facts}", + ); + assert!( + (min_rejected..=max_rejected).contains(&rejected), + "rejected={rejected} not in {min_rejected}..={max_rejected}; {facts}", + ); + assert!( + (min_seen..=max_seen).contains(&seen), + "seen={seen} not in {min_seen}..={max_seen}, rejected={rejected}; {facts}", + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn ring_buf_async_no_drop() { + let WithData( + RingBufTest { + ring_buf, + regs, + _bpf, + }, + data, + ) = WithData::new(RING_BUF_MAX_ENTRIES * 3); + + let writer = { + let data = data.to_owned(); + tokio::spawn(async move { + for value in data { + // Sleep a tad so we feel confident that the consumer will keep up + // and no messages will be dropped. + let dur = Duration::from_nanos(rand::thread_rng().gen_range(0..10)); + sleep(dur).await; + ring_buf_trigger_ebpf_program(value); + } + }) + }; + + // Construct an AsyncFd from the RingBuf in order to receive readiness notifications. + let mut async_fd = AsyncFd::new(ring_buf).unwrap(); + // Note that unlike in the synchronous case where all of the entries are written before any of + // them are read, in this case we expect all of the entries to make their way to userspace + // because entries are being consumed as they are produced. + let expected: Vec = data.iter().cloned().filter(|v| *v % 2 == 0).collect(); + let expected_len = expected.len(); + let reader = async move { + let mut seen = Vec::with_capacity(expected_len); + while seen.len() < expected_len { + let mut guard = async_fd.readable_mut().await.unwrap(); + let ring_buf = guard.get_inner_mut(); + while let Some(read) = ring_buf.next() { + let read: [u8; 8] = (*read) + .try_into() + .with_context(|| format!("data: {:?}", read.len())) + .unwrap(); + let arg = u64::from_ne_bytes(read); + seen.push(arg); + } + guard.clear_ready(); + } + (seen, async_fd.into_inner()) + }; + let (writer, (seen, mut ring_buf)) = futures::future::join(writer, reader).await; + writer.unwrap(); + + // Make sure that there is nothing else in the ring_buf. + assert_matches!(ring_buf.next(), None); + + // Ensure that the data that was read matches what was passed. + assert_eq!(&seen, &expected); + let Registers { dropped, rejected } = regs.get(&0, 0).unwrap().iter().sum(); + assert_eq!(dropped, 0); + assert_eq!(rejected, (data.len() - expected.len()).try_into().unwrap()); +} + +// This test reproduces a bug where the ring buffer would not be notified of new entries if the +// state was not properly synchronized between the producer and consumer. This would result in the +// consumer never being woken up and the test hanging. +#[test] +fn ring_buf_epoll_wakeup() { + let RingBufTest { + mut ring_buf, + _bpf, + regs: _, + } = RingBufTest::new(); + + let epoll_fd = epoll::create(false).unwrap(); + epoll::ctl( + epoll_fd, + epoll::ControlOptions::EPOLL_CTL_ADD, + ring_buf.as_raw_fd(), + // The use of EPOLLET is intentional. Without it, level-triggering would result in + // more notifications, and would mask the underlying bug this test reproduced when + // the synchronization logic in the RingBuf mirrored that of libbpf. Also, tokio's + // AsyncFd always uses this flag (as demonstrated in the subsequent test). + epoll::Event::new(epoll::Events::EPOLLIN | epoll::Events::EPOLLET, 0), + ) + .unwrap(); + let mut epoll_event_buf = [epoll::Event::new(epoll::Events::EPOLLIN, 0); 1]; + let mut total_events: u64 = 0; + let writer = WriterThread::spawn(); + while total_events < WriterThread::NUM_MESSAGES { + epoll::wait(epoll_fd, -1, &mut epoll_event_buf).unwrap(); + while let Some(read) = ring_buf.next() { + assert_eq!(read.len(), 8); + total_events += 1; + } + } + writer.join(); +} + +// This test is like the above test but uses tokio and AsyncFd instead of raw epoll. +#[tokio::test] +async fn ring_buf_asyncfd_events() { + let RingBufTest { + ring_buf, + regs: _, + _bpf, + } = RingBufTest::new(); + + let mut async_fd = AsyncFd::new(ring_buf).unwrap(); + let mut total_events = 0; + let writer = WriterThread::spawn(); + while total_events < WriterThread::NUM_MESSAGES { + let mut guard = async_fd.readable_mut().await.unwrap(); + let rb = guard.get_inner_mut(); + while let Some(read) = rb.next() { + assert_eq!(read.len(), 8); + total_events += 1; + } + guard.clear_ready(); + } + writer.join(); +} + +// WriterThread triggers the ring_buf write continuously until the join() method is called. It is +// used by both the epoll and async fd test that need frequent writes to the ring buffer to trigger +// the memory synchronization bug that was fixed. +struct WriterThread { + thread: thread::JoinHandle<()>, + done: Arc, +} + +impl WriterThread { + // When the ring buffer implementation uses Ordering::Relaxed to write the consumer position + // rather than Ordering::SeqCst, the test will hang. This number was determined to be large + // enough to tickle that bug on a hardware accelerated VM with 2 vCPUs. + const NUM_MESSAGES: u64 = 20_000; + + fn spawn() -> Self { + let done = Arc::new(AtomicBool::new(false)); + Self { + thread: { + let done = done.clone(); + thread::spawn(move || { + while !done.load(Ordering::Relaxed) { + // Write 0 which is even and won't be rejected. + ring_buf_trigger_ebpf_program(0); + } + }) + }, + done, + } + } + + fn join(self) { + let Self { thread, done } = self; + done.store(true, Ordering::Relaxed); + thread.join().unwrap(); + } +} diff --git a/xtask/public-api/aya-bpf.txt b/xtask/public-api/aya-bpf.txt index e221d2cc..ba5ea3d8 100644 --- a/xtask/public-api/aya-bpf.txt +++ b/xtask/public-api/aya-bpf.txt @@ -448,6 +448,65 @@ impl core::borrow::BorrowMut for aya_bpf::maps::queue::Queue where T: c pub fn aya_bpf::maps::queue::Queue::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::queue::Queue pub fn aya_bpf::maps::queue::Queue::from(t: T) -> T +pub mod aya_bpf::maps::ring_buf +#[repr(transparent)] pub struct aya_bpf::maps::ring_buf::RingBuf +impl aya_bpf::maps::ring_buf::RingBuf +pub fn aya_bpf::maps::ring_buf::RingBuf::output(&self, data: &T, flags: u64) -> core::result::Result<(), i64> +pub const fn aya_bpf::maps::ring_buf::RingBuf::pinned(byte_size: u32, flags: u32) -> Self +pub fn aya_bpf::maps::ring_buf::RingBuf::query(&self, flags: u64) -> u64 +pub fn aya_bpf::maps::ring_buf::RingBuf::reserve(&self, flags: u64) -> core::option::Option> where const_assert::Assert<{ _ }>: const_assert::IsTrue +pub const fn aya_bpf::maps::ring_buf::RingBuf::with_byte_size(byte_size: u32, flags: u32) -> Self +impl core::marker::Sync for aya_bpf::maps::ring_buf::RingBuf +impl core::marker::Send for aya_bpf::maps::ring_buf::RingBuf +impl core::marker::Unpin for aya_bpf::maps::ring_buf::RingBuf +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::ring_buf::RingBuf +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::ring_buf::RingBuf +impl core::convert::Into for aya_bpf::maps::ring_buf::RingBuf where U: core::convert::From +pub fn aya_bpf::maps::ring_buf::RingBuf::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::ring_buf::RingBuf where U: core::convert::Into +pub type aya_bpf::maps::ring_buf::RingBuf::Error = core::convert::Infallible +pub fn aya_bpf::maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::ring_buf::RingBuf where U: core::convert::TryFrom +pub type aya_bpf::maps::ring_buf::RingBuf::Error = >::Error +pub fn aya_bpf::maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::ring_buf::RingBuf where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBuf::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::ring_buf::RingBuf +pub fn aya_bpf::maps::ring_buf::RingBuf::from(t: T) -> T +pub struct aya_bpf::maps::ring_buf::RingBufEntry(_) +impl aya_bpf::maps::ring_buf::RingBufEntry +pub fn aya_bpf::maps::ring_buf::RingBufEntry::discard(self, flags: u64) +pub fn aya_bpf::maps::ring_buf::RingBufEntry::submit(self, flags: u64) +impl core::ops::deref::Deref for aya_bpf::maps::ring_buf::RingBufEntry +pub type aya_bpf::maps::ring_buf::RingBufEntry::Target = core::mem::maybe_uninit::MaybeUninit +pub fn aya_bpf::maps::ring_buf::RingBufEntry::deref(&self) -> &Self::Target +impl core::ops::deref::DerefMut for aya_bpf::maps::ring_buf::RingBufEntry +pub fn aya_bpf::maps::ring_buf::RingBufEntry::deref_mut(&mut self) -> &mut Self::Target +impl core::marker::Send for aya_bpf::maps::ring_buf::RingBufEntry where T: core::marker::Send +impl core::marker::Sync for aya_bpf::maps::ring_buf::RingBufEntry where T: core::marker::Sync +impl core::marker::Unpin for aya_bpf::maps::ring_buf::RingBufEntry +impl core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::ring_buf::RingBufEntry where T: core::panic::unwind_safe::RefUnwindSafe +impl !core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::ring_buf::RingBufEntry +impl core::convert::Into for aya_bpf::maps::ring_buf::RingBufEntry where U: core::convert::From +pub fn aya_bpf::maps::ring_buf::RingBufEntry::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::ring_buf::RingBufEntry where U: core::convert::Into +pub type aya_bpf::maps::ring_buf::RingBufEntry::Error = core::convert::Infallible +pub fn aya_bpf::maps::ring_buf::RingBufEntry::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::ring_buf::RingBufEntry where U: core::convert::TryFrom +pub type aya_bpf::maps::ring_buf::RingBufEntry::Error = >::Error +pub fn aya_bpf::maps::ring_buf::RingBufEntry::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::ring_buf::RingBufEntry where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBufEntry::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::ring_buf::RingBufEntry where T: core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBufEntry::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::ring_buf::RingBufEntry where T: core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBufEntry::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::ring_buf::RingBufEntry +pub fn aya_bpf::maps::ring_buf::RingBufEntry::from(t: T) -> T pub mod aya_bpf::maps::sock_hash #[repr(transparent)] pub struct aya_bpf::maps::sock_hash::SockHash impl aya_bpf::maps::sock_hash::SockHash @@ -1091,6 +1150,34 @@ impl core::borrow::BorrowMut for aya_bpf::maps::queue::Queue where T: c pub fn aya_bpf::maps::queue::Queue::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::queue::Queue pub fn aya_bpf::maps::queue::Queue::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::RingBuf +impl aya_bpf::maps::ring_buf::RingBuf +pub fn aya_bpf::maps::ring_buf::RingBuf::output(&self, data: &T, flags: u64) -> core::result::Result<(), i64> +pub const fn aya_bpf::maps::ring_buf::RingBuf::pinned(byte_size: u32, flags: u32) -> Self +pub fn aya_bpf::maps::ring_buf::RingBuf::query(&self, flags: u64) -> u64 +pub fn aya_bpf::maps::ring_buf::RingBuf::reserve(&self, flags: u64) -> core::option::Option> where const_assert::Assert<{ _ }>: const_assert::IsTrue +pub const fn aya_bpf::maps::ring_buf::RingBuf::with_byte_size(byte_size: u32, flags: u32) -> Self +impl core::marker::Sync for aya_bpf::maps::ring_buf::RingBuf +impl core::marker::Send for aya_bpf::maps::ring_buf::RingBuf +impl core::marker::Unpin for aya_bpf::maps::ring_buf::RingBuf +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::ring_buf::RingBuf +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::ring_buf::RingBuf +impl core::convert::Into for aya_bpf::maps::ring_buf::RingBuf where U: core::convert::From +pub fn aya_bpf::maps::ring_buf::RingBuf::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::ring_buf::RingBuf where U: core::convert::Into +pub type aya_bpf::maps::ring_buf::RingBuf::Error = core::convert::Infallible +pub fn aya_bpf::maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::ring_buf::RingBuf where U: core::convert::TryFrom +pub type aya_bpf::maps::ring_buf::RingBuf::Error = >::Error +pub fn aya_bpf::maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::ring_buf::RingBuf where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBuf::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya_bpf::maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::ring_buf::RingBuf +pub fn aya_bpf::maps::ring_buf::RingBuf::from(t: T) -> T #[repr(transparent)] pub struct aya_bpf::maps::SockHash impl aya_bpf::maps::sock_hash::SockHash pub const fn aya_bpf::maps::sock_hash::SockHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::sock_hash::SockHash diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 6891b279..b2b28876 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -572,6 +572,71 @@ impl core::borrow::BorrowMut for aya::maps::queue::Queue where T: co pub fn aya::maps::queue::Queue::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::queue::Queue pub fn aya::maps::queue::Queue::from(t: T) -> T +pub mod aya::maps::ring_buf +pub struct aya::maps::ring_buf::RingBuf +impl aya::maps::ring_buf::RingBuf +pub fn aya::maps::ring_buf::RingBuf::next(&mut self) -> core::option::Option> +impl core::convert::TryFrom for aya::maps::ring_buf::RingBuf +pub type aya::maps::ring_buf::RingBuf::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData> +pub type aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData> +pub type aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl> std::os::fd::raw::AsRawFd for aya::maps::ring_buf::RingBuf +pub fn aya::maps::ring_buf::RingBuf::as_raw_fd(&self) -> std::os::fd::raw::RawFd +impl !core::marker::Send for aya::maps::ring_buf::RingBuf +impl !core::marker::Sync for aya::maps::ring_buf::RingBuf +impl core::marker::Unpin for aya::maps::ring_buf::RingBuf where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::ring_buf::RingBuf where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::ring_buf::RingBuf where U: core::convert::From +pub fn aya::maps::ring_buf::RingBuf::into(self) -> U +impl core::convert::TryFrom for aya::maps::ring_buf::RingBuf where U: core::convert::Into +pub type aya::maps::ring_buf::RingBuf::Error = core::convert::Infallible +pub fn aya::maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::ring_buf::RingBuf where U: core::convert::TryFrom +pub type aya::maps::ring_buf::RingBuf::Error = >::Error +pub fn aya::maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::ring_buf::RingBuf where T: 'static + core::marker::Sized +pub fn aya::maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya::maps::ring_buf::RingBuf::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya::maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::ring_buf::RingBuf +pub fn aya::maps::ring_buf::RingBuf::from(t: T) -> T +pub struct aya::maps::ring_buf::RingBufItem<'a> +impl core::fmt::Debug for aya::maps::ring_buf::RingBufItem<'_> +pub fn aya::maps::ring_buf::RingBufItem<'_>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::ops::deref::Deref for aya::maps::ring_buf::RingBufItem<'_> +pub type aya::maps::ring_buf::RingBufItem<'_>::Target = [u8] +pub fn aya::maps::ring_buf::RingBufItem<'_>::deref(&self) -> &Self::Target +impl core::ops::drop::Drop for aya::maps::ring_buf::RingBufItem<'_> +pub fn aya::maps::ring_buf::RingBufItem<'_>::drop(&mut self) +impl<'a> !core::marker::Send for aya::maps::ring_buf::RingBufItem<'a> +impl<'a> !core::marker::Sync for aya::maps::ring_buf::RingBufItem<'a> +impl<'a> core::marker::Unpin for aya::maps::ring_buf::RingBufItem<'a> +impl<'a> core::panic::unwind_safe::RefUnwindSafe for aya::maps::ring_buf::RingBufItem<'a> +impl<'a> !core::panic::unwind_safe::UnwindSafe for aya::maps::ring_buf::RingBufItem<'a> +impl core::convert::Into for aya::maps::ring_buf::RingBufItem<'a> where U: core::convert::From +pub fn aya::maps::ring_buf::RingBufItem<'a>::into(self) -> U +impl core::convert::TryFrom for aya::maps::ring_buf::RingBufItem<'a> where U: core::convert::Into +pub type aya::maps::ring_buf::RingBufItem<'a>::Error = core::convert::Infallible +pub fn aya::maps::ring_buf::RingBufItem<'a>::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::ring_buf::RingBufItem<'a> where U: core::convert::TryFrom +pub type aya::maps::ring_buf::RingBufItem<'a>::Error = >::Error +pub fn aya::maps::ring_buf::RingBufItem<'a>::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::ring_buf::RingBufItem<'a> where T: 'static + core::marker::Sized +pub fn aya::maps::ring_buf::RingBufItem<'a>::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::ring_buf::RingBufItem<'a> where T: core::marker::Sized +pub fn aya::maps::ring_buf::RingBufItem<'a>::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::ring_buf::RingBufItem<'a> where T: core::marker::Sized +pub fn aya::maps::ring_buf::RingBufItem<'a>::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::ring_buf::RingBufItem<'a> +pub fn aya::maps::ring_buf::RingBufItem<'a>::from(t: T) -> T pub mod aya::maps::sock pub struct aya::maps::sock::SockHash impl, K: aya::Pod> aya::maps::SockHash @@ -1024,6 +1089,7 @@ pub aya::maps::Map::PerCpuLruHashMap(aya::maps::MapData) pub aya::maps::Map::PerfEventArray(aya::maps::MapData) pub aya::maps::Map::ProgramArray(aya::maps::MapData) pub aya::maps::Map::Queue(aya::maps::MapData) +pub aya::maps::Map::RingBuf(aya::maps::MapData) pub aya::maps::Map::SockHash(aya::maps::MapData) pub aya::maps::Map::SockMap(aya::maps::MapData) pub aya::maps::Map::Stack(aya::maps::MapData) @@ -1056,6 +1122,9 @@ pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: a impl core::convert::TryFrom for aya::maps::perf::PerfEventArray pub type aya::maps::perf::PerfEventArray::Error = aya::maps::MapError pub fn aya::maps::perf::PerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::ring_buf::RingBuf +pub type aya::maps::ring_buf::RingBuf::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::stack_trace::StackTraceMap pub type aya::maps::stack_trace::StackTraceMap::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap::try_from(map: aya::maps::Map) -> core::result::Result @@ -1137,6 +1206,9 @@ pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(ma impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData> +pub type aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -1164,6 +1236,9 @@ pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_fro impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::perf::PerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData> +pub type aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result @@ -1948,6 +2023,41 @@ impl core::borrow::BorrowMut for aya::maps::queue::Queue where T: co pub fn aya::maps::queue::Queue::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::queue::Queue pub fn aya::maps::queue::Queue::from(t: T) -> T +pub struct aya::maps::RingBuf +impl aya::maps::ring_buf::RingBuf +pub fn aya::maps::ring_buf::RingBuf::next(&mut self) -> core::option::Option> +impl core::convert::TryFrom for aya::maps::ring_buf::RingBuf +pub type aya::maps::ring_buf::RingBuf::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData> +pub type aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData> +pub type aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::ring_buf::RingBuf<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl> std::os::fd::raw::AsRawFd for aya::maps::ring_buf::RingBuf +pub fn aya::maps::ring_buf::RingBuf::as_raw_fd(&self) -> std::os::fd::raw::RawFd +impl !core::marker::Send for aya::maps::ring_buf::RingBuf +impl !core::marker::Sync for aya::maps::ring_buf::RingBuf +impl core::marker::Unpin for aya::maps::ring_buf::RingBuf where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::ring_buf::RingBuf where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::ring_buf::RingBuf where U: core::convert::From +pub fn aya::maps::ring_buf::RingBuf::into(self) -> U +impl core::convert::TryFrom for aya::maps::ring_buf::RingBuf where U: core::convert::Into +pub type aya::maps::ring_buf::RingBuf::Error = core::convert::Infallible +pub fn aya::maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::ring_buf::RingBuf where U: core::convert::TryFrom +pub type aya::maps::ring_buf::RingBuf::Error = >::Error +pub fn aya::maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::ring_buf::RingBuf where T: 'static + core::marker::Sized +pub fn aya::maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya::maps::ring_buf::RingBuf::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::ring_buf::RingBuf where T: core::marker::Sized +pub fn aya::maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::ring_buf::RingBuf +pub fn aya::maps::ring_buf::RingBuf::from(t: T) -> T pub struct aya::maps::SockHash impl, K: aya::Pod> aya::maps::SockHash pub fn aya::maps::SockHash::fd(&self) -> &aya::maps::sock::SockMapFd From 2227223a96b0016ec960a8d5ba354d8c889ecc68 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Sun, 15 Oct 2023 15:45:18 +1100 Subject: [PATCH 76/95] aya-log: fix hygiene Before this change we leaked some bindings to the calling scope, so for instance logging a variable named "len" led to a compile error. --- aya-log-ebpf-macros/src/expand.rs | 21 ++++++++++++--------- test/integration-ebpf/src/log.rs | 5 +++++ test/integration-test/src/tests/log.rs | 9 +++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/aya-log-ebpf-macros/src/expand.rs b/aya-log-ebpf-macros/src/expand.rs index efc1a943..fb4630b3 100644 --- a/aya-log-ebpf-macros/src/expand.rs +++ b/aya-log-ebpf-macros/src/expand.rs @@ -1,6 +1,6 @@ use aya_log_common::DisplayHint; use aya_log_parser::{parse, Fragment}; -use proc_macro2::TokenStream; +use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; use syn::{ parse::{Parse, ParseStream}, @@ -141,13 +141,16 @@ pub(crate) fn log(args: LogArgs, level: Option) -> Result {}, Some(::aya_log_ebpf::LogBuf { buf }) => { let _: Option<()> = (|| { - let size = ::aya_log_ebpf::write_record_header( + let #size = ::aya_log_ebpf::write_record_header( buf, #target, #lvl, @@ -156,14 +159,14 @@ pub(crate) fn log(args: LogArgs, level: Option) -> Result Date: Mon, 16 Oct 2023 18:51:26 +1100 Subject: [PATCH 77/95] integration-tests: enable logs Use test_log::test so setting RUST_LOG=aya=debug works and it's easier to debug failures. --- Cargo.toml | 1 + test/integration-test/Cargo.toml | 2 ++ test/integration-test/src/tests/bpf_probe_read.rs | 1 + test/integration-test/src/tests/elf.rs | 1 + test/integration-test/src/tests/load.rs | 1 + test/integration-test/src/tests/log.rs | 3 ++- test/integration-test/src/tests/rbpf.rs | 1 + test/integration-test/src/tests/relocations.rs | 1 + test/integration-test/src/tests/ring_buf.rs | 7 ++++--- test/integration-test/src/tests/smoke.rs | 1 + test/integration-test/src/tests/xdp.rs | 1 + 11 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cfda2f5d..3ce5005f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,6 +91,7 @@ rustversion = { version = "1.0.0", default-features = false } syn = { version = "2", default-features = false } tempfile = { version = "3", default-features = false } test-case = { version = "3.1.0", default-features = false } +test-log = { version = "0.2.13", default-features = false } testing_logger = { version = "0.1.1", default-features = false } thiserror = { version = "1", default-features = false } tokio = { version = "1.24.0", default-features = false } diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml index 4db38be6..6ef15833 100644 --- a/test/integration-test/Cargo.toml +++ b/test/integration-test/Cargo.toml @@ -10,6 +10,7 @@ assert_matches = { workspace = true } aya = { workspace = true } aya-log = { workspace = true } aya-obj = { workspace = true } +env_logger = { workspace = true } epoll = { workspace = true } futures = { workspace = true, features = ["std"] } libc = { workspace = true } @@ -19,6 +20,7 @@ object = { workspace = true, features = ["elf", "read_core", "std"] } rand = { workspace = true, features = ["std", "std_rng"] } rbpf = { workspace = true } test-case = { workspace = true } +test-log = { workspace = true, features = ["log"] } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } [build-dependencies] diff --git a/test/integration-test/src/tests/bpf_probe_read.rs b/test/integration-test/src/tests/bpf_probe_read.rs index 4c425507..5d7cf6ab 100644 --- a/test/integration-test/src/tests/bpf_probe_read.rs +++ b/test/integration-test/src/tests/bpf_probe_read.rs @@ -1,4 +1,5 @@ use aya::{maps::Array, programs::UProbe, Bpf}; +use test_log::test; const RESULT_BUF_LEN: usize = 1024; diff --git a/test/integration-test/src/tests/elf.rs b/test/integration-test/src/tests/elf.rs index 9c68144f..3a5ad0a3 100644 --- a/test/integration-test/src/tests/elf.rs +++ b/test/integration-test/src/tests/elf.rs @@ -1,4 +1,5 @@ use object::{Object, ObjectSymbol}; +use test_log::test; #[test] fn test_maps() { diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 685867e9..6707a99e 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -16,6 +16,7 @@ use aya::{ Bpf, }; use aya_obj::programs::XdpAttachType; +use test_log::test; const MAX_RETRIES: usize = 100; const RETRY_DURATION: Duration = Duration::from_millis(10); diff --git a/test/integration-test/src/tests/log.rs b/test/integration-test/src/tests/log.rs index be99948b..c7980e0c 100644 --- a/test/integration-test/src/tests/log.rs +++ b/test/integration-test/src/tests/log.rs @@ -6,6 +6,7 @@ use std::{ use aya::{programs::UProbe, Bpf}; use aya_log::BpfLogger; use log::{Level, Log, Record}; +use test_log::test; #[no_mangle] #[inline(never)] @@ -37,7 +38,7 @@ struct CapturedLog<'a> { pub target: Cow<'a, str>, } -#[tokio::test] +#[test(tokio::test)] async fn log() { let mut bpf = Bpf::load(crate::LOG).unwrap(); diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index d2aeafd8..900d1462 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use assert_matches::assert_matches; use aya_obj::{generated::bpf_insn, programs::XdpAttachType, Object, ProgramSection}; +use test_log::test; #[test] fn run_with_rbpf() { diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 9e7d5719..e47e11f1 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,4 +1,5 @@ use aya::{programs::UProbe, Bpf}; +use test_log::test; #[test] fn relocations() { diff --git a/test/integration-test/src/tests/ring_buf.rs b/test/integration-test/src/tests/ring_buf.rs index ca222848..927d80a9 100644 --- a/test/integration-test/src/tests/ring_buf.rs +++ b/test/integration-test/src/tests/ring_buf.rs @@ -17,6 +17,7 @@ use aya::{ }; use aya_obj::generated::BPF_RINGBUF_HDR_SZ; use rand::Rng as _; +use test_log::test; use tokio::{ io::unix::AsyncFd, time::{sleep, Duration}, @@ -175,7 +176,7 @@ pub extern "C" fn ring_buf_trigger_ebpf_program(arg: u64) { // to fill the ring_buf. We just ensure that the number of events we see is sane given // what the producer sees, and that the logic does not hang. This exercises interleaving // discards, successful commits, and drops due to the ring_buf being full. -#[tokio::test(flavor = "multi_thread")] +#[test(tokio::test(flavor = "multi_thread"))] async fn ring_buf_async_with_drops() { let WithData( RingBufTest { @@ -282,7 +283,7 @@ async fn ring_buf_async_with_drops() { ); } -#[tokio::test(flavor = "multi_thread")] +#[test(tokio::test(flavor = "multi_thread"))] async fn ring_buf_async_no_drop() { let WithData( RingBufTest { @@ -380,7 +381,7 @@ fn ring_buf_epoll_wakeup() { } // This test is like the above test but uses tokio and AsyncFd instead of raw epoll. -#[tokio::test] +#[test(tokio::test)] async fn ring_buf_asyncfd_events() { let RingBufTest { ring_buf, diff --git a/test/integration-test/src/tests/smoke.rs b/test/integration-test/src/tests/smoke.rs index 48c1600b..7aadef1a 100644 --- a/test/integration-test/src/tests/smoke.rs +++ b/test/integration-test/src/tests/smoke.rs @@ -3,6 +3,7 @@ use aya::{ util::KernelVersion, Bpf, BpfLoader, }; +use test_log::test; use crate::utils::NetNsGuard; diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index 092f280e..c756dd20 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -6,6 +6,7 @@ use aya::{ Bpf, }; use object::{Object, ObjectSection, ObjectSymbol, SymbolSection}; +use test_log::test; use crate::utils::NetNsGuard; From 35e21ae0079d38e90d90fc85d29580c8b44b16d4 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Mon, 16 Oct 2023 21:47:07 +1100 Subject: [PATCH 78/95] aya: don't parse labels as programs Fixes a bug introduced by https://github.com/aya-rs/aya/pull/413 where we were generating a bunch of spurious LBB* programs. --- aya-obj/src/obj.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 1776b3ca..9d65690e 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -599,12 +599,12 @@ impl Object { .get(symbol_index) .expect("all symbols in symbols_by_section are also in symbol_table"); - let Some(name) = symbol.name.as_ref() else { - continue; + // Here we get both ::Label (LBB*) and ::Text symbols, and we only want the latter. + let name = match (symbol.name.as_ref(), symbol.kind) { + (Some(name), SymbolKind::Text) if !name.is_empty() => name, + _ => continue, }; - if name.is_empty() { - continue; - } + let (p, f) = self.parse_program(section, program_section.clone(), name.to_string(), symbol)?; let key = p.function_key(); From fa6f5e2532736ba7bb77b7007f9c7be1d14bbb6e Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 9 Aug 2023 17:04:03 -0400 Subject: [PATCH 79/95] github: run integration tests on local kernel This tests on 6.2.0-1012-azure (see https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20231001.1). --- .github/workflows/ci.yml | 6 +++++- test/integration-test/src/tests/relocations.rs | 8 +++++++- test/integration-test/src/tests/smoke.rs | 9 +++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39ab82de..59bff5bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -246,7 +246,11 @@ jobs: find test/.tmp -name '*.deb' -print0 | xargs -t -0 -I {} \ sh -c "dpkg --fsys-tarfile {} | tar -C test/.tmp --wildcards --extract '*vmlinuz*' --file -" - - name: Run integration tests + - name: Run local integration tests + if: runner.os == 'Linux' + run: cargo xtask integration-test local + + - name: Run virtualized integration tests run: find test/.tmp -name 'vmlinuz-*' | xargs -t cargo xtask integration-test vm # Provides a single status check for the entire build workflow. diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index e47e11f1..9c5dab7f 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,4 +1,4 @@ -use aya::{programs::UProbe, Bpf}; +use aya::{programs::UProbe, util::KernelVersion, Bpf}; use test_log::test; #[test] @@ -15,6 +15,12 @@ fn relocations() { #[test] fn text_64_64_reloc() { + let kernel_version = KernelVersion::current().unwrap(); + if kernel_version < KernelVersion::new(5, 13, 0) { + eprintln!("skipping test on kernel {kernel_version:?}, support for bpf_for_each_map_elem was added in 5.13.0; see https://github.com/torvalds/linux/commit/69c087b"); + return; + } + let mut bpf = load_and_attach("test_text_64_64_reloc", crate::TEXT_64_64_RELOC); let mut m = aya::maps::Array::<_, u64>::try_from(bpf.map_mut("RESULTS").unwrap()).unwrap(); diff --git a/test/integration-test/src/tests/smoke.rs b/test/integration-test/src/tests/smoke.rs index 7aadef1a..2b01938d 100644 --- a/test/integration-test/src/tests/smoke.rs +++ b/test/integration-test/src/tests/smoke.rs @@ -9,14 +9,14 @@ use crate::utils::NetNsGuard; #[test] fn xdp() { - let _netns = NetNsGuard::new(); - let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { eprintln!("skipping test on kernel {kernel_version:?}, support for BPF_F_XDP_HAS_FRAGS was added in 5.18.0; see https://github.com/torvalds/linux/commit/c2f2cdb"); return; } + let _netns = NetNsGuard::new(); + let mut bpf = Bpf::load(crate::PASS).unwrap(); let dispatcher: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); dispatcher.load().unwrap(); @@ -47,13 +47,14 @@ fn two_progs() { #[test] fn extension() { - let _netns = NetNsGuard::new(); - let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 9, 0) { eprintln!("skipping test on kernel {kernel_version:?}, XDP uses netlink"); return; } + + let _netns = NetNsGuard::new(); + let mut bpf = Bpf::load(crate::MAIN).unwrap(); let pass: &mut Xdp = bpf.program_mut("xdp_pass").unwrap().try_into().unwrap(); pass.load().unwrap(); From 984c08cbad73c51a501b528c53e72f6130976639 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Wed, 18 Oct 2023 15:45:50 +0200 Subject: [PATCH 80/95] aya: fix unused async-io dependency linter error Not using the `dep:` syntax created a Cargo feature flag for async-io, though this feature alone does nothing without the `async_std` or `async_tokio` features. --- aya/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aya/Cargo.toml b/aya/Cargo.toml index cec83a0f..74ef5660 100644 --- a/aya/Cargo.toml +++ b/aya/Cargo.toml @@ -30,7 +30,7 @@ tempfile = { workspace = true } [features] default = [] async_tokio = ["tokio/net"] -async_std = ["async-io"] +async_std = ["dep:async-io"] [package.metadata.docs.rs] all-features = true From a31332fb6c2fecf40bd4e3181e1cb0ff5f47b0fe Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 22 Oct 2023 12:37:09 -0400 Subject: [PATCH 81/95] aya-bpf-macros: appease clippy ``` warning: accessing first element with `args.args.get(0)` --> aya-bpf-macros/src/args.rs:71:24 | 71 | if let Some(arg) = args.args.get(0) { | ^^^^^^^^^^^^^^^^ help: try: `args.args.first()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first = note: `#[warn(clippy::get_first)]` on by default ``` Appears https://github.com/rust-lang/rust-clippy/commit/31fd282732e15811 has just landed in nightly. --- aya-bpf-macros/src/args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aya-bpf-macros/src/args.rs b/aya-bpf-macros/src/args.rs index b695053a..12ed84d1 100644 --- a/aya-bpf-macros/src/args.rs +++ b/aya-bpf-macros/src/args.rs @@ -68,7 +68,7 @@ pub(crate) fn pop_bool_arg(args: &mut Args, name: &str) -> bool { } pub(crate) fn err_on_unknown_args(args: &Args) -> Result<()> { - if let Some(arg) = args.args.get(0) { + if let Some(arg) = args.args.first() { let tokens = match arg { Arg::String(name_val) => name_val.name.clone(), Arg::Bool(ident) => ident.clone(), From 3824b3d4797c89b88c2a1a56c77f3dcc72722829 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:59:27 +0000 Subject: [PATCH 82/95] build(deps): update which requirement from 4.4.0 to 5.0.0 Updates the requirements on [which](https://github.com/harryfei/which-rs) to permit the latest version. - [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/harryfei/which-rs/compare/4.4.0...4.4.2) --- updated-dependencies: - dependency-name: which dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3ce5005f..232d67d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,7 +95,7 @@ test-log = { version = "0.2.13", default-features = false } testing_logger = { version = "0.1.1", default-features = false } thiserror = { version = "1", default-features = false } tokio = { version = "1.24.0", default-features = false } -which = { version = "4.4.0", default-features = false } +which = { version = "5.0.0", default-features = false } xtask = { path = "xtask", default-features = false } [profile.dev] From c89b2d156dbddd495f885edecbf71910cc61bba8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:00:25 +0000 Subject: [PATCH 83/95] build(deps): update async-io requirement from 1.3 to 2.0 Updates the requirements on [async-io](https://github.com/smol-rs/async-io) to permit the latest version. - [Release notes](https://github.com/smol-rs/async-io/releases) - [Changelog](https://github.com/smol-rs/async-io/blob/master/CHANGELOG.md) - [Commits](https://github.com/smol-rs/async-io/compare/v1.3.0...v1.13.0) --- updated-dependencies: - dependency-name: async-io dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- aya/src/maps/perf/async_perf_event_array.rs | 2 +- aya/src/maps/perf/perf_event_array.rs | 8 +++++++- xtask/public-api/aya.txt | 2 ++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3ce5005f..70684050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ default-members = [ [workspace.dependencies] anyhow = { version = "1", default-features = false } assert_matches = { version = "1.5.0", default-features = false } -async-io = { version = "1.3", default-features = false } +async-io = { version = "2.0", default-features = false } aya = { path = "aya", version = "0.11.0", default-features = false } aya-bpf = { path = "bpf/aya-bpf", default-features = false } aya-log = { path = "aya-log", default-features = false } diff --git a/aya/src/maps/perf/async_perf_event_array.rs b/aya/src/maps/perf/async_perf_event_array.rs index 4b7d097e..7828759a 100644 --- a/aya/src/maps/perf/async_perf_event_array.rs +++ b/aya/src/maps/perf/async_perf_event_array.rs @@ -159,7 +159,7 @@ impl> AsyncPerfEventArrayBuffer { if !buf.get_ref().readable() { buf.readable().await?; } - buf.get_mut() + unsafe { buf.get_mut() } }; let events = buf.read_events(buffers)?; diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index ebeef672..c1df535a 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -4,7 +4,7 @@ use std::{ borrow::{Borrow, BorrowMut}, ops::Deref, - os::fd::{AsFd as _, AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd}, sync::Arc, }; @@ -55,6 +55,12 @@ impl> PerfEventArrayBuffer { } } +impl> AsFd for PerfEventArrayBuffer { + fn as_fd(&self) -> BorrowedFd<'_> { + self.buf.as_fd() + } +} + impl> AsRawFd for PerfEventArrayBuffer { fn as_raw_fd(&self) -> RawFd { self.buf.as_raw_fd() diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index b2b28876..591ebaf4 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -510,6 +510,8 @@ pub struct aya::maps::perf::PerfEventArrayBuffer impl> aya::maps::perf::PerfEventArrayBuffer pub fn aya::maps::perf::PerfEventArrayBuffer::read_events(&mut self, out_bufs: &mut [bytes::bytes_mut::BytesMut]) -> core::result::Result pub fn aya::maps::perf::PerfEventArrayBuffer::readable(&self) -> bool +impl> std::os::fd::owned::AsFd for aya::maps::perf::PerfEventArrayBuffer +pub fn aya::maps::perf::PerfEventArrayBuffer::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> impl> std::os::fd::raw::AsRawFd for aya::maps::perf::PerfEventArrayBuffer pub fn aya::maps::perf::PerfEventArrayBuffer::as_raw_fd(&self) -> std::os::fd::raw::RawFd impl core::marker::Send for aya::maps::perf::PerfEventArrayBuffer where T: core::marker::Send + core::marker::Sync From b65a6529911a47c01e1beb83e74cc7c162c82466 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 24 Oct 2023 10:54:24 -0400 Subject: [PATCH 84/95] aya-bpf-cty: remove empty module This triggers the unused import lint after https://github.com/rust-lang/rust/commit/482275b19422b871b986ec0400257a. --- bpf/aya-bpf-cty/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bpf/aya-bpf-cty/src/lib.rs b/bpf/aya-bpf-cty/src/lib.rs index e40645f5..4a62a0d9 100644 --- a/bpf/aya-bpf-cty/src/lib.rs +++ b/bpf/aya-bpf-cty/src/lib.rs @@ -12,8 +12,6 @@ pub use ad::*; // OD = OS dependent pub use od::*; -// PWD = Pointer Width Dependent -pub use pwd::*; #[cfg(target_arch = "bpf")] mod ad { @@ -106,12 +104,6 @@ mod od { pub type c_ulong = u64; } -#[cfg(target_pointer_width = "32")] -mod pwd {} - -#[cfg(target_pointer_width = "64")] -mod pwd {} - pub type int8_t = i8; pub type int16_t = i16; pub type int32_t = i32; From aa5ff517e7c7b6600afc826fde2d81d55be3bf50 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Thu, 17 Aug 2023 11:05:56 +0200 Subject: [PATCH 85/95] tests: add AF_XDP test using xdpilone --- Cargo.toml | 1 + test/integration-test/Cargo.toml | 1 + test/integration-test/src/tests/xdp.rs | 77 +++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b7accb7c..5a983086 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,6 +96,7 @@ testing_logger = { version = "0.1.1", default-features = false } thiserror = { version = "1", default-features = false } tokio = { version = "1.24.0", default-features = false } which = { version = "5.0.0", default-features = false } +xdpilone = { version = "1.0", default-features = false } xtask = { path = "xtask", default-features = false } [profile.dev] diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml index 6ef15833..36eedfef 100644 --- a/test/integration-test/Cargo.toml +++ b/test/integration-test/Cargo.toml @@ -22,6 +22,7 @@ rbpf = { workspace = true } test-case = { workspace = true } test-log = { workspace = true, features = ["log"] } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } +xdpilone = { workspace = true } [build-dependencies] cargo_metadata = { workspace = true } diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index c756dd20..fec278d7 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -1,15 +1,88 @@ -use std::{net::UdpSocket, time::Duration}; +use std::{ + ffi::CStr, mem::MaybeUninit, net::UdpSocket, num::NonZeroU32, ptr::NonNull, time::Duration, +}; use aya::{ - maps::{Array, CpuMap}, + maps::{Array, CpuMap, XskMap}, programs::{Xdp, XdpFlags}, Bpf, }; use object::{Object, ObjectSection, ObjectSymbol, SymbolSection}; use test_log::test; +use xdpilone::{BufIdx, IfInfo, Socket, SocketConfig, Umem, UmemConfig}; use crate::utils::NetNsGuard; +#[test] +fn af_xdp() { + let _netns = NetNsGuard::new(); + + let mut bpf = Bpf::load(crate::REDIRECT).unwrap(); + let mut socks: XskMap<_> = bpf.take_map("SOCKS").unwrap().try_into().unwrap(); + + let xdp: &mut Xdp = bpf + .program_mut("redirect_sock") + .unwrap() + .try_into() + .unwrap(); + xdp.load().unwrap(); + xdp.attach("lo", XdpFlags::default()).unwrap(); + + // So this needs to be page aligned. Pages are 4k on all mainstream architectures except for + // Apple Silicon which uses 16k pages. So let's align on that for tests to run natively there. + #[repr(align(16384))] + struct PacketMap(MaybeUninit<[u8; 4096]>); + + let mem = Box::new(PacketMap(MaybeUninit::uninit())); + let mem = NonNull::new(Box::leak(mem).0.as_mut_ptr()).unwrap(); + let umem = unsafe { Umem::new(UmemConfig::default(), mem).unwrap() }; + + let mut iface = IfInfo::invalid(); + iface + .from_name(CStr::from_bytes_with_nul(b"lo\0").unwrap()) + .unwrap(); + let sock = Socket::with_shared(&iface, &umem).unwrap(); + + let mut fq_cq = umem.fq_cq(&sock).unwrap(); // Fill Queue / Completion Queue + + let cfg = SocketConfig { + rx_size: NonZeroU32::new(32), + ..Default::default() + }; + let rxtx = umem.rx_tx(&sock, &cfg).unwrap(); // RX + TX Queues + let mut rx = rxtx.map_rx().unwrap(); + + umem.bind(&rxtx).unwrap(); + + socks.set(0, rx.as_raw_fd(), 0).unwrap(); + + let frame = umem.frame(BufIdx(0)).unwrap(); + + // Produce a frame to be filled by the kernel + let mut writer = fq_cq.fill(1); + writer.insert_once(frame.offset); + writer.commit(); + + let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); + let port = sock.local_addr().unwrap().port(); + sock.send_to(b"hello AF_XDP", "127.0.0.1:1777").unwrap(); + + assert_eq!(rx.available(), 1); + let desc = rx.receive(1).read().unwrap(); + let buf = unsafe { + &frame.addr.as_ref()[desc.addr as usize..(desc.addr as usize + desc.len as usize)] + }; + + let (eth, buf) = buf.split_at(14); + assert_eq!(eth[12..14], [0x08, 0x00]); // IP + let (ip, buf) = buf.split_at(20); + assert_eq!(ip[9], 17); // UDP + let (udp, payload) = buf.split_at(8); + assert_eq!(&udp[0..2], port.to_be_bytes().as_slice()); // Source + assert_eq!(&udp[2..4], 1777u16.to_be_bytes().as_slice()); // Dest + assert_eq!(payload, b"hello AF_XDP"); +} + #[test] fn prog_sections() { let obj_file = object::File::parse(crate::XDP_SEC).unwrap(); From e148ce1af39071c4811a53d92ebed553bb803c61 Mon Sep 17 00:00:00 2001 From: Tuetuopay Date: Wed, 18 Oct 2023 14:50:04 +0200 Subject: [PATCH 86/95] tests/xdp: don't leak memory in AF_XDP test --- test/integration-test/src/tests/xdp.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs index fec278d7..784ffe75 100644 --- a/test/integration-test/src/tests/xdp.rs +++ b/test/integration-test/src/tests/xdp.rs @@ -1,6 +1,4 @@ -use std::{ - ffi::CStr, mem::MaybeUninit, net::UdpSocket, num::NonZeroU32, ptr::NonNull, time::Duration, -}; +use std::{ffi::CStr, mem::MaybeUninit, net::UdpSocket, num::NonZeroU32, time::Duration}; use aya::{ maps::{Array, CpuMap, XskMap}, @@ -33,9 +31,14 @@ fn af_xdp() { #[repr(align(16384))] struct PacketMap(MaybeUninit<[u8; 4096]>); - let mem = Box::new(PacketMap(MaybeUninit::uninit())); - let mem = NonNull::new(Box::leak(mem).0.as_mut_ptr()).unwrap(); - let umem = unsafe { Umem::new(UmemConfig::default(), mem).unwrap() }; + // Safety: don't access alloc down the line. + let mut alloc = Box::new(PacketMap(MaybeUninit::uninit())); + let umem = { + // Safety: this is a shared buffer between the kernel and us, uninitialized memory is valid. + let mem = unsafe { alloc.0.assume_init_mut() }.as_mut().into(); + // Safety: we cannot access `mem` further down the line because it falls out of scope. + unsafe { Umem::new(UmemConfig::default(), mem).unwrap() } + }; let mut iface = IfInfo::invalid(); iface From 6e256fad5b1c3f33ca9d1d5a53dcb2f78dfe4934 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 31 Oct 2023 11:54:14 -0400 Subject: [PATCH 87/95] public-api: bless with new nightly See https://github.com/rust-lang/rust/commit/58a80c85b9323e59e1b7e744d6. --- xtask/public-api/aya-bpf-bindings.txt | 4 +- xtask/public-api/aya-log-common.txt | 4 +- xtask/public-api/aya-log-parser.txt | 4 +- xtask/public-api/aya-obj.txt | 50 ++++++------- xtask/public-api/aya.txt | 104 +++++++++++++------------- 5 files changed, 83 insertions(+), 83 deletions(-) diff --git a/xtask/public-api/aya-bpf-bindings.txt b/xtask/public-api/aya-bpf-bindings.txt index c98486a2..1d35dcf8 100644 --- a/xtask/public-api/aya-bpf-bindings.txt +++ b/xtask/public-api/aya-bpf-bindings.txt @@ -1813,9 +1813,9 @@ pub fn aya_bpf_bindings::bindings::__BindgenBitfieldUnit::clone(&self) impl core::cmp::Eq for aya_bpf_bindings::bindings::__BindgenBitfieldUnit impl core::cmp::Ord for aya_bpf_bindings::bindings::__BindgenBitfieldUnit pub fn aya_bpf_bindings::bindings::__BindgenBitfieldUnit::cmp(&self, other: &aya_bpf_bindings::bindings::__BindgenBitfieldUnit) -> core::cmp::Ordering -impl core::cmp::PartialEq> for aya_bpf_bindings::bindings::__BindgenBitfieldUnit +impl core::cmp::PartialEq for aya_bpf_bindings::bindings::__BindgenBitfieldUnit pub fn aya_bpf_bindings::bindings::__BindgenBitfieldUnit::eq(&self, other: &aya_bpf_bindings::bindings::__BindgenBitfieldUnit) -> bool -impl core::cmp::PartialOrd> for aya_bpf_bindings::bindings::__BindgenBitfieldUnit +impl core::cmp::PartialOrd for aya_bpf_bindings::bindings::__BindgenBitfieldUnit pub fn aya_bpf_bindings::bindings::__BindgenBitfieldUnit::partial_cmp(&self, other: &aya_bpf_bindings::bindings::__BindgenBitfieldUnit) -> core::option::Option impl core::default::Default for aya_bpf_bindings::bindings::__BindgenBitfieldUnit pub fn aya_bpf_bindings::bindings::__BindgenBitfieldUnit::default() -> aya_bpf_bindings::bindings::__BindgenBitfieldUnit diff --git a/xtask/public-api/aya-log-common.txt b/xtask/public-api/aya-log-common.txt index fd921d9b..cc1621b5 100644 --- a/xtask/public-api/aya-log-common.txt +++ b/xtask/public-api/aya-log-common.txt @@ -60,7 +60,7 @@ pub fn u8::from(enum_value: aya_log_common::DisplayHint) -> Self impl core::clone::Clone for aya_log_common::DisplayHint pub fn aya_log_common::DisplayHint::clone(&self) -> aya_log_common::DisplayHint impl core::cmp::Eq for aya_log_common::DisplayHint -impl core::cmp::PartialEq for aya_log_common::DisplayHint +impl core::cmp::PartialEq for aya_log_common::DisplayHint pub fn aya_log_common::DisplayHint::eq(&self, other: &aya_log_common::DisplayHint) -> bool impl core::fmt::Debug for aya_log_common::DisplayHint pub fn aya_log_common::DisplayHint::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -99,7 +99,7 @@ pub fn u8::from(enum_value: aya_log_common::Level) -> Self impl core::clone::Clone for aya_log_common::Level pub fn aya_log_common::Level::clone(&self) -> aya_log_common::Level impl core::cmp::Eq for aya_log_common::Level -impl core::cmp::PartialEq for aya_log_common::Level +impl core::cmp::PartialEq for aya_log_common::Level pub fn aya_log_common::Level::eq(&self, other: &aya_log_common::Level) -> bool impl core::fmt::Debug for aya_log_common::Level pub fn aya_log_common::Level::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result diff --git a/xtask/public-api/aya-log-parser.txt b/xtask/public-api/aya-log-parser.txt index cf1f3493..3b933b14 100644 --- a/xtask/public-api/aya-log-parser.txt +++ b/xtask/public-api/aya-log-parser.txt @@ -5,7 +5,7 @@ pub aya_log_parser::Fragment::Parameter(aya_log_parser::Parameter) impl core::clone::Clone for aya_log_parser::Fragment pub fn aya_log_parser::Fragment::clone(&self) -> aya_log_parser::Fragment impl core::cmp::Eq for aya_log_parser::Fragment -impl core::cmp::PartialEq for aya_log_parser::Fragment +impl core::cmp::PartialEq for aya_log_parser::Fragment pub fn aya_log_parser::Fragment::eq(&self, other: &aya_log_parser::Fragment) -> bool impl core::fmt::Debug for aya_log_parser::Fragment pub fn aya_log_parser::Fragment::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -41,7 +41,7 @@ pub aya_log_parser::Parameter::hint: aya_log_common::DisplayHint impl core::clone::Clone for aya_log_parser::Parameter pub fn aya_log_parser::Parameter::clone(&self) -> aya_log_parser::Parameter impl core::cmp::Eq for aya_log_parser::Parameter -impl core::cmp::PartialEq for aya_log_parser::Parameter +impl core::cmp::PartialEq for aya_log_parser::Parameter pub fn aya_log_parser::Parameter::eq(&self, other: &aya_log_parser::Parameter) -> bool impl core::fmt::Debug for aya_log_parser::Parameter pub fn aya_log_parser::Parameter::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index 5c361372..50f42ac4 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -98,7 +98,7 @@ pub fn aya_obj::btf::BtfKind::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> co impl core::clone::Clone for aya_obj::btf::BtfKind pub fn aya_obj::btf::BtfKind::clone(&self) -> aya_obj::btf::BtfKind impl core::cmp::Eq for aya_obj::btf::BtfKind -impl core::cmp::PartialEq for aya_obj::btf::BtfKind +impl core::cmp::PartialEq for aya_obj::btf::BtfKind pub fn aya_obj::btf::BtfKind::eq(&self, other: &aya_obj::btf::BtfKind) -> bool impl core::default::Default for aya_obj::btf::BtfKind pub fn aya_obj::btf::BtfKind::default() -> aya_obj::btf::BtfKind @@ -194,7 +194,7 @@ pub fn aya_obj::btf::FuncLinkage::from(v: u32) -> Self impl core::clone::Clone for aya_obj::btf::FuncLinkage pub fn aya_obj::btf::FuncLinkage::clone(&self) -> aya_obj::btf::FuncLinkage impl core::cmp::Eq for aya_obj::btf::FuncLinkage -impl core::cmp::PartialEq for aya_obj::btf::FuncLinkage +impl core::cmp::PartialEq for aya_obj::btf::FuncLinkage pub fn aya_obj::btf::FuncLinkage::eq(&self, other: &aya_obj::btf::FuncLinkage) -> bool impl core::fmt::Debug for aya_obj::btf::FuncLinkage pub fn aya_obj::btf::FuncLinkage::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -236,7 +236,7 @@ pub fn aya_obj::btf::IntEncoding::from(v: u32) -> Self impl core::clone::Clone for aya_obj::btf::IntEncoding pub fn aya_obj::btf::IntEncoding::clone(&self) -> aya_obj::btf::IntEncoding impl core::cmp::Eq for aya_obj::btf::IntEncoding -impl core::cmp::PartialEq for aya_obj::btf::IntEncoding +impl core::cmp::PartialEq for aya_obj::btf::IntEncoding pub fn aya_obj::btf::IntEncoding::eq(&self, other: &aya_obj::btf::IntEncoding) -> bool impl core::fmt::Debug for aya_obj::btf::IntEncoding pub fn aya_obj::btf::IntEncoding::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -277,7 +277,7 @@ pub fn aya_obj::btf::VarLinkage::from(v: u32) -> Self impl core::clone::Clone for aya_obj::btf::VarLinkage pub fn aya_obj::btf::VarLinkage::clone(&self) -> aya_obj::btf::VarLinkage impl core::cmp::Eq for aya_obj::btf::VarLinkage -impl core::cmp::PartialEq for aya_obj::btf::VarLinkage +impl core::cmp::PartialEq for aya_obj::btf::VarLinkage pub fn aya_obj::btf::VarLinkage::eq(&self, other: &aya_obj::btf::VarLinkage) -> bool impl core::fmt::Debug for aya_obj::btf::VarLinkage pub fn aya_obj::btf::VarLinkage::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1347,7 +1347,7 @@ pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp:: impl core::clone::Clone for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::clone(&self) -> aya_obj::generated::bpf_attach_type impl core::cmp::Eq for aya_obj::generated::bpf_attach_type -impl core::cmp::PartialEq for aya_obj::generated::bpf_attach_type +impl core::cmp::PartialEq for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::eq(&self, other: &aya_obj::generated::bpf_attach_type) -> bool impl core::fmt::Debug for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1423,7 +1423,7 @@ pub const aya_obj::generated::bpf_cmd::BPF_PROG_RUN: aya_obj::generated::bpf_cmd impl core::clone::Clone for aya_obj::generated::bpf_cmd pub fn aya_obj::generated::bpf_cmd::clone(&self) -> aya_obj::generated::bpf_cmd impl core::cmp::Eq for aya_obj::generated::bpf_cmd -impl core::cmp::PartialEq for aya_obj::generated::bpf_cmd +impl core::cmp::PartialEq for aya_obj::generated::bpf_cmd pub fn aya_obj::generated::bpf_cmd::eq(&self, other: &aya_obj::generated::bpf_cmd) -> bool impl core::fmt::Debug for aya_obj::generated::bpf_cmd pub fn aya_obj::generated::bpf_cmd::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1473,7 +1473,7 @@ pub aya_obj::generated::bpf_link_type::MAX_BPF_LINK_TYPE = 11 impl core::clone::Clone for aya_obj::generated::bpf_link_type pub fn aya_obj::generated::bpf_link_type::clone(&self) -> aya_obj::generated::bpf_link_type impl core::cmp::Eq for aya_obj::generated::bpf_link_type -impl core::cmp::PartialEq for aya_obj::generated::bpf_link_type +impl core::cmp::PartialEq for aya_obj::generated::bpf_link_type pub fn aya_obj::generated::bpf_link_type::eq(&self, other: &aya_obj::generated::bpf_link_type) -> bool impl core::fmt::Debug for aya_obj::generated::bpf_link_type pub fn aya_obj::generated::bpf_link_type::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1549,7 +1549,7 @@ pub fn aya_obj::generated::bpf_map_type::try_from(map_type: u32) -> core::result impl core::clone::Clone for aya_obj::generated::bpf_map_type pub fn aya_obj::generated::bpf_map_type::clone(&self) -> aya_obj::generated::bpf_map_type impl core::cmp::Eq for aya_obj::generated::bpf_map_type -impl core::cmp::PartialEq for aya_obj::generated::bpf_map_type +impl core::cmp::PartialEq for aya_obj::generated::bpf_map_type pub fn aya_obj::generated::bpf_map_type::eq(&self, other: &aya_obj::generated::bpf_map_type) -> bool impl core::fmt::Debug for aya_obj::generated::bpf_map_type pub fn aya_obj::generated::bpf_map_type::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1620,7 +1620,7 @@ pub aya_obj::generated::bpf_prog_type::BPF_PROG_TYPE_XDP = 6 impl core::clone::Clone for aya_obj::generated::bpf_prog_type pub fn aya_obj::generated::bpf_prog_type::clone(&self) -> aya_obj::generated::bpf_prog_type impl core::cmp::Eq for aya_obj::generated::bpf_prog_type -impl core::cmp::PartialEq for aya_obj::generated::bpf_prog_type +impl core::cmp::PartialEq for aya_obj::generated::bpf_prog_type pub fn aya_obj::generated::bpf_prog_type::eq(&self, other: &aya_obj::generated::bpf_prog_type) -> bool impl core::fmt::Debug for aya_obj::generated::bpf_prog_type pub fn aya_obj::generated::bpf_prog_type::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1661,7 +1661,7 @@ pub aya_obj::generated::btf_func_linkage::BTF_FUNC_STATIC = 0 impl core::clone::Clone for aya_obj::generated::btf_func_linkage pub fn aya_obj::generated::btf_func_linkage::clone(&self) -> aya_obj::generated::btf_func_linkage impl core::cmp::Eq for aya_obj::generated::btf_func_linkage -impl core::cmp::PartialEq for aya_obj::generated::btf_func_linkage +impl core::cmp::PartialEq for aya_obj::generated::btf_func_linkage pub fn aya_obj::generated::btf_func_linkage::eq(&self, other: &aya_obj::generated::btf_func_linkage) -> bool impl core::fmt::Debug for aya_obj::generated::btf_func_linkage pub fn aya_obj::generated::btf_func_linkage::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1725,7 +1725,7 @@ pub aya_obj::generated::perf_event_sample_format::PERF_SAMPLE_WEIGHT_STRUCT = 16 impl core::clone::Clone for aya_obj::generated::perf_event_sample_format pub fn aya_obj::generated::perf_event_sample_format::clone(&self) -> aya_obj::generated::perf_event_sample_format impl core::cmp::Eq for aya_obj::generated::perf_event_sample_format -impl core::cmp::PartialEq for aya_obj::generated::perf_event_sample_format +impl core::cmp::PartialEq for aya_obj::generated::perf_event_sample_format pub fn aya_obj::generated::perf_event_sample_format::eq(&self, other: &aya_obj::generated::perf_event_sample_format) -> bool impl core::fmt::Debug for aya_obj::generated::perf_event_sample_format pub fn aya_obj::generated::perf_event_sample_format::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1785,7 +1785,7 @@ pub aya_obj::generated::perf_event_type::PERF_RECORD_UNTHROTTLE = 6 impl core::clone::Clone for aya_obj::generated::perf_event_type pub fn aya_obj::generated::perf_event_type::clone(&self) -> aya_obj::generated::perf_event_type impl core::cmp::Eq for aya_obj::generated::perf_event_type -impl core::cmp::PartialEq for aya_obj::generated::perf_event_type +impl core::cmp::PartialEq for aya_obj::generated::perf_event_type pub fn aya_obj::generated::perf_event_type::eq(&self, other: &aya_obj::generated::perf_event_type) -> bool impl core::fmt::Debug for aya_obj::generated::perf_event_type pub fn aya_obj::generated::perf_event_type::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1831,7 +1831,7 @@ pub aya_obj::generated::perf_hw_cache_id::PERF_COUNT_HW_CACHE_NODE = 6 impl core::clone::Clone for aya_obj::generated::perf_hw_cache_id pub fn aya_obj::generated::perf_hw_cache_id::clone(&self) -> aya_obj::generated::perf_hw_cache_id impl core::cmp::Eq for aya_obj::generated::perf_hw_cache_id -impl core::cmp::PartialEq for aya_obj::generated::perf_hw_cache_id +impl core::cmp::PartialEq for aya_obj::generated::perf_hw_cache_id pub fn aya_obj::generated::perf_hw_cache_id::eq(&self, other: &aya_obj::generated::perf_hw_cache_id) -> bool impl core::fmt::Debug for aya_obj::generated::perf_hw_cache_id pub fn aya_obj::generated::perf_hw_cache_id::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1873,7 +1873,7 @@ pub aya_obj::generated::perf_hw_cache_op_id::PERF_COUNT_HW_CACHE_OP_WRITE = 1 impl core::clone::Clone for aya_obj::generated::perf_hw_cache_op_id pub fn aya_obj::generated::perf_hw_cache_op_id::clone(&self) -> aya_obj::generated::perf_hw_cache_op_id impl core::cmp::Eq for aya_obj::generated::perf_hw_cache_op_id -impl core::cmp::PartialEq for aya_obj::generated::perf_hw_cache_op_id +impl core::cmp::PartialEq for aya_obj::generated::perf_hw_cache_op_id pub fn aya_obj::generated::perf_hw_cache_op_id::eq(&self, other: &aya_obj::generated::perf_hw_cache_op_id) -> bool impl core::fmt::Debug for aya_obj::generated::perf_hw_cache_op_id pub fn aya_obj::generated::perf_hw_cache_op_id::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1914,7 +1914,7 @@ pub aya_obj::generated::perf_hw_cache_op_result_id::PERF_COUNT_HW_CACHE_RESULT_M impl core::clone::Clone for aya_obj::generated::perf_hw_cache_op_result_id pub fn aya_obj::generated::perf_hw_cache_op_result_id::clone(&self) -> aya_obj::generated::perf_hw_cache_op_result_id impl core::cmp::Eq for aya_obj::generated::perf_hw_cache_op_result_id -impl core::cmp::PartialEq for aya_obj::generated::perf_hw_cache_op_result_id +impl core::cmp::PartialEq for aya_obj::generated::perf_hw_cache_op_result_id pub fn aya_obj::generated::perf_hw_cache_op_result_id::eq(&self, other: &aya_obj::generated::perf_hw_cache_op_result_id) -> bool impl core::fmt::Debug for aya_obj::generated::perf_hw_cache_op_result_id pub fn aya_obj::generated::perf_hw_cache_op_result_id::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1963,7 +1963,7 @@ pub aya_obj::generated::perf_hw_id::PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7 impl core::clone::Clone for aya_obj::generated::perf_hw_id pub fn aya_obj::generated::perf_hw_id::clone(&self) -> aya_obj::generated::perf_hw_id impl core::cmp::Eq for aya_obj::generated::perf_hw_id -impl core::cmp::PartialEq for aya_obj::generated::perf_hw_id +impl core::cmp::PartialEq for aya_obj::generated::perf_hw_id pub fn aya_obj::generated::perf_hw_id::eq(&self, other: &aya_obj::generated::perf_hw_id) -> bool impl core::fmt::Debug for aya_obj::generated::perf_hw_id pub fn aya_obj::generated::perf_hw_id::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2014,7 +2014,7 @@ pub aya_obj::generated::perf_sw_ids::PERF_COUNT_SW_TASK_CLOCK = 1 impl core::clone::Clone for aya_obj::generated::perf_sw_ids pub fn aya_obj::generated::perf_sw_ids::clone(&self) -> aya_obj::generated::perf_sw_ids impl core::cmp::Eq for aya_obj::generated::perf_sw_ids -impl core::cmp::PartialEq for aya_obj::generated::perf_sw_ids +impl core::cmp::PartialEq for aya_obj::generated::perf_sw_ids pub fn aya_obj::generated::perf_sw_ids::eq(&self, other: &aya_obj::generated::perf_sw_ids) -> bool impl core::fmt::Debug for aya_obj::generated::perf_sw_ids pub fn aya_obj::generated::perf_sw_ids::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2059,7 +2059,7 @@ pub aya_obj::generated::perf_type_id::PERF_TYPE_TRACEPOINT = 2 impl core::clone::Clone for aya_obj::generated::perf_type_id pub fn aya_obj::generated::perf_type_id::clone(&self) -> aya_obj::generated::perf_type_id impl core::cmp::Eq for aya_obj::generated::perf_type_id -impl core::cmp::PartialEq for aya_obj::generated::perf_type_id +impl core::cmp::PartialEq for aya_obj::generated::perf_type_id pub fn aya_obj::generated::perf_type_id::eq(&self, other: &aya_obj::generated::perf_type_id) -> bool impl core::fmt::Debug for aya_obj::generated::perf_type_id pub fn aya_obj::generated::perf_type_id::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2759,9 +2759,9 @@ pub fn aya_obj::generated::__BindgenBitfieldUnit::clone(&self) -> aya_o impl core::cmp::Eq for aya_obj::generated::__BindgenBitfieldUnit impl core::cmp::Ord for aya_obj::generated::__BindgenBitfieldUnit pub fn aya_obj::generated::__BindgenBitfieldUnit::cmp(&self, other: &aya_obj::generated::__BindgenBitfieldUnit) -> core::cmp::Ordering -impl core::cmp::PartialEq> for aya_obj::generated::__BindgenBitfieldUnit +impl core::cmp::PartialEq for aya_obj::generated::__BindgenBitfieldUnit pub fn aya_obj::generated::__BindgenBitfieldUnit::eq(&self, other: &aya_obj::generated::__BindgenBitfieldUnit) -> bool -impl core::cmp::PartialOrd> for aya_obj::generated::__BindgenBitfieldUnit +impl core::cmp::PartialOrd for aya_obj::generated::__BindgenBitfieldUnit pub fn aya_obj::generated::__BindgenBitfieldUnit::partial_cmp(&self, other: &aya_obj::generated::__BindgenBitfieldUnit) -> core::option::Option impl core::default::Default for aya_obj::generated::__BindgenBitfieldUnit pub fn aya_obj::generated::__BindgenBitfieldUnit::default() -> aya_obj::generated::__BindgenBitfieldUnit @@ -5485,7 +5485,7 @@ pub fn aya_obj::maps::PinningType::try_from(value: u32) -> core::result::Result< impl core::clone::Clone for aya_obj::maps::PinningType pub fn aya_obj::maps::PinningType::clone(&self) -> aya_obj::maps::PinningType impl core::cmp::Eq for aya_obj::maps::PinningType -impl core::cmp::PartialEq for aya_obj::maps::PinningType +impl core::cmp::PartialEq for aya_obj::maps::PinningType pub fn aya_obj::maps::PinningType::eq(&self, other: &aya_obj::maps::PinningType) -> bool impl core::default::Default for aya_obj::maps::PinningType pub fn aya_obj::maps::PinningType::default() -> aya_obj::maps::PinningType @@ -5556,7 +5556,7 @@ pub aya_obj::maps::BtfMapDef::btf_value_type_id: u32 impl core::clone::Clone for aya_obj::maps::BtfMapDef pub fn aya_obj::maps::BtfMapDef::clone(&self) -> aya_obj::maps::BtfMapDef impl core::cmp::Eq for aya_obj::maps::BtfMapDef -impl core::cmp::PartialEq for aya_obj::maps::BtfMapDef +impl core::cmp::PartialEq for aya_obj::maps::BtfMapDef pub fn aya_obj::maps::BtfMapDef::eq(&self, other: &aya_obj::maps::BtfMapDef) -> bool impl core::default::Default for aya_obj::maps::BtfMapDef pub fn aya_obj::maps::BtfMapDef::default() -> aya_obj::maps::BtfMapDef @@ -5659,7 +5659,7 @@ pub aya_obj::maps::bpf_map_def::value_size: u32 impl core::clone::Clone for aya_obj::maps::bpf_map_def pub fn aya_obj::maps::bpf_map_def::clone(&self) -> aya_obj::maps::bpf_map_def impl core::cmp::Eq for aya_obj::maps::bpf_map_def -impl core::cmp::PartialEq for aya_obj::maps::bpf_map_def +impl core::cmp::PartialEq for aya_obj::maps::bpf_map_def pub fn aya_obj::maps::bpf_map_def::eq(&self, other: &aya_obj::maps::bpf_map_def) -> bool impl core::default::Default for aya_obj::maps::bpf_map_def pub fn aya_obj::maps::bpf_map_def::default() -> aya_obj::maps::bpf_map_def @@ -5710,7 +5710,7 @@ pub aya_obj::obj::BpfSectionKind::Version impl core::clone::Clone for aya_obj::BpfSectionKind pub fn aya_obj::BpfSectionKind::clone(&self) -> aya_obj::BpfSectionKind impl core::cmp::Eq for aya_obj::BpfSectionKind -impl core::cmp::PartialEq for aya_obj::BpfSectionKind +impl core::cmp::PartialEq for aya_obj::BpfSectionKind pub fn aya_obj::BpfSectionKind::eq(&self, other: &aya_obj::BpfSectionKind) -> bool impl core::fmt::Debug for aya_obj::BpfSectionKind pub fn aya_obj::BpfSectionKind::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -6453,7 +6453,7 @@ pub aya_obj::BpfSectionKind::Version impl core::clone::Clone for aya_obj::BpfSectionKind pub fn aya_obj::BpfSectionKind::clone(&self) -> aya_obj::BpfSectionKind impl core::cmp::Eq for aya_obj::BpfSectionKind -impl core::cmp::PartialEq for aya_obj::BpfSectionKind +impl core::cmp::PartialEq for aya_obj::BpfSectionKind pub fn aya_obj::BpfSectionKind::eq(&self, other: &aya_obj::BpfSectionKind) -> bool impl core::fmt::Debug for aya_obj::BpfSectionKind pub fn aya_obj::BpfSectionKind::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 591ebaf4..5aa23f6a 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -446,7 +446,7 @@ pub struct aya::maps::perf::Events pub aya::maps::perf::Events::lost: usize pub aya::maps::perf::Events::read: usize impl core::cmp::Eq for aya::maps::perf::Events -impl core::cmp::PartialEq for aya::maps::perf::Events +impl core::cmp::PartialEq for aya::maps::perf::Events pub fn aya::maps::perf::Events::eq(&self, other: &aya::maps::perf::Events) -> bool impl core::fmt::Debug for aya::maps::perf::Events pub fn aya::maps::perf::Events::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1881,11 +1881,11 @@ pub fn aya::maps::hash_map::PerCpuHashMap::borrow_mut(&mut self) -> &mu impl core::convert::From for aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::from(t: T) -> T pub struct aya::maps::PerCpuValues -impl core::convert::TryFrom> for aya::maps::PerCpuValues +impl core::convert::TryFrom> for aya::maps::PerCpuValues pub type aya::maps::PerCpuValues::Error = std::io::error::Error pub fn aya::maps::PerCpuValues::try_from(values: alloc::vec::Vec) -> core::result::Result impl core::ops::deref::Deref for aya::maps::PerCpuValues -pub type aya::maps::PerCpuValues::Target = alloc::boxed::Box<[T], alloc::alloc::Global> +pub type aya::maps::PerCpuValues::Target = alloc::boxed::Box<[T]> pub fn aya::maps::PerCpuValues::deref(&self) -> &Self::Target impl, K: aya::Pod, V: aya::Pod> aya::maps::IterableMap> for aya::maps::hash_map::PerCpuHashMap pub fn aya::maps::hash_map::PerCpuHashMap::get(&self, key: &K) -> core::result::Result, aya::maps::MapError> @@ -2410,7 +2410,7 @@ impl core::convert::From for aya::programs::cgroup_device::CgroupDeviceLin pub fn aya::programs::cgroup_device::CgroupDeviceLink::from(t: T) -> T pub struct aya::programs::cgroup_device::CgroupDeviceLinkId(_) impl core::cmp::Eq for aya::programs::cgroup_device::CgroupDeviceLinkId -impl core::cmp::PartialEq for aya::programs::cgroup_device::CgroupDeviceLinkId +impl core::cmp::PartialEq for aya::programs::cgroup_device::CgroupDeviceLinkId pub fn aya::programs::cgroup_device::CgroupDeviceLinkId::eq(&self, other: &aya::programs::cgroup_device::CgroupDeviceLinkId) -> bool impl core::fmt::Debug for aya::programs::cgroup_device::CgroupDeviceLinkId pub fn aya::programs::cgroup_device::CgroupDeviceLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2553,7 +2553,7 @@ impl core::convert::From for aya::programs::cgroup_skb::CgroupSkbLink pub fn aya::programs::cgroup_skb::CgroupSkbLink::from(t: T) -> T pub struct aya::programs::cgroup_skb::CgroupSkbLinkId(_) impl core::cmp::Eq for aya::programs::cgroup_skb::CgroupSkbLinkId -impl core::cmp::PartialEq for aya::programs::cgroup_skb::CgroupSkbLinkId +impl core::cmp::PartialEq for aya::programs::cgroup_skb::CgroupSkbLinkId pub fn aya::programs::cgroup_skb::CgroupSkbLinkId::eq(&self, other: &aya::programs::cgroup_skb::CgroupSkbLinkId) -> bool impl core::fmt::Debug for aya::programs::cgroup_skb::CgroupSkbLinkId pub fn aya::programs::cgroup_skb::CgroupSkbLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2663,7 +2663,7 @@ impl core::convert::From for aya::programs::cgroup_sock::CgroupSockLink pub fn aya::programs::cgroup_sock::CgroupSockLink::from(t: T) -> T pub struct aya::programs::cgroup_sock::CgroupSockLinkId(_) impl core::cmp::Eq for aya::programs::cgroup_sock::CgroupSockLinkId -impl core::cmp::PartialEq for aya::programs::cgroup_sock::CgroupSockLinkId +impl core::cmp::PartialEq for aya::programs::cgroup_sock::CgroupSockLinkId pub fn aya::programs::cgroup_sock::CgroupSockLinkId::eq(&self, other: &aya::programs::cgroup_sock::CgroupSockLinkId) -> bool impl core::fmt::Debug for aya::programs::cgroup_sock::CgroupSockLinkId pub fn aya::programs::cgroup_sock::CgroupSockLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2773,7 +2773,7 @@ impl core::convert::From for aya::programs::cgroup_sock_addr::CgroupSockAd pub fn aya::programs::cgroup_sock_addr::CgroupSockAddrLink::from(t: T) -> T pub struct aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId(_) impl core::cmp::Eq for aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId -impl core::cmp::PartialEq for aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId +impl core::cmp::PartialEq for aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId pub fn aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId::eq(&self, other: &aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId) -> bool impl core::fmt::Debug for aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId pub fn aya::programs::cgroup_sock_addr::CgroupSockAddrLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2883,7 +2883,7 @@ impl core::convert::From for aya::programs::cgroup_sockopt::CgroupSockoptL pub fn aya::programs::cgroup_sockopt::CgroupSockoptLink::from(t: T) -> T pub struct aya::programs::cgroup_sockopt::CgroupSockoptLinkId(_) impl core::cmp::Eq for aya::programs::cgroup_sockopt::CgroupSockoptLinkId -impl core::cmp::PartialEq for aya::programs::cgroup_sockopt::CgroupSockoptLinkId +impl core::cmp::PartialEq for aya::programs::cgroup_sockopt::CgroupSockoptLinkId pub fn aya::programs::cgroup_sockopt::CgroupSockoptLinkId::eq(&self, other: &aya::programs::cgroup_sockopt::CgroupSockoptLinkId) -> bool impl core::fmt::Debug for aya::programs::cgroup_sockopt::CgroupSockoptLinkId pub fn aya::programs::cgroup_sockopt::CgroupSockoptLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -2993,7 +2993,7 @@ impl core::convert::From for aya::programs::cgroup_sysctl::CgroupSysctlLin pub fn aya::programs::cgroup_sysctl::CgroupSysctlLink::from(t: T) -> T pub struct aya::programs::cgroup_sysctl::CgroupSysctlLinkId(_) impl core::cmp::Eq for aya::programs::cgroup_sysctl::CgroupSysctlLinkId -impl core::cmp::PartialEq for aya::programs::cgroup_sysctl::CgroupSysctlLinkId +impl core::cmp::PartialEq for aya::programs::cgroup_sysctl::CgroupSysctlLinkId pub fn aya::programs::cgroup_sysctl::CgroupSysctlLinkId::eq(&self, other: &aya::programs::cgroup_sysctl::CgroupSysctlLinkId) -> bool impl core::fmt::Debug for aya::programs::cgroup_sysctl::CgroupSysctlLinkId pub fn aya::programs::cgroup_sysctl::CgroupSysctlLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3140,7 +3140,7 @@ impl core::convert::From for aya::programs::extension::ExtensionLink pub fn aya::programs::extension::ExtensionLink::from(t: T) -> T pub struct aya::programs::extension::ExtensionLinkId(_) impl core::cmp::Eq for aya::programs::extension::ExtensionLinkId -impl core::cmp::PartialEq for aya::programs::extension::ExtensionLinkId +impl core::cmp::PartialEq for aya::programs::extension::ExtensionLinkId pub fn aya::programs::extension::ExtensionLinkId::eq(&self, other: &aya::programs::extension::ExtensionLinkId) -> bool impl core::fmt::Debug for aya::programs::extension::ExtensionLinkId pub fn aya::programs::extension::ExtensionLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3254,7 +3254,7 @@ impl core::convert::From for aya::programs::fentry::FEntryLink pub fn aya::programs::fentry::FEntryLink::from(t: T) -> T pub struct aya::programs::fentry::FEntryLinkId(_) impl core::cmp::Eq for aya::programs::fentry::FEntryLinkId -impl core::cmp::PartialEq for aya::programs::fentry::FEntryLinkId +impl core::cmp::PartialEq for aya::programs::fentry::FEntryLinkId pub fn aya::programs::fentry::FEntryLinkId::eq(&self, other: &aya::programs::fentry::FEntryLinkId) -> bool impl core::fmt::Debug for aya::programs::fentry::FEntryLinkId pub fn aya::programs::fentry::FEntryLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3368,7 +3368,7 @@ impl core::convert::From for aya::programs::fexit::FExitLink pub fn aya::programs::fexit::FExitLink::from(t: T) -> T pub struct aya::programs::fexit::FExitLinkId(_) impl core::cmp::Eq for aya::programs::fexit::FExitLinkId -impl core::cmp::PartialEq for aya::programs::fexit::FExitLinkId +impl core::cmp::PartialEq for aya::programs::fexit::FExitLinkId pub fn aya::programs::fexit::FExitLinkId::eq(&self, other: &aya::programs::fexit::FExitLinkId) -> bool impl core::fmt::Debug for aya::programs::fexit::FExitLinkId pub fn aya::programs::fexit::FExitLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3519,7 +3519,7 @@ impl core::convert::From for aya::programs::kprobe::KProbeLink pub fn aya::programs::kprobe::KProbeLink::from(t: T) -> T pub struct aya::programs::kprobe::KProbeLinkId(_) impl core::cmp::Eq for aya::programs::kprobe::KProbeLinkId -impl core::cmp::PartialEq for aya::programs::kprobe::KProbeLinkId +impl core::cmp::PartialEq for aya::programs::kprobe::KProbeLinkId pub fn aya::programs::kprobe::KProbeLinkId::eq(&self, other: &aya::programs::kprobe::KProbeLinkId) -> bool impl core::fmt::Debug for aya::programs::kprobe::KProbeLinkId pub fn aya::programs::kprobe::KProbeLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3665,7 +3665,7 @@ impl core::convert::From for aya::programs::links::FdLink pub fn aya::programs::links::FdLink::from(t: T) -> T pub struct aya::programs::links::FdLinkId(_) impl core::cmp::Eq for aya::programs::links::FdLinkId -impl core::cmp::PartialEq for aya::programs::links::FdLinkId +impl core::cmp::PartialEq for aya::programs::links::FdLinkId pub fn aya::programs::links::FdLinkId::eq(&self, other: &aya::programs::links::FdLinkId) -> bool impl core::fmt::Debug for aya::programs::links::FdLinkId pub fn aya::programs::links::FdLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3753,7 +3753,7 @@ impl core::convert::From for aya::programs::links::ProgAttachLink pub fn aya::programs::links::ProgAttachLink::from(t: T) -> T pub struct aya::programs::links::ProgAttachLinkId(_, _, _) impl core::cmp::Eq for aya::programs::links::ProgAttachLinkId -impl core::cmp::PartialEq for aya::programs::links::ProgAttachLinkId +impl core::cmp::PartialEq for aya::programs::links::ProgAttachLinkId pub fn aya::programs::links::ProgAttachLinkId::eq(&self, other: &aya::programs::links::ProgAttachLinkId) -> bool impl core::fmt::Debug for aya::programs::links::ProgAttachLinkId pub fn aya::programs::links::ProgAttachLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -3903,7 +3903,7 @@ impl core::convert::From for aya::programs::lirc_mode2::LircLink pub fn aya::programs::lirc_mode2::LircLink::from(t: T) -> T pub struct aya::programs::lirc_mode2::LircLinkId(_, _) impl core::cmp::Eq for aya::programs::lirc_mode2::LircLinkId -impl core::cmp::PartialEq for aya::programs::lirc_mode2::LircLinkId +impl core::cmp::PartialEq for aya::programs::lirc_mode2::LircLinkId pub fn aya::programs::lirc_mode2::LircLinkId::eq(&self, other: &aya::programs::lirc_mode2::LircLinkId) -> bool impl core::fmt::Debug for aya::programs::lirc_mode2::LircLinkId pub fn aya::programs::lirc_mode2::LircLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4066,7 +4066,7 @@ impl core::convert::From for aya::programs::lsm::LsmLink pub fn aya::programs::lsm::LsmLink::from(t: T) -> T pub struct aya::programs::lsm::LsmLinkId(_) impl core::cmp::Eq for aya::programs::lsm::LsmLinkId -impl core::cmp::PartialEq for aya::programs::lsm::LsmLinkId +impl core::cmp::PartialEq for aya::programs::lsm::LsmLinkId pub fn aya::programs::lsm::LsmLinkId::eq(&self, other: &aya::programs::lsm::LsmLinkId) -> bool impl core::fmt::Debug for aya::programs::lsm::LsmLinkId pub fn aya::programs::lsm::LsmLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4126,7 +4126,7 @@ impl core::convert::From for aya::programs::perf_attach::PerfLink pub fn aya::programs::perf_attach::PerfLink::from(t: T) -> T pub struct aya::programs::perf_attach::PerfLinkId(_) impl core::cmp::Eq for aya::programs::perf_attach::PerfLinkId -impl core::cmp::PartialEq for aya::programs::perf_attach::PerfLinkId +impl core::cmp::PartialEq for aya::programs::perf_attach::PerfLinkId pub fn aya::programs::perf_attach::PerfLinkId::eq(&self, other: &aya::programs::perf_attach::PerfLinkId) -> bool impl core::fmt::Debug for aya::programs::perf_attach::PerfLinkId pub fn aya::programs::perf_attach::PerfLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4355,7 +4355,7 @@ impl core::convert::From for aya::programs::perf_event::PerfEventLink pub fn aya::programs::perf_event::PerfEventLink::from(t: T) -> T pub struct aya::programs::perf_event::PerfEventLinkId(_) impl core::cmp::Eq for aya::programs::perf_event::PerfEventLinkId -impl core::cmp::PartialEq for aya::programs::perf_event::PerfEventLinkId +impl core::cmp::PartialEq for aya::programs::perf_event::PerfEventLinkId pub fn aya::programs::perf_event::PerfEventLinkId::eq(&self, other: &aya::programs::perf_event::PerfEventLinkId) -> bool impl core::fmt::Debug for aya::programs::perf_event::PerfEventLinkId pub fn aya::programs::perf_event::PerfEventLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4392,7 +4392,7 @@ pub aya::programs::tc::TcAttachType::Ingress impl core::clone::Clone for aya::programs::tc::TcAttachType pub fn aya::programs::tc::TcAttachType::clone(&self) -> aya::programs::tc::TcAttachType impl core::cmp::Eq for aya::programs::tc::TcAttachType -impl core::cmp::PartialEq for aya::programs::tc::TcAttachType +impl core::cmp::PartialEq for aya::programs::tc::TcAttachType pub fn aya::programs::tc::TcAttachType::eq(&self, other: &aya::programs::tc::TcAttachType) -> bool impl core::fmt::Debug for aya::programs::tc::TcAttachType pub fn aya::programs::tc::TcAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4545,7 +4545,7 @@ impl core::convert::From for aya::programs::tc::SchedClassifierLink pub fn aya::programs::tc::SchedClassifierLink::from(t: T) -> T pub struct aya::programs::tc::SchedClassifierLinkId(_) impl core::cmp::Eq for aya::programs::tc::SchedClassifierLinkId -impl core::cmp::PartialEq for aya::programs::tc::SchedClassifierLinkId +impl core::cmp::PartialEq for aya::programs::tc::SchedClassifierLinkId pub fn aya::programs::tc::SchedClassifierLinkId::eq(&self, other: &aya::programs::tc::SchedClassifierLinkId) -> bool impl core::fmt::Debug for aya::programs::tc::SchedClassifierLinkId pub fn aya::programs::tc::SchedClassifierLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4687,7 +4687,7 @@ impl core::convert::From for aya::programs::tp_btf::BtfTracePointLink pub fn aya::programs::tp_btf::BtfTracePointLink::from(t: T) -> T pub struct aya::programs::tp_btf::BtfTracePointLinkId(_) impl core::cmp::Eq for aya::programs::tp_btf::BtfTracePointLinkId -impl core::cmp::PartialEq for aya::programs::tp_btf::BtfTracePointLinkId +impl core::cmp::PartialEq for aya::programs::tp_btf::BtfTracePointLinkId pub fn aya::programs::tp_btf::BtfTracePointLinkId::eq(&self, other: &aya::programs::tp_btf::BtfTracePointLinkId) -> bool impl core::fmt::Debug for aya::programs::tp_btf::BtfTracePointLinkId pub fn aya::programs::tp_btf::BtfTracePointLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4838,7 +4838,7 @@ impl core::convert::From for aya::programs::trace_point::TracePointLink pub fn aya::programs::trace_point::TracePointLink::from(t: T) -> T pub struct aya::programs::trace_point::TracePointLinkId(_) impl core::cmp::Eq for aya::programs::trace_point::TracePointLinkId -impl core::cmp::PartialEq for aya::programs::trace_point::TracePointLinkId +impl core::cmp::PartialEq for aya::programs::trace_point::TracePointLinkId pub fn aya::programs::trace_point::TracePointLinkId::eq(&self, other: &aya::programs::trace_point::TracePointLinkId) -> bool impl core::fmt::Debug for aya::programs::trace_point::TracePointLinkId pub fn aya::programs::trace_point::TracePointLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -4996,7 +4996,7 @@ impl core::convert::From for aya::programs::uprobe::UProbeLink pub fn aya::programs::uprobe::UProbeLink::from(t: T) -> T pub struct aya::programs::uprobe::UProbeLinkId(_) impl core::cmp::Eq for aya::programs::uprobe::UProbeLinkId -impl core::cmp::PartialEq for aya::programs::uprobe::UProbeLinkId +impl core::cmp::PartialEq for aya::programs::uprobe::UProbeLinkId pub fn aya::programs::uprobe::UProbeLinkId::eq(&self, other: &aya::programs::uprobe::UProbeLinkId) -> bool impl core::fmt::Debug for aya::programs::uprobe::UProbeLinkId pub fn aya::programs::uprobe::UProbeLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -5164,25 +5164,25 @@ impl core::iter::traits::collect::IntoIterator for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::IntoIter = bitflags::iter::Iter pub type aya::programs::xdp::XdpFlags::Item = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::into_iter(self) -> Self::IntoIter -impl core::ops::arith::Sub for aya::programs::xdp::XdpFlags +impl core::ops::arith::Sub for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::sub(self, other: Self) -> Self -impl core::ops::arith::SubAssign for aya::programs::xdp::XdpFlags +impl core::ops::arith::SubAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::sub_assign(&mut self, other: Self) -impl core::ops::bit::BitAnd for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitAnd for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitand(self, other: Self) -> Self -impl core::ops::bit::BitAndAssign for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitAndAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitand_assign(&mut self, other: Self) -impl core::ops::bit::BitOr for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitOr for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitor(self, other: aya::programs::xdp::XdpFlags) -> Self -impl core::ops::bit::BitOrAssign for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitOrAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitor_assign(&mut self, other: Self) -impl core::ops::bit::BitXor for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitXor for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitxor(self, other: Self) -> Self -impl core::ops::bit::BitXorAssign for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitXorAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitxor_assign(&mut self, other: Self) impl core::ops::bit::Not for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags @@ -5257,7 +5257,7 @@ impl core::convert::From for aya::programs::xdp::XdpLink pub fn aya::programs::xdp::XdpLink::from(t: T) -> T pub struct aya::programs::xdp::XdpLinkId(_) impl core::cmp::Eq for aya::programs::xdp::XdpLinkId -impl core::cmp::PartialEq for aya::programs::xdp::XdpLinkId +impl core::cmp::PartialEq for aya::programs::xdp::XdpLinkId pub fn aya::programs::xdp::XdpLinkId::eq(&self, other: &aya::programs::xdp::XdpLinkId) -> bool impl core::fmt::Debug for aya::programs::xdp::XdpLinkId pub fn aya::programs::xdp::XdpLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -5876,7 +5876,7 @@ pub aya::programs::TcAttachType::Ingress impl core::clone::Clone for aya::programs::tc::TcAttachType pub fn aya::programs::tc::TcAttachType::clone(&self) -> aya::programs::tc::TcAttachType impl core::cmp::Eq for aya::programs::tc::TcAttachType -impl core::cmp::PartialEq for aya::programs::tc::TcAttachType +impl core::cmp::PartialEq for aya::programs::tc::TcAttachType pub fn aya::programs::tc::TcAttachType::eq(&self, other: &aya::programs::tc::TcAttachType) -> bool impl core::fmt::Debug for aya::programs::tc::TcAttachType pub fn aya::programs::tc::TcAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -7330,25 +7330,25 @@ impl core::iter::traits::collect::IntoIterator for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::IntoIter = bitflags::iter::Iter pub type aya::programs::xdp::XdpFlags::Item = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::into_iter(self) -> Self::IntoIter -impl core::ops::arith::Sub for aya::programs::xdp::XdpFlags +impl core::ops::arith::Sub for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::sub(self, other: Self) -> Self -impl core::ops::arith::SubAssign for aya::programs::xdp::XdpFlags +impl core::ops::arith::SubAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::sub_assign(&mut self, other: Self) -impl core::ops::bit::BitAnd for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitAnd for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitand(self, other: Self) -> Self -impl core::ops::bit::BitAndAssign for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitAndAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitand_assign(&mut self, other: Self) -impl core::ops::bit::BitOr for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitOr for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitor(self, other: aya::programs::xdp::XdpFlags) -> Self -impl core::ops::bit::BitOrAssign for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitOrAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitor_assign(&mut self, other: Self) -impl core::ops::bit::BitXor for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitXor for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitxor(self, other: Self) -> Self -impl core::ops::bit::BitXorAssign for aya::programs::xdp::XdpFlags +impl core::ops::bit::BitXorAssign for aya::programs::xdp::XdpFlags pub fn aya::programs::xdp::XdpFlags::bitxor_assign(&mut self, other: Self) impl core::ops::bit::Not for aya::programs::xdp::XdpFlags pub type aya::programs::xdp::XdpFlags::Output = aya::programs::xdp::XdpFlags @@ -7482,9 +7482,9 @@ pub fn aya::util::KernelVersion::new(major: u8, minor: u8, patch: u16) -> Self impl core::clone::Clone for aya::util::KernelVersion pub fn aya::util::KernelVersion::clone(&self) -> aya::util::KernelVersion impl core::cmp::Eq for aya::util::KernelVersion -impl core::cmp::PartialEq for aya::util::KernelVersion +impl core::cmp::PartialEq for aya::util::KernelVersion pub fn aya::util::KernelVersion::eq(&self, other: &aya::util::KernelVersion) -> bool -impl core::cmp::PartialOrd for aya::util::KernelVersion +impl core::cmp::PartialOrd for aya::util::KernelVersion pub fn aya::util::KernelVersion::partial_cmp(&self, other: &aya::util::KernelVersion) -> core::option::Option impl core::fmt::Debug for aya::util::KernelVersion pub fn aya::util::KernelVersion::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -7730,25 +7730,25 @@ impl core::iter::traits::collect::IntoIterator for aya::VerifierLogLevel pub type aya::VerifierLogLevel::IntoIter = bitflags::iter::Iter pub type aya::VerifierLogLevel::Item = aya::VerifierLogLevel pub fn aya::VerifierLogLevel::into_iter(self) -> Self::IntoIter -impl core::ops::arith::Sub for aya::VerifierLogLevel +impl core::ops::arith::Sub for aya::VerifierLogLevel pub type aya::VerifierLogLevel::Output = aya::VerifierLogLevel pub fn aya::VerifierLogLevel::sub(self, other: Self) -> Self -impl core::ops::arith::SubAssign for aya::VerifierLogLevel +impl core::ops::arith::SubAssign for aya::VerifierLogLevel pub fn aya::VerifierLogLevel::sub_assign(&mut self, other: Self) -impl core::ops::bit::BitAnd for aya::VerifierLogLevel +impl core::ops::bit::BitAnd for aya::VerifierLogLevel pub type aya::VerifierLogLevel::Output = aya::VerifierLogLevel pub fn aya::VerifierLogLevel::bitand(self, other: Self) -> Self -impl core::ops::bit::BitAndAssign for aya::VerifierLogLevel +impl core::ops::bit::BitAndAssign for aya::VerifierLogLevel pub fn aya::VerifierLogLevel::bitand_assign(&mut self, other: Self) -impl core::ops::bit::BitOr for aya::VerifierLogLevel +impl core::ops::bit::BitOr for aya::VerifierLogLevel pub type aya::VerifierLogLevel::Output = aya::VerifierLogLevel pub fn aya::VerifierLogLevel::bitor(self, other: aya::VerifierLogLevel) -> Self -impl core::ops::bit::BitOrAssign for aya::VerifierLogLevel +impl core::ops::bit::BitOrAssign for aya::VerifierLogLevel pub fn aya::VerifierLogLevel::bitor_assign(&mut self, other: Self) -impl core::ops::bit::BitXor for aya::VerifierLogLevel +impl core::ops::bit::BitXor for aya::VerifierLogLevel pub type aya::VerifierLogLevel::Output = aya::VerifierLogLevel pub fn aya::VerifierLogLevel::bitxor(self, other: Self) -> Self -impl core::ops::bit::BitXorAssign for aya::VerifierLogLevel +impl core::ops::bit::BitXorAssign for aya::VerifierLogLevel pub fn aya::VerifierLogLevel::bitxor_assign(&mut self, other: Self) impl core::ops::bit::Not for aya::VerifierLogLevel pub type aya::VerifierLogLevel::Output = aya::VerifierLogLevel From c1b367eb4ac6aa807eb2e5ac36dcf5f60a0611f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:10:43 +0000 Subject: [PATCH 88/95] build(deps): update bindgen requirement from 0.68 to 0.69 Updates the requirements on [bindgen](https://github.com/rust-lang/rust-bindgen) to permit the latest version. - [Release notes](https://github.com/rust-lang/rust-bindgen/releases) - [Changelog](https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.68.0...v0.68.1) --- updated-dependencies: - dependency-name: bindgen dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b7accb7c..947d9131 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ aya-log-common = { path = "aya-log-common", version = "0.1.13", default-features aya-log-parser = { path = "aya-log-parser", default-features = false } aya-obj = { path = "aya-obj", version = "0.1.0", default-features = false } aya-tool = { path = "aya-tool", default-features = false } -bindgen = { version = "0.68", default-features = false } +bindgen = { version = "0.69", default-features = false } bitflags = { version = "2.2.1", default-features = false } bytes = { version = "1", default-features = false } cargo_metadata = { version = "0.18.0", default-features = false } From 42cc175aebf63fb291df1e0b42a71b8f3cc3b0cd Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 9 Nov 2023 21:29:05 +0000 Subject: [PATCH 89/95] xtask: attempt to open /dev/kvm We're seeing test failures where KVM is present but we aren't able to use it. See https://github.com/actions/runner-images/issues/7670#issuecomment-1760184162. --- xtask/src/run.rs | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 64114620..5625e037 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -2,7 +2,7 @@ use std::{ env::consts::{ARCH, OS}, ffi::OsString, fmt::Write as _, - fs::{copy, create_dir_all, metadata, File}, + fs::{copy, create_dir_all, OpenOptions}, io::{BufRead as _, BufReader, ErrorKind, Write as _}, path::{Path, PathBuf}, process::{Child, ChildStdin, Command, Output, Stdio}, @@ -284,9 +284,13 @@ pub fn run(opts: Options) -> Result<()> { let tmp_dir = tempfile::tempdir().context("tempdir failed")?; let initrd_image = tmp_dir.path().join("qemu-initramfs.img"); - let initrd_image_file = File::create(&initrd_image).with_context(|| { - format!("failed to create {} for writing", initrd_image.display()) - })?; + let initrd_image_file = OpenOptions::new() + .create_new(true) + .write(true) + .open(&initrd_image) + .with_context(|| { + format!("failed to create {} for writing", initrd_image.display()) + })?; let mut gen_init_cpio = Command::new(&gen_init_cpio); let mut gen_init_cpio_child = gen_init_cpio @@ -351,19 +355,21 @@ pub fn run(opts: Options) -> Result<()> { } if guest_arch == ARCH { match OS { - "linux" => match metadata("/dev/kvm") { - Ok(metadata) => { - use std::os::unix::fs::FileTypeExt as _; - if metadata.file_type().is_char_device() { + "linux" => { + const KVM: &str = "/dev/kvm"; + match OpenOptions::new().read(true).write(true).open(KVM) { + Ok(_file) => { qemu.args(["-accel", "kvm"]); } + Err(error) => match error.kind() { + ErrorKind::NotFound | ErrorKind::PermissionDenied => {} + _kind => { + return Err(error) + .with_context(|| format!("failed to open {KVM}")); + } + }, } - Err(error) => { - if error.kind() != ErrorKind::NotFound { - Err(error).context("failed to check existence of /dev/kvm")?; - } - } - }, + } "macos" => { qemu.args(["-accel", "hvf"]); } From 8780a50be194f7d7c41f6886f1c5de8eee4e59d0 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Thu, 10 Aug 2023 20:21:37 +0100 Subject: [PATCH 90/95] .github: Add markdownlint This adds a linter to catch common markdown formatting errors. The linter used is markdownlint-cli2 which is available on all platforms and has an associated Github Action to automate these checks in CI. Configuration is checked in at .markdownlint-cli2.yaml. You may run the check locally using `markdownlint-cli2`. Or you may install the extension for VSCode: DavidAnson.vscode-markdownlint Signed-off-by: Dave Tucker --- .github/workflows/ci.yml | 6 ++++- .markdownlint-cli2.yaml | 8 +++++++ CODE_OF_CONDUCT.md | 10 ++++---- CONTRIBUTING.md | 48 ++++++++++++++++++++++----------------- README.md | 21 +++++++++-------- aya/README.md | 23 ++++++++++--------- bpf/aya-bpf-cty/README.md | 9 ++++---- test/README.md | 11 ++++----- 8 files changed, 77 insertions(+), 59 deletions(-) create mode 100644 .markdownlint-cli2.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59bff5bf..b55e57bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,8 +35,12 @@ jobs: - name: Check C formatting run: git ls-files -- '*.c' '*.h' | xargs clang-format --dry-run --Werror + + - name: Check Markdown + uses: DavidAnson/markdownlint-cli2-action@v9 - - run: taplo fmt --check + - name: Check TOML formatting + run: taplo fmt --check - name: Check formatting run: cargo fmt --all -- --check diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml new file mode 100644 index 00000000..33e410af --- /dev/null +++ b/.markdownlint-cli2.yaml @@ -0,0 +1,8 @@ +config: + no-duplicate-heading: false + +globs: + - "**/*.md" +ignores: + - "target/**/*" + - "xtask/libbpf/**/*" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 57c1b866..0d9ca6f7 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -115,14 +115,14 @@ the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. +version 2.0, available [here][covenant-2-0]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org +[covenant-2-0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. +For answers to common questions about this code of conduct, see the +[FAQ](https://www.contributor-covenant.org/faq). Translations are available +[here](https://www.contributor-covenant.org/translations). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 34ada6e8..4f2cb6a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,12 +17,16 @@ version of aya you're using and which version of the linux kernel. If you find an API that is not documented, unclear or missing examples, please file an issue. If you make changes to the documentation, please read -https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html and make sure -your changes conform to the format outlined here -https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html#documenting-components. +[How To Write Documentation] and make sure your changes conform to the +format outlined in [Documenting Components]. -If you want to make changes to the Aya Book, see the readme in the book repo -https://github.com/aya-rs/book. +[How To Write Documentation]: https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html +[Documenting Components]: https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html#documenting-components + +If you want to make changes to the Aya Book, see the readme in the +[book repository]. + +[book repository]: https://github.com/aya-rs/book ## Fixing bugs and implementing new features @@ -31,7 +35,11 @@ helps us avoid duplicating work. If your work includes publicly visible changes, make sure those are properly documented as explained in the section above. ### Running tests -Run the unit tests with `cargo test`. See [Aya Integration Tests](https://github.com/aya-rs/aya/blob/main/test/README.md) regarding running the integration tests. + +Run the unit tests with `cargo test`. See [Aya Integration Tests] regarding +running the integration tests. + +[Aya Integration Tests]: https://github.com/aya-rs/aya/blob/main/test/README.md ### Commits @@ -45,21 +53,19 @@ change, please squash those together before asking for a review. A good commit message should describe what changed and why. 1. The first line should: - - * contain a short description of the change (preferably 50 characters or less, - and no more than 72 characters) - * be entirely in lowercase with the exception of proper nouns, acronyms, and - the words that refer to code, like function/variable names - * be prefixed with the name of the sub crate being changed - - Examples: - - * aya: handle reordered functions - * aya-bpf: SkSkbContext: add ::l3_csum_replace - -2. Keep the second line blank. -3. Wrap all other lines at 72 columns (except for long URLs). -4. If your patch fixes an open issue, you can add a reference to it at the end + - Contain a short description of the change (preferably 50 characters or less, + and no more than 72 characters) + - Be entirely in lowercase with the exception of proper nouns, acronyms, and + the words that refer to code, like function/variable names + - Be prefixed with the name of the sub crate being changed + + Examples: + - `aya: handle reordered functions` + - `aya-bpf: SkSkbContext: add ::l3_csum_replace` + +1. Keep the second line blank. +1. Wrap all other lines at 72 columns (except for long URLs). +1. If your patch fixes an open issue, you can add a reference to it at the end of the log. Use the `Fixes: #` prefix and the issue number. For other references use `Refs: #`. `Refs` may include multiple issues, separated by a comma. diff --git a/README.md b/README.md index 9b4e2b42..cb2d2222 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![Build status][build-badge]][build-url] [![Book][book-badge]][book-url] - [crates-badge]: https://img.shields.io/crates/v/aya.svg?style=for-the-badge&logo=rust [crates-url]: https://crates.io/crates/aya [license-badge]: https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=for-the-badge @@ -27,8 +26,8 @@ [![Discord][discord-badge]][chat-url] [![Awesome][awesome-badge]][awesome-aya] -Join [the conversation on Discord][chat-url] to discuss anything related to Aya, or discover -and contribute to a list of [Awesome Aya][awesome-aya] projects. +Join [the conversation on Discord][chat-url] to discuss anything related to Aya +or discover and contribute to a list of [Awesome Aya][awesome-aya] projects. [discord-badge]: https://img.shields.io/badge/Discord-chat-5865F2?style=for-the-badge&logo=discord [chat-url]: https://discord.gg/xHW2cb2N6G @@ -38,7 +37,7 @@ and contribute to a list of [Awesome Aya][awesome-aya] projects. ## Overview eBPF is a technology that allows running user-supplied programs inside the Linux -kernel. For more info see https://ebpf.io/what-is-ebpf. +kernel. For more info see [What is eBBF](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] nor [bcc] - it's built from the ground @@ -70,9 +69,8 @@ Some of the major features provided include: ### Example -Aya supports a large chunk of the eBPF API. The following example shows how to use a -`BPF_PROG_TYPE_CGROUP_SKB` program with aya: - +Aya supports a large chunk of the eBPF API. The following example shows how to +use a `BPF_PROG_TYPE_CGROUP_SKB` program with aya: ```rust use std::fs::File; @@ -97,12 +95,15 @@ ingress.attach(cgroup, CgroupSkbAttachType::Ingress)?; ## Contributing Please see the [contributing guide](https://github.com/aya-rs/aya/blob/main/CONTRIBUTING.md). + ## License -Aya is distributed under the terms of either the [MIT license] or the [Apache License] (version -2.0), at your option. +Aya is distributed under the terms of either the [MIT license] or the +[Apache License] (version 2.0), at your option. -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. [MIT license]: https://github.com/aya-rs/aya/blob/main/LICENSE-MIT [Apache license]: https://github.com/aya-rs/aya/blob/main/LICENSE-APACHE diff --git a/aya/README.md b/aya/README.md index 873612af..f64767f9 100644 --- a/aya/README.md +++ b/aya/README.md @@ -5,11 +5,10 @@ ![Build status][build-badge] [![Book][book-badge]][book-url] - [crates-badge]: https://img.shields.io/crates/v/aya.svg?style=for-the-badge&logo=rust [crates-url]: https://crates.io/crates/aya [license-badge]: https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=for-the-badge -[build-badge]: https://img.shields.io/github/workflow/status/aya-rs/aya/build-aya?style=for-the-badge&logo=github +[build-badge]: https://img.shields.io/github/actions/workflow/status/aya-rs/aya/build-aya.yml?branch=main&style=for-the-badge [book-badge]: https://img.shields.io/badge/read%20the-book-9cf.svg?style=for-the-badge&logo=mdbook [book-url]: https://aya-rs.dev/book @@ -26,8 +25,8 @@ [![Discord][discord-badge]][chat-url] [![Awesome][awesome-badge]][awesome-aya] -Join [the conversation on Discord][chat-url] to discuss anything related to Aya, or discover -and contribute to a list of [Awesome Aya][awesome-aya] projects. +Join [the conversation on Discord][chat-url] to discuss anything related to Aya +or discover and contribute to a list of [Awesome Aya][awesome-aya] projects. [discord-badge]: https://img.shields.io/badge/Discord-chat-5865F2?style=for-the-badge&logo=discord [chat-url]: https://discord.gg/xHW2cb2N6G @@ -37,7 +36,7 @@ and contribute to a list of [Awesome Aya][awesome-aya] projects. ## Overview eBPF is a technology that allows running user-supplied programs inside the Linux -kernel. For more info see https://ebpf.io/what-is-ebpf. +kernel. For more info see [What is eBBF](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] nor [bcc] - it's built from the ground @@ -69,9 +68,8 @@ Some of the major features provided include: ### Example -Aya supports a large chunk of the eBPF API. The following example shows how to use a -`BPF_PROG_TYPE_CGROUP_SKB` program with aya: - +Aya supports a large chunk of the eBPF API. The following example shows how to +use a `BPF_PROG_TYPE_CGROUP_SKB` program with aya: ```rust use std::fs::File; @@ -96,12 +94,15 @@ ingress.attach(cgroup, CgroupSkbAttachType::Ingress)?; ## Contributing Please see the [contributing guide](https://github.com/aya-rs/aya/blob/main/CONTRIBUTING.md). + ## License -Aya is distributed under the terms of either the [MIT license] or the [Apache License] (version -2.0), at your option. +Aya is distributed under the terms of either the [MIT license] or the +[Apache License] (version 2.0), at your option. -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. [MIT license]: https://github.com/aya-rs/aya/blob/main/LICENSE-MIT [Apache license]: https://github.com/aya-rs/aya/blob/main/LICENSE-APACHE diff --git a/bpf/aya-bpf-cty/README.md b/bpf/aya-bpf-cty/README.md index f5d09bd4..122e7b69 100644 --- a/bpf/aya-bpf-cty/README.md +++ b/bpf/aya-bpf-cty/README.md @@ -1,17 +1,16 @@ +# `cty` + [![crates.io](https://img.shields.io/crates/v/cty.svg)](https://crates.io/crates/cty) [![crates.io](https://img.shields.io/crates/d/cty.svg)](https://crates.io/crates/cty) -# `cty` - > Type aliases to C types like c_int for use with bindgen ## License Licensed under either of -- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) -- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +- Apache License, Version 2.0 [LICENSE-APACHE](./LICENSE-APACHE) or +- MIT license [LICENSE-MIT](./LICENSE-MIT) at your option. diff --git a/test/README.md b/test/README.md index 82e41da0..5a0db31b 100644 --- a/test/README.md +++ b/test/README.md @@ -1,5 +1,4 @@ -Aya Integration Tests -===================== +# Aya Integration Tests The aya integration test suite is a set of tests to ensure that common usage behaviours work on real Linux distros @@ -19,13 +18,13 @@ From the root of this repository: ### Native -``` +```bash cargo xtask integration-test local ``` ### Virtualized -``` +```bash cargo xtask integration-test vm ``` @@ -41,5 +40,5 @@ Tests should follow these guidelines: constants in `integration-test/src/lib.rs` using `include_bytes_aligned!`. - Tests should be added to `integration-test/tests`. - You may add a new module, or use an existing one. -- Test functions should not return `anyhow::Result<()>` since this produces errors without stack - traces. Prefer to `panic!` instead. +- Test functions should not return `anyhow::Result<()>` since this produces + errors without stack traces. Prefer to `panic!` instead. From 68ba02002fbd3bcf157c72b8212a697551cae8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Medina?= Date: Fri, 10 Nov 2023 11:23:47 -0800 Subject: [PATCH 91/95] aya: make KernelVersion::code public --- aya/src/util.rs | 2 +- xtask/public-api/aya.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/aya/src/util.rs b/aya/src/util.rs index 3184dae4..149f1a97 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -53,7 +53,7 @@ impl KernelVersion { } /// The equivalent of LINUX_VERSION_CODE. - pub(crate) fn code(self) -> u32 { + pub fn code(self) -> u32 { let Self { major, minor, diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 5aa23f6a..28a82b88 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -7477,6 +7477,7 @@ pub fn aya::programs::loaded_programs() -> impl core::iter::traits::iterator::It pub mod aya::util pub struct aya::util::KernelVersion impl aya::util::KernelVersion +pub fn aya::util::KernelVersion::code(self) -> u32 pub fn aya::util::KernelVersion::current() -> core::result::Result pub fn aya::util::KernelVersion::new(major: u8, minor: u8, patch: u16) -> Self impl core::clone::Clone for aya::util::KernelVersion From 36420d929734beb7486cc5d14944fc7cf8e9b62a Mon Sep 17 00:00:00 2001 From: Adam Preuss Date: Fri, 1 Sep 2023 14:34:21 +0000 Subject: [PATCH 92/95] aya: support loading a map by fd This adds support to loading maps by fd similarly to the way programs can be loaded by fd. --- aya/src/maps/mod.rs | 44 ++++++++++++++++++++++++++++++++++++++-- aya/src/sys/bpf.rs | 15 ++++++++++++++ xtask/public-api/aya.txt | 1 + 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index a934d361..ceab7307 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -68,8 +68,9 @@ use crate::{ obj::{self, parse_map_info, BpfSectionKind}, pin::PinError, sys::{ - bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_info_by_fd, - bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, SyscallError, + bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_fd_by_id, + bpf_map_get_info_by_fd, bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, + SyscallError, }, util::{nr_cpus, KernelVersion}, PinningType, Pod, @@ -648,6 +649,13 @@ impl MapData { }) } + /// Loads a map from a map id. + pub fn from_id(id: u32) -> Result { + bpf_map_get_fd_by_id(id) + .map_err(MapError::from) + .and_then(Self::from_fd) + } + /// Loads a map from a file descriptor. /// /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`](crate::maps::MapData::from_pin). @@ -935,6 +943,38 @@ mod tests { }) } + #[test] + fn test_from_map_id() { + override_syscall(|call| match call { + Syscall::Bpf { + cmd: bpf_cmd::BPF_MAP_GET_FD_BY_ID, + attr, + } => { + assert_eq!( + unsafe { attr.__bindgen_anon_6.__bindgen_anon_1.map_id }, + 1234 + ); + Ok(42) + } + Syscall::Bpf { + cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, + attr, + } => { + assert_eq!(unsafe { attr.info.bpf_fd }, 42); + Ok(0) + } + _ => Err((-1, io::Error::from_raw_os_error(EFAULT))), + }); + + assert_matches!( + MapData::from_id(1234), + Ok(MapData { + obj: _, + fd, + }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) + ); + } + #[test] fn test_create() { override_syscall(|call| match call { diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index dd42120a..511f0163 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -550,6 +550,21 @@ pub(crate) fn bpf_prog_get_info_by_fd( }) } +pub(crate) fn bpf_map_get_fd_by_id(map_id: u32) -> Result { + let mut attr = unsafe { mem::zeroed::() }; + + attr.__bindgen_anon_6.__bindgen_anon_1.map_id = map_id; + + // SAFETY: BPF_MAP_GET_FD_BY_ID returns a new file descriptor. + unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_GET_FD_BY_ID, &mut attr) }.map_err(|(code, io_error)| { + assert_eq!(code, -1); + SyscallError { + call: "bpf_map_get_fd_by_id", + io_error, + } + }) +} + pub(crate) fn bpf_map_get_info_by_fd(fd: BorrowedFd<'_>) -> Result { bpf_obj_get_info_by_fd(fd, |_| {}) } diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 28a82b88..3650d1f3 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1686,6 +1686,7 @@ impl aya::maps::MapData pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option>) -> core::result::Result pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result +pub fn aya::maps::MapData::from_id(id: u32) -> core::result::Result pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result pub fn aya::maps::MapData::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::fmt::Debug for aya::maps::MapData From 4d24d1cfe8108365403d834e40efa3fa72983f6d Mon Sep 17 00:00:00 2001 From: Adam Preuss Date: Wed, 21 Jun 2023 19:29:54 +0000 Subject: [PATCH 93/95] aya: add MapInfo struct following the same pattern as ProgramInfo This makes the APIs for loading maps and programs more similar. --- aya/src/maps/mod.rs | 240 +++++++++++++++++++++-- aya/src/sys/bpf.rs | 4 + test/integration-test/src/tests/smoke.rs | 26 +++ xtask/public-api/aya.txt | 38 ++++ 4 files changed, 293 insertions(+), 15 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index ceab7307..fa6d73fc 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -65,12 +65,13 @@ use obj::maps::InvalidMapTypeError; use thiserror::Error; use crate::{ + generated::bpf_map_info, obj::{self, parse_map_info, BpfSectionKind}, pin::PinError, sys::{ bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_fd_by_id, bpf_map_get_info_by_fd, bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, - SyscallError, + iter_map_ids, SyscallError, }, util::{nr_cpus, KernelVersion}, PinningType, Pod, @@ -639,21 +640,14 @@ impl MapData { call: "BPF_OBJ_GET", io_error, })?; - let fd = MapFd(fd); - - let info = bpf_map_get_info_by_fd(fd.as_fd())?; - Ok(Self { - obj: parse_map_info(info, PinningType::ByName), - fd, - }) + Self::from_fd(fd) } /// Loads a map from a map id. pub fn from_id(id: u32) -> Result { - bpf_map_get_fd_by_id(id) - .map_err(MapError::from) - .and_then(Self::from_fd) + let fd = bpf_map_get_fd_by_id(id)?; + Self::from_fd(fd) } /// Loads a map from a file descriptor. @@ -662,12 +656,10 @@ impl MapData { /// This API is intended for cases where you have received a valid BPF FD from some other means. /// For example, you received an FD over Unix Domain Socket. pub fn from_fd(fd: OwnedFd) -> Result { - let info = bpf_map_get_info_by_fd(fd.as_fd())?; - - let fd = MapFd(fd); + let MapInfo(info) = MapInfo::new_from_fd(fd.as_fd())?; Ok(Self { obj: parse_map_info(info, PinningType::None), - fd, + fd: MapFd(fd), }) } @@ -723,6 +715,11 @@ impl MapData { let Self { obj, fd: _ } = self; obj } + + /// Returns the kernel's information about the loaded map. + pub fn info(&self) -> Result { + MapInfo::new_from_fd(self.fd.as_fd()) + } } /// An iterable map @@ -911,6 +908,129 @@ impl Deref for PerCpuValues { } } +/// Provides information about a loaded map, like name, id and size. +#[derive(Debug)] +pub struct MapInfo(bpf_map_info); + +impl MapInfo { + fn new_from_fd(fd: BorrowedFd<'_>) -> Result { + let info = bpf_map_get_info_by_fd(fd.as_fd())?; + Ok(Self(info)) + } + + /// Loads map info from a map id. + pub fn from_id(id: u32) -> Result { + bpf_map_get_fd_by_id(id) + .map_err(MapError::from) + .and_then(|fd| Self::new_from_fd(fd.as_fd())) + } + + /// The name of the map, limited to 16 bytes. + pub fn name(&self) -> &[u8] { + let length = self + .0 + .name + .iter() + .rposition(|ch| *ch != 0) + .map(|pos| pos + 1) + .unwrap_or(0); + + // The name field is defined as [std::os::raw::c_char; 16]. c_char may be signed or + // unsigned depending on the platform; that's why we're using from_raw_parts here. + unsafe { std::slice::from_raw_parts(self.0.name.as_ptr() as *const _, length) } + } + + /// The name of the map as a &str. If the name is not valid unicode, None is returned. + pub fn name_as_str(&self) -> Option<&str> { + std::str::from_utf8(self.name()).ok() + } + + /// The id for this map. Each map has a unique id. + pub fn id(&self) -> u32 { + self.0.id + } + + /// The map type as defined by the linux kernel enum + /// [`bpf_map_type`](https://elixir.bootlin.com/linux/v6.4.4/source/include/uapi/linux/bpf.h#L905). + pub fn map_type(&self) -> u32 { + self.0.type_ + } + + /// The key size for this map. + pub fn key_size(&self) -> u32 { + self.0.key_size + } + + /// The value size for this map. + pub fn value_size(&self) -> u32 { + self.0.value_size + } + + /// The maximum number of entries in this map. + pub fn max_entries(&self) -> u32 { + self.0.max_entries + } + + /// The flags for this map. + pub fn map_flags(&self) -> u32 { + self.0.map_flags + } + + /// Returns a file descriptor referencing the map. + /// + /// The returned file descriptor can be closed at any time and doing so does + /// not influence the life cycle of the map. + pub fn fd(&self) -> Result { + let Self(info) = self; + let fd = bpf_map_get_fd_by_id(info.id)?; + Ok(MapFd(fd)) + } + + /// Loads a map from a pinned path in bpffs. + pub fn from_pin>(path: P) -> Result { + use std::os::unix::ffi::OsStrExt as _; + + // TODO: avoid this unwrap by adding a new error variant. + let path_string = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap(); + let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError { + call: "BPF_OBJ_GET", + io_error, + })?; + + Self::new_from_fd(fd.as_fd()) + } +} + +/// Returns an iterator over all loaded bpf maps. +/// +/// This differs from [`crate::Bpf::maps`] since it will return all maps +/// listed on the host system and not only maps for a specific [`crate::Bpf`] instance. +/// +/// # Example +/// ``` +/// # use aya::maps::loaded_maps; +/// +/// for m in loaded_maps() { +/// match m { +/// Ok(map) => println!("{:?}", map.name_as_str()), +/// Err(e) => println!("Error iterating maps: {:?}", e), +/// } +/// } +/// ``` +/// +/// # Errors +/// +/// Returns [`MapError::SyscallError`] if any of the syscalls required to either get +/// next map id, get the map fd, or the [`MapInfo`] fail. In cases where +/// iteration can't be performed, for example the caller does not have the necessary privileges, +/// a single item will be yielded containing the error that occurred. +pub fn loaded_maps() -> impl Iterator> { + iter_map_ids().map(|id| { + let id = id?; + MapInfo::from_id(id) + }) +} + #[cfg(test)] mod tests { use std::os::fd::AsRawFd as _; @@ -994,6 +1114,96 @@ mod tests { ); } + #[test] + // Syscall overrides are performing integer-to-pointer conversions, which + // should be done with `ptr::from_exposed_addr` in Rust nightly, but we have + // to support stable as well. + #[cfg_attr(miri, ignore)] + fn test_name() { + use crate::generated::bpf_map_info; + + const TEST_NAME: &str = "foo"; + + override_syscall(|call| match call { + Syscall::Bpf { + cmd: bpf_cmd::BPF_MAP_CREATE, + .. + } => Ok(42), + Syscall::Bpf { + cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, + attr, + } => { + assert_eq!( + unsafe { attr.info.info_len }, + mem::size_of::() as u32 + ); + let map_info = unsafe { &mut *(attr.info.info as *mut bpf_map_info) }; + map_info.name[..TEST_NAME.len()] + .copy_from_slice(unsafe { std::mem::transmute(TEST_NAME) }); + Ok(0) + } + _ => Err((-1, io::Error::from_raw_os_error(EFAULT))), + }); + + let map_data = MapData::create(new_obj_map(), TEST_NAME, None).unwrap(); + assert_eq!(TEST_NAME, map_data.info().unwrap().name_as_str().unwrap()); + } + + #[test] + // Syscall overrides are performing integer-to-pointer conversions, which + // should be done with `ptr::from_exposed_addr` in Rust nightly, but we have + // to support stable as well. + #[cfg_attr(miri, ignore)] + fn test_loaded_maps() { + use crate::generated::bpf_map_info; + + override_syscall(|call| match call { + Syscall::Bpf { + cmd: bpf_cmd::BPF_MAP_GET_NEXT_ID, + attr, + } => unsafe { + let id = attr.__bindgen_anon_6.__bindgen_anon_1.start_id; + if id < 5 { + attr.__bindgen_anon_6.next_id = id + 1; + Ok(0) + } else { + Err((-1, io::Error::from_raw_os_error(libc::ENOENT))) + } + }, + Syscall::Bpf { + cmd: bpf_cmd::BPF_MAP_GET_FD_BY_ID, + attr, + } => Ok((1000 + unsafe { attr.__bindgen_anon_6.__bindgen_anon_1.map_id }) as c_long), + Syscall::Bpf { + cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, + attr, + } => { + let map_info = unsafe { &mut *(attr.info.info as *mut bpf_map_info) }; + map_info.id = unsafe { attr.info.bpf_fd } - 1000; + map_info.key_size = 32; + map_info.value_size = 64; + map_info.map_flags = 1234; + map_info.max_entries = 99; + Ok(0) + } + _ => Err((-1, io::Error::from_raw_os_error(EFAULT))), + }); + + let loaded_maps: Vec<_> = loaded_maps().collect(); + assert_eq!(loaded_maps.len(), 5); + + for (i, map_info) in loaded_maps.into_iter().enumerate() { + let i = i + 1; + let map_info = map_info.unwrap(); + assert_eq!(map_info.id(), i as u32); + assert_eq!(map_info.key_size(), 32); + assert_eq!(map_info.value_size(), 64); + assert_eq!(map_info.map_flags(), 1234); + assert_eq!(map_info.max_entries(), 99); + assert_eq!(map_info.fd().unwrap().as_fd().as_raw_fd(), 1000 + i as i32); + } + } + #[test] fn test_create_failed() { override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 511f0163..a971234f 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -1049,6 +1049,10 @@ pub(crate) fn iter_link_ids() -> impl Iterator> iter_obj_ids(bpf_cmd::BPF_LINK_GET_NEXT_ID, "bpf_link_get_next_id") } +pub(crate) fn iter_map_ids() -> impl Iterator> { + iter_obj_ids(bpf_cmd::BPF_MAP_GET_NEXT_ID, "bpf_map_get_next_id") +} + pub(crate) fn retry_with_verifier_logs( max_retries: usize, f: impl Fn(&mut [u8]) -> SysResult, diff --git a/test/integration-test/src/tests/smoke.rs b/test/integration-test/src/tests/smoke.rs index 2b01938d..13204557 100644 --- a/test/integration-test/src/tests/smoke.rs +++ b/test/integration-test/src/tests/smoke.rs @@ -1,4 +1,5 @@ use aya::{ + maps::loaded_maps, programs::{loaded_programs, Extension, TracePoint, Xdp, XdpFlags}, util::KernelVersion, Bpf, BpfLoader, @@ -98,3 +99,28 @@ fn list_loaded_programs() { prog.loaded_at(); prog.fd().unwrap(); } + +#[test] +fn list_loaded_maps() { + // Load a program with maps. + let mut bpf = Bpf::load(crate::MAP_TEST).unwrap(); + let dispatcher: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + dispatcher.load().unwrap(); + dispatcher.attach("lo", XdpFlags::default()).unwrap(); + + // Ensure the loaded_maps() api doesn't panic and retrieve a map. + let map = loaded_maps() + .map(|m| m.unwrap()) + .find(|m| m.name_as_str().unwrap() == "FOO") + .unwrap(); + + // Ensure all relevant helper functions don't panic. + map.name(); + map.id(); + map.map_type(); + map.key_size(); + map.value_size(); + map.max_entries(); + map.map_flags(); + map.fd().unwrap(); +} diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 3650d1f3..196e0cec 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1688,6 +1688,7 @@ pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result pub fn aya::maps::MapData::from_id(id: u32) -> core::result::Result pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result +pub fn aya::maps::MapData::info(&self) -> core::result::Result pub fn aya::maps::MapData::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::fmt::Debug for aya::maps::MapData pub fn aya::maps::MapData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result @@ -1738,6 +1739,42 @@ impl core::borrow::BorrowMut for aya::maps::MapFd where T: core::marker::S pub fn aya::maps::MapFd::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::MapFd pub fn aya::maps::MapFd::from(t: T) -> T +pub struct aya::maps::MapInfo(_) +impl aya::maps::MapInfo +pub fn aya::maps::MapInfo::fd(&self) -> core::result::Result +pub fn aya::maps::MapInfo::from_id(id: u32) -> core::result::Result +pub fn aya::maps::MapInfo::from_pin>(path: P) -> core::result::Result +pub fn aya::maps::MapInfo::id(&self) -> u32 +pub fn aya::maps::MapInfo::key_size(&self) -> u32 +pub fn aya::maps::MapInfo::map_flags(&self) -> u32 +pub fn aya::maps::MapInfo::map_type(&self) -> u32 +pub fn aya::maps::MapInfo::max_entries(&self) -> u32 +pub fn aya::maps::MapInfo::name(&self) -> &[u8] +pub fn aya::maps::MapInfo::name_as_str(&self) -> core::option::Option<&str> +pub fn aya::maps::MapInfo::value_size(&self) -> u32 +impl core::fmt::Debug for aya::maps::MapInfo +pub fn aya::maps::MapInfo::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Send for aya::maps::MapInfo +impl core::marker::Sync for aya::maps::MapInfo +impl core::marker::Unpin for aya::maps::MapInfo +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::MapInfo +impl core::panic::unwind_safe::UnwindSafe for aya::maps::MapInfo +impl core::convert::Into for aya::maps::MapInfo where U: core::convert::From +pub fn aya::maps::MapInfo::into(self) -> U +impl core::convert::TryFrom for aya::maps::MapInfo where U: core::convert::Into +pub type aya::maps::MapInfo::Error = core::convert::Infallible +pub fn aya::maps::MapInfo::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::MapInfo where U: core::convert::TryFrom +pub type aya::maps::MapInfo::Error = >::Error +pub fn aya::maps::MapInfo::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::MapInfo where T: 'static + core::marker::Sized +pub fn aya::maps::MapInfo::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::MapInfo where T: core::marker::Sized +pub fn aya::maps::MapInfo::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::MapInfo where T: core::marker::Sized +pub fn aya::maps::MapInfo::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::MapInfo +pub fn aya::maps::MapInfo::from(t: T) -> T pub struct aya::maps::MapIter<'coll, K: aya::Pod, V, I: aya::maps::IterableMap> impl> core::iter::traits::iterator::Iterator for aya::maps::MapIter<'_, K, V, I> pub type aya::maps::MapIter<'_, K, V, I>::Item = core::result::Result<(K, V), aya::maps::MapError> @@ -2289,6 +2326,7 @@ pub fn aya::maps::PerCpuArray::map(&self) -> &aya::maps::MapData impl> aya::maps::IterableMap for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core::result::Result pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData +pub fn aya::maps::loaded_maps() -> impl core::iter::traits::iterator::Iterator> pub mod aya::pin pub enum aya::pin::PinError pub aya::pin::PinError::InvalidPinPath From 15faca8b2eddfad22594824cc634bfa1e540eeaa Mon Sep 17 00:00:00 2001 From: Adam Preuss Date: Tue, 31 Oct 2023 21:05:34 +0000 Subject: [PATCH 94/95] aya: extracting program and map names with the same function --- aya/src/maps/mod.rs | 14 ++------------ aya/src/programs/mod.rs | 14 ++------------ aya/src/util.rs | 9 +++++++++ 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index fa6d73fc..c81e7bb0 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -73,7 +73,7 @@ use crate::{ bpf_map_get_info_by_fd, bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, iter_map_ids, SyscallError, }, - util::{nr_cpus, KernelVersion}, + util::{bytes_of_bpf_name, nr_cpus, KernelVersion}, PinningType, Pod, }; @@ -927,17 +927,7 @@ impl MapInfo { /// The name of the map, limited to 16 bytes. pub fn name(&self) -> &[u8] { - let length = self - .0 - .name - .iter() - .rposition(|ch| *ch != 0) - .map(|pos| pos + 1) - .unwrap_or(0); - - // The name field is defined as [std::os::raw::c_char; 16]. c_char may be signed or - // unsigned depending on the platform; that's why we're using from_raw_parts here. - unsafe { std::slice::from_raw_parts(self.0.name.as_ptr() as *const _, length) } + bytes_of_bpf_name(&self.0.name) } /// The name of the map as a &str. If the name is not valid unicode, None is returned. diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 64da0fdf..fcbbce86 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -117,7 +117,7 @@ use crate::{ bpf_prog_query, iter_link_ids, iter_prog_ids, retry_with_verifier_logs, BpfLoadProgramAttrs, SyscallError, }, - util::KernelVersion, + util::{bytes_of_bpf_name, KernelVersion}, VerifierLogLevel, }; @@ -1002,17 +1002,7 @@ impl ProgramInfo { /// The name of the program as was provided when it was load. This is limited to 16 bytes pub fn name(&self) -> &[u8] { - let length = self - .0 - .name - .iter() - .rposition(|ch| *ch != 0) - .map(|pos| pos + 1) - .unwrap_or(0); - - // The name field is defined as [std::os::raw::c_char; 16]. c_char may be signed or - // unsigned depending on the platform; that's why we're using from_raw_parts here - unsafe { std::slice::from_raw_parts(self.0.name.as_ptr() as *const _, length) } + bytes_of_bpf_name(&self.0.name) } /// The name of the program as a &str. If the name was not valid unicode, None is returned. diff --git a/aya/src/util.rs b/aya/src/util.rs index 149f1a97..4e91d081 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -364,6 +364,15 @@ pub(crate) fn bytes_of_slice(val: &[T]) -> &[u8] { unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) } } +pub(crate) fn bytes_of_bpf_name(bpf_name: &[core::ffi::c_char; 16]) -> &[u8] { + let length = bpf_name + .iter() + .rposition(|ch| *ch != 0) + .map(|pos| pos + 1) + .unwrap_or(0); + unsafe { std::slice::from_raw_parts(bpf_name.as_ptr() as *const _, length) } +} + #[cfg(test)] mod tests { use assert_matches::assert_matches; From 8e485bc77aaa49d41063853f83ab6017d334939e Mon Sep 17 00:00:00 2001 From: lyuts Date: Sat, 18 Nov 2023 15:19:46 -0800 Subject: [PATCH 95/95] aya-log-parser: add support of :p format --- aya-log-parser/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/aya-log-parser/src/lib.rs b/aya-log-parser/src/lib.rs index 8e4f30a7..cdce04e0 100644 --- a/aya-log-parser/src/lib.rs +++ b/aya-log-parser/src/lib.rs @@ -55,7 +55,7 @@ fn push_literal(frag: &mut Vec, unescaped_literal: &str) -> Result<(), /// Parses the display hint (e.g. the `ipv4` in `{:ipv4}`). fn parse_display_hint(s: &str) -> Result { Ok(match s { - "x" => DisplayHint::LowerHex, + "p" | "x" => DisplayHint::LowerHex, "X" => DisplayHint::UpperHex, "i" => DisplayHint::Ip, "mac" => DisplayHint::LowerMac, @@ -145,7 +145,7 @@ mod test { #[test] fn test_parse() { assert_eq!( - parse("foo {} bar {:x} test {:X} ayy {:i} lmao {{}} {{something}}"), + parse("foo {} bar {:x} test {:X} ayy {:i} lmao {{}} {{something}} {:p}"), Ok(vec![ Fragment::Literal("foo ".into()), Fragment::Parameter(Parameter { @@ -163,7 +163,10 @@ mod test { Fragment::Parameter(Parameter { hint: DisplayHint::Ip }), - Fragment::Literal(" lmao {} {something}".into()), + Fragment::Literal(" lmao {} {something} ".into()), + Fragment::Parameter(Parameter { + hint: DisplayHint::LowerHex + }), ]) ); assert!(parse("foo {:}").is_err());