diff options
author | Jakub Staron <jstaron@google.com> | 2019-06-11 15:17:49 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-06-24 07:53:29 +0000 |
commit | 4aaefc377f37a14ecad2725946d8385b92ceb1e4 (patch) | |
tree | 3b5ae801832958b27df09db6150e44a43872bda5 | |
parent | dd11d434730a5dea56106d0533bf42c6b7206ed0 (diff) | |
download | crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.tar crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.tar.gz crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.tar.bz2 crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.tar.lz crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.tar.xz crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.tar.zst crosvm-4aaefc377f37a14ecad2725946d8385b92ceb1e4.zip |
devices: Use Reader/Writer interfaces in virtio-net.
BUG=chromium:966258 TEST=tast run ${IP} vm.CrostiniStartEverything TEST=tast run ${IP} vm.CrostiniNetworkPerf Change-Id: I99c5b9e564c219b76593d729fb934722fc8a3431 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1658980 Reviewed-by: Stephen Barber <smbarber@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Stephen Barber <smbarber@chromium.org>
-rw-r--r-- | devices/src/virtio/net.rs | 110 |
1 files changed, 34 insertions, 76 deletions
diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs index 61a82cc..cfb43b9 100644 --- a/devices/src/virtio/net.rs +++ b/devices/src/virtio/net.rs @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std::cmp; use std::fmt::{self, Display}; use std::mem; use std::net::Ipv4Addr; @@ -14,12 +13,13 @@ use std::thread; use libc::EAGAIN; use net_sys; use net_util::{Error as TapError, MacAddress, TapT}; +use sys_util::guest_memory::Error as MemoryError; use sys_util::Error as SysError; use sys_util::{error, warn, EventFd, GuestMemory, PollContext, PollToken}; use virtio_sys::virtio_net::virtio_net_hdr_v1; use virtio_sys::{vhost, virtio_net}; -use super::{Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_NET}; +use super::{Queue, Reader, VirtioDevice, Writer, INTERRUPT_STATUS_USED_RING, TYPE_NET}; /// The maximum buffer size when segmentation offload is enabled. This /// includes the 12-byte virtio net header. @@ -108,54 +108,29 @@ where // if a buffer was used, and false if the frame must be deferred until a buffer // is made available by the driver. fn rx_single_frame(&mut self) -> bool { - let mut next_desc = self.rx_queue.pop(&self.mem); - - if next_desc.is_none() { - return false; - } - - // We just checked that the head descriptor exists. - let head_index = next_desc.as_ref().unwrap().index; - let mut write_count = 0; - - // Copy from frame into buffer, which may span multiple descriptors. - loop { - match next_desc { - Some(desc) => { - if !desc.is_write_only() { - break; - } - let limit = cmp::min(write_count + desc.len as usize, self.rx_count); - let source_slice = &self.rx_buf[write_count..limit]; - let write_result = self.mem.write_at_addr(source_slice, desc.addr); - - match write_result { - Ok(sz) => { - write_count += sz; - } - Err(e) => { - warn!("net: rx: failed to write slice: {}", e); - break; - } - }; - - if write_count >= self.rx_count { - break; - } - next_desc = desc.next_descriptor(); - } - None => { - warn!( - "net: rx: buffer is too small to hold frame of size {}", - self.rx_count - ); - break; - } + let desc_chain = match self.rx_queue.pop(&self.mem) { + Some(desc) => desc, + None => return false, + }; + + let index = desc_chain.index; + let mut writer = Writer::new(&self.mem, desc_chain); + + match writer.write_all(&self.rx_buf[0..self.rx_count]) { + Ok(()) => (), + Err(MemoryError::ShortWrite { .. }) => { + warn!( + "net: rx: buffer is too small to hold frame of size {}", + self.rx_count + ); + } + Err(e) => { + warn!("net: rx: failed to write slice: {}", e); } } self.rx_queue - .add_used(&self.mem, head_index, write_count as u32); + .add_used(&self.mem, index, writer.bytes_written() as u32); // Interrupt the guest immediately for received frames to // reduce latency. @@ -191,41 +166,24 @@ where fn process_tx(&mut self) { let mut frame = [0u8; MAX_BUFFER_SIZE]; - while let Some(avail_desc) = self.tx_queue.pop(&self.mem) { - let head_index = avail_desc.index; - let mut next_desc = Some(avail_desc); - let mut read_count = 0; + while let Some(desc_chain) = self.tx_queue.pop(&self.mem) { + let index = desc_chain.index; + let mut reader = Reader::new(&self.mem, desc_chain); - // Copy buffer from across multiple descriptors. - while let Some(desc) = next_desc { - if desc.is_write_only() { - break; - } - let limit = cmp::min(read_count + desc.len as usize, frame.len()); - let read_result = self - .mem - .read_at_addr(&mut frame[read_count..limit as usize], desc.addr); - match read_result { - Ok(sz) => { - read_count += sz; - } - Err(e) => { - warn!("net: tx: failed to read slice: {}", e); - break; + match reader.read(&mut frame) { + // We need to copy frame into continuous buffer before writing it to tap + // because tap requires frame to complete in a single write. + Ok(read_count) => { + if let Err(err) = self.tap.write_all(&frame[..read_count]) { + error!("net: tx: failed to write to tap: {}", err); } } - next_desc = desc.next_descriptor(); - } - - let write_result = self.tap.write(&frame[..read_count as usize]); - match write_result { - Ok(_) => {} - Err(e) => { - warn!("net: tx: error failed to write to tap: {}", e); + Err(err) => { + error!("net: tx: failed to read frame into buffer: {}", err); } - }; + } - self.tx_queue.add_used(&self.mem, head_index, 0); + self.tx_queue.add_used(&self.mem, index, 0); } self.signal_used_queue(); |