aya: Replace ProgramFd trait with struct

This removes the ProgramFd trait with a struct that wraps a RawFd.
Program::fd() has been implemented as well as fd() for each Program
Type. This allows for a better API than requiring the use of the
ProgramFd trait.

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/282/head
Dave Tucker 2 years ago
parent fd52bfeadc
commit b4413322e3

@ -4,7 +4,7 @@ use std::{
convert::TryFrom,
mem,
ops::{Deref, DerefMut},
os::unix::prelude::RawFd,
os::unix::prelude::{AsRawFd, RawFd},
};
use crate::{
@ -26,26 +26,28 @@ use crate::{
///
/// # Examples
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::ProgramArray;
/// use aya::programs::{CgroupSkb, ProgramFd};
/// use aya::programs::CgroupSkb;
/// use std::convert::{TryFrom, TryInto};
///
/// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?;
/// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?;
/// let prog_0_fd = prog_0.fd().unwrap();
/// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?;
/// let prog_1_fd = prog_1.fd().unwrap();
/// let prog_2: &CgroupSkb = bpf.program("example_prog_2").unwrap().try_into()?;
///
/// let prog_2_fd = prog_2.fd().unwrap();
/// let flags = 0;
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 0) will jump to prog_0
/// prog_array.set(0, prog_0, flags);
/// prog_array.set(0, prog_0_fd, flags);
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 1) will jump to prog_1
/// prog_array.set(1, prog_1, flags);
/// prog_array.set(1, prog_1_fd, flags);
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 2) will jump to prog_2
/// prog_array.set(2, prog_2, flags);
/// prog_array.set(2, prog_2_fd, flags);
/// # Ok::<(), aya::BpfError>(())
/// ```
#[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
@ -98,10 +100,10 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
///
/// When an eBPF program calls `bpf_tail_call(ctx, prog_array, index)`, control
/// flow will jump to `program`.
pub fn set(&mut self, index: u32, program: impl ProgramFd, flags: u64) -> Result<(), MapError> {
pub fn set(&mut self, index: u32, program: ProgramFd, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?;
self.check_bounds(index)?;
let prog_fd = program.fd().ok_or(MapError::ProgramNotLoaded)?;
let prog_fd = program.as_raw_fd();
bpf_map_update_elem(fd, &index, &prog_fd, flags).map_err(|(code, io_error)| {
MapError::SyscallError {

@ -214,10 +214,14 @@ pub enum ProgramError {
},
}
/// Allows the Fd of a loaded [`Program`] to be retrieved
pub trait ProgramFd {
/// Returns the [`RawFd`] of the program if it has been loaded, or `None`
fn fd(&self) -> Option<RawFd>;
/// A [`Program`] file descriptor.
#[derive(Copy, Clone)]
pub struct ProgramFd(RawFd);
impl AsRawFd for ProgramFd {
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
/// eBPF program type.
@ -359,6 +363,38 @@ impl Program {
Program::CgroupSock(p) => p.unload(),
}
}
/// Returns the file descriptor of a program.
///
/// Can be used to add a program to a [`crate::maps::ProgramArray`] or attach an [`Extension`] program.
/// Can be converted to [`RawFd`] using [`AsRawFd`].
pub fn fd(&self) -> Option<ProgramFd> {
match self {
Program::KProbe(p) => p.fd(),
Program::UProbe(p) => p.fd(),
Program::TracePoint(p) => p.fd(),
Program::SocketFilter(p) => p.fd(),
Program::Xdp(p) => p.fd(),
Program::SkMsg(p) => p.fd(),
Program::SkSkb(p) => p.fd(),
Program::SockOps(p) => p.fd(),
Program::SchedClassifier(p) => p.fd(),
Program::CgroupSkb(p) => p.fd(),
Program::CgroupSysctl(p) => p.fd(),
Program::CgroupSockopt(p) => p.fd(),
Program::LircMode2(p) => p.fd(),
Program::PerfEvent(p) => p.fd(),
Program::RawTracePoint(p) => p.fd(),
Program::Lsm(p) => p.fd(),
Program::BtfTracePoint(p) => p.fd(),
Program::FEntry(p) => p.fd(),
Program::FExit(p) => p.fd(),
Program::Extension(p) => p.fd(),
Program::CgroupSockAddr(p) => p.fd(),
Program::SkLookup(p) => p.fd(),
Program::CgroupSock(p) => p.fd(),
}
}
}
impl Drop for Program {
@ -555,42 +591,6 @@ pub(crate) fn query<T: AsRawFd>(
}
}
impl ProgramFd for Program {
fn fd(&self) -> Option<RawFd> {
match self {
Program::KProbe(p) => p.data.fd,
Program::UProbe(p) => p.data.fd,
Program::TracePoint(p) => p.data.fd,
Program::SocketFilter(p) => p.data.fd,
Program::Xdp(p) => p.data.fd,
Program::SkMsg(p) => p.data.fd,
Program::SkSkb(p) => p.data.fd,
Program::SockOps(p) => p.data.fd,
Program::SchedClassifier(p) => p.data.fd,
Program::CgroupSkb(p) => p.data.fd,
Program::CgroupSysctl(p) => p.data.fd,
Program::CgroupSockopt(p) => p.data.fd,
Program::LircMode2(p) => p.data.fd,
Program::PerfEvent(p) => p.data.fd,
Program::RawTracePoint(p) => p.data.fd,
Program::Lsm(p) => p.data.fd,
Program::BtfTracePoint(p) => p.data.fd,
Program::FEntry(p) => p.data.fd,
Program::FExit(p) => p.data.fd,
Program::Extension(p) => p.data.fd,
Program::CgroupSockAddr(p) => p.data.fd,
Program::SkLookup(p) => p.data.fd,
Program::CgroupSock(p) => p.data.fd,
}
}
}
impl<'a, P: ProgramFd> ProgramFd for &'a P {
fn fd(&self) -> Option<RawFd> {
(*self).fd()
}
}
macro_rules! impl_program_unload {
($($struct_name:ident),+ $(,)?) => {
$(
@ -634,25 +634,20 @@ impl_program_unload!(
CgroupSock,
);
macro_rules! impl_program_fd {
macro_rules! impl_fd {
($($struct_name:ident),+ $(,)?) => {
$(
impl ProgramFd for $struct_name {
fn fd(&self) -> Option<RawFd> {
self.data.fd
}
}
impl ProgramFd for &mut $struct_name {
fn fd(&self) -> Option<RawFd> {
self.data.fd
impl $struct_name {
/// Returns the file descriptor of this Program.
pub fn fd(&self) -> Option<ProgramFd> {
self.data.fd.map(|fd| ProgramFd(fd))
}
}
)+
}
}
impl_program_fd!(
impl_fd!(
KProbe,
UProbe,
TracePoint,
@ -674,6 +669,7 @@ impl_program_fd!(
Extension,
CgroupSockAddr,
SkLookup,
SockOps,
CgroupSock,
);

Loading…
Cancel
Save