From e84cd73fa337b4374edfd2e8dce5906ed2fe0043 Mon Sep 17 00:00:00 2001 From: astoycos Date: Fri, 8 Sep 2023 14:22:21 -0400 Subject: [PATCH] aya/maps: add name to mapdata Add a name field to mapdata to make the workflow a bit simplier. Signed-off-by: astoycos --- aya/src/maps/mod.rs | 38 ++++++++++++++++++++++++++++++++------ aya/src/programs/mod.rs | 14 ++------------ aya/src/util.rs | 12 ++++++++++++ 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 4d8183e9..45b817f3 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -59,7 +59,7 @@ use crate::{ bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key, bpf_pin_object, SyscallError, }, - util::nr_cpus, + util::{bytes_of_c_char, nr_cpus}, PinningType, Pod, }; @@ -399,6 +399,7 @@ pub struct MapData { pub(crate) fd: RawFd, /// Indicates if this map has been pinned to bpffs pub pinned: bool, + pub(crate) name: String, } impl MapData { @@ -433,6 +434,7 @@ impl MapData { obj, fd, pinned: false, + name: name.to_string(), }) } @@ -463,10 +465,11 @@ impl MapData { obj, fd: fd.into_raw_fd(), pinned: false, + name: name.to_string(), }), Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; - map.pin(name, path).map_err(|error| MapError::PinError { + map.pin(path).map_err(|error| MapError::PinError { name: Some(name.into()), error, })?; @@ -496,10 +499,15 @@ impl MapData { let info = bpf_map_get_info_by_fd(fd.as_fd())?; + let name_bytes = bytes_of_c_char(&info.name); + Ok(Self { obj: parse_map_info(info, PinningType::ByName), fd: fd.into_raw_fd(), pinned: true, + name: std::str::from_utf8(name_bytes) + .expect("unable to parse map name from bpf_map_info") + .to_string(), }) } @@ -511,19 +519,30 @@ impl MapData { pub fn from_fd(fd: OwnedFd) -> Result { let info = bpf_map_get_info_by_fd(fd.as_fd())?; + let name_bytes = bytes_of_c_char(&info.name); Ok(Self { obj: parse_map_info(info, PinningType::None), fd: fd.into_raw_fd(), pinned: false, + name: std::str::from_utf8(name_bytes) + .expect("unable to parse map name from bpf_map_info") + .to_string(), }) } - pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { + pub(crate) fn pin>(&mut self, path: P) -> Result<(), PinError> { use std::os::unix::ffi::OsStrExt as _; - let Self { fd, pinned, obj: _ } = self; + let Self { + fd, + pinned, + obj: _, + name, + } = self; if *pinned { - return Err(PinError::AlreadyPinned { name: name.into() }); + return Err(PinError::AlreadyPinned { + name: name.to_string(), + }); } let path = path.as_ref().join(name); let path_string = CString::new(path.as_os_str().as_bytes()) @@ -555,11 +574,17 @@ impl Drop for MapData { impl Clone for MapData { fn clone(&self) -> Self { - let Self { obj, fd, pinned } = self; + let Self { + obj, + fd, + pinned, + name, + } = self; Self { obj: obj.clone(), fd: unsafe { libc::dup(*fd) }, pinned: *pinned, + name: name.clone(), } } } @@ -797,6 +822,7 @@ mod tests { obj: _, fd: 42, pinned: false + name: "foo".to_string(), }) ); } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 616244e0..a4f68258 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -117,7 +117,7 @@ use crate::{ bpf_prog_query, iter_link_ids, iter_prog_ids, retry_with_verifier_logs, BpfLoadProgramAttrs, SyscallError, }, - util::KernelVersion, + util::{bytes_of_c_char, KernelVersion}, VerifierLogLevel, }; @@ -977,17 +977,7 @@ impl ProgramInfo { /// The name of the program as was provided when it was load. This is limited to 16 bytes pub fn name(&self) -> &[u8] { - let length = self - .0 - .name - .iter() - .rposition(|ch| *ch != 0) - .map(|pos| pos + 1) - .unwrap_or(0); - - // The name field is defined as [std::os::raw::c_char; 16]. c_char may be signed or - // unsigned depending on the platform; that's why we're using from_raw_parts here - unsafe { std::slice::from_raw_parts(self.0.name.as_ptr() as *const _, length) } + bytes_of_c_char(&self.0.name) } /// The name of the program as a &str. If the name was not valid unicode, None is returned. diff --git a/aya/src/util.rs b/aya/src/util.rs index 54c289b0..ef244333 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -337,6 +337,18 @@ pub(crate) fn bytes_of_slice(val: &[T]) -> &[u8] { unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) } } +pub(crate) fn bytes_of_c_char(val: &[std::os::raw::c_char]) -> &[u8] { + let length = val + .iter() + .rposition(|ch| *ch != 0) + .map(|pos| pos + 1) + .unwrap_or(0); + + // The name field is defined as [std::os::raw::c_char; 16]. c_char may be signed or + // unsigned depending on the platform; that's why we're using from_raw_parts here + unsafe { std::slice::from_raw_parts(val.as_ptr() as *const _, length) } +} + #[cfg(test)] mod tests { use super::*;