aya: Use OwnedFd in FdLink.

reviewable/pr709/r3
Andrés Medina 1 year ago committed by Tamir Duberstein
parent e9153792f1
commit 8ebf0ac327
No known key found for this signature in database

@ -42,7 +42,7 @@ use std::{
marker::PhantomData,
mem,
ops::Deref,
os::fd::{AsFd, AsRawFd, OwnedFd, RawFd},
os::fd::{AsFd as _, AsRawFd, IntoRawFd as _, OwnedFd, RawFd},
path::Path,
ptr,
sync::Arc,
@ -516,11 +516,9 @@ impl MapData {
code,
io_error,
}
})? as RawFd;
self.fd = Some(fd);
})?;
Ok(fd)
Ok(*self.fd.insert(fd as RawFd))
}
pub(crate) fn open_pinned<P: AsRef<Path>>(
@ -536,11 +534,9 @@ impl MapData {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
self.fd = Some(fd);
})?;
Ok(fd)
Ok(*self.fd.insert(fd.into_raw_fd()))
}
/// Loads a map from a pinned path in bpffs.
@ -558,29 +554,29 @@ impl MapData {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
})?;
let info = bpf_map_get_info_by_fd(fd)?;
let info = bpf_map_get_info_by_fd(fd.as_fd())?;
Ok(MapData {
obj: parse_map_info(info, PinningType::ByName),
fd: Some(fd),
fd: Some(fd.into_raw_fd()),
btf_fd: None,
pinned: true,
})
}
/// Loads a map from a [`RawFd`].
/// Loads a map from a file descriptor.
///
/// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`](crate::maps::MapData::from_pin).
/// This API is intended for cases where you have received a valid BPF FD from some other means.
/// For example, you received an FD over Unix Domain Socket.
pub fn from_fd(fd: RawFd) -> Result<MapData, MapError> {
let info = bpf_map_get_info_by_fd(fd)?;
pub fn from_fd(fd: OwnedFd) -> Result<MapData, MapError> {
let info = bpf_map_get_info_by_fd(fd.as_fd())?;
Ok(MapData {
obj: parse_map_info(info, PinningType::None),
fd: Some(fd),
fd: Some(fd.into_raw_fd()),
btf_fd: None,
pinned: false,
})

@ -1,7 +1,7 @@
//! Cgroup device programs.
use crate::util::KernelVersion;
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::AsRawFd;
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE},
@ -70,7 +70,7 @@ impl CgroupDevice {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::Fd(

@ -1,11 +1,7 @@
//! Cgroup skb programs.
use crate::util::KernelVersion;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::{
@ -105,7 +101,7 @@ impl CgroupSkb {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(CgroupSkbLink::new(CgroupSkbLinkInner::Fd(FdLink::new(

@ -3,11 +3,7 @@
pub use aya_obj::programs::CgroupSockAttachType;
use crate::util::KernelVersion;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK,
@ -80,7 +76,7 @@ impl CgroupSock {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(CgroupSockLink::new(CgroupSockLinkInner::Fd(FdLink::new(

@ -3,11 +3,7 @@
pub use aya_obj::programs::CgroupSockAddrAttachType;
use crate::util::KernelVersion;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
@ -81,7 +77,7 @@ impl CgroupSockAddr {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(CgroupSockAddrLink::new(CgroupSockAddrLinkInner::Fd(

@ -3,11 +3,7 @@
pub use aya_obj::programs::CgroupSockoptAttachType;
use crate::util::KernelVersion;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT,
@ -78,7 +74,7 @@ impl CgroupSockopt {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::Fd(

@ -1,10 +1,7 @@
//! Cgroup sysctl programs.
use crate::util::KernelVersion;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
};
use std::{hash::Hash, os::fd::AsRawFd};
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL},
@ -72,7 +69,7 @@ impl CgroupSysctl {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::Fd(

@ -94,7 +94,7 @@ impl Extension {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
})? as RawFd;
})?;
self.data
.links
.insert(ExtensionLink::new(FdLink::new(link_fd)))
@ -124,7 +124,7 @@ impl Extension {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
})? as RawFd;
})?;
self.data
.links
.insert(ExtensionLink::new(FdLink::new(link_fd)))

@ -1,5 +1,5 @@
//! Kernel space probes.
use std::{io, path::Path};
use std::{io, os::fd::AsFd as _, path::Path};
use thiserror::Error;
use crate::{
@ -137,7 +137,7 @@ impl TryFrom<FdLink> for KProbeLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info = bpf_link_get_info_by_fd(fd_link.fd)?;
let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_KPROBE_MULTI as u32) {
return Ok(KProbeLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -6,7 +6,7 @@ use std::{
collections::{hash_map::Entry, HashMap},
ffi::CString,
io,
os::fd::RawFd,
os::fd::{AsRawFd as _, OwnedFd, RawFd},
path::{Path, PathBuf},
};
@ -108,11 +108,11 @@ pub struct FdLinkId(pub(crate) RawFd);
/// ```
#[derive(Debug)]
pub struct FdLink {
pub(crate) fd: RawFd,
pub(crate) fd: OwnedFd,
}
impl FdLink {
pub(crate) fn new(fd: RawFd) -> FdLink {
pub(crate) fn new(fd: OwnedFd) -> FdLink {
FdLink { fd }
}
@ -152,9 +152,11 @@ impl FdLink {
error: e.to_string(),
}
})?;
bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| SyscallError {
bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| {
SyscallError {
call: "BPF_OBJ_PIN",
io_error,
}
})?;
Ok(PinnedLink::new(PathBuf::from(path.as_ref()), self))
}
@ -164,7 +166,7 @@ impl Link for FdLink {
type Id = FdLinkId;
fn id(&self) -> Self::Id {
FdLinkId(self.fd)
FdLinkId(self.fd.as_raw_fd())
}
fn detach(self) -> Result<(), ProgramError> {
@ -183,12 +185,6 @@ impl From<PinnedLink> for FdLink {
}
}
impl Drop for FdLink {
fn drop(&mut self) {
unsafe { close(self.fd) };
}
}
/// A pinned file descriptor link.
///
/// This link has been pinned to the BPF filesystem. On drop, the file descriptor that backs
@ -213,7 +209,7 @@ impl PinnedLink {
call: "BPF_OBJ_GET",
io_error,
})
})? as RawFd;
})?;
Ok(PinnedLink::new(
path.as_ref().to_path_buf(),
FdLink::new(fd),
@ -346,7 +342,7 @@ pub enum LinkError {
#[cfg(test)]
mod tests {
use assert_matches::assert_matches;
use std::{cell::RefCell, fs::File, mem, os::fd::AsRawFd, rc::Rc};
use std::{cell::RefCell, fs::File, rc::Rc};
use tempfile::tempdir;
use crate::{programs::ProgramError, sys::override_syscall};
@ -484,10 +480,7 @@ mod tests {
fn test_pin() {
let dir = tempdir().unwrap();
let f1 = File::create(dir.path().join("f1")).expect("unable to create file in tmpdir");
let fd_link = FdLink::new(f1.as_raw_fd());
// leak the fd, it will get closed when our pinned link is dropped
mem::forget(f1);
let fd_link = FdLink::new(f1.into());
// override syscall to allow for pin to happen in our tmpdir
override_syscall(|_| Ok(0));

@ -440,7 +440,7 @@ impl<T: Link> ProgramData<T> {
pub(crate) fn from_bpf_prog_info(
name: Option<String>,
fd: RawFd,
fd: OwnedFd,
path: &Path,
info: bpf_prog_info,
verifier_log_level: VerifierLogLevel,
@ -464,7 +464,7 @@ impl<T: Link> ProgramData<T> {
Ok(ProgramData {
name,
obj: None,
fd: Some(fd),
fd: Some(fd.into_raw_fd()),
links: LinkMap::new(),
expected_attach_type: None,
attach_btf_obj_fd,
@ -486,9 +486,9 @@ impl<T: Link> ProgramData<T> {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "bpf_obj_get",
io_error,
})? as RawFd;
})?;
let info = bpf_prog_get_info_by_fd(fd)?;
let info = bpf_prog_get_info_by_fd(fd.as_raw_fd())?;
let name = ProgramInfo(info).name_as_str().map(|s| s.to_string());
ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info, verifier_log_level)
}
@ -953,13 +953,9 @@ impl ProgramInfo {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
})?;
let info = bpf_prog_get_info_by_fd(fd);
unsafe {
libc::close(fd);
}
let info = info?;
let info = bpf_prog_get_info_by_fd(fd.as_raw_fd())?;
Ok(ProgramInfo(info))
}
}
@ -1011,7 +1007,7 @@ pub fn loaded_links() -> impl Iterator<Item = Result<bpf_link_info, ProgramError
})
.map(|fd| {
let fd = fd?;
bpf_link_get_info_by_fd(fd.as_raw_fd())
bpf_link_get_info_by_fd(fd.as_fd())
})
.map(|result| result.map_err(Into::into))
}

@ -77,7 +77,7 @@ pub(crate) fn perf_attach(prog_fd: RawFd, fd: OwnedFd) -> Result<PerfLinkInner,
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
Ok(PerfLinkInner::FdLink(FdLink::new(link_fd)))
} else {
perf_attach_either(prog_fd, fd, None)

@ -1,5 +1,7 @@
//! Perf event programs.
use std::os::fd::AsFd as _;
pub use crate::generated::{
perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids,
};
@ -206,7 +208,7 @@ impl TryFrom<FdLink> for PerfEventLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info = bpf_link_get_info_by_fd(fd_link.fd)?;
let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_PERF_EVENT as u32) {
return Ok(PerfEventLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -1,4 +1,4 @@
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::AsRawFd;
use crate::{
generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP},
@ -69,7 +69,7 @@ impl SkLookup {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(SkLookupLink::new(FdLink::new(link_fd)))

@ -1,5 +1,5 @@
//! Tracepoint programs.
use std::{fs, io, path::Path};
use std::{fs, io, os::fd::AsFd as _, path::Path};
use thiserror::Error;
use crate::{
@ -131,7 +131,7 @@ impl TryFrom<FdLink> for TracePointLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info = bpf_link_get_info_by_fd(fd_link.fd)?;
let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
return Ok(TracePointLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -8,7 +8,7 @@ use std::{
fs,
io::{self, BufRead, Cursor, Read},
mem,
os::raw::c_char,
os::{fd::AsFd as _, raw::c_char},
path::{Path, PathBuf},
sync::Arc,
};
@ -202,7 +202,7 @@ impl TryFrom<FdLink> for UProbeLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info = bpf_link_get_info_by_fd(fd_link.fd)?;
let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
return Ok(UProbeLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -1,5 +1,5 @@
//! Common functions shared between multiple eBPF program types.
use std::{ffi::CStr, io, os::fd::RawFd, path::Path};
use std::{ffi::CStr, io, path::Path};
use crate::{
programs::{FdLink, Link, ProgramData, ProgramError},
@ -17,7 +17,7 @@ pub(crate) fn attach_raw_tracepoint<T: Link + From<FdLink>>(
bpf_raw_tracepoint_open(tp_name, prog_fd).map_err(|(_code, io_error)| SyscallError {
call: "bpf_raw_tracepoint_open",
io_error,
})? as RawFd;
})?;
program_data.links.insert(FdLink::new(pfd).into())
}

@ -3,7 +3,13 @@
use crate::{sys::SyscallError, util::KernelVersion};
use bitflags;
use libc::if_nametoindex;
use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::fd::RawFd};
use std::{
convert::TryFrom,
ffi::CString,
hash::Hash,
io,
os::fd::{AsFd as _, RawFd},
};
use thiserror::Error;
use crate::{
@ -131,7 +137,7 @@ impl Xdp {
call: "bpf_link_create",
io_error,
},
)? as RawFd;
)?;
self.data
.links
.insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd))))
@ -169,17 +175,16 @@ impl Xdp {
/// Ownership of the link will transfer to this program.
pub fn attach_to_link(&mut self, link: XdpLink) -> Result<XdpLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
match link.inner() {
match link.into_inner() {
XdpLinkInner::FdLink(fd_link) => {
let link_fd = fd_link.fd;
bpf_link_update(link_fd, prog_fd, None, 0).map_err(|(_, io_error)| {
bpf_link_update(link_fd.as_fd(), prog_fd, None, 0).map_err(|(_, io_error)| {
SyscallError {
call: "bpf_link_update",
io_error,
}
})?;
// dispose of link and avoid detach on drop
mem::forget(link);
self.data
.links
.insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd))))
@ -193,8 +198,7 @@ impl Xdp {
netlink_set_xdp_fd(if_index, prog_fd, Some(old_prog_fd), replace_flags.bits())
.map_err(|io_error| XdpError::NetlinkError { io_error })?;
}
// dispose of link and avoid detach on drop
mem::forget(link);
self.data
.links
.insert(XdpLink::new(XdpLinkInner::NlLink(NlLink {
@ -279,7 +283,7 @@ impl TryFrom<FdLink> for XdpLink {
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
// unwrap of fd_link.fd will not panic since it's only None when being dropped.
let info = bpf_link_get_info_by_fd(fd_link.fd)?;
let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_XDP as u32) {
return Ok(XdpLink::new(XdpLinkInner::FdLink(fd_link)));
}

@ -101,11 +101,12 @@ pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult<c_long> {
sys_bpf(bpf_cmd::BPF_OBJ_PIN, &mut attr)
}
pub(crate) fn bpf_get_object(path: &CStr) -> SysResult<c_long> {
pub(crate) fn bpf_get_object(path: &CStr) -> SysResult<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_4 };
u.pathname = path.as_ptr() as u64;
sys_bpf(bpf_cmd::BPF_OBJ_GET, &mut attr)
// SAFETY: BPF_OBJ_GET returns a new file descriptor.
unsafe { fd_sys_bpf(bpf_cmd::BPF_OBJ_GET, &mut attr) }
}
pub(crate) struct BpfLoadProgramAttrs<'a> {
@ -370,7 +371,7 @@ pub(crate) fn bpf_link_create(
attach_type: bpf_attach_type,
btf_id: Option<u32>,
flags: u32,
) -> SysResult<c_long> {
) -> SysResult<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.link_create.__bindgen_anon_1.prog_fd = prog_fd as u32;
@ -381,19 +382,20 @@ pub(crate) fn bpf_link_create(
attr.link_create.__bindgen_anon_3.target_btf_id = btf_id;
}
sys_bpf(bpf_cmd::BPF_LINK_CREATE, &mut attr)
// SAFETY: BPF_LINK_CREATE returns a new file descriptor.
unsafe { fd_sys_bpf(bpf_cmd::BPF_LINK_CREATE, &mut attr) }
}
// since kernel 5.7
pub(crate) fn bpf_link_update(
link_fd: RawFd,
link_fd: BorrowedFd<'_>,
new_prog_fd: RawFd,
old_prog_fd: Option<RawFd>,
flags: u32,
) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.link_update.link_fd = link_fd as u32;
attr.link_update.link_fd = link_fd.as_raw_fd() as u32;
attr.link_update.__bindgen_anon_1.new_prog_fd = new_prog_fd as u32;
if let Some(fd) = old_prog_fd {
attr.link_update.__bindgen_anon_2.old_prog_fd = fd as u32;
@ -503,8 +505,7 @@ pub(crate) fn bpf_prog_get_info_by_fd(fd: RawFd) -> Result<bpf_prog_info, Syscal
bpf_obj_get_info_by_fd::<bpf_prog_info>(fd)
}
pub(crate) fn bpf_map_get_info_by_fd(fd: RawFd) -> Result<bpf_map_info, SyscallError> {
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
pub(crate) fn bpf_map_get_info_by_fd(fd: BorrowedFd<'_>) -> Result<bpf_map_info, SyscallError> {
bpf_obj_get_info_by_fd::<bpf_map_info>(fd)
}
@ -522,8 +523,7 @@ pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result<OwnedFd, SyscallErro
})
}
pub(crate) fn bpf_link_get_info_by_fd(fd: RawFd) -> Result<bpf_link_info, SyscallError> {
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
pub(crate) fn bpf_link_get_info_by_fd(fd: BorrowedFd<'_>) -> Result<bpf_link_info, SyscallError> {
bpf_obj_get_info_by_fd::<bpf_link_info>(fd)
}
@ -546,7 +546,7 @@ pub(crate) fn btf_obj_get_info_by_fd(
}
}
pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> SysResult<c_long> {
pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> SysResult<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.raw_tracepoint.name = match name {
@ -555,7 +555,8 @@ pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Sy
};
attr.raw_tracepoint.prog_fd = prog_fd as u32;
sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &mut attr)
// SAFETY: BPF_RAW_TRACEPOINT_OPEN returns a new file descriptor.
unsafe { fd_sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &mut attr) }
}
pub(crate) fn bpf_load_btf(

@ -1238,7 +1238,7 @@ pub aya::maps::MapData::pinned: bool
impl aya::maps::MapData
pub fn aya::maps::MapData::create(&mut self, name: &str) -> core::result::Result<std::os::fd::raw::RawFd, aya::maps::MapError>
pub fn aya::maps::MapData::fd(&self) -> core::option::Option<aya::maps::MapFd>
pub fn aya::maps::MapData::from_fd(fd: std::os::fd::raw::RawFd) -> core::result::Result<aya::maps::MapData, aya::maps::MapError>
pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result<aya::maps::MapData, aya::maps::MapError>
pub fn aya::maps::MapData::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<aya::maps::MapData, aya::maps::MapError>
impl core::clone::Clone for aya::maps::MapData
pub fn aya::maps::MapData::clone(&self) -> aya::maps::MapData
@ -3099,8 +3099,6 @@ pub fn aya::programs::links::FdLink::try_from(value: aya::programs::uprobe::UPro
impl core::convert::TryFrom<aya::programs::xdp::XdpLink> 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::xdp::XdpLink) -> core::result::Result<Self, Self::Error>
impl core::ops::drop::Drop for aya::programs::links::FdLink
pub fn aya::programs::links::FdLink::drop(&mut self)
impl core::fmt::Debug for aya::programs::links::FdLink
pub fn aya::programs::links::FdLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Send for aya::programs::links::FdLink

Loading…
Cancel
Save