From 2cb67eb0df1bae1328a093d74acd416d431d52c0 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Mon, 30 May 2022 11:43:38 +0100 Subject: [PATCH 1/2] aya: Implement XDP Map Types This commit adds implementations for: - xskmap - devmap - devmap_hash - cpumap Which can all be used to redirect XDP packets to various different locations Signed-off-by: Dave Tucker --- aya/src/maps/mod.rs | 2 + aya/src/maps/xdp/cpu_map.rs | 120 +++++++++++++++++++++++++++++++ aya/src/maps/xdp/dev_map.rs | 117 ++++++++++++++++++++++++++++++ aya/src/maps/xdp/dev_map_hash.rs | 118 ++++++++++++++++++++++++++++++ aya/src/maps/xdp/mod.rs | 10 +++ aya/src/maps/xdp/xsk_map.rs | 118 ++++++++++++++++++++++++++++++ 6 files changed, 485 insertions(+) create mode 100644 aya/src/maps/xdp/cpu_map.rs create mode 100644 aya/src/maps/xdp/dev_map.rs create mode 100644 aya/src/maps/xdp/dev_map_hash.rs create mode 100644 aya/src/maps/xdp/mod.rs create mode 100644 aya/src/maps/xdp/xsk_map.rs diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 81a0ec357..609a630e3 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -56,6 +56,7 @@ pub mod queue; pub mod sock; pub mod stack; pub mod stack_trace; +pub mod xdp; pub use array::{Array, PerCpuArray, ProgramArray}; pub use hash_map::{HashMap, PerCpuHashMap}; @@ -65,6 +66,7 @@ pub use queue::Queue; pub use sock::{SockHash, SockMap}; pub use stack::Stack; pub use stack_trace::StackTraceMap; +pub use xdp::XskMap; #[derive(Error, Debug)] /// Errors occuring from working with Maps diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs new file mode 100644 index 000000000..2b6ba3cb5 --- /dev/null +++ b/aya/src/maps/xdp/cpu_map.rs @@ -0,0 +1,120 @@ +//! An array of available CPUs. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_CPUMAP, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of available CPUs. +/// +/// XDP programs can use this map to redirect packets to a target +/// CPU for processing. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::CpuMap; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS")?)?; +/// let flags = 0; +/// let queue_size = 2048; +/// for i in 0u32..8u32 { +/// cpumap.set(i, queue_size, flags); +/// } +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_CPUMAP")] +pub struct CpuMap> { + inner: T, +} + +impl> CpuMap { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_CPUMAP as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + 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 }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.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 + DerefMut> CpuMap { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + 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 for CpuMap { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + CpuMap::new(a) + } +} + +impl TryFrom for CpuMap { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + CpuMap::new(a) + } +} diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs new file mode 100644 index 000000000..365a5b1e0 --- /dev/null +++ b/aya/src/maps/xdp/dev_map.rs @@ -0,0 +1,117 @@ +//! An array of network devices. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of network devices. +/// +/// XDP programs can use this map to redirect to other network +/// devices. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::DevMap; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES")?)?; +/// let ifindex = 32u32; +/// devmap.set(ifindex, ifindex, 0); +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_DEVMAP")] +pub struct DevMap> { + inner: T, +} + +impl> DevMap { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_DEVMAP as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + 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 }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.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 + DerefMut> DevMap { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + 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 for DevMap { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + DevMap::new(a) + } +} + +impl TryFrom for DevMap { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + DevMap::new(a) + } +} diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs new file mode 100644 index 000000000..4cf167626 --- /dev/null +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -0,0 +1,118 @@ +//! An array of network devices. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of network devices. +/// +/// XDP programs can use this map to redirect to other network +/// devices. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::DevMapHash; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES")?)?; +/// let flags = 0; +/// let ifindex = 32u32; +/// devmap.set(ifindex, ifindex, flags); +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] +pub struct DevMapHash> { + inner: T, +} + +impl> DevMapHash { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_DEVMAP_HASH as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + 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 }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.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 + DerefMut> DevMapHash { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: u32, flags: u64) -> Result<(), MapError> { + 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 for DevMapHash { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + DevMapHash::new(a) + } +} + +impl TryFrom for DevMapHash { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + DevMapHash::new(a) + } +} diff --git a/aya/src/maps/xdp/mod.rs b/aya/src/maps/xdp/mod.rs new file mode 100644 index 000000000..6120dc909 --- /dev/null +++ b/aya/src/maps/xdp/mod.rs @@ -0,0 +1,10 @@ +//! XDP maps. +mod cpu_map; +mod dev_map; +mod dev_map_hash; +mod xsk_map; + +pub use cpu_map::CpuMap; +pub use dev_map::DevMap; +pub use dev_map_hash::DevMapHash; +pub use xsk_map::XskMap; diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs new file mode 100644 index 000000000..239c908c1 --- /dev/null +++ b/aya/src/maps/xdp/xsk_map.rs @@ -0,0 +1,118 @@ +//! An array of AF_XDP sockets. + +use std::{ + convert::TryFrom, + mem, + ops::{Deref, DerefMut}, + os::unix::prelude::{AsRawFd, RawFd}, +}; + +use crate::{ + generated::bpf_map_type::BPF_MAP_TYPE_XSKMAP, + maps::{Map, MapError, MapRef, MapRefMut}, + sys::bpf_map_update_elem, +}; + +/// An array of AF_XDP sockets. +/// +/// XDP programs can use this map to redirect packets to a target +/// AF_XDP socket using the `XDP_REDIRECT` action. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.2. +/// +/// # Examples +/// ```no_run +/// # let bpf = aya::Bpf::load(&[])?; +/// # let socket_fd = 1; +/// use aya::maps::XskMap; +/// use std::convert::{TryFrom, TryInto}; +/// +/// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS")?)?; +/// // socket_fd is the RawFd of an AF_XDP socket +/// xskmap.set(0, socket_fd, 0); +/// # Ok::<(), aya::BpfError>(()) +/// ``` +#[doc(alias = "BPF_MAP_TYPE_XSKMAP")] +pub struct XskMap> { + inner: T, +} + +impl> XskMap { + fn new(map: T) -> Result, MapError> { + let map_type = map.obj.def.map_type; + if map_type != BPF_MAP_TYPE_XSKMAP as u32 { + return Err(MapError::InvalidMapType { + map_type: map_type as u32, + }); + } + let expected = mem::size_of::(); + let size = map.obj.def.key_size as usize; + if size != expected { + return Err(MapError::InvalidKeySize { size, expected }); + } + + let expected = mem::size_of::(); + 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 }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.obj.def.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 + DerefMut> XskMap { + /// Sets the value of the element at the given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { + let fd = self.inner.fd_or_err()?; + self.check_bounds(index)?; + bpf_map_update_elem(fd, &index, &value.as_raw_fd(), flags).map_err( + |(code, io_error)| MapError::SyscallError { + call: "bpf_map_update_elem".to_owned(), + code, + io_error, + }, + )?; + Ok(()) + } +} + +impl TryFrom for XskMap { + type Error = MapError; + + fn try_from(a: MapRef) -> Result, MapError> { + XskMap::new(a) + } +} + +impl TryFrom for XskMap { + type Error = MapError; + + fn try_from(a: MapRefMut) -> Result, MapError> { + XskMap::new(a) + } +} From 464102bd63bfd0147fbdaae634e5c5b0ee2721bf Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Mon, 30 May 2022 11:58:59 +0100 Subject: [PATCH 2/2] bpf: Implement XDP maps Signed-off-by: Dave Tucker --- bpf/aya-bpf/src/maps/mod.rs | 2 + bpf/aya-bpf/src/maps/xdp/cpu_map.rs | 55 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/dev_map.rs | 55 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs | 55 ++++++++++++++++++++++++ bpf/aya-bpf/src/maps/xdp/mod.rs | 9 ++++ bpf/aya-bpf/src/maps/xdp/xsk_map.rs | 55 ++++++++++++++++++++++++ 6 files changed, 231 insertions(+) create mode 100644 bpf/aya-bpf/src/maps/xdp/cpu_map.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/dev_map.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/mod.rs create mode 100644 bpf/aya-bpf/src/maps/xdp/xsk_map.rs diff --git a/bpf/aya-bpf/src/maps/mod.rs b/bpf/aya-bpf/src/maps/mod.rs index fc4f17323..5fb6d67fd 100644 --- a/bpf/aya-bpf/src/maps/mod.rs +++ b/bpf/aya-bpf/src/maps/mod.rs @@ -15,6 +15,7 @@ pub mod queue; pub mod sock_hash; pub mod sock_map; pub mod stack_trace; +pub mod xdp; pub use array::Array; pub use hash_map::{HashMap, LruHashMap, LruPerCpuHashMap, PerCpuHashMap}; @@ -26,3 +27,4 @@ pub use queue::Queue; pub use sock_hash::SockHash; pub use sock_map::SockMap; pub use stack_trace::StackTrace; +pub use xdp::{CpuMap, DevMap, DevMapHash, XskMap}; diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs new file mode 100644 index 000000000..bc16c271b --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct CpuMap { + def: bpf_map_def, +} + +impl CpuMap { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> CpuMap { + CpuMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_CPUMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> CpuMap { + CpuMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_CPUMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs new file mode 100644 index 000000000..8a9415ecd --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct DevMap { + def: bpf_map_def, +} + +impl DevMap { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMap { + DevMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> DevMap { + DevMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs new file mode 100644 index 000000000..6a0b1903a --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct DevMapHash { + def: bpf_map_def, +} + +impl DevMapHash { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMapHash { + DevMapHash { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP_HASH, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> DevMapHash { + DevMapHash { + def: bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP_HASH, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/mod.rs b/bpf/aya-bpf/src/maps/xdp/mod.rs new file mode 100644 index 000000000..b7ced7b5f --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/mod.rs @@ -0,0 +1,9 @@ +mod cpu_map; +mod dev_map; +mod dev_map_hash; +mod xsk_map; + +pub use cpu_map::CpuMap; +pub use dev_map::DevMap; +pub use dev_map_hash::DevMapHash; +pub use xsk_map::XskMap; diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs new file mode 100644 index 000000000..39fba557e --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -0,0 +1,55 @@ +use core::{mem, ptr::NonNull}; + +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_XSKMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +#[repr(transparent)] +pub struct XskMap { + def: bpf_map_def, +} + +impl XskMap { + pub const fn with_max_entries(max_entries: u32, flags: u32) -> XskMap { + XskMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_XSKMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub const fn pinned(max_entries: u32, flags: u32) -> XskMap { + XskMap { + def: bpf_map_def { + type_: BPF_MAP_TYPE_XSKMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }, + } + } + + pub fn get(&mut self, index: u32) -> Option<&u32> { + unsafe { + let value = bpf_map_lookup_elem( + &mut self.def as *mut _ as *mut _, + &index as *const _ as *const c_void, + ); + // FIXME: alignment + NonNull::new(value as *mut u32).map(|p| p.as_ref()) + } + } +}