From a98b638fa95fd8edb8c015ee03154d2f03ecffc8 Mon Sep 17 00:00:00 2001 From: "Christian A. Jacobsen" Date: Wed, 15 Oct 2025 09:28:57 +0200 Subject: [PATCH 01/19] feat(log): add support for logging raw pointer types * Requires the usage of `:p` display hint. * Will, like stdlib, log with `0x` prefix. --- aya-log-common/src/lib.rs | 22 ++++++++++++ aya-log-ebpf-macros/src/expand.rs | 3 ++ aya-log-parser/src/lib.rs | 5 +-- aya-log/src/lib.rs | 47 ++++++++++++++++++++++++++ ebpf/aya-log-ebpf/src/lib.rs | 3 +- test/integration-ebpf/src/log.rs | 2 ++ test/integration-test/src/tests/log.rs | 9 +++++ xtask/public-api/aya-log-common.txt | 9 +++++ xtask/public-api/aya-log.txt | 31 +++++++++++++++++ 9 files changed, 128 insertions(+), 3 deletions(-) diff --git a/aya-log-common/src/lib.rs b/aya-log-common/src/lib.rs index 37591f7e..449c891b 100644 --- a/aya-log-common/src/lib.rs +++ b/aya-log-common/src/lib.rs @@ -97,6 +97,10 @@ impl LowerMacFormatter for [u8; 6] {} pub trait UpperMacFormatter {} impl UpperMacFormatter for [u8; 6] {} +pub trait PointerFormatter {} +impl PointerFormatter for *const T {} +impl PointerFormatter for *mut T {} + #[repr(u8)] #[derive(Copy, Clone, Debug, IntoPrimitive)] pub enum RecordFieldKind { @@ -144,6 +148,8 @@ pub enum ArgumentKind { Bytes, Str, + + Pointer, } /// All display hints @@ -162,6 +168,8 @@ pub enum DisplayHint { LowerMac, /// `:MAC` UpperMac, + /// `:p` + Pointer, } mod sealed { @@ -282,6 +290,20 @@ impl Argument for DisplayHint { } } +impl sealed::Sealed for *const T {} +impl Argument for *const T { + fn as_argument(&self) -> (ArgumentKind, impl AsRef<[u8]>) { + (ArgumentKind::Pointer, (*self as usize).to_ne_bytes()) + } +} + +impl sealed::Sealed for *mut T {} +impl Argument for *mut T { + fn as_argument(&self) -> (ArgumentKind, impl AsRef<[u8]>) { + (ArgumentKind::Pointer, (*self as usize).to_ne_bytes()) + } +} + fn wire_len(value: &[u8]) -> Option<[u8; 2]> { match LogValueLength::try_from(value.len()) { Ok(wire_len) => Some(wire_len.to_ne_bytes()), diff --git a/aya-log-ebpf-macros/src/expand.rs b/aya-log-ebpf-macros/src/expand.rs index ab8dfc9e..24345092 100644 --- a/aya-log-ebpf-macros/src/expand.rs +++ b/aya-log-ebpf-macros/src/expand.rs @@ -127,6 +127,9 @@ pub(crate) fn log(args: LogArgs, level_expr: Option) -> Result { (quote!(DisplayHint::UpperMac), quote!(UpperMacFormatter)) } + DisplayHint::Pointer => { + (quote!(DisplayHint::Pointer), quote!(PointerFormatter)) + } }; let hint = quote!(::aya_log_ebpf::macro_support::#hint); let arg = quote!( diff --git a/aya-log-parser/src/lib.rs b/aya-log-parser/src/lib.rs index d01a17ed..8f3e9eb9 100644 --- a/aya-log-parser/src/lib.rs +++ b/aya-log-parser/src/lib.rs @@ -59,11 +59,12 @@ fn parse_param(input: &str) -> Result { let hint = match input.strip_prefix(":") { Some(input) => match input { "" => return Err("malformed format string (missing display hint after ':')".into()), - "p" | "x" => DisplayHint::LowerHex, + "x" => DisplayHint::LowerHex, "X" => DisplayHint::UpperHex, "i" => DisplayHint::Ip, "mac" => DisplayHint::LowerMac, "MAC" => DisplayHint::UpperMac, + "p" => DisplayHint::Pointer, input => return Err(format!("unknown display hint: {input:?}")), }, None => { @@ -155,7 +156,7 @@ mod test { }), Fragment::Literal(" lmao {} {something} ".into()), Fragment::Parameter(Parameter { - hint: DisplayHint::LowerHex + hint: DisplayHint::Pointer }), ]) ); diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index 04bb79b1..9c7c6492 100644 --- a/aya-log/src/lib.rs +++ b/aya-log/src/lib.rs @@ -284,6 +284,19 @@ impl Formatter<[u8; 6]> for UpperMacFormatter { } } +pub struct PointerFormatter; +impl Formatter<*const T> for PointerFormatter { + fn format(v: *const T) -> String { + format!("{v:p}") + } +} + +impl Formatter<*mut T> for PointerFormatter { + fn format(v: *mut T) -> String { + format!("{v:p}") + } +} + trait Format { fn format(&self, last_hint: Option) -> Result; } @@ -307,6 +320,7 @@ impl Format for u32 { Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Ok(DefaultFormatter::format(self)), } } @@ -321,6 +335,7 @@ impl Format for Ipv4Addr { Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Ok(Ipv4Formatter::format(*self)), } } @@ -335,6 +350,7 @@ impl Format for Ipv6Addr { Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Ok(Ipv6Formatter::format(*self)), } } @@ -349,6 +365,7 @@ impl Format for [u8; 4] { Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Ok(Ipv4Formatter::format(*self)), } } @@ -363,6 +380,7 @@ impl Format for [u8; 6] { Some(DisplayHint::Ip) => Err(()), Some(DisplayHint::LowerMac) => Ok(LowerMacFormatter::format(*self)), Some(DisplayHint::UpperMac) => Ok(UpperMacFormatter::format(*self)), + Some(DisplayHint::Pointer) => Err(()), None => Err(()), } } @@ -377,6 +395,7 @@ impl Format for [u8; 16] { Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Err(()), } } @@ -391,6 +410,7 @@ impl Format for [u16; 8] { Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Err(()), } } @@ -407,6 +427,7 @@ macro_rules! impl_format { Some(DisplayHint::Ip) => Err(()), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Ok(DefaultFormatter::format(self)), } } @@ -436,6 +457,7 @@ macro_rules! impl_format_float { Some(DisplayHint::Ip) => Err(()), Some(DisplayHint::LowerMac) => Err(()), Some(DisplayHint::UpperMac) => Err(()), + Some(DisplayHint::Pointer) => Err(()), None => Ok(DefaultFormatter::format(self)), } } @@ -446,6 +468,24 @@ macro_rules! impl_format_float { impl_format_float!(f32); impl_format_float!(f64); +impl Format for *const T { + fn format(&self, last_hint: Option) -> Result { + match last_hint.map(|DisplayHintWrapper(dh)| dh) { + Some(DisplayHint::Pointer) => Ok(PointerFormatter::format(*self)), + _ => Err(()), + } + } +} + +impl Format for *mut T { + fn format(&self, last_hint: Option) -> Result { + match last_hint.map(|DisplayHintWrapper(dh)| dh) { + Some(DisplayHint::Pointer) => Ok(PointerFormatter::format(*self)), + _ => Err(()), + } + } +} + #[derive(Error, Debug)] pub enum Error { #[error("{} not found", MAP_NAME)] @@ -732,6 +772,13 @@ fn log_buf(mut buf: &[u8], logger: &T) -> Result<(), ()> { } Err(e) => error!("received invalid utf8 string: {e}"), }, + ArgumentKind::Pointer => { + let value = value + .try_into() + .map_err(|std::array::TryFromSliceError { .. }| ())?; + let ptr = usize::from_ne_bytes(value) as *const (); + full_log_msg.push_str(&ptr.format(last_hint.take())?); + } } buf = rest; diff --git a/ebpf/aya-log-ebpf/src/lib.rs b/ebpf/aya-log-ebpf/src/lib.rs index 7238c006..6be37975 100644 --- a/ebpf/aya-log-ebpf/src/lib.rs +++ b/ebpf/aya-log-ebpf/src/lib.rs @@ -14,7 +14,8 @@ pub mod macro_support { use aya_ebpf::maps::RingBuf; pub use aya_log_common::{ Argument, DefaultFormatter, DisplayHint, Field, Header, IpFormatter, Level, LogValueLength, - LowerHexFormatter, LowerMacFormatter, UpperHexFormatter, UpperMacFormatter, + LowerHexFormatter, LowerMacFormatter, PointerFormatter, UpperHexFormatter, + UpperMacFormatter, }; // This cfg_attr prevents compilation failures on macOS where the generated section name doesn't diff --git a/test/integration-ebpf/src/log.rs b/test/integration-ebpf/src/log.rs index 2abb5566..3e7bf5b8 100644 --- a/test/integration-ebpf/src/log.rs +++ b/test/integration-ebpf/src/log.rs @@ -89,6 +89,8 @@ fn test_log(ctx: ProbeContext) { &ctx, "{} {} {} {} {} {} {}", header, tmp, kind, value, size, op, buf ); + let ptr = 0xdeadbeef as *const u8; + debug!(&ctx, "ptr: {:p}", ptr); // Testing compilation only. if false { diff --git a/test/integration-test/src/tests/log.rs b/test/integration-test/src/tests/log.rs index e1659d54..1973bf84 100644 --- a/test/integration-test/src/tests/log.rs +++ b/test/integration-test/src/tests/log.rs @@ -187,6 +187,15 @@ fn log() { }) ); + assert_eq!( + records.next(), + Some(&CapturedLog { + body: "ptr: 0xdeadbeef".into(), + level: Level::Debug, + target: "log".into(), + }) + ); + assert_eq!( records.next(), Some(&CapturedLog { diff --git a/xtask/public-api/aya-log-common.txt b/xtask/public-api/aya-log-common.txt index 481b273e..7187da8e 100644 --- a/xtask/public-api/aya-log-common.txt +++ b/xtask/public-api/aya-log-common.txt @@ -15,6 +15,7 @@ pub aya_log_common::ArgumentKind::I8 pub aya_log_common::ArgumentKind::Ipv4Addr pub aya_log_common::ArgumentKind::Ipv6Addr pub aya_log_common::ArgumentKind::Isize +pub aya_log_common::ArgumentKind::Pointer pub aya_log_common::ArgumentKind::Str pub aya_log_common::ArgumentKind::U16 pub aya_log_common::ArgumentKind::U32 @@ -57,6 +58,7 @@ pub aya_log_common::DisplayHint::Default = 1 pub aya_log_common::DisplayHint::Ip pub aya_log_common::DisplayHint::LowerHex pub aya_log_common::DisplayHint::LowerMac +pub aya_log_common::DisplayHint::Pointer pub aya_log_common::DisplayHint::UpperHex pub aya_log_common::DisplayHint::UpperMac impl aya_log_common::Argument for aya_log_common::DisplayHint @@ -215,6 +217,10 @@ impl aya_log_common::Argument for u8 pub fn u8::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) impl aya_log_common::Argument for usize pub fn usize::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) +impl aya_log_common::Argument for *const T +pub fn *const T::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) +impl aya_log_common::Argument for *mut T +pub fn *mut T::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) impl aya_log_common::Argument for [u8; N] pub fn [u8; N]::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) pub trait aya_log_common::DefaultFormatter @@ -260,6 +266,9 @@ impl aya_log_common::LowerHexFormatter for usize impl aya_log_common::LowerHexFormatter for &[u8; N] pub trait aya_log_common::LowerMacFormatter impl aya_log_common::LowerMacFormatter for [u8; 6] +pub trait aya_log_common::PointerFormatter +impl aya_log_common::PointerFormatter for *const T +impl aya_log_common::PointerFormatter for *mut T pub trait aya_log_common::UpperHexFormatter impl aya_log_common::UpperHexFormatter for &[u8] impl aya_log_common::UpperHexFormatter for i16 diff --git a/xtask/public-api/aya-log.txt b/xtask/public-api/aya-log.txt index 3583315e..a469879c 100644 --- a/xtask/public-api/aya-log.txt +++ b/xtask/public-api/aya-log.txt @@ -223,6 +223,33 @@ impl core::borrow::BorrowMut for aya_log::LowerMacFormatter where T: ?core pub fn aya_log::LowerMacFormatter::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_log::LowerMacFormatter pub fn aya_log::LowerMacFormatter::from(t: T) -> T +pub struct aya_log::PointerFormatter +impl aya_log::Formatter<*const T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *const T) -> alloc::string::String +impl aya_log::Formatter<*mut T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *mut T) -> alloc::string::String +impl core::marker::Freeze for aya_log::PointerFormatter +impl core::marker::Send for aya_log::PointerFormatter +impl core::marker::Sync for aya_log::PointerFormatter +impl core::marker::Unpin for aya_log::PointerFormatter +impl core::panic::unwind_safe::RefUnwindSafe for aya_log::PointerFormatter +impl core::panic::unwind_safe::UnwindSafe for aya_log::PointerFormatter +impl core::convert::Into for aya_log::PointerFormatter where U: core::convert::From +pub fn aya_log::PointerFormatter::into(self) -> U +impl core::convert::TryFrom for aya_log::PointerFormatter where U: core::convert::Into +pub type aya_log::PointerFormatter::Error = core::convert::Infallible +pub fn aya_log::PointerFormatter::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_log::PointerFormatter where U: core::convert::TryFrom +pub type aya_log::PointerFormatter::Error = >::Error +pub fn aya_log::PointerFormatter::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_log::PointerFormatter where T: 'static + ?core::marker::Sized +pub fn aya_log::PointerFormatter::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_log::PointerFormatter where T: ?core::marker::Sized +pub fn aya_log::PointerFormatter::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_log::PointerFormatter where T: ?core::marker::Sized +pub fn aya_log::PointerFormatter::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::from(t: T) -> T pub struct aya_log::UpperHexBytesFormatter impl aya_log::Formatter<&[u8]> for aya_log::UpperHexBytesFormatter pub fn aya_log::UpperHexBytesFormatter::format(v: &[u8]) -> alloc::string::String @@ -309,6 +336,10 @@ impl aya_log::Formatter<[u8; 6]> for aya_log::LowerMacFormatter pub fn aya_log::LowerMacFormatter::format(v: [u8; 6]) -> alloc::string::String impl aya_log::Formatter<[u8; 6]> for aya_log::UpperMacFormatter pub fn aya_log::UpperMacFormatter::format(v: [u8; 6]) -> alloc::string::String +impl aya_log::Formatter<*const T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *const T) -> alloc::string::String +impl aya_log::Formatter<*mut T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *mut T) -> alloc::string::String impl aya_log::Formatter for aya_log::DefaultFormatter where T: alloc::string::ToString pub fn aya_log::DefaultFormatter::format(v: T) -> alloc::string::String impl aya_log::Formatter for aya_log::Ipv4Formatter where T: core::convert::Into From 57a75dfd6177e517dfe74c7d45345159bc717ef4 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 12:32:22 -0400 Subject: [PATCH 02/19] .vscode: always use linux in rust-analyzer --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index b383a959..fe99dc28 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "rust-analyzer.check.allTargets": true, "rust-analyzer.check.command": "clippy", + "rust-analyzer.cargo.target": "x86_64-unknown-linux-musl", "search.exclude": { "/xtask/public-api/*.txt": true }, From 4ce1e29804c6caf56e711ad95b0f4a5d3d952391 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 12:32:51 -0400 Subject: [PATCH 03/19] clippy.sh: build for BPF after everything else In cases where I run `./clippy.sh ... -p ` I really want the results for that crate to come quickly. --- clippy.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy.sh b/clippy.sh index a710c7c1..6d454a9e 100755 --- a/clippy.sh +++ b/clippy.sh @@ -2,15 +2,6 @@ set -eux -cargo +nightly hack clippy \ - --target bpfel-unknown-none -Zbuild-std=core \ - --package aya-ebpf-bindings \ - --package aya-ebpf \ - --package aya-log-ebpf \ - --package integration-ebpf \ - --feature-powerset \ - -- --deny warnings - # `-C panic=abort` because "unwinding panics are not supported without std"; integration-ebpf # contains `#[no_std]` binaries. # @@ -26,3 +17,12 @@ cargo +nightly hack clippy "$@" \ -- --deny warnings \ -C panic=abort \ -Zpanic_abort_tests + +cargo +nightly hack clippy \ + --target bpfel-unknown-none -Zbuild-std=core \ + --package aya-ebpf-bindings \ + --package aya-ebpf \ + --package aya-log-ebpf \ + --package integration-ebpf \ + --feature-powerset \ + -- --deny warnings From 6fc06b9fcf073447438b41a066497946293825d5 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 12:52:54 -0400 Subject: [PATCH 04/19] Remove unused error variant --- aya/src/sys/netlink.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index cec74523..bd27aa6b 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -40,8 +40,6 @@ pub(crate) enum NetlinkErrorInternal { #[error(transparent)] IoError(#[from] io::Error), #[error(transparent)] - NulError(#[from] std::ffi::NulError), - #[error(transparent)] NlAttrError(#[from] NlAttrError), } From 667790e103072702bf075c5f071fc20cd472cb1a Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 15:13:04 -0400 Subject: [PATCH 05/19] xtask: avoid `git submodule update` when possible `git submodule update` fails when running in a codex sandbox: ``` error: could not lock config file /Users/tamird/src/aya/.git/modules/libbpf/config: Operation not permitted ``` so just avoid it when not necessary. --- xtask/src/main.rs | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index b085cc12..99c48c0e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -3,9 +3,9 @@ mod docs; mod public_api; mod run; -use std::process::Command; +use std::process::{Command, Output}; -use anyhow::{Context as _, Result}; +use anyhow::{Context as _, Result, bail}; use cargo_metadata::{Metadata, MetadataCommand}; use clap::Parser; use xtask::{LIBBPF_DIR, exec}; @@ -33,12 +33,29 @@ fn main() -> Result<()> { .context("failed to run cargo metadata")?; let Metadata { workspace_root, .. } = &metadata; - // Initialize the submodules. - exec(Command::new("git").arg("-C").arg(workspace_root).args([ - "submodule", - "update", - "--init", - ]))?; + let mut libbpf_submodule_status = Command::new("git"); + let output = libbpf_submodule_status + .arg("-C") + .arg(workspace_root) + .arg("submodule") + .arg("status") + .arg(LIBBPF_DIR) + .output() + .with_context(|| format!("failed to run {libbpf_submodule_status:?}"))?; + let Output { status, .. } = &output; + if !status.success() { + bail!("{libbpf_submodule_status:?} failed: {output:?}") + } + let Output { stdout, .. } = output; + if !stdout.starts_with(b" ") { + // Initialize the submodules. + exec(Command::new("git").arg("-C").arg(workspace_root).args([ + "submodule", + "update", + "--init", + ]))?; + } + let libbpf_dir = workspace_root.join(LIBBPF_DIR); let libbpf_dir = libbpf_dir.as_std_path(); From 0cb52e850a584e47db58d116f5ff52050d4d323a Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 15:16:06 -0400 Subject: [PATCH 06/19] xtask: tolerate curl failure when possible Codex sandbox forbids network access. --- xtask/src/run.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 79433217..b52e8890 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -208,7 +208,7 @@ pub(crate) fn run(opts: Options) -> Result<()> { let etag_path_exists = etag_path.try_exists().with_context(|| { format!("failed to check existence of {}", etag_path.display()) })?; - if !dest_path_exists && etag_path_exists { + if dest_path_exists != etag_path_exists { println!( "cargo:warning=({}).exists()={} != ({})={} (mismatch)", dest_path.display(), @@ -237,7 +237,14 @@ pub(crate) fn run(opts: Options) -> Result<()> { .with_context(|| format!("failed to run {curl:?}"))?; let Output { status, .. } = &output; if status.code() != Some(0) { - bail!("{curl:?} failed: {output:?}") + if dest_path_exists { + println!( + "cargo:warning={curl:?} failed ({status:?}); using cached {}", + dest_path.display() + ); + } else { + bail!("{curl:?} failed: {output:?}") + } } let mut patch = Command::new("patch"); From 82aec2696394f953c886f146f02673753a94cb0d Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 17:24:14 -0400 Subject: [PATCH 07/19] flow_dissector: add missing impl_try_into_fdlink --- aya/src/programs/flow_dissector.rs | 4 +++- xtask/public-api/aya.txt | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/aya/src/programs/flow_dissector.rs b/aya/src/programs/flow_dissector.rs index e0b3685b..64d657bd 100644 --- a/aya/src/programs/flow_dissector.rs +++ b/aya/src/programs/flow_dissector.rs @@ -9,7 +9,7 @@ use aya_obj::generated::{ use crate::{ programs::{ CgroupAttachMode, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, ProgramType, - define_link_wrapper, id_as_key, load_program, + define_link_wrapper, id_as_key, impl_try_into_fdlink, load_program, }, sys::{LinkTarget, SyscallError, bpf_link_create}, util::KernelVersion, @@ -155,3 +155,5 @@ define_link_wrapper!( FlowDissectorLinkIdInner, FlowDissector, ); + +impl_try_into_fdlink!(FlowDissectorLink, FlowDissectorLinkInner); diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 680204ac..d5e03521 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -3828,6 +3828,9 @@ pub fn aya::programs::flow_dissector::FlowDissectorLink::id(&self) -> Self::Id impl core::cmp::Eq for aya::programs::flow_dissector::FlowDissectorLink impl core::cmp::PartialEq for aya::programs::flow_dissector::FlowDissectorLink pub fn aya::programs::flow_dissector::FlowDissectorLink::eq(&self, other: &Self) -> bool +impl core::convert::TryFrom for aya::programs::links::FdLink +pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError +pub fn aya::programs::links::FdLink::try_from(value: aya::programs::flow_dissector::FlowDissectorLink) -> core::result::Result impl core::fmt::Debug for aya::programs::flow_dissector::FlowDissectorLink pub fn aya::programs::flow_dissector::FlowDissectorLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::hash::Hash for aya::programs::flow_dissector::FlowDissectorLink @@ -4416,6 +4419,9 @@ pub fn aya::programs::links::FdLink::try_from(value: aya::programs::cgroup_sock: impl core::convert::TryFrom for aya::programs::links::FdLink pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError pub fn aya::programs::links::FdLink::try_from(value: aya::programs::cgroup_sock_addr::CgroupSockAddrLink) -> core::result::Result +impl core::convert::TryFrom for aya::programs::links::FdLink +pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError +pub fn aya::programs::links::FdLink::try_from(value: aya::programs::flow_dissector::FlowDissectorLink) -> core::result::Result impl core::convert::TryFrom for aya::programs::links::FdLink pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError pub fn aya::programs::links::FdLink::try_from(value: aya::programs::iter::IterLink) -> core::result::Result From f76fdf9da51852f5e13011b2d3ba6f9204943de7 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 15 May 2025 11:56:46 -0400 Subject: [PATCH 08/19] Improve error output - Use consistent casing. - Emit syscall return value. --- aya-obj/src/btf/btf.rs | 8 ++++---- aya/src/programs/mod.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index 4a580ffc..a94cac95 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -99,21 +99,21 @@ pub enum BtfError { }, /// unknown BTF type id - #[error("Unknown BTF type id `{type_id}`")] + #[error("unknown BTF type id `{type_id}`")] UnknownBtfType { /// type id type_id: u32, }, /// unexpected btf type id - #[error("Unexpected BTF type id `{type_id}`")] + #[error("unexpected BTF type id `{type_id}`")] UnexpectedBtfType { /// type id type_id: u32, }, /// unknown BTF type - #[error("Unknown BTF type `{type_name}`")] + #[error("unknown BTF type `{type_name}`")] UnknownBtfTypeName { /// type name type_name: String, @@ -128,7 +128,7 @@ pub enum BtfError { #[cfg(feature = "std")] /// Loading the btf failed - #[error("the BPF_BTF_LOAD syscall failed. Verifier output: {verifier_log}")] + #[error("the BPF_BTF_LOAD syscall returned {io_error}. Verifier output: {verifier_log}")] LoadError { /// The [`std::io::Error`] returned by the `BPF_BTF_LOAD` syscall. #[source] diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 4fb734f2..eda6fa7f 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -158,7 +158,7 @@ pub enum ProgramError { NotAttached, /// Loading the program failed. - #[error("the BPF_PROG_LOAD syscall failed. Verifier output: {verifier_log}")] + #[error("the BPF_PROG_LOAD syscall returned {io_error}. Verifier output: {verifier_log}")] LoadError { /// The [`io::Error`] returned by the `BPF_PROG_LOAD` syscall. #[source] From c2fb7fed6c4cc2b75a0188cddd8480789e99e0d5 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 14 Oct 2025 10:51:20 -0400 Subject: [PATCH 09/19] Remove useless impl --- aya/src/sys/netlink.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/aya/src/sys/netlink.rs b/aya/src/sys/netlink.rs index bd27aa6b..9788fe8b 100644 --- a/aya/src/sys/netlink.rs +++ b/aya/src/sys/netlink.rs @@ -697,12 +697,6 @@ pub(crate) enum NlAttrError { InvalidHeaderLength(usize), } -impl From for io::Error { - fn from(err: NlAttrError) -> Self { - Self::other(err) - } -} - unsafe fn request_attributes(req: &mut T, msg_len: usize) -> &mut [u8] { let req: *mut _ = req; let req: *mut u8 = req.cast(); From 4041fe929388fbec72833c3a0561b01e9721dd3a Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 08:14:52 -0400 Subject: [PATCH 10/19] integration-test: move memmove out of pin tests --- test/integration-test/src/tests/load.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 024b612d..5141a807 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -31,6 +31,13 @@ fn long_name() { // Therefore, as long as we were able to load the program, this is good enough. } +#[test_log::test] +fn memmove() { + let mut bpf = Ebpf::load(crate::MEMMOVE_TEST).unwrap(); + let prog: &mut Xdp = bpf.program_mut("do_dnat").unwrap().try_into().unwrap(); + prog.load().unwrap(); +} + #[test_log::test] fn multiple_btf_maps() { let mut bpf = Ebpf::load(crate::MULTIMAP_BTF).unwrap(); @@ -240,15 +247,6 @@ fn unload_kprobe() { assert_unloaded("test_kprobe"); } -#[test_log::test] -fn memmove() { - let mut bpf = Ebpf::load(crate::MEMMOVE_TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("do_dnat").unwrap().try_into().unwrap(); - - prog.load().unwrap(); - assert_loaded("do_dnat"); -} - #[test_log::test] fn basic_tracepoint() { let mut bpf = Ebpf::load(crate::TEST).unwrap(); From 48300b64988da78cd38e577f7f7537e2c43e69df Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 08:14:15 -0400 Subject: [PATCH 11/19] integration-test: extract program names --- test/integration-test/src/tests/load.rs | 152 +++++++++++++----------- 1 file changed, 82 insertions(+), 70 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 5141a807..ce02ec6e 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -199,92 +199,96 @@ fn assert_unloaded(name: &str) { #[test_log::test] fn unload_xdp() { + let program_name = "pass"; + let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); let link = prog.attach("lo", XdpFlags::default()).unwrap(); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded_and_linked("pass"); + assert_loaded_and_linked(program_name); }; - assert_unloaded("pass"); + assert_unloaded(program_name); prog.load().unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); prog.attach("lo", XdpFlags::default()).unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); prog.unload().unwrap(); - assert_unloaded("pass"); + assert_unloaded(program_name); } #[test_log::test] fn unload_kprobe() { + let program_name = "test_kprobe"; + let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); + let prog: &mut KProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - assert_loaded("test_kprobe"); + assert_loaded(program_name); let link = prog.attach("try_to_wake_up", 0).unwrap(); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded_and_linked("test_kprobe"); + assert_loaded_and_linked(program_name); }; - assert_unloaded("test_kprobe"); + assert_unloaded(program_name); prog.load().unwrap(); - assert_loaded("test_kprobe"); + assert_loaded(program_name); prog.attach("try_to_wake_up", 0).unwrap(); - assert_loaded("test_kprobe"); + assert_loaded(program_name); prog.unload().unwrap(); - assert_unloaded("test_kprobe"); + assert_unloaded(program_name); } #[test_log::test] fn basic_tracepoint() { + let program_name = "test_tracepoint"; + let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut TracePoint = bpf - .program_mut("test_tracepoint") - .unwrap() - .try_into() - .unwrap(); + let prog: &mut TracePoint = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - assert_loaded("test_tracepoint"); + assert_loaded(program_name); let link = prog.attach("syscalls", "sys_enter_kill").unwrap(); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded_and_linked("test_tracepoint"); + assert_loaded_and_linked(program_name); }; - assert_unloaded("test_tracepoint"); + assert_unloaded(program_name); prog.load().unwrap(); - assert_loaded("test_tracepoint"); + assert_loaded(program_name); prog.attach("syscalls", "sys_enter_kill").unwrap(); - assert_loaded("test_tracepoint"); + assert_loaded(program_name); prog.unload().unwrap(); - assert_unloaded("test_tracepoint"); + assert_unloaded(program_name); } #[test_log::test] fn basic_uprobe() { + let program_name = "test_uprobe"; + let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut UProbe = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap(); + let prog: &mut UProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - assert_loaded("test_uprobe"); + assert_loaded(program_name); let link = prog .attach("uprobe_function", "/proc/self/exe", None, None) .unwrap(); @@ -292,52 +296,56 @@ fn basic_uprobe() { { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded_and_linked("test_uprobe"); + assert_loaded_and_linked(program_name); }; - assert_unloaded("test_uprobe"); + assert_unloaded(program_name); prog.load().unwrap(); - assert_loaded("test_uprobe"); + assert_loaded(program_name); prog.attach("uprobe_function", "/proc/self/exe", None, None) .unwrap(); - assert_loaded("test_uprobe"); + assert_loaded(program_name); prog.unload().unwrap(); - assert_unloaded("test_uprobe"); + assert_unloaded(program_name); } #[test_log::test] fn basic_flow_dissector() { + let program_name = "test_flow"; + let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut FlowDissector = bpf.program_mut("test_flow").unwrap().try_into().unwrap(); + let prog: &mut FlowDissector = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - assert_loaded("test_flow"); + assert_loaded(program_name); let net_ns = std::fs::File::open("/proc/self/ns/net").unwrap(); let link = prog.attach(net_ns.try_clone().unwrap()).unwrap(); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded_and_linked("test_flow"); + assert_loaded_and_linked(program_name); }; - assert_unloaded("test_flow"); + assert_unloaded(program_name); prog.load().unwrap(); - assert_loaded("test_flow"); + assert_loaded(program_name); prog.attach(net_ns).unwrap(); - assert_loaded("test_flow"); + assert_loaded(program_name); prog.unload().unwrap(); - assert_unloaded("test_flow"); + assert_unloaded(program_name); } #[test_log::test] fn pin_link() { + let program_name = "pass"; + let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 9, 0) { eprintln!("skipping test on kernel {kernel_version:?}, XDP uses netlink"); @@ -345,30 +353,32 @@ fn pin_link() { } let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); let fd_link: FdLink = link.try_into().unwrap(); let pinned = fd_link.pin("/sys/fs/bpf/aya-xdp-test-lo").unwrap(); // because of the pin, the program is still attached prog.unload().unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); // delete the pin, but the program is still attached let new_link = pinned.unpin().unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); // finally when new_link is dropped we're detached drop(new_link); - assert_unloaded("pass"); + assert_unloaded(program_name); } #[test_log::test] fn pin_lifecycle() { + let program_name = "pass"; + let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { eprintln!( @@ -380,13 +390,13 @@ fn pin_lifecycle() { // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::PASS).unwrap(); - let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); } // should still be loaded since prog was pinned - assert_loaded("pass"); + assert_loaded(program_name); // 2. Load program from bpffs but don't attach it { @@ -394,7 +404,7 @@ fn pin_lifecycle() { } // should still be loaded since prog was pinned - assert_loaded("pass"); + assert_loaded(program_name); // 3. Load program from bpffs and attach { @@ -410,12 +420,12 @@ fn pin_lifecycle() { } // should still be loaded since link was pinned - assert_loaded_and_linked("pass"); + assert_loaded_and_linked(program_name); // 4. Load a new version of the program, unpin link, and atomically replace old program { let mut bpf = Ebpf::load(crate::PASS).unwrap(); - let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo") @@ -423,29 +433,27 @@ fn pin_lifecycle() { .unpin() .unwrap(); prog.attach_to_link(link.try_into().unwrap()).unwrap(); - assert_loaded("pass"); + assert_loaded(program_name); } // program should be unloaded - assert_unloaded("pass"); + assert_unloaded(program_name); } #[test_log::test] fn pin_lifecycle_tracepoint() { + let program_name = "test_tracepoint"; + // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut TracePoint = bpf - .program_mut("test_tracepoint") - .unwrap() - .try_into() - .unwrap(); + let prog: &mut TracePoint = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); } // should still be loaded since prog was pinned - assert_loaded("test_tracepoint"); + assert_loaded(program_name); // 2. Load program from bpffs but don't attach it { @@ -453,7 +461,7 @@ fn pin_lifecycle_tracepoint() { } // should still be loaded since prog was pinned - assert_loaded("test_tracepoint"); + assert_loaded(program_name); // 3. Load program from bpffs and attach { @@ -470,7 +478,7 @@ fn pin_lifecycle_tracepoint() { } // should still be loaded since link was pinned - assert_loaded_and_linked("test_tracepoint"); + assert_loaded_and_linked(program_name); // 4. unpin link, and make sure everything is unloaded { @@ -481,21 +489,23 @@ fn pin_lifecycle_tracepoint() { } // program should be unloaded - assert_unloaded("test_tracepoint"); + assert_unloaded(program_name); } #[test_log::test] fn pin_lifecycle_kprobe() { + let program_name = "test_kprobe"; + // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); + let prog: &mut KProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap(); } // should still be loaded since prog was pinned - assert_loaded("test_kprobe"); + assert_loaded(program_name); // 2. Load program from bpffs but don't attach it { @@ -507,7 +517,7 @@ fn pin_lifecycle_kprobe() { } // should still be loaded since prog was pinned - assert_loaded("test_kprobe"); + assert_loaded(program_name); // 3. Load program from bpffs and attach { @@ -528,7 +538,7 @@ fn pin_lifecycle_kprobe() { } // should still be loaded since link was pinned - assert_loaded_and_linked("test_kprobe"); + assert_loaded_and_linked(program_name); // 4. unpin link, and make sure everything is unloaded { @@ -539,7 +549,7 @@ fn pin_lifecycle_kprobe() { } // program should be unloaded - assert_unloaded("test_kprobe"); + assert_unloaded(program_name); } #[unsafe(no_mangle)] @@ -550,19 +560,21 @@ extern "C" fn uprobe_function() { #[test_log::test] fn pin_lifecycle_uprobe() { + let program_name = "test_uprobe"; + const FIRST_PIN_PATH: &str = "/sys/fs/bpf/aya-uprobe-test-prog-1"; const SECOND_PIN_PATH: &str = "/sys/fs/bpf/aya-uprobe-test-prog-2"; // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut UProbe = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap(); + let prog: &mut UProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin(FIRST_PIN_PATH).unwrap(); } // should still be loaded since prog was pinned - assert_loaded("test_uprobe"); + assert_loaded(program_name); // 2. Load program from bpffs but don't attach it { @@ -570,7 +582,7 @@ fn pin_lifecycle_uprobe() { } // should still be loaded since prog was pinned - assert_loaded("test_uprobe"); + assert_loaded(program_name); // 3. Load program from bpffs and attach { @@ -587,7 +599,7 @@ fn pin_lifecycle_uprobe() { } // should still be loaded since link was pinned - assert_loaded_and_linked("test_uprobe"); + assert_loaded_and_linked(program_name); // 4. unpin link, and make sure everything is unloaded { @@ -598,7 +610,7 @@ fn pin_lifecycle_uprobe() { } // program should be unloaded - assert_unloaded("test_uprobe"); + assert_unloaded(program_name); // Make sure the function isn't optimized out. uprobe_function(); From 89d746ad1b5b31bd869ab8a8081333b1a078be9f Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 08:31:17 -0400 Subject: [PATCH 12/19] integration-test: extract attach fns --- test/integration-test/src/tests/load.rs | 55 +++++++++++++++---------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index ce02ec6e..0bb21d71 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -200,12 +200,13 @@ fn assert_unloaded(name: &str) { #[test_log::test] fn unload_xdp() { let program_name = "pass"; + let attach = |prog: &mut Xdp| prog.attach("lo", XdpFlags::default()).unwrap(); let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); - let link = prog.attach("lo", XdpFlags::default()).unwrap(); + let link = attach(prog); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); @@ -216,7 +217,7 @@ fn unload_xdp() { prog.load().unwrap(); assert_loaded(program_name); - prog.attach("lo", XdpFlags::default()).unwrap(); + attach(prog); assert_loaded(program_name); prog.unload().unwrap(); @@ -227,12 +228,13 @@ fn unload_xdp() { #[test_log::test] fn unload_kprobe() { let program_name = "test_kprobe"; + let attach = |prog: &mut KProbe| prog.attach("try_to_wake_up", 0).unwrap(); let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut KProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); - let link = prog.attach("try_to_wake_up", 0).unwrap(); + let link = attach(prog); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); @@ -243,7 +245,7 @@ fn unload_kprobe() { prog.load().unwrap(); assert_loaded(program_name); - prog.attach("try_to_wake_up", 0).unwrap(); + attach(prog); assert_loaded(program_name); prog.unload().unwrap(); @@ -254,13 +256,14 @@ fn unload_kprobe() { #[test_log::test] fn basic_tracepoint() { let program_name = "test_tracepoint"; + let attach = |prog: &mut TracePoint| prog.attach("syscalls", "sys_enter_kill").unwrap(); let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut TracePoint = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); - let link = prog.attach("syscalls", "sys_enter_kill").unwrap(); + let link = attach(prog); { let _link_owned = prog.take_link(link).unwrap(); @@ -272,7 +275,7 @@ fn basic_tracepoint() { prog.load().unwrap(); assert_loaded(program_name); - prog.attach("syscalls", "sys_enter_kill").unwrap(); + attach(prog); assert_loaded(program_name); prog.unload().unwrap(); @@ -283,15 +286,17 @@ fn basic_tracepoint() { #[test_log::test] fn basic_uprobe() { let program_name = "test_uprobe"; + let attach = |prog: &mut UProbe| { + prog.attach("uprobe_function", "/proc/self/exe", None, None) + .unwrap() + }; let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut UProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); - let link = prog - .attach("uprobe_function", "/proc/self/exe", None, None) - .unwrap(); + let link = attach(prog); { let _link_owned = prog.take_link(link).unwrap(); @@ -303,8 +308,7 @@ fn basic_uprobe() { prog.load().unwrap(); assert_loaded(program_name); - prog.attach("uprobe_function", "/proc/self/exe", None, None) - .unwrap(); + attach(prog); assert_loaded(program_name); prog.unload().unwrap(); @@ -315,6 +319,10 @@ fn basic_uprobe() { #[test_log::test] fn basic_flow_dissector() { let program_name = "test_flow"; + let attach = |prog: &mut FlowDissector| { + let net_ns = std::fs::File::open("/proc/self/ns/net").unwrap(); + prog.attach(net_ns).unwrap() + }; let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut FlowDissector = bpf.program_mut(program_name).unwrap().try_into().unwrap(); @@ -322,8 +330,7 @@ fn basic_flow_dissector() { prog.load().unwrap(); assert_loaded(program_name); - let net_ns = std::fs::File::open("/proc/self/ns/net").unwrap(); - let link = prog.attach(net_ns.try_clone().unwrap()).unwrap(); + let link = attach(prog); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); @@ -334,7 +341,7 @@ fn basic_flow_dissector() { prog.load().unwrap(); assert_loaded(program_name); - prog.attach(net_ns).unwrap(); + attach(prog); assert_loaded(program_name); prog.unload().unwrap(); @@ -345,6 +352,7 @@ fn basic_flow_dissector() { #[test_log::test] fn pin_link() { let program_name = "pass"; + let attach = |prog: &mut Xdp| prog.attach("lo", XdpFlags::default()).unwrap(); let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 9, 0) { @@ -355,7 +363,7 @@ fn pin_link() { let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); + let link_id = attach(prog); let link = prog.take_link(link_id).unwrap(); assert_loaded(program_name); @@ -378,6 +386,7 @@ fn pin_link() { #[test_log::test] fn pin_lifecycle() { let program_name = "pass"; + let attach = |prog: &mut Xdp| prog.attach("lo", XdpFlags::default()).unwrap(); let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { @@ -410,7 +419,7 @@ fn pin_lifecycle() { { 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_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); fd_link.pin("/sys/fs/bpf/aya-xdp-test-lo").unwrap(); @@ -443,6 +452,7 @@ fn pin_lifecycle() { #[test_log::test] fn pin_lifecycle_tracepoint() { let program_name = "test_tracepoint"; + let attach = |prog: &mut TracePoint| prog.attach("syscalls", "sys_enter_kill").unwrap(); // 1. Load Program and Pin { @@ -466,7 +476,7 @@ fn pin_lifecycle_tracepoint() { // 3. Load program from bpffs and attach { let mut prog = TracePoint::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); - let link_id = prog.attach("syscalls", "sys_enter_kill").unwrap(); + let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); fd_link @@ -495,6 +505,7 @@ fn pin_lifecycle_tracepoint() { #[test_log::test] fn pin_lifecycle_kprobe() { let program_name = "test_kprobe"; + let attach = |prog: &mut KProbe| prog.attach("try_to_wake_up", 0).unwrap(); // 1. Load Program and Pin { @@ -526,7 +537,7 @@ fn pin_lifecycle_kprobe() { aya::programs::ProbeKind::KProbe, ) .unwrap(); - let link_id = prog.attach("try_to_wake_up", 0).unwrap(); + let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); fd_link @@ -561,6 +572,10 @@ extern "C" fn uprobe_function() { #[test_log::test] fn pin_lifecycle_uprobe() { let program_name = "test_uprobe"; + let attach = |prog: &mut UProbe| { + prog.attach("uprobe_function", "/proc/self/exe", None, None) + .unwrap() + }; const FIRST_PIN_PATH: &str = "/sys/fs/bpf/aya-uprobe-test-prog-1"; const SECOND_PIN_PATH: &str = "/sys/fs/bpf/aya-uprobe-test-prog-2"; @@ -587,9 +602,7 @@ fn pin_lifecycle_uprobe() { // 3. Load program from bpffs and attach { let mut prog = UProbe::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); - let link_id = prog - .attach("uprobe_function", "/proc/self/exe", None, None) - .unwrap(); + let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); fd_link.pin(SECOND_PIN_PATH).unwrap(); From a2f4951ccec19254a64cbfb5df190f4d5a92245b Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 08:39:25 -0400 Subject: [PATCH 13/19] integration-test: remove errant semicolons --- test/integration-test/src/tests/load.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 0bb21d71..00ce691b 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -211,7 +211,7 @@ fn unload_xdp() { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); assert_loaded_and_linked(program_name); - }; + } assert_unloaded(program_name); prog.load().unwrap(); @@ -239,7 +239,7 @@ fn unload_kprobe() { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); assert_loaded_and_linked(program_name); - }; + } assert_unloaded(program_name); prog.load().unwrap(); @@ -269,7 +269,7 @@ fn basic_tracepoint() { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); assert_loaded_and_linked(program_name); - }; + } assert_unloaded(program_name); prog.load().unwrap(); @@ -302,7 +302,7 @@ fn basic_uprobe() { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); assert_loaded_and_linked(program_name); - }; + } assert_unloaded(program_name); prog.load().unwrap(); @@ -335,7 +335,7 @@ fn basic_flow_dissector() { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); assert_loaded_and_linked(program_name); - }; + } assert_unloaded(program_name); prog.load().unwrap(); From a6458804fc704e6e351b66c2d75f8488e3e52e2f Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 09:13:31 -0400 Subject: [PATCH 14/19] integration-test: extract types --- test/integration-test/src/tests/load.rs | 78 ++++++++++++++++--------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 00ce691b..cac176ee 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -199,11 +199,13 @@ fn assert_unloaded(name: &str) { #[test_log::test] fn unload_xdp() { + type P = Xdp; + let program_name = "pass"; - let attach = |prog: &mut Xdp| prog.attach("lo", XdpFlags::default()).unwrap(); + let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); let link = attach(prog); @@ -227,11 +229,13 @@ fn unload_xdp() { #[test_log::test] fn unload_kprobe() { + type P = KProbe; + let program_name = "test_kprobe"; - let attach = |prog: &mut KProbe| prog.attach("try_to_wake_up", 0).unwrap(); + let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap(); let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut KProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); let link = attach(prog); @@ -255,11 +259,13 @@ fn unload_kprobe() { #[test_log::test] fn basic_tracepoint() { + type P = TracePoint; + let program_name = "test_tracepoint"; - let attach = |prog: &mut TracePoint| prog.attach("syscalls", "sys_enter_kill").unwrap(); + let attach = |prog: &mut P| prog.attach("syscalls", "sys_enter_kill").unwrap(); let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut TracePoint = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); @@ -285,14 +291,16 @@ fn basic_tracepoint() { #[test_log::test] fn basic_uprobe() { + type P = UProbe; + let program_name = "test_uprobe"; - let attach = |prog: &mut UProbe| { + let attach = |prog: &mut P| { prog.attach("uprobe_function", "/proc/self/exe", None, None) .unwrap() }; let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut UProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); @@ -318,14 +326,16 @@ fn basic_uprobe() { #[test_log::test] fn basic_flow_dissector() { + type P = FlowDissector; + let program_name = "test_flow"; - let attach = |prog: &mut FlowDissector| { + let attach = |prog: &mut P| { let net_ns = std::fs::File::open("/proc/self/ns/net").unwrap(); prog.attach(net_ns).unwrap() }; let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut FlowDissector = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); @@ -351,8 +361,10 @@ fn basic_flow_dissector() { #[test_log::test] fn pin_link() { + type P = Xdp; + let program_name = "pass"; - let attach = |prog: &mut Xdp| prog.attach("lo", XdpFlags::default()).unwrap(); + let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 9, 0) { @@ -361,7 +373,7 @@ fn pin_link() { } let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); let link_id = attach(prog); let link = prog.take_link(link_id).unwrap(); @@ -385,8 +397,10 @@ fn pin_link() { #[test_log::test] fn pin_lifecycle() { + type P = Xdp; + let program_name = "pass"; - let attach = |prog: &mut Xdp| prog.attach("lo", XdpFlags::default()).unwrap(); + let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { @@ -399,7 +413,7 @@ fn pin_lifecycle() { // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::PASS).unwrap(); - let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); } @@ -409,7 +423,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", XdpAttachType::Interface).unwrap(); + let _ = P::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); } // should still be loaded since prog was pinned @@ -418,7 +432,7 @@ fn pin_lifecycle() { // 3. Load program from bpffs and attach { let mut prog = - Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); + P::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); @@ -434,7 +448,7 @@ fn pin_lifecycle() { // 4. Load a new version of the program, unpin link, and atomically replace old program { let mut bpf = Ebpf::load(crate::PASS).unwrap(); - let prog: &mut Xdp = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo") @@ -451,13 +465,15 @@ fn pin_lifecycle() { #[test_log::test] fn pin_lifecycle_tracepoint() { + type P = TracePoint; + let program_name = "test_tracepoint"; - let attach = |prog: &mut TracePoint| prog.attach("syscalls", "sys_enter_kill").unwrap(); + let attach = |prog: &mut P| prog.attach("syscalls", "sys_enter_kill").unwrap(); // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut TracePoint = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); } @@ -467,7 +483,7 @@ fn pin_lifecycle_tracepoint() { // 2. Load program from bpffs but don't attach it { - let _ = TracePoint::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); + let _ = P::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); } // should still be loaded since prog was pinned @@ -475,7 +491,7 @@ fn pin_lifecycle_tracepoint() { // 3. Load program from bpffs and attach { - let mut prog = TracePoint::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); + let mut prog = P::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); @@ -504,13 +520,15 @@ fn pin_lifecycle_tracepoint() { #[test_log::test] fn pin_lifecycle_kprobe() { + type P = KProbe; + let program_name = "test_kprobe"; - let attach = |prog: &mut KProbe| prog.attach("try_to_wake_up", 0).unwrap(); + let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap(); // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut KProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap(); } @@ -520,7 +538,7 @@ fn pin_lifecycle_kprobe() { // 2. Load program from bpffs but don't attach it { - let _ = KProbe::from_pin( + let _ = P::from_pin( "/sys/fs/bpf/aya-kprobe-test-prog", aya::programs::ProbeKind::KProbe, ) @@ -532,7 +550,7 @@ fn pin_lifecycle_kprobe() { // 3. Load program from bpffs and attach { - let mut prog = KProbe::from_pin( + let mut prog = P::from_pin( "/sys/fs/bpf/aya-kprobe-test-prog", aya::programs::ProbeKind::KProbe, ) @@ -571,8 +589,10 @@ extern "C" fn uprobe_function() { #[test_log::test] fn pin_lifecycle_uprobe() { + type P = UProbe; + let program_name = "test_uprobe"; - let attach = |prog: &mut UProbe| { + let attach = |prog: &mut P| { prog.attach("uprobe_function", "/proc/self/exe", None, None) .unwrap() }; @@ -583,7 +603,7 @@ fn pin_lifecycle_uprobe() { // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut UProbe = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin(FIRST_PIN_PATH).unwrap(); } @@ -593,7 +613,7 @@ fn pin_lifecycle_uprobe() { // 2. Load program from bpffs but don't attach it { - let _ = UProbe::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); + let _ = P::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); } // should still be loaded since prog was pinned @@ -601,7 +621,7 @@ fn pin_lifecycle_uprobe() { // 3. Load program from bpffs and attach { - let mut prog = UProbe::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); + let mut prog = P::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); From 0f1c975632e9cb9a8f2ec939a46402f5e9e7e2ca Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 08:52:51 -0400 Subject: [PATCH 15/19] integration-test: extract run_unload_program_test --- test/integration-test/src/tests/load.rs | 152 +++++++++--------------- 1 file changed, 55 insertions(+), 97 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index cac176ee..2898ad05 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -4,9 +4,14 @@ use aya::{ Ebpf, maps::Array, programs::{ - FlowDissector, KProbe, TracePoint, UProbe, Xdp, XdpFlags, + FlowDissector, KProbe, Program, ProgramError, TracePoint, UProbe, Xdp, XdpFlags, + flow_dissector::{FlowDissectorLink, FlowDissectorLinkId}, + kprobe::{KProbeLink, KProbeLinkId}, links::{FdLink, PinnedLink}, loaded_links, loaded_programs, + trace_point::{TracePointLink, TracePointLinkId}, + uprobe::{UProbeLink, UProbeLinkId}, + xdp::{XdpLink, XdpLinkId}, }, util::KernelVersion, }; @@ -197,20 +202,63 @@ fn assert_unloaded(name: &str) { ) } +trait UnloadProgramOps { + type LinkId; + type OwnedLink; + + fn load(&mut self) -> Result<(), ProgramError>; + fn unload(&mut self) -> Result<(), ProgramError>; + fn take_link(&mut self, id: Self::LinkId) -> Result; +} + +macro_rules! impl_unload_program_ops { + ($program:ty, $link_id:ty, $link:ty) => { + impl UnloadProgramOps for $program { + type LinkId = $link_id; + type OwnedLink = $link; + + fn load(&mut self) -> Result<(), ProgramError> { + <$program>::load(self) + } + + fn unload(&mut self) -> Result<(), ProgramError> { + <$program>::unload(self) + } + + fn take_link(&mut self, id: Self::LinkId) -> Result { + <$program>::take_link(self, id) + } + } + }; +} + +impl_unload_program_ops!(Xdp, XdpLinkId, XdpLink); +impl_unload_program_ops!(KProbe, KProbeLinkId, KProbeLink); +impl_unload_program_ops!(TracePoint, TracePointLinkId, TracePointLink); +impl_unload_program_ops!(UProbe, UProbeLinkId, UProbeLink); +impl_unload_program_ops!(FlowDissector, FlowDissectorLinkId, FlowDissectorLink); + #[test_log::test] fn unload_xdp() { type P = Xdp; let program_name = "pass"; let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); + run_unload_program_test(crate::TEST, program_name, attach); +} - let mut bpf = Ebpf::load(crate::TEST).unwrap(); +fn run_unload_program_test

