mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
virtio-devices, vmm: vhost: net: Add client mode support
Adding the support for an OVS vhost-user backend to connect as the vhost-user client. This means we introduce with this patch a new option to our `--net` parameter. This option is called 'server' in order to ask the VMM to run as the server for the vhost-user socket. Fixes #1745 Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
656b9f97f9
commit
b5c6b04b36
@ -24,10 +24,14 @@ pub use self::vu_common_ctrl::VhostUserConfig;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Failed accepting connection.
|
||||
AcceptConnection(io::Error),
|
||||
/// Invalid available address.
|
||||
AvailAddress,
|
||||
/// Queue number is not correct
|
||||
BadQueueNum,
|
||||
/// Failed binding vhost-user socket.
|
||||
BindSocket(io::Error),
|
||||
/// Creating kill eventfd failed.
|
||||
CreateKillEventFd(io::Error),
|
||||
/// Cloning kill eventfd failed.
|
||||
|
@ -16,6 +16,7 @@ use net_util::MacAddr;
|
||||
use seccomp::{SeccompAction, SeccompFilter};
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread;
|
||||
@ -46,6 +47,7 @@ pub struct Net {
|
||||
seccomp_action: SeccompAction,
|
||||
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
acked_protocol_features: u64,
|
||||
socket_path: Option<String>,
|
||||
}
|
||||
|
||||
impl Net {
|
||||
@ -56,9 +58,23 @@ impl Net {
|
||||
mac_addr: MacAddr,
|
||||
vu_cfg: VhostUserConfig,
|
||||
seccomp_action: SeccompAction,
|
||||
server: bool,
|
||||
) -> Result<Net> {
|
||||
let mut vhost_user_net = Master::connect(&vu_cfg.socket, vu_cfg.num_queues as u64)
|
||||
.map_err(Error::VhostUserCreateMaster)?;
|
||||
let mut socket_path: Option<String> = None;
|
||||
|
||||
let mut vhost_user_net = if server {
|
||||
info!("Binding vhost-user-net listener...");
|
||||
let listener = UnixListener::bind(&vu_cfg.socket).map_err(Error::BindSocket)?;
|
||||
info!("Waiting for incoming vhost-user-net connection...");
|
||||
let (stream, _) = listener.accept().map_err(Error::AcceptConnection)?;
|
||||
|
||||
socket_path = Some(vu_cfg.socket.clone());
|
||||
|
||||
Master::from_stream(stream, vu_cfg.num_queues as u64)
|
||||
} else {
|
||||
Master::connect(&vu_cfg.socket, vu_cfg.num_queues as u64)
|
||||
.map_err(Error::VhostUserCreateMaster)?
|
||||
};
|
||||
|
||||
// Filling device and vring features VMM supports.
|
||||
let mut avail_features = 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM
|
||||
@ -166,6 +182,7 @@ impl Net {
|
||||
seccomp_action,
|
||||
guest_memory: None,
|
||||
acked_protocol_features,
|
||||
socket_path,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -368,6 +385,11 @@ impl VirtioDevice for Net {
|
||||
|
||||
fn shutdown(&mut self) {
|
||||
let _ = unsafe { libc::close(self.vhost_user_net.as_raw_fd()) };
|
||||
|
||||
// Remove socket path if needed
|
||||
if let Some(socket_path) = &self.socket_path {
|
||||
let _ = std::fs::remove_file(socket_path);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_memory_region(
|
||||
|
@ -712,6 +712,9 @@ components:
|
||||
default: false
|
||||
vhost_socket:
|
||||
type: string
|
||||
vhost_mode:
|
||||
type: string
|
||||
default: "client"
|
||||
id:
|
||||
type: string
|
||||
fd:
|
||||
|
@ -878,6 +878,35 @@ impl DiskConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub enum VhostMode {
|
||||
Client,
|
||||
Server,
|
||||
}
|
||||
|
||||
impl Default for VhostMode {
|
||||
fn default() -> Self {
|
||||
VhostMode::Client
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseVhostModeError {
|
||||
InvalidValue(String),
|
||||
}
|
||||
|
||||
impl FromStr for VhostMode {
|
||||
type Err = ParseVhostModeError;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"client" => Ok(VhostMode::Client),
|
||||
"server" => Ok(VhostMode::Server),
|
||||
_ => Err(ParseVhostModeError::InvalidValue(s.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub struct NetConfig {
|
||||
#[serde(default = "default_netconfig_tap")]
|
||||
@ -900,6 +929,8 @@ pub struct NetConfig {
|
||||
pub vhost_user: bool,
|
||||
pub vhost_socket: Option<String>,
|
||||
#[serde(default)]
|
||||
pub vhost_mode: VhostMode,
|
||||
#[serde(default)]
|
||||
pub id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub fds: Option<Vec<i32>>,
|
||||
@ -944,6 +975,7 @@ impl Default for NetConfig {
|
||||
queue_size: default_netconfig_queue_size(),
|
||||
vhost_user: false,
|
||||
vhost_socket: None,
|
||||
vhost_mode: VhostMode::Client,
|
||||
id: None,
|
||||
fds: None,
|
||||
rate_limiter_config: None,
|
||||
@ -954,8 +986,8 @@ impl Default for NetConfig {
|
||||
impl NetConfig {
|
||||
pub const SYNTAX: &'static str = "Network parameters \
|
||||
\"tap=<if_name>,ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>,fd=<fd1:fd2...>,iommu=on|off,\
|
||||
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,\
|
||||
vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>,id=<device_id>,\
|
||||
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,\
|
||||
vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>,vhost_mode=client|server,\
|
||||
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
|
||||
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>\"";
|
||||
|
||||
@ -973,6 +1005,7 @@ impl NetConfig {
|
||||
.add("num_queues")
|
||||
.add("vhost_user")
|
||||
.add("socket")
|
||||
.add("vhost_mode")
|
||||
.add("id")
|
||||
.add("fd")
|
||||
.add("bw_size")
|
||||
@ -1016,6 +1049,10 @@ impl NetConfig {
|
||||
.unwrap_or(Toggle(false))
|
||||
.0;
|
||||
let vhost_socket = parser.get("socket");
|
||||
let vhost_mode = parser
|
||||
.convert("vhost_mode")
|
||||
.map_err(Error::ParseNetwork)?
|
||||
.unwrap_or_default();
|
||||
let id = parser.get("id");
|
||||
let fds = parser
|
||||
.convert::<IntegerList>("fd")
|
||||
@ -1084,6 +1121,7 @@ impl NetConfig {
|
||||
queue_size,
|
||||
vhost_user,
|
||||
vhost_socket,
|
||||
vhost_mode,
|
||||
id,
|
||||
fds,
|
||||
rate_limiter_config,
|
||||
|
@ -9,9 +9,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
//
|
||||
|
||||
use crate::config::ConsoleOutputMode;
|
||||
use crate::config::DeviceConfig;
|
||||
use crate::config::{DiskConfig, FsConfig, NetConfig, PmemConfig, VmConfig, VsockConfig};
|
||||
use crate::config::{
|
||||
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, VhostMode,
|
||||
VmConfig, VsockConfig,
|
||||
};
|
||||
use crate::device_tree::{DeviceNode, DeviceTree};
|
||||
#[cfg(feature = "kvm")]
|
||||
use crate::interrupt::kvm::KvmMsiInterruptManager as MsiInterruptManager;
|
||||
@ -2035,12 +2036,17 @@ impl DeviceManager {
|
||||
num_queues: net_cfg.num_queues,
|
||||
queue_size: net_cfg.queue_size,
|
||||
};
|
||||
let server = match net_cfg.vhost_mode {
|
||||
VhostMode::Client => false,
|
||||
VhostMode::Server => true,
|
||||
};
|
||||
let vhost_user_net_device = Arc::new(Mutex::new(
|
||||
match virtio_devices::vhost_user::Net::new(
|
||||
id.clone(),
|
||||
net_cfg.mac,
|
||||
vu_cfg,
|
||||
self.seccomp_action.clone(),
|
||||
server,
|
||||
) {
|
||||
Ok(vun_device) => vun_device,
|
||||
Err(e) => {
|
||||
|
Loading…
Reference in New Issue
Block a user