mirror of https://github.com/aya-rs/aya
aya: programs: add support for BPF_PROG_TYPE_CGROUP_SKB programs
parent
fb3e2f7f9d
commit
08a68faf8a
@ -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,
|
||||||
|
}
|
Loading…
Reference in New Issue