mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: vhost_user: Move reconnection code to module
The reconnection code is moved to the vhost-user module as it is a common place to be shared across all vhost-user devices. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
@@ -2,13 +2,21 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
VIRTIO_F_IN_ORDER, VIRTIO_F_NOTIFICATION_DATA, VIRTIO_F_ORDER_PLATFORM,
|
EpollHelper, EpollHelperError, EpollHelperHandler, Queue, VirtioInterrupt,
|
||||||
VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_RING_INDIRECT_DESC, VIRTIO_F_RING_PACKED, VIRTIO_F_VERSION_1,
|
EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IN_ORDER, VIRTIO_F_NOTIFICATION_DATA,
|
||||||
|
VIRTIO_F_ORDER_PLATFORM, VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_RING_INDIRECT_DESC,
|
||||||
|
VIRTIO_F_RING_PACKED, VIRTIO_F_VERSION_1,
|
||||||
};
|
};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::sync::{atomic::AtomicBool, Arc, Barrier, Mutex};
|
||||||
use vhost::vhost_user::message::VhostUserVirtioFeatures;
|
use vhost::vhost_user::message::VhostUserVirtioFeatures;
|
||||||
|
use vhost::vhost_user::Master;
|
||||||
use vhost::Error as VhostError;
|
use vhost::Error as VhostError;
|
||||||
use vm_memory::Error as MmapError;
|
use vm_memory::{Error as MmapError, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
||||||
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
use vu_common_ctrl::{connect_vhost_user, reinitialize_vhost_user};
|
||||||
|
|
||||||
pub mod blk;
|
pub mod blk;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
@@ -114,3 +122,110 @@ pub const DEFAULT_VIRTIO_FEATURES: u64 = 1 << VIRTIO_F_RING_INDIRECT_DESC
|
|||||||
| 1 << VIRTIO_F_ORDER_PLATFORM
|
| 1 << VIRTIO_F_ORDER_PLATFORM
|
||||||
| 1 << VIRTIO_F_NOTIFICATION_DATA
|
| 1 << VIRTIO_F_NOTIFICATION_DATA
|
||||||
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
||||||
|
|
||||||
|
const HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
|
||||||
|
|
||||||
|
pub struct ReconnectEpollHandler {
|
||||||
|
pub vu: Arc<Mutex<Master>>,
|
||||||
|
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
|
pub kill_evt: EventFd,
|
||||||
|
pub pause_evt: EventFd,
|
||||||
|
pub queues: Vec<Queue>,
|
||||||
|
pub queue_evts: Vec<EventFd>,
|
||||||
|
pub virtio_interrupt: Arc<dyn VirtioInterrupt>,
|
||||||
|
pub acked_features: u64,
|
||||||
|
pub acked_protocol_features: u64,
|
||||||
|
pub socket_path: String,
|
||||||
|
pub server: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReconnectEpollHandler {
|
||||||
|
pub fn run(
|
||||||
|
&mut self,
|
||||||
|
paused: Arc<AtomicBool>,
|
||||||
|
paused_sync: Arc<Barrier>,
|
||||||
|
) -> std::result::Result<(), EpollHelperError> {
|
||||||
|
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
|
||||||
|
helper.add_event_custom(
|
||||||
|
self.vu.lock().unwrap().as_raw_fd(),
|
||||||
|
HUP_CONNECTION_EVENT,
|
||||||
|
epoll::Events::EPOLLHUP,
|
||||||
|
)?;
|
||||||
|
helper.run(paused, paused_sync, self)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reconnect(&mut self, helper: &mut EpollHelper) -> std::result::Result<(), EpollHelperError> {
|
||||||
|
helper.del_event_custom(
|
||||||
|
self.vu.lock().unwrap().as_raw_fd(),
|
||||||
|
HUP_CONNECTION_EVENT,
|
||||||
|
epoll::Events::EPOLLHUP,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut vhost_user = connect_vhost_user(
|
||||||
|
self.server,
|
||||||
|
&self.socket_path,
|
||||||
|
self.queues.len() as u64,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
EpollHelperError::IoError(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
format!("failed connecting vhost-user backend{:?}", e),
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Initialize the backend
|
||||||
|
reinitialize_vhost_user(
|
||||||
|
&mut vhost_user,
|
||||||
|
self.mem.memory().deref(),
|
||||||
|
self.queues.clone(),
|
||||||
|
self.queue_evts
|
||||||
|
.iter()
|
||||||
|
.map(|q| q.try_clone().unwrap())
|
||||||
|
.collect(),
|
||||||
|
&self.virtio_interrupt,
|
||||||
|
self.acked_features,
|
||||||
|
self.acked_protocol_features,
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
EpollHelperError::IoError(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
format!("failed reconnecting vhost-user backend{:?}", e),
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
helper.add_event_custom(
|
||||||
|
vhost_user.as_raw_fd(),
|
||||||
|
HUP_CONNECTION_EVENT,
|
||||||
|
epoll::Events::EPOLLHUP,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Update vhost-user reference
|
||||||
|
let mut vu = self.vu.lock().unwrap();
|
||||||
|
*vu = vhost_user;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EpollHelperHandler for ReconnectEpollHandler {
|
||||||
|
fn handle_event(&mut self, helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
||||||
|
let ev_type = event.data as u16;
|
||||||
|
match ev_type {
|
||||||
|
HUP_CONNECTION_EVENT => {
|
||||||
|
if let Err(e) = self.reconnect(helper) {
|
||||||
|
error!("failed to reconnect vhost-user backend: {:?}", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("Unknown event for vhost-user reconnection thread");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::super::{
|
|
||||||
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
|
|
||||||
VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST,
|
|
||||||
};
|
|
||||||
use super::vu_common_ctrl::{
|
|
||||||
add_memory_region, connect_vhost_user, negotiate_features_vhost_user, reinitialize_vhost_user,
|
|
||||||
reset_vhost_user, setup_vhost_user, update_mem_table, VhostUserConfig,
|
|
||||||
};
|
|
||||||
use super::{Error, Result};
|
|
||||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||||
use crate::{VirtioInterrupt, VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_VERSION_1};
|
use crate::vhost_user::vu_common_ctrl::{
|
||||||
|
add_memory_region, connect_vhost_user, negotiate_features_vhost_user, reset_vhost_user,
|
||||||
|
setup_vhost_user, update_mem_table, VhostUserConfig,
|
||||||
|
};
|
||||||
|
use crate::vhost_user::{Error, ReconnectEpollHandler, Result};
|
||||||
|
use crate::{
|
||||||
|
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
|
||||||
|
VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterrupt, EPOLL_HELPER_EVENT_LAST,
|
||||||
|
VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_VERSION_1,
|
||||||
|
};
|
||||||
use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig};
|
use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig};
|
||||||
use seccomp::{SeccompAction, SeccompFilter};
|
use seccomp::{SeccompAction, SeccompFilter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@@ -92,115 +92,6 @@ impl EpollHelperHandler for NetCtrlEpollHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconnection thread
|
|
||||||
// Event meaning the connection was closed.
|
|
||||||
const HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
|
|
||||||
|
|
||||||
pub struct ReconnectEpollHandler {
|
|
||||||
pub vu: Arc<Mutex<Master>>,
|
|
||||||
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
|
||||||
pub kill_evt: EventFd,
|
|
||||||
pub pause_evt: EventFd,
|
|
||||||
pub queues: Vec<Queue>,
|
|
||||||
pub queue_evts: Vec<EventFd>,
|
|
||||||
pub virtio_interrupt: Arc<dyn VirtioInterrupt>,
|
|
||||||
pub acked_features: u64,
|
|
||||||
pub acked_protocol_features: u64,
|
|
||||||
pub socket_path: String,
|
|
||||||
pub server: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ReconnectEpollHandler {
|
|
||||||
pub fn run(
|
|
||||||
&mut self,
|
|
||||||
paused: Arc<AtomicBool>,
|
|
||||||
paused_sync: Arc<Barrier>,
|
|
||||||
) -> std::result::Result<(), EpollHelperError> {
|
|
||||||
let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
|
|
||||||
helper.add_event_custom(
|
|
||||||
self.vu.lock().unwrap().as_raw_fd(),
|
|
||||||
HUP_CONNECTION_EVENT,
|
|
||||||
epoll::Events::EPOLLHUP,
|
|
||||||
)?;
|
|
||||||
helper.run(paused, paused_sync, self)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reconnect(&mut self, helper: &mut EpollHelper) -> std::result::Result<(), EpollHelperError> {
|
|
||||||
helper.del_event_custom(
|
|
||||||
self.vu.lock().unwrap().as_raw_fd(),
|
|
||||||
HUP_CONNECTION_EVENT,
|
|
||||||
epoll::Events::EPOLLHUP,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut vhost_user_net = connect_vhost_user(
|
|
||||||
self.server,
|
|
||||||
&self.socket_path,
|
|
||||||
self.queues.len() as u64,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
EpollHelperError::IoError(std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
format!("failed connecting vhost-user backend{:?}", e),
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Initialize the backend
|
|
||||||
reinitialize_vhost_user(
|
|
||||||
&mut vhost_user_net,
|
|
||||||
self.mem.memory().deref(),
|
|
||||||
self.queues.clone(),
|
|
||||||
self.queue_evts
|
|
||||||
.iter()
|
|
||||||
.map(|q| q.try_clone().unwrap())
|
|
||||||
.collect(),
|
|
||||||
&self.virtio_interrupt,
|
|
||||||
self.acked_features,
|
|
||||||
self.acked_protocol_features,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
EpollHelperError::IoError(std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
format!("failed reconnecting vhost-user backend{:?}", e),
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
helper.add_event_custom(
|
|
||||||
vhost_user_net.as_raw_fd(),
|
|
||||||
HUP_CONNECTION_EVENT,
|
|
||||||
epoll::Events::EPOLLHUP,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Update vhost-user reference
|
|
||||||
let mut vu = self.vu.lock().unwrap();
|
|
||||||
*vu = vhost_user_net;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EpollHelperHandler for ReconnectEpollHandler {
|
|
||||||
fn handle_event(&mut self, helper: &mut EpollHelper, event: &epoll::Event) -> bool {
|
|
||||||
let ev_type = event.data as u16;
|
|
||||||
match ev_type {
|
|
||||||
HUP_CONNECTION_EVENT => {
|
|
||||||
if let Err(e) = self.reconnect(helper) {
|
|
||||||
error!("failed to reconnect vhost-user-net backend: {:?}", e);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
error!("Unknown event for vhost-user-net reconnection thread");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Net {
|
pub struct Net {
|
||||||
common: VirtioCommon,
|
common: VirtioCommon,
|
||||||
id: String,
|
id: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user