use crate::{Umem, libc::rings};
pub struct CompletionRing {
ring: super::XskConsumer<u64>,
_mmap: crate::mmap::Mmap,
}
impl CompletionRing {
pub(crate) fn new(
socket: std::os::fd::RawFd,
cfg: &super::RingConfig,
offsets: &rings::xdp_mmap_offsets,
) -> Result<Self, crate::socket::SocketError> {
let (_mmap, mut ring) = super::map_ring(
socket,
cfg.completion_count,
rings::RingPageOffsets::Completion,
&offsets.completion,
)
.map_err(|inner| crate::socket::SocketError::RingMap {
inner,
ring: super::Ring::Completion,
})?;
ring.cached_consumed = 0;
ring.cached_produced = 0;
Ok(Self {
ring: super::XskConsumer(ring),
_mmap,
})
}
pub fn dequeue(&mut self, umem: &mut Umem, num_packets: usize) -> usize {
let requested = num_packets;
if requested == 0 {
return 0;
}
let (actual, idx) = self.ring.peek(requested as _);
if actual > 0 {
for i in idx..idx + actual {
let addr = self.ring.get(i);
umem.free_addr(addr);
}
self.ring.release(actual as _);
}
actual
}
pub fn dequeue_with_timestamps(&mut self, umem: &mut Umem, timestamps: &mut [u64]) -> usize {
let requested = timestamps.len();
if requested == 0 {
return 0;
}
let (actual, idx) = self.ring.peek(requested as _);
if actual > 0 {
for (ts, i) in timestamps.iter_mut().zip(idx..idx + actual) {
let addr = self.ring.get(i);
*ts = umem.free_get_timestamp(addr);
}
self.ring.release(actual as _);
}
actual
}
}