diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 53628eb1..7dd3e36a 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -6,9 +6,12 @@ use std::{ path::{Path, PathBuf}, }; -use aya_obj::generated::{ - BPF_F_AFTER, BPF_F_ALLOW_MULTI, BPF_F_ALLOW_OVERRIDE, BPF_F_BEFORE, BPF_F_ID, BPF_F_LINK, - BPF_F_REPLACE, bpf_attach_type, +use aya_obj::{ + InvalidTypeBinding, + generated::{ + BPF_F_AFTER, BPF_F_ALLOW_MULTI, BPF_F_ALLOW_OVERRIDE, BPF_F_BEFORE, BPF_F_ID, BPF_F_LINK, + BPF_F_REPLACE, bpf_attach_type, bpf_link_info, bpf_link_type, + }, }; use hashbrown::hash_set::{Entry, HashSet}; use thiserror::Error; @@ -16,7 +19,10 @@ use thiserror::Error; use crate::{ pin::PinError, programs::{MultiProgLink, MultiProgram, ProgramError, ProgramFd, ProgramId}, - sys::{SyscallError, bpf_get_object, bpf_pin_object, bpf_prog_attach, bpf_prog_detach}, + sys::{ + SyscallError, bpf_get_object, bpf_link_get_info_by_fd, bpf_pin_object, bpf_prog_attach, + bpf_prog_detach, + }, }; /// A Link. @@ -105,6 +111,108 @@ impl Drop for Links { } } +/// Provides metadata information about an eBPF attachment. +#[doc(alias = "bpf_link_info")] +pub struct LinkInfo(bpf_link_info); + +impl LinkInfo { + pub(crate) fn new_from_fd(fd: BorrowedFd<'_>) -> Result { + let info = bpf_link_get_info_by_fd(fd)?; + Ok(Self(info)) + } + + /// Returns the link ID. + pub fn id(&self) -> u32 { + self.0.id + } + + /// Returns the program ID. + pub fn program_id(&self) -> u32 { + self.0.prog_id + } + + /// Returns the type of the link. + pub fn link_type(&self) -> Result { + bpf_link_type::try_from(self.0.type_) + .map_err(|InvalidTypeBinding { value }| LinkError::UnknownLinkType(value)) + .and_then(LinkType::try_from) + } +} + +/// The type of eBPF link. +#[non_exhaustive] +#[doc(alias = "bpf_link_type")] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum LinkType { + /// An unspecified link type. + #[doc(alias = "BPF_LINK_TYPE_UNSPEC")] + Unspecified = bpf_link_type::BPF_LINK_TYPE_UNSPEC as isize, + /// A Raw Tracepoint link type. + #[doc(alias = "BPF_LINK_TYPE_RAW_TRACEPOINT")] + RawTracePoint = bpf_link_type::BPF_LINK_TYPE_RAW_TRACEPOINT as isize, + /// A Tracing link type. + #[doc(alias = "BPF_LINK_TYPE_TRACING")] + Tracing = bpf_link_type::BPF_LINK_TYPE_TRACING as isize, + /// A Cgroup link type. + #[doc(alias = "BPF_LINK_TYPE_CGROUP")] + Cgroup = bpf_link_type::BPF_LINK_TYPE_CGROUP as isize, + /// An Iterator link type. + #[doc(alias = "BPF_LINK_TYPE_ITER")] + Iter = bpf_link_type::BPF_LINK_TYPE_ITER as isize, + /// A Network Namespace link type. + #[doc(alias = "BPF_LINK_TYPE_NETNS")] + Netns = bpf_link_type::BPF_LINK_TYPE_NETNS as isize, + /// An XDP link type. + #[doc(alias = "BPF_LINK_TYPE_XDP")] + Xdp = bpf_link_type::BPF_LINK_TYPE_XDP as isize, + /// A Perf Event link type. + #[doc(alias = "BPF_LINK_TYPE_PERF_EVENT")] + PerfEvent = bpf_link_type::BPF_LINK_TYPE_PERF_EVENT as isize, + /// A KProbe Multi link type. + #[doc(alias = "BPF_LINK_TYPE_KPROBE_MULTI")] + KProbeMulti = bpf_link_type::BPF_LINK_TYPE_KPROBE_MULTI as isize, + /// A StructOps link type. + #[doc(alias = "BPF_LINK_TYPE_STRUCT_OPS")] + StructOps = bpf_link_type::BPF_LINK_TYPE_STRUCT_OPS as isize, + /// A Netfilter link type. + #[doc(alias = "BPF_LINK_TYPE_NETFILTER")] + Netfilter = bpf_link_type::BPF_LINK_TYPE_NETFILTER as isize, + /// A Tcx link type. + #[doc(alias = "BPF_LINK_TYPE_TCX")] + Tcx = bpf_link_type::BPF_LINK_TYPE_TCX as isize, + /// A Uprobe Multi link type. + #[doc(alias = "BPF_LINK_TYPE_UPROBE_MULTI")] + UProbeMulti = bpf_link_type::BPF_LINK_TYPE_UPROBE_MULTI as isize, + /// A Netkit link type. + #[doc(alias = "BPF_LINK_TYPE_NETKIT")] + Netkit = bpf_link_type::BPF_LINK_TYPE_NETKIT as isize, +} + +impl TryFrom for LinkType { + type Error = LinkError; + + fn try_from(link_type: bpf_link_type) -> Result { + use bpf_link_type::*; + match link_type { + BPF_LINK_TYPE_UNSPEC => Ok(Self::Unspecified), + BPF_LINK_TYPE_RAW_TRACEPOINT => Ok(Self::RawTracePoint), + BPF_LINK_TYPE_TRACING => Ok(Self::Tracing), + BPF_LINK_TYPE_CGROUP => Ok(Self::Cgroup), + BPF_LINK_TYPE_ITER => Ok(Self::Iter), + BPF_LINK_TYPE_NETNS => Ok(Self::Netns), + BPF_LINK_TYPE_XDP => Ok(Self::Xdp), + BPF_LINK_TYPE_PERF_EVENT => Ok(Self::PerfEvent), + BPF_LINK_TYPE_KPROBE_MULTI => Ok(Self::KProbeMulti), + BPF_LINK_TYPE_STRUCT_OPS => Ok(Self::StructOps), + BPF_LINK_TYPE_NETFILTER => Ok(Self::Netfilter), + BPF_LINK_TYPE_TCX => Ok(Self::Tcx), + BPF_LINK_TYPE_UPROBE_MULTI => Ok(Self::UProbeMulti), + BPF_LINK_TYPE_NETKIT => Ok(Self::Netkit), + __MAX_BPF_LINK_TYPE => Err(LinkError::UnknownLinkType(link_type as u32)), + } + } +} + /// The identifier of an `FdLink`. #[derive(Debug, Hash, Eq, PartialEq)] pub struct FdLinkId(pub(crate) RawFd); @@ -189,6 +297,11 @@ impl FdLink { })?; Ok(PinnedLink::new(path.into(), self)) } + + /// Returns the kernel information about this link. + pub fn info(&self) -> Result { + LinkInfo::new_from_fd(self.fd.as_fd()) + } } impl Link for FdLink { @@ -449,6 +562,12 @@ pub enum LinkError { /// Invalid link. #[error("Invalid link")] InvalidLink, + + /// The kernel type of this link is not understood by Aya. + /// Please open an issue on GitHub if you encounter this error. + #[error("unknown link type {0}")] + UnknownLinkType(u32), + /// Syscall failed. #[error(transparent)] SyscallError(#[from] SyscallError), diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index c975c747..fa1e41ec 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -83,7 +83,7 @@ use std::{ use aya_obj::{ VerifierLog, btf::BtfError, - generated::{bpf_attach_type, bpf_link_info, bpf_prog_info, bpf_prog_type}, + generated::{bpf_attach_type, bpf_prog_info, bpf_prog_type}, programs::XdpAttachType, }; use info::impl_info; @@ -130,9 +130,8 @@ use crate::{ programs::{links::*, perf_attach::*}, sys::{ EbpfLoadProgramAttrs, NetlinkError, ProgQueryTarget, SyscallError, bpf_btf_get_fd_by_id, - bpf_get_object, bpf_link_get_fd_by_id, bpf_link_get_info_by_fd, bpf_load_program, - bpf_pin_object, bpf_prog_get_fd_by_id, bpf_prog_query, iter_link_ids, - retry_with_verifier_logs, + bpf_get_object, bpf_link_get_fd_by_id, bpf_load_program, bpf_pin_object, + bpf_prog_get_fd_by_id, bpf_prog_query, iter_link_ids, retry_with_verifier_logs, }, util::KernelVersion, }; @@ -1192,10 +1191,29 @@ impl_info!( Iter, ); -// TODO(https://github.com/aya-rs/aya/issues/645): this API is currently used in tests. Stabilize -// and remove doc(hidden). -#[doc(hidden)] -pub fn loaded_links() -> impl Iterator> { +/// Returns an iterator over all loaded links. +/// +/// This function is useful for debugging and inspecting the state of +/// loaded links in the kernel. It can be used to check which links are +/// currently active and to gather information about them. +/// +/// # Errors +/// +/// The returned iterator may yield an error if link information cannot be +/// retrieved from the kernel. +/// +/// # Example +/// +/// ```no_run +/// use aya::programs::loaded_links; +/// +/// for info in loaded_links() { +/// if let Ok(info) = info { +/// println!("Loaded link: {}", info.id()); +/// } +/// } +/// ``` +pub fn loaded_links() -> impl Iterator> { iter_link_ids() .map(|id| { let id = id?; @@ -1203,7 +1221,6 @@ pub fn loaded_links() -> impl Iterator T pub enum aya::programs::links::LinkError pub aya::programs::links::LinkError::InvalidLink pub aya::programs::links::LinkError::SyscallError(aya::sys::SyscallError) +pub aya::programs::links::LinkError::UnknownLinkType(u32) impl core::convert::From for aya::programs::links::LinkError pub fn aya::programs::links::LinkError::from(source: aya::sys::SyscallError) -> Self impl core::error::Error for aya::programs::links::LinkError @@ -4304,8 +4305,63 @@ impl core::borrow::BorrowMut for aya::programs::links::LinkError where T: pub fn aya::programs::links::LinkError::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::links::LinkError pub fn aya::programs::links::LinkError::from(t: T) -> T +#[non_exhaustive] pub enum aya::programs::links::LinkType +pub aya::programs::links::LinkType::Cgroup = 3 +pub aya::programs::links::LinkType::Iter = 4 +pub aya::programs::links::LinkType::KProbeMulti = 8 +pub aya::programs::links::LinkType::Netfilter = 10 +pub aya::programs::links::LinkType::Netkit = 13 +pub aya::programs::links::LinkType::Netns = 5 +pub aya::programs::links::LinkType::PerfEvent = 7 +pub aya::programs::links::LinkType::RawTracePoint = 1 +pub aya::programs::links::LinkType::StructOps = 9 +pub aya::programs::links::LinkType::Tcx = 11 +pub aya::programs::links::LinkType::Tracing = 2 +pub aya::programs::links::LinkType::UProbeMulti = 12 +pub aya::programs::links::LinkType::Unspecified = 0 +pub aya::programs::links::LinkType::Xdp = 6 +impl core::clone::Clone for aya::programs::links::LinkType +pub fn aya::programs::links::LinkType::clone(&self) -> aya::programs::links::LinkType +impl core::cmp::PartialEq for aya::programs::links::LinkType +pub fn aya::programs::links::LinkType::eq(&self, other: &aya::programs::links::LinkType) -> bool +impl core::convert::TryFrom for aya::programs::links::LinkType +pub type aya::programs::links::LinkType::Error = aya::programs::links::LinkError +pub fn aya::programs::links::LinkType::try_from(link_type: aya_obj::generated::linux_bindings_x86_64::bpf_link_type) -> core::result::Result +impl core::fmt::Debug for aya::programs::links::LinkType +pub fn aya::programs::links::LinkType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::links::LinkType +impl core::marker::StructuralPartialEq for aya::programs::links::LinkType +impl core::marker::Freeze for aya::programs::links::LinkType +impl core::marker::Send for aya::programs::links::LinkType +impl core::marker::Sync for aya::programs::links::LinkType +impl core::marker::Unpin for aya::programs::links::LinkType +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::links::LinkType +impl core::panic::unwind_safe::UnwindSafe for aya::programs::links::LinkType +impl core::convert::Into for aya::programs::links::LinkType where U: core::convert::From +pub fn aya::programs::links::LinkType::into(self) -> U +impl core::convert::TryFrom for aya::programs::links::LinkType where U: core::convert::Into +pub type aya::programs::links::LinkType::Error = core::convert::Infallible +pub fn aya::programs::links::LinkType::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::links::LinkType where U: core::convert::TryFrom +pub type aya::programs::links::LinkType::Error = >::Error +pub fn aya::programs::links::LinkType::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::links::LinkType where T: core::clone::Clone +pub type aya::programs::links::LinkType::Owned = T +pub fn aya::programs::links::LinkType::clone_into(&self, target: &mut T) +pub fn aya::programs::links::LinkType::to_owned(&self) -> T +impl core::any::Any for aya::programs::links::LinkType where T: 'static + ?core::marker::Sized +pub fn aya::programs::links::LinkType::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::links::LinkType where T: ?core::marker::Sized +pub fn aya::programs::links::LinkType::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::links::LinkType where T: ?core::marker::Sized +pub fn aya::programs::links::LinkType::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::links::LinkType where T: core::clone::Clone +pub unsafe fn aya::programs::links::LinkType::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::links::LinkType +pub fn aya::programs::links::LinkType::from(t: T) -> T pub struct aya::programs::links::FdLink impl aya::programs::links::FdLink +pub fn aya::programs::links::FdLink::info(&self) -> core::result::Result pub fn aya::programs::links::FdLink::pin>(self, path: P) -> core::result::Result impl aya::programs::links::Link for aya::programs::links::FdLink pub type aya::programs::links::FdLink::Id = aya::programs::links::FdLinkId @@ -4454,6 +4510,33 @@ impl core::borrow::BorrowMut for aya::programs::links::FdLinkId where T: ? pub fn aya::programs::links::FdLinkId::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::links::FdLinkId pub fn aya::programs::links::FdLinkId::from(t: T) -> T +pub struct aya::programs::links::LinkInfo(_) +impl aya::programs::links::LinkInfo +pub fn aya::programs::links::LinkInfo::id(&self) -> u32 +pub fn aya::programs::links::LinkInfo::link_type(&self) -> core::result::Result +pub fn aya::programs::links::LinkInfo::program_id(&self) -> u32 +impl core::marker::Freeze for aya::programs::links::LinkInfo +impl core::marker::Send for aya::programs::links::LinkInfo +impl core::marker::Sync for aya::programs::links::LinkInfo +impl core::marker::Unpin for aya::programs::links::LinkInfo +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::links::LinkInfo +impl core::panic::unwind_safe::UnwindSafe for aya::programs::links::LinkInfo +impl core::convert::Into for aya::programs::links::LinkInfo where U: core::convert::From +pub fn aya::programs::links::LinkInfo::into(self) -> U +impl core::convert::TryFrom for aya::programs::links::LinkInfo where U: core::convert::Into +pub type aya::programs::links::LinkInfo::Error = core::convert::Infallible +pub fn aya::programs::links::LinkInfo::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::links::LinkInfo where U: core::convert::TryFrom +pub type aya::programs::links::LinkInfo::Error = >::Error +pub fn aya::programs::links::LinkInfo::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::programs::links::LinkInfo where T: 'static + ?core::marker::Sized +pub fn aya::programs::links::LinkInfo::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::links::LinkInfo where T: ?core::marker::Sized +pub fn aya::programs::links::LinkInfo::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::links::LinkInfo where T: ?core::marker::Sized +pub fn aya::programs::links::LinkInfo::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::programs::links::LinkInfo +pub fn aya::programs::links::LinkInfo::from(t: T) -> T pub struct aya::programs::links::LinkOrder impl aya::programs::links::LinkOrder pub fn aya::programs::links::LinkOrder::after_link(link: &L) -> core::result::Result @@ -9995,6 +10078,7 @@ pub trait aya::programs::MultiProgram pub fn aya::programs::MultiProgram::fd(&self) -> core::result::Result, aya::programs::ProgramError> impl aya::programs::MultiProgram for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result, aya::programs::ProgramError> +pub fn aya::programs::loaded_links() -> impl core::iter::traits::iterator::Iterator> pub fn aya::programs::loaded_programs() -> impl core::iter::traits::iterator::Iterator> pub mod aya::sys #[non_exhaustive] pub enum aya::sys::Stats