aya: programs: add support for BPF_PROG_TYPE_CGROUP_SKB programs

pull/1/head
Alessandro Decina 3 years ago
parent fb3e2f7f9d
commit 08a68faf8a

@ -19,8 +19,8 @@ use crate::{
Object, ParseError, ProgramKind, Object, ParseError, ProgramKind,
}, },
programs::{ programs::{
KProbe, ProbeKind, Program, ProgramData, ProgramError, SchedClassifier, SkMsg, SkSkb, CgroupSkb, CgroupSkbAttachType, KProbe, ProbeKind, Program, ProgramData, ProgramError,
SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp, SchedClassifier, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp,
}, },
sys::bpf_map_update_elem_ptr, sys::bpf_map_update_elem_ptr,
util::{possible_cpus, POSSIBLE_CPUS}, util::{possible_cpus, POSSIBLE_CPUS},
@ -187,6 +187,14 @@ impl Bpf {
ProgramKind::SchedClassifier => { ProgramKind::SchedClassifier => {
Program::SchedClassifier(SchedClassifier { data }) Program::SchedClassifier(SchedClassifier { data })
} }
ProgramKind::CgroupSkbIngress => Program::CgroupSkb(CgroupSkb {
data,
expected_attach_type: Some(CgroupSkbAttachType::Ingress),
}),
ProgramKind::CgroupSkbEgress => Program::CgroupSkb(CgroupSkb {
data,
expected_attach_type: Some(CgroupSkbAttachType::Egress),
}),
}; };
(name, program) (name, program)

