pub mod error;
pub mod frame_buf;
pub mod pool;
pub mod ring;
pub mod stats;
pub use error::{Error, Result};
pub use frame_buf::FrameBuf;
pub use pool::{PacketBuffer, PacketPool, PacketRef};
pub use ring::LockFreeRing;
pub use stats::DatapathStats;
pub const CACHE_LINE_SIZE: usize = 64;
pub const DEFAULT_BATCH_SIZE: usize = 64;
pub const DEFAULT_RING_CAPACITY: usize = 4096;
pub const DEFAULT_POOL_CAPACITY: usize = 8192;
pub const MAX_PACKET_SIZE: usize = 65535;
#[repr(C, align(64))]
#[derive(Debug, Default, Clone, Copy)]
pub struct CachePadded<T>(pub T);
impl<T> CachePadded<T> {
#[inline]
pub const fn new(value: T) -> Self {
Self(value)
}
#[inline]
pub const fn get(&self) -> &T {
&self.0
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
&mut self.0
}
}
#[allow(clippy::inline_always)] #[inline(always)]
pub fn prefetch_read<T>(ptr: *const T) {
#[cfg(target_arch = "aarch64")]
unsafe {
core::arch::asm!(
"prfm pldl1keep, [{ptr}]",
ptr = in(reg) ptr,
options(nostack, preserves_flags)
);
}
#[cfg(target_arch = "x86_64")]
unsafe {
core::arch::x86_64::_mm_prefetch(ptr.cast::<i8>(), core::arch::x86_64::_MM_HINT_T0);
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
{
let _ = ptr;
}
}
#[allow(clippy::inline_always)] #[inline(always)]
pub fn prefetch_write<T>(ptr: *mut T) {
#[cfg(target_arch = "aarch64")]
unsafe {
core::arch::asm!(
"prfm pstl1keep, [{ptr}]",
ptr = in(reg) ptr,
options(nostack, preserves_flags)
);
}
#[cfg(target_arch = "x86_64")]
unsafe {
core::arch::x86_64::_mm_prefetch(ptr.cast::<i8>(), core::arch::x86_64::_MM_HINT_T0);
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
{
let _ = ptr;
}
}
#[inline]
pub const fn is_power_of_two(n: usize) -> bool {
n != 0 && n.is_power_of_two()
}
#[inline]
pub const fn next_power_of_two(mut n: usize) -> usize {
if n == 0 {
return 1;
}
n -= 1;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n |= n >> 32;
n + 1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cache_padded_size() {
assert_eq!(std::mem::size_of::<CachePadded<u64>>(), CACHE_LINE_SIZE);
}
#[test]
fn test_power_of_two() {
assert!(is_power_of_two(1));
assert!(is_power_of_two(2));
assert!(is_power_of_two(4));
assert!(is_power_of_two(4096));
assert!(!is_power_of_two(0));
assert!(!is_power_of_two(3));
assert!(!is_power_of_two(5));
}
#[test]
fn test_next_power_of_two() {
assert_eq!(next_power_of_two(0), 1);
assert_eq!(next_power_of_two(1), 1);
assert_eq!(next_power_of_two(2), 2);
assert_eq!(next_power_of_two(3), 4);
assert_eq!(next_power_of_two(5), 8);
assert_eq!(next_power_of_two(1000), 1024);
}
}