aya_friday/programs/
iter.rs1use std::{
3 fs::File,
4 os::fd::{AsFd, BorrowedFd},
5};
6
7use aya_obj::{
8 btf::{Btf, BtfKind},
9 generated::{
10 bpf_attach_type::BPF_TRACE_ITER, bpf_link_type::BPF_LINK_TYPE_ITER,
11 bpf_prog_type::BPF_PROG_TYPE_TRACING,
12 },
13};
14
15use crate::{
16 programs::{
17 FdLink, LinkError, PerfLinkIdInner, PerfLinkInner, ProgramData, ProgramError, ProgramType,
18 define_link_wrapper, impl_try_from_fdlink, impl_try_into_fdlink,
19 load_program_with_attach_type,
20 },
21 sys::{LinkTarget, SyscallError, bpf_create_iter, bpf_link_create},
22};
23
24#[derive(Debug)]
59pub struct Iter {
60 pub(crate) data: ProgramData<IterLink>,
61}
62
63impl Iter {
64 pub const PROGRAM_TYPE: ProgramType = ProgramType::Tracing;
66
67 pub fn load(&mut self, iter_type: &str, btf: &Btf) -> Result<(), ProgramError> {
69 let Self { data } = self;
70 let type_name = format!("bpf_iter_{iter_type}");
71 data.attach_btf_id = Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Func)?);
72 load_program_with_attach_type(BPF_PROG_TYPE_TRACING, BPF_TRACE_ITER, data)
73 }
74
75 pub fn attach(&mut self) -> Result<IterLinkId, ProgramError> {
79 let prog_fd = self.fd()?;
80 let prog_fd = prog_fd.as_fd();
81 let link_fd = bpf_link_create(prog_fd, LinkTarget::Iter, BPF_TRACE_ITER, 0, None).map_err(
82 |io_error| SyscallError {
83 call: "bpf_link_create",
84 io_error,
85 },
86 )?;
87
88 self.data
89 .links
90 .insert(IterLink::new(PerfLinkInner::Fd(FdLink::new(link_fd))))
91 }
92}
93
94#[derive(Debug)]
96pub struct IterFd {
97 fd: crate::MockableFd,
98}
99
100impl AsFd for IterFd {
101 fn as_fd(&self) -> BorrowedFd<'_> {
102 let Self { fd } = self;
103 fd.as_fd()
104 }
105}
106
107impl_try_into_fdlink!(IterLink, PerfLinkInner);
108impl_try_from_fdlink!(IterLink, PerfLinkInner, BPF_LINK_TYPE_ITER);
109
110define_link_wrapper!(IterLink, IterLinkId, PerfLinkInner, PerfLinkIdInner, Iter);
111
112impl IterLink {
113 pub fn into_file(self) -> Result<File, LinkError> {
116 if let PerfLinkInner::Fd(fd) = self.into_inner() {
117 let fd = bpf_create_iter(fd.fd.as_fd()).map_err(|io_error| {
118 LinkError::SyscallError(SyscallError {
119 call: "bpf_iter_create",
120 io_error,
121 })
122 })?;
123 Ok(fd.into_inner().into())
124 } else {
125 Err(LinkError::InvalidLink)
126 }
127 }
128}