Merge pull request #120 from eero-thia/thia/dedup

aya: eliminate name duplication in maps and programs.
pull/118/head
Alessandro Decina 3 years ago committed by GitHub
commit 07a6016ebb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,6 +2,7 @@ use std::{
borrow::Cow,
collections::HashMap,
error::Error,
ffi::CString,
fs, io,
os::{raw::c_int, unix::io::RawFd},
path::{Path, PathBuf},
@ -191,8 +192,8 @@ impl<'a> BpfLoader<'a> {
obj.relocate_btf(btf)?;
}
let mut maps = Vec::new();
for (_, mut obj) in obj.maps.drain() {
let mut maps = HashMap::new();
for (name, mut obj) in obj.maps.drain() {
if obj.def.map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 && obj.def.max_entries == 0
{
obj.def.max_entries = possible_cpus()
@ -214,21 +215,21 @@ impl<'a> BpfLoader<'a> {
None => return Err(BpfError::NoPinPath),
};
// try to open map in case it's already pinned
match map.from_pinned(path) {
match map.from_pinned(&name, path) {
Ok(fd) => {
map.pinned = true;
fd as RawFd
}
Err(_) => {
let fd = map.create()?;
map.pin(path)?;
let fd = map.create(&name)?;
map.pin(&name, path)?;
fd
}
}
}
PinningType::None => map.create()?,
PinningType::None => map.create(&name)?,
};
if !map.obj.data.is_empty() && map.obj.name != ".bss" {
if !map.obj.data.is_empty() && name != ".bss" {
bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data.as_mut_ptr(), 0).map_err(
|(code, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
@ -237,27 +238,25 @@ impl<'a> BpfLoader<'a> {
},
)?;
}
maps.push(map);
maps.insert(name, map);
}
obj.relocate_maps(maps.as_slice())?;
obj.relocate_maps(maps.iter().map(|(name, map)| (name.as_str(), map)))?;
obj.relocate_calls()?;
let programs = obj
.programs
.drain()
.map(|(name, obj)| {
let section = obj.section.clone();
let data = ProgramData {
obj,
name: name.clone(),
fd: None,
links: Vec::new(),
expected_attach_type: None,
attach_btf_obj_fd: None,
attach_btf_id: None,
};
let program = match section {
let program = match &data.obj.section {
ProgramSection::KProbe { .. } => Program::KProbe(KProbe {
data,
kind: ProbeKind::KProbe,
@ -290,7 +289,13 @@ impl<'a> BpfLoader<'a> {
}),
ProgramSection::SockOps { .. } => Program::SockOps(SockOps { data }),
ProgramSection::SchedClassifier { .. } => {
Program::SchedClassifier(SchedClassifier { data })
Program::SchedClassifier(SchedClassifier {
data,
name: unsafe {
CString::from_vec_unchecked(Vec::from(name.clone()))
.into_boxed_c_str()
},
})
}
ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb {
data,
@ -314,13 +319,11 @@ impl<'a> BpfLoader<'a> {
(name, program)
})
.collect();
Ok(Bpf {
maps: maps
.drain(..)
.map(|map| (map.obj.name.clone(), MapLock::new(map)))
.collect(),
programs,
})
let maps = maps
.drain()
.map(|(name, map)| (name, MapLock::new(map)))
.collect();
Ok(Bpf { maps, programs })
}
}
@ -468,24 +471,16 @@ impl Bpf {
/// For more details on programs and their usage, see the [programs module
/// documentation](crate::programs).
///
/// # Errors
///
/// Returns [`ProgramError::NotFound`] if the program does not exist.
///
/// # Examples
///
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// let program = bpf.program("SSL_read")?;
/// let program = bpf.program("SSL_read").unwrap();
/// println!("program SSL_read is of type {:?}", program.prog_type());
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn program(&self, name: &str) -> Result<&Program, ProgramError> {
self.programs
.get(name)
.ok_or_else(|| ProgramError::NotFound {
name: name.to_owned(),
})
pub fn program(&self, name: &str) -> Option<&Program> {
self.programs.get(name)
}
/// Returns a mutable reference to the program with the given name.
@ -493,10 +488,6 @@ impl Bpf {
/// Used to get a program before loading and attaching it. For more details on programs and
/// their usage, see the [programs module documentation](crate::programs).
///
/// # Errors
///
/// Returns [`ProgramError::NotFound`] if the program does not exist.
///
/// # Examples
///
/// ```no_run
@ -504,17 +495,13 @@ impl Bpf {
/// use aya::programs::UProbe;
/// use std::convert::TryInto;
///
/// let program: &mut UProbe = bpf.program_mut("SSL_read")?.try_into()?;
/// let program: &mut UProbe = bpf.program_mut("SSL_read").unwrap().try_into()?;
/// program.load()?;
/// program.attach(Some("SSL_read"), 0, "libssl", None)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn program_mut(&mut self, name: &str) -> Result<&mut Program, ProgramError> {
self.programs
.get_mut(name)
.ok_or_else(|| ProgramError::NotFound {
name: name.to_owned(),
})
pub fn program_mut(&mut self, name: &str) -> Option<&mut Program> {
self.programs.get_mut(name)
}
/// An iterator over all the programs.
@ -522,17 +509,17 @@ impl Bpf {
/// # Examples
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// for program in bpf.programs() {
/// for (name, program) in bpf.programs() {
/// println!(
/// "found program `{}` of type `{:?}`",
/// program.name(),
/// name,
/// program.prog_type()
/// );
/// }
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn programs(&self) -> impl Iterator<Item = &Program> {
self.programs.values()
pub fn programs(&self) -> impl Iterator<Item = (&str, &Program)> {
self.programs.iter().map(|(s, p)| (s.as_str(), p))
}
/// An iterator mutably referencing all of the programs.
@ -542,13 +529,13 @@ impl Bpf {
/// # use std::path::Path;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// # let pin_path = Path::new("/tmp/pin_path");
/// for program in bpf.programs_mut() {
/// for (_, program) in bpf.programs_mut() {
/// program.pin(pin_path)?;
/// }
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn programs_mut(&mut self) -> impl Iterator<Item = &mut Program> {
self.programs.values_mut()
pub fn programs_mut(&mut self) -> impl Iterator<Item = (&str, &mut Program)> {
self.programs.iter_mut().map(|(s, p)| (s.as_str(), p))
}
}

@ -32,9 +32,9 @@ use crate::{
/// use std::convert::{TryFrom, TryInto};
///
/// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?;
/// let prog_0: &CgroupSkb = bpf.program("example_prog_0")?.try_into()?;
/// let prog_1: &CgroupSkb = bpf.program("example_prog_1")?.try_into()?;
/// let prog_2: &CgroupSkb = bpf.program("example_prog_2")?.try_into()?;
/// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?;
/// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?;
/// let prog_2: &CgroupSkb = bpf.program("example_prog_2").unwrap().try_into()?;
///
/// let flags = 0;
///

@ -158,9 +158,8 @@ mod tests {
use super::*;
fn new_obj_map(name: &str) -> obj::Map {
fn new_obj_map() -> obj::Map {
obj::Map {
name: name.to_string(),
def: bpf_map_def {
map_type: BPF_MAP_TYPE_HASH as u32,
key_size: 4,
@ -180,7 +179,7 @@ mod tests {
#[test]
fn test_wrong_key_size() {
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: None,
pinned: false,
};
@ -196,7 +195,7 @@ mod tests {
#[test]
fn test_wrong_value_size() {
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: None,
pinned: false,
};
@ -213,7 +212,6 @@ mod tests {
fn test_try_from_wrong_map() {
let map = Map {
obj: obj::Map {
name: "TEST".to_string(),
def: bpf_map_def {
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
key_size: 4,
@ -237,7 +235,7 @@ mod tests {
#[test]
fn test_new_not_created() {
let mut map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: None,
pinned: false,
};
@ -251,7 +249,7 @@ mod tests {
#[test]
fn test_new_ok() {
let mut map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -262,7 +260,7 @@ mod tests {
#[test]
fn test_try_from_ok() {
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -273,7 +271,6 @@ mod tests {
fn test_try_from_ok_lru() {
let map = Map {
obj: obj::Map {
name: "TEST".to_string(),
def: bpf_map_def {
map_type: BPF_MAP_TYPE_LRU_HASH as u32,
key_size: 4,
@ -296,7 +293,7 @@ mod tests {
override_syscall(|_| sys_error(EFAULT));
let mut map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -319,7 +316,7 @@ mod tests {
});
let mut map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -333,7 +330,7 @@ mod tests {
override_syscall(|_| sys_error(EFAULT));
let mut map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -356,7 +353,7 @@ mod tests {
});
let mut map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -369,7 +366,7 @@ mod tests {
fn test_get_syscall_error() {
override_syscall(|_| sys_error(EFAULT));
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -391,7 +388,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -430,7 +427,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -474,7 +471,7 @@ mod tests {
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -502,7 +499,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -532,7 +529,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -565,7 +562,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -599,7 +596,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};
@ -639,7 +636,7 @@ mod tests {
_ => sys_error(EFAULT),
});
let map = Map {
obj: new_obj_map("TEST"),
obj: new_obj_map(),
fd: Some(42),
pinned: false,
};

@ -21,7 +21,7 @@
//! use aya::programs::SkMsg;
//!
//! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?;
//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
//! prog.load()?;
//! prog.attach(&intercept_egress)?;
//! # Ok::<(), aya::BpfError>(())
@ -79,8 +79,8 @@ pub enum MapError {
#[error("invalid map path `{error}`")]
InvalidPinPath { error: String },
#[error("the map `{name}` has not been created")]
NotCreated { name: String },
#[error("the map has not been created")]
NotCreated,
#[error("the map `{name}` has already been created")]
AlreadyCreated { name: String },
@ -148,18 +148,16 @@ pub struct Map {
}
impl Map {
pub fn create(&mut self) -> Result<RawFd, MapError> {
let name = self.obj.name.clone();
pub fn create(&mut self, name: &str) -> Result<RawFd, MapError> {
if self.fd.is_some() {
return Err(MapError::AlreadyCreated { name });
return Err(MapError::AlreadyCreated { name: name.into() });
}
let c_name =
CString::new(name.clone()).map_err(|_| MapError::InvalidName { name: name.clone() })?;
let c_name = CString::new(name).map_err(|_| MapError::InvalidName { name: name.into() })?;
let fd = bpf_create_map(&c_name, &self.obj.def).map_err(|(code, io_error)| {
MapError::CreateError {
name,
name: name.into(),
code,
io_error,
}
@ -170,12 +168,15 @@ impl Map {
Ok(fd)
}
pub(crate) fn from_pinned<P: AsRef<Path>>(&mut self, path: P) -> Result<RawFd, MapError> {
let name = self.obj.name.clone();
pub(crate) fn from_pinned<P: AsRef<Path>>(
&mut self,
name: &str,
path: P,
) -> Result<RawFd, MapError> {
if self.fd.is_some() {
return Err(MapError::AlreadyCreated { name });
return Err(MapError::AlreadyCreated { name: name.into() });
}
let map_path = path.as_ref().join(self.name());
let map_path = path.as_ref().join(name);
let path_string = match CString::new(map_path.to_str().unwrap()) {
Ok(s) => s,
Err(e) => {
@ -185,7 +186,7 @@ impl Map {
}
};
let fd = bpf_get_object(&path_string).map_err(|(code, io_error)| MapError::PinError {
name,
name: name.into(),
code,
io_error,
})? as RawFd;
@ -195,27 +196,19 @@ impl Map {
Ok(fd)
}
pub fn name(&self) -> &str {
&self.obj.name
}
pub fn map_type(&self) -> Result<bpf_map_type, MapError> {
bpf_map_type::try_from(self.obj.def.map_type)
}
pub(crate) fn fd_or_err(&self) -> Result<RawFd, MapError> {
self.fd.ok_or_else(|| MapError::NotCreated {
name: self.obj.name.clone(),
})
self.fd.ok_or(MapError::NotCreated)
}
pub(crate) fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), MapError> {
pub(crate) fn pin<P: AsRef<Path>>(&mut self, name: &str, path: P) -> Result<(), MapError> {
if self.pinned {
return Err(MapError::AlreadyPinned {
name: self.name().to_string(),
});
return Err(MapError::AlreadyPinned { name: name.into() });
}
let map_path = path.as_ref().join(self.name());
let map_path = path.as_ref().join(name);
let fd = self.fd_or_err()?;
let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| {
MapError::InvalidPinPath {
@ -492,9 +485,8 @@ mod tests {
use super::*;
fn new_obj_map(name: &str) -> obj::Map {
fn new_obj_map() -> obj::Map {
obj::Map {
name: name.to_string(),
def: bpf_map_def {
map_type: BPF_MAP_TYPE_HASH as u32,
key_size: 4,
@ -507,9 +499,9 @@ mod tests {
}
}
fn new_map(name: &str) -> Map {
fn new_map() -> Map {
Map {
obj: new_obj_map(name),
obj: new_obj_map(),
fd: None,
pinned: false,
}
@ -525,18 +517,21 @@ mod tests {
_ => Err((-1, io::Error::from_raw_os_error(EFAULT))),
});
let mut map = new_map("foo");
assert!(matches!(map.create(), Ok(42)));
let mut map = new_map();
assert!(matches!(map.create("foo"), Ok(42)));
assert_eq!(map.fd, Some(42));
assert!(matches!(map.create(), Err(MapError::AlreadyCreated { .. })));
assert!(matches!(
map.create("foo"),
Err(MapError::AlreadyCreated { .. })
));
}
#[test]
fn test_create_failed() {
override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT))));
let mut map = new_map("foo");
let ret = map.create();
let mut map = new_map();
let ret = map.create("foo");
assert!(matches!(ret, Err(MapError::CreateError { .. })));
if let Err(MapError::CreateError {
name,

@ -50,7 +50,7 @@ use crate::{
/// use aya::programs::SkMsg;
///
/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_egress)?;
///

@ -35,7 +35,7 @@ use crate::{
/// use aya::programs::SkSkb;
///
/// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?;
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet")?.try_into()?;
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_ingress)?;
/// # Ok::<(), aya::BpfError>(())

@ -44,7 +44,6 @@ pub struct Object {
#[derive(Debug, Clone)]
pub struct Map {
pub(crate) name: String,
pub(crate) def: bpf_map_def,
pub(crate) section_index: usize,
pub(crate) data: Vec<u8>,
@ -530,7 +529,6 @@ fn parse_map(section: &Section, name: &str) -> Result<Map, ParseError> {
Ok(Map {
section_index: section.index.0,
name: name.to_string(),
def,
data,
})
@ -785,7 +783,6 @@ mod tests {
),
Ok(Map {
section_index: 0,
name,
def: bpf_map_def {
map_type: 1,
key_size: 2,
@ -796,7 +793,7 @@ mod tests {
pinning: PinningType::None,
},
data
}) if name == "foo" && data.is_empty()
}) if data.is_empty()
))
}
@ -813,7 +810,6 @@ mod tests {
),
Ok(Map {
section_index: 0,
name,
def: bpf_map_def {
map_type: _map_type,
key_size: 4,
@ -824,7 +820,7 @@ mod tests {
pinning: PinningType::None,
},
data
}) if name == ".bss" && data == map_data && value_size == map_data.len() as u32
}) if data == map_data && value_size == map_data.len() as u32
))
}

@ -61,10 +61,12 @@ pub(crate) struct Symbol {
}
impl Object {
pub fn relocate_maps(&mut self, maps: &[Map]) -> Result<(), BpfError> {
pub fn relocate_maps<'a>(
&'a mut self,
maps: impl Iterator<Item = (&'a str, &'a Map)>,
) -> Result<(), BpfError> {
let maps_by_section = maps
.iter()
.map(|map| (map.obj.section_index, map))
.map(|(name, map)| (map.obj.section_index, (name, map)))
.collect::<HashMap<_, _>>();
let functions = self
@ -110,7 +112,7 @@ impl Object {
fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
fun: &mut Function,
relocations: I,
maps_by_section: &HashMap<usize, &Map>,
maps_by_section: &HashMap<usize, (&str, &Map)>,
symbol_table: &HashMap<usize, Symbol>,
) -> Result<(), RelocationError> {
let section_offset = fun.section_offset;
@ -152,7 +154,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
None => continue,
};
let map =
let (name, map) =
maps_by_section
.get(&section_index.0)
.ok_or(RelocationError::SectionNotFound {
@ -162,7 +164,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
})?;
let map_fd = map.fd.ok_or_else(|| RelocationError::MapNotCreated {
name: map.obj.name.clone(),
name: (*name).into(),
section_index: section_index.0,
})?;

@ -43,7 +43,7 @@ use super::FdLink;
/// use aya::programs::{CgroupSkb, CgroupSkbAttachType};
///
/// let file = File::open("/sys/fs/cgroup/unified")?;
/// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter")?.try_into()?;
/// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter").unwrap().try_into()?;
/// egress.load()?;
/// egress.attach(file, CgroupSkbAttachType::Egress)?;
/// # Ok::<(), Error>(())
@ -63,11 +63,6 @@ impl CgroupSkb {
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

@ -30,7 +30,7 @@ use crate::{
/// use aya::{Bpf, programs::KProbe};
/// use std::convert::TryInto;
///
/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?;
/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?;
/// program.load()?;
/// program.attach("try_to_wake_up", 0)?;
/// # Ok::<(), aya::BpfError>(())
@ -50,11 +50,6 @@ impl KProbe {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the
/// program is a `kretprobe`.
pub fn kind(&self) -> ProbeKind {

@ -40,7 +40,7 @@ use libc::{close, dup};
///
/// let file = File::open("/dev/lirc0")?;
/// let mut bpf = aya::Bpf::load_file("imon_rsc.o")?;
/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc")?.try_into().unwrap();
/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap();
/// decoder.load()?;
/// decoder.attach(file)?;
/// # Ok::<(), Error>(())
@ -59,11 +59,6 @@ impl LircMode2 {
load_program(BPF_PROG_TYPE_LIRC_MODE2, &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 lirc device.
pub fn attach<T: AsRawFd>(&mut self, lircdev: T) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;

@ -43,7 +43,7 @@ use crate::{
/// use std::convert::TryInto;
///
/// let btf = Btf::from_sys_fs()?;
/// let program: &mut Lsm = bpf.program_mut("lsm_prog")?.try_into()?;
/// let program: &mut Lsm = bpf.program_mut("lsm_prog").unwrap().try_into()?;
/// program.load("security_bprm_exec", &btf)?;
/// program.attach()?;
/// # Ok::<(), LsmError>(())
@ -83,11 +83,6 @@ impl Lsm {
load_program(BPF_PROG_TYPE_LSM, &mut self.data).map_err(LsmLoadError::from)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Attaches the program.
pub fn attach(&mut self) -> Result<LinkRef, ProgramError> {
attach_btf_id(&mut self.data)

@ -19,7 +19,7 @@
//!
//! let mut bpf = Bpf::load_file("ebpf_programs.o")?;
//! // intercept_wakeups is the name of the program we want to load
//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?;
//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?;
//! program.load()?;
//! // intercept_wakeups will be called every time try_to_wake_up() is called
//! // inside the kernel
@ -95,10 +95,6 @@ use crate::{
/// Error type returned when working with programs.
#[derive(Debug, Error)]
pub enum ProgramError {
/// The program could not be found in the object code.
#[error("program `{name}` not found")]
NotFound { name: String },
/// The program is already loaded.
#[error("the program is already loaded")]
AlreadyLoaded,
@ -240,11 +236,6 @@ impl Program {
}
}
/// Returns the name of the program.
pub fn name(&self) -> &str {
&self.data().name
}
/// Pin the program to the provided path
pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), ProgramError> {
self.data_mut().pin(path)
@ -293,7 +284,6 @@ impl Program {
#[derive(Debug)]
pub(crate) struct ProgramData {
pub(crate) name: String,
pub(crate) obj: obj::Program,
pub(crate) fd: Option<RawFd>,
pub(crate) links: Vec<Rc<RefCell<dyn Link>>>,

@ -66,7 +66,7 @@ pub enum PerfEventScope {
/// perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK, PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy,
/// };
///
/// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock")?.try_into()?;
/// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?;
/// prog.load()?;
///
/// for cpu in online_cpus()? {

@ -26,7 +26,7 @@ use crate::{
/// use aya::{Bpf, programs::RawTracePoint};
/// use std::convert::TryInto;
///
/// let program: &mut RawTracePoint = bpf.program_mut("sys_enter")?.try_into()?;
/// let program: &mut RawTracePoint = bpf.program_mut("sys_enter").unwrap().try_into()?;
/// program.load()?;
/// program.attach("sys_enter")?;
/// # Ok::<(), aya::BpfError>(())
@ -45,11 +45,6 @@ impl RawTracePoint {
load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &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 tracepoint.
pub fn attach(&mut self, tp_name: &str) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;

@ -38,7 +38,7 @@ use crate::{
/// use aya::programs::SkMsg;
///
/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?;
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_egress)?;
///
@ -67,11 +67,6 @@ impl SkMsg {
load_program(BPF_PROG_TYPE_SK_MSG, &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(&mut self, map: &dyn SocketMap) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;

@ -34,7 +34,7 @@ pub enum SkSkbKind {
/// use aya::programs::SkSkb;
///
/// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?;
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet")?.try_into()?;
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(&intercept_ingress)?;
/// # Ok::<(), aya::BpfError>(())
@ -58,11 +58,6 @@ impl SkSkb {
load_program(BPF_PROG_TYPE_SK_SKB, &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 socket map.
pub fn attach(&mut self, map: &dyn SocketMap) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;

@ -36,7 +36,7 @@ use crate::{
/// use aya::programs::SockOps;
///
/// let file = File::open("/sys/fs/cgroup/unified")?;
/// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets")?.try_into()?;
/// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(file)?;
/// # Ok::<(), Error>(())
@ -54,11 +54,6 @@ impl SockOps {
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 cgroup.
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;

@ -51,7 +51,7 @@ pub enum SocketFilterError {
/// use aya::programs::SocketFilter;
///
/// let mut client = TcpStream::connect("127.0.0.1:1234")?;
/// let prog: &mut SocketFilter = bpf.program_mut("filter_packets")?.try_into()?;
/// let prog: &mut SocketFilter = bpf.program_mut("filter_packets").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach(client.as_raw_fd())?;
/// # Ok::<(), Error>(())

@ -1,7 +1,11 @@
//! Network traffic control programs.
use thiserror::Error;
use std::{ffi::CString, io, os::unix::io::RawFd};
use std::{
ffi::{CStr, CString},
io,
os::unix::io::RawFd,
};
use crate::{
generated::{
@ -59,7 +63,7 @@ pub enum TcAttachType {
/// // attached
/// tc::qdisc_add_clsact("eth0")?;
///
/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress")?.try_into()?;
/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach("eth0", TcAttachType::Ingress)?;
///
@ -69,6 +73,7 @@ pub enum TcAttachType {
#[doc(alias = "BPF_PROG_TYPE_SCHED_CLS")]
pub struct SchedClassifier {
pub(crate) data: ProgramData,
pub(crate) name: Box<CStr>,
}
#[derive(Debug, Error)]
@ -108,11 +113,6 @@ impl SchedClassifier {
load_program(BPF_PROG_TYPE_SCHED_CLS, &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 `interface`.
///
/// # Errors
@ -129,9 +129,8 @@ impl SchedClassifier {
let prog_fd = self.data.fd_or_err()?;
let if_index = ifindex_from_ifname(interface)
.map_err(|io_error| TcError::NetlinkError { io_error })?;
let name = CString::new(self.name()).unwrap();
let priority =
unsafe { netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &name) }
unsafe { netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &self.name) }
.map_err(|io_error| TcError::NetlinkError { io_error })?;
Ok(self.data.link(TcLink {
@ -181,13 +180,33 @@ pub fn qdisc_detach_program(
if_name: &str,
attach_type: TcAttachType,
name: &str,
) -> Result<(), io::Error> {
let cstr = CString::new(name)?;
qdisc_detach_program_fast(if_name, attach_type, &cstr)
}
/// Detaches the programs with the given name as a C string.
/// Unlike qdisc_detach_program, this function does not allocate an additional
/// CString to.
///
/// # Errors
///
/// Returns [`io::ErrorKind::NotFound`] to indicate that no programs with the
/// given name were found, so nothing was detached. Other error kinds indicate
/// an actual failure while detaching a program.
fn qdisc_detach_program_fast(
if_name: &str,
attach_type: TcAttachType,
name: &CStr,
) -> Result<(), io::Error> {
let if_index = ifindex_from_ifname(if_name)? as i32;
let c_name = CString::new(name).unwrap();
let prios = unsafe { netlink_find_filter_with_name(if_index, attach_type, &c_name)? };
let prios = unsafe { netlink_find_filter_with_name(if_index, attach_type, name)? };
if prios.is_empty() {
return Err(io::Error::new(io::ErrorKind::NotFound, name.to_string()));
return Err(io::Error::new(
io::ErrorKind::NotFound,
name.to_string_lossy(),
));
}
for prio in prios {

@ -40,7 +40,7 @@ use crate::{
/// use std::convert::TryInto;
///
/// let btf = Btf::from_sys_fs()?;
/// let program: &mut BtfTracePoint = bpf.program_mut("sched_process_fork")?.try_into()?;
/// let program: &mut BtfTracePoint = bpf.program_mut("sched_process_fork").unwrap().try_into()?;
/// program.load("sched_process_fork", &btf)?;
/// program.attach()?;
/// # Ok::<(), Error>(())
@ -81,11 +81,6 @@ impl BtfTracePoint {
load_program(BPF_PROG_TYPE_TRACING, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Attaches the program.
pub fn attach(&mut self) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;

@ -44,7 +44,7 @@ pub enum TracePointError {
/// use std::convert::TryInto;
/// use aya::programs::TracePoint;
///
/// let prog: &mut TracePoint = bpf.program_mut("trace_context_switch")?.try_into()?;
/// let prog: &mut TracePoint = bpf.program_mut("trace_context_switch").unwrap().try_into()?;
/// prog.load()?;
/// prog.attach("sched", "sched_switch")?;
/// # Ok::<(), Error>(())

@ -52,11 +52,6 @@ impl UProbe {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the
/// program is a `uretprobe`.
pub fn kind(&self) -> ProbeKind {

@ -57,7 +57,7 @@ bitflags! {
/// use aya::{Bpf, programs::{Xdp, XdpFlags}};
/// use std::convert::TryInto;
///
/// let program: &mut Xdp = bpf.program_mut("intercept_packets")?.try_into()?;
/// let program: &mut Xdp = bpf.program_mut("intercept_packets").unwrap().try_into()?;
/// program.attach("eth0", XdpFlags::default())?;
/// # Ok::<(), aya::BpfError>(())
/// ```
@ -75,11 +75,6 @@ impl Xdp {
load_program(BPF_PROG_TYPE_XDP, &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 `interface`.
///
/// # Errors

Loading…
Cancel
Save