mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-07-15 13:47:14 +00:00
vm-virtio: Implement reset() for vhost-user-net
The virtio specification defines a device can be reset, which was not supported by this vhost-user-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:
parent
8225d4cd6e
commit
4b1328a29c
@ -30,12 +30,14 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {}
|
|||||||
|
|
||||||
pub struct Net {
|
pub struct Net {
|
||||||
vhost_user_net: Master,
|
vhost_user_net: Master,
|
||||||
kill_evt: EventFd,
|
kill_evt: Option<EventFd>,
|
||||||
avail_features: u64,
|
avail_features: u64,
|
||||||
acked_features: u64,
|
acked_features: u64,
|
||||||
backend_features: u64,
|
backend_features: u64,
|
||||||
config_space: Vec<u8>,
|
config_space: Vec<u8>,
|
||||||
queue_sizes: Vec<u16>,
|
queue_sizes: Vec<u16>,
|
||||||
|
queue_evts: Option<Vec<EventFd>>,
|
||||||
|
interrupt_cb: Option<Arc<VirtioInterrupt>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Net {
|
impl Net {
|
||||||
@ -44,8 +46,6 @@ impl Net {
|
|||||||
let mut vhost_user_net = Master::connect(&vu_cfg.sock, vu_cfg.num_queues as u64)
|
let mut vhost_user_net = Master::connect(&vu_cfg.sock, vu_cfg.num_queues as u64)
|
||||||
.map_err(Error::VhostUserCreateMaster)?;
|
.map_err(Error::VhostUserCreateMaster)?;
|
||||||
|
|
||||||
let kill_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?;
|
|
||||||
|
|
||||||
// Filling device and vring features VMM supports.
|
// Filling device and vring features VMM supports.
|
||||||
let mut avail_features = 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM
|
let mut avail_features = 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM
|
||||||
| 1 << virtio_net::VIRTIO_NET_F_CSUM
|
| 1 << virtio_net::VIRTIO_NET_F_CSUM
|
||||||
@ -108,20 +108,24 @@ impl Net {
|
|||||||
|
|
||||||
Ok(Net {
|
Ok(Net {
|
||||||
vhost_user_net,
|
vhost_user_net,
|
||||||
kill_evt,
|
kill_evt: None,
|
||||||
avail_features,
|
avail_features,
|
||||||
acked_features,
|
acked_features,
|
||||||
backend_features,
|
backend_features,
|
||||||
config_space,
|
config_space,
|
||||||
queue_sizes: vec![vu_cfg.queue_size; vu_cfg.num_queues],
|
queue_sizes: vec![vu_cfg.queue_size; vu_cfg.num_queues],
|
||||||
|
queue_evts: None,
|
||||||
|
interrupt_cb: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Net {
|
impl Drop for Net {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Err(_e) = self.kill_evt.write(1) {
|
if let Some(kill_evt) = self.kill_evt.take() {
|
||||||
error!("failed to kill vhost-user-net with error {}", _e);
|
if let Err(e) = kill_evt.write(1) {
|
||||||
|
error!("failed to kill vhost-user-net: {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,10 +201,30 @@ impl VirtioDevice for Net {
|
|||||||
queues: Vec<Queue>,
|
queues: Vec<Queue>,
|
||||||
queue_evts: Vec<EventFd>,
|
queue_evts: Vec<EventFd>,
|
||||||
) -> ActivateResult {
|
) -> ActivateResult {
|
||||||
let handler_kill_evt = self
|
let (self_kill_evt, kill_evt) =
|
||||||
.kill_evt
|
match EventFd::new(EFD_NONBLOCK).and_then(|e| Ok((e.try_clone()?, e))) {
|
||||||
.try_clone()
|
Ok(v) => v,
|
||||||
.map_err(|_| ActivateError::CloneKillEventFd)?;
|
Err(e) => {
|
||||||
|
error!("failed creating kill EventFd pair: {}", e);
|
||||||
|
return Err(ActivateError::BadActivate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.kill_evt = Some(self_kill_evt);
|
||||||
|
|
||||||
|
// 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 vu_interrupt_list = setup_vhost_user(
|
let vu_interrupt_list = setup_vhost_user(
|
||||||
&mut self.vhost_user_net,
|
&mut self.vhost_user_net,
|
||||||
@ -213,7 +237,7 @@ impl VirtioDevice for Net {
|
|||||||
|
|
||||||
let mut handler = VhostUserEpollHandler::<SlaveReqHandler>::new(VhostUserEpollConfig {
|
let mut handler = VhostUserEpollHandler::<SlaveReqHandler>::new(VhostUserEpollConfig {
|
||||||
interrupt_cb,
|
interrupt_cb,
|
||||||
kill_evt: handler_kill_evt,
|
kill_evt,
|
||||||
vu_interrupt_list,
|
vu_interrupt_list,
|
||||||
slave_req_handler: None,
|
slave_req_handler: None,
|
||||||
});
|
});
|
||||||
@ -230,4 +254,22 @@ impl VirtioDevice for Net {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) -> Option<(Arc<VirtioInterrupt>, Vec<EventFd>)> {
|
||||||
|
if let Err(e) = reset_vhost_user(&mut self.vhost_user_net, self.queue_sizes.len()) {
|
||||||
|
error!("Failed to reset vhost-user daemon: {:?}", e);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user