Skip to content

Commit

Permalink
aya: Add support for BPF_PROG_TYPE_SK_LOOKUP
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
  • Loading branch information
dave-tucker committed May 20, 2022
1 parent 63b6286 commit f05726f
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
5 changes: 4 additions & 1 deletion aya/src/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
programs::{
BtfTracePoint, CgroupSkb, CgroupSkbAttachType, CgroupSockAddr, CgroupSysctl, Extension,
FEntry, FExit, KProbe, LircMode2, Lsm, PerfEvent, ProbeKind, Program, ProgramData,
ProgramError, RawTracePoint, SchedClassifier, SkMsg, SkSkb, SkSkbKind, SockOps,
ProgramError, RawTracePoint, SchedClassifier, SkLookup, SkMsg, SkSkb, SkSkbKind, SockOps,
SocketFilter, TracePoint, UProbe, Xdp,
},
sys::{
Expand Down Expand Up @@ -515,6 +515,9 @@ impl<'a> BpfLoader<'a> {
ProgramSection::Extension { .. } => Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd),
}),
ProgramSection::SkLookup { .. } => Program::SkLookup(SkLookup {
data: ProgramData::new(prog_name, obj, btf_fd),
}),
}
};
(name, program)
Expand Down
5 changes: 5 additions & 0 deletions aya/src/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pub enum ProgramSection {
Extension {
name: String,
},
SkLookup {
name: String,
},
}

impl ProgramSection {
Expand Down Expand Up @@ -211,6 +214,7 @@ impl ProgramSection {
ProgramSection::FEntry { name } => name,
ProgramSection::FExit { name } => name,
ProgramSection::Extension { name } => name,
ProgramSection::SkLookup { name } => name,
}
}
}
Expand Down Expand Up @@ -339,6 +343,7 @@ impl FromStr for ProgramSection {
"fentry" => FEntry { name },
"fexit" => FExit { name },
"freplace" => Extension { name },
"sk_lookup" => SkLookup { name },
_ => {
return Err(ParseError::InvalidProgramSection {
section: section.to_owned(),
Expand Down
9 changes: 9 additions & 0 deletions aya/src/programs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mod perf_attach;
pub mod perf_event;
mod probe;
mod raw_trace_point;
mod sk_lookup;
mod sk_msg;
mod sk_skb;
mod sock_ops;
Expand Down Expand Up @@ -86,6 +87,7 @@ use perf_attach::*;
pub use perf_event::{PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy};
pub use probe::ProbeKind;
pub use raw_trace_point::RawTracePoint;
pub use sk_lookup::SkLookup;
pub use sk_msg::SkMsg;
pub use sk_skb::{SkSkb, SkSkbKind};
pub use sock_ops::SockOps;
Expand Down Expand Up @@ -257,6 +259,8 @@ pub enum Program {
FExit(FExit),
/// A [`Extension`] program
Extension(Extension),
/// A [`SkLookup`] program
SkLookup(SkLookup),
}

impl Program {
Expand Down Expand Up @@ -284,6 +288,7 @@ impl Program {
Program::FExit(_) => BPF_PROG_TYPE_TRACING,
Program::Extension(_) => BPF_PROG_TYPE_EXT,
Program::CgroupSockAddr(_) => BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
Program::SkLookup(_) => BPF_PROG_TYPE_SK_LOOKUP,
}
}

Expand All @@ -310,6 +315,7 @@ impl Program {
Program::FExit(p) => p.data.pin(path),
Program::Extension(p) => p.data.pin(path),
Program::CgroupSockAddr(p) => p.data.pin(path),
Program::SkLookup(p) => p.data.pin(path),
}
}
}
Expand Down Expand Up @@ -516,6 +522,7 @@ impl ProgramFd for Program {
Program::FExit(p) => p.data.fd,
Program::Extension(p) => p.data.fd,
Program::CgroupSockAddr(p) => p.data.fd,
Program::SkLookup(p) => p.data.fd,
}
}
}
Expand Down Expand Up @@ -564,6 +571,7 @@ impl_program_fd!(
FExit,
Extension,
CgroupSockAddr,
SkLookup,
);

