diff options
author | Stephen Barber <smbarber@chromium.org> | 2019-10-02 18:36:21 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-03 19:44:37 +0000 |
commit | 28a9d2b70d98e4fd8ce466190a52b85cf270e7bb (patch) | |
tree | 2424a3d47f40f3b8feb5d87bf3dd52834ea4b12d | |
parent | 82ff397489cc9fcc6bee1cdc98aa5eede18f8978 (diff) | |
download | crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.tar crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.tar.gz crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.tar.bz2 crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.tar.lz crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.tar.xz crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.tar.zst crosvm-28a9d2b70d98e4fd8ce466190a52b85cf270e7bb.zip |
devices: virtio_net: avoid busylooping when no rx buffers available
If the guest is unable to return rx queue buffers to the device, we should temporarily stop polling for reads on the tap fd. Otherwise, we'll spin and burn CPU needlessly. BUG=chromium:1010742 TEST=repro from b/141940546 Change-Id: Iac004e870779a8dd39004f44b44e17a2b45bcfa1 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1836914 Tested-by: Stephen Barber <smbarber@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Dylan Reid <dgreid@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Stephen Barber <smbarber@chromium.org>
-rw-r--r-- | devices/src/virtio/net.rs | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs index 2a4784c..43fba38 100644 --- a/devices/src/virtio/net.rs +++ b/devices/src/virtio/net.rs @@ -38,6 +38,10 @@ pub enum NetError { CreatePollContext(SysError), /// Cloning kill eventfd failed. CloneKillEventFd(SysError), + /// Adding the tap fd back to the poll context failed. + PollAddTap(SysError), + /// Removing the tap fd from the poll context failed. + PollDeleteTap(SysError), /// Open tap device failed. TapOpen(TapError), /// Setting tap IP failed. @@ -66,6 +70,8 @@ impl Display for NetError { CreateKillEventFd(e) => write!(f, "failed to create kill eventfd: {}", e), CreatePollContext(e) => write!(f, "failed to create poll context: {}", e), CloneKillEventFd(e) => write!(f, "failed to clone kill eventfd: {}", e), + PollAddTap(e) => write!(f, "failed to add tap fd to poll context: {}", e), + PollDeleteTap(e) => write!(f, "failed to remove tap fd from poll context: {}", e), TapOpen(e) => write!(f, "failed to open tap device: {}", e), TapSetIp(e) => write!(f, "failed to set tap IP: {}", e), TapSetNetmask(e) => write!(f, "failed to set tap netmask: {}", e), @@ -231,6 +237,9 @@ where if self.rx_single_frame() { self.deferred_rx = false; } else { + // The guest has not yet made any buffers available. Remove the + // tapfd from the poll context until more are made available. + poll_ctx.delete(&self.tap).map_err(NetError::PollDeleteTap); continue; } } @@ -243,6 +252,11 @@ where } // There should be a buffer available now to receive the frame into. if self.deferred_rx && self.rx_single_frame() { + // The guest has made buffers available, so add the tap back to the + // poll context. + poll_ctx + .add(&self.tap, Token::RxTap) + .map_err(NetError::PollAddTap); self.deferred_rx = false; } } |