(bpf_image: &[u8], program_name: &str, attach: fn(&mut P) -> P::LinkId) +where + P: UnloadProgramOps, + for<'a> &'a mut Program: TryInto<&'a mut P, Error = ProgramError>, +{ + let mut bpf = Ebpf::load(bpf_image).unwrap(); let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded(program_name); let link = attach(prog); { - let _link_owned = prog.take_link(link).unwrap(); + let _link_owned: P::OwnedLink = prog.take_link(link).unwrap(); prog.unload().unwrap(); assert_loaded_and_linked(program_name); } @@ -233,28 +281,7 @@ fn unload_kprobe() { let program_name = "test_kprobe"; let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap(); - - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - prog.load().unwrap(); - assert_loaded(program_name); - let link = attach(prog); - { - let _link_owned = prog.take_link(link).unwrap(); - prog.unload().unwrap(); - assert_loaded_and_linked(program_name); - } - - assert_unloaded(program_name); - prog.load().unwrap(); - - assert_loaded(program_name); - attach(prog); - - assert_loaded(program_name); - prog.unload().unwrap(); - - assert_unloaded(program_name); + run_unload_program_test(crate::TEST, program_name, attach); } #[test_log::test] @@ -263,30 +290,7 @@ fn basic_tracepoint() { let program_name = "test_tracepoint"; let attach = |prog: &mut P| prog.attach("syscalls", "sys_enter_kill").unwrap(); - - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - - prog.load().unwrap(); - assert_loaded(program_name); - let link = attach(prog); - - { - let _link_owned = prog.take_link(link).unwrap(); - prog.unload().unwrap(); - assert_loaded_and_linked(program_name); - } - - assert_unloaded(program_name); - prog.load().unwrap(); - - assert_loaded(program_name); - attach(prog); - - assert_loaded(program_name); - prog.unload().unwrap(); - - assert_unloaded(program_name); + run_unload_program_test(crate::TEST, program_name, attach); } #[test_log::test] @@ -298,30 +302,7 @@ fn basic_uprobe() { prog.attach("uprobe_function", "/proc/self/exe", None, None) .unwrap() }; - - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - - prog.load().unwrap(); - assert_loaded(program_name); - let link = attach(prog); - - { - let _link_owned = prog.take_link(link).unwrap(); - prog.unload().unwrap(); - assert_loaded_and_linked(program_name); - } - - assert_unloaded(program_name); - prog.load().unwrap(); - - assert_loaded(program_name); - attach(prog); - - assert_loaded(program_name); - prog.unload().unwrap(); - - assert_unloaded(program_name); + run_unload_program_test(crate::TEST, program_name, attach); } #[test_log::test] @@ -333,30 +314,7 @@ fn basic_flow_dissector() { let net_ns = std::fs::File::open("/proc/self/ns/net").unwrap(); prog.attach(net_ns).unwrap() }; - - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - - prog.load().unwrap(); - assert_loaded(program_name); - - let link = attach(prog); - { - let _link_owned = prog.take_link(link).unwrap(); - prog.unload().unwrap(); - assert_loaded_and_linked(program_name); - } - - assert_unloaded(program_name); - prog.load().unwrap(); - - assert_loaded(program_name); - attach(prog); - - assert_loaded(program_name); - prog.unload().unwrap(); - - assert_unloaded(program_name); + run_unload_program_test(crate::TEST, program_name, attach); } #[test_log::test] From 0840faf6b12cfd2d2e8a40be32f4074544229678 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 09:00:45 -0400 Subject: [PATCH 16/19] integration-test: extract pin paths --- test/integration-test/src/tests/load.rs | 76 +++++++++---------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 2898ad05..ceb42087 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -359,6 +359,8 @@ fn pin_lifecycle() { let program_name = "pass"; let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); + let program_pin = "/sys/fs/bpf/aya-xdp-test-prog"; + let link_pin = "/sys/fs/bpf/aya-xdp-test-lo"; let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { @@ -373,7 +375,7 @@ fn pin_lifecycle() { let mut bpf = Ebpf::load(crate::PASS).unwrap(); let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); + prog.pin(program_pin).unwrap(); } // should still be loaded since prog was pinned @@ -381,7 +383,7 @@ fn pin_lifecycle() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); + let _ = P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); } // should still be loaded since prog was pinned @@ -389,12 +391,11 @@ fn pin_lifecycle() { // 3. Load program from bpffs and attach { - let mut prog = - P::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); + let mut prog = P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); - fd_link.pin("/sys/fs/bpf/aya-xdp-test-lo").unwrap(); + fd_link.pin(link_pin).unwrap(); // Unpin the program. It will stay attached since its links were pinned. prog.unpin().unwrap(); @@ -409,10 +410,7 @@ fn pin_lifecycle() { let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo") - .unwrap() - .unpin() - .unwrap(); + let link = PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); prog.attach_to_link(link.try_into().unwrap()).unwrap(); assert_loaded(program_name); } @@ -427,13 +425,15 @@ fn pin_lifecycle_tracepoint() { let program_name = "test_tracepoint"; let attach = |prog: &mut P| prog.attach("syscalls", "sys_enter_kill").unwrap(); + let program_pin = "/sys/fs/bpf/aya-tracepoint-test-prog"; + let link_pin = "/sys/fs/bpf/aya-tracepoint-test-sys-enter-kill"; // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); + prog.pin(program_pin).unwrap(); } // should still be loaded since prog was pinned @@ -441,7 +441,7 @@ fn pin_lifecycle_tracepoint() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); + let _ = P::from_pin(program_pin).unwrap(); } // should still be loaded since prog was pinned @@ -449,13 +449,11 @@ fn pin_lifecycle_tracepoint() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); + let mut prog = P::from_pin(program_pin).unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); - fd_link - .pin("/sys/fs/bpf/aya-tracepoint-test-sys-enter-kill") - .unwrap(); + fd_link.pin(link_pin).unwrap(); // Unpin the program. It will stay attached since its links were pinned. prog.unpin().unwrap(); @@ -466,10 +464,7 @@ fn pin_lifecycle_tracepoint() { // 4. unpin link, and make sure everything is unloaded { - PinnedLink::from_pin("/sys/fs/bpf/aya-tracepoint-test-sys-enter-kill") - .unwrap() - .unpin() - .unwrap(); + PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); } // program should be unloaded @@ -482,13 +477,15 @@ fn pin_lifecycle_kprobe() { let program_name = "test_kprobe"; let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap(); + let program_pin = "/sys/fs/bpf/aya-kprobe-test-prog"; + let link_pin = "/sys/fs/bpf/aya-kprobe-test-try-to-wake-up"; // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap(); + prog.pin(program_pin).unwrap(); } // should still be loaded since prog was pinned @@ -496,11 +493,7 @@ fn pin_lifecycle_kprobe() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin( - "/sys/fs/bpf/aya-kprobe-test-prog", - aya::programs::ProbeKind::KProbe, - ) - .unwrap(); + let _ = P::from_pin(program_pin, aya::programs::ProbeKind::KProbe).unwrap(); } // should still be loaded since prog was pinned @@ -508,17 +501,11 @@ fn pin_lifecycle_kprobe() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin( - "/sys/fs/bpf/aya-kprobe-test-prog", - aya::programs::ProbeKind::KProbe, - ) - .unwrap(); + let mut prog = P::from_pin(program_pin, aya::programs::ProbeKind::KProbe).unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); - fd_link - .pin("/sys/fs/bpf/aya-kprobe-test-try-to-wake-up") - .unwrap(); + fd_link.pin(link_pin).unwrap(); // Unpin the program. It will stay attached since its links were pinned. prog.unpin().unwrap(); @@ -529,10 +516,7 @@ fn pin_lifecycle_kprobe() { // 4. unpin link, and make sure everything is unloaded { - PinnedLink::from_pin("/sys/fs/bpf/aya-kprobe-test-try-to-wake-up") - .unwrap() - .unpin() - .unwrap(); + PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); } // program should be unloaded @@ -554,16 +538,15 @@ fn pin_lifecycle_uprobe() { prog.attach("uprobe_function", "/proc/self/exe", None, None) .unwrap() }; - - const FIRST_PIN_PATH: &str = "/sys/fs/bpf/aya-uprobe-test-prog-1"; - const SECOND_PIN_PATH: &str = "/sys/fs/bpf/aya-uprobe-test-prog-2"; + let program_pin = "/sys/fs/bpf/aya-uprobe-test-prog"; + let link_pin = "/sys/fs/bpf/aya-uprobe-test-uprobe-function"; // 1. Load Program and Pin { let mut bpf = Ebpf::load(crate::TEST).unwrap(); let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); - prog.pin(FIRST_PIN_PATH).unwrap(); + prog.pin(program_pin).unwrap(); } // should still be loaded since prog was pinned @@ -571,7 +554,7 @@ fn pin_lifecycle_uprobe() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); + let _ = P::from_pin(program_pin, aya::programs::ProbeKind::UProbe).unwrap(); } // should still be loaded since prog was pinned @@ -579,11 +562,11 @@ fn pin_lifecycle_uprobe() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin(FIRST_PIN_PATH, aya::programs::ProbeKind::UProbe).unwrap(); + let mut prog = P::from_pin(program_pin, aya::programs::ProbeKind::UProbe).unwrap(); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); - fd_link.pin(SECOND_PIN_PATH).unwrap(); + fd_link.pin(link_pin).unwrap(); // Unpin the program. It will stay attached since its links were pinned. prog.unpin().unwrap(); @@ -594,10 +577,7 @@ fn pin_lifecycle_uprobe() { // 4. unpin link, and make sure everything is unloaded { - PinnedLink::from_pin(SECOND_PIN_PATH) - .unwrap() - .unpin() - .unwrap(); + PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); } // program should be unloaded From fe43f776c312f8b69057dbcd342f4d8104cae207 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 09:38:32 -0400 Subject: [PATCH 17/19] integration-test: extract from_pin --- test/integration-test/src/tests/load.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index ceb42087..2f1af1df 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -4,7 +4,7 @@ use aya::{ Ebpf, maps::Array, programs::{ - FlowDissector, KProbe, Program, ProgramError, TracePoint, UProbe, Xdp, XdpFlags, + FlowDissector, KProbe, ProbeKind, Program, ProgramError, TracePoint, UProbe, Xdp, XdpFlags, flow_dissector::{FlowDissectorLink, FlowDissectorLinkId}, kprobe::{KProbeLink, KProbeLinkId}, links::{FdLink, PinnedLink}, @@ -361,6 +361,7 @@ fn pin_lifecycle() { let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); let program_pin = "/sys/fs/bpf/aya-xdp-test-prog"; let link_pin = "/sys/fs/bpf/aya-xdp-test-lo"; + let from_pin = |program_pin| P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { @@ -383,7 +384,7 @@ fn pin_lifecycle() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); + let _: P = from_pin(program_pin); } // should still be loaded since prog was pinned @@ -391,7 +392,7 @@ fn pin_lifecycle() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); + let mut prog = from_pin(program_pin); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); @@ -427,6 +428,7 @@ fn pin_lifecycle_tracepoint() { let attach = |prog: &mut P| prog.attach("syscalls", "sys_enter_kill").unwrap(); let program_pin = "/sys/fs/bpf/aya-tracepoint-test-prog"; let link_pin = "/sys/fs/bpf/aya-tracepoint-test-sys-enter-kill"; + let from_pin = |program_pin| P::from_pin(program_pin).unwrap(); // 1. Load Program and Pin { @@ -441,7 +443,7 @@ fn pin_lifecycle_tracepoint() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin(program_pin).unwrap(); + let _: P = from_pin(program_pin); } // should still be loaded since prog was pinned @@ -449,7 +451,7 @@ fn pin_lifecycle_tracepoint() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin(program_pin).unwrap(); + let mut prog = from_pin(program_pin); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); @@ -479,6 +481,7 @@ fn pin_lifecycle_kprobe() { let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap(); let program_pin = "/sys/fs/bpf/aya-kprobe-test-prog"; let link_pin = "/sys/fs/bpf/aya-kprobe-test-try-to-wake-up"; + let from_pin = |program_pin| P::from_pin(program_pin, ProbeKind::KProbe).unwrap(); // 1. Load Program and Pin { @@ -493,7 +496,7 @@ fn pin_lifecycle_kprobe() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin(program_pin, aya::programs::ProbeKind::KProbe).unwrap(); + let _: P = from_pin(program_pin); } // should still be loaded since prog was pinned @@ -501,7 +504,7 @@ fn pin_lifecycle_kprobe() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin(program_pin, aya::programs::ProbeKind::KProbe).unwrap(); + let mut prog = from_pin(program_pin); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); @@ -540,6 +543,7 @@ fn pin_lifecycle_uprobe() { }; let program_pin = "/sys/fs/bpf/aya-uprobe-test-prog"; let link_pin = "/sys/fs/bpf/aya-uprobe-test-uprobe-function"; + let from_pin = |program_pin| P::from_pin(program_pin, ProbeKind::UProbe).unwrap(); // 1. Load Program and Pin { @@ -554,7 +558,7 @@ fn pin_lifecycle_uprobe() { // 2. Load program from bpffs but don't attach it { - let _ = P::from_pin(program_pin, aya::programs::ProbeKind::UProbe).unwrap(); + let _: P = from_pin(program_pin); } // should still be loaded since prog was pinned @@ -562,7 +566,7 @@ fn pin_lifecycle_uprobe() { // 3. Load program from bpffs and attach { - let mut prog = P::from_pin(program_pin, aya::programs::ProbeKind::UProbe).unwrap(); + let mut prog = from_pin(program_pin); let link_id = attach(&mut prog); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); From 08cf90881f0f3e1c94db8b182191dfe31b87b8d1 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 15 Oct 2025 09:49:55 -0400 Subject: [PATCH 18/19] integration-test: extract run_pin_program_lifecycle_test --- test/integration-test/src/tests/load.rs | 228 ++++++++++-------------- 1 file changed, 90 insertions(+), 138 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 2f1af1df..ab784692 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -3,11 +3,12 @@ use std::{convert::TryInto as _, fs::remove_file, path::Path, thread, time::Dura use aya::{ Ebpf, maps::Array, + pin::PinError, programs::{ FlowDissector, KProbe, ProbeKind, Program, ProgramError, TracePoint, UProbe, Xdp, XdpFlags, flow_dissector::{FlowDissectorLink, FlowDissectorLinkId}, kprobe::{KProbeLink, KProbeLinkId}, - links::{FdLink, PinnedLink}, + links::{FdLink, LinkError, PinnedLink}, loaded_links, loaded_programs, trace_point::{TracePointLink, TracePointLinkId}, uprobe::{UProbeLink, UProbeLinkId}, @@ -353,6 +354,30 @@ fn pin_link() { assert_unloaded(program_name); } +trait PinProgramOps { + fn pin>(&mut self, path: P) -> Result<(), PinError>; + fn unpin(self) -> Result<(), std::io::Error>; +} + +macro_rules! impl_pin_program_ops { + ($program:ty) => { + impl PinProgramOps for $program { + fn pin>(&mut self, path: P) -> Result<(), PinError> { + <$program>::pin(self, path) + } + + fn unpin(self) -> Result<(), std::io::Error> { + <$program>::unpin(self) + } + } + }; +} + +impl_pin_program_ops!(Xdp); +impl_pin_program_ops!(KProbe); +impl_pin_program_ops!(TracePoint); +impl_pin_program_ops!(UProbe); + #[test_log::test] fn pin_lifecycle() { type P = Xdp; @@ -361,7 +386,7 @@ fn pin_lifecycle() { let attach = |prog: &mut P| prog.attach("lo", XdpFlags::default()).unwrap(); let program_pin = "/sys/fs/bpf/aya-xdp-test-prog"; let link_pin = "/sys/fs/bpf/aya-xdp-test-lo"; - let from_pin = |program_pin| P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); + let from_pin = |program_pin: &str| P::from_pin(program_pin, XdpAttachType::Interface).unwrap(); let kernel_version = KernelVersion::current().unwrap(); if kernel_version < KernelVersion::new(5, 18, 0) { @@ -370,10 +395,35 @@ fn pin_lifecycle() { ); return; } + run_pin_program_lifecycle_test( + crate::PASS, + program_name, + program_pin, + link_pin, + from_pin, + attach, + Some(|prog: &mut P, pinned: FdLink| { + prog.attach_to_link(pinned.try_into().unwrap()).unwrap() + }), + ); +} +fn run_pin_program_lifecycle_test

