aya, bpf: misc fixes following review comments

pull/527/head
Tuetuopay 1 year ago
parent 46551de3e7
commit 579e3cee22

@ -147,14 +147,7 @@ pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// ///
/// #[xdp(frags)] /// #[xdp(frags)]
/// pub fn xdp(ctx: XdpContext) -> u32 { /// pub fn xdp(ctx: XdpContext) -> u32 {
/// match unsafe { try_xdp(ctx) } { /// XDP_PASS
/// Ok(ret) => ret,
/// Err(ret) => ret,
/// }
/// }
///
/// unsafe fn try_xdp(_ctx: XdpContext) -> Result<u32, u32> {
/// Ok(XDP_PASS)
/// } /// }
/// ``` /// ```
#[proc_macro_error] #[proc_macro_error]

@ -28,7 +28,7 @@ impl Xdp {
Some(name) => { Some(name) => {
return Err(Error::new_spanned( return Err(Error::new_spanned(
"map", "map",
format!("invalid value. expected 'cpumap' or 'devmap', found '{name}'"), format!("Invalid value. Expected 'cpumap' or 'devmap', found '{name}'"),
)) ))
} }
None => None, None => None,

@ -50,7 +50,6 @@ pub struct Features {
bpf_cookie: bool, bpf_cookie: bool,
cpumap_prog_id: bool, cpumap_prog_id: bool,
devmap_prog_id: bool, devmap_prog_id: bool,
devmap_hash_prog_id: bool,
btf: Option<BtfFeatures>, btf: Option<BtfFeatures>,
} }
@ -65,7 +64,6 @@ impl Features {
bpf_cookie: bool, bpf_cookie: bool,
cpumap_prog_id: bool, cpumap_prog_id: bool,
devmap_prog_id: bool, devmap_prog_id: bool,
devmap_hash_prog_id: bool,
btf: Option<BtfFeatures>, btf: Option<BtfFeatures>,
) -> Self { ) -> Self {
Self { Self {
@ -76,7 +74,6 @@ impl Features {
bpf_cookie, bpf_cookie,
cpumap_prog_id, cpumap_prog_id,
devmap_prog_id, devmap_prog_id,
devmap_hash_prog_id,
btf, btf,
} }
} }
@ -116,11 +113,6 @@ impl Features {
self.devmap_prog_id self.devmap_prog_id
} }
/// Returns whether XDP Hash Device Maps support chained program IDs.
pub fn devmap_hash_prog_id(&self) -> bool {
self.devmap_hash_prog_id
}
/// If BTF is supported, returns which BTF features are supported. /// If BTF is supported, returns which BTF features are supported.
pub fn btf(&self) -> Option<&BtfFeatures> { pub fn btf(&self) -> Option<&BtfFeatures> {
self.btf.as_ref() self.btf.as_ref()

@ -96,7 +96,6 @@ fn detect_features() -> Features {
is_bpf_cookie_supported(), is_bpf_cookie_supported(),
is_prog_id_supported(BPF_MAP_TYPE_CPUMAP), is_prog_id_supported(BPF_MAP_TYPE_CPUMAP),
is_prog_id_supported(BPF_MAP_TYPE_DEVMAP), is_prog_id_supported(BPF_MAP_TYPE_DEVMAP),
is_prog_id_supported(BPF_MAP_TYPE_DEVMAP_HASH),
btf, btf,
); );
debug!("BPF Feature Detection: {:#?}", f); debug!("BPF Feature Detection: {:#?}", f);
@ -484,12 +483,9 @@ impl<'a> BpfLoader<'a> {
Ok(BPF_MAP_TYPE_CPUMAP) => { Ok(BPF_MAP_TYPE_CPUMAP) => {
obj.set_value_size(if FEATURES.cpumap_prog_id() { 8 } else { 4 }) obj.set_value_size(if FEATURES.cpumap_prog_id() { 8 } else { 4 })
} }
Ok(BPF_MAP_TYPE_DEVMAP) => { Ok(BPF_MAP_TYPE_DEVMAP | BPF_MAP_TYPE_DEVMAP_HASH) => {
obj.set_value_size(if FEATURES.devmap_prog_id() { 8 } else { 4 }) obj.set_value_size(if FEATURES.devmap_prog_id() { 8 } else { 4 })
} }
Ok(BPF_MAP_TYPE_DEVMAP_HASH) => {
obj.set_value_size(if FEATURES.devmap_hash_prog_id() { 8 } else { 4 })
}
_ => (), _ => (),
} }
let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd());

@ -279,7 +279,7 @@ pub enum Map {
DevMapHash(MapData), DevMapHash(MapData),
/// A [`XskMap`] map. /// A [`XskMap`] map.
XskMap(MapData), XskMap(MapData),
/// An unsupported map type /// An unsupported map type.
Unsupported(MapData), Unsupported(MapData),
} }

