summary refs log tree commit diff
path: root/devices/src/virtio/vhost/net.rs
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-03-26 12:26:18 +0000
committerAlyssa Ross <hi@alyssa.is>2020-03-26 12:26:18 +0000
commitdbd5f925b6b2f4cb1bf87563be4d24c8ed35689a (patch)
tree5a51c0af87b6a8bb3dfe43d599cabf96523a7f6f /devices/src/virtio/vhost/net.rs
parent88b7821302043b7ad871fcc0c7748573d0f140e2 (diff)
parent22964eab8874d41cf0eadf03dfeb1ffb653283e5 (diff)
downloadcrosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar
crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.gz
crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.bz2
crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.lz
crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.xz
crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.tar.zst
crosvm-dbd5f925b6b2f4cb1bf87563be4d24c8ed35689a.zip
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'devices/src/virtio/vhost/net.rs')
-rw-r--r--devices/src/virtio/vhost/net.rs66
1 files changed, 66 insertions, 0 deletions
diff --git a/devices/src/virtio/vhost/net.rs b/devices/src/virtio/vhost/net.rs
index ff72970..542423a 100644
--- a/devices/src/virtio/vhost/net.rs
+++ b/devices/src/virtio/vhost/net.rs
@@ -14,9 +14,12 @@ use sys_util::{error, warn, EventFd, GuestMemory};
 use vhost::NetT as VhostNetT;
 use virtio_sys::virtio_net;
 
+use super::control_socket::*;
 use super::worker::Worker;
 use super::{Error, Result};
+use crate::pci::MsixStatus;
 use crate::virtio::{Interrupt, Queue, VirtioDevice, TYPE_NET};
+use msg_socket::{MsgReceiver, MsgSender};
 
 const QUEUE_SIZE: u16 = 256;
 const NUM_QUEUES: usize = 2;
@@ -31,6 +34,8 @@ pub struct Net<T: TapT, U: VhostNetT<T>> {
     vhost_interrupt: Option<Vec<EventFd>>,
     avail_features: u64,
     acked_features: u64,
+    request_socket: Option<VhostDevRequestSocket>,
+    response_socket: Option<VhostDevResponseSocket>,
 }
 
 impl<T, U> Net<T, U>
@@ -85,6 +90,8 @@ where
             vhost_interrupt.push(EventFd::new().map_err(Error::VhostIrqCreate)?);
         }
 
+        let (request_socket, response_socket) = create_control_sockets();
+
         Ok(Net {
             workers_kill_evt: Some(kill_evt.try_clone().map_err(Error::CloneKillEventFd)?),
             kill_evt,
@@ -94,6 +101,8 @@ where
             vhost_interrupt: Some(vhost_interrupt),
             avail_features,
             acked_features: 0u64,
+            request_socket,
+            response_socket,
         })
     }
 }
@@ -143,6 +152,14 @@ where
         }
         keep_fds.push(self.kill_evt.as_raw_fd());
 
+        if let Some(request_socket) = &self.request_socket {
+            keep_fds.push(request_socket.as_raw_fd());
+        }
+
+        if let Some(response_socket) = &self.response_socket {
+            keep_fds.push(response_socket.as_raw_fd());
+        }
+
         keep_fds
     }
 
@@ -189,6 +206,11 @@ where
                 if let Some(vhost_interrupt) = self.vhost_interrupt.take() {
                     if let Some(kill_evt) = self.workers_kill_evt.take() {
                         let acked_features = self.acked_features;
+                        let socket = if self.response_socket.is_some() {
+                            self.response_socket.take()
+                        } else {
+                            None
+                        };
                         let worker_result = thread::Builder::new()
                             .name("vhost_net".to_string())
                             .spawn(move || {
@@ -199,6 +221,7 @@ where
                                     interrupt,
                                     acked_features,
                                     kill_evt,
+                                    socket,
                                 );
                                 let activate_vqs = |handle: &U| -> Result<()> {
                                     for idx in 0..NUM_QUEUES {
@@ -251,6 +274,48 @@ where
         }
     }
 
+    fn control_notify(&self, behavior: MsixStatus) {
+        if self.worker_thread.is_none() || self.request_socket.is_none() {
+            return;
+        }
+        if let Some(socket) = &self.request_socket {
+            match behavior {
+                MsixStatus::EntryChanged(index) => {
+                    if let Err(e) = socket.send(&VhostDevRequest::MsixEntryChanged(index)) {
+                        error!(
+                            "{} failed to send VhostMsixEntryChanged request for entry {}: {:?}",
+                            self.debug_label(),
+                            index,
+                            e
+                        );
+                        return;
+                    }
+                    if let Err(e) = socket.recv() {
+                        error!("{} failed to receive VhostMsixEntryChanged response for entry {}: {:?}", self.debug_label(), index, e);
+                    }
+                }
+                MsixStatus::Changed => {
+                    if let Err(e) = socket.send(&VhostDevRequest::MsixChanged) {
+                        error!(
+                            "{} failed to send VhostMsixChanged request: {:?}",
+                            self.debug_label(),
+                            e
+                        );
+                        return;
+                    }
+                    if let Err(e) = socket.recv() {
+                        error!(
+                            "{} failed to receive VhostMsixChanged response {:?}",
+                            self.debug_label(),
+                            e
+                        );
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+
     fn reset(&mut self) -> bool {
         // Only kill the child if it claimed its eventfd.
         if self.workers_kill_evt.is_none() && self.kill_evt.write(1).is_err() {
@@ -269,6 +334,7 @@ where
                     self.tap = Some(tap);
                     self.vhost_interrupt = Some(worker.vhost_interrupt);
                     self.workers_kill_evt = Some(worker.kill_evt);
+                    self.response_socket = worker.response_socket;
                     return true;
                 }
             }