use std::io;
use std::io::Read;
use std::io::Write;
use std::result;
use std::sync::Arc;
use std::sync::MutexGuard;
use base::error;
use base::named_pipes::OverlappedWrapper;
use base::warn;
use base::Event;
use base::ReadNotifier;
use base::WaitContext;
use libc::EEXIST;
use net_util::TapT;
use sync::Mutex;
use virtio_sys::virtio_net;
use vm_memory::GuestMemory;
use super::super::super::base_features;
use super::super::super::net::Net;
use super::super::super::net::NetError;
use super::super::super::net::Token;
use super::super::super::net::Worker;
use super::super::super::net::MAX_BUFFER_SIZE;
use super::super::super::Interrupt;
use super::super::super::ProtectionType;
use super::super::super::Queue;
use super::super::super::Reader;
use super::PendingBuffer;
#[cfg(not(feature = "slirp"))]
compile_error!("Net device without slirp not supported on windows");
pub fn validate_and_configure_tap<T: TapT>(_tap: &T, _vq_pairs: u16) -> Result<(), NetError> {
Ok(())
}
pub fn virtio_features_to_tap_offload(_features: u64) -> u32 {
0
}
fn rx_single_frame(rx_queue: &mut Queue, rx_buf: &mut [u8], rx_count: usize) -> bool {
let mut desc_chain = match rx_queue.pop() {
Some(desc) => desc,
None => return false,
};
match desc_chain.writer.write_all(&rx_buf[0..rx_count]) {
Ok(()) => (),
Err(ref e) if e.kind() == io::ErrorKind::WriteZero => {
warn!(
"net: rx: buffer is too small to hold frame of size {}",
rx_count
);
}
Err(e) => {
warn!("net: rx: failed to write slice: {}", e);
}
};
rx_queue.add_used(desc_chain);
true
}
pub fn process_mrg_rx<T: TapT>(
rx_queue: &mut Queue,
tap: &mut T,
pending_buffer: &mut Option<PendingBuffer>,
) -> result::Result<(), NetError> {
unimplemented!("Unimplemented on Windows")
}
pub fn process_rx<T: TapT>(
rx_queue: &mut Queue,
tap: &mut T,
rx_buf: &mut [u8],
deferred_rx: &mut bool,
rx_count: &mut usize,
overlapped_wrapper: &mut OverlappedWrapper,
) -> bool {
let mut needs_interrupt = false;
let mut first_frame = true;
loop {
let res = if *deferred_rx {
Ok(*rx_count)
} else {
tap.try_read_result(overlapped_wrapper)
};
match res {
Ok(count) => {
*rx_count = count;
if !rx_single_frame(rx_queue, rx_buf, *rx_count) {
*deferred_rx = true;
break;
} else if first_frame {
rx_queue.trigger_interrupt();
first_frame = false;
} else {
needs_interrupt = true;
}
match unsafe { tap.read_overlapped(rx_buf, overlapped_wrapper) } {
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
warn!("net: rx: read_overlapped failed: {}", e);
break;
}
Err(e) => {
panic!("read_overlapped failed: {e}");
}
_ => {}
}
*deferred_rx = false;
}
Err(e) => {
if e.kind() != std::io::ErrorKind::WouldBlock {
warn!("net: rx: failed to read tap: {}", e);
match unsafe { tap.read_overlapped(rx_buf, overlapped_wrapper) } {
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
warn!("net: rx: read_overlapped failed: {}", e);
break;
}
Err(e) => {
panic!("read_overlapped failed: {e}");
}
_ => {}
}
}
break;
}
}
}
needs_interrupt
}
pub fn process_tx<T: TapT>(tx_queue: &mut Queue, tap: &mut T) {
fn read_to_end(r: &mut Reader, buf: &mut [u8]) -> io::Result<usize> {
let mut count = 0;
while count < buf.len() {
match r.read(&mut buf[count..]) {
Ok(0) => break,
Ok(n) => count += n,
Err(e) => return Err(e),
}
}
Ok(count)
}
while let Some(mut desc_chain) = tx_queue.pop() {
let mut frame = [0u8; MAX_BUFFER_SIZE];
match read_to_end(&mut desc_chain.reader, &mut frame[..]) {
Ok(len) => {
if let Err(err) = tap.write_all(&frame[..len]) {
error!("net: tx: failed to write to tap: {}", err);
}
}
Err(e) => error!("net: tx: failed to read frame into buffer: {}", e),
}
tx_queue.add_used(desc_chain);
}
tx_queue.trigger_interrupt();
}
impl<T> Worker<T>
where
T: TapT + ReadNotifier,
{
pub(super) fn process_rx_slirp(&mut self) -> bool {
process_rx(
&mut self.rx_queue,
&mut self.tap,
&mut self.rx_buf,
&mut self.deferred_rx,
&mut self.rx_count,
&mut self.overlapped_wrapper,
)
}
pub(in crate::virtio) fn handle_rx_token(
&mut self,
wait_ctx: &WaitContext<Token>,
_pending_buffer: &mut PendingBuffer,
) -> result::Result<(), NetError> {
let mut needs_interrupt = false;
if self.deferred_rx {
if rx_single_frame(&mut self.rx_queue, &mut self.rx_buf, self.rx_count) {
self.deferred_rx = false;
needs_interrupt = true;
} else {
wait_ctx
.delete(&self.tap)
.map_err(NetError::EventRemoveTap)?;
return Ok(());
}
}
needs_interrupt |= self.process_rx_slirp();
if needs_interrupt {
self.rx_queue.trigger_interrupt();
}
Ok(())
}
pub(in crate::virtio) fn handle_rx_queue(
&mut self,
wait_ctx: &WaitContext<Token>,
_tap_polling_enabled: bool,
) -> result::Result<(), NetError> {
if self.deferred_rx && rx_single_frame(&mut self.rx_queue, &mut self.rx_buf, self.rx_count)
{
match wait_ctx.add(&self.tap, Token::RxTap) {
Ok(_) => {}
Err(e) if e.errno() == EEXIST => {}
Err(e) => {
return Err(NetError::EventAddTap(e));
}
}
self.deferred_rx = false;
self.rx_queue.trigger_interrupt();
}
Ok(())
}
}