Pārlūkot izejas kodu

aya: Add support for BPF_PROG_TYPE_SK_LOOKUP

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
Dave Tucker 2 gadi atpakaļ
vecāks
revīzija
2226b89
4 mainītis faili ar 127 papildinājumiem un 7 dzēšanām
  1. 5 2
      aya/src/bpf.rs
  2. 5 0
      aya/src/obj/mod.rs
  3. 14 5
      aya/src/programs/mod.rs
  4. 103 0
      aya/src/programs/sk_lookup.rs

+ 5 - 2
aya/src/bpf.rs

@@ -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,
@@ -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)

+ 5 - 0
aya/src/obj/mod.rs

@@ -185,6 +185,9 @@ pub enum ProgramSection {
     Extension {
         name: String,
     },
+    SkLookup {
+        name: String,
+    },
 }
 
 impl ProgramSection {
@@ -216,6 +219,7 @@ impl ProgramSection {
             ProgramSection::FEntry { name } => name,
             ProgramSection::FExit { name } => name,
             ProgramSection::Extension { name } => name,
+            ProgramSection::SkLookup { name } => name,
         }
     }
 }
@@ -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(),

+ 14 - 5
aya/src/programs/mod.rs

@@ -50,11 +50,12 @@ pub mod lsm;
 pub mod perf_attach;
 pub mod perf_event;
 mod probe;
-pub mod raw_trace_point;
-pub mod sk_msg;
-pub mod sk_skb;
-pub mod sock_ops;
-pub mod socket_filter;
+mod raw_trace_point;
+mod sk_lookup;
+mod sk_msg;
+mod sk_skb;
+mod sock_ops;
+mod socket_filter;
 pub mod tc;
 pub mod tp_btf;
 pub mod trace_point;
@@ -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;
@@ -261,6 +263,8 @@ pub enum Program {
     FExit(FExit),
     /// A [`Extension`] program
     Extension(Extension),
+    /// A [`SkLookup`] program
+    SkLookup(SkLookup),
 }
 
 impl Program {
@@ -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,
         }
     }
 
@@ -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),
         }
     }
 }
@@ -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,
         }
     }
 }
@@ -572,6 +579,7 @@ impl_program_fd!(
     FExit,
     Extension,
     CgroupSockAddr,
+    SkLookup,
 );
 
 macro_rules! impl_try_from_program {
@@ -624,6 +632,7 @@ impl_try_from_program!(
     FExit,
     Extension,
     CgroupSockAddr,
+    SkLookup,
 );
 
 /// Provides information about a loaded program, like name, id and statistics

+ 103 - 0
aya/src/programs/sk_lookup.rs

@@ -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
+);