use super::SocketId;
use crate::dpdk::DpdkError;
use crate::ffi::{self, AsStr, ToCString, ToResult};
use crate::{debug, info};
use anyhow::Result;
use std::cell::Cell;
use std::collections::HashMap;
use std::fmt;
use std::os::raw;
use std::ptr::{self, NonNull};
use std::sync::atomic::{AtomicUsize, Ordering};
use thiserror::Error;
pub(crate) struct Mempool {
raw: NonNull<ffi::rte_mempool>,
}
impl Mempool {
pub(crate) fn new(capacity: usize, cache_size: usize, socket_id: SocketId) -> Result<Self> {
static MEMPOOL_COUNT: AtomicUsize = AtomicUsize::new(0);
let n = MEMPOOL_COUNT.fetch_add(1, Ordering::Relaxed);
let name = format!("mempool{}", n);
let raw = unsafe {
ffi::rte_pktmbuf_pool_create(
name.clone().into_cstring().as_ptr(),
capacity as raw::c_uint,
cache_size as raw::c_uint,
0,
ffi::RTE_MBUF_DEFAULT_BUF_SIZE as u16,
socket_id.raw(),
)
.into_result(|_| DpdkError::new())?
};
info!("created {}.", name);
Ok(Self { raw })
}
#[inline]
pub(crate) fn raw(&self) -> &ffi::rte_mempool {
unsafe { self.raw.as_ref() }
}
#[inline]
pub(crate) fn raw_mut(&mut self) -> &mut ffi::rte_mempool {
unsafe { self.raw.as_mut() }
}
#[inline]
pub(crate) fn name(&self) -> &str {
self.raw().name[..].as_str()
}
#[cfg(feature = "metrics")]
pub(crate) fn stats(&self) -> super::MempoolStats {
super::MempoolStats::build(self)
}
}
impl fmt::Debug for Mempool {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let raw = self.raw();
f.debug_struct(self.name())
.field("capacity", &raw.size)
.field("cache_size", &raw.cache_size)
.field("flags", &format_args!("{:#x}", raw.flags))
.field("socket", &raw.socket_id)
.finish()
}
}
impl Drop for Mempool {
fn drop(&mut self) {
debug!("freeing {}.", self.name());
unsafe {
ffi::rte_mempool_free(self.raw_mut());
}
}
}
thread_local! {
pub static MEMPOOL: Cell<*mut ffi::rte_mempool> = Cell::new(ptr::null_mut());
}
#[derive(Debug, Error)]
pub(crate) enum MempoolError {
#[error("Cannot allocate a new mbuf from mempool")]
Exhausted,
#[error("Mempool for {0:?} not found.")]
NotFound(SocketId),
}
#[derive(Debug)]
pub(crate) struct MempoolMap<'a> {
inner: HashMap<SocketId, &'a mut Mempool>,
}
impl<'a> MempoolMap<'a> {
pub(crate) fn new(mempools: &'a mut [Mempool]) -> Self {
let map = mempools
.iter_mut()
.map(|pool| {
let socket = SocketId(pool.raw().socket_id);
(socket, pool)
})
.collect::<HashMap<_, _>>();
Self { inner: map }
}
pub(crate) fn get_raw(&mut self, socket_id: SocketId) -> Result<&mut ffi::rte_mempool> {
self.inner
.get_mut(&socket_id)
.ok_or_else(|| MempoolError::NotFound(socket_id).into())
.map(|pool| pool.raw_mut())
}
}
impl<'a> Default for MempoolMap<'a> {
fn default() -> MempoolMap<'a> {
MempoolMap {
inner: HashMap::new(),
}
}
}