From b9ec3a6f3b7e35b342a778ded719cab4602e01a7 Mon Sep 17 00:00:00 2001 From: Ming Yang Date: Sat, 28 Aug 2021 10:25:21 +0800 Subject: [PATCH 08/10] machine_manager: add multifunction for devices. 1. Add arugument: "multifunction" for devices Signed-off-by: Xinle.Guo Signed-off-by: Ming Yang --- machine_manager/src/config/balloon.rs | 7 +++- machine_manager/src/config/chardev.rs | 43 +++++++++++++++-------- machine_manager/src/config/drive.rs | 9 +++++ machine_manager/src/config/network.rs | 9 +++++ machine_manager/src/config/pci.rs | 49 +++++++++++++++++++++++++++ machine_manager/src/config/rng.rs | 8 +++++ machine_manager/src/config/vfio.rs | 8 ++++- 7 files changed, 116 insertions(+), 17 deletions(-) diff --git a/machine_manager/src/config/balloon.rs b/machine_manager/src/config/balloon.rs index 77dc1b5..ec19445 100644 --- a/machine_manager/src/config/balloon.rs +++ b/machine_manager/src/config/balloon.rs @@ -47,6 +47,7 @@ pub fn parse_balloon(vm_config: &mut VmConfig, balloon_config: &str) -> Result Result { .push("id") .push("bus") .push("addr") + .push("multifunction") .push("guest-cid") .push("vhostfd"); cmd_parser.parse(vsock_config)?; @@ -290,18 +291,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result { } else { return Err(ErrorKind::FieldIsMissing("guest-cid", "vsock").into()); }; - let device_type = cmd_parser.get_value::("")?; - // Safe, because "parse_vsock" function only be called when certain - // devices type are added. - let dev_type = device_type.unwrap(); - if dev_type == *"vhost-vsock-device" { - if cmd_parser.get_value::("bus")?.is_some() { - bail!("virtio mmio device does not support bus property"); - } - if cmd_parser.get_value::("addr")?.is_some() { - bail!("virtio mmio device does not support addr property"); - } - } + let vhost_fd = cmd_parser.get_value::("vhostfd")?; let vsock = VsockConfig { id, @@ -315,6 +305,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result { pub struct VirtioSerialInfo { pub id: String, pub pci_bdf: Option, + pub multifunction: bool, } impl ConfigCheck for VirtioSerialInfo { @@ -333,7 +324,12 @@ impl ConfigCheck for VirtioSerialInfo { pub fn parse_virtio_serial(vm_config: &mut VmConfig, serial_config: &str) -> Result<()> { let mut cmd_parser = CmdParser::new("virtio-serial"); - cmd_parser.push("").push("id").push("bus").push("addr"); + cmd_parser + .push("") + .push("id") + .push("bus") + .push("addr") + .push("multifunction"); cmd_parser.parse(serial_config)?; pci_args_check(&cmd_parser)?; @@ -343,14 +339,24 @@ pub fn parse_virtio_serial(vm_config: &mut VmConfig, serial_config: &str) -> Res } else { "".to_string() }; + let multifunction = if let Some(switch) = cmd_parser.get_value::("multifunction")? { + switch.into() + } else { + false + }; let virtio_serial = if serial_config.contains("-pci") { let pci_bdf = get_pci_bdf(serial_config)?; VirtioSerialInfo { id, pci_bdf: Some(pci_bdf), + multifunction, } } else { - VirtioSerialInfo { id, pci_bdf: None } + VirtioSerialInfo { + id, + pci_bdf: None, + multifunction, + } }; virtio_serial.check()?; vm_config.virtio_serial = Some(virtio_serial); @@ -434,6 +440,13 @@ mod tests { console_cfg.chardev.backend, ChardevType::Socket("/path/to/socket".to_string()) ); + + let mut vm_config = VmConfig::default(); + assert!(parse_virtio_serial( + &mut vm_config, + "virtio-serial-pci,bus=pcie.0,addr=0x1.0x2,multifunction=on" + ) + .is_ok()); } #[test] diff --git a/machine_manager/src/config/drive.rs b/machine_manager/src/config/drive.rs index 3aaef75..16831df 100644 --- a/machine_manager/src/config/drive.rs +++ b/machine_manager/src/config/drive.rs @@ -164,6 +164,7 @@ pub fn parse_blk(vm_config: &mut VmConfig, drive_config: &str) -> Result Result Result { Ok(pci_bdf) } +pub fn get_multi_function(pci_cfg: &str) -> Result { + let mut cmd_parser = CmdParser::new("multifunction"); + cmd_parser.push("").push("multifunction"); + cmd_parser.get_parameters(pci_cfg)?; + + if let Some(multi_func) = cmd_parser + .get_value::("multifunction") + .chain_err(|| "Failed to get multifunction parameter, please set on or off (default).")? + { + return Ok(multi_func.inner); + } + + Ok(false) +} + pub fn parse_root_port(rootport_cfg: &str) -> Result { let mut cmd_parser = CmdParser::new("pcie-root-port"); cmd_parser @@ -138,6 +156,12 @@ pub fn parse_root_port(rootport_cfg: &str) -> Result { } else { return Err(ErrorKind::FieldIsMissing("id", "rootport").into()); } + root_port.multifunction = + if let Some(multi_func) = cmd_parser.get_value::("multifunction")? { + multi_func.into() + } else { + false + }; root_port.check()?; Ok(root_port) @@ -155,6 +179,9 @@ pub fn pci_args_check(cmd_parser: &CmdParser) -> Result<()> { if cmd_parser.get_value::("addr")?.is_some() { bail!("virtio mmio device does not support addr arguments"); } + if cmd_parser.get_value::("multifunction")?.is_some() { + bail!("virtio mmio device does not support multifunction arguments"); + } } Ok(()) } @@ -193,4 +220,26 @@ mod tests { let pci_bdf = get_pci_bdf("virtio-balloon-device,addr=0x1.0x2"); assert!(pci_bdf.is_err()); } + + #[test] + fn test_get_multi_function() { + assert_eq!( + get_multi_function("virtio-balloon-device,bus=pcie.0,addr=0x1.0x2").unwrap(), + false + ); + assert_eq!( + get_multi_function("virtio-balloon-device,bus=pcie.0,addr=0x1.0x2,multifunction=on") + .unwrap(), + true + ); + assert_eq!( + get_multi_function("virtio-balloon-device,bus=pcie.0,addr=0x1.0x2,multifunction=off") + .unwrap(), + false + ); + assert!(get_multi_function( + "virtio-balloon-device,bus=pcie.0,addr=0x1.0x2,multifunction=close" + ) + .is_err()); + } } diff --git a/machine_manager/src/config/rng.rs b/machine_manager/src/config/rng.rs index 295c6f2..139d15e 100644 --- a/machine_manager/src/config/rng.rs +++ b/machine_manager/src/config/rng.rs @@ -72,6 +72,7 @@ pub fn parse_rng_dev(vm_config: &mut VmConfig, rng_config: &str) -> Result Result