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 e68d734 commit e860760
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 2 deletions.
7 changes: 5 additions & 2 deletions aya/src/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use crate::{
programs::{
BtfTracePoint, CgroupSkb, CgroupSkbAttachType, CgroupSockAddr, CgroupSockopt, CgroupSysctl,
Extension, FEntry, FExit, KProbe, LircMode2, Lsm, PerfEvent, ProbeKind, Program,
ProgramData, ProgramError, RawTracePoint, SchedClassifier, SkMsg, SkSkb, SkSkbKind,
SockOps, SocketFilter, TracePoint, UProbe, Xdp,
ProgramData, ProgramError, RawTracePoint, SchedClassifier, SkLookup, SkMsg, SkSkb,
SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp,
},
sys::{
bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_btf_datasec_supported,
Expand Down Expand Up @@ -521,6 +521,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 @@ -185,6 +185,9 @@ pub enum ProgramSection {
Extension {
name: String,
},
SkLookup {
name: String,
},
}

impl ProgramSection {
Expand Down Expand Up @@ -216,6 +219,7 @@ impl ProgramSection {
ProgramSection::FEntry { name } => name,
ProgramSection::FExit { name } => name,
ProgramSection::Extension { name } => name,
ProgramSection::SkLookup { name } => name,
}
}
}
Expand Down Expand Up @@ -361,6 +365,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 @@ -51,6 +51,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 @@ -88,6 +89,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 @@ -261,6 +263,8 @@ pub enum Program {
FExit(FExit),
/// A [`Extension`] program
Extension(Extension),
/// A [`SkLookup`] program
SkLookup(SkLookup),
}

impl Program {
Expand Down Expand Up @@ -289,6 +293,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 Down Expand Up @@ -316,6 +321,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 @@ -523,6 +529,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 @@ -572,6 +579,7 @@ impl_program_fd!(
FExit,
Extension,
CgroupSockAddr,
SkLookup,
);

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

/// Provides information about a loaded program, like name, id and statistics
Expand Down
103 changes: 103 additions & 0 deletions aya/src/programs/sk_lookup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
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.
///
/// # 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 e860760

Please sign in to comment.