vm-virtio: Implement reset() for virtio-net

The virtio specification defines a device can be reset, which was not
supported by this virtio-net implementation. The reason it is needed is
to support unbinding this device from the guest driver, and rebind it to
vfio-pci driver.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2019-10-02 11:21:34 -07:00 committed by Samuel Ortiz
parent 8288cb2ac8
commit 59b4aaba87

View File

@ -439,6 +439,8 @@ pub struct Net {
// The config space will only consist of the MAC address specified by the user, // The config space will only consist of the MAC address specified by the user,
// or nothing, if no such address if provided. // or nothing, if no such address if provided.
config_space: Vec<u8>, config_space: Vec<u8>,
queue_evts: Option<Vec<EventFd>>,
interrupt_cb: Option<Arc<VirtioInterrupt>>,
} }
impl Net { impl Net {
@ -481,6 +483,8 @@ impl Net {
avail_features, avail_features,
acked_features: 0u64, acked_features: 0u64,
config_space, config_space,
queue_evts: None,
interrupt_cb: None,
}) })
} }
@ -597,7 +601,22 @@ impl VirtioDevice for Net {
}; };
self.kill_evt = Some(self_kill_evt); self.kill_evt = Some(self_kill_evt);
if let Some(tap) = self.tap.take() { if let Some(tap) = self.tap.clone() {
// Save the interrupt EventFD as we need to return it on reset
// but clone it to pass into the thread.
self.interrupt_cb = Some(interrupt_cb.clone());
let mut tmp_queue_evts: Vec<EventFd> = Vec::new();
for queue_evt in queue_evts.iter() {
// Save the queue EventFD as we need to return it on reset
// but clone it to pass into the thread.
tmp_queue_evts.push(queue_evt.try_clone().map_err(|e| {
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?);
}
self.queue_evts = Some(tmp_queue_evts);
let rx_queue = queues.remove(0); let rx_queue = queues.remove(0);
let tx_queue = queues.remove(0); let tx_queue = queues.remove(0);
let rx_queue_evt = queue_evts.remove(0); let rx_queue_evt = queue_evts.remove(0);
@ -626,4 +645,17 @@ impl VirtioDevice for Net {
} }
Err(ActivateError::BadActivate) Err(ActivateError::BadActivate)
} }
fn reset(&mut self) -> Option<(Arc<VirtioInterrupt>, Vec<EventFd>)> {
if let Some(kill_evt) = self.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
// Return the interrupt and queue EventFDs
Some((
self.interrupt_cb.take().unwrap(),
self.queue_evts.take().unwrap(),
))
}
} }