( + bpf_image: &[u8], + program_name: &str, + program_pin: &str, + link_pin: &str, + from_pin: fn(&str) -> P, + attach: fn(&mut P) -> P::LinkId, + attach_to_link: Option P::LinkId>, +) where + P: UnloadProgramOps + PinProgramOps, + P::OwnedLink: TryInto, + for<'a> &'a mut Program: TryInto<&'a mut P, Error = ProgramError>, +{ // 1. Load Program and Pin { - let mut bpf = Ebpf::load(crate::PASS).unwrap(); + let mut bpf = Ebpf::load(bpf_image).unwrap(); let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin(program_pin).unwrap(); @@ -407,13 +457,14 @@ fn pin_lifecycle() { // 4. Load a new version of the program, unpin link, and atomically replace old program { - let mut bpf = Ebpf::load(crate::PASS).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - prog.load().unwrap(); - let link = PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); - prog.attach_to_link(link.try_into().unwrap()).unwrap(); - assert_loaded(program_name); + if let Some(attach_to_link) = attach_to_link { + let mut bpf = Ebpf::load(bpf_image).unwrap(); + let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); + prog.load().unwrap(); + attach_to_link(prog, link); + assert_loaded(program_name); + } } // program should be unloaded @@ -428,49 +479,16 @@ fn pin_lifecycle_tracepoint() { let attach = |prog: &mut P| prog.attach("syscalls", "sys_enter_kill").unwrap(); let program_pin = "/sys/fs/bpf/aya-tracepoint-test-prog"; let link_pin = "/sys/fs/bpf/aya-tracepoint-test-sys-enter-kill"; - let from_pin = |program_pin| P::from_pin(program_pin).unwrap(); - - // 1. Load Program and Pin - { - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - prog.load().unwrap(); - prog.pin(program_pin).unwrap(); - } - - // should still be loaded since prog was pinned - assert_loaded(program_name); - - // 2. Load program from bpffs but don't attach it - { - let _: P = from_pin(program_pin); - } - - // should still be loaded since prog was pinned - assert_loaded(program_name); - - // 3. Load program from bpffs and attach - { - let mut prog = from_pin(program_pin); - let link_id = attach(&mut prog); - let link = prog.take_link(link_id).unwrap(); - let fd_link: FdLink = link.try_into().unwrap(); - fd_link.pin(link_pin).unwrap(); - - // Unpin the program. It will stay attached since its links were pinned. - prog.unpin().unwrap(); - } - - // should still be loaded since link was pinned - assert_loaded_and_linked(program_name); - - // 4. unpin link, and make sure everything is unloaded - { - PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); - } - - // program should be unloaded - assert_unloaded(program_name); + let from_pin = |program_pin: &str| P::from_pin(program_pin).unwrap(); + run_pin_program_lifecycle_test( + crate::TEST, + program_name, + program_pin, + link_pin, + from_pin, + attach, + None, + ); } #[test_log::test] @@ -481,49 +499,16 @@ fn pin_lifecycle_kprobe() { let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap(); let program_pin = "/sys/fs/bpf/aya-kprobe-test-prog"; let link_pin = "/sys/fs/bpf/aya-kprobe-test-try-to-wake-up"; - let from_pin = |program_pin| P::from_pin(program_pin, ProbeKind::KProbe).unwrap(); - - // 1. Load Program and Pin - { - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - prog.load().unwrap(); - prog.pin(program_pin).unwrap(); - } - - // should still be loaded since prog was pinned - assert_loaded(program_name); - - // 2. Load program from bpffs but don't attach it - { - let _: P = from_pin(program_pin); - } - - // should still be loaded since prog was pinned - assert_loaded(program_name); - - // 3. Load program from bpffs and attach - { - let mut prog = from_pin(program_pin); - let link_id = attach(&mut prog); - let link = prog.take_link(link_id).unwrap(); - let fd_link: FdLink = link.try_into().unwrap(); - fd_link.pin(link_pin).unwrap(); - - // Unpin the program. It will stay attached since its links were pinned. - prog.unpin().unwrap(); - } - - // should still be loaded since link was pinned - assert_loaded_and_linked(program_name); - - // 4. unpin link, and make sure everything is unloaded - { - PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); - } - - // program should be unloaded - assert_unloaded(program_name); + let from_pin = |program_pin: &str| P::from_pin(program_pin, ProbeKind::KProbe).unwrap(); + run_pin_program_lifecycle_test( + crate::TEST, + program_name, + program_pin, + link_pin, + from_pin, + attach, + None, + ); } #[unsafe(no_mangle)] @@ -543,49 +528,16 @@ fn pin_lifecycle_uprobe() { }; let program_pin = "/sys/fs/bpf/aya-uprobe-test-prog"; let link_pin = "/sys/fs/bpf/aya-uprobe-test-uprobe-function"; - let from_pin = |program_pin| P::from_pin(program_pin, ProbeKind::UProbe).unwrap(); - - // 1. Load Program and Pin - { - let mut bpf = Ebpf::load(crate::TEST).unwrap(); - let prog: &mut P = bpf.program_mut(program_name).unwrap().try_into().unwrap(); - prog.load().unwrap(); - prog.pin(program_pin).unwrap(); - } - - // should still be loaded since prog was pinned - assert_loaded(program_name); - - // 2. Load program from bpffs but don't attach it - { - let _: P = from_pin(program_pin); - } - - // should still be loaded since prog was pinned - assert_loaded(program_name); - - // 3. Load program from bpffs and attach - { - let mut prog = from_pin(program_pin); - let link_id = attach(&mut prog); - let link = prog.take_link(link_id).unwrap(); - let fd_link: FdLink = link.try_into().unwrap(); - fd_link.pin(link_pin).unwrap(); - - // Unpin the program. It will stay attached since its links were pinned. - prog.unpin().unwrap(); - } - - // should still be loaded since link was pinned - assert_loaded_and_linked(program_name); - - // 4. unpin link, and make sure everything is unloaded - { - PinnedLink::from_pin(link_pin).unwrap().unpin().unwrap(); - } - - // program should be unloaded - assert_unloaded(program_name); + let from_pin = |program_pin: &str| P::from_pin(program_pin, ProbeKind::UProbe).unwrap(); + run_pin_program_lifecycle_test( + crate::TEST, + program_name, + program_pin, + link_pin, + from_pin, + attach, + None, + ); // Make sure the function isn't optimized out. uprobe_function(); From 3d7fbaad28fc8ad49f0a5afb08c686011ed25c5c Mon Sep 17 00:00:00 2001 From: Tyrone Wu Date: Tue, 8 Oct 2024 17:45:28 +0000 Subject: [PATCH 19/19] aya: enforce valid perf_event type & config combos Add guardrails for when setting event type and config for perf_event programs. The `PerfEventConfig` enum now defines the event `type` and `config` of interest. Remove public re-exports, and add idiomatic Rust types for: - perf_hw_id => HardwareEvent - perf_sw_ids => SoftwareEvent - perf_hw_cache_id => HwCacheEvent - perf_hw_cache_op_id => HwCacheOp - perf_hw_cache_op_result_id => HwCacheResult The motivation behind this is mainly for the `type` and `config` fields of `bpf_link_info.perf_event.event`. The newly added enums are planned to also be used in the `bpf_link_info` metadata. Although `Breakpoint`/`PERF_TYPE_BREAKPOINT` variant exists, it is not fully implemented. It's only usage at the moment is in link info. --- aya/src/programs/mod.rs | 2 +- aya/src/programs/perf_event.rs | 332 ++++++++++++++++++++++++++++---- xtask/public-api/aya.txt | 339 ++++++++++++++++++++++++--------- 3 files changed, 554 insertions(+), 119 deletions(-) diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index eda6fa7f..ec7d1520 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -111,7 +111,7 @@ pub use crate::programs::{ lirc_mode2::LircMode2, lsm::Lsm, lsm_cgroup::LsmCgroup, - perf_event::{PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy}, + perf_event::{PerfEvent, PerfEventScope, SamplePolicy}, probe::ProbeKind, raw_trace_point::RawTracePoint, sk_lookup::SkLookup, diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 991227b1..93d3dfe1 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -5,14 +5,13 @@ use std::os::fd::AsFd as _; use aya_obj::generated::{ bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_PERF_EVENT, + perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids, + perf_type_id, perf_type_id::{ PERF_TYPE_BREAKPOINT, PERF_TYPE_HARDWARE, PERF_TYPE_HW_CACHE, PERF_TYPE_RAW, PERF_TYPE_SOFTWARE, PERF_TYPE_TRACEPOINT, }, }; -pub use aya_obj::generated::{ - perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids, -}; use crate::{ programs::{ @@ -24,22 +23,263 @@ use crate::{ sys::{SyscallError, bpf_link_get_info_by_fd, perf_event_open}, }; -/// The type of perf event +/// The type of perf event and their respective configuration. +#[doc(alias = "perf_type_id")] +#[derive(Debug, Clone, Copy)] +pub enum PerfEventConfig { + /// The hardware event to report. + #[doc(alias = "PERF_TYPE_HARDWARE")] + Hardware(HardwareEvent), + /// The software event to report. + #[doc(alias = "PERF_TYPE_SOFTWARE")] + Software(SoftwareEvent), + /// The kernel trace point event to report. + #[doc(alias = "PERF_TYPE_TRACEPOINT")] + TracePoint { + /// The ID of the tracing event. This can be obtained from + /// `/sys/kernel/debug/tracing/events/*/*/id` if `ftrace` is enabled in the kernel. + event_id: u64, + }, + /// The hardware cache event to report. + #[doc(alias = "PERF_TYPE_HW_CACHE")] + HwCache { + /// The hardware cache event. + event: HwCacheEvent, + /// The hardware cache operation. + operation: HwCacheOp, + /// The hardware cache result of interest. + result: HwCacheResult, + }, + /// The "raw" implementation-specific event to report. + #[doc(alias = "PERF_TYPE_RAW")] + Raw { + /// The "raw" event value, which is not covered by the "generalized" events. This is CPU + /// implementation defined events. + event_id: u64, + }, + /// A hardware breakpoint. + /// + /// Note: this variant is not fully implemented at the moment. + // TODO: Variant not fully implemented due to additional `perf_event_attr` fields like + // `bp_type`, `bp_addr`, etc. + #[doc(alias = "PERF_TYPE_BREAKPOINT")] + Breakpoint, + /// The dynamic PMU (Performance Monitor Unit) event to report. + /// + /// Available PMU's may be found under `/sys/bus/event_source/devices`. + Pmu { + /// The PMU type. + /// + /// This value can extracted from `/sys/bus/event_source/devices/*/type`. + pmu_type: u32, + /// The PMU config option. + /// + /// This value can extracted from `/sys/bus/event_source/devices/*/format/`, where the + /// `config:` indicates the bit position to set. + /// + /// For example, `config:3` => `config = 1 << 3`. + config: u64, + }, +} + +macro_rules! impl_to_u32 { + ($($t:ty, $fn:ident),*) => { + $(const fn $fn(id: $t) -> u32 { + const _: [(); 4] = [(); std::mem::size_of::<$t>()]; + id as u32 + })* + }; +} + +impl_to_u32!( + perf_hw_id, + perf_hw_id_to_u32, + perf_sw_ids, + perf_sw_ids_to_u32, + perf_hw_cache_id, + perf_hw_cache_id_to_u32, + perf_hw_cache_op_id, + perf_hw_cache_op_id_to_u32, + perf_hw_cache_op_result_id, + perf_hw_cache_op_result_id_to_u32, + perf_type_id, + perf_type_id_to_u32 +); + +/// The "generalized" hardware CPU events provided by the kernel. +#[doc(alias = "perf_hw_id")] +#[derive(Debug, Clone, Copy)] #[repr(u32)] -#[derive(Debug, Clone)] -pub enum PerfTypeId { - /// PERF_TYPE_HARDWARE - Hardware = PERF_TYPE_HARDWARE as u32, - /// PERF_TYPE_SOFTWARE - Software = PERF_TYPE_SOFTWARE as u32, - /// PERF_TYPE_TRACEPOINT - TracePoint = PERF_TYPE_TRACEPOINT as u32, - /// PERF_TYPE_HW_CACHE - HwCache = PERF_TYPE_HW_CACHE as u32, - /// PERF_TYPE_RAW - Raw = PERF_TYPE_RAW as u32, - /// PERF_TYPE_BREAKPOINT - Breakpoint = PERF_TYPE_BREAKPOINT as u32, +pub enum HardwareEvent { + /// The total CPU cycles. + #[doc(alias = "PERF_COUNT_HW_CPU_CYCLES")] + CpuCycles = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_CPU_CYCLES), + /// Number of retired instructions. + #[doc(alias = "PERF_COUNT_HW_INSTRUCTIONS")] + Instructions = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_INSTRUCTIONS), + /// Number of cache accesses. + #[doc(alias = "PERF_COUNT_HW_CACHE_REFERENCES")] + CacheReferences = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_CACHE_REFERENCES), + /// Number of cache misses. + #[doc(alias = "PERF_COUNT_HW_CACHE_MISSES")] + CacheMisses = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_CACHE_MISSES), + /// Number of retired branch instructions. + #[doc(alias = "PERF_COUNT_HW_BRANCH_INSTRUCTIONS")] + BranchInstructions = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_BRANCH_INSTRUCTIONS), + /// Number of mispredicted branch instructions. + #[doc(alias = "PERF_COUNT_HW_BRANCH_MISSES")] + BranchMisses = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_BRANCH_MISSES), + /// Number of bus cycles. + #[doc(alias = "PERF_COUNT_HW_BUS_CYCLES")] + BusCycles = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_BUS_CYCLES), + /// Number of stalled cycles during issue. + #[doc(alias = "PERF_COUNT_HW_STALLED_CYCLES_FRONTEND")] + StalledCyclesFrontend = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_STALLED_CYCLES_FRONTEND), + /// Number of stalled cycles during retirement. + #[doc(alias = "PERF_COUNT_HW_STALLED_CYCLES_BACKEND")] + StalledCyclesBackend = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_STALLED_CYCLES_BACKEND), + /// The total CPU cycles, which is not affected by CPU frequency scaling. + #[doc(alias = "PERF_COUNT_HW_REF_CPU_CYCLES")] + RefCpuCycles = perf_hw_id_to_u32(perf_hw_id::PERF_COUNT_HW_REF_CPU_CYCLES), +} + +impl HardwareEvent { + const fn into_primitive(self) -> u32 { + const _: [(); 4] = [(); std::mem::size_of::()]; + self as u32 + } +} + +/// The software-defined events provided by the kernel. +#[doc(alias = "perf_sw_ids")] +#[derive(Debug, Clone, Copy)] +#[repr(u32)] +pub enum SoftwareEvent { + /// The CPU clock timer. + #[doc(alias = "PERF_COUNT_SW_CPU_CLOCK")] + CpuClock = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK), + /// The clock count specific to the task that is running. + #[doc(alias = "PERF_COUNT_SW_TASK_CLOCK")] + TaskClock = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_TASK_CLOCK), + /// Number of page faults. + #[doc(alias = "PERF_COUNT_SW_PAGE_FAULTS")] + PageFaults = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_PAGE_FAULTS), + /// Numer of context switches. + #[doc(alias = "PERF_COUNT_SW_CONTEXT_SWITCHES")] + ContextSwitches = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_CONTEXT_SWITCHES), + /// Number of times the process has migrated to a new CPU. + #[doc(alias = "PERF_COUNT_SW_CPU_MIGRATIONS")] + CpuMigrations = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_CPU_MIGRATIONS), + /// Number of minor page faults. + #[doc(alias = "PERF_COUNT_SW_PAGE_FAULTS_MIN")] + PageFaultsMin = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_PAGE_FAULTS_MIN), + /// Number of major page faults. + #[doc(alias = "PERF_COUNT_SW_PAGE_FAULTS_MAJ")] + PageFaultsMaj = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_PAGE_FAULTS_MAJ), + /// Number of alignment faults. + #[doc(alias = "PERF_COUNT_SW_ALIGNMENT_FAULTS")] + AlignmentFaults = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_ALIGNMENT_FAULTS), + /// Number of emulation faults. + #[doc(alias = "PERF_COUNT_SW_EMULATION_FAULTS")] + EmulationFaults = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_EMULATION_FAULTS), + /// Placeholder event that counts nothing. + #[doc(alias = "PERF_COUNT_SW_DUMMY")] + Dummy = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_DUMMY), + /// Generates raw sample data from BPF. + #[doc(alias = "PERF_COUNT_SW_BPF_OUTPUT")] + BpfOutput = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_BPF_OUTPUT), + /// Number of context switches to a task when switching to a different cgroup. + #[doc(alias = "PERF_COUNT_SW_CGROUP_SWITCHES")] + CgroupSwitches = perf_sw_ids_to_u32(perf_sw_ids::PERF_COUNT_SW_CGROUP_SWITCHES), +} + +impl SoftwareEvent { + const fn into_primitive(self) -> u32 { + const _: [(); 4] = [(); std::mem::size_of::()]; + self as u32 + } +} + +/// The hardware CPU cache events. +#[doc(alias = "perf_hw_cache_id")] +#[derive(Debug, Clone, Copy)] +#[repr(u32)] +pub enum HwCacheEvent { + /// Measures Level 1 data cache. + #[doc(alias = "PERF_COUNT_HW_CACHE_L1D")] + L1d = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_L1D), + /// Measures Level 1 data cache. + #[doc(alias = "PERF_COUNT_HW_CACHE_L1I")] + L1i = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_L1I), + /// Measures Last-level cache. + #[doc(alias = "PERF_COUNT_HW_CACHE_LL")] + Ll = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_LL), + /// Measures Data TLB (Translation Lookaside Buffer). + #[doc(alias = "PERF_COUNT_HW_CACHE_DTLB")] + Dtlb = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_DTLB), + /// Measures Instruction TLB (Translation Lookaside Buffer). + #[doc(alias = "PERF_COUNT_HW_CACHE_ITLB")] + Itlb = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_ITLB), + /// Measures branch prediction. + #[doc(alias = "PERF_COUNT_HW_CACHE_BPU")] + Bpu = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_BPU), + /// Measures local memory accesses. + #[doc(alias = "PERF_COUNT_HW_CACHE_NODE")] + Node = perf_hw_cache_id_to_u32(perf_hw_cache_id::PERF_COUNT_HW_CACHE_NODE), +} + +impl HwCacheEvent { + const fn into_primitive(self) -> u32 { + const _: [(); 4] = [(); std::mem::size_of::()]; + self as u32 + } +} + +/// The hardware CPU cache operations. +#[doc(alias = "perf_hw_cache_op_id")] +#[derive(Debug, Clone, Copy)] +#[repr(u32)] +pub enum HwCacheOp { + /// Read access. + #[doc(alias = "PERF_COUNT_HW_CACHE_OP_READ")] + Read = perf_hw_cache_op_id_to_u32(perf_hw_cache_op_id::PERF_COUNT_HW_CACHE_OP_READ), + /// Write access. + #[doc(alias = "PERF_COUNT_HW_CACHE_OP_WRITE")] + Write = perf_hw_cache_op_id_to_u32(perf_hw_cache_op_id::PERF_COUNT_HW_CACHE_OP_WRITE), + /// Prefetch access. + #[doc(alias = "PERF_COUNT_HW_CACHE_OP_PREFETCH")] + Prefetch = perf_hw_cache_op_id_to_u32(perf_hw_cache_op_id::PERF_COUNT_HW_CACHE_OP_PREFETCH), +} + +impl HwCacheOp { + const fn into_primitive(self) -> u32 { + const _: [(); 4] = [(); std::mem::size_of::()]; + self as u32 + } +} + +/// The hardware CPU cache result. +#[doc(alias = "perf_hw_cache_op_result_id")] +#[derive(Debug, Clone, Copy)] +#[repr(u32)] +pub enum HwCacheResult { + /// Cache accesses. + #[doc(alias = "PERF_COUNT_HW_CACHE_RESULT_ACCESS")] + Access = perf_hw_cache_op_result_id_to_u32( + perf_hw_cache_op_result_id::PERF_COUNT_HW_CACHE_RESULT_ACCESS, + ), + /// Cache missed accesses. + #[doc(alias = "PERF_COUNT_HW_CACHE_RESULT_MISS")] + Miss = perf_hw_cache_op_result_id_to_u32( + perf_hw_cache_op_result_id::PERF_COUNT_HW_CACHE_RESULT_MISS, + ), +} + +impl HwCacheResult { + const fn into_primitive(self) -> u32 { + const _: [(); 4] = [(); std::mem::size_of::()]; + self as u32 + } } /// Sample Policy @@ -100,19 +340,21 @@ pub enum PerfEventScope { /// # #[error(transparent)] /// # Ebpf(#[from] aya::EbpfError) /// # } -/// # let mut bpf = aya::Ebpf::load(&[])?; -/// use aya::util::online_cpus; -/// use aya::programs::perf_event::{ -/// perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK, PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy, +/// use aya::{ +/// util::online_cpus, +/// programs::perf_event::{ +/// PerfEvent, PerfEventConfig, PerfEventScope, SamplePolicy, SoftwareEvent, +/// }, /// }; /// +/// # let mut bpf = aya::Ebpf::load(&[])?; /// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?; /// prog.load()?; /// +/// let perf_type = PerfEventConfig::Software(SoftwareEvent::CpuClock); /// for cpu in online_cpus().map_err(|(_, error)| error)? { /// prog.attach( -/// PerfTypeId::Software, -/// PERF_COUNT_SW_CPU_CLOCK as u64, +/// perf_type, /// PerfEventScope::AllProcessesOneCpu { cpu }, /// SamplePolicy::Period(1000000), /// true, @@ -137,25 +379,49 @@ impl PerfEvent { /// Attaches to the given perf event. /// - /// The possible values and encoding of the `config` argument depends on the - /// `perf_type`. See `perf_sw_ids`, `perf_hw_id`, `perf_hw_cache_id`, - /// `perf_hw_cache_op_id` and `perf_hw_cache_op_result_id`. + /// [`perf_type`](PerfEventConfig) defines the event `type` and `config` of interest. /// - /// The `scope` argument determines which processes are sampled. If `inherit` - /// is true, any new processes spawned by those processes will also - /// automatically get sampled. + /// [`scope`](PerfEventScope) determines which processes are sampled. If `inherit` is + /// `true`, any new processes spawned by those processes will also automatically be + /// sampled. /// /// The returned value can be used to detach, see [PerfEvent::detach]. pub fn attach( &mut self, - perf_type: PerfTypeId, - config: u64, + perf_type: PerfEventConfig, scope: PerfEventScope, sample_policy: SamplePolicy, inherit: bool, ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); + + let (perf_type, config) = match perf_type { + PerfEventConfig::Pmu { pmu_type, config } => (pmu_type, config), + PerfEventConfig::Hardware(hw_event) => ( + perf_type_id_to_u32(PERF_TYPE_HARDWARE), + u64::from(hw_event.into_primitive()), + ), + PerfEventConfig::Software(sw_event) => ( + perf_type_id_to_u32(PERF_TYPE_SOFTWARE), + u64::from(sw_event.into_primitive()), + ), + PerfEventConfig::TracePoint { event_id } => { + (perf_type_id_to_u32(PERF_TYPE_TRACEPOINT), event_id) + } + PerfEventConfig::HwCache { + event, + operation, + result, + } => ( + perf_type_id_to_u32(PERF_TYPE_HW_CACHE), + u64::from(event.into_primitive()) + | (u64::from(operation.into_primitive()) << 8) + | (u64::from(result.into_primitive()) << 16), + ), + PerfEventConfig::Raw { event_id } => (perf_type_id_to_u32(PERF_TYPE_RAW), event_id), + PerfEventConfig::Breakpoint => (perf_type_id_to_u32(PERF_TYPE_BREAKPOINT), 0), + }; let (sample_period, sample_frequency) = match sample_policy { SamplePolicy::Period(period) => (period, None), SamplePolicy::Frequency(frequency) => (0, Some(frequency)), @@ -168,7 +434,7 @@ impl PerfEvent { PerfEventScope::AllProcessesOneCpu { cpu } => (-1, cpu as i32), }; let fd = perf_event_open( - perf_type as u32, + perf_type, config, pid, cpu, diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index d5e03521..d4a5d1cc 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -5299,11 +5299,212 @@ pub fn aya::programs::perf_attach::PerfLinkId::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::perf_attach::PerfLinkId pub fn aya::programs::perf_attach::PerfLinkId::from(t: T) -> T pub mod aya::programs::perf_event -pub use aya::programs::perf_event::perf_hw_cache_id -pub use aya::programs::perf_event::perf_hw_cache_op_id -pub use aya::programs::perf_event::perf_hw_cache_op_result_id -pub use aya::programs::perf_event::perf_hw_id -pub use aya::programs::perf_event::perf_sw_ids +#[repr(u32)] pub enum aya::programs::perf_event::HardwareEvent +pub aya::programs::perf_event::HardwareEvent::BranchInstructions = 4 +pub aya::programs::perf_event::HardwareEvent::BranchMisses = 5 +pub aya::programs::perf_event::HardwareEvent::BusCycles = 6 +pub aya::programs::perf_event::HardwareEvent::CacheMisses = 3 +pub aya::programs::perf_event::HardwareEvent::CacheReferences = 2 +pub aya::programs::perf_event::HardwareEvent::CpuCycles = 0 +pub aya::programs::perf_event::HardwareEvent::Instructions = 1 +pub aya::programs::perf_event::HardwareEvent::RefCpuCycles = 9 +pub aya::programs::perf_event::HardwareEvent::StalledCyclesBackend = 8 +pub aya::programs::perf_event::HardwareEvent::StalledCyclesFrontend = 7 +impl core::clone::Clone for aya::programs::perf_event::HardwareEvent +pub fn aya::programs::perf_event::HardwareEvent::clone(&self) -> aya::programs::perf_event::HardwareEvent +impl core::fmt::Debug for aya::programs::perf_event::HardwareEvent +pub fn aya::programs::perf_event::HardwareEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::perf_event::HardwareEvent +impl core::marker::Freeze for aya::programs::perf_event::HardwareEvent +impl core::marker::Send for aya::programs::perf_event::HardwareEvent +impl core::marker::Sync for aya::programs::perf_event::HardwareEvent +impl core::marker::Unpin for aya::programs::perf_event::HardwareEvent +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::HardwareEvent +impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::HardwareEvent +impl core::convert::Into for aya::programs::perf_event::HardwareEvent where U: core::convert::From +pub fn aya::programs::perf_event::HardwareEvent::into(self) -> U +impl core::convert::TryFrom for aya::programs::perf_event::HardwareEvent where U: core::convert::Into +pub type aya::programs::perf_event::HardwareEvent::Error = core::convert::Infallible +pub fn aya::programs::perf_event::HardwareEvent::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::perf_event::HardwareEvent where U: core::convert::TryFrom +pub type aya::programs::perf_event::HardwareEvent::Error = >::Error +pub fn aya::programs::perf_event::HardwareEvent::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::perf_event::HardwareEvent where T: core::clone::Clone +pub type aya::programs::perf_event::HardwareEvent::Owned = T +pub fn aya::programs::perf_event::HardwareEvent::clone_into(&self, target: &mut T) +pub fn aya::programs::perf_event::HardwareEvent::to_owned(&self) -> T +impl core::any::Any for aya::programs::perf_event::HardwareEvent where T: 'static + ?core::marker::Sized +pub fn aya::programs::perf_event::HardwareEvent::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::perf_event::HardwareEvent where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HardwareEvent::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::perf_event::HardwareEvent where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HardwareEvent::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::perf_event::HardwareEvent where T: core::clone::Clone +pub unsafe fn aya::programs::perf_event::HardwareEvent::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::perf_event::HardwareEvent +pub fn aya::programs::perf_event::HardwareEvent::from(t: T) -> T +#[repr(u32)] pub enum aya::programs::perf_event::HwCacheEvent +pub aya::programs::perf_event::HwCacheEvent::Bpu = 5 +pub aya::programs::perf_event::HwCacheEvent::Dtlb = 3 +pub aya::programs::perf_event::HwCacheEvent::Itlb = 4 +pub aya::programs::perf_event::HwCacheEvent::L1d = 0 +pub aya::programs::perf_event::HwCacheEvent::L1i = 1 +pub aya::programs::perf_event::HwCacheEvent::Ll = 2 +pub aya::programs::perf_event::HwCacheEvent::Node = 6 +impl core::clone::Clone for aya::programs::perf_event::HwCacheEvent +pub fn aya::programs::perf_event::HwCacheEvent::clone(&self) -> aya::programs::perf_event::HwCacheEvent +impl core::fmt::Debug for aya::programs::perf_event::HwCacheEvent +pub fn aya::programs::perf_event::HwCacheEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::perf_event::HwCacheEvent +impl core::marker::Freeze for aya::programs::perf_event::HwCacheEvent +impl core::marker::Send for aya::programs::perf_event::HwCacheEvent +impl core::marker::Sync for aya::programs::perf_event::HwCacheEvent +impl core::marker::Unpin for aya::programs::perf_event::HwCacheEvent +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::HwCacheEvent +impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::HwCacheEvent +impl core::convert::Into for aya::programs::perf_event::HwCacheEvent where U: core::convert::From +pub fn aya::programs::perf_event::HwCacheEvent::into(self) -> U +impl core::convert::TryFrom for aya::programs::perf_event::HwCacheEvent where U: core::convert::Into +pub type aya::programs::perf_event::HwCacheEvent::Error = core::convert::Infallible +pub fn aya::programs::perf_event::HwCacheEvent::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::perf_event::HwCacheEvent where U: core::convert::TryFrom +pub type aya::programs::perf_event::HwCacheEvent::Error = >::Error +pub fn aya::programs::perf_event::HwCacheEvent::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::perf_event::HwCacheEvent where T: core::clone::Clone +pub type aya::programs::perf_event::HwCacheEvent::Owned = T +pub fn aya::programs::perf_event::HwCacheEvent::clone_into(&self, target: &mut T) +pub fn aya::programs::perf_event::HwCacheEvent::to_owned(&self) -> T +impl core::any::Any for aya::programs::perf_event::HwCacheEvent where T: 'static + ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheEvent::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::perf_event::HwCacheEvent where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheEvent::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::perf_event::HwCacheEvent where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheEvent::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::perf_event::HwCacheEvent where T: core::clone::Clone +pub unsafe fn aya::programs::perf_event::HwCacheEvent::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::perf_event::HwCacheEvent +pub fn aya::programs::perf_event::HwCacheEvent::from(t: T) -> T +#[repr(u32)] pub enum aya::programs::perf_event::HwCacheOp +pub aya::programs::perf_event::HwCacheOp::Prefetch = 2 +pub aya::programs::perf_event::HwCacheOp::Read = 0 +pub aya::programs::perf_event::HwCacheOp::Write = 1 +impl core::clone::Clone for aya::programs::perf_event::HwCacheOp +pub fn aya::programs::perf_event::HwCacheOp::clone(&self) -> aya::programs::perf_event::HwCacheOp +impl core::fmt::Debug for aya::programs::perf_event::HwCacheOp +pub fn aya::programs::perf_event::HwCacheOp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::perf_event::HwCacheOp +impl core::marker::Freeze for aya::programs::perf_event::HwCacheOp +impl core::marker::Send for aya::programs::perf_event::HwCacheOp +impl core::marker::Sync for aya::programs::perf_event::HwCacheOp +impl core::marker::Unpin for aya::programs::perf_event::HwCacheOp +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::HwCacheOp +impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::HwCacheOp +impl core::convert::Into for aya::programs::perf_event::HwCacheOp where U: core::convert::From +pub fn aya::programs::perf_event::HwCacheOp::into(self) -> U +impl core::convert::TryFrom for aya::programs::perf_event::HwCacheOp where U: core::convert::Into +pub type aya::programs::perf_event::HwCacheOp::Error = core::convert::Infallible +pub fn aya::programs::perf_event::HwCacheOp::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::perf_event::HwCacheOp where U: core::convert::TryFrom +pub type aya::programs::perf_event::HwCacheOp::Error = >::Error +pub fn aya::programs::perf_event::HwCacheOp::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::perf_event::HwCacheOp where T: core::clone::Clone +pub type aya::programs::perf_event::HwCacheOp::Owned = T +pub fn aya::programs::perf_event::HwCacheOp::clone_into(&self, target: &mut T) +pub fn aya::programs::perf_event::HwCacheOp::to_owned(&self) -> T +impl core::any::Any for aya::programs::perf_event::HwCacheOp where T: 'static + ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheOp::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::perf_event::HwCacheOp where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheOp::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::perf_event::HwCacheOp where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheOp::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::perf_event::HwCacheOp where T: core::clone::Clone +pub unsafe fn aya::programs::perf_event::HwCacheOp::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::perf_event::HwCacheOp +pub fn aya::programs::perf_event::HwCacheOp::from(t: T) -> T +#[repr(u32)] pub enum aya::programs::perf_event::HwCacheResult +pub aya::programs::perf_event::HwCacheResult::Access = 0 +pub aya::programs::perf_event::HwCacheResult::Miss = 1 +impl core::clone::Clone for aya::programs::perf_event::HwCacheResult +pub fn aya::programs::perf_event::HwCacheResult::clone(&self) -> aya::programs::perf_event::HwCacheResult +impl core::fmt::Debug for aya::programs::perf_event::HwCacheResult +pub fn aya::programs::perf_event::HwCacheResult::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::perf_event::HwCacheResult +impl core::marker::Freeze for aya::programs::perf_event::HwCacheResult +impl core::marker::Send for aya::programs::perf_event::HwCacheResult +impl core::marker::Sync for aya::programs::perf_event::HwCacheResult +impl core::marker::Unpin for aya::programs::perf_event::HwCacheResult +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::HwCacheResult +impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::HwCacheResult +impl core::convert::Into for aya::programs::perf_event::HwCacheResult where U: core::convert::From +pub fn aya::programs::perf_event::HwCacheResult::into(self) -> U +impl core::convert::TryFrom for aya::programs::perf_event::HwCacheResult where U: core::convert::Into +pub type aya::programs::perf_event::HwCacheResult::Error = core::convert::Infallible +pub fn aya::programs::perf_event::HwCacheResult::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::perf_event::HwCacheResult where U: core::convert::TryFrom +pub type aya::programs::perf_event::HwCacheResult::Error = >::Error +pub fn aya::programs::perf_event::HwCacheResult::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::perf_event::HwCacheResult where T: core::clone::Clone +pub type aya::programs::perf_event::HwCacheResult::Owned = T +pub fn aya::programs::perf_event::HwCacheResult::clone_into(&self, target: &mut T) +pub fn aya::programs::perf_event::HwCacheResult::to_owned(&self) -> T +impl core::any::Any for aya::programs::perf_event::HwCacheResult where T: 'static + ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheResult::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::perf_event::HwCacheResult where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheResult::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::perf_event::HwCacheResult where T: ?core::marker::Sized +pub fn aya::programs::perf_event::HwCacheResult::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::perf_event::HwCacheResult where T: core::clone::Clone +pub unsafe fn aya::programs::perf_event::HwCacheResult::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::perf_event::HwCacheResult +pub fn aya::programs::perf_event::HwCacheResult::from(t: T) -> T +pub enum aya::programs::perf_event::PerfEventConfig +pub aya::programs::perf_event::PerfEventConfig::Breakpoint +pub aya::programs::perf_event::PerfEventConfig::Hardware(aya::programs::perf_event::HardwareEvent) +pub aya::programs::perf_event::PerfEventConfig::HwCache +pub aya::programs::perf_event::PerfEventConfig::HwCache::event: aya::programs::perf_event::HwCacheEvent +pub aya::programs::perf_event::PerfEventConfig::HwCache::operation: aya::programs::perf_event::HwCacheOp +pub aya::programs::perf_event::PerfEventConfig::HwCache::result: aya::programs::perf_event::HwCacheResult +pub aya::programs::perf_event::PerfEventConfig::Pmu +pub aya::programs::perf_event::PerfEventConfig::Pmu::config: u64 +pub aya::programs::perf_event::PerfEventConfig::Pmu::pmu_type: u32 +pub aya::programs::perf_event::PerfEventConfig::Raw +pub aya::programs::perf_event::PerfEventConfig::Raw::event_id: u64 +pub aya::programs::perf_event::PerfEventConfig::Software(aya::programs::perf_event::SoftwareEvent) +pub aya::programs::perf_event::PerfEventConfig::TracePoint +pub aya::programs::perf_event::PerfEventConfig::TracePoint::event_id: u64 +impl core::clone::Clone for aya::programs::perf_event::PerfEventConfig +pub fn aya::programs::perf_event::PerfEventConfig::clone(&self) -> aya::programs::perf_event::PerfEventConfig +impl core::fmt::Debug for aya::programs::perf_event::PerfEventConfig +pub fn aya::programs::perf_event::PerfEventConfig::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::perf_event::PerfEventConfig +impl core::marker::Freeze for aya::programs::perf_event::PerfEventConfig +impl core::marker::Send for aya::programs::perf_event::PerfEventConfig +impl core::marker::Sync for aya::programs::perf_event::PerfEventConfig +impl core::marker::Unpin for aya::programs::perf_event::PerfEventConfig +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::PerfEventConfig +impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::PerfEventConfig +impl core::convert::Into for aya::programs::perf_event::PerfEventConfig where U: core::convert::From +pub fn aya::programs::perf_event::PerfEventConfig::into(self) -> U +impl core::convert::TryFrom for aya::programs::perf_event::PerfEventConfig where U: core::convert::Into +pub type aya::programs::perf_event::PerfEventConfig::Error = core::convert::Infallible +pub fn aya::programs::perf_event::PerfEventConfig::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::perf_event::PerfEventConfig where U: core::convert::TryFrom +pub type aya::programs::perf_event::PerfEventConfig::Error = >::Error +pub fn aya::programs::perf_event::PerfEventConfig::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::perf_event::PerfEventConfig where T: core::clone::Clone +pub type aya::programs::perf_event::PerfEventConfig::Owned = T +pub fn aya::programs::perf_event::PerfEventConfig::clone_into(&self, target: &mut T) +pub fn aya::programs::perf_event::PerfEventConfig::to_owned(&self) -> T +impl core::any::Any for aya::programs::perf_event::PerfEventConfig where T: 'static + ?core::marker::Sized +pub fn aya::programs::perf_event::PerfEventConfig::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::perf_event::PerfEventConfig where T: ?core::marker::Sized +pub fn aya::programs::perf_event::PerfEventConfig::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::perf_event::PerfEventConfig where T: ?core::marker::Sized +pub fn aya::programs::perf_event::PerfEventConfig::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::perf_event::PerfEventConfig where T: core::clone::Clone +pub unsafe fn aya::programs::perf_event::PerfEventConfig::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::perf_event::PerfEventConfig +pub fn aya::programs::perf_event::PerfEventConfig::from(t: T) -> T pub enum aya::programs::perf_event::PerfEventScope pub aya::programs::perf_event::PerfEventScope::AllProcessesOneCpu pub aya::programs::perf_event::PerfEventScope::AllProcessesOneCpu::cpu: u32 @@ -5347,45 +5548,6 @@ impl core::clone::CloneToUninit for aya::programs::perf_event::PerfEventScope pub unsafe fn aya::programs::perf_event::PerfEventScope::clone_to_uninit(&self, dest: *mut u8) impl core::convert::From for aya::programs::perf_event::PerfEventScope pub fn aya::programs::perf_event::PerfEventScope::from(t: T) -> T -#[repr(u32)] pub enum aya::programs::perf_event::PerfTypeId -pub aya::programs::perf_event::PerfTypeId::Breakpoint = 5 -pub aya::programs::perf_event::PerfTypeId::Hardware = 0 -pub aya::programs::perf_event::PerfTypeId::HwCache = 3 -pub aya::programs::perf_event::PerfTypeId::Raw = 4 -pub aya::programs::perf_event::PerfTypeId::Software = 1 -pub aya::programs::perf_event::PerfTypeId::TracePoint = 2 -impl core::clone::Clone for aya::programs::perf_event::PerfTypeId -pub fn aya::programs::perf_event::PerfTypeId::clone(&self) -> aya::programs::perf_event::PerfTypeId -impl core::fmt::Debug for aya::programs::perf_event::PerfTypeId -pub fn aya::programs::perf_event::PerfTypeId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result -impl core::marker::Freeze for aya::programs::perf_event::PerfTypeId -impl core::marker::Send for aya::programs::perf_event::PerfTypeId -impl core::marker::Sync for aya::programs::perf_event::PerfTypeId -impl core::marker::Unpin for aya::programs::perf_event::PerfTypeId -impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::PerfTypeId -impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::PerfTypeId -impl core::convert::Into for aya::programs::perf_event::PerfTypeId where U: core::convert::From -pub fn aya::programs::perf_event::PerfTypeId::into(self) -> U -impl core::convert::TryFrom for aya::programs::perf_event::PerfTypeId where U: core::convert::Into -pub type aya::programs::perf_event::PerfTypeId::Error = core::convert::Infallible -pub fn aya::programs::perf_event::PerfTypeId::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya::programs::perf_event::PerfTypeId where U: core::convert::TryFrom -pub type aya::programs::perf_event::PerfTypeId::Error = >::Error -pub fn aya::programs::perf_event::PerfTypeId::try_into(self) -> core::result::Result>::Error> -impl alloc::borrow::ToOwned for aya::programs::perf_event::PerfTypeId where T: core::clone::Clone -pub type aya::programs::perf_event::PerfTypeId::Owned = T -pub fn aya::programs::perf_event::PerfTypeId::clone_into(&self, target: &mut T) -pub fn aya::programs::perf_event::PerfTypeId::to_owned(&self) -> T -impl core::any::Any for aya::programs::perf_event::PerfTypeId where T: 'static + ?core::marker::Sized -pub fn aya::programs::perf_event::PerfTypeId::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya::programs::perf_event::PerfTypeId where T: ?core::marker::Sized -pub fn aya::programs::perf_event::PerfTypeId::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya::programs::perf_event::PerfTypeId where T: ?core::marker::Sized -pub fn aya::programs::perf_event::PerfTypeId::borrow_mut(&mut self) -> &mut T -impl core::clone::CloneToUninit for aya::programs::perf_event::PerfTypeId where T: core::clone::Clone -pub unsafe fn aya::programs::perf_event::PerfTypeId::clone_to_uninit(&self, dest: *mut u8) -impl core::convert::From for aya::programs::perf_event::PerfTypeId -pub fn aya::programs::perf_event::PerfTypeId::from(t: T) -> T pub enum aya::programs::perf_event::SamplePolicy pub aya::programs::perf_event::SamplePolicy::Frequency(u64) pub aya::programs::perf_event::SamplePolicy::Period(u64) @@ -5421,10 +5583,56 @@ impl core::clone::CloneToUninit for aya::programs::perf_event::SamplePolicy w pub unsafe fn aya::programs::perf_event::SamplePolicy::clone_to_uninit(&self, dest: *mut u8) impl core::convert::From for aya::programs::perf_event::SamplePolicy pub fn aya::programs::perf_event::SamplePolicy::from(t: T) -> T +#[repr(u32)] pub enum aya::programs::perf_event::SoftwareEvent +pub aya::programs::perf_event::SoftwareEvent::AlignmentFaults = 7 +pub aya::programs::perf_event::SoftwareEvent::BpfOutput = 10 +pub aya::programs::perf_event::SoftwareEvent::CgroupSwitches = 11 +pub aya::programs::perf_event::SoftwareEvent::ContextSwitches = 3 +pub aya::programs::perf_event::SoftwareEvent::CpuClock = 0 +pub aya::programs::perf_event::SoftwareEvent::CpuMigrations = 4 +pub aya::programs::perf_event::SoftwareEvent::Dummy = 9 +pub aya::programs::perf_event::SoftwareEvent::EmulationFaults = 8 +pub aya::programs::perf_event::SoftwareEvent::PageFaults = 2 +pub aya::programs::perf_event::SoftwareEvent::PageFaultsMaj = 6 +pub aya::programs::perf_event::SoftwareEvent::PageFaultsMin = 5 +pub aya::programs::perf_event::SoftwareEvent::TaskClock = 1 +impl core::clone::Clone for aya::programs::perf_event::SoftwareEvent +pub fn aya::programs::perf_event::SoftwareEvent::clone(&self) -> aya::programs::perf_event::SoftwareEvent +impl core::fmt::Debug for aya::programs::perf_event::SoftwareEvent +pub fn aya::programs::perf_event::SoftwareEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::perf_event::SoftwareEvent +impl core::marker::Freeze for aya::programs::perf_event::SoftwareEvent +impl core::marker::Send for aya::programs::perf_event::SoftwareEvent +impl core::marker::Sync for aya::programs::perf_event::SoftwareEvent +impl core::marker::Unpin for aya::programs::perf_event::SoftwareEvent +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::SoftwareEvent +impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::SoftwareEvent +impl core::convert::Into for aya::programs::perf_event::SoftwareEvent where U: core::convert::From +pub fn aya::programs::perf_event::SoftwareEvent::into(self) -> U +impl core::convert::TryFrom for aya::programs::perf_event::SoftwareEvent where U: core::convert::Into +pub type aya::programs::perf_event::SoftwareEvent::Error = core::convert::Infallible +pub fn aya::programs::perf_event::SoftwareEvent::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::perf_event::SoftwareEvent where U: core::convert::TryFrom +pub type aya::programs::perf_event::SoftwareEvent::Error = >::Error +pub fn aya::programs::perf_event::SoftwareEvent::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::perf_event::SoftwareEvent where T: core::clone::Clone +pub type aya::programs::perf_event::SoftwareEvent::Owned = T +pub fn aya::programs::perf_event::SoftwareEvent::clone_into(&self, target: &mut T) +pub fn aya::programs::perf_event::SoftwareEvent::to_owned(&self) -> T +impl core::any::Any for aya::programs::perf_event::SoftwareEvent where T: 'static + ?core::marker::Sized +pub fn aya::programs::perf_event::SoftwareEvent::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::perf_event::SoftwareEvent where T: ?core::marker::Sized +pub fn aya::programs::perf_event::SoftwareEvent::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::perf_event::SoftwareEvent where T: ?core::marker::Sized +pub fn aya::programs::perf_event::SoftwareEvent::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::perf_event::SoftwareEvent where T: core::clone::Clone +pub unsafe fn aya::programs::perf_event::SoftwareEvent::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::perf_event::SoftwareEvent +pub fn aya::programs::perf_event::SoftwareEvent::from(t: T) -> T pub struct aya::programs::perf_event::PerfEvent impl aya::programs::perf_event::PerfEvent pub const aya::programs::perf_event::PerfEvent::PROGRAM_TYPE: aya::programs::ProgramType -pub fn aya::programs::perf_event::PerfEvent::attach(&mut self, perf_type: aya::programs::perf_event::PerfTypeId, config: u64, scope: aya::programs::perf_event::PerfEventScope, sample_policy: aya::programs::perf_event::SamplePolicy, inherit: bool) -> core::result::Result +pub fn aya::programs::perf_event::PerfEvent::attach(&mut self, perf_type: aya::programs::perf_event::PerfEventConfig, scope: aya::programs::perf_event::PerfEventScope, sample_policy: aya::programs::perf_event::SamplePolicy, inherit: bool) -> core::result::Result pub fn aya::programs::perf_event::PerfEvent::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::detach(&mut self, link_id: aya::programs::perf_event::PerfEventLinkId) -> core::result::Result<(), aya::programs::ProgramError> @@ -7739,45 +7947,6 @@ impl core::clone::CloneToUninit for aya::programs::perf_event::PerfEventScope pub unsafe fn aya::programs::perf_event::PerfEventScope::clone_to_uninit(&self, dest: *mut u8) impl core::convert::From for aya::programs::perf_event::PerfEventScope pub fn aya::programs::perf_event::PerfEventScope::from(t: T) -> T -#[repr(u32)] pub enum aya::programs::PerfTypeId -pub aya::programs::PerfTypeId::Breakpoint = 5 -pub aya::programs::PerfTypeId::Hardware = 0 -pub aya::programs::PerfTypeId::HwCache = 3 -pub aya::programs::PerfTypeId::Raw = 4 -pub aya::programs::PerfTypeId::Software = 1 -pub aya::programs::PerfTypeId::TracePoint = 2 -impl core::clone::Clone for aya::programs::perf_event::PerfTypeId -pub fn aya::programs::perf_event::PerfTypeId::clone(&self) -> aya::programs::perf_event::PerfTypeId -impl core::fmt::Debug for aya::programs::perf_event::PerfTypeId -pub fn aya::programs::perf_event::PerfTypeId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result -impl core::marker::Freeze for aya::programs::perf_event::PerfTypeId -impl core::marker::Send for aya::programs::perf_event::PerfTypeId -impl core::marker::Sync for aya::programs::perf_event::PerfTypeId -impl core::marker::Unpin for aya::programs::perf_event::PerfTypeId -impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::PerfTypeId -impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::PerfTypeId -impl core::convert::Into for aya::programs::perf_event::PerfTypeId where U: core::convert::From -pub fn aya::programs::perf_event::PerfTypeId::into(self) -> U -impl core::convert::TryFrom for aya::programs::perf_event::PerfTypeId where U: core::convert::Into -pub type aya::programs::perf_event::PerfTypeId::Error = core::convert::Infallible -pub fn aya::programs::perf_event::PerfTypeId::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya::programs::perf_event::PerfTypeId where U: core::convert::TryFrom -pub type aya::programs::perf_event::PerfTypeId::Error = >::Error -pub fn aya::programs::perf_event::PerfTypeId::try_into(self) -> core::result::Result>::Error> -impl alloc::borrow::ToOwned for aya::programs::perf_event::PerfTypeId where T: core::clone::Clone -pub type aya::programs::perf_event::PerfTypeId::Owned = T -pub fn aya::programs::perf_event::PerfTypeId::clone_into(&self, target: &mut T) -pub fn aya::programs::perf_event::PerfTypeId::to_owned(&self) -> T -impl core::any::Any for aya::programs::perf_event::PerfTypeId where T: 'static + ?core::marker::Sized -pub fn aya::programs::perf_event::PerfTypeId::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya::programs::perf_event::PerfTypeId where T: ?core::marker::Sized -pub fn aya::programs::perf_event::PerfTypeId::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya::programs::perf_event::PerfTypeId where T: ?core::marker::Sized -pub fn aya::programs::perf_event::PerfTypeId::borrow_mut(&mut self) -> &mut T -impl core::clone::CloneToUninit for aya::programs::perf_event::PerfTypeId where T: core::clone::Clone -pub unsafe fn aya::programs::perf_event::PerfTypeId::clone_to_uninit(&self, dest: *mut u8) -impl core::convert::From for aya::programs::perf_event::PerfTypeId -pub fn aya::programs::perf_event::PerfTypeId::from(t: T) -> T pub enum aya::programs::ProbeKind pub aya::programs::ProbeKind::KProbe pub aya::programs::ProbeKind::KRetProbe @@ -9375,7 +9544,7 @@ pub fn aya::programs::lsm_cgroup::LsmCgroup::from(t: T) -> T pub struct aya::programs::PerfEvent impl aya::programs::perf_event::PerfEvent pub const aya::programs::perf_event::PerfEvent::PROGRAM_TYPE: aya::programs::ProgramType -pub fn aya::programs::perf_event::PerfEvent::attach(&mut self, perf_type: aya::programs::perf_event::PerfTypeId, config: u64, scope: aya::programs::perf_event::PerfEventScope, sample_policy: aya::programs::perf_event::SamplePolicy, inherit: bool) -> core::result::Result +pub fn aya::programs::perf_event::PerfEvent::attach(&mut self, perf_type: aya::programs::perf_event::PerfEventConfig, scope: aya::programs::perf_event::PerfEventScope, sample_policy: aya::programs::perf_event::SamplePolicy, inherit: bool) -> core::result::Result pub fn aya::programs::perf_event::PerfEvent::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::detach(&mut self, link_id: aya::programs::perf_event::PerfEventLinkId) -> core::result::Result<(), aya::programs::ProgramError>