mirror of https://github.com/aya-rs/aya
maps: add ProgramArray
ProgramArray is a wrapper around BPF_MAP_TYPE_PROG_ARRAY maps. Can be used to setup jump tables for bpf_tail_call().pull/1/head
parent
f7cdd2e059
commit
a41edbca2c
@ -0,0 +1,128 @@
|
|||||||
|
use std::{
|
||||||
|
cell::{Ref, RefMut},
|
||||||
|
convert::TryFrom,
|
||||||
|
mem,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
os::unix::prelude::RawFd,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
generated::bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY,
|
||||||
|
maps::{IterableMap, Map, MapError, MapIter, MapKeys},
|
||||||
|
programs::ProgramFd,
|
||||||
|
syscalls::{
|
||||||
|
bpf_map_delete_elem, bpf_map_lookup_and_delete_elem, bpf_map_lookup_elem,
|
||||||
|
bpf_map_update_elem,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ProgramArray<T: Deref<Target = Map>> {
|
||||||
|
inner: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Deref<Target = Map>> ProgramArray<T> {
|
||||||
|
pub fn new(map: T) -> Result<ProgramArray<T>, MapError> {
|
||||||
|
let inner = map.deref();
|
||||||
|
let map_type = inner.obj.def.map_type;
|
||||||
|
if map_type != BPF_MAP_TYPE_PROG_ARRAY {
|
||||||
|
return Err(MapError::InvalidMapType {
|
||||||
|
map_type: map_type as u32,
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
let expected = mem::size_of::<RawFd>();
|
||||||
|
let size = inner.obj.def.key_size as usize;
|
||||||
|
if size != expected {
|
||||||
|
return Err(MapError::InvalidKeySize { size, expected });
|
||||||
|
}
|
||||||
|
|
||||||
|
let expected = mem::size_of::<RawFd>();
|
||||||
|
let size = inner.obj.def.value_size as usize;
|
||||||
|
if size != expected {
|
||||||
|
return Err(MapError::InvalidValueSize { size, expected });
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ProgramArray { inner: map })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get(&self, key: &u32, flags: u64) -> Result<Option<RawFd>, MapError> {
|
||||||
|
let fd = self.inner.deref().fd_or_err()?;
|
||||||
|
let fd = bpf_map_lookup_elem(fd, key, flags)
|
||||||
|
.map_err(|(code, io_error)| MapError::LookupElementFailed { code, io_error })?;
|
||||||
|
Ok(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn iter<'coll>(&'coll self) -> MapIter<'coll, u32, RawFd> {
|
||||||
|
MapIter::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn keys<'coll>(&'coll self) -> MapKeys<'coll, u32, RawFd> {
|
||||||
|
MapKeys::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_bounds(&self, index: u32) -> Result<(), MapError> {
|
||||||
|
let max_entries = self.inner.deref().obj.def.max_entries;
|
||||||
|
if index >= self.inner.deref().obj.def.max_entries {
|
||||||
|
Err(MapError::OutOfBounds { index, max_entries })
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
|
||||||
|
pub fn insert(
|
||||||
|
&mut self,
|
||||||
|
index: u32,
|
||||||
|
program: &dyn ProgramFd,
|
||||||
|
flags: u64,
|
||||||
|
) -> Result<(), MapError> {
|
||||||
|
let fd = self.inner.deref().fd_or_err()?;
|
||||||
|
self.check_bounds(index)?;
|
||||||
|
let prog_fd = program.fd().ok_or(MapError::ProgramNotLoaded)?;
|
||||||
|
|
||||||
|
bpf_map_update_elem(fd, &index, &prog_fd, flags)
|
||||||
|
.map_err(|(code, io_error)| MapError::UpdateElementFailed { code, io_error })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn pop(&mut self, index: &u32) -> Result<Option<RawFd>, MapError> {
|
||||||
|
let fd = self.inner.deref().fd_or_err()?;
|
||||||
|
self.check_bounds(*index)?;
|
||||||
|
bpf_map_lookup_and_delete_elem(fd, index)
|
||||||
|
.map_err(|(code, io_error)| MapError::LookupAndDeleteElementFailed { code, io_error })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, index: &u32) -> Result<(), MapError> {
|
||||||
|
let fd = self.inner.deref().fd_or_err()?;
|
||||||
|
self.check_bounds(*index)?;
|
||||||
|
bpf_map_delete_elem(fd, index)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(|(code, io_error)| MapError::DeleteElementFailed { code, io_error })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Deref<Target = Map>> IterableMap<u32, RawFd> for ProgramArray<T> {
|
||||||
|
fn fd(&self) -> Result<RawFd, MapError> {
|
||||||
|
self.inner.deref().fd_or_err()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get(&self, index: &u32) -> Result<Option<RawFd>, MapError> {
|
||||||
|
self.get(index, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<Ref<'a, Map>> for ProgramArray<Ref<'a, Map>> {
|
||||||
|
type Error = MapError;
|
||||||
|
|
||||||
|
fn try_from(inner: Ref<'a, Map>) -> Result<ProgramArray<Ref<'a, Map>>, MapError> {
|
||||||
|
ProgramArray::new(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<RefMut<'a, Map>> for ProgramArray<RefMut<'a, Map>> {
|
||||||
|
type Error = MapError;
|
||||||
|
|
||||||
|
fn try_from(inner: RefMut<'a, Map>) -> Result<ProgramArray<RefMut<'a, Map>>, MapError> {
|
||||||
|
ProgramArray::new(inner)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue