#![allow(private_interfaces)]
#![allow(private_bounds)]
use std::sync::atomic::Ordering;
use std::{io, ptr};
use crate::socket::{_Direction, Commit_, RingError, Socket};
impl<const T: _Direction> Socket<T>
where
Socket<T>: Commit_<T>,
{
pub fn kick(&self) -> Result<(), io::Error> {
let need_wakeup = unsafe {
(*self.x_ring.mmap.flags).load(Ordering::Relaxed) & libc::XDP_RING_NEED_WAKEUP != 0
};
if need_wakeup {
let ret = unsafe {
libc::sendto(
self.raw_fd,
ptr::null(),
0,
libc::MSG_DONTWAIT | libc::MSG_NOSIGNAL,
ptr::null(),
0,
)
};
if ret < 0 {
match io::Error::last_os_error().raw_os_error() {
None | Some(libc::EBUSY | libc::ENOBUFS | libc::EAGAIN) => {}
Some(libc::ENETDOWN) => {
log::warn!("network interface is down, cannot wake up");
}
Some(e) => {
return Err(io::Error::from_raw_os_error(e));
}
}
}
}
Ok(())
}
pub fn commit_and_kick(&mut self, n: usize) -> Result<(), RingError> {
self.commit_(n)?;
self.kick().map_err(RingError::Io)
}
}