v1 of virtualrouter definition schema

This commit is contained in:
Christien Rioux 2024-11-15 20:36:56 -05:00
parent fd96af88f3
commit a37b91dc37
2 changed files with 372 additions and 68 deletions

View File

@ -37,14 +37,54 @@ const fn default_weight() -> f32 {
1.0f32 1.0f32
} }
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum WeightedList<T: fmt::Debug + Clone> {
List {
#[serde(flatten)]
value: Vec<Weighted<T>>,
},
Single {
#[serde(flatten)]
value: T,
},
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct Probability {
#[serde(flatten)]
probability: f32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum Weighted<T: fmt::Debug + Clone> {
Weighted {
item: T,
weight: f32,
},
Unweighted {
#[serde(flatten)]
value: T,
},
}
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Profile { pub struct Profile {
machine: One<String>, instances: Vec<Instance>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum Instance {
Machine { machine: WeightedList<String> },
Template { template: WeightedList<String> },
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Machine { pub struct Machine {
network: One<String>, #[serde(flatten)]
location: Location,
#[serde(default)] #[serde(default)]
address4: Option<Ipv4Addr>, address4: Option<Ipv4Addr>,
#[serde(default)] #[serde(default)]
@ -55,57 +95,100 @@ pub struct Machine {
bootstrap: bool, bootstrap: bool,
} }
#[derive(Debug, Clone, Default, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct One<T: fmt::Debug + Clone> { pub struct Template {
#[serde(flatten)] #[serde(flatten)]
pub value: Vec<Weighted<T>>, location: Location,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct OneOrNone<T: fmt::Debug + Clone> {
#[serde(flatten)] #[serde(flatten)]
pub value: Vec<Weighted<T>>, limits: Limits,
#[serde(default = "default_weight")] #[serde(default)]
pub none_weight: f32, disable_capabilities: Vec<String>,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct Probability {
#[serde(flatten)]
probability: f32,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Weighted<T: fmt::Debug + Clone> { pub struct Limits {
#[serde(flatten)] machine_count: WeightedList<u32>,
pub value: T,
#[serde(default = "default_weight")]
pub weight: f32,
} }
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum Location {
Network { network: WeightedList<String> },
Blueprint { blueprint: WeightedList<String> },
}
////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Network { pub struct Network {
#[serde(flatten)] model: String,
subnets: Subnets,
#[serde(default)] #[serde(default)]
distance: Option<Distance>, ipv4: Option<NetworkIpv4>,
#[serde(flatten)]
performance: Performance,
#[serde(default)] #[serde(default)]
gateway: Option<Gateway>, ipv6: Option<NetworkIpv6>,
} }
#[derive(Debug, Clone, Deserialize)]
pub struct NetworkIpv4 {
allocation: String,
#[serde(default)]
gateway: Option<NetworkGateway>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct NetworkIpv6 {
allocation: String,
#[serde(default)]
gateway: Option<NetworkGateway>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct NetworkGateway {
translation: Translation,
upnp: bool,
network: Option<String>,
}
////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Deserialize)]
pub struct Blueprint {
models: WeightedList<String>,
#[serde(default)]
ipv4: Option<BlueprintIpv4>,
#[serde(default)]
ipv6: Option<BlueprintIpv6>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct BlueprintIpv4 {
#[serde(default)]
allocation: Option<String>,
prefix: u8,
#[serde(default)]
gateway: Option<BlueprintGateway>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct BlueprintIpv6 {
#[serde(default)]
allocation: Option<String>,
prefix: u8,
#[serde(default)]
gateway: Option<BlueprintGateway>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct BlueprintGateway {
translation: WeightedList<Translation>,
upnp: Probability,
network: Option<String>,
}
////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Subnets { pub struct Subnets {
subnet4: OneOrNone<Ipv4Net>, subnet4: Vec<Ipv4Net>,
subnet6: OneOrNone<Ipv6Net>, subnet6: Vec<Ipv6Net>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Gateway {
translation: One<Translation>,
upnp: Probability,
network: String,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
@ -124,17 +207,7 @@ pub struct Distribution {
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Decay { #[serde(rename_all = "snake_case")]
lambda: f32,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Performance {
latency: Distribution,
loss: Probability,
}
#[derive(Debug, Clone, Deserialize)]
pub enum Translation { pub enum Translation {
None, None,
PortRestricted, PortRestricted,
@ -142,12 +215,38 @@ pub enum Translation {
Symmetric, Symmetric,
} }
impl Default for Translation {
fn default() -> Self {
Self::None
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct Model {
latency: Distribution,
#[serde(default)]
distance: Option<Distance>,
#[serde(default)]
loss: Probability,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Allocation {
#[serde(flatten)]
subnets: Subnets,
}
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Config { pub struct Config {
seed: Option<u32>, seed: Option<u32>,
default_network: String,
profiles: HashMap<String, Profile>, profiles: HashMap<String, Profile>,
machines: HashMap<String, Machine>, machines: HashMap<String, Machine>,
templates: HashMap<String, Template>,
networks: HashMap<String, Network>, networks: HashMap<String, Network>,
blueprint: HashMap<String, Network>,
allocations: HashMap<String, Allocation>,
models: HashMap<String, Model>,
} }
impl Config { impl Config {

View File

@ -1,9 +1,46 @@
--- ---
# Random number seed used to generate all profile configurations
# for a test. The seed can be overriden on the VirtualRouter command
# line to choose a different test scenario. The same seed will
# generate the same configuration on all machines given the same
# configuration file.
seed: 0 seed: 0
# The name of the predefined network to use by default (typically
# this is '$internet')
default_network: "$internet"
#################################################################
# Profiles
#
# Profiles are ordered lists of machine instances or machine templates
# to assign to new instances of Veilid as they are allocated from
# the VirtualRouter
profiles: profiles:
- default:
- bootstrap: - bootstrap:
instances:
# two bootstrap machines
- machine: "bootstrap-1.veilid.net"
- machine: "bootstrap-2.veilid.net"
# pool of up to 4 relay-capable servers
- template: "bootrelay"
# geographically disperse servers of various configurations
- server: - server:
instances:
- template:
- "relayserver"
- "ipv4server"
- "ipv6server"
- "nat4home"
- "nat4+6home"
#################################################################
# Machines
#
# Machines are single, fully-defined machine specifications that
# can only be allocated one time
machines: machines:
- bootstrap-1.veilid.net: - bootstrap-1.veilid.net:
network: "boot" network: "boot"
@ -19,25 +56,193 @@ machines:
disable_capabilities: disable_capabilities:
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"] ["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
bootstrap: true bootstrap: true
#################################################################
# Templates
#
# Templates are used to generate Machines that are all on a single
# network. A maximum number of machines are allocated on the
# network within the limits specified.
templates:
# Default servers on the boot network
# - will have ipv4 and ipv6 addresses
# - will have no capabilities disabled
# - will not use NAT, and be directly connected
# - limited to 4 machines
- bootrelay:
network: "boot"
machine_count: 4
# Servers on subnets within the 'internet' network
- relayserver:
blueprint: "direct"
machine_count: [1, 2, 3]
- ipv4server:
blueprint: "direct_ipv4_no_ipv6"
machine_count: [1, 2, 3]
- ipv6server:
blueprint: "direct_ipv6_no_ipv4"
machine_count: [1, 2, 3]
- nat4home:
blueprint: "nat_ipv4_no_ipv6"
machine_count: [1, 2, 3]
- nat4+6home:
blueprint: "nat_ipv4_direct_ipv6"
machine_count: [1, 2, 3]
#################################################################
# Networks
#
# Networks are
networks: networks:
- internet: # Custom networks
distance: - boot:
min: 0.04 model: "$lan"
max: 2.0 ipv4:
latency: allocation: "boot"
mean: 0.200 ipv6:
sigma: 0.080 allocation: "boot"
skew: 0
min: 0.030 # Predefined networks
max: 0.400 - $internet:
loss: 0.01 model: "$internet"
#################################################################
# Blueprints
#
# Blueprints are used to generate Networks for use with Machines
blueprints:
# A subnet of the internet directly attached with no translation
# with both ipv4 and ipv6 networking
- direct:
models: "$lan"
ipv4:
prefix: 24
ipv6:
prefix: 64
# An ipv4-only subnet of the internet directly attached with no translation
- direct_ipv4_no_ipv6:
models: "$lan"
ipv4:
prefix: 24
# An ipv6-only subnet of the internet directly attached with no translation
- direct_ipv6_no_ipv4:
models: "$lan"
ipv6:
prefix: 64
# An ipv4-only subnet of the internet attached via NAT
- nat_ipv4_no_ipv6:
models: "$lan"
ipv4:
allocation: "$private"
prefix: 0
gateway:
translation: "PortRestricted"
upnp: 0.25
# An ipv4 subnet of the internet attached via NAT and
# an ipv6 subnet of the internet directly attached with no translation
- nat_ipv4_direct_ipv6:
models: "$lan"
ipv4:
allocation: "$private"
prefix: 0
gateway:
translation: "PortRestricted"
upnp: 0.25
ipv6:
prefix: 56
#################################################################
# Allocations
#
# Allocations are partitions of the address space that networks
# can be assigned to. Machines on the networks will be given
# addresses within these ranges. If an allocation
# is not specified, an address -outside- any of the allocation
# will be used (on the 'public internet').
allocations:
# Custom network allocations
- boot: - boot:
subnet4: ["170.64.128.0/24"] subnet4: ["170.64.128.0/24"]
subnet6: ["2a03:b0c0:2::/48"] subnet6: ["2a03:b0c0:2::/48"]
latency:
mean: 0.0038 # Predefined networks
sigma: 0.001416 - $private:
skew: 0.0009 subnet4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
min: 0.0015 subnet6: ["fc00::/7"]
max: 0.0075 - $cgnat:
loss: 0.0 subnet4: ["100.64.0.0/10"]
- $linklocal:
subnet4: ["169.254.0.0/16"]
subnet6: ["fe80::/10"]
- $localhost:
subnet4: ["127.0.0.0/8"]
subnet6: ["::1/128"]
- $ietf:
subnet4: ["192.0.0.0/24"]
- $cellnat:
subnet4: ["192.0.0.0/29"]
- $documentation:
subnet4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
subnet6: ["2001:db8::/32", "3fff::/20"]
- $benchmark:
subnet4: ["198.18.0.0/15"]
- $mulitcast:
subnet4: ["224.0.0.0/4"]
- $mulitcasttest:
subnet4: ["233.252.0.0/24"]
subnet6: ["ff00::/8"]
- $unspecified:
subnet4: ["0.0.0.0/8"]
subnet6: ["::/128"]
- $reserved:
subnet4: ["192.88.99.0/24", "240.0.0.0/4"]
- $broadcast:
subnet4: ["255.255.255.255/32"]
- $mapped:
subnet6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
- $translation:
subnet6: ["64:ff9b::/96", "64:ff9b:1::/48"]
- $discard:
subnet6: ["100::/64"]
- $teredo:
subnet6: ["2001::/32"]
- $orchidv2:
subnet6: ["2001:20::/28"]
- $6to4:
subnet6: ["2002::/16"]
- $srv6:
subnet6: ["5f00::/16"]
#################################################################
# Models
#
# Performance models representing how a network behaves
# Latency models are a skewed normal distribution
# Distance is assigned over a circular probability and then
# mapped linearly as a multiplier to latency and loss
models:
# Predefined models
$lan:
latency:
mean: 0.0038
sigma: 0.001416
skew: 0.0009
min: 0.0015
max: 0.0075
loss: 0.0
$internet:
distance:
min: 0.04
max: 2.0
latency:
mean: 0.200
sigma: 0.080
skew: 0
min: 0.030
max: 0.400
loss: 0.01