@ -78,6 +78,8 @@ pub enum ProgramKind {
SkSkbStreamVerdict, SkSkbStreamVerdict,
SockOps, SockOps,
SchedClassifier, SchedClassifier,
CgroupSkbIngress,
CgroupSkbEgress,
} }
impl FromStr for ProgramKind { impl FromStr for ProgramKind {
@ -98,6 +100,8 @@ impl FromStr for ProgramKind {
"sk_skb/stream_verdict" => SkSkbStreamVerdict, "sk_skb/stream_verdict" => SkSkbStreamVerdict,
"sockops" => SockOps, "sockops" => SockOps,
"classifier" => SchedClassifier, "classifier" => SchedClassifier,
"cgroup_skb/ingress" => CgroupSkbIngress,
"cgroup_skb/egress" => CgroupSkbEgress,
_ => { _ => {
return Err(ParseError::InvalidProgramKind { return Err(ParseError::InvalidProgramKind {
kind: kind.to_string(), kind: kind.to_string(),
@ -295,7 +299,10 @@ impl Object {
| &[ty @ "sk_skb/stream_parser", name] | &[ty @ "sk_skb/stream_parser", name]
| &[ty @ "sk_skb/stream_verdict", name] | &[ty @ "sk_skb/stream_verdict", name]
| &[ty @ "sockops", name] | &[ty @ "sockops", name]
| &[ty @ "classifier", name] => { | &[ty @ "classifier", name]
| &[ty @ "cgroup_skb/ingress", name]
| &[ty @ "cgroup_skb/egress", name]
| &[ty @ "cgroup/skb", name] => {
self.programs self.programs
.insert(name.to_string(), self.parse_program(&section, ty, name)?); .insert(name.to_string(), self.parse_program(&section, ty, name)?);
if !section.relocations.is_empty() { if !section.relocations.is_empty() {

@ -0,0 +1,114 @@
use std::os::unix::prelude::{AsRawFd, RawFd};
use crate::{
generated::{
bpf_attach_type::{BPF_CGROUP_INET_EGRESS, BPF_CGROUP_INET_INGRESS},
bpf_prog_type::BPF_PROG_TYPE_CGROUP_SKB,
},
programs::{load_program, LinkRef, ProgAttachLink, ProgramData, ProgramError},
sys::{bpf_link_create, bpf_prog_attach, kernel_version},
};
use super::FdLink;
/// A program used to inspect or filter network activity for a given cgroup.
///
/// [`CgroupSkb`] programs can be used to inspect or filter network activity
/// generated on all the sockets belonging to a given [cgroup].
///
/// [cgroup]: https://man7.org/linux/man-pages/man7/cgroups.7.html
#[derive(Debug)]
pub struct CgroupSkb {
pub(crate) data: ProgramData,
pub(crate) expected_attach_type: Option<CgroupSkbAttachType>,
}
impl CgroupSkb {
/// Loads the program inside the kernel.
///
/// See also [`Program::load`](crate::programs::Program::load).
pub fn load(&mut self) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_CGROUP_SKB, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Returns the expected attach type of the program.
///
/// [`CgroupSkb`] programs can specify the expected attach type in their ELF
/// section name, eg `cgroup_skb/ingress` or `cgroup_skb/egress`. This
/// method returns `None` for programs defined with the generic section
/// `cgroup/skb`.
pub fn expected_attach_type(&self) -> &Option<CgroupSkbAttachType> {
&self.expected_attach_type
}
/// Attaches the program to the given cgroup.
///
/// # Example
///
/// ```no_run
/// # #[derive(thiserror::Error, Debug)]
/// # enum Error {
/// # #[error(transparent)]
/// # IO(#[from] std::io::Error),
/// # #[error(transparent)]
/// # Map(#[from] aya::maps::MapError),
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError)
/// # }
/// # let bpf = aya::Bpf::load(&[], None)?;
/// use aya::programs::{CgroupSkb, CgroupSkbAttachType};
///
/// let file = File::open("/sys/fs/cgroup/unified")?;
/// let egress: &mut CgroupSkb =
/// self.bpf.program_mut("egress_filter")?.try_into()?;
/// egress.load()?;
/// egress.attach(file, CgroupSkbAttachType::Egress)?;
/// # Ok::<(), Error>(())
/// ```
pub fn attach<T: AsRawFd>(
&mut self,
cgroup: T,
attach_type: CgroupSkbAttachType,
) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let cgroup_fd = cgroup.as_raw_fd();
let attach_type = match attach_type {
CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS,
CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS,
};
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd =
bpf_link_create(prog_fd, cgroup_fd, attach_type, 0).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
}
})? as RawFd;
Ok(self.data.link(FdLink { fd: Some(link_fd) }))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
Ok(self
.data
.link(ProgAttachLink::new(prog_fd, cgroup_fd, attach_type)))
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum CgroupSkbAttachType {
Ingress,
Egress,
}

@ -44,7 +44,7 @@
//! [`Bpf::program`]: crate::Bpf::program //! [`Bpf::program`]: crate::Bpf::program
//! [`Bpf::program_mut`]: crate::Bpf::program_mut //! [`Bpf::program_mut`]: crate::Bpf::program_mut
//! [maps]: crate::maps //! [maps]: crate::maps
mod tc; mod cgroup_skb;
mod kprobe; mod kprobe;
mod perf_attach; mod perf_attach;
mod probe; mod probe;
@ -52,6 +52,7 @@ mod sk_msg;
mod sk_skb; mod sk_skb;
mod sock_ops; mod sock_ops;
mod socket_filter; mod socket_filter;
mod tc;
mod trace_point; mod trace_point;
mod uprobe; mod uprobe;
mod xdp; mod xdp;
@ -60,7 +61,7 @@ use libc::{close, dup, ENOSPC};
use std::{cell::RefCell, cmp, convert::TryFrom, ffi::CStr, io, os::unix::io::RawFd, rc::Rc}; use std::{cell::RefCell, cmp, convert::TryFrom, ffi::CStr, io, os::unix::io::RawFd, rc::Rc};
use thiserror::Error; use thiserror::Error;
pub use tc::{SchedClassifier, TcError, TcAttachPoint}; pub use cgroup_skb::{CgroupSkb, CgroupSkbAttachType};
pub use kprobe::{KProbe, KProbeError}; pub use kprobe::{KProbe, KProbeError};
use perf_attach::*; use perf_attach::*;
pub use probe::ProbeKind; pub use probe::ProbeKind;
@ -68,6 +69,7 @@ pub use sk_msg::SkMsg;
pub use sk_skb::{SkSkb, SkSkbKind}; pub use sk_skb::{SkSkb, SkSkbKind};
pub use sock_ops::SockOps; pub use sock_ops::SockOps;
pub use socket_filter::{SocketFilter, SocketFilterError}; pub use socket_filter::{SocketFilter, SocketFilterError};
pub use tc::{SchedClassifier, TcAttachPoint, TcError};
pub use trace_point::{TracePoint, TracePointError}; pub use trace_point::{TracePoint, TracePointError};
pub use uprobe::{UProbe, UProbeError}; pub use uprobe::{UProbe, UProbeError};
pub use xdp::{Xdp, XdpError, XdpFlags}; pub use xdp::{Xdp, XdpError, XdpFlags};
@ -153,6 +155,7 @@ pub enum Program {
SkSkb(SkSkb), SkSkb(SkSkb),
SockOps(SockOps), SockOps(SockOps),
SchedClassifier(SchedClassifier), SchedClassifier(SchedClassifier),
CgroupSkb(CgroupSkb),
} }
impl Program { impl Program {
@ -183,6 +186,7 @@ impl Program {
Program::SkSkb(_) => BPF_PROG_TYPE_SK_SKB, Program::SkSkb(_) => BPF_PROG_TYPE_SK_SKB,
Program::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS, Program::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS,
Program::SchedClassifier(_) => BPF_PROG_TYPE_SCHED_CLS, Program::SchedClassifier(_) => BPF_PROG_TYPE_SCHED_CLS,
Program::CgroupSkb(_) => BPF_PROG_TYPE_CGROUP_SKB,
} }
} }
@ -202,6 +206,7 @@ impl Program {
Program::SkSkb(p) => &p.data, Program::SkSkb(p) => &p.data,
Program::SockOps(p) => &p.data, Program::SockOps(p) => &p.data,
Program::SchedClassifier(p) => &p.data, Program::SchedClassifier(p) => &p.data,
Program::CgroupSkb(p) => &p.data,
} }
} }
@ -216,6 +221,7 @@ impl Program {
Program::SkSkb(p) => &mut p.data, Program::SkSkb(p) => &mut p.data,
Program::SockOps(p) => &mut p.data, Program::SockOps(p) => &mut p.data,
Program::SchedClassifier(p) => &mut p.data, Program::SchedClassifier(p) => &mut p.data,
Program::CgroupSkb(p) => &mut p.data,
} }
} }
} }
@ -496,5 +502,6 @@ impl_try_from_program!(
SkMsg, SkMsg,
SkSkb, SkSkb,
SockOps, SockOps,
SchedClassifier SchedClassifier,
CgroupSkb
); );

Loading…
Cancel
Save