@ -6,7 +6,7 @@ use std::{
os::fd::{AsFd, AsRawFd}, os::fd::{AsFd, AsRawFd},
}; };
use aya_obj::generated::{bpf_cpumap_val, bpf_cpumap_val__bindgen_ty_1}; use aya_obj::generated::bpf_cpumap_val;
use crate::{ use crate::{
maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError},
@ -15,6 +15,8 @@ use crate::{
Pod, FEATURES, Pod, FEATURES,
}; };
use super::XdpMapError;
/// An array of available CPUs. /// An array of available CPUs.
/// ///
/// XDP programs can use this map to redirect packets to a target /// XDP programs can use this map to redirect packets to a target
@ -29,19 +31,24 @@ use crate::{
/// # let elf_bytes = &[]; /// # let elf_bytes = &[];
/// use aya::maps::xdp::CpuMap; /// use aya::maps::xdp::CpuMap;
/// ///
/// let ncpus = aya::util::nr_cpus().unwrap() as u32;
/// let mut bpf = aya::BpfLoader::new() /// let mut bpf = aya::BpfLoader::new()
/// .set_max_entries("CPUS", aya::util::nr_cpus().unwrap() as u32) /// .set_max_entries("CPUS", ncpus)
/// .load(elf_bytes) /// .load(elf_bytes)
/// .unwrap(); /// .unwrap();
/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS").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 0..ncpus {
/// cpumap.set(i, queue_size, None, flags); /// cpumap.set(i, queue_size, None, flags);
/// } /// }
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
///
/// # See also
///
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_cpumap.html>
#[doc(alias = "BPF_MAP_TYPE_CPUMAP")] #[doc(alias = "BPF_MAP_TYPE_CPUMAP")]
pub struct CpuMap<T> { pub struct CpuMap<T> {
inner: T, inner: T,
@ -67,7 +74,7 @@ impl<T: Borrow<MapData>> CpuMap<T> {
self.inner.borrow().obj.max_entries() self.inner.borrow().obj.max_entries()
} }
/// Returns the queue size and possible program for a given CPU index. /// Returns the queue size and optional program for a given CPU index.
/// ///
/// # Errors /// # Errors
/// ///
@ -81,7 +88,7 @@ impl<T: Borrow<MapData>> CpuMap<T> {
let value = if FEATURES.cpumap_prog_id() { let value = if FEATURES.cpumap_prog_id() {
bpf_map_lookup_elem::<_, bpf_cpumap_val>(fd, &cpu_index, flags).map(|value| { bpf_map_lookup_elem::<_, bpf_cpumap_val>(fd, &cpu_index, flags).map(|value| {
value.map(|value| CpuMapValue { value.map(|value| CpuMapValue {
qsize: value.qsize, queue_size: value.qsize,
// SAFETY: map writes use fd, map reads use id. // SAFETY: map writes use fd, map reads use id.
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241
prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }),
@ -90,7 +97,7 @@ impl<T: Borrow<MapData>> CpuMap<T> {
} else { } else {
bpf_map_lookup_elem::<_, u32>(fd, &cpu_index, flags).map(|value| { bpf_map_lookup_elem::<_, u32>(fd, &cpu_index, flags).map(|value| {
value.map(|qsize| CpuMapValue { value.map(|qsize| CpuMapValue {
qsize, queue_size: qsize,
prog_id: None, prog_id: None,
}) })
}) })
@ -115,52 +122,52 @@ impl<T: BorrowMut<MapData>> CpuMap<T> {
/// When sending the packet to the CPU at the given index, the kernel will queue up to /// When sending the packet to the CPU at the given index, the kernel will queue up to
/// `queue_size` packets before dropping them. /// `queue_size` packets before dropping them.
/// ///
/// Another XDP program can be passed in that will be run on the target CPU, instead of the CPU /// Starting from Linux kernel 5.9, another XDP program can be passed in that will be run on the
/// that receives the packets. This allows to perform minimal computations on CPUs that /// target CPU, instead of the CPU that receives the packets. This allows to perform minimal
/// directly handle packets from a NIC's RX queues, and perform possibly heavier ones in other, /// computations on CPUs that directly handle packets from a NIC's RX queues, and perform
/// less busy CPUs. /// possibly heavier ones in other, less busy CPUs.
/// ///
/// Note that only XDP programs with the `map = "cpumap"` argument can be passed. See the /// The chained program must be loaded with the `BPF_XDP_CPUMAP` attach type. When using
/// kernel-space `aya_bpf::xdp` for more information. /// `aya-ebpf`, that means XDP programs that specify the `map = "cpumap"` argument. See the
/// kernel-space `aya_ebpf::xdp` for more information.
/// ///
/// # Errors /// # Errors
/// ///
/// 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, [`MapError::ProgIdNotSupported`] if the kernel does not /// if `bpf_map_update_elem` fails, [`XdpMapError::ChainedProgramNotSupported`] if the kernel
/// support program ids and one is provided. /// does not support chained programs and one is provided.
pub fn set( pub fn set(
&mut self, &mut self,
cpu_index: u32, cpu_index: u32,
queue_size: u32, queue_size: u32,
program: Option<&ProgramFd>, program: Option<&ProgramFd>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), XdpMapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, cpu_index)?; check_bounds(data, cpu_index)?;
let fd = data.fd().as_fd(); let fd = data.fd().as_fd();
let res = if FEATURES.cpumap_prog_id() { let res = if FEATURES.cpumap_prog_id() {
let value = bpf_cpumap_val { let mut value = unsafe { std::mem::zeroed::<bpf_cpumap_val>() };
qsize: queue_size, value.qsize = queue_size;
bpf_prog: bpf_cpumap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0:
// Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 value.bpf_prog.fd = program
fd: program .map(|prog| prog.as_fd().as_raw_fd())
.map(|prog| prog.as_fd().as_raw_fd()) .unwrap_or_default();
.unwrap_or_default(),
},
};
bpf_map_update_elem(fd, Some(&cpu_index), &value, flags) bpf_map_update_elem(fd, Some(&cpu_index), &value, flags)
} else { } else {
if program.is_some() { if program.is_some() {
return Err(MapError::ProgIdNotSupported); return Err(XdpMapError::ChainedProgramNotSupported);
} }
bpf_map_update_elem(fd, Some(&cpu_index), &queue_size, flags) bpf_map_update_elem(fd, Some(&cpu_index), &queue_size, flags)
}; };
res.map_err(|(_, io_error)| SyscallError { res.map_err(|(_, io_error)| {
call: "bpf_map_update_elem", MapError::from(SyscallError {
io_error, call: "bpf_map_update_elem",
io_error,
})
})?; })?;
Ok(()) Ok(())
} }
@ -179,7 +186,10 @@ impl<T: Borrow<MapData>> IterableMap<u32, CpuMapValue> for CpuMap<T> {
unsafe impl Pod for bpf_cpumap_val {} unsafe impl Pod for bpf_cpumap_val {}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
/// The value of a CPU map.
pub struct CpuMapValue { pub struct CpuMapValue {
pub qsize: u32, /// Size of the for the CPU.
pub queue_size: u32,
/// Chained XDP program ID.
pub prog_id: Option<NonZeroU32>, pub prog_id: Option<NonZeroU32>,
} }

@ -6,7 +6,7 @@ use std::{
os::fd::{AsFd, AsRawFd}, os::fd::{AsFd, AsRawFd},
}; };
use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; use aya_obj::generated::bpf_devmap_val;
use crate::{ use crate::{
maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError},
@ -15,6 +15,8 @@ use crate::{
Pod, FEATURES, Pod, FEATURES,
}; };
use super::XdpMapError;
/// An array of network devices. /// An array 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
@ -30,12 +32,15 @@ use crate::{
/// use aya::maps::xdp::DevMap; /// use aya::maps::xdp::DevMap;
/// ///
/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?; /// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?;
/// let source = 32u32; /// // Lookups at index 2 will redirect packets to interface with index 3 (e.g. eth1)
/// let dest = 42u32; /// devmap.set(2, 3, None, 0);
/// devmap.set(source, dest, None, 0);
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
///
/// # See also
///
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_devmap.html>
#[doc(alias = "BPF_MAP_TYPE_DEVMAP")] #[doc(alias = "BPF_MAP_TYPE_DEVMAP")]
pub struct DevMap<T> { pub struct DevMap<T> {
inner: T, inner: T,
@ -61,7 +66,7 @@ impl<T: Borrow<MapData>> DevMap<T> {
self.inner.borrow().obj.max_entries() self.inner.borrow().obj.max_entries()
} }
/// Returns the target ifindex and possible program at a given index. /// Returns the target interface index and optional program at a given index.
/// ///
/// # Errors /// # Errors
/// ///
@ -75,7 +80,7 @@ impl<T: Borrow<MapData>> DevMap<T> {
let value = if FEATURES.devmap_prog_id() { let value = if FEATURES.devmap_prog_id() {
bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &index, flags).map(|value| { bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &index, flags).map(|value| {
value.map(|value| DevMapValue { value.map(|value| DevMapValue {
ifindex: value.ifindex, if_index: value.ifindex,
// SAFETY: map writes use fd, map reads use id. // SAFETY: map writes use fd, map reads use id.
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228
prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }),
@ -84,7 +89,7 @@ impl<T: Borrow<MapData>> DevMap<T> {
} else { } else {
bpf_map_lookup_elem::<_, u32>(fd, &index, flags).map(|value| { bpf_map_lookup_elem::<_, u32>(fd, &index, flags).map(|value| {
value.map(|ifindex| DevMapValue { value.map(|ifindex| DevMapValue {
ifindex, if_index: ifindex,
prog_id: None, prog_id: None,
}) })
}) })
@ -104,57 +109,57 @@ impl<T: Borrow<MapData>> DevMap<T> {
} }
impl<T: BorrowMut<MapData>> DevMap<T> { impl<T: BorrowMut<MapData>> DevMap<T> {
/// Sets the target ifindex at index, and optionally a chained program. /// Sets the target interface index at index, and optionally a chained program.
/// ///
/// When redirecting using `index`, packets will be transmitted by the interface with /// When redirecting using `index`, packets will be transmitted by the interface with
/// `ifindex`. /// `target_if_index`.
/// ///
/// Another XDP program can be passed in that will be run before actual transmission. It can be /// Starting from Linux kernel 5.8, another XDP program can be passed in that will be run before
/// used to modify the packet before transmission with NIC specific data (MAC address update, /// actual transmission. It can be used to modify the packet before transmission with NIC
/// checksum computations, etc) or other purposes. /// specific data (MAC address update, checksum computations, etc) or other purposes.
/// ///
/// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the /// The chained program must be loaded with the `BPF_XDP_DEVMAP` attach type. When using
/// kernel-space `aya_bpf::xdp` for more information. /// `aya-ebpf`, that means XDP programs that specify the `map = "devmap"` argument. See the
/// kernel-space `aya_ebpf::xdp` for more information.
/// ///
/// # Errors /// # Errors
/// ///
/// 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, [`MapError::ProgIdNotSupported`] if the kernel does not /// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not
/// support program ids and one is provided. /// support chained programs and one is provided.
pub fn set( pub fn set(
&mut self, &mut self,
index: u32, index: u32,
ifindex: u32, target_if_index: u32,
program: Option<&ProgramFd>, program: Option<&ProgramFd>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), XdpMapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, index)?; check_bounds(data, index)?;
let fd = data.fd().as_fd(); let fd = data.fd().as_fd();
let res = if FEATURES.devmap_prog_id() { let res = if FEATURES.devmap_prog_id() {
let value = bpf_devmap_val { let mut value = unsafe { std::mem::zeroed::<bpf_devmap_val>() };
ifindex, value.ifindex = target_if_index;
bpf_prog: bpf_devmap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0:
// Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 value.bpf_prog.fd = program
fd: program .map(|prog| prog.as_fd().as_raw_fd())
.map(|prog| prog.as_fd().as_raw_fd()) .unwrap_or_default();
.unwrap_or_default(),
},
};
bpf_map_update_elem(fd, Some(&index), &value, flags) bpf_map_update_elem(fd, Some(&index), &value, flags)
} else { } else {
if program.is_some() { if program.is_some() {
return Err(MapError::ProgIdNotSupported); return Err(XdpMapError::ChainedProgramNotSupported);
} }
bpf_map_update_elem(fd, Some(&index), &ifindex, flags) bpf_map_update_elem(fd, Some(&index), &target_if_index, flags)
}; };
res.map_err(|(_, io_error)| SyscallError { res.map_err(|(_, io_error)| {
call: "bpf_map_update_elem", MapError::from(SyscallError {
io_error, call: "bpf_map_update_elem",
io_error,
})
})?; })?;
Ok(()) Ok(())
} }
@ -173,7 +178,10 @@ impl<T: Borrow<MapData>> IterableMap<u32, DevMapValue> for DevMap<T> {
unsafe impl Pod for bpf_devmap_val {} unsafe impl Pod for bpf_devmap_val {}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
/// The value of a device map.
pub struct DevMapValue { pub struct DevMapValue {
pub ifindex: u32, /// Target interface index to redirect to.
pub if_index: u32,
/// Chained XDP program ID.
pub prog_id: Option<NonZeroU32>, pub prog_id: Option<NonZeroU32>,
} }

@ -6,7 +6,7 @@ use std::{
os::fd::{AsFd, AsRawFd}, os::fd::{AsFd, AsRawFd},
}; };
use aya_obj::generated::{bpf_devmap_val, bpf_devmap_val__bindgen_ty_1}; use aya_obj::generated::bpf_devmap_val;
use crate::{ use crate::{
maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys},
@ -15,7 +15,7 @@ use crate::{
FEATURES, FEATURES,
}; };
use super::dev_map::DevMapValue; use super::{dev_map::DevMapValue, XdpMapError};
/// An hashmap of network devices. /// An hashmap of network devices.
/// ///
@ -32,12 +32,15 @@ use super::dev_map::DevMapValue;
/// use aya::maps::xdp::DevMapHash; /// use aya::maps::xdp::DevMapHash;
/// ///
/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?; /// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?;
/// let flags = 0; /// // Lookups with key 2 will redirect packets to interface with index 3 (e.g. eth1)
/// let ifindex = 32u32; /// devmap.insert(2, 3, None, 0);
/// devmap.insert(ifindex, ifindex, None, flags);
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
///
/// # See also
///
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_devmap.html>
#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] #[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")]
pub struct DevMapHash<T> { pub struct DevMapHash<T> {
inner: T, inner: T,
@ -47,7 +50,7 @@ impl<T: Borrow<MapData>> DevMapHash<T> {
pub(crate) fn new(map: T) -> Result<Self, MapError> { pub(crate) fn new(map: T) -> Result<Self, MapError> {
let data = map.borrow(); let data = map.borrow();
if FEATURES.devmap_hash_prog_id() { if FEATURES.devmap_prog_id() {
check_kv_size::<u32, bpf_devmap_val>(data)?; check_kv_size::<u32, bpf_devmap_val>(data)?;
} else { } else {
check_kv_size::<u32, u32>(data)?; check_kv_size::<u32, u32>(data)?;
@ -56,7 +59,7 @@ impl<T: Borrow<MapData>> DevMapHash<T> {
Ok(Self { inner: map }) Ok(Self { inner: map })
} }
/// Returns the target ifindex and possible program for a given key. /// Returns the target interface index and optional program for a given key.
/// ///
/// # Errors /// # Errors
/// ///
@ -64,10 +67,10 @@ impl<T: Borrow<MapData>> DevMapHash<T> {
pub fn get(&self, key: u32, flags: u64) -> Result<DevMapValue, MapError> { pub fn get(&self, key: u32, flags: u64) -> Result<DevMapValue, MapError> {
let fd = self.inner.borrow().fd().as_fd(); let fd = self.inner.borrow().fd().as_fd();
let value = if FEATURES.devmap_hash_prog_id() { let value = if FEATURES.devmap_prog_id() {
bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &key, flags).map(|value| { bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &key, flags).map(|value| {
value.map(|value| DevMapValue { value.map(|value| DevMapValue {
ifindex: value.ifindex, if_index: value.ifindex,
// SAFETY: map writes use fd, map reads use id. // SAFETY: map writes use fd, map reads use id.
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228
prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }),
@ -76,7 +79,7 @@ impl<T: Borrow<MapData>> DevMapHash<T> {
} else { } else {
bpf_map_lookup_elem::<_, u32>(fd, &key, flags).map(|value| { bpf_map_lookup_elem::<_, u32>(fd, &key, flags).map(|value| {
value.map(|ifindex| DevMapValue { value.map(|ifindex| DevMapValue {
ifindex, if_index: ifindex,
prog_id: None, prog_id: None,
}) })
}) })
@ -105,44 +108,43 @@ impl<T: BorrowMut<MapData>> DevMapHash<T> {
/// ///
/// When redirecting using `key`, packets will be transmitted by the interface with `ifindex`. /// When redirecting using `key`, packets will be transmitted by the interface with `ifindex`.
/// ///
/// Another XDP program can be passed in that will be run before actual transmission. It can be /// Starting from Linux kernel 5.8, another XDP program can be passed in that will be run before
/// used to modify the packet before transmission with NIC specific data (MAC address update, /// actual transmission. It can be used to modify the packet before transmission with NIC
/// checksum computations, etc) or other purposes. /// specific data (MAC address update, checksum computations, etc) or other purposes.
/// ///
/// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the /// The chained program must be loaded with the `BPF_XDP_DEVMAP` attach type. When using
/// kernel-space `aya_bpf::xdp` for more information. /// `aya-ebpf`, that means XDP programs that specify the `map = "devmap"` argument. See the
/// kernel-space `aya_ebpf::xdp` for more information.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails, /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails,
/// [`MapError::ProgIdNotSupported`] if the kernel does not support program ids and one is /// [`MapError::ProgIdNotSupported`] if the kernel does not support chained programs and one is
/// provided. /// provided.
pub fn insert( pub fn insert(
&mut self, &mut self,
key: u32, key: u32,
ifindex: u32, target_if_index: u32,
program: Option<&ProgramFd>, program: Option<&ProgramFd>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), XdpMapError> {
if FEATURES.devmap_hash_prog_id() { if FEATURES.devmap_prog_id() {
let value = bpf_devmap_val { let mut value = unsafe { std::mem::zeroed::<bpf_devmap_val>() };
ifindex, value.ifindex = target_if_index;
bpf_prog: bpf_devmap_val__bindgen_ty_1 { // Default is valid as the kernel will only consider fd > 0:
// Default is valid as the kernel will only consider fd > 0: // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 value.bpf_prog.fd = program
fd: program .map(|prog| prog.as_fd().as_raw_fd())
.map(|prog| prog.as_fd().as_raw_fd()) .unwrap_or_default();
.unwrap_or_default(), hash_map::insert(self.inner.borrow_mut(), &key, &value, flags)?;
},
};
hash_map::insert(self.inner.borrow_mut(), &key, &value, flags)
} else { } else {
if program.is_some() { if program.is_some() {
return Err(MapError::ProgIdNotSupported); return Err(XdpMapError::ChainedProgramNotSupported);
} }
hash_map::insert(self.inner.borrow_mut(), &key, &ifindex, flags) hash_map::insert(self.inner.borrow_mut(), &key, &target_if_index, flags)?;
} }
Ok(())
} }
/// Removes a value from the map. /// Removes a value from the map.

@ -8,3 +8,18 @@ pub use cpu_map::CpuMap;
pub use dev_map::DevMap; pub use dev_map::DevMap;
pub use dev_map_hash::DevMapHash; pub use dev_map_hash::DevMapHash;
pub use xsk_map::XskMap; pub use xsk_map::XskMap;
use super::MapError;
use thiserror::Error;
#[derive(Error, Debug)]
/// Errors occuring from working with XDP maps.
pub enum XdpMapError {
/// Chained programs are not supported.
#[error("chained programs are not supported by the current kernel")]
ChainedProgramNotSupported,
/// Map operation failed.
#[error(transparent)]
MapError(#[from] MapError),
}

@ -30,6 +30,10 @@ use crate::{
/// xskmap.set(0, socket_fd, 0); /// xskmap.set(0, socket_fd, 0);
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
///
/// # See also
///
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_xskmap.html>
#[doc(alias = "BPF_MAP_TYPE_XSKMAP")] #[doc(alias = "BPF_MAP_TYPE_XSKMAP")]
pub struct XskMap<T> { pub struct XskMap<T> {
inner: T, inner: T,

@ -1,6 +1,6 @@
use core::{cell::UnsafeCell, mem}; use core::{cell::UnsafeCell, mem};
use aya_bpf_bindings::bindings::bpf_cpumap_val; use aya_bpf_bindings::bindings::{bpf_cpumap_val, xdp_action::XDP_REDIRECT};
use crate::{ use crate::{
bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP},
@ -40,9 +40,9 @@ unsafe impl Sync for CpuMap {}
impl CpuMap { impl CpuMap {
/// Creates a [`CpuMap`] with a set maximum number of elements. /// Creates a [`CpuMap`] with a set maximum number of elements.
/// ///
/// In a CPU Map, an entry represents a CPU core. Thus there should be as many entries as there /// In a CPU map, an entry represents a CPU core. Thus there should be as many entries as there
/// are CPU cores on the system. It can be set to zero here, and updated by userspace at /// are CPU cores on the system. `max_entries` can be set to zero here, and updated by userspace
/// runtime. Refer to the userspace documentation for more information. /// at runtime. Refer to the userspace documentation for more information.
/// ///
/// # Examples /// # Examples
/// ///
@ -109,16 +109,18 @@ impl CpuMap {
/// #[xdp] /// #[xdp]
/// fn xdp(_ctx: XdpContext) -> u32 { /// fn xdp(_ctx: XdpContext) -> u32 {
/// // Redirect to CPU 7 or drop packet if no entry found. /// // Redirect to CPU 7 or drop packet if no entry found.
/// MAP.redirect(7, xdp_action::XDP_DROP as u64) /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP)
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn redirect(&self, index: u32, flags: u64) -> u32 { pub fn redirect(&self, index: u32, flags: u64) -> Result<u32, u32> {
unsafe { let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) };
match ret.unsigned_abs() as u32 {
XDP_REDIRECT => Ok(XDP_REDIRECT),
// Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags
// argument on error. Thus I have no idea why it returns a long (i64) instead of // argument on error. Thus I have no idea why it returns a long (i64) instead of
// something saner, hence the unsigned_abs. // something saner, hence the unsigned_abs.
bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 ret => Err(ret),
} }
} }
} }

@ -1,6 +1,6 @@
use core::{cell::UnsafeCell, mem, ptr::NonNull}; use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull};
use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_bindings::bindings::{bpf_devmap_val, xdp_action::XDP_REDIRECT};
use aya_bpf_cty::c_void; use aya_bpf_cty::c_void;
use crate::{ use crate::{
@ -99,9 +99,9 @@ impl DevMap {
/// #[map] /// #[map]
/// static MAP: DevMap = DevMap::with_max_entries(1, 0); /// static MAP: DevMap = DevMap::with_max_entries(1, 0);
/// ///
/// let ifindex = MAP.get(0); /// let target_if_index = MAP.get(0).target_if_index;
/// ///
/// // redirect to ifindex /// // redirect to if_index
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn get(&self, index: u32) -> Option<DevMapValue> { pub fn get(&self, index: u32) -> Option<DevMapValue> {
@ -111,10 +111,10 @@ impl DevMap {
&index as *const _ as *const c_void, &index as *const _ as *const c_void,
); );
NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue {
ifindex: p.as_ref().ifindex, if_index: p.as_ref().ifindex,
// SAFETY: map writes use fd, map reads use id. // SAFETY: map writes use fd, map reads use id.
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136
prog_id: p.as_ref().bpf_prog.id, prog_id: NonZeroU32::new(p.as_ref().bpf_prog.id),
}) })
} }
} }
@ -133,23 +133,28 @@ impl DevMap {
/// static MAP: DevMap = DevMap::with_max_entries(8, 0); /// static MAP: DevMap = DevMap::with_max_entries(8, 0);
/// ///
/// #[xdp] /// #[xdp]
/// fn xdp(_ctx: XdpContext) -> i32 { /// fn xdp(_ctx: XdpContext) -> u32 {
/// MAP.redirect(7, xdp_action::XDP_PASS as u64) /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP)
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn redirect(&self, index: u32, flags: u64) -> u32 { pub fn redirect(&self, index: u32, flags: u64) -> Result<u32, u32> {
// Return XDP_REDIRECT on success, or the value of the two lower bits of the flags let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) };
// argument on error. Thus I have no idea why it returns a long (i64) instead of match ret.unsigned_abs() as u32 {
// something saner, hence the unsigned_abs. XDP_REDIRECT => Ok(XDP_REDIRECT),
unsafe { // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags
bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 // argument on error. Thus I have no idea why it returns a long (i64) instead of
// something saner, hence the unsigned_abs.
ret => Err(ret),
} }
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
/// The value of a device map.
pub struct DevMapValue { pub struct DevMapValue {
pub ifindex: u32, /// Target interface index to redirect to.
pub prog_id: u32, pub if_index: u32,
/// Chained XDP program ID.
pub prog_id: Option<NonZeroU32>,
} }

@ -1,6 +1,6 @@
use core::{cell::UnsafeCell, mem, ptr::NonNull}; use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull};
use aya_bpf_bindings::bindings::bpf_devmap_val; use aya_bpf_bindings::bindings::{bpf_devmap_val, xdp_action::XDP_REDIRECT};
use aya_bpf_cty::c_void; use aya_bpf_cty::c_void;
use crate::{ use crate::{
@ -103,7 +103,7 @@ impl DevMapHash {
/// #[map] /// #[map]
/// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0); /// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0);
/// ///
/// let ifindex = MAP.get(42); /// let target_if_index = MAP.get(42).target_if_index;
/// ///
/// // redirect to ifindex /// // redirect to ifindex
/// ``` /// ```
@ -113,10 +113,10 @@ impl DevMapHash {
let value = let value =
bpf_map_lookup_elem(self.def.get() as *mut _, &key as *const _ as *const c_void); bpf_map_lookup_elem(self.def.get() as *mut _, &key as *const _ as *const c_void);
NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue {
ifindex: p.as_ref().ifindex, if_index: p.as_ref().ifindex,
// SAFETY: map writes use fd, map reads use id. // SAFETY: map writes use fd, map reads use id.
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136
prog_id: p.as_ref().bpf_prog.id, prog_id: NonZeroU32::new(p.as_ref().bpf_prog.id),
}) })
} }
} }
@ -135,17 +135,19 @@ impl DevMapHash {
/// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0); /// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0);
/// ///
/// #[xdp] /// #[xdp]
/// fn xdp(_ctx: XdpContext) -> i32 { /// fn xdp(_ctx: XdpContext) -> u32 {
/// MAP.redirect(7, xdp_action::XDP_PASS as u64) /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP)
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn redirect(&self, key: u32, flags: u64) -> u32 { pub fn redirect(&self, index: u32, flags: u64) -> Result<u32, u32> {
unsafe { let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) };
match ret.unsigned_abs() as u32 {
XDP_REDIRECT => Ok(XDP_REDIRECT),
// Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags
// argument on error. Thus I have no idea why it returns a long (i64) instead of // argument on error. Thus I have no idea why it returns a long (i64) instead of
// something saner, hence the unsigned_abs. // something saner, hence the unsigned_abs.
bpf_redirect_map(self.def.get() as *mut _, key.into(), flags).unsigned_abs() as u32 ret => Err(ret),
} }
} }
} }

@ -1,6 +1,6 @@
use core::{cell::UnsafeCell, mem, ptr::NonNull}; use core::{cell::UnsafeCell, mem, ptr::NonNull};
use aya_bpf_bindings::bindings::bpf_xdp_sock; use aya_bpf_bindings::bindings::{bpf_xdp_sock, xdp_action::XDP_REDIRECT};
use aya_bpf_cty::c_void; use aya_bpf_cty::c_void;
use crate::{ use crate::{
@ -150,18 +150,20 @@ impl XskMap {
/// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); /// static SOCKS: XskMap = XskMap::with_max_entries(8, 0);
/// ///
/// #[xdp] /// #[xdp]
/// fn xdp(ctx, XdpContext) -> i32 { /// fn xdp(ctx, XdpContext) -> u32 {
/// let queue_id = unsafe { (*ctx.ctx).rx_queue_index }; /// let queue_id = unsafe { (*ctx.ctx).rx_queue_index };
/// MAP.redirect(queue_id, xdp_action::XDP_DROP as u64) /// MAP.redirect(queue_id, 0).unwrap_or(xdp_action::XDP_DROP)
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn redirect(&self, index: u32, flags: u64) -> u32 { pub fn redirect(&self, index: u32, flags: u64) -> Result<u32, u32> {
unsafe { let ret = unsafe { bpf_redirect_map(self.def.get() as *mut _, index.into(), flags) };
match ret.unsigned_abs() as u32 {
XDP_REDIRECT => Ok(XDP_REDIRECT),
// Return XDP_REDIRECT on success, or the value of the two lower bits of the flags // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags
// argument on error. Thus I have no idea why it returns a long (i64) instead of // argument on error. Thus I have no idea why it returns a long (i64) instead of
// something saner, hence the unsigned_abs. // something saner, hence the unsigned_abs.
bpf_redirect_map(self.def.get() as *mut _, index.into(), flags).unsigned_abs() as u32 ret => Err(ret),
} }
} }
} }

@ -26,25 +26,25 @@ static mut HITS: Array<u32> = Array::with_max_entries(2, 0);
#[xdp] #[xdp]
pub fn redirect_sock(_ctx: XdpContext) -> u32 { pub fn redirect_sock(_ctx: XdpContext) -> u32 {
SOCKS.redirect(0, xdp_action::XDP_ABORTED as u64) SOCKS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED)
} }
#[xdp] #[xdp]
pub fn redirect_dev(_ctx: XdpContext) -> u32 { pub fn redirect_dev(_ctx: XdpContext) -> u32 {
inc_hit(0); inc_hit(0);
DEVS.redirect(0, xdp_action::XDP_ABORTED as u64) DEVS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED)
} }
#[xdp] #[xdp]
pub fn redirect_dev_hash(_ctx: XdpContext) -> u32 { pub fn redirect_dev_hash(_ctx: XdpContext) -> u32 {
inc_hit(0); inc_hit(0);
DEVS_HASH.redirect(10, xdp_action::XDP_ABORTED as u64) DEVS_HASH.redirect(10, 0).unwrap_or(xdp_action::XDP_ABORTED)
} }
#[xdp] #[xdp]
pub fn redirect_cpu(_ctx: XdpContext) -> u32 { pub fn redirect_cpu(_ctx: XdpContext) -> u32 {
inc_hit(0); inc_hit(0);
CPUS.redirect(0, xdp_action::XDP_ABORTED as u64) CPUS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED)
} }
#[xdp(map = "cpumap")] #[xdp(map = "cpumap")]

@ -567,7 +567,7 @@ pub mod aya_bpf::maps::xdp
#[repr(transparent)] pub struct aya_bpf::maps::xdp::CpuMap #[repr(transparent)] pub struct aya_bpf::maps::xdp::CpuMap
impl aya_bpf::maps::CpuMap impl aya_bpf::maps::CpuMap
pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap
pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> u32 pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap
impl core::marker::Sync for aya_bpf::maps::CpuMap impl core::marker::Sync for aya_bpf::maps::CpuMap
impl core::marker::Send for aya_bpf::maps::CpuMap impl core::marker::Send for aya_bpf::maps::CpuMap
@ -594,7 +594,7 @@ pub fn aya_bpf::maps::CpuMap::from(t: T) -> T
impl aya_bpf::maps::DevMap impl aya_bpf::maps::DevMap
pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option<DevMapValue> pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option<DevMapValue>
pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap
pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> u32 pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap
impl core::marker::Sync for aya_bpf::maps::DevMap impl core::marker::Sync for aya_bpf::maps::DevMap
impl core::marker::Send for aya_bpf::maps::DevMap impl core::marker::Send for aya_bpf::maps::DevMap
@ -621,7 +621,7 @@ pub fn aya_bpf::maps::DevMap::from(t: T) -> T
impl aya_bpf::maps::DevMapHash impl aya_bpf::maps::DevMapHash
pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option<DevMapValue> pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option<DevMapValue>
pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash
pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> u32 pub fn aya_bpf::maps::DevMapHash::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash
impl core::marker::Sync for aya_bpf::maps::DevMapHash impl core::marker::Sync for aya_bpf::maps::DevMapHash
impl core::marker::Send for aya_bpf::maps::DevMapHash impl core::marker::Send for aya_bpf::maps::DevMapHash
@ -648,7 +648,7 @@ pub fn aya_bpf::maps::DevMapHash::from(t: T) -> T
impl aya_bpf::maps::XskMap impl aya_bpf::maps::XskMap
pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option<u32> pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option<u32>
pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap
pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> u32 pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap
impl core::marker::Sync for aya_bpf::maps::XskMap impl core::marker::Sync for aya_bpf::maps::XskMap
impl core::marker::Send for aya_bpf::maps::XskMap impl core::marker::Send for aya_bpf::maps::XskMap
@ -729,7 +729,7 @@ pub fn aya_bpf::maps::bloom_filter::BloomFilter<T>::from(t: T) -> T
#[repr(transparent)] pub struct aya_bpf::maps::CpuMap #[repr(transparent)] pub struct aya_bpf::maps::CpuMap
impl aya_bpf::maps::CpuMap impl aya_bpf::maps::CpuMap
pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap
pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> u32 pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap
impl core::marker::Sync for aya_bpf::maps::CpuMap impl core::marker::Sync for aya_bpf::maps::CpuMap
impl core::marker::Send for aya_bpf::maps::CpuMap impl core::marker::Send for aya_bpf::maps::CpuMap
@ -756,7 +756,7 @@ pub fn aya_bpf::maps::CpuMap::from(t: T) -> T
impl aya_bpf::maps::DevMap impl aya_bpf::maps::DevMap
pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option<DevMapValue> pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option<DevMapValue>
pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap
pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> u32 pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap
impl core::marker::Sync for aya_bpf::maps::DevMap impl core::marker::Sync for aya_bpf::maps::DevMap
impl core::marker::Send for aya_bpf::maps::DevMap impl core::marker::Send for aya_bpf::maps::DevMap
@ -783,7 +783,7 @@ pub fn aya_bpf::maps::DevMap::from(t: T) -> T
impl aya_bpf::maps::DevMapHash impl aya_bpf::maps::DevMapHash
pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option<DevMapValue> pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option<DevMapValue>
pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash
pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> u32 pub fn aya_bpf::maps::DevMapHash::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash
impl core::marker::Sync for aya_bpf::maps::DevMapHash impl core::marker::Sync for aya_bpf::maps::DevMapHash
impl core::marker::Send for aya_bpf::maps::DevMapHash impl core::marker::Send for aya_bpf::maps::DevMapHash
@ -1206,7 +1206,7 @@ pub fn aya_bpf::maps::stack_trace::StackTrace::from(t: T) -> T
impl aya_bpf::maps::XskMap impl aya_bpf::maps::XskMap
pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option<u32> pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option<u32>
pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap
pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> u32 pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> core::result::Result<u32, u32>
pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap
impl core::marker::Sync for aya_bpf::maps::XskMap impl core::marker::Sync for aya_bpf::maps::XskMap
impl core::marker::Send for aya_bpf::maps::XskMap impl core::marker::Send for aya_bpf::maps::XskMap

Loading…
Cancel
Save