361 lines
13 KiB
Diff
361 lines
13 KiB
Diff
|
|
From b9ec3a6f3b7e35b342a778ded719cab4602e01a7 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Ming Yang <yangming73@huawei.com>
|
||
|
|
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 <guoxinle1@huawei.com>
|
||
|
|
Signed-off-by: Ming Yang <yangming73@huawei.com>
|
||
|
|
---
|
||
|
|
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<B
|
||
|
|
.push("")
|
||
|
|
.push("bus")
|
||
|
|
.push("addr")
|
||
|
|
+ .push("multifunction")
|
||
|
|
.push("id")
|
||
|
|
.push("deflate-on-oom");
|
||
|
|
cmd_parser.parse(balloon_config)?;
|
||
|
|
@@ -84,7 +85,7 @@ mod tests {
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
- fn test_pci_block_config_cmdline_parser() {
|
||
|
|
+ fn test_pci_balloon_config_cmdline_parser() {
|
||
|
|
let mut vm_config = VmConfig::default();
|
||
|
|
let bln_cfg = "virtio-balloon-pci,deflate-on-oom=true,bus=pcie.0,addr=0x1.0x2,id=balloon0";
|
||
|
|
let bln_cfg_res = parse_balloon(&mut vm_config, bln_cfg);
|
||
|
|
@@ -98,6 +99,10 @@ mod tests {
|
||
|
|
let pci = pci_bdf.unwrap();
|
||
|
|
assert_eq!(pci.bus, "pcie.0".to_string());
|
||
|
|
assert_eq!(pci.addr, (1, 2));
|
||
|
|
+
|
||
|
|
+ let mut vm_config = VmConfig::default();
|
||
|
|
+ let bln_cfg = "virtio-balloon-pci,deflate-on-oom=true,bus=pcie.0,addr=0x1.0x2,id=balloon0,multifunction=on";
|
||
|
|
+ assert!(parse_balloon(&mut vm_config, bln_cfg).is_ok());
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
diff --git a/machine_manager/src/config/chardev.rs b/machine_manager/src/config/chardev.rs
|
||
|
|
index e5b3ff1..c1f37b5 100644
|
||
|
|
--- a/machine_manager/src/config/chardev.rs
|
||
|
|
+++ b/machine_manager/src/config/chardev.rs
|
||
|
|
@@ -16,7 +16,7 @@ use super::{
|
||
|
|
errors::{ErrorKind, Result, ResultExt},
|
||
|
|
get_pci_bdf, pci_args_check, PciBdf,
|
||
|
|
};
|
||
|
|
-use crate::config::{CmdParser, ConfigCheck, VmConfig};
|
||
|
|
+use crate::config::{CmdParser, ConfigCheck, ExBool, VmConfig};
|
||
|
|
|
||
|
|
const MAX_STRING_LENGTH: usize = 255;
|
||
|
|
const MAX_PATH_LENGTH: usize = 4096;
|
||
|
|
@@ -275,6 +275,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result<VsockConfig> {
|
||
|
|
.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<VsockConfig> {
|
||
|
|
} else {
|
||
|
|
return Err(ErrorKind::FieldIsMissing("guest-cid", "vsock").into());
|
||
|
|
};
|
||
|
|
- let device_type = cmd_parser.get_value::<String>("")?;
|
||
|
|
- // 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::<String>("bus")?.is_some() {
|
||
|
|
- bail!("virtio mmio device does not support bus property");
|
||
|
|
- }
|
||
|
|
- if cmd_parser.get_value::<String>("addr")?.is_some() {
|
||
|
|
- bail!("virtio mmio device does not support addr property");
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
+
|
||
|
|
let vhost_fd = cmd_parser.get_value::<i32>("vhostfd")?;
|
||
|
|
let vsock = VsockConfig {
|
||
|
|
id,
|
||
|
|
@@ -315,6 +305,7 @@ pub fn parse_vsock(vsock_config: &str) -> Result<VsockConfig> {
|
||
|
|
pub struct VirtioSerialInfo {
|
||
|
|
pub id: String,
|
||
|
|
pub pci_bdf: Option<PciBdf>,
|
||
|
|
+ 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::<ExBool>("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<BlkDevC
|
||
|
|
.push("id")
|
||
|
|
.push("bus")
|
||
|
|
.push("addr")
|
||
|
|
+ .push("multifunction")
|
||
|
|
.push("drive")
|
||
|
|
.push("bootindex")
|
||
|
|
.push("serial")
|
||
|
|
@@ -412,6 +413,14 @@ mod tests {
|
||
|
|
// drive "rootfs" has been removed.
|
||
|
|
let blk_cfg_res = parse_blk(&mut vm_config, blk_cfg);
|
||
|
|
assert!(blk_cfg_res.is_err());
|
||
|
|
+
|
||
|
|
+ let mut vm_config = VmConfig::default();
|
||
|
|
+ assert!(vm_config
|
||
|
|
+ .add_drive("id=rootfs,file=/path/to/rootfs,serial=111111,readonly=off,direct=on")
|
||
|
|
+ .is_ok());
|
||
|
|
+ let blk_cfg =
|
||
|
|
+ "virtio-blk-pci,id=blk1,bus=pcie.0,addr=0x1.0x2,drive=rootfs,multifunction=on";
|
||
|
|
+ assert!(parse_blk(&mut vm_config, blk_cfg).is_ok());
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
diff --git a/machine_manager/src/config/network.rs b/machine_manager/src/config/network.rs
|
||
|
|
index 71e6b3f..b0ad545 100644
|
||
|
|
--- a/machine_manager/src/config/network.rs
|
||
|
|
+++ b/machine_manager/src/config/network.rs
|
||
|
|
@@ -159,6 +159,7 @@ pub fn parse_net(vm_config: &mut VmConfig, net_config: &str) -> Result<NetworkIn
|
||
|
|
.push("netdev")
|
||
|
|
.push("bus")
|
||
|
|
.push("addr")
|
||
|
|
+ .push("multifunction")
|
||
|
|
.push("mac")
|
||
|
|
.push("iothread");
|
||
|
|
|
||
|
|
@@ -344,5 +345,13 @@ mod tests {
|
||
|
|
|
||
|
|
let net_cfg_res = parse_net(&mut vm_config, net_cfg);
|
||
|
|
assert!(net_cfg_res.is_err());
|
||
|
|
+
|
||
|
|
+ let mut vm_config = VmConfig::default();
|
||
|
|
+ assert!(vm_config
|
||
|
|
+ .add_netdev("tap,id=eth1,ifname=tap1,vhost=on,vhostfd=4")
|
||
|
|
+ .is_ok());
|
||
|
|
+ let net_cfg =
|
||
|
|
+ "virtio-net-pci,id=net1,netdev=eth1,bus=pcie.0,addr=0x1.0x2,mac=12:34:56:78:9A:BC,multifunction=on";
|
||
|
|
+ assert!(parse_net(&mut vm_config, net_cfg).is_ok());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
diff --git a/machine_manager/src/config/pci.rs b/machine_manager/src/config/pci.rs
|
||
|
|
index 13bca99..a3a6c9d 100644
|
||
|
|
--- a/machine_manager/src/config/pci.rs
|
||
|
|
+++ b/machine_manager/src/config/pci.rs
|
||
|
|
@@ -12,6 +12,7 @@
|
||
|
|
|
||
|
|
use super::errors::{ErrorKind, Result, ResultExt};
|
||
|
|
use super::{CmdParser, ConfigCheck, MAX_STRING_LENGTH};
|
||
|
|
+use crate::config::ExBool;
|
||
|
|
|
||
|
|
/// Basic information of pci devices such as bus number,
|
||
|
|
/// slot number and function number.
|
||
|
|
@@ -43,6 +44,7 @@ impl Default for PciBdf {
|
||
|
|
pub struct RootPortConfig {
|
||
|
|
pub port: u8,
|
||
|
|
pub id: String,
|
||
|
|
+ pub multifunction: bool,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl ConfigCheck for RootPortConfig {
|
||
|
|
@@ -64,6 +66,7 @@ impl Default for RootPortConfig {
|
||
|
|
RootPortConfig {
|
||
|
|
port: 0,
|
||
|
|
id: "".to_string(),
|
||
|
|
+ multifunction: false,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -112,6 +115,21 @@ pub fn get_pci_bdf(pci_cfg: &str) -> Result<PciBdf> {
|
||
|
|
Ok(pci_bdf)
|
||
|
|
}
|
||
|
|
|
||
|
|
+pub fn get_multi_function(pci_cfg: &str) -> Result<bool> {
|
||
|
|
+ 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::<ExBool>("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<RootPortConfig> {
|
||
|
|
let mut cmd_parser = CmdParser::new("pcie-root-port");
|
||
|
|
cmd_parser
|
||
|
|
@@ -138,6 +156,12 @@ pub fn parse_root_port(rootport_cfg: &str) -> Result<RootPortConfig> {
|
||
|
|
} else {
|
||
|
|
return Err(ErrorKind::FieldIsMissing("id", "rootport").into());
|
||
|
|
}
|
||
|
|
+ root_port.multifunction =
|
||
|
|
+ if let Some(multi_func) = cmd_parser.get_value::<ExBool>("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::<String>("addr")?.is_some() {
|
||
|
|
bail!("virtio mmio device does not support addr arguments");
|
||
|
|
}
|
||
|
|
+ if cmd_parser.get_value::<ExBool>("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<RngCo
|
||
|
|
.push("id")
|
||
|
|
.push("bus")
|
||
|
|
.push("addr")
|
||
|
|
+ .push("multifunction")
|
||
|
|
.push("max-bytes")
|
||
|
|
.push("period")
|
||
|
|
.push("rng");
|
||
|
|
@@ -234,5 +235,12 @@ mod tests {
|
||
|
|
let rng_cfg = "virtio-rng-device,rng=objrng0,bus=pcie.0,addr=0x1.0x3";
|
||
|
|
let rng_config = parse_rng_dev(&mut vm_config, rng_cfg);
|
||
|
|
assert!(rng_config.is_err());
|
||
|
|
+
|
||
|
|
+ let mut vm_config = VmConfig::default();
|
||
|
|
+ assert!(vm_config
|
||
|
|
+ .add_object("rng-random,id=objrng0,filename=/path/to/random_file")
|
||
|
|
+ .is_ok());
|
||
|
|
+ let rng_cfg = "virtio-rng-pci,rng=objrng0,bus=pcie.0,addr=0x1.0x3,multifunction=on";
|
||
|
|
+ assert!(parse_rng_dev(&mut vm_config, rng_cfg).is_ok());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
diff --git a/machine_manager/src/config/vfio.rs b/machine_manager/src/config/vfio.rs
|
||
|
|
index 2a941c5..5f7d450 100644
|
||
|
|
--- a/machine_manager/src/config/vfio.rs
|
||
|
|
+++ b/machine_manager/src/config/vfio.rs
|
||
|
|
@@ -52,7 +52,8 @@ pub fn parse_vfio(_vm_config: &VmConfig, vfio_config: &str) -> Result<VfioConfig
|
||
|
|
.push("host")
|
||
|
|
.push("id")
|
||
|
|
.push("bus")
|
||
|
|
- .push("addr");
|
||
|
|
+ .push("addr")
|
||
|
|
+ .push("multifunction");
|
||
|
|
cmd_parser.parse(vfio_config)?;
|
||
|
|
|
||
|
|
let mut vfio: VfioConfig = VfioConfig::default();
|
||
|
|
@@ -127,5 +128,10 @@ mod tests {
|
||
|
|
let pci = pci_bdf.unwrap();
|
||
|
|
assert_eq!(pci.bus, "pcie.0".to_string());
|
||
|
|
assert_eq!(pci.addr, (1, 2));
|
||
|
|
+
|
||
|
|
+ let mut vm_config = VmConfig::default();
|
||
|
|
+ let vfio_cfg1 =
|
||
|
|
+ "vfio-pci,host=0000:1a:00.3,id=net,bus=pcie.0,addr=0x1.0x2,multifunction=on";
|
||
|
|
+ assert!(parse_vfio(&mut vm_config, vfio_cfg1).is_ok());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
--
|
||
|
|
2.25.1
|
||
|
|
|