aya: add support for SockOps programs

pull/1/head
Alessandro Decina 4 years ago
parent b57cace941
commit ca4b3bfc04

@ -19,8 +19,8 @@ use crate::{
Object, ParseError, ProgramKind, Object, ParseError, ProgramKind,
}, },
programs::{ programs::{
KProbe, ProbeKind, Program, ProgramData, ProgramError, SkSkb, SkSkbKind, SocketFilter, KProbe, ProbeKind, Program, ProgramData, ProgramError, SkSkb, SkSkbKind, SockOps,
TracePoint, UProbe, Xdp, 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},
@ -181,6 +181,7 @@ impl Bpf {
data, data,
kind: SkSkbKind::StreamVerdict, kind: SkSkbKind::StreamVerdict,
}), }),
ProgramKind::SockOps => Program::SockOps(SockOps { data }),
}; };
(name, program) (name, program)

@ -75,6 +75,7 @@ pub enum ProgramKind {
Xdp, Xdp,
SkSkbStreamParser, SkSkbStreamParser,
SkSkbStreamVerdict, SkSkbStreamVerdict,
SockOps,
} }
impl FromStr for ProgramKind { impl FromStr for ProgramKind {
@ -92,6 +93,7 @@ impl FromStr for ProgramKind {
"socket_filter" => SocketFilter, "socket_filter" => SocketFilter,
"sk_skb/stream_parser" => SkSkbStreamParser, "sk_skb/stream_parser" => SkSkbStreamParser,
"sk_skb/stream_verdict" => SkSkbStreamVerdict, "sk_skb/stream_verdict" => SkSkbStreamVerdict,
"sockops" => SockOps,
_ => { _ => {
return Err(ParseError::InvalidProgramKind { return Err(ParseError::InvalidProgramKind {
kind: kind.to_string(), kind: kind.to_string(),
@ -254,6 +256,12 @@ impl Object {
let mut parts = section.name.rsplitn(2, "/").collect::<Vec<_>>(); let mut parts = section.name.rsplitn(2, "/").collect::<Vec<_>>();
parts.reverse(); parts.reverse();
if parts.len() == 1 {
if parts[0] == "xdp" || parts[0] == "sockops" {
parts.push(parts[0]);
}
}
match parts.as_slice() { match parts.as_slice() {
&[name] &[name]
if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") => if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") =>
@ -276,7 +284,8 @@ impl Object {
| &[ty @ "xdp", name] | &[ty @ "xdp", name]
| &[ty @ "trace_point", name] | &[ty @ "trace_point", name]
| &[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] => {
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() {

@ -48,6 +48,7 @@ mod kprobe;
mod perf_attach; mod perf_attach;
mod probe; mod probe;
mod sk_skb; mod sk_skb;
mod sock_ops;
mod socket_filter; mod socket_filter;
mod trace_point; mod trace_point;
mod uprobe; mod uprobe;
@ -61,6 +62,7 @@ pub use kprobe::{KProbe, KProbeError};
use perf_attach::*; use perf_attach::*;
pub use probe::ProbeKind; pub use probe::ProbeKind;
pub use sk_skb::{SkSkb, SkSkbKind}; pub use sk_skb::{SkSkb, SkSkbKind};
pub use sock_ops::SockOps;
pub use socket_filter::{SocketFilter, SocketFilterError}; pub use socket_filter::{SocketFilter, SocketFilterError};
pub use trace_point::{TracePoint, TracePointError}; pub use trace_point::{TracePoint, TracePointError};
pub use uprobe::{UProbe, UProbeError}; pub use uprobe::{UProbe, UProbeError};
@ -141,6 +143,7 @@ pub enum Program {
SocketFilter(SocketFilter), SocketFilter(SocketFilter),
Xdp(Xdp), Xdp(Xdp),
SkSkb(SkSkb), SkSkb(SkSkb),
SockOps(SockOps),
} }
impl Program { impl Program {
@ -168,6 +171,7 @@ impl Program {
Program::SocketFilter(_) => BPF_PROG_TYPE_SOCKET_FILTER, Program::SocketFilter(_) => BPF_PROG_TYPE_SOCKET_FILTER,
Program::Xdp(_) => BPF_PROG_TYPE_XDP, Program::Xdp(_) => BPF_PROG_TYPE_XDP,
Program::SkSkb(_) => BPF_PROG_TYPE_SK_SKB, Program::SkSkb(_) => BPF_PROG_TYPE_SK_SKB,
Program::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS,
} }
} }
@ -184,6 +188,7 @@ impl Program {
Program::SocketFilter(p) => &p.data, Program::SocketFilter(p) => &p.data,
Program::Xdp(p) => &p.data, Program::Xdp(p) => &p.data,
Program::SkSkb(p) => &p.data, Program::SkSkb(p) => &p.data,
Program::SockOps(p) => &p.data,
} }
} }
@ -195,6 +200,7 @@ impl Program {
Program::SocketFilter(p) => &mut p.data, Program::SocketFilter(p) => &mut p.data,
Program::Xdp(p) => &mut p.data, Program::Xdp(p) => &mut p.data,
Program::SkSkb(p) => &mut p.data, Program::SkSkb(p) => &mut p.data,
Program::SockOps(p) => &mut p.data,
} }
} }
} }
@ -365,14 +371,14 @@ impl Drop for FdLink {
#[derive(Debug)] #[derive(Debug)]
struct ProgAttachLink { struct ProgAttachLink {
prog_fd: Option<RawFd>, prog_fd: Option<RawFd>,
map_fd: Option<RawFd>, target_fd: Option<RawFd>,
attach_type: bpf_attach_type, attach_type: bpf_attach_type,
} }
impl Link for ProgAttachLink { impl Link for ProgAttachLink {
fn detach(&mut self) -> Result<(), ProgramError> { fn detach(&mut self) -> Result<(), ProgramError> {
if let Some(prog_fd) = self.prog_fd.take() { if let Some(prog_fd) = self.prog_fd.take() {
let _ = bpf_prog_detach(prog_fd, self.map_fd.take().unwrap(), self.attach_type); let _ = bpf_prog_detach(prog_fd, self.target_fd.take().unwrap(), self.attach_type);
Ok(()) Ok(())
} else { } else {
Err(ProgramError::AlreadyDetached) Err(ProgramError::AlreadyDetached)
@ -434,4 +440,12 @@ macro_rules! impl_try_from_program {
} }
} }
impl_try_from_program!(KProbe, UProbe, TracePoint, SocketFilter, Xdp, SkSkb); impl_try_from_program!(
KProbe,
UProbe,
TracePoint,
SocketFilter,
Xdp,
SkSkb,
SockOps
);

@ -54,7 +54,7 @@ impl SkSkb {
})?; })?;
Ok(self.data.link(ProgAttachLink { Ok(self.data.link(ProgAttachLink {
prog_fd: Some(prog_fd), prog_fd: Some(prog_fd),
map_fd: Some(map_fd), target_fd: Some(map_fd),
attach_type, attach_type,
})) }))
} }

@ -0,0 +1,44 @@
use std::os::unix::io::AsRawFd;
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS},
programs::{load_program, LinkRef, ProgAttachLink, ProgramData, ProgramError},
sys::bpf_prog_attach,
};
#[derive(Debug)]
pub struct SockOps {
pub(crate) data: ProgramData,
}
impl SockOps {
/// 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_SOCK_OPS, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Attaches the program to the given sockmap.
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let cgroup_fd = cgroup.as_raw_fd();
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
}
})?;
Ok(self.data.link(ProgAttachLink {
prog_fd: Some(prog_fd),
target_fd: Some(cgroup_fd),
attach_type: BPF_CGROUP_SOCK_OPS,
}))
}
}
Loading…
Cancel
Save