mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-05 21:15:45 +00:00
vmm: Add vhost-user-net support
Update vm configuration and device initial process to add vhost-user-net support. Signed-off-by: Cathy Zhang <cathy.zhang@intel.com>
This commit is contained in:
parent
633f51af9c
commit
584a2cccee
@ -3,6 +3,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
|
extern crate vm_virtio;
|
||||||
|
|
||||||
use linux_loader::cmdline::Cmdline;
|
use linux_loader::cmdline::Cmdline;
|
||||||
use net_util::MacAddr;
|
use net_util::MacAddr;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
@ -11,6 +13,7 @@ use std::net::Ipv4Addr;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::result;
|
use std::result;
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
|
use vm_virtio::vhost_user::VhostUserConfig;
|
||||||
|
|
||||||
pub const DEFAULT_VCPUS: &str = "1";
|
pub const DEFAULT_VCPUS: &str = "1";
|
||||||
pub const DEFAULT_MEMORY: &str = "size=512M";
|
pub const DEFAULT_MEMORY: &str = "size=512M";
|
||||||
@ -58,6 +61,16 @@ pub enum Error<'a> {
|
|||||||
ParseConsoleParam,
|
ParseConsoleParam,
|
||||||
/// Both console and serial are tty.
|
/// Both console and serial are tty.
|
||||||
ParseTTYParam,
|
ParseTTYParam,
|
||||||
|
/// Failed parsing vhost-user-net mac parameter.
|
||||||
|
ParseVuNetMacParam(&'a str),
|
||||||
|
/// Failed parsing vhost-user-net sock parameter.
|
||||||
|
ParseVuNetSockParam,
|
||||||
|
/// Failed parsing vhost-user-net queue number parameter.
|
||||||
|
ParseVuNetNumQueuesParam(std::num::ParseIntError),
|
||||||
|
/// Failed parsing vhost-user-net queue size parameter.
|
||||||
|
ParseVuNetQueueSizeParam(std::num::ParseIntError),
|
||||||
|
/// Failed parsing vhost-user-net server parameter.
|
||||||
|
ParseVuNetServerParam(std::num::ParseIntError),
|
||||||
}
|
}
|
||||||
pub type Result<'a, T> = result::Result<T, Error<'a>>;
|
pub type Result<'a, T> = result::Result<T, Error<'a>>;
|
||||||
|
|
||||||
@ -74,6 +87,7 @@ pub struct VmParams<'a> {
|
|||||||
pub serial: &'a str,
|
pub serial: &'a str,
|
||||||
pub console: &'a str,
|
pub console: &'a str,
|
||||||
pub devices: Option<Vec<&'a str>>,
|
pub devices: Option<Vec<&'a str>>,
|
||||||
|
pub vhost_user_net: Option<Vec<&'a str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_size(size: &str) -> Result<u64> {
|
fn parse_size(size: &str) -> Result<u64> {
|
||||||
@ -441,6 +455,64 @@ impl<'a> DeviceConfig<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct VhostUserNetConfig<'a> {
|
||||||
|
pub mac: MacAddr,
|
||||||
|
pub vu_cfg: VhostUserConfig<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> VhostUserNetConfig<'a> {
|
||||||
|
pub fn parse(vhost_user_net: &'a str) -> Result<Self> {
|
||||||
|
// Split the parameters based on the comma delimiter
|
||||||
|
let params_list: Vec<&str> = vhost_user_net.split(',').collect();
|
||||||
|
|
||||||
|
let mut mac_str: &str = "";
|
||||||
|
let mut sock: &str = "";
|
||||||
|
let mut num_queues_str: &str = "";
|
||||||
|
let mut queue_size_str: &str = "";
|
||||||
|
|
||||||
|
for param in params_list.iter() {
|
||||||
|
if param.starts_with("mac=") {
|
||||||
|
mac_str = ¶m[4..];
|
||||||
|
} else if param.starts_with("sock=") {
|
||||||
|
sock = ¶m[5..];
|
||||||
|
} else if param.starts_with("num_queues=") {
|
||||||
|
num_queues_str = ¶m[11..];
|
||||||
|
} else if param.starts_with("queue_size=") {
|
||||||
|
queue_size_str = ¶m[11..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mac: MacAddr = MacAddr::local_random();
|
||||||
|
let mut num_queues: usize = 2;
|
||||||
|
let mut queue_size: u16 = 256;
|
||||||
|
|
||||||
|
if !mac_str.is_empty() {
|
||||||
|
mac = MacAddr::parse_str(mac_str).map_err(Error::ParseVuNetMacParam)?;
|
||||||
|
}
|
||||||
|
if sock.is_empty() {
|
||||||
|
return Err(Error::ParseVuNetSockParam);
|
||||||
|
}
|
||||||
|
if !num_queues_str.is_empty() {
|
||||||
|
num_queues = num_queues_str
|
||||||
|
.parse()
|
||||||
|
.map_err(Error::ParseVuNetNumQueuesParam)?;
|
||||||
|
}
|
||||||
|
if !queue_size_str.is_empty() {
|
||||||
|
queue_size = queue_size_str
|
||||||
|
.parse()
|
||||||
|
.map_err(Error::ParseVuNetQueueSizeParam)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let vu_cfg = VhostUserConfig {
|
||||||
|
sock,
|
||||||
|
num_queues,
|
||||||
|
queue_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(VhostUserNetConfig { mac, vu_cfg })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct VmConfig<'a> {
|
pub struct VmConfig<'a> {
|
||||||
pub cpus: CpusConfig,
|
pub cpus: CpusConfig,
|
||||||
pub memory: MemoryConfig<'a>,
|
pub memory: MemoryConfig<'a>,
|
||||||
@ -454,6 +526,7 @@ pub struct VmConfig<'a> {
|
|||||||
pub serial: ConsoleConfig<'a>,
|
pub serial: ConsoleConfig<'a>,
|
||||||
pub console: ConsoleConfig<'a>,
|
pub console: ConsoleConfig<'a>,
|
||||||
pub devices: Option<Vec<DeviceConfig<'a>>>,
|
pub devices: Option<Vec<DeviceConfig<'a>>>,
|
||||||
|
pub vhost_user_net: Option<Vec<VhostUserNetConfig<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VmConfig<'a> {
|
impl<'a> VmConfig<'a> {
|
||||||
@ -509,6 +582,15 @@ impl<'a> VmConfig<'a> {
|
|||||||
devices = Some(device_config_list);
|
devices = Some(device_config_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut vhost_user_net: Option<Vec<VhostUserNetConfig>> = None;
|
||||||
|
if let Some(vhost_user_net_list) = &vm_params.vhost_user_net {
|
||||||
|
let mut vhost_user_net_config_list = Vec::new();
|
||||||
|
for item in vhost_user_net_list.iter() {
|
||||||
|
vhost_user_net_config_list.push(VhostUserNetConfig::parse(item)?);
|
||||||
|
}
|
||||||
|
vhost_user_net = Some(vhost_user_net_config_list);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(VmConfig {
|
Ok(VmConfig {
|
||||||
cpus: CpusConfig::parse(vm_params.cpus)?,
|
cpus: CpusConfig::parse(vm_params.cpus)?,
|
||||||
memory: MemoryConfig::parse(vm_params.memory)?,
|
memory: MemoryConfig::parse(vm_params.memory)?,
|
||||||
@ -522,6 +604,7 @@ impl<'a> VmConfig<'a> {
|
|||||||
serial,
|
serial,
|
||||||
console,
|
console,
|
||||||
devices,
|
devices,
|
||||||
|
vhost_user_net,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,6 +234,9 @@ pub enum DeviceManagerError {
|
|||||||
/// Cannot open disk path
|
/// Cannot open disk path
|
||||||
Disk(io::Error),
|
Disk(io::Error),
|
||||||
|
|
||||||
|
/// Cannot create vhost-user-net device
|
||||||
|
CreateVhostUserNet(vm_virtio::vhost_user::Error),
|
||||||
|
|
||||||
/// Cannot create virtio-blk device
|
/// Cannot create virtio-blk device
|
||||||
CreateVirtioBlock(io::Error),
|
CreateVirtioBlock(io::Error),
|
||||||
|
|
||||||
@ -773,6 +776,15 @@ impl DeviceManager {
|
|||||||
&mut mem_slots,
|
&mut mem_slots,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Add virtio-vhost-user-net if required
|
||||||
|
DeviceManager::add_virtio_vhost_user_net_devices(
|
||||||
|
vm_info,
|
||||||
|
allocator,
|
||||||
|
pci,
|
||||||
|
buses,
|
||||||
|
&interrupt_info,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1061,6 +1073,37 @@ impl DeviceManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_virtio_vhost_user_net_devices(
|
||||||
|
vm_info: &VmInfo,
|
||||||
|
allocator: &mut SystemAllocator,
|
||||||
|
pci: &mut PciConfigIo,
|
||||||
|
buses: &mut BusInfo,
|
||||||
|
interrupt_info: &InterruptInfo,
|
||||||
|
) -> DeviceManagerResult<()> {
|
||||||
|
// Add vhost-user-net if required
|
||||||
|
if let Some(vhost_user_net_list_cfg) = &vm_info.vm_cfg.vhost_user_net {
|
||||||
|
for vhost_user_net_cfg in vhost_user_net_list_cfg.iter() {
|
||||||
|
let vhost_user_net_device = vm_virtio::vhost_user::Net::new(
|
||||||
|
vhost_user_net_cfg.mac,
|
||||||
|
vhost_user_net_cfg.vu_cfg,
|
||||||
|
)
|
||||||
|
.map_err(DeviceManagerError::CreateVhostUserNet)?;
|
||||||
|
|
||||||
|
DeviceManager::add_virtio_pci_device(
|
||||||
|
Box::new(vhost_user_net_device),
|
||||||
|
vm_info.memory,
|
||||||
|
allocator,
|
||||||
|
vm_info.vm_fd,
|
||||||
|
pci,
|
||||||
|
buses,
|
||||||
|
&interrupt_info,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn create_kvm_device(vm: &Arc<VmFd>) -> DeviceManagerResult<DeviceFd> {
|
fn create_kvm_device(vm: &Arc<VmFd>) -> DeviceManagerResult<DeviceFd> {
|
||||||
let mut vfio_dev = kvm_bindings::kvm_create_device {
|
let mut vfio_dev = kvm_bindings::kvm_create_device {
|
||||||
type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_VFIO,
|
type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_VFIO,
|
||||||
|
Loading…
Reference in New Issue
Block a user