Skip to content

Commit

Permalink
bpf: Support 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 28, 2022
1 parent e860760 commit c9eeea1
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 8 deletions.
4 changes: 2 additions & 2 deletions aya/src/programs/sk_lookup.rs
Expand Up @@ -11,7 +11,7 @@ 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
/// 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.
Expand Down Expand Up @@ -58,7 +58,7 @@ impl SkLookup {
load_program(BPF_PROG_TYPE_SK_LOOKUP, &mut self.data)
}

/// Attaches the program to the given network namespace
/// 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> {
Expand Down
32 changes: 32 additions & 0 deletions bpf/aya-bpf-macros/src/expand.rs
Expand Up @@ -744,6 +744,38 @@ impl FExit {
}
}

pub struct SkLookup {
item: ItemFn,
name: Option<String>,
}

impl SkLookup {
pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SkLookup> {
let name = name_arg(&mut args)?;

Ok(SkLookup { item, name })
}

pub fn expand(&self) -> Result<TokenStream> {
let section_name = if let Some(name) = &self.name {
format!("sk_lookup/{}", name)
} else {
"sk_lookup".to_owned()
};
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sk_lookup) -> u32 {
return #fn_name(::aya_bpf::programs::SkLookupContext::new(ctx));

#item
}
})
}
}

#[cfg(test)]
mod tests {
use syn::parse_quote;
Expand Down
33 changes: 31 additions & 2 deletions bpf/aya-bpf-macros/src/lib.rs
Expand Up @@ -2,8 +2,8 @@ mod expand;

use expand::{
Args, BtfTracePoint, CgroupSkb, CgroupSockAddr, CgroupSockopt, CgroupSysctl, FEntry, FExit,
Lsm, Map, PerfEvent, Probe, ProbeKind, RawTracePoint, SchedClassifier, SkMsg, SkSkb, SkSkbKind,
SockAddrArgs, SockOps, SocketFilter, SockoptArgs, TracePoint, Xdp,
Lsm, Map, PerfEvent, Probe, ProbeKind, RawTracePoint, SchedClassifier, SkLookup, SkMsg, SkSkb,
SkSkbKind, SockAddrArgs, SockOps, SocketFilter, SockoptArgs, TracePoint, Xdp,
};
use proc_macro::TokenStream;
use syn::{parse_macro_input, ItemFn, ItemStatic};
Expand Down Expand Up @@ -467,3 +467,32 @@ pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream {
.unwrap_or_else(|err| err.to_compile_error())
.into()
}

/// Marks a function as an eBPF Socket Lookup program that can be attached to
/// a network namespace.
///
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 5.9
///
/// # Examples
///
/// ```no_run
/// use aya_bpf::{macros::sk_lookup, programs::SkLookupContext};
///
/// #[sk_lookup(name = "redirect")]
/// pub fn accept_all(_ctx: SkLookupContext) -> u32 {
/// // use sk_assign to redirect
/// return 0
/// }
/// ```
#[proc_macro_attribute]
pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream {
let args = parse_macro_input!(attrs as Args);
let item = parse_macro_input!(item as ItemFn);

SkLookup::from_syn(args, item)
.and_then(|u| u.expand())
.unwrap_or_else(|err| err.to_compile_error())
.into()
}
27 changes: 25 additions & 2 deletions bpf/aya-bpf/src/maps/sock_hash.rs
Expand Up @@ -4,9 +4,12 @@ use aya_bpf_cty::c_void;

use crate::{
bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_SOCKHASH, bpf_sock_ops},
helpers::{bpf_msg_redirect_hash, bpf_sk_redirect_hash, bpf_sock_hash_update},
helpers::{
bpf_map_lookup_elem, bpf_msg_redirect_hash, bpf_sk_assign, bpf_sk_redirect_hash,
bpf_sk_release, bpf_sock_hash_update,
},
maps::PinningType,
programs::{SkBuffContext, SkMsgContext},
programs::{SkBuffContext, SkLookupContext, SkMsgContext},
BpfContext,
};

Expand Down Expand Up @@ -85,4 +88,24 @@ impl<K> SockHash<K> {
)
}
}

pub fn redirect_sk_lookup(
&mut self,
ctx: &SkLookupContext,
key: K,
flags: u64,
) -> Result<(), u32> {
unsafe {
let sk = bpf_map_lookup_elem(
&mut self.def as *mut _ as *mut _,
&key as *const _ as *const c_void,
);
if sk.is_null() {
return Err(1);
}
let ret = bpf_sk_assign(ctx.as_ptr() as *mut _, sk, flags);
bpf_sk_release(sk);
(ret >= 0).then(|| ()).ok_or(1)
}
}
}
27 changes: 25 additions & 2 deletions bpf/aya-bpf/src/maps/sock_map.rs
Expand Up @@ -4,9 +4,12 @@ use aya_bpf_cty::c_void;

use crate::{
bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_SOCKMAP, bpf_sock_ops},
helpers::{bpf_msg_redirect_map, bpf_sk_redirect_map, bpf_sock_map_update},
helpers::{
bpf_map_lookup_elem, bpf_msg_redirect_map, bpf_sk_assign, bpf_sk_redirect_map,
bpf_sk_release, bpf_sock_map_update,
},
maps::PinningType,
programs::{SkBuffContext, SkMsgContext},
programs::{SkBuffContext, SkLookupContext, SkMsgContext},
BpfContext,
};

Expand Down Expand Up @@ -80,4 +83,24 @@ impl SockMap {
flags,
)
}

pub fn redirect_sk_lookup(
&mut self,
ctx: &SkLookupContext,
index: u32,
flags: u64,
) -> Result<(), u32> {
unsafe {
let sk = bpf_map_lookup_elem(
&mut self.def as *mut _ as *mut _,
&index as *const _ as *const c_void,
);
if sk.is_null() {
return Err(1);
}
let ret = bpf_sk_assign(ctx.as_ptr() as *mut _, sk, flags);
bpf_sk_release(sk);
(ret >= 0).then(|| ()).ok_or(1)
}
}
}
2 changes: 2 additions & 0 deletions bpf/aya-bpf/src/programs/mod.rs
Expand Up @@ -5,6 +5,7 @@ pub mod perf_event;
pub mod probe;
pub mod raw_tracepoint;
pub mod sk_buff;
pub mod sk_lookup;
pub mod sk_msg;
pub mod sock_addr;
pub mod sock_ops;
Expand All @@ -21,6 +22,7 @@ pub use perf_event::PerfEventContext;
pub use probe::ProbeContext;
pub use raw_tracepoint::RawTracePointContext;
pub use sk_buff::SkBuffContext;
pub use sk_lookup::SkLookupContext;
pub use sk_msg::SkMsgContext;
pub use sock_addr::SockAddrContext;
pub use sock_ops::SockOpsContext;
Expand Down
19 changes: 19 additions & 0 deletions bpf/aya-bpf/src/programs/sk_lookup.rs
@@ -0,0 +1,19 @@
use core::ffi::c_void;

use crate::{bindings::bpf_sk_lookup, BpfContext};

pub struct SkLookupContext {
pub lookup: *mut bpf_sk_lookup,
}

impl SkLookupContext {
pub fn new(lookup: *mut bpf_sk_lookup) -> SkLookupContext {
SkLookupContext { lookup }
}
}

impl BpfContext for SkLookupContext {
fn as_ptr(&self) -> *mut c_void {
self.lookup as *mut _
}
}

0 comments on commit c9eeea1

Please sign in to comment.