vmm: Extend --numa parameter with NUMA node distances

By introducing 'distances' option, we let the user describe a list of
destination NUMA nodes with their associated distances compared to the
current node (defined through 'id').

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-08-31 14:20:20 +02:00
parent d6fc18da9e
commit a5a29134ca
3 changed files with 82 additions and 4 deletions

View File

@ -214,3 +214,37 @@ impl FromStr for IntegerList {
Ok(IntegerList(integer_list)) Ok(IntegerList(integer_list))
} }
} }
pub struct TupleTwoIntegers(pub Vec<(u64, u64)>);
pub enum TupleTwoIntegersParseError {
InvalidValue(String),
}
impl FromStr for TupleTwoIntegers {
type Err = TupleTwoIntegersParseError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut list = Vec::new();
let tuples_list: Vec<&str> = s.trim().split(':').collect();
for tuple in tuples_list.iter() {
let items: Vec<&str> = tuple.split('@').collect();
if items.len() != 2 {
return Err(TupleTwoIntegersParseError::InvalidValue(tuple.to_string()));
}
let item1 = items[0]
.parse::<u64>()
.map_err(|_| TupleTwoIntegersParseError::InvalidValue(items[0].to_owned()))?;
let item2 = items[1]
.parse::<u64>()
.map_err(|_| TupleTwoIntegersParseError::InvalidValue(items[1].to_owned()))?;
list.push((item1, item2));
}
Ok(TupleTwoIntegers(list))
}
}

View File

@ -721,6 +721,19 @@ components:
type: boolean type: boolean
default: false default: false
NumaDistance:
required:
- destination
- distance
type: object
properties:
destination:
type: integer
format: uint32
distance:
type: integer
format: uint8
NumaConfig: NumaConfig:
required: required:
- id - id
@ -734,6 +747,10 @@ components:
items: items:
type: integer type: integer
format: uint8 format: uint8
distances:
type: array
items:
$ref: '#/components/schemas/NumaDistance'
VmResize: VmResize:
type: object type: object

View File

@ -5,7 +5,9 @@
use clap::ArgMatches; use clap::ArgMatches;
use net_util::MacAddr; use net_util::MacAddr;
use option_parser::{ByteSized, IntegerList, OptionParser, OptionParserError, Toggle}; use option_parser::{
ByteSized, IntegerList, OptionParser, OptionParserError, Toggle, TupleTwoIntegers,
};
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
@ -1210,20 +1212,30 @@ impl SgxEpcConfig {
} }
} }
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
pub struct NumaDistance {
#[serde(default)]
pub destination: u32,
#[serde(default)]
pub distance: u8,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)] #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
pub struct NumaConfig { pub struct NumaConfig {
#[serde(default)] #[serde(default)]
pub id: u32, pub id: u32,
#[serde(default)] #[serde(default)]
pub cpus: Option<Vec<u8>>, pub cpus: Option<Vec<u8>>,
#[serde(default)]
pub distances: Option<Vec<NumaDistance>>,
} }
impl NumaConfig { impl NumaConfig {
pub const SYNTAX: &'static str = "Settings related to a given NUMA node \ pub const SYNTAX: &'static str = "Settings related to a given NUMA node \
\"id=<node_id>,cpus=<cpus_id>\""; \"id=<node_id>,cpus=<cpus_id>,distances=<list_of_distances_to_destination_nodes>\"";
pub fn parse(numa: &str) -> Result<Self> { pub fn parse(numa: &str) -> Result<Self> {
let mut parser = OptionParser::new(); let mut parser = OptionParser::new();
parser.add("id").add("cpus"); parser.add("id").add("cpus").add("distances");
parser.parse(numa).map_err(Error::ParseNuma)?; parser.parse(numa).map_err(Error::ParseNuma)?;
let id = parser let id = parser
@ -1234,8 +1246,23 @@ impl NumaConfig {
.convert::<IntegerList>("cpus") .convert::<IntegerList>("cpus")
.map_err(Error::ParseNuma)? .map_err(Error::ParseNuma)?
.map(|v| v.0.iter().map(|e| *e as u8).collect()); .map(|v| v.0.iter().map(|e| *e as u8).collect());
let distances = parser
.convert::<TupleTwoIntegers>("distances")
.map_err(Error::ParseNuma)?
.map(|v| {
v.0.iter()
.map(|(e1, e2)| NumaDistance {
destination: *e1 as u32,
distance: *e2 as u8,
})
.collect()
});
Ok(NumaConfig { id, cpus }) Ok(NumaConfig {
id,
cpus,
distances,
})
} }
} }