Skip to content

Commit

Permalink
Add links iterator
Browse files Browse the repository at this point in the history
This is not yet exposed in documentation, but is complete enough for use
in tests, removing the dependency on bpftool.

Updates #645.
  • Loading branch information
tamird committed Aug 2, 2023
1 parent 7bb9b7f commit 30faa5f
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 110 deletions.
25 changes: 21 additions & 4 deletions aya/src/programs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,15 @@ pub use uprobe::{UProbe, UProbeError};
pub use xdp::{Xdp, XdpError, XdpFlags};

use crate::{
generated::{bpf_attach_type, bpf_prog_info, bpf_prog_type},
generated::{bpf_attach_type, bpf_link_info, bpf_prog_info, bpf_prog_type},
maps::MapError,
obj::{self, btf::BtfError, Function, VerifierLog},
pin::PinError,
sys::{
bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object,
bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_query, iter_prog_ids,
retry_with_verifier_logs, BpfLoadProgramAttrs, 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_get_info_by_fd,
bpf_prog_query, iter_link_ids, iter_prog_ids, retry_with_verifier_logs,
BpfLoadProgramAttrs, SyscallError,
},
util::KernelVersion,
VerifierLogLevel,
Expand Down Expand Up @@ -998,3 +999,19 @@ pub fn loaded_programs() -> impl Iterator<Item = Result<ProgramInfo, ProgramErro
})
.map(|result| result.map(ProgramInfo).map_err(Into::into))
}

// 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<Item = Result<bpf_link_info, ProgramError>> {
iter_link_ids()
.map(|id| {
let id = id?;
bpf_link_get_fd_by_id(id)
})
.map(|fd| {
let fd = fd?;
bpf_link_get_info_by_fd(fd.as_raw_fd())
})
.map(|result| result.map_err(Into::into))
}
39 changes: 34 additions & 5 deletions aya/src/sys/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,20 @@ pub(crate) fn bpf_map_get_info_by_fd(fd: RawFd) -> Result<bpf_map_info, SyscallE
bpf_obj_get_info_by_fd::<bpf_map_info>(fd)
}

pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result<OwnedFd, SyscallError> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };

attr.__bindgen_anon_6.__bindgen_anon_1.link_id = link_id;
// SAFETY: BPF_LINK_GET_FD_BY_ID returns a new file descriptor.
unsafe { fd_sys_bpf(bpf_cmd::BPF_LINK_GET_FD_BY_ID, &mut attr) }.map_err(|(code, io_error)| {
assert_eq!(code, -1);
SyscallError {
call: "bpf_link_get_fd_by_id",
io_error,
}
})
}

pub(crate) fn bpf_link_get_info_by_fd(fd: RawFd) -> Result<bpf_link_info, SyscallError> {
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
bpf_obj_get_info_by_fd::<bpf_link_info>(fd)
Expand Down Expand Up @@ -909,11 +923,15 @@ fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> {
syscall(Syscall::Bpf { cmd, attr })
}

fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, SyscallError> {
fn bpf_obj_get_next_id(
id: u32,
cmd: bpf_cmd,
name: &'static str,
) -> Result<Option<u32>, SyscallError> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_6 };
u.__bindgen_anon_1.start_id = id;
match sys_bpf(bpf_cmd::BPF_PROG_GET_NEXT_ID, &mut attr) {
match sys_bpf(cmd, &mut attr) {
Ok(code) => {
assert_eq!(code, 0);
Ok(Some(unsafe { attr.__bindgen_anon_6.next_id }))
Expand All @@ -924,20 +942,23 @@ fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, SyscallError> {
Ok(None)
} else {
Err(SyscallError {
call: "bpf_prog_get_next_id",
call: name,
io_error,
})
}
}
}
}

pub(crate) fn iter_prog_ids() -> impl Iterator<Item = Result<u32, SyscallError>> {
fn iter_obj_ids(
cmd: bpf_cmd,
name: &'static str,
) -> impl Iterator<Item = Result<u32, SyscallError>> {
let mut current_id = Some(0);
iter::from_fn(move || {
let next_id = {
let current_id = current_id?;
bpf_prog_get_next_id(current_id).transpose()
bpf_obj_get_next_id(current_id, cmd, name).transpose()
};
current_id = next_id.as_ref().and_then(|next_id| match next_id {
Ok(next_id) => Some(*next_id),
Expand All @@ -947,6 +968,14 @@ pub(crate) fn iter_prog_ids() -> impl Iterator<Item = Result<u32, SyscallError>>
})
}

pub(crate) fn iter_prog_ids() -> impl Iterator<Item = Result<u32, SyscallError>> {
iter_obj_ids(bpf_cmd::BPF_PROG_GET_NEXT_ID, "bpf_prog_get_next_id")
}

pub(crate) fn iter_link_ids() -> impl Iterator<Item = Result<u32, SyscallError>> {
iter_obj_ids(bpf_cmd::BPF_LINK_GET_NEXT_ID, "bpf_link_get_next_id")
}

pub(crate) fn retry_with_verifier_logs<T>(
max_retries: usize,
f: impl Fn(&mut [u8]) -> SysResult<T>,
Expand Down
3 changes: 0 additions & 3 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ To run locally all you need is:

1. Rust nightly
1. `cargo install bpf-linker`
1. `bpftool` [^1]

### Other OSs

Expand Down Expand Up @@ -52,5 +51,3 @@ Tests should follow these guidelines:
- You may add a new module, or use an existing one.
- Test functions should not return `anyhow::Result<()>` since this produces errors without stack
traces. Prefer to `panic!` instead.

[^1]: TODO(https://github.com/aya-rs/aya/issues/645): Remove this dependency.
Loading

0 comments on commit 30faa5f

Please sign in to comment.