use std::os::fd::AsFd;
use aya_obj::generated::{
bpf_attach_type::BPF_FLOW_DISSECTOR, bpf_prog_type::BPF_PROG_TYPE_FLOW_DISSECTOR,
};
use crate::{
programs::{
CgroupAttachMode, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, ProgramType,
define_link_wrapper, id_as_key, impl_try_into_fdlink, load_program_with_attach_type,
},
sys::{LinkTarget, SyscallError, bpf_link_create},
util::KernelVersion,
};
#[derive(Debug)]
#[doc(alias = "BPF_PROG_TYPE_FLOW_DISSECTOR")]
pub struct FlowDissector {
pub(crate) data: ProgramData<FlowDissectorLink>,
}
impl FlowDissector {
pub const PROGRAM_TYPE: ProgramType = ProgramType::FlowDissector;
pub fn load(&mut self) -> Result<(), ProgramError> {
let Self { data } = self;
load_program_with_attach_type(BPF_PROG_TYPE_FLOW_DISSECTOR, BPF_FLOW_DISSECTOR, data)
}
pub fn attach<T: AsFd>(&mut self, netns: T) -> Result<FlowDissectorLinkId, ProgramError> {
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let netns_fd = netns.as_fd();
let attach_type = BPF_FLOW_DISSECTOR;
if KernelVersion::at_least(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(netns_fd), attach_type, 0, None)
.map_err(|io_error| SyscallError {
call: "bpf_link_create",
io_error,
})?;
self.data
.links
.insert(FlowDissectorLink::new(FlowDissectorLinkInner::Fd(
FdLink::new(link_fd),
)))
} else {
let link = ProgAttachLink::attach(
prog_fd,
netns_fd,
attach_type,
CgroupAttachMode::default(),
)?;
self.data
.links
.insert(FlowDissectorLink::new(FlowDissectorLinkInner::ProgAttach(
link,
)))
}
}
}
#[derive(Debug, Hash, Eq, PartialEq)]
enum FlowDissectorLinkIdInner {
Fd(<FdLink as Link>::Id),
ProgAttach(<ProgAttachLink as Link>::Id),
}
#[derive(Debug)]
enum FlowDissectorLinkInner {
Fd(FdLink),
ProgAttach(ProgAttachLink),
}
impl Link for FlowDissectorLinkInner {
type Id = FlowDissectorLinkIdInner;
fn id(&self) -> Self::Id {
match self {
Self::Fd(fd) => FlowDissectorLinkIdInner::Fd(fd.id()),
Self::ProgAttach(p) => FlowDissectorLinkIdInner::ProgAttach(p.id()),
}
}
fn detach(self) -> Result<(), ProgramError> {
match self {
Self::Fd(fd) => fd.detach(),
Self::ProgAttach(p) => p.detach(),
}
}
}
id_as_key!(FlowDissectorLinkInner, FlowDissectorLinkIdInner);
define_link_wrapper!(
FlowDissectorLink,
FlowDissectorLinkId,
FlowDissectorLinkInner,
FlowDissectorLinkIdInner,
FlowDissector,
);
impl_try_into_fdlink!(FlowDissectorLink, FlowDissectorLinkInner);