Add `from_pinned` and `from_fd` methods

Add `from_pinned` to allow loading BPF maps
from pinned points in the bpffs and
`from_fd` to allow loading BPF maps from
RawFds aquired via some other means eg
a unix socket.

These functions return an
aya::Map which has not been used previously
but will be the future abstraction once
all bpf maps are represented as an enum.

Signed-off-by: Andrew Stoycos <astoycos@redhat.com>
pull/387/head
Andrew Stoycos 2 years ago
parent 98e25ca5e6
commit 8a9cbf179f

@ -443,7 +443,7 @@ impl<'a> BpfLoader<'a> {
Err(_) => { Err(_) => {
let fd = map.create(&name)?; let fd = map.create(&name)?;
map.pin(&name, path).map_err(|error| MapError::PinError { map.pin(&name, path).map_err(|error| MapError::PinError {
name: name.to_string(), name: Some(name.to_string()),
error, error,
})?; })?;
fd fd
@ -454,16 +454,14 @@ impl<'a> BpfLoader<'a> {
}; };
if !map.obj.data().is_empty() && map.obj.kind() != MapKind::Bss { if !map.obj.data().is_empty() && map.obj.kind() != MapKind::Bss {
bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0) bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0)
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
})?; })?;
} }
if map.obj.kind() == MapKind::Rodata { if map.obj.kind() == MapKind::Rodata {
bpf_map_freeze(fd).map_err(|(code, io_error)| MapError::SyscallError { bpf_map_freeze(fd).map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_freeze".to_owned(), call: "bpf_map_freeze".to_owned(),
code,
io_error, io_error,
})?; })?;
} }

