aya: Update XDP maps implementations

Map impls changed since this was first written.

Fixes: 2b726c8 ("aya: Implement XDP Map Types")
reviewable/pr527/r16
Tuetuopay 1 year ago
parent e90d521a21
commit ede3e91014

@ -707,6 +707,10 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> {
BPF_MAP_TYPE_STACK => Map::Stack(map), BPF_MAP_TYPE_STACK => Map::Stack(map),
BPF_MAP_TYPE_STACK_TRACE => Map::StackTraceMap(map), BPF_MAP_TYPE_STACK_TRACE => Map::StackTraceMap(map),
BPF_MAP_TYPE_QUEUE => Map::Queue(map), BPF_MAP_TYPE_QUEUE => Map::Queue(map),
BPF_MAP_TYPE_CPUMAP => Map::CpuMap(map),
BPF_MAP_TYPE_DEVMAP => Map::DevMap(map),
BPF_MAP_TYPE_DEVMAP_HASH => Map::DevMapHash(map),
BPF_MAP_TYPE_XSKMAP => Map::XskMap(map),
m => { m => {
warn!("The map {name} is of type {:#?} which is currently unsupported in Aya, use `allow_unsupported_maps()` to load it anyways", m); warn!("The map {name} is of type {:#?} which is currently unsupported in Aya, use `allow_unsupported_maps()` to load it anyways", m);
Map::Unsupported(map) Map::Unsupported(map)

@ -97,7 +97,7 @@ pub use queue::Queue;
pub use sock::{SockHash, SockMap}; pub use sock::{SockHash, SockMap};
pub use stack::Stack; pub use stack::Stack;
pub use stack_trace::StackTraceMap; pub use stack_trace::StackTraceMap;
pub use xdp::XskMap; pub use xdp::{CpuMap, DevMap, DevMapHash, XskMap};
#[derive(Error, Debug)] #[derive(Error, Debug)]
/// Errors occuring from working with Maps /// Errors occuring from working with Maps
@ -267,6 +267,14 @@ pub enum Map {
StackTraceMap(MapData), StackTraceMap(MapData),
/// A [`Queue`] map /// A [`Queue`] map
Queue(MapData), Queue(MapData),
/// A [`CpuMap`] map
CpuMap(MapData),
/// A [`DevMap`] map
DevMap(MapData),
/// A [`DevMapHash`] map
DevMapHash(MapData),
/// A [`XskMap`] map
XskMap(MapData),
/// An unsupported map type /// An unsupported map type
Unsupported(MapData), Unsupported(MapData),
} }
@ -290,6 +298,10 @@ impl Map {
Self::Stack(map) => map.obj.map_type(), Self::Stack(map) => map.obj.map_type(),
Self::StackTraceMap(map) => map.obj.map_type(), Self::StackTraceMap(map) => map.obj.map_type(),
Self::Queue(map) => map.obj.map_type(), Self::Queue(map) => map.obj.map_type(),
Self::CpuMap(map) => map.obj.map_type(),
Self::DevMap(map) => map.obj.map_type(),
Self::DevMapHash(map) => map.obj.map_type(),
Self::XskMap(map) => map.obj.map_type(),
Self::Unsupported(map) => map.obj.map_type(), Self::Unsupported(map) => map.obj.map_type(),
} }
} }
@ -349,6 +361,10 @@ impl_try_from_map!(() {
SockMap, SockMap,
PerfEventArray, PerfEventArray,
StackTraceMap, StackTraceMap,
CpuMap,
DevMap,
DevMapHash,
XskMap,
}); });
#[cfg(any(feature = "async_tokio", feature = "async_std"))] #[cfg(any(feature = "async_tokio", feature = "async_std"))]

