mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
main, vmm: Add new --numa parameter
Through this new parameter, we give users the opportunity to specify a set of CPUs attached to a NUMA node that has been previously created from the --memory-zone parameter. This parameter will be extended in the future to describe the distance between multiple nodes. For instance, if a user wants to attach CPUs 0, 1, 2 and 6 to a NUMA node, here are two different ways of doing so: Either ./cloud-hypervisor ... --numa id=0,cpus=0-2:6 Or ./cloud-hypervisor ... --numa id=0,cpus=0:1:2:6 Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
36171caba9
commit
42f963d6f2
@ -170,3 +170,47 @@ impl FromStr for ByteSized {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct IntegerList(pub Vec<u64>);
|
||||||
|
|
||||||
|
pub enum IntegerListParseError {
|
||||||
|
InvalidValue(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for IntegerList {
|
||||||
|
type Err = IntegerListParseError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
let mut integer_list = Vec::new();
|
||||||
|
let ranges_list: Vec<&str> = s.trim().split(':').collect();
|
||||||
|
|
||||||
|
for range in ranges_list.iter() {
|
||||||
|
let items: Vec<&str> = range.split('-').collect();
|
||||||
|
|
||||||
|
if items.len() > 2 {
|
||||||
|
return Err(IntegerListParseError::InvalidValue(range.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_range = items[0]
|
||||||
|
.parse::<u64>()
|
||||||
|
.map_err(|_| IntegerListParseError::InvalidValue(items[0].to_owned()))?;
|
||||||
|
|
||||||
|
integer_list.push(start_range);
|
||||||
|
|
||||||
|
if items.len() == 2 {
|
||||||
|
let end_range = items[1]
|
||||||
|
.parse::<u64>()
|
||||||
|
.map_err(|_| IntegerListParseError::InvalidValue(items[1].to_owned()))?;
|
||||||
|
if start_range >= end_range {
|
||||||
|
return Err(IntegerListParseError::InvalidValue(range.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in start_range..end_range {
|
||||||
|
integer_list.push(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(IntegerList(integer_list))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -221,6 +221,14 @@ fn create_app<'a, 'b>(
|
|||||||
.number_of_values(1)
|
.number_of_values(1)
|
||||||
.group("vm-config"),
|
.group("vm-config"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("numa")
|
||||||
|
.long("numa")
|
||||||
|
.help(config::NumaConfig::SYNTAX)
|
||||||
|
.takes_value(true)
|
||||||
|
.min_values(1)
|
||||||
|
.group("vm-config"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("v")
|
Arg::with_name("v")
|
||||||
.short("v")
|
.short("v")
|
||||||
@ -566,6 +574,7 @@ mod unit_tests {
|
|||||||
iommu: false,
|
iommu: false,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
sgx_epc: None,
|
sgx_epc: None,
|
||||||
|
numa: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
aver_eq!(tb, expected_vm_config, result_vm_config);
|
aver_eq!(tb, expected_vm_config, result_vm_config);
|
||||||
|
@ -413,6 +413,10 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/SgxEpcConfig'
|
$ref: '#/components/schemas/SgxEpcConfig'
|
||||||
|
numa:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/NumaConfig'
|
||||||
iommu:
|
iommu:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
@ -717,6 +721,20 @@ components:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
|
NumaConfig:
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: uint32
|
||||||
|
cpus:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
format: uint8
|
||||||
|
|
||||||
VmResize:
|
VmResize:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use net_util::MacAddr;
|
use net_util::MacAddr;
|
||||||
use option_parser::{ByteSized, OptionParser, OptionParserError, Toggle};
|
use option_parser::{ByteSized, IntegerList, OptionParser, OptionParserError, Toggle};
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
@ -69,6 +69,8 @@ pub enum Error {
|
|||||||
/// Failed to parse SGX EPC parameters
|
/// Failed to parse SGX EPC parameters
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
ParseSgxEpc(OptionParserError),
|
ParseSgxEpc(OptionParserError),
|
||||||
|
/// Failed to parse NUMA parameters
|
||||||
|
ParseNuma(OptionParserError),
|
||||||
/// Failed to validate configuration
|
/// Failed to validate configuration
|
||||||
Validation(ValidationError),
|
Validation(ValidationError),
|
||||||
}
|
}
|
||||||
@ -156,6 +158,7 @@ impl fmt::Display for Error {
|
|||||||
ParseRestore(o) => write!(f, "Error parsing --restore: {}", o),
|
ParseRestore(o) => write!(f, "Error parsing --restore: {}", o),
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
ParseSgxEpc(o) => write!(f, "Error parsing --sgx-epc: {}", o),
|
ParseSgxEpc(o) => write!(f, "Error parsing --sgx-epc: {}", o),
|
||||||
|
ParseNuma(o) => write!(f, "Error parsing --numa: {}", o),
|
||||||
ParseRestoreSourceUrlMissing => {
|
ParseRestoreSourceUrlMissing => {
|
||||||
write!(f, "Error parsing --restore: source_url missing")
|
write!(f, "Error parsing --restore: source_url missing")
|
||||||
}
|
}
|
||||||
@ -184,6 +187,7 @@ pub struct VmParams<'a> {
|
|||||||
pub vsock: Option<&'a str>,
|
pub vsock: Option<&'a str>,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub sgx_epc: Option<Vec<&'a str>>,
|
pub sgx_epc: Option<Vec<&'a str>>,
|
||||||
|
pub numa: Option<Vec<&'a str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VmParams<'a> {
|
impl<'a> VmParams<'a> {
|
||||||
@ -208,6 +212,7 @@ impl<'a> VmParams<'a> {
|
|||||||
let vsock: Option<&str> = args.value_of("vsock");
|
let vsock: Option<&str> = args.value_of("vsock");
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
let sgx_epc: Option<Vec<&str>> = args.values_of("sgx-epc").map(|x| x.collect());
|
let sgx_epc: Option<Vec<&str>> = args.values_of("sgx-epc").map(|x| x.collect());
|
||||||
|
let numa: Option<Vec<&str>> = args.values_of("numa").map(|x| x.collect());
|
||||||
|
|
||||||
VmParams {
|
VmParams {
|
||||||
cpus,
|
cpus,
|
||||||
@ -227,6 +232,7 @@ impl<'a> VmParams<'a> {
|
|||||||
vsock,
|
vsock,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
sgx_epc,
|
sgx_epc,
|
||||||
|
numa,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1204,6 +1210,35 @@ impl SgxEpcConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
|
||||||
|
pub struct NumaConfig {
|
||||||
|
#[serde(default)]
|
||||||
|
pub id: u32,
|
||||||
|
#[serde(default)]
|
||||||
|
pub cpus: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NumaConfig {
|
||||||
|
pub const SYNTAX: &'static str = "Settings related to a given NUMA node \
|
||||||
|
\"id=<node_id>,cpus=<cpus_id>\"";
|
||||||
|
pub fn parse(numa: &str) -> Result<Self> {
|
||||||
|
let mut parser = OptionParser::new();
|
||||||
|
parser.add("id").add("cpus");
|
||||||
|
parser.parse(numa).map_err(Error::ParseNuma)?;
|
||||||
|
|
||||||
|
let id = parser
|
||||||
|
.convert::<u32>("id")
|
||||||
|
.map_err(Error::ParseNuma)?
|
||||||
|
.unwrap_or(0);
|
||||||
|
let cpus = parser
|
||||||
|
.convert::<IntegerList>("cpus")
|
||||||
|
.map_err(Error::ParseNuma)?
|
||||||
|
.map(|v| v.0.iter().map(|e| *e as u8).collect());
|
||||||
|
|
||||||
|
Ok(NumaConfig { id, cpus })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
|
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
|
||||||
pub struct RestoreConfig {
|
pub struct RestoreConfig {
|
||||||
pub source_url: PathBuf,
|
pub source_url: PathBuf,
|
||||||
@ -1265,6 +1300,7 @@ pub struct VmConfig {
|
|||||||
pub iommu: bool,
|
pub iommu: bool,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub sgx_epc: Option<Vec<SgxEpcConfig>>,
|
pub sgx_epc: Option<Vec<SgxEpcConfig>>,
|
||||||
|
pub numa: Option<Vec<NumaConfig>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VmConfig {
|
impl VmConfig {
|
||||||
@ -1438,6 +1474,16 @@ impl VmConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut numa: Option<Vec<NumaConfig>> = None;
|
||||||
|
if let Some(numa_list) = &vm_params.numa {
|
||||||
|
let mut numa_config_list = Vec::new();
|
||||||
|
for item in numa_list.iter() {
|
||||||
|
let numa_config = NumaConfig::parse(item)?;
|
||||||
|
numa_config_list.push(numa_config);
|
||||||
|
}
|
||||||
|
numa = Some(numa_config_list);
|
||||||
|
}
|
||||||
|
|
||||||
let mut kernel: Option<KernelConfig> = None;
|
let mut kernel: Option<KernelConfig> = None;
|
||||||
if let Some(k) = vm_params.kernel {
|
if let Some(k) = vm_params.kernel {
|
||||||
kernel = Some(KernelConfig {
|
kernel = Some(KernelConfig {
|
||||||
@ -1470,6 +1516,7 @@ impl VmConfig {
|
|||||||
iommu,
|
iommu,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
sgx_epc,
|
sgx_epc,
|
||||||
|
numa,
|
||||||
};
|
};
|
||||||
config.validate().map_err(Error::Validation)?;
|
config.validate().map_err(Error::Validation)?;
|
||||||
Ok(config)
|
Ok(config)
|
||||||
@ -2038,6 +2085,7 @@ mod tests {
|
|||||||
iommu: false,
|
iommu: false,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
sgx_epc: None,
|
sgx_epc: None,
|
||||||
|
numa: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(valid_config.validate().is_ok());
|
assert!(valid_config.validate().is_ok());
|
||||||
|
Loading…
Reference in New Issue
Block a user