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,
},
programs::{
KProbe, ProbeKind, Program, ProgramData, ProgramError, SkSkb, SkSkbKind, SocketFilter,
TracePoint, UProbe, Xdp,
KProbe, ProbeKind, Program, ProgramData, ProgramError, SkSkb, SkSkbKind, SockOps,
SocketFilter, TracePoint, UProbe, Xdp,
},
sys::bpf_map_update_elem_ptr,
util::{possible_cpus, POSSIBLE_CPUS},
@ -181,6 +181,7 @@ impl Bpf {
data,
kind: SkSkbKind::StreamVerdict,
}),
ProgramKind::SockOps => Program::SockOps(SockOps { data }),
};
(name, program)

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

@ -48,6 +48,7 @@ mod kprobe;
mod perf_attach;
mod probe;
mod sk_skb;
mod sock_ops;
mod socket_filter;
mod trace_point;
mod uprobe;
@ -61,6 +62,7 @@ pub use kprobe::{KProbe, KProbeError};
use perf_attach::*;
pub use probe::ProbeKind;
pub use sk_skb::{SkSkb, SkSkbKind};
pub use sock_ops::SockOps;
pub use socket_filter::{SocketFilter, SocketFilterError};
pub use trace_point::{TracePoint, TracePointError};
pub use uprobe::{UProbe, UProbeError};
@ -141,6 +143,7 @@ pub enum Program {
SocketFilter(SocketFilter),
Xdp(Xdp),
SkSkb(SkSkb),
SockOps(SockOps),
}
impl Program {
@ -168,6 +171,7 @@ impl Program {
Program::SocketFilter(_) => BPF_PROG_TYPE_SOCKET_FILTER,
Program::Xdp(_) => BPF_PROG_TYPE_XDP,
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::Xdp(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::Xdp(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)]
struct ProgAttachLink {
prog_fd: Option<RawFd>,
map_fd: Option<RawFd>,
target_fd: Option<RawFd>,
attach_type: bpf_attach_type,
}
impl Link for ProgAttachLink {
fn detach(&mut self) -> Result<(), ProgramError> {
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(())
} else {
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 {
prog_fd: Some(prog_fd),
map_fd: Some(map_fd),
target_fd: Some(map_fd),
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