@ -1,15 +1,10 @@
//! An array of available CPUs. //! An array of available CPUs.
use std::{ use std::borrow::{Borrow, BorrowMut};
convert::TryFrom,
mem,
ops::{Deref, DerefMut},
};
use crate::{ use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_CPUMAP, maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError},
maps::{Map, MapError, MapRef, MapRefMut}, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError},
sys::bpf_map_update_elem,
}; };
/// An array of available CPUs. /// An array of available CPUs.
@ -19,15 +14,18 @@ use crate::{
/// ///
/// # Minimum kernel version /// # Minimum kernel version
/// ///
/// The minimum kernel version required to use this feature is 4.2. /// The minimum kernel version required to use this feature is 4.15.
/// ///
/// # Examples /// # Examples
/// ```no_run /// ```no_run
/// # let bpf = aya::Bpf::load(&[])?; /// # let elf_bytes = &[];
/// use aya::maps::xdp::CpuMap; /// use aya::maps::xdp::CpuMap;
/// use std::convert::{TryFrom, TryInto};
/// ///
/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS")?)?; /// let mut bpf = aya::BpfLoader::new()
/// .set_max_entries("CPUS", aya::util::nr_cpus().unwrap() as u32)
/// .load(elf_bytes)
/// .unwrap();
/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS").unwrap())?;
/// let flags = 0; /// let flags = 0;
/// let queue_size = 2048; /// let queue_size = 2048;
/// for i in 0u32..8u32 { /// for i in 0u32..8u32 {
@ -37,52 +35,51 @@ use crate::{
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_CPUMAP")] #[doc(alias = "BPF_MAP_TYPE_CPUMAP")]
pub struct CpuMap<T: Deref<Target = Map>> { pub struct CpuMap<T> {
inner: T, inner: T,
} }
impl<T: Deref<Target = Map>> CpuMap<T> { impl<T: Borrow<MapData>> CpuMap<T> {
fn new(map: T) -> Result<CpuMap<T>, MapError> { pub(crate) fn new(map: T) -> Result<Self, MapError> {
let map_type = map.obj.def.map_type; let data = map.borrow();
if map_type != BPF_MAP_TYPE_CPUMAP as u32 { check_kv_size::<u32, u32>(data)?;
return Err(MapError::InvalidMapType {
map_type: map_type as u32,
});
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.key_size as usize;
if size != expected {
return Err(MapError::InvalidKeySize { size, expected });
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.value_size as usize;
if size != expected {
return Err(MapError::InvalidValueSize { size, expected });
}
let _fd = map.fd_or_err()?;
Ok(CpuMap { inner: map }) Ok(Self { inner: map })
} }
/// Returns the number of elements in the array. /// Returns the number of elements in the array.
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.obj.def.max_entries self.inner.borrow().obj.max_entries()
} }
fn check_bounds(&self, index: u32) -> Result<(), MapError> { /// Returns the value stored at the given index.
let max_entries = self.inner.obj.def.max_entries; ///
if index >= self.inner.obj.def.max_entries { /// # Errors
Err(MapError::OutOfBounds { index, max_entries }) ///
} else { /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
Ok(()) /// if `bpf_map_lookup_elem` fails.
pub fn get(&self, index: u32, flags: u64) -> Result<u32, MapError> {
let data = self.inner.borrow();
check_bounds(data, index)?;
let fd = data.fd().as_fd();
let value =
bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
} }
/// An iterator over the elements of the map.
pub fn iter(&self) -> impl Iterator<Item = Result<u32, MapError>> + '_ {
(0..self.len()).map(move |i| self.get(i, 0))
} }
} }
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> CpuMap<T> { impl<T: BorrowMut<MapData>> CpuMap<T> {
/// Sets the value of the element at the given index. /// Sets the value of the element at the given index.
/// ///
/// # Errors /// # Errors
@ -90,12 +87,12 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> CpuMap<T> {
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_update_elem` fails. /// if `bpf_map_update_elem` fails.
pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let data = self.inner.borrow_mut();
self.check_bounds(index)?; check_bounds(data, index)?;
bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { let fd = data.fd().as_fd();
MapError::SyscallError { bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| {
call: "bpf_map_update_elem".to_owned(), SyscallError {
code, call: "bpf_map_update_elem",
io_error, io_error,
} }
})?; })?;
@ -103,18 +100,12 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> CpuMap<T> {
} }
} }
impl TryFrom<MapRef> for CpuMap<MapRef> { impl<T: Borrow<MapData>> IterableMap<u32, u32> for CpuMap<T> {
type Error = MapError; fn map(&self) -> &MapData {
self.inner.borrow()
fn try_from(a: MapRef) -> Result<CpuMap<MapRef>, MapError> {
CpuMap::new(a)
} }
}
impl TryFrom<MapRefMut> for CpuMap<MapRefMut> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<CpuMap<MapRefMut>, MapError> { fn get(&self, key: &u32) -> Result<u32, MapError> {
CpuMap::new(a) self.get(*key, 0)
} }
} }

@ -1,15 +1,10 @@
//! An array of network devices. //! An array of network devices.
use std::{ use std::borrow::{Borrow, BorrowMut};
convert::TryFrom,
mem,
ops::{Deref, DerefMut},
};
use crate::{ use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP, maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError},
maps::{Map, MapError, MapRef, MapRefMut}, sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError},
sys::bpf_map_update_elem,
}; };
/// An array of network devices. /// An array of network devices.
@ -19,67 +14,66 @@ use crate::{
/// ///
/// # Minimum kernel version /// # Minimum kernel version
/// ///
/// The minimum kernel version required to use this feature is 4.2. /// The minimum kernel version required to use this feature is 4.14.
/// ///
/// # Examples /// # Examples
/// ```no_run /// ```no_run
/// # let bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::xdp::DevMap; /// use aya::maps::xdp::DevMap;
/// use std::convert::{TryFrom, TryInto};
/// ///
/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES")?)?; /// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?;
/// let ifindex = 32u32; /// let source = 32u32;
/// devmap.set(ifindex, ifindex, 0); /// let dest = 42u32;
/// devmap.set(source, dest, 0);
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_DEVMAP")] #[doc(alias = "BPF_MAP_TYPE_DEVMAP")]
pub struct DevMap<T: Deref<Target = Map>> { pub struct DevMap<T> {
inner: T, inner: T,
} }
impl<T: Deref<Target = Map>> DevMap<T> { impl<T: Borrow<MapData>> DevMap<T> {
fn new(map: T) -> Result<DevMap<T>, MapError> { pub(crate) fn new(map: T) -> Result<Self, MapError> {
let map_type = map.obj.def.map_type; let data = map.borrow();
if map_type != BPF_MAP_TYPE_DEVMAP as u32 { check_kv_size::<u32, u32>(data)?;
return Err(MapError::InvalidMapType {
map_type: map_type as u32,
});
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.key_size as usize;
if size != expected {
return Err(MapError::InvalidKeySize { size, expected });
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.value_size as usize;
if size != expected {
return Err(MapError::InvalidValueSize { size, expected });
}
let _fd = map.fd_or_err()?;
Ok(DevMap { inner: map }) Ok(Self { inner: map })
} }
/// Returns the number of elements in the array. /// Returns the number of elements in the array.
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.obj.def.max_entries self.inner.borrow().obj.max_entries()
} }
fn check_bounds(&self, index: u32) -> Result<(), MapError> { /// Returns the value stored at the given index.
let max_entries = self.inner.obj.def.max_entries; ///
if index >= self.inner.obj.def.max_entries { /// # Errors
Err(MapError::OutOfBounds { index, max_entries }) ///
} else { /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
Ok(()) /// if `bpf_map_lookup_elem` fails.
pub fn get(&self, index: u32, flags: u64) -> Result<u32, MapError> {
let data = self.inner.borrow();
check_bounds(data, index)?;
let fd = data.fd().as_fd();
let value =
bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
} }
/// An iterator over the elements of the array.
pub fn iter(&self) -> impl Iterator<Item = Result<u32, MapError>> + '_ {
(0..self.len()).map(move |i| self.get(i, 0))
} }
} }
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> DevMap<T> { impl<T: BorrowMut<MapData>> DevMap<T> {
/// Sets the value of the element at the given index. /// Sets the value of the element at the given index.
/// ///
/// # Errors /// # Errors
@ -87,12 +81,12 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> DevMap<T> {
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_update_elem` fails. /// if `bpf_map_update_elem` fails.
pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let data = self.inner.borrow_mut();
self.check_bounds(index)?; check_bounds(data, index)?;
bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| { let fd = data.fd().as_fd();
MapError::SyscallError { bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| {
call: "bpf_map_update_elem".to_owned(), SyscallError {
code, call: "bpf_map_update_elem",
io_error, io_error,
} }
})?; })?;
@ -100,18 +94,12 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> DevMap<T> {
} }
} }
impl TryFrom<MapRef> for DevMap<MapRef> { impl<T: Borrow<MapData>> IterableMap<u32, u32> for DevMap<T> {
type Error = MapError; fn map(&self) -> &MapData {
self.inner.borrow()
fn try_from(a: MapRef) -> Result<DevMap<MapRef>, MapError> {
DevMap::new(a)
} }
}
impl TryFrom<MapRefMut> for DevMap<MapRefMut> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<DevMap<MapRefMut>, MapError> { fn get(&self, key: &u32) -> Result<u32, MapError> {
DevMap::new(a) self.get(*key, 0)
} }
} }

@ -1,118 +1,99 @@
//! An array of network devices. //! An hashmap of network devices.
use std::{ use std::borrow::{Borrow, BorrowMut};
convert::TryFrom,
mem,
ops::{Deref, DerefMut},
};
use crate::{ use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH, maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys},
maps::{Map, MapError, MapRef, MapRefMut}, sys::{bpf_map_lookup_elem, SyscallError},
sys::bpf_map_update_elem,
}; };
/// An array of network devices. /// An hashmap of network devices.
/// ///
/// XDP programs can use this map to redirect to other network /// XDP programs can use this map to redirect to other network
/// devices. /// devices.
/// ///
/// # Minimum kernel version /// # Minimum kernel version
/// ///
/// The minimum kernel version required to use this feature is 4.2. /// The minimum kernel version required to use this feature is 5.4.
/// ///
/// # Examples /// # Examples
/// ```no_run /// ```no_run
/// # let bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::xdp::DevMapHash; /// use aya::maps::xdp::DevMapHash;
/// use std::convert::{TryFrom, TryInto};
/// ///
/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES")?)?; /// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?;
/// let flags = 0; /// let flags = 0;
/// let ifindex = 32u32; /// let ifindex = 32u32;
/// devmap.set(ifindex, ifindex, flags); /// devmap.insert(ifindex, ifindex, flags);
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] #[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")]
pub struct DevMapHash<T: Deref<Target = Map>> { pub struct DevMapHash<T> {
inner: T, inner: T,
} }
impl<T: Deref<Target = Map>> DevMapHash<T> { impl<T: Borrow<MapData>> DevMapHash<T> {
fn new(map: T) -> Result<DevMapHash<T>, MapError> { pub(crate) fn new(map: T) -> Result<Self, MapError> {
let map_type = map.obj.def.map_type; let data = map.borrow();
if map_type != BPF_MAP_TYPE_DEVMAP_HASH as u32 { check_kv_size::<u32, u32>(data)?;
return Err(MapError::InvalidMapType {
map_type: map_type as u32,
});
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.key_size as usize;
if size != expected {
return Err(MapError::InvalidKeySize { size, expected });
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.value_size as usize;
if size != expected {
return Err(MapError::InvalidValueSize { size, expected });
}
let _fd = map.fd_or_err()?;
Ok(DevMapHash { inner: map }) Ok(Self { inner: map })
} }
/// Returns the number of elements in the array. /// Returns the value stored at the given index.
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// # Errors
pub fn len(&self) -> u32 { ///
self.inner.obj.def.max_entries /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_lookup_elem` fails.
pub fn get(&self, index: u32, flags: u64) -> Result<u32, MapError> {
let fd = self.inner.borrow().fd().as_fd();
let value =
bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
} }
fn check_bounds(&self, index: u32) -> Result<(), MapError> { /// An iterator over the elements of the devmap in arbitrary order.
let max_entries = self.inner.obj.def.max_entries; pub fn iter(&self) -> MapIter<'_, u32, u32, Self> {
if index >= self.inner.obj.def.max_entries { MapIter::new(self)
Err(MapError::OutOfBounds { index, max_entries })
} else {
Ok(())
} }
/// An iterator visiting all keys in arbitrary order.
pub fn keys(&self) -> MapKeys<'_, u32> {
MapKeys::new(self.inner.borrow())
} }
} }
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> DevMapHash<T> { impl<T: BorrowMut<MapData>> DevMapHash<T> {
/// Sets the value of the element at the given index. /// Inserts a value in the map.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
/// if `bpf_map_update_elem` fails. pub fn insert(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> {
pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { hash_map::insert(self.inner.borrow_mut(), &index, &value, flags)
let fd = self.inner.fd_or_err()?;
self.check_bounds(index)?;
bpf_map_update_elem(fd, &index, &value, flags).map_err(|(code, io_error)| {
MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
code,
io_error,
}
})?;
Ok(())
}
} }
impl TryFrom<MapRef> for DevMapHash<MapRef> { /// Remove a value from the map.
type Error = MapError; ///
/// # Errors
fn try_from(a: MapRef) -> Result<DevMapHash<MapRef>, MapError> { ///
DevMapHash::new(a) /// Returns [`MapError::SyscallError`] if `bpf_map_delete_elem` fails.
pub fn remove(&mut self, key: u32) -> Result<(), MapError> {
hash_map::remove(self.inner.borrow_mut(), &key)
} }
} }
impl TryFrom<MapRefMut> for DevMapHash<MapRefMut> { impl<T: Borrow<MapData>> IterableMap<u32, u32> for DevMapHash<T> {
type Error = MapError; fn map(&self) -> &MapData {
self.inner.borrow()
}
fn try_from(a: MapRefMut) -> Result<DevMapHash<MapRefMut>, MapError> { fn get(&self, key: &u32) -> Result<u32, MapError> {
DevMapHash::new(a) self.get(*key, 0)
} }
} }

@ -1,16 +1,13 @@
//! An array of AF_XDP sockets. //! An array of AF_XDP sockets.
use std::{ use std::{
convert::TryFrom, borrow::{Borrow, BorrowMut},
mem, os::fd::{AsFd, AsRawFd, RawFd},
ops::{Deref, DerefMut},
os::unix::prelude::{AsRawFd, RawFd},
}; };
use crate::{ use crate::{
generated::bpf_map_type::BPF_MAP_TYPE_XSKMAP, maps::{check_bounds, check_kv_size, MapData, MapError},
maps::{Map, MapError, MapRef, MapRefMut}, sys::{bpf_map_update_elem, SyscallError},
sys::bpf_map_update_elem,
}; };
/// An array of AF_XDP sockets. /// An array of AF_XDP sockets.
@ -20,67 +17,41 @@ use crate::{
/// ///
/// # Minimum kernel version /// # Minimum kernel version
/// ///
/// The minimum kernel version required to use this feature is 4.2. /// The minimum kernel version required to use this feature is 4.18.
/// ///
/// # Examples /// # Examples
/// ```no_run /// ```no_run
/// # let bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// # let socket_fd = 1; /// # let socket_fd = 1;
/// use aya::maps::XskMap; /// use aya::maps::XskMap;
/// use std::convert::{TryFrom, TryInto};
/// ///
/// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS")?)?; /// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS").unwrap())?;
/// // socket_fd is the RawFd of an AF_XDP socket /// // socket_fd is the RawFd of an AF_XDP socket
/// xskmap.set(0, socket_fd, 0); /// xskmap.set(0, socket_fd, 0);
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_XSKMAP")] #[doc(alias = "BPF_MAP_TYPE_XSKMAP")]
pub struct XskMap<T: Deref<Target = Map>> { pub struct XskMap<T> {
inner: T, inner: T,
} }
impl<T: Deref<Target = Map>> XskMap<T> { impl<T: Borrow<MapData>> XskMap<T> {
fn new(map: T) -> Result<XskMap<T>, MapError> { pub(crate) fn new(map: T) -> Result<Self, MapError> {
let map_type = map.obj.def.map_type; let data = map.borrow();
if map_type != BPF_MAP_TYPE_XSKMAP as u32 { check_kv_size::<u32, RawFd>(data)?;
return Err(MapError::InvalidMapType {
map_type: map_type as u32,
});
}
let expected = mem::size_of::<u32>();
let size = map.obj.def.key_size as usize;
if size != expected {
return Err(MapError::InvalidKeySize { size, expected });
}
let expected = mem::size_of::<RawFd>();
let size = map.obj.def.value_size as usize;
if size != expected {
return Err(MapError::InvalidValueSize { size, expected });
}
let _fd = map.fd_or_err()?;
Ok(XskMap { inner: map }) Ok(Self { inner: map })
} }
/// Returns the number of elements in the array. /// Returns the number of elements in the array.
/// ///
/// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
self.inner.obj.def.max_entries self.inner.borrow().obj.max_entries()
}
fn check_bounds(&self, index: u32) -> Result<(), MapError> {
let max_entries = self.inner.obj.def.max_entries;
if index >= self.inner.obj.def.max_entries {
Err(MapError::OutOfBounds { index, max_entries })
} else {
Ok(())
}
} }
} }
impl<T: Deref<Target = Map> + DerefMut<Target = Map>> XskMap<T> { impl<T: BorrowMut<MapData>> XskMap<T> {
/// Sets the value of the element at the given index. /// Sets the value of the element at the given index.
/// ///
/// # Errors /// # Errors
@ -88,31 +59,15 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> XskMap<T> {
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_update_elem` fails. /// if `bpf_map_update_elem` fails.
pub fn set<V: AsRawFd>(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { pub fn set<V: AsRawFd>(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.fd_or_err()?; let data = self.inner.borrow_mut();
self.check_bounds(index)?; check_bounds(data, index)?;
bpf_map_update_elem(fd, &index, &value.as_raw_fd(), flags).map_err( let fd = data.fd().as_fd();
|(code, io_error)| MapError::SyscallError { bpf_map_update_elem(fd, Some(&index), &value.as_raw_fd(), flags).map_err(
call: "bpf_map_update_elem".to_owned(), |(_, io_error)| SyscallError {
code, call: "bpf_map_update_elem",
io_error, io_error,
}, },
)?; )?;
Ok(()) Ok(())
} }
} }
impl TryFrom<MapRef> for XskMap<MapRef> {
type Error = MapError;
fn try_from(a: MapRef) -> Result<XskMap<MapRef>, MapError> {
XskMap::new(a)
}
}
impl TryFrom<MapRefMut> for XskMap<MapRefMut> {
type Error = MapError;
fn try_from(a: MapRefMut) -> Result<XskMap<MapRefMut>, MapError> {
XskMap::new(a)
}
}

Loading…
Cancel
Save