diff --git a/vmm/src/config.rs b/vmm/src/config.rs index b1dd5e4c2..13530bf48 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -71,6 +71,8 @@ pub enum Error<'a> { ParseVuQueueSizeParam(std::num::ParseIntError), /// Failed parsing vhost-user-net server parameter. ParseVuNetServerParam(std::num::ParseIntError), + /// Failed parsing vhost-user-blk wce parameter. + ParseVuBlkWceParam(std::str::ParseBoolError), /// Failed parsing vsock context ID parameter. ParseVsockCidParam(std::num::ParseIntError), /// Failed parsing vsock socket path parameter. @@ -92,6 +94,7 @@ pub struct VmParams<'a> { pub console: &'a str, pub devices: Option>, pub vhost_user_net: Option>, + pub vhost_user_blk: Option>, pub vsock: Option>, } @@ -550,6 +553,61 @@ impl<'a> VsockConfig<'a> { } } +pub struct VhostUserBlkConfig<'a> { + pub wce: bool, + pub vu_cfg: VhostUserConfig<'a>, +} + +impl<'a> VhostUserBlkConfig<'a> { + pub fn parse(vhost_user_blk: &'a str) -> Result { + // Split the parameters based on the comma delimiter + let params_list: Vec<&str> = vhost_user_blk.split(',').collect(); + + let mut sock: &str = ""; + let mut num_queues_str: &str = ""; + let mut queue_size_str: &str = ""; + let mut wce_str: &str = ""; + + for param in params_list.iter() { + 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..]; + } else if param.starts_with("wce=") { + wce_str = ¶m[4..]; + } + } + + let mut num_queues: usize = 1; + let mut queue_size: u16 = 128; + let mut wce: bool = true; + + if !num_queues_str.is_empty() { + num_queues = num_queues_str + .parse() + .map_err(Error::ParseVuNumQueuesParam)?; + } + if !queue_size_str.is_empty() { + queue_size = queue_size_str + .parse() + .map_err(Error::ParseVuQueueSizeParam)?; + } + if !wce_str.is_empty() { + wce = wce_str.parse().map_err(Error::ParseVuBlkWceParam)?; + } + + let vu_cfg = VhostUserConfig { + sock, + num_queues, + queue_size, + }; + + Ok(VhostUserBlkConfig { wce, vu_cfg }) + } +} + pub struct VmConfig<'a> { pub cpus: CpusConfig, pub memory: MemoryConfig<'a>, @@ -564,6 +622,7 @@ pub struct VmConfig<'a> { pub console: ConsoleConfig<'a>, pub devices: Option>>, pub vhost_user_net: Option>>, + pub vhost_user_blk: Option>>, pub vsock: Option>>, } @@ -638,6 +697,15 @@ impl<'a> VmConfig<'a> { vsock = Some(vsock_config_list); } + let mut vhost_user_blk: Option> = None; + if let Some(vhost_user_blk_list) = &vm_params.vhost_user_blk { + let mut vhost_user_blk_config_list = Vec::new(); + for item in vhost_user_blk_list.iter() { + vhost_user_blk_config_list.push(VhostUserBlkConfig::parse(item)?); + } + vhost_user_blk = Some(vhost_user_blk_config_list); + } + Ok(VmConfig { cpus: CpusConfig::parse(vm_params.cpus)?, memory: MemoryConfig::parse(vm_params.memory)?, @@ -652,6 +720,7 @@ impl<'a> VmConfig<'a> { console, devices, vhost_user_net, + vhost_user_blk, vsock, }) } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index d2bee9fa8..d392faf8d 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -78,6 +78,9 @@ pub enum DeviceManagerError { /// Cannot create virtio-fs device CreateVirtioFs(vm_virtio::vhost_user::Error), + /// Cannot create vhost-user-blk device + CreateVhostUserBlk(vm_virtio::vhost_user::Error), + /// Cannot create virtio-pmem device CreateVirtioPmem(io::Error), @@ -515,6 +518,11 @@ impl DeviceManager { vm_info, )?); + // Add virtio-vhost-user-blk if required + devices.append(&mut DeviceManager::make_virtio_vhost_user_blk_devices( + vm_info, + )?); + // Add virtio-vsock if required devices.append(&mut DeviceManager::make_virtio_vsock_devices(vm_info)?); @@ -778,6 +786,26 @@ impl DeviceManager { Ok(devices) } + fn make_virtio_vhost_user_blk_devices( + vm_info: &VmInfo, + ) -> DeviceManagerResult>> { + let mut devices = Vec::new(); + // Add vhost-user-blk if required + if let Some(vhost_user_blk_list_cfg) = &vm_info.vm_cfg.vhost_user_blk { + for vhost_user_blk_cfg in vhost_user_blk_list_cfg.iter() { + let vhost_user_blk_device = vm_virtio::vhost_user::Blk::new( + vhost_user_blk_cfg.wce, + vhost_user_blk_cfg.vu_cfg, + ) + .map_err(DeviceManagerError::CreateVhostUserBlk)?; + + devices.push(Box::new(vhost_user_blk_device) as Box); + } + } + + Ok(devices) + } + fn make_virtio_vsock_devices( vm_info: &VmInfo, ) -> DeviceManagerResult>> {