浏览代码

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

aya: eliminate name duplication in maps and programs.
Alessandro Decina 3 年之前
父节点
当前提交
07a6016ebb

+ 36 - 49
aya/src/bpf.rs

@@ -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))
     }
 }
 

+ 3 - 3
aya/src/maps/array/program_array.rs

@@ -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;
 ///

+ 19 - 22
aya/src/maps/hash_map/hash_map.rs

@@ -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,
         };

+ 30 - 35
aya/src/maps/mod.rs

@@ -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,

+ 1 - 1
aya/src/maps/sock/sock_hash.rs

@@ -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)?;
 ///

+ 1 - 1
aya/src/maps/sock/sock_map.rs

@@ -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>(())

+ 2 - 6
aya/src/obj/mod.rs

@@ -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
         ))
     }
 

+ 8 - 6
aya/src/obj/relocation.rs

@@ -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,
         })?;
 

+ 1 - 6
aya/src/programs/cgroup_skb.rs

@@ -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

+ 1 - 6
aya/src/programs/kprobe.rs

@@ -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 {

+ 1 - 6
aya/src/programs/lirc_mode2.rs

@@ -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()?;

+ 1 - 6
aya/src/programs/lsm.rs

@@ -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)

+ 1 - 11
aya/src/programs/mod.rs

@@ -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>>>,

+ 1 - 1
aya/src/programs/perf_event.rs

@@ -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()? {

+ 1 - 6
aya/src/programs/raw_trace_point.rs

@@ -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()?;

+ 1 - 6
aya/src/programs/sk_msg.rs

@@ -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()?;

+ 1 - 6
aya/src/programs/sk_skb.rs

@@ -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()?;

+ 1 - 6
aya/src/programs/sock_ops.rs

@@ -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()?;

+ 1 - 1
aya/src/programs/socket_filter.rs

@@ -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>(())

+ 31 - 12
aya/src/programs/tc.rs

@@ -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 {

+ 1 - 6
aya/src/programs/tp_btf.rs

@@ -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()?;

+ 1 - 1
aya/src/programs/trace_point.rs

@@ -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>(())

+ 0 - 5
aya/src/programs/uprobe.rs

@@ -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 {

+ 1 - 6
aya/src/programs/xdp.rs

@@ -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