Merge pull request #1262 from dave-tucker/stabilize-links

feat(aya): Make LinkInfo and loaded_links public
reviewable/pr1264/r7^2
Dave Tucker 1 week ago committed by GitHub
commit f74a157907
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -6,9 +6,12 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use aya_obj::generated::{ 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_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_F_REPLACE, bpf_attach_type, bpf_link_info, bpf_link_type,
},
}; };
use hashbrown::hash_set::{Entry, HashSet}; use hashbrown::hash_set::{Entry, HashSet};
use thiserror::Error; use thiserror::Error;
@ -16,7 +19,10 @@ use thiserror::Error;
use crate::{ use crate::{
pin::PinError, pin::PinError,
programs::{MultiProgLink, MultiProgram, ProgramError, ProgramFd, ProgramId}, 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. /// A Link.
@ -105,6 +111,108 @@ impl<T: Link> Drop for Links<T> {
} }
} }
/// 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<Self, LinkError> {
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<LinkType, LinkError> {
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<bpf_link_type> for LinkType {
type Error = LinkError;
fn try_from(link_type: bpf_link_type) -> Result<Self, Self::Error> {
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`. /// The identifier of an `FdLink`.
#[derive(Debug, Hash, Eq, PartialEq)] #[derive(Debug, Hash, Eq, PartialEq)]
pub struct FdLinkId(pub(crate) RawFd); pub struct FdLinkId(pub(crate) RawFd);
@ -189,6 +297,11 @@ impl FdLink {
})?; })?;
Ok(PinnedLink::new(path.into(), self)) Ok(PinnedLink::new(path.into(), self))
} }
/// Returns the kernel information about this link.
pub fn info(&self) -> Result<LinkInfo, LinkError> {
LinkInfo::new_from_fd(self.fd.as_fd())
}
} }
impl Link for FdLink { impl Link for FdLink {
@ -449,6 +562,12 @@ pub enum LinkError {
/// Invalid link. /// Invalid link.
#[error("Invalid link")] #[error("Invalid link")]
InvalidLink, 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. /// Syscall failed.
#[error(transparent)] #[error(transparent)]
SyscallError(#[from] SyscallError), SyscallError(#[from] SyscallError),

@ -83,7 +83,7 @@ use std::{
use aya_obj::{ use aya_obj::{
VerifierLog, VerifierLog,
btf::BtfError, 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, programs::XdpAttachType,
}; };
use info::impl_info; use info::impl_info;
@ -130,9 +130,8 @@ use crate::{
programs::{links::*, perf_attach::*}, programs::{links::*, perf_attach::*},
sys::{ sys::{
EbpfLoadProgramAttrs, NetlinkError, ProgQueryTarget, SyscallError, bpf_btf_get_fd_by_id, 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_get_object, bpf_link_get_fd_by_id, bpf_load_program, bpf_pin_object,
bpf_pin_object, bpf_prog_get_fd_by_id, bpf_prog_query, iter_link_ids, bpf_prog_get_fd_by_id, bpf_prog_query, iter_link_ids, retry_with_verifier_logs,
retry_with_verifier_logs,
}, },
util::KernelVersion, util::KernelVersion,
}; };
@ -1192,10 +1191,29 @@ impl_info!(
Iter, Iter,
); );
// TODO(https://github.com/aya-rs/aya/issues/645): this API is currently used in tests. Stabilize /// Returns an iterator over all loaded links.
// and remove doc(hidden). ///
#[doc(hidden)] /// This function is useful for debugging and inspecting the state of
pub fn loaded_links() -> impl Iterator<Item = Result<bpf_link_info, ProgramError>> { /// 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<Item = Result<LinkInfo, LinkError>> {
iter_link_ids() iter_link_ids()
.map(|id| { .map(|id| {
let id = id?; let id = id?;
@ -1203,7 +1221,6 @@ pub fn loaded_links() -> impl Iterator<Item = Result<bpf_link_info, ProgramError
}) })
.map(|fd| { .map(|fd| {
let fd = fd?; let fd = fd?;
bpf_link_get_info_by_fd(fd.as_fd()) LinkInfo::new_from_fd(fd.as_fd())
}) })
.map(|result| result.map_err(Into::into))
} }

@ -160,7 +160,7 @@ fn assert_loaded_and_linked(name: &str) {
// program in the middle of a `loaded_programs()` call. // program in the middle of a `loaded_programs()` call.
loaded_links() loaded_links()
.filter_map(|link| link.ok()) .filter_map(|link| link.ok())
.find_map(|link| (link.prog_id == prog_id).then_some(link.id)) .find_map(|link| (link.program_id() == prog_id).then_some(link.id()))
}); });
assert!( assert!(
poll_loaded_link_id poll_loaded_link_id

@ -4272,6 +4272,7 @@ pub fn aya::programs::links::CgroupAttachMode::from(t: T) -> T
pub enum aya::programs::links::LinkError pub enum aya::programs::links::LinkError
pub aya::programs::links::LinkError::InvalidLink pub aya::programs::links::LinkError::InvalidLink
pub aya::programs::links::LinkError::SyscallError(aya::sys::SyscallError) pub aya::programs::links::LinkError::SyscallError(aya::sys::SyscallError)
pub aya::programs::links::LinkError::UnknownLinkType(u32)
impl core::convert::From<aya::sys::SyscallError> for aya::programs::links::LinkError impl core::convert::From<aya::sys::SyscallError> for aya::programs::links::LinkError
pub fn aya::programs::links::LinkError::from(source: aya::sys::SyscallError) -> Self pub fn aya::programs::links::LinkError::from(source: aya::sys::SyscallError) -> Self
impl core::error::Error for aya::programs::links::LinkError impl core::error::Error for aya::programs::links::LinkError
@ -4304,8 +4305,63 @@ impl<T> core::borrow::BorrowMut<T> for aya::programs::links::LinkError where T:
pub fn aya::programs::links::LinkError::borrow_mut(&mut self) -> &mut T pub fn aya::programs::links::LinkError::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya::programs::links::LinkError impl<T> core::convert::From<T> for aya::programs::links::LinkError
pub fn aya::programs::links::LinkError::from(t: T) -> T 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<aya_obj::generated::linux_bindings_x86_64::bpf_link_type> 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<Self, Self::Error>
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<T, U> core::convert::Into<U> for aya::programs::links::LinkType where U: core::convert::From<T>
pub fn aya::programs::links::LinkType::into(self) -> U
impl<T, U> core::convert::TryFrom<U> for aya::programs::links::LinkType where U: core::convert::Into<T>
pub type aya::programs::links::LinkType::Error = core::convert::Infallible
pub fn aya::programs::links::LinkType::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
impl<T, U> core::convert::TryInto<U> for aya::programs::links::LinkType where U: core::convert::TryFrom<T>
pub type aya::programs::links::LinkType::Error = <U as core::convert::TryFrom<T>>::Error
pub fn aya::programs::links::LinkType::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
impl<T> 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<T> 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<T> core::borrow::Borrow<T> for aya::programs::links::LinkType where T: ?core::marker::Sized
pub fn aya::programs::links::LinkType::borrow(&self) -> &T
impl<T> core::borrow::BorrowMut<T> for aya::programs::links::LinkType where T: ?core::marker::Sized
pub fn aya::programs::links::LinkType::borrow_mut(&mut self) -> &mut T
impl<T> 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<T> core::convert::From<T> for aya::programs::links::LinkType
pub fn aya::programs::links::LinkType::from(t: T) -> T
pub struct aya::programs::links::FdLink pub struct aya::programs::links::FdLink
impl aya::programs::links::FdLink impl aya::programs::links::FdLink
pub fn aya::programs::links::FdLink::info(&self) -> core::result::Result<aya::programs::links::LinkInfo, aya::programs::links::LinkError>
pub fn aya::programs::links::FdLink::pin<P: core::convert::AsRef<std::path::Path>>(self, path: P) -> core::result::Result<aya::programs::links::PinnedLink, aya::pin::PinError> pub fn aya::programs::links::FdLink::pin<P: core::convert::AsRef<std::path::Path>>(self, path: P) -> core::result::Result<aya::programs::links::PinnedLink, aya::pin::PinError>
impl aya::programs::links::Link for aya::programs::links::FdLink impl aya::programs::links::Link for aya::programs::links::FdLink
pub type aya::programs::links::FdLink::Id = aya::programs::links::FdLinkId pub type aya::programs::links::FdLink::Id = aya::programs::links::FdLinkId
@ -4454,6 +4510,33 @@ impl<T> core::borrow::BorrowMut<T> for aya::programs::links::FdLinkId where T: ?
pub fn aya::programs::links::FdLinkId::borrow_mut(&mut self) -> &mut T pub fn aya::programs::links::FdLinkId::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya::programs::links::FdLinkId impl<T> core::convert::From<T> for aya::programs::links::FdLinkId
pub fn aya::programs::links::FdLinkId::from(t: T) -> T 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<aya::programs::links::LinkType, aya::programs::links::LinkError>
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<T, U> core::convert::Into<U> for aya::programs::links::LinkInfo where U: core::convert::From<T>
pub fn aya::programs::links::LinkInfo::into(self) -> U
impl<T, U> core::convert::TryFrom<U> for aya::programs::links::LinkInfo where U: core::convert::Into<T>
pub type aya::programs::links::LinkInfo::Error = core::convert::Infallible
pub fn aya::programs::links::LinkInfo::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
impl<T, U> core::convert::TryInto<U> for aya::programs::links::LinkInfo where U: core::convert::TryFrom<T>
pub type aya::programs::links::LinkInfo::Error = <U as core::convert::TryFrom<T>>::Error
pub fn aya::programs::links::LinkInfo::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
impl<T> 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<T> core::borrow::Borrow<T> for aya::programs::links::LinkInfo where T: ?core::marker::Sized
pub fn aya::programs::links::LinkInfo::borrow(&self) -> &T
impl<T> core::borrow::BorrowMut<T> for aya::programs::links::LinkInfo where T: ?core::marker::Sized
pub fn aya::programs::links::LinkInfo::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya::programs::links::LinkInfo
pub fn aya::programs::links::LinkInfo::from(t: T) -> T
pub struct aya::programs::links::LinkOrder pub struct aya::programs::links::LinkOrder
impl aya::programs::links::LinkOrder impl aya::programs::links::LinkOrder
pub fn aya::programs::links::LinkOrder::after_link<L: aya::programs::MultiProgLink>(link: &L) -> core::result::Result<Self, aya::programs::links::LinkError> pub fn aya::programs::links::LinkOrder::after_link<L: aya::programs::MultiProgLink>(link: &L) -> core::result::Result<Self, aya::programs::links::LinkError>
@ -9995,6 +10078,7 @@ pub trait aya::programs::MultiProgram
pub fn aya::programs::MultiProgram::fd(&self) -> core::result::Result<std::os::fd::owned::BorrowedFd<'_>, aya::programs::ProgramError> pub fn aya::programs::MultiProgram::fd(&self) -> core::result::Result<std::os::fd::owned::BorrowedFd<'_>, aya::programs::ProgramError>
impl aya::programs::MultiProgram for aya::programs::tc::SchedClassifier impl aya::programs::MultiProgram for aya::programs::tc::SchedClassifier
pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<std::os::fd::owned::BorrowedFd<'_>, aya::programs::ProgramError> pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<std::os::fd::owned::BorrowedFd<'_>, aya::programs::ProgramError>
pub fn aya::programs::loaded_links() -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::programs::links::LinkInfo, aya::programs::links::LinkError>>
pub fn aya::programs::loaded_programs() -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>> pub fn aya::programs::loaded_programs() -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>>
pub mod aya::sys pub mod aya::sys
#[non_exhaustive] pub enum aya::sys::Stats #[non_exhaustive] pub enum aya::sys::Stats

Loading…
Cancel
Save