@ -80,10 +80,9 @@ impl<T: Deref<Target = Map>, V: Pod> Array<T, V> {
self.check_bounds(*index)?; self.check_bounds(*index)?;
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(code, io_error)| { let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -116,10 +115,9 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Array<T, V> {
pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
self.check_bounds(index)?; self.check_bounds(index)?;
bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(code, io_error)| { bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;

@ -99,10 +99,9 @@ impl<T: Deref<Target = Map>, V: Pod> PerCpuArray<T, V> {
self.check_bounds(*index)?; self.check_bounds(*index)?;
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(code, io_error)| { let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -135,10 +134,9 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> PerCpuArray<T, V>
pub fn set(&mut self, index: u32, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
self.check_bounds(index)?; self.check_bounds(index)?;
bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(code, io_error)| { bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;

@ -103,10 +103,9 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
self.check_bounds(index)?; self.check_bounds(index)?;
let prog_fd = program.as_raw_fd(); let prog_fd = program.as_raw_fd();
bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(code, io_error)| { bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -122,9 +121,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
self.check_bounds(*index)?; self.check_bounds(*index)?;
bpf_map_delete_elem(fd, index) bpf_map_delete_elem(fd, index)
.map(|_| ()) .map(|_| ())
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(), call: "bpf_map_delete_elem".to_owned(),
code,
io_error, io_error,
}) })
} }

@ -68,9 +68,8 @@ impl<T: Deref<Target = Map>, V: Pod> BloomFilter<T, V> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags) bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags)
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
})? })?
.ok_or(MapError::ElementNotFound)?; .ok_or(MapError::ElementNotFound)?;
@ -80,12 +79,9 @@ impl<T: Deref<Target = Map>, V: Pod> BloomFilter<T, V> {
/// Inserts a value into the map. /// Inserts a value into the map.
pub fn insert(&self, value: V, flags: u64) -> Result<(), MapError> { pub fn insert(&self, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_push_elem(fd, &value, flags).map_err(|(code, io_error)| { bpf_map_push_elem(fd, &value, flags).map_err(|(_, io_error)| MapError::SyscallError {
MapError::SyscallError {
call: "bpf_map_push_elem".to_owned(), call: "bpf_map_push_elem".to_owned(),
code,
io_error, io_error,
}
})?; })?;
Ok(()) Ok(())
} }
@ -254,7 +250,7 @@ mod tests {
assert!(matches!( assert!(matches!(
bloom_filter.insert(1, 0), bloom_filter.insert(1, 0),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }
@ -292,7 +288,7 @@ mod tests {
assert!(matches!( assert!(matches!(
bloom_filter.contains(&1, 0), bloom_filter.contains(&1, 0),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }

@ -61,10 +61,9 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
/// Returns a copy of the value associated with the key. /// Returns a copy of the value associated with the key.
pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> { pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -313,7 +312,7 @@ mod tests {
assert!(matches!( assert!(matches!(
hm.insert(1, 42, 0), hm.insert(1, 42, 0),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }
@ -352,7 +351,7 @@ mod tests {
assert!(matches!( assert!(matches!(
hm.remove(&1), hm.remove(&1),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }
@ -390,7 +389,7 @@ mod tests {
assert!(matches!( assert!(matches!(
hm.get(&1, 0), hm.get(&1, 0),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }

@ -29,10 +29,9 @@ pub(crate) fn check_kv_size<K, V>(map: &Map) -> Result<(), MapError> {
pub(crate) fn insert<K, V>(map: &mut Map, key: K, value: V, flags: u64) -> Result<(), MapError> { pub(crate) fn insert<K, V>(map: &mut Map, key: K, value: V, flags: u64) -> Result<(), MapError> {
let fd = map.fd_or_err()?; let fd = map.fd_or_err()?;
bpf_map_update_elem(fd, Some(&key), &value, flags).map_err(|(code, io_error)| { bpf_map_update_elem(fd, Some(&key), &value, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -44,9 +43,8 @@ pub(crate) fn remove<K>(map: &mut Map, key: &K) -> Result<(), MapError> {
let fd = map.fd_or_err()?; let fd = map.fd_or_err()?;
bpf_map_delete_elem(fd, key) bpf_map_delete_elem(fd, key)
.map(|_| ()) .map(|_| ())
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(), call: "bpf_map_delete_elem".to_owned(),
code,
io_error, io_error,
}) })
} }

@ -73,10 +73,9 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
/// Returns a slice of values - one for each CPU - associated with the key. /// Returns a slice of values - one for each CPU - associated with the key.
pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> { pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(code, io_error)| { let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -127,10 +126,9 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
/// ``` /// ```
pub fn insert(&mut self, key: K, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> { pub fn insert(&mut self, key: K, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
bpf_map_update_elem_per_cpu(fd, &key, &values, flags).map_err(|(code, io_error)| { bpf_map_update_elem_per_cpu(fd, &key, &values, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;

@ -129,10 +129,9 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie. /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> { pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -142,10 +141,9 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Inserts a key value pair into the map. /// Inserts a key value pair into the map.
pub fn insert(&self, key: &Key<K>, value: V, flags: u64) -> Result<(), MapError> { pub fn insert(&self, key: &Key<K>, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_update_elem(fd, Some(key), &value, flags).map_err(|(code, io_error)| { bpf_map_update_elem(fd, Some(key), &value, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;
@ -160,9 +158,8 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
bpf_map_delete_elem(fd, key) bpf_map_delete_elem(fd, key)
.map(|_| ()) .map(|_| ())
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(), call: "bpf_map_delete_elem".to_owned(),
code,
io_error, io_error,
}) })
} }
@ -360,7 +357,7 @@ mod tests {
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(matches!( assert!(matches!(
trie.insert(&key, 1, 0), trie.insert(&key, 1, 0),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }
@ -402,7 +399,7 @@ mod tests {
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(matches!( assert!(matches!(
trie.remove(&key), trie.remove(&key),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }
@ -443,7 +440,7 @@ mod tests {
assert!(matches!( assert!(matches!(
trie.get(&key, 0), trie.get(&key, 0),
Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
)); ));
} }

@ -50,7 +50,10 @@ use crate::{
generated::bpf_map_type, generated::bpf_map_type,
obj, obj,
pin::PinError, pin::PinError,
sys::{bpf_create_map, bpf_get_object, bpf_map_get_next_key, bpf_pin_object, kernel_version}, sys::{
bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key,
bpf_pin_object, kernel_version,
},
util::nr_cpus, util::nr_cpus,
Pod, Pod,
}; };
@ -163,13 +166,10 @@ pub enum MapError {
ProgramNotLoaded, ProgramNotLoaded,
/// Syscall failed /// Syscall failed
#[error("the `{call}` syscall failed with code {code}")] #[error("the `{call}` syscall failed")]
SyscallError { SyscallError {
/// Syscall Name /// Syscall Name
call: String, call: String,
/// Error code
code: libc::c_long,
#[source]
/// Original io::Error /// Original io::Error
io_error: io::Error, io_error: io::Error,
}, },
@ -189,10 +189,10 @@ pub enum MapError {
}, },
/// Could not pin map by name /// Could not pin map by name
#[error("map `{name}` requested pinning by name. pinning failed")] #[error("map `{name:?}` requested pinning by name. pinning failed")]
PinError { PinError {
/// The map name /// The map name
name: String, name: Option<String>,
/// The reason for the failure /// The reason for the failure
#[source] #[source]
error: PinError, error: PinError,
@ -292,10 +292,8 @@ impl Map {
} }
let map_path = path.as_ref().join(name); let map_path = path.as_ref().join(name);
let path_string = CString::new(map_path.to_str().unwrap()).unwrap(); let path_string = CString::new(map_path.to_str().unwrap()).unwrap();
let fd = let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError {
bpf_get_object(&path_string).map_err(|(code, io_error)| MapError::SyscallError {
call: "BPF_OBJ_GET".to_string(), call: "BPF_OBJ_GET".to_string(),
code,
io_error, io_error,
})? as RawFd; })? as RawFd;
@ -304,6 +302,55 @@ impl Map {
Ok(fd) Ok(fd)
} }
/// Loads a map from a pinned path in bpffs.
pub fn from_pinned<P: AsRef<Path>>(path: P) -> Result<Map, MapError> {
let path_string =
CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| {
MapError::PinError {
name: None,
error: PinError::InvalidPinPath {
error: e.to_string(),
},
}
})?;
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError {
call: "BPF_OBJ_GET".to_owned(),
io_error,
})? as RawFd;
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError {
call: "BPF_MAP_GET_INFO_BY_FD".to_owned(),
io_error,
})?;
Ok(Map {
obj: obj::parse_map_info(info, crate::PinningType::ByName),
fd: Some(fd),
btf_fd: None,
pinned: true,
})
}
/// Loads a map from a [`RawFd`].
///
/// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pinned`].
/// This API is intended for cases where you have received a valid BPF FD from some other means.
/// For example, you received an FD over Unix Domain Socket.
pub fn from_fd(fd: RawFd) -> Result<Map, MapError> {
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError {
call: "BPF_OBJ_GET".to_owned(),
io_error,
})?;
Ok(Map {
obj: obj::parse_map_info(info, crate::PinningType::None),
fd: Some(fd),
btf_fd: None,
pinned: false,
})
}
/// Returns the [`bpf_map_type`] of this map /// Returns the [`bpf_map_type`] of this map
pub fn map_type(&self) -> Result<bpf_map_type, MapError> { pub fn map_type(&self) -> Result<bpf_map_type, MapError> {
bpf_map_type::try_from(self.obj.map_type()) bpf_map_type::try_from(self.obj.map_type())
@ -402,11 +449,10 @@ impl<K: Pod> Iterator for MapKeys<'_, K> {
self.key = None; self.key = None;
None None
} }
Err((code, io_error)) => { Err((_, io_error)) => {
self.err = true; self.err = true;
Some(Err(MapError::SyscallError { Some(Err(MapError::SyscallError {
call: "bpf_map_get_next_key".to_owned(), call: "bpf_map_get_next_key".to_owned(),
code,
io_error, io_error,
})) }))
} }

@ -81,9 +81,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err( let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
|(code, io_error)| MapError::SyscallError { |(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_and_delete_elem".to_owned(), call: "bpf_map_lookup_and_delete_elem".to_owned(),
code,
io_error, io_error,
}, },
)?; )?;
@ -97,12 +96,9 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> { pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
bpf_map_push_elem(fd, &value, flags).map_err(|(code, io_error)| { bpf_map_push_elem(fd, &value, flags).map_err(|(_, io_error)| MapError::SyscallError {
MapError::SyscallError {
call: "bpf_map_push_elem".to_owned(), call: "bpf_map_push_elem".to_owned(),
code,
io_error, io_error,
}
})?; })?;
Ok(()) Ok(())
} }

@ -87,10 +87,9 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
/// Returns the fd of the socket stored at the given key. /// Returns the fd of the socket stored at the given key.
pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> { pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
let fd = self.inner.deref().fd_or_err()?; let fd = self.inner.deref().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;

@ -89,9 +89,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
self.check_bounds(index)?; self.check_bounds(index)?;
bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err( bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
|(code, io_error)| MapError::SyscallError { |(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
}, },
)?; )?;
@ -104,9 +103,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
self.check_bounds(*index)?; self.check_bounds(*index)?;
bpf_map_delete_elem(fd, index) bpf_map_delete_elem(fd, index)
.map(|_| ()) .map(|_| ())
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(), call: "bpf_map_delete_elem".to_owned(),
code,
io_error, io_error,
}) })
} }

@ -81,9 +81,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err( let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
|(code, io_error)| MapError::SyscallError { |(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_and_delete_elem".to_owned(), call: "bpf_map_lookup_and_delete_elem".to_owned(),
code,
io_error, io_error,
}, },
)?; )?;
@ -97,10 +96,9 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> { pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let fd = self.inner.fd_or_err()?;
bpf_map_update_elem(fd, None::<&u32>, &value, flags).map_err(|(code, io_error)| { bpf_map_update_elem(fd, None::<&u32>, &value, flags).map_err(|(_, io_error)| {
MapError::SyscallError { MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(), call: "bpf_map_update_elem".to_owned(),
code,
io_error, io_error,
} }
})?; })?;

@ -86,7 +86,6 @@ impl<T: Deref<Target = Map>> StackTraceMap<T> {
sysctl::<usize>("kernel/perf_event_max_stack").map_err(|io_error| { sysctl::<usize>("kernel/perf_event_max_stack").map_err(|io_error| {
MapError::SyscallError { MapError::SyscallError {
call: "sysctl".to_owned(), call: "sysctl".to_owned(),
code: -1,
io_error, io_error,
} }
})?; })?;
@ -113,9 +112,8 @@ impl<T: Deref<Target = Map>> StackTraceMap<T> {
let mut frames = vec![0; self.max_stack_depth]; let mut frames = vec![0; self.max_stack_depth];
bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags) bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags)
.map_err(|(code, io_error)| MapError::SyscallError { .map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(), call: "bpf_map_lookup_elem".to_owned(),
code,
io_error, io_error,
})? })?
.ok_or(MapError::KeyNotFound)?; .ok_or(MapError::KeyNotFound)?;

@ -19,7 +19,7 @@ use relocation::*;
use crate::{ use crate::{
bpf_map_def, bpf_map_def,
generated::{bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG}, generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
obj::btf::{Btf, BtfError, BtfExt, BtfType}, obj::btf::{Btf, BtfError, BtfExt, BtfType},
programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType}, programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
BpfError, BtfMapDef, PinningType, BpfError, BtfMapDef, PinningType,
@ -1305,6 +1305,45 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe
Ok((map_name.to_string(), map_def)) Ok((map_name.to_string(), map_def))
} }
pub(crate) fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
if info.btf_key_type_id != 0 {
Map::Btf(BtfMap {
def: BtfMapDef {
map_type: info.type_,
key_size: info.key_size,
value_size: info.value_size,
max_entries: info.max_entries,
map_flags: info.map_flags,
pinning: pinned,
btf_key_type_id: info.btf_key_type_id,
btf_value_type_id: info.btf_value_type_id,
},
section_index: 0,
symbol_index: 0,
data: Vec::new(),
// We should never be loading the .bss or .data or .rodata FDs
kind: MapKind::Other,
})
} else {
Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: info.type_,
key_size: info.key_size,
value_size: info.value_size,
max_entries: info.max_entries,
map_flags: info.map_flags,
pinning: pinned,
id: info.id,
},
section_index: 0,
symbol_index: 0,
data: Vec::new(),
// We should never be loading the .bss or .data or .rodata FDs
kind: MapKind::Other,
})
}
}
pub(crate) fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> { pub(crate) fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
if data.len() % mem::size_of::<bpf_insn>() > 0 { if data.len() % mem::size_of::<bpf_insn>() > 0 {
return Err(ParseError::InvalidProgramCode); return Err(ParseError::InvalidProgramCode);

@ -175,7 +175,7 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr
let btf_info = let btf_info =
sys::btf_obj_get_info_by_fd(btf_fd, &mut buf).map_err(|io_error| { sys::btf_obj_get_info_by_fd(btf_fd, &mut buf).map_err(|io_error| {
ProgramError::SyscallError { ProgramError::SyscallError {
call: "btf_obj_get_info_by_fd".to_owned(), call: "bpf_prog_get_info_by_fd".to_owned(),
io_error, io_error,
} }
})?; })?;
@ -185,7 +185,7 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr
} }
} }
Err(io_error) => Err(ProgramError::SyscallError { Err(io_error) => Err(ProgramError::SyscallError {
call: "btf_obj_get_info_by_fd".to_owned(), call: "bpf_prog_get_info_by_fd".to_owned(),
io_error, io_error,
}), }),
}?; }?;

@ -11,8 +11,8 @@ use libc::{c_char, c_long, close, ENOENT, ENOSPC};
use crate::{ use crate::{
generated::{ generated::{
bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_prog_info, bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_map_info,
bpf_prog_type, BPF_F_REPLACE, bpf_prog_info, bpf_prog_type, BPF_F_REPLACE,
}, },
maps::PerCpuValues, maps::PerCpuValues,
obj::{ obj::{
@ -439,14 +439,29 @@ pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> Result<RawFd, io::Error> {
pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_prog_info, io::Error> { pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_prog_info, io::Error> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
// info gets entirely populated by the kernel // info gets entirely populated by the kernel
let info = unsafe { MaybeUninit::zeroed().assume_init() }; let info = MaybeUninit::zeroed();
attr.info.bpf_fd = prog_fd as u32; attr.info.bpf_fd = prog_fd as u32;
attr.info.info = &info as *const _ as u64; attr.info.info = &info as *const _ as u64;
attr.info.info_len = mem::size_of::<bpf_prog_info>() as u32; attr.info.info_len = mem::size_of::<bpf_prog_info>() as u32;
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) { match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
Ok(_) => Ok(info), Ok(_) => Ok(unsafe { info.assume_init() }),
Err((_, err)) => Err(err),
}
}
pub(crate) fn bpf_map_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_map_info, io::Error> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
// info gets entirely populated by the kernel
let info = MaybeUninit::zeroed();
attr.info.bpf_fd = prog_fd as u32;
attr.info.info = info.as_ptr() as *const _ as u64;
attr.info.info_len = mem::size_of::<bpf_map_info>() as u32;
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
Ok(_) => Ok(unsafe { info.assume_init() }),
Err((_, err)) => Err(err), Err((_, err)) => Err(err),
} }
} }

Loading…
Cancel
Save