runtime-rs: Add network support for cloud-hypervisor

This PR adds support for adding a network device before starting the
cloud-hypervisor VM.

Support for adding and removing network devices is not really added to
the resource manager, so supporting this for cloud-hypervisor is not
scoped in this PR.

This also changes "pending_devices" for clh implementation from an
Option of vector to simply a vector. This simplifies the structure a bit
as we can simple iterate over the pending devices instead of having to
check for a "Some" value as this is not really required.

Fixes: #6333

Signed-off-by: Shuaiyi Zhang <zhang_syi@qq.com>
Signed-off-by: Archana Shinde <archana.m.shinde@intel.com>
This commit is contained in:
Archana Shinde 2023-09-15 01:33:01 -07:00
parent c2b2a00ad9
commit 9049d311df
5 changed files with 51 additions and 35 deletions

View File

@ -58,6 +58,7 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
};
let fs = n.shared_fs_devices;
let net = n.network_devices;
let cpus = CpusConfig::try_from(cfg.cpu_info).map_err(VmConfigError::CPUError)?;
@ -129,6 +130,7 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
console,
payload,
fs,
net,
pmem,
disks,
vsock: Some(vsock),

View File

@ -492,4 +492,5 @@ pub struct NamedHypervisorConfig {
pub tdx_enabled: bool,
pub shared_fs_devices: Option<Vec<FsConfig>>,
pub network_devices: Option<Vec<NetConfig>>,
}

View File

@ -44,7 +44,7 @@ pub struct CloudHypervisorInner {
pub(crate) jailer_root: String,
/// List of devices that will be added to the VM once it boots
pub(crate) pending_devices: Option<Vec<DeviceType>>,
pub(crate) pending_devices: Vec<DeviceType>,
pub(crate) _capabilities: Capabilities,
@ -81,7 +81,7 @@ impl CloudHypervisorInner {
vm_path: String::default(),
run_dir: String::default(),
netns: None,
pending_devices: None,
pending_devices: vec![],
_capabilities: capabilities,
shutdown_tx: Some(tx),
shutdown_rx: Some(rx),

View File

@ -8,12 +8,13 @@ use super::inner::CloudHypervisorInner;
use crate::device::DeviceType;
use crate::BlockConfig;
use crate::HybridVsockConfig;
use crate::NetworkConfig;
use crate::ShareFsDeviceConfig;
use crate::VmmState;
use anyhow::{anyhow, Context, Result};
use ch_config::ch_api::{cloud_hypervisor_vm_blockdev_add, cloud_hypervisor_vm_fs_add};
use ch_config::DiskConfig;
use ch_config::FsConfig;
use ch_config::{net_util::MacAddr, FsConfig, NetConfig};
use safe_path::scoped_join;
use std::convert::TryFrom;
use std::path::PathBuf;
@ -25,15 +26,7 @@ const DEFAULT_DISK_QUEUE_SIZE: u16 = 1024;
impl CloudHypervisorInner {
pub(crate) async fn add_device(&mut self, device: DeviceType) -> Result<()> {
if self.state != VmmState::VmRunning {
let mut devices: Vec<DeviceType> = if let Some(devices) = self.pending_devices.take() {
devices
} else {
vec![]
};
devices.insert(0, device);
self.pending_devices = Some(devices);
self.pending_devices.insert(0, device);
return Ok(());
}
@ -63,10 +56,8 @@ impl CloudHypervisorInner {
));
}
if let Some(mut devices) = self.pending_devices.take() {
while let Some(dev) = devices.pop() {
self.add_device(dev).await.context("add_device")?;
}
while let Some(dev) = self.pending_devices.pop() {
self.add_device(dev).await.context("add_device")?;
}
Ok(())
@ -161,32 +152,53 @@ impl CloudHypervisorInner {
Ok(())
}
pub(crate) async fn get_shared_fs_devices(&mut self) -> Result<Option<Vec<FsConfig>>> {
let pending_root_devices = self.pending_devices.take();
pub(crate) async fn get_shared_devices(
&mut self,
) -> Result<(Option<Vec<FsConfig>>, Option<Vec<NetConfig>>)> {
let mut shared_fs_devices = Vec::<FsConfig>::new();
let mut network_devices = Vec::<NetConfig>::new();
let mut root_devices = Vec::<FsConfig>::new();
while let Some(dev) = self.pending_devices.pop() {
match dev {
DeviceType::ShareFs(dev) => {
let settings = ShareFsSettings::new(dev.config, self.vm_path.clone());
if let Some(devices) = pending_root_devices {
for dev in devices {
match dev {
DeviceType::ShareFs(dev) => {
let settings = ShareFsSettings::new(dev.config, self.vm_path.clone());
let fs_cfg = FsConfig::try_from(settings)?;
let fs_cfg = FsConfig::try_from(settings)?;
root_devices.push(fs_cfg);
}
_ => continue,
};
shared_fs_devices.push(fs_cfg);
}
DeviceType::Network(net_device) => {
let net_config = NetConfig::try_from(net_device.config)?;
network_devices.push(net_config);
}
_ => continue,
}
Ok(Some(root_devices))
} else {
Ok(None)
}
Ok((Some(shared_fs_devices), Some(network_devices)))
}
}
impl TryFrom<NetworkConfig> for NetConfig {
type Error = anyhow::Error;
fn try_from(cfg: NetworkConfig) -> Result<Self, Self::Error> {
if let Some(mac) = cfg.guest_mac {
let net_config = NetConfig {
tap: Some(cfg.host_dev_name.clone()),
id: Some(cfg.virt_iface_name.clone()),
num_queues: cfg.queue_num,
queue_size: cfg.queue_size as u16,
mac: MacAddr { bytes: mac.0 },
..Default::default()
};
return Ok(net_config);
}
Err(anyhow!("Missing mac address for network device"))
}
}
#[derive(Debug)]
pub struct ShareFsSettings {
cfg: ShareFsDeviceConfig,

View File

@ -107,7 +107,7 @@ impl CloudHypervisorInner {
}
async fn boot_vm(&mut self) -> Result<()> {
let shared_fs_devices = self.get_shared_fs_devices().await?;
let (shared_fs_devices, network_devices) = self.get_shared_devices().await?;
let socket = self
.api_socket
@ -147,6 +147,7 @@ impl CloudHypervisorInner {
cfg: hypervisor_config.clone(),
tdx_enabled,
shared_fs_devices,
network_devices,
};
let cfg = VmConfig::try_from(named_cfg)?;