use crate::{Umem, libc, slab::Slab};
pub struct RxRing {
ring: super::XskConsumer<libc::xdp::xdp_desc>,
_mmap: crate::mmap::Mmap,
}
impl RxRing {
pub(crate) fn new(
socket: std::os::fd::RawFd,
cfg: &super::RingConfig,
offsets: &libc::rings::xdp_mmap_offsets,
) -> Result<Self, crate::socket::SocketError> {
let (_mmap, mut ring) = super::map_ring(
socket,
cfg.rx_count,
libc::rings::RingPageOffsets::Rx,
&offsets.rx,
)
.map_err(|inner| crate::socket::SocketError::RingMap {
inner,
ring: super::Ring::Rx,
})?;
ring.cached_consumed = ring.consumer.load(std::sync::atomic::Ordering::Relaxed);
ring.cached_produced = ring.producer.load(std::sync::atomic::Ordering::Relaxed);
Ok(Self {
ring: super::XskConsumer(ring),
_mmap,
})
}
#[inline]
pub unsafe fn recv<S: Slab>(&mut self, umem: &Umem, packets: &mut S) -> usize {
let nb = packets.available();
if nb == 0 {
return 0;
}
let (actual, idx) = self.ring.peek(nb as _);
if actual > 0 {
for i in idx..idx + actual {
let desc = self.ring.get(i);
packets.push_front(
unsafe { umem.packet(desc) },
);
}
self.ring.release(actual as _);
}
actual
}
}