macro_rules! impl_try_from_program {
Expand Down Expand Up @@ -615,6 +623,7 @@ impl_try_from_program!(
FExit,
Extension,
CgroupSockAddr,
SkLookup,
);

/// Provides information about a loaded program, like name, id and statistics
Expand Down
105 changes: 105 additions & 0 deletions aya/src/programs/sk_lookup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use std::os::unix::prelude::{AsRawFd, RawFd};

use crate::{
generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP},
programs::{define_link_wrapper, load_program, FdLinkId, OwnedLink, ProgramData, ProgramError},
sys::bpf_link_create,
};

use super::links::FdLink;

/// A program used to redirect incoming packets to a local socket.
///
/// [`SkLookup`] programs are attached to [network namespaces] to provide programmable
/// socket lookup for TCP/UDP when a packet is to be delievered locally
///
/// You may attach multiple programs to the same namespace and they are executed
/// in the order they were attached.
///
/// [network namespaces]: https://www.man7.org/linux/man-pages/man8/ip-netns.8.html
///
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 5.9.
///
/// # Examples
///
/// ```no_run
/// # #[derive(Debug, thiserror::Error)]
/// # enum Error {
/// # #[error(transparent)]
/// # IO(#[from] std::io::Error),
/// # #[error(transparent)]
/// # Map(#[from] aya::maps::MapError),
/// # #[error(transparent)]
/// # Program(#[from] aya::programs::ProgramError),
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError)
/// # }
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use std::fs::File;
/// use std::convert::TryInto;
/// use aya::programs::SkLookup;
///
/// let file = File::open("/var/run/netns/test")?;
/// let program: &mut SkLookup = bpf.program_mut("sk_lookup").unwrap().try_into()?;
/// program.load()?;
/// program.attach(file)?;
/// # Ok::<(), Error>(())
/// ```
#[derive(Debug)]
#[doc(alias = "BPF_PROG_TYPE_SK_LOOKUP")]
pub struct SkLookup {
pub(crate) data: ProgramData<SkLookupLink>,
}

impl SkLookup {
/// Loads the program inside the kernel.
pub fn load(&mut self) -> Result<(), ProgramError> {
self.data.expected_attach_type = Some(BPF_SK_LOOKUP);
load_program(BPF_PROG_TYPE_SK_LOOKUP, &mut self.data)
}

/// Attaches the program to the given network namespace
///
/// The returned value can be used to detach, see [SkLookup::detach].
pub fn attach<T: AsRawFd>(&mut self, netns: T) -> Result<SkLookupLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let netns_fd = netns.as_raw_fd();

let link_fd = bpf_link_create(prog_fd, netns_fd, BPF_SK_LOOKUP, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
self.data.links.insert(SkLookupLink(FdLink::new(link_fd)))
}

/// Takes ownership of the link referenced by the provided link_id.
///
/// The link will be detached on `Drop` and the caller is now responsible
/// for managing its lifetime.
pub fn forget_link(
&mut self,
link_id: SkLookupLinkId,
) -> Result<OwnedLink<SkLookupLink>, ProgramError> {
Ok(OwnedLink::new(self.data.forget_link(link_id)?))
}

/// Detaches the program.
///
/// See [SkLookup::attach].
pub fn detach(&mut self, link_id: SkLookupLinkId) -> Result<(), ProgramError> {
self.data.links.remove(link_id)
}
}

define_link_wrapper!(
/// The link used by [SkLookup] programs.
SkLookupLink,
/// The type returned by [SkLookup::attach]. Can be passed to [SkLookup::detach].
SkLookupLinkId,
FdLink,
FdLinkId
);

0 comments on commit f05726f

Please sign in to comment.