vmm: Support vhost-user-net via "--net"

Add a socket and vhost_user parameter to this option so that the same
configuration option can be used for both virtio-net and vhost-user-net.
For now it is necessary to specify both vhost_user and socket parameters
as auto activation is not yet implemented. The original command line
parameter is still supported for now.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2020-01-27 15:14:07 +00:00
parent e155e3690c
commit a831aa214c
4 changed files with 87 additions and 35 deletions

View File

@ -137,7 +137,8 @@ fn create_app<'a, 'b>(
"Network parameters \"tap=<if_name>,\
ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>,\
iommu=on|off,num_queues=<number_of_queues>,\
queue_size=<size_of_each_queue>\"",
queue_size=<size_of_each_queue>,\
vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>\"",
)
.takes_value(true)
.min_values(1)

View File

@ -307,6 +307,11 @@ components:
queue_size:
type: integer
default: 256
vhost_user:
type: boolean
default: false
vhost_socket:
type: string
RngConfig:
required:

View File

@ -55,6 +55,10 @@ pub enum Error {
ParseNetNumQueuesParam(std::num::ParseIntError),
/// Failed parsing network queue size parameter.
ParseNetQueueSizeParam(std::num::ParseIntError),
/// Failed to parse vhost parameters
ParseNetVhostParam(std::str::ParseBoolError),
/// Need a vhost socket
ParseNetVhostSocketRequired,
/// Failed parsing fs tag parameter.
ParseFsTagParam,
/// Failed parsing fs socket path parameter.
@ -431,6 +435,9 @@ pub struct NetConfig {
pub num_queues: usize,
#[serde(default = "default_netconfig_queue_size")]
pub queue_size: u16,
#[serde(default)]
pub vhost_user: bool,
pub vhost_socket: Option<String>,
}
fn default_netconfig_tap() -> Option<String> {
@ -469,6 +476,8 @@ impl NetConfig {
let mut iommu_str: &str = "";
let mut num_queues_str: &str = "";
let mut queue_size_str: &str = "";
let mut vhost_socket_str: &str = "";
let mut vhost_user_str: &str = "";
for param in params_list.iter() {
if param.starts_with("tap=") {
@ -485,6 +494,10 @@ impl NetConfig {
num_queues_str = &param[11..];
} else if param.starts_with("queue_size=") {
queue_size_str = &param[11..];
} else if param.starts_with("vhost_user=") {
vhost_user_str = &param[11..];
} else if param.starts_with("socket=") {
vhost_socket_str = &param[7..];
}
}
@ -495,6 +508,8 @@ impl NetConfig {
let iommu = parse_on_off(iommu_str)?;
let mut num_queues: usize = default_netconfig_num_queues();
let mut queue_size: u16 = default_netconfig_queue_size();
let mut vhost_user = false;
let mut vhost_socket = None;
if !tap_str.is_empty() {
tap = Some(tap_str.to_string());
@ -518,6 +533,17 @@ impl NetConfig {
.parse()
.map_err(Error::ParseNetQueueSizeParam)?;
}
if !vhost_user_str.is_empty() {
vhost_user = vhost_user_str.parse().map_err(Error::ParseNetVhostParam)?;
}
if !vhost_socket_str.is_empty() {
vhost_socket = Some(vhost_socket_str.to_owned());
}
// For now we require a socket if vhost-user is turned on
if vhost_user && vhost_socket.is_none() {
return Err(Error::ParseNetVhostSocketRequired);
}
Ok(NetConfig {
tap,
@ -527,6 +553,8 @@ impl NetConfig {
iommu,
num_queues,
queue_size,
vhost_user,
vhost_socket,
})
}
}

View File

@ -1032,49 +1032,67 @@ impl DeviceManager {
Ok(devices)
}
/// Add virto-net and vhost-user-net devices
fn make_virtio_net_devices(
vm_info: &VmInfo,
migratable_devices: &mut Vec<Arc<Mutex<dyn Migratable>>>,
) -> DeviceManagerResult<Vec<(VirtioDeviceArc, bool)>> {
let mut devices = Vec::new();
// Add virtio-net if required
if let Some(net_list_cfg) = &vm_info.vm_cfg.lock().unwrap().net {
for net_cfg in net_list_cfg.iter() {
let virtio_net_device = if let Some(ref tap_if_name) = net_cfg.tap {
Arc::new(Mutex::new(
vm_virtio::Net::new(
Some(tap_if_name),
None,
None,
Some(net_cfg.mac),
net_cfg.iommu,
net_cfg.num_queues,
net_cfg.queue_size,
)
.map_err(DeviceManagerError::CreateVirtioNet)?,
))
if net_cfg.vhost_user {
let vu_cfg = VhostUserConfig {
sock: net_cfg.vhost_socket.clone().unwrap(),
num_queues: net_cfg.num_queues,
queue_size: net_cfg.queue_size,
};
let vhost_user_net_device = Arc::new(Mutex::new(
vm_virtio::vhost_user::Net::new(net_cfg.mac, vu_cfg)
.map_err(DeviceManagerError::CreateVhostUserNet)?,
));
devices.push((
Arc::clone(&vhost_user_net_device)
as Arc<Mutex<dyn vm_virtio::VirtioDevice>>,
net_cfg.iommu,
));
migratable_devices
.push(Arc::clone(&vhost_user_net_device) as Arc<Mutex<dyn Migratable>>);
} else {
Arc::new(Mutex::new(
vm_virtio::Net::new(
None,
Some(net_cfg.ip),
Some(net_cfg.mask),
Some(net_cfg.mac),
net_cfg.iommu,
net_cfg.num_queues,
net_cfg.queue_size,
)
.map_err(DeviceManagerError::CreateVirtioNet)?,
))
};
devices.push((
Arc::clone(&virtio_net_device) as Arc<Mutex<dyn vm_virtio::VirtioDevice>>,
net_cfg.iommu,
));
migratable_devices
.push(Arc::clone(&virtio_net_device) as Arc<Mutex<dyn Migratable>>);
let virtio_net_device = if let Some(ref tap_if_name) = net_cfg.tap {
Arc::new(Mutex::new(
vm_virtio::Net::new(
Some(tap_if_name),
None,
None,
Some(net_cfg.mac),
net_cfg.iommu,
net_cfg.num_queues,
net_cfg.queue_size,
)
.map_err(DeviceManagerError::CreateVirtioNet)?,
))
} else {
Arc::new(Mutex::new(
vm_virtio::Net::new(
None,
Some(net_cfg.ip),
Some(net_cfg.mask),
Some(net_cfg.mac),
net_cfg.iommu,
net_cfg.num_queues,
net_cfg.queue_size,
)
.map_err(DeviceManagerError::CreateVirtioNet)?,
))
};
devices.push((
Arc::clone(&virtio_net_device) as Arc<Mutex<dyn vm_virtio::VirtioDevice>>,
net_cfg.iommu,
));
migratable_devices
.push(Arc::clone(&virtio_net_device) as Arc<Mutex<dyn Migratable>>);
}
}
}