mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-03-30 17:48:03 -04:00
[skip ci] blueprint config execution
This commit is contained in:
parent
80c85f0e35
commit
a7eee5574b
@ -80,9 +80,9 @@ fn main() -> Result<(), String> {
|
|||||||
|
|
||||||
let router_server = virtual_network::RouterServer::new();
|
let router_server = virtual_network::RouterServer::new();
|
||||||
|
|
||||||
if let Err(e) = router_server.execute_config(initial_config) {
|
router_server
|
||||||
xxx continue here
|
.execute_config(initial_config)
|
||||||
}
|
.map_err(|e| format!("Error executing config: {}", e))?;
|
||||||
|
|
||||||
let _ss_tcp = if !args.no_tcp {
|
let _ss_tcp = if !args.no_tcp {
|
||||||
Some(
|
Some(
|
||||||
|
@ -120,10 +120,10 @@ pub struct TemplateLimits {
|
|||||||
/// maximum number of machines this template will generate
|
/// maximum number of machines this template will generate
|
||||||
#[validate(nested)]
|
#[validate(nested)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub machine_count: Option<WeightedList<u32>>,
|
pub machine_count: Option<WeightedList<usize>>,
|
||||||
#[validate(nested)]
|
#[validate(nested)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub machines_per_network: Option<WeightedList<u32>>,
|
pub machines_per_network: Option<WeightedList<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_template_limits(limits: &TemplateLimits) -> Result<(), ValidationError> {
|
fn validate_template_limits(limits: &TemplateLimits) -> Result<(), ValidationError> {
|
||||||
@ -255,7 +255,7 @@ pub struct BlueprintLimits {
|
|||||||
/// maximum number of networks this blueprint will generate
|
/// maximum number of networks this blueprint will generate
|
||||||
#[validate(nested)]
|
#[validate(nested)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub network_count: Option<WeightedList<u32>>,
|
pub network_count: Option<WeightedList<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_blueprint_limits(limits: &BlueprintLimits) -> Result<(), ValidationError> {
|
fn validate_blueprint_limits(limits: &BlueprintLimits) -> Result<(), ValidationError> {
|
||||||
@ -329,7 +329,7 @@ fn validate_blueprint_ipv4(blueprint_ipv4: &BlueprintIpv4) -> Result<(), Validat
|
|||||||
pub struct BlueprintIpv6 {
|
pub struct BlueprintIpv6 {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
#[validate(nested)]
|
#[validate(nested)]
|
||||||
pub allocation: BlueprintLocation,
|
pub location: BlueprintLocation,
|
||||||
#[validate(nested)]
|
#[validate(nested)]
|
||||||
pub prefix: WeightedList<u8>,
|
pub prefix: WeightedList<u8>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -354,29 +354,27 @@ pub struct BlueprintGateway {
|
|||||||
pub translation: WeightedList<Translation>,
|
pub translation: WeightedList<Translation>,
|
||||||
#[validate(range(min = 0.0, max = 1.0))]
|
#[validate(range(min = 0.0, max = 1.0))]
|
||||||
pub upnp: Probability,
|
pub upnp: Probability,
|
||||||
#[serde(flatten)]
|
#[serde(default, flatten)]
|
||||||
pub location: TemplateLocation,
|
#[validate(nested)]
|
||||||
|
pub location: Option<TemplateLocation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
#[validate(schema(function = "validate_subnets"))]
|
pub struct Scope4 {
|
||||||
pub struct Subnets {
|
#[validate(length(min = 1))]
|
||||||
|
pub scope4: Vec<Ipv4Net>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[validate(nested)]
|
pub pool4: Option<String>,
|
||||||
pub subnet4: Option<WeightedList<Ipv4Net>>,
|
|
||||||
#[serde(default)]
|
|
||||||
#[validate(nested)]
|
|
||||||
pub subnet6: Option<WeightedList<Ipv6Net>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_subnets(subnets: &Subnets) -> Result<(), ValidationError> {
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
if subnets.subnet4.is_none() && subnets.subnet6.is_none() {
|
pub struct Scope6 {
|
||||||
return Err(ValidationError::new("badsub")
|
#[validate(length(min = 1))]
|
||||||
.with_message("subnets must support at least one address type".into()));
|
pub scope6: Vec<Ipv6Net>,
|
||||||
}
|
#[serde(default)]
|
||||||
Ok(())
|
pub pool6: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
@ -398,7 +396,7 @@ fn validate_distance(distance: &Distance) -> Result<(), ValidationError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate, Default)]
|
||||||
#[validate(schema(function = "validate_distribution"))]
|
#[validate(schema(function = "validate_distribution"))]
|
||||||
pub struct Distribution {
|
pub struct Distribution {
|
||||||
pub mean: f32,
|
pub mean: f32,
|
||||||
@ -455,7 +453,10 @@ pub struct Model {
|
|||||||
pub struct Allocation {
|
pub struct Allocation {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
#[validate(nested)]
|
#[validate(nested)]
|
||||||
pub subnets: Subnets,
|
pub scope4: Option<Scope4>,
|
||||||
|
#[serde(flatten)]
|
||||||
|
#[validate(nested)]
|
||||||
|
pub scope6: Option<Scope6>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
@ -467,6 +468,8 @@ pub struct Config {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub default_model: Option<String>,
|
pub default_model: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub default_pool: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub profiles: HashMap<String, Profile>,
|
pub profiles: HashMap<String, Profile>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub machines: HashMap<String, Machine>,
|
pub machines: HashMap<String, Machine>,
|
||||||
@ -509,6 +512,17 @@ impl Validate for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(default_pool) = self.default_pool.as_ref() {
|
||||||
|
if default_pool.is_empty() {
|
||||||
|
errors.add(
|
||||||
|
"default_pool",
|
||||||
|
ValidationError::new("badlen").with_message(
|
||||||
|
"Config must have non-empty default pool if specified".into(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errors.merge_self("profiles", validate_hash_map(&self.profiles));
|
errors.merge_self("profiles", validate_hash_map(&self.profiles));
|
||||||
errors.merge_self("machines", validate_hash_map(&self.machines));
|
errors.merge_self("machines", validate_hash_map(&self.machines));
|
||||||
errors.merge_self("templates", validate_hash_map(&self.templates));
|
errors.merge_self("templates", validate_hash_map(&self.templates));
|
||||||
@ -575,6 +589,7 @@ impl Config {
|
|||||||
seed: other.seed.or(self.seed),
|
seed: other.seed.or(self.seed),
|
||||||
default_network: other.default_network.or(self.default_network),
|
default_network: other.default_network.or(self.default_network),
|
||||||
default_model: other.default_model.or(self.default_model),
|
default_model: other.default_model.or(self.default_model),
|
||||||
|
default_pool: other.default_pool.or(self.default_pool),
|
||||||
profiles: self.profiles.into_iter().chain(other.profiles).collect(),
|
profiles: self.profiles.into_iter().chain(other.profiles).collect(),
|
||||||
machines: self.machines.into_iter().chain(other.machines).collect(),
|
machines: self.machines.into_iter().chain(other.machines).collect(),
|
||||||
templates: self.templates.into_iter().chain(other.templates).collect(),
|
templates: self.templates.into_iter().chain(other.templates).collect(),
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
# this is '$lan')
|
# this is '$lan')
|
||||||
# default_model: "$lan"
|
# default_model: "$lan"
|
||||||
|
|
||||||
|
# The name of the default allocation pool that subnets are allocated from
|
||||||
|
# default_pool: "$internet"
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Profiles
|
# Profiles
|
||||||
#
|
#
|
||||||
@ -174,56 +177,58 @@ blueprints:
|
|||||||
allocations:
|
allocations:
|
||||||
# Custom network allocations
|
# Custom network allocations
|
||||||
boot:
|
boot:
|
||||||
subnet4: ["170.64.128.0/24"]
|
scope4: ["170.64.128.0/24"]
|
||||||
subnet6: ["2a03:b0c0:2::/48"]
|
scope6: ["2a03:b0c0:2::/48"]
|
||||||
# # Predefined networks
|
# # Predefined allocations
|
||||||
# $internet: {}
|
# $internet:
|
||||||
|
# scope4: ["0.0.0.0/0"]
|
||||||
|
# scope6: ["::/0"]
|
||||||
# $private:
|
# $private:
|
||||||
# subnet4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
# scope4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
||||||
# subnet6: ["fc00::/7"]
|
# scope6: ["fc00::/7"]
|
||||||
# $cgnat:
|
# $cgnat:
|
||||||
# subnet4: ["100.64.0.0/10"]
|
# scope4: ["100.64.0.0/10"]
|
||||||
# $linklocal:
|
# $linklocal:
|
||||||
# subnet4: ["169.254.0.0/16"]
|
# scope4: ["169.254.0.0/16"]
|
||||||
# subnet6: ["fe80::/10"]
|
# scope6: ["fe80::/10"]
|
||||||
# $localhost:
|
# $localhost:
|
||||||
# subnet4: ["127.0.0.0/8"]
|
# scope4: ["127.0.0.0/8"]
|
||||||
# subnet6: ["::1/128"]
|
# scope6: ["::1/128"]
|
||||||
# $ietf:
|
# $ietf:
|
||||||
# subnet4: ["192.0.0.0/24"]
|
# scope4: ["192.0.0.0/24"]
|
||||||
# $cellnat:
|
# $cellnat:
|
||||||
# subnet4: ["192.0.0.0/29"]
|
# scope4: ["192.0.0.0/29"]
|
||||||
# $documentation:
|
# $documentation:
|
||||||
# subnet4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
|
# scope4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
|
||||||
# subnet6: ["2001:db8::/32", "3fff::/20"]
|
# scope6: ["2001:db8::/32", "3fff::/20"]
|
||||||
# $benchmark:
|
# $benchmark:
|
||||||
# subnet4: ["198.18.0.0/15"]
|
# scope4: ["198.18.0.0/15"]
|
||||||
# $mulitcast:
|
# $mulitcast:
|
||||||
# subnet4: ["224.0.0.0/4"]
|
# scope4: ["224.0.0.0/4"]
|
||||||
# $mulitcasttest:
|
# $mulitcasttest:
|
||||||
# subnet4: ["233.252.0.0/24"]
|
# scope4: ["233.252.0.0/24"]
|
||||||
# subnet6: ["ff00::/8"]
|
# scope6: ["ff00::/8"]
|
||||||
# $unspecified:
|
# $unspecified:
|
||||||
# subnet4: ["0.0.0.0/8"]
|
# scope4: ["0.0.0.0/8"]
|
||||||
# subnet6: ["::/128"]
|
# scope6: ["::/128"]
|
||||||
# $reserved:
|
# $reserved:
|
||||||
# subnet4: ["192.88.99.0/24", "240.0.0.0/4"]
|
# scope4: ["192.88.99.0/24", "240.0.0.0/4"]
|
||||||
# $broadcast:
|
# $broadcast:
|
||||||
# subnet4: ["255.255.255.255/32"]
|
# scope4: ["255.255.255.255/32"]
|
||||||
# $mapped:
|
# $mapped:
|
||||||
# subnet6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
|
# scope6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
|
||||||
# $translation:
|
# $translation:
|
||||||
# subnet6: ["64:ff9b::/96", "64:ff9b:1::/48"]
|
# scope6: ["64:ff9b::/96", "64:ff9b:1::/48"]
|
||||||
# $discard:
|
# $discard:
|
||||||
# subnet6: ["100::/64"]
|
# scope6: ["100::/64"]
|
||||||
# $teredo:
|
# $teredo:
|
||||||
# subnet6: ["2001::/32"]
|
# scope6: ["2001::/32"]
|
||||||
# $orchidv2:
|
# $orchidv2:
|
||||||
# subnet6: ["2001:20::/28"]
|
# scope6: ["2001:20::/28"]
|
||||||
# $6to4:
|
# $6to4:
|
||||||
# subnet6: ["2002::/16"]
|
# scope6: ["2002::/16"]
|
||||||
# $srv6:
|
# $srv6:
|
||||||
# subnet6: ["5f00::/16"]
|
# scope6: ["5f00::/16"]
|
||||||
#################################################################
|
#################################################################
|
||||||
# Models
|
# Models
|
||||||
#
|
#
|
||||||
|
@ -26,6 +26,19 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub fn scopes_v4(&self) -> Vec<Ipv4Net> {
|
||||||
|
self.scope_v4.iter().cloned().collect()
|
||||||
|
}
|
||||||
|
pub fn allocations_v4(&self) -> Vec<Ipv4Net> {
|
||||||
|
self.allocated_v4.iter().cloned().collect()
|
||||||
|
}
|
||||||
|
pub fn scopes_v6(&self) -> Vec<Ipv6Net> {
|
||||||
|
self.scope_v6.iter().cloned().collect()
|
||||||
|
}
|
||||||
|
pub fn allocations_v6(&self) -> Vec<Ipv6Net> {
|
||||||
|
self.allocated_v6.iter().cloned().collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_scope_v4(&mut self, allocation: Ipv4Net) {
|
pub fn add_scope_v4(&mut self, allocation: Ipv4Net) {
|
||||||
let mut scopes = self.scope_v4.iter().copied().collect::<Vec<_>>();
|
let mut scopes = self.scope_v4.iter().copied().collect::<Vec<_>>();
|
||||||
scopes.push(allocation);
|
scopes.push(allocation);
|
||||||
@ -40,22 +53,22 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
self.scope_v6 = scopes.into();
|
self.scope_v6 = scopes.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_in_scope_v4(&self, allocation: Ipv4Net) -> bool {
|
pub fn find_scope_v4(&self, allocation: Ipv4Net) -> Option<Ipv4Net> {
|
||||||
for x in &self.scope_v4 {
|
for x in &self.scope_v4 {
|
||||||
if x.contains(&allocation) {
|
if x.contains(&allocation) {
|
||||||
return true;
|
return Some(*x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_in_scope_v6(&self, allocation: Ipv6Net) -> bool {
|
pub fn find_scope_v6(&self, allocation: Ipv6Net) -> Option<Ipv6Net> {
|
||||||
for x in &self.scope_v6 {
|
for x in &self.scope_v6 {
|
||||||
if x.contains(&allocation) {
|
if x.contains(&allocation) {
|
||||||
return true;
|
return Some(*x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_v6(&self, prefix: u8) -> GlobalStateManagerResult<bool> {
|
pub fn can_allocate_v6(&self, prefix: u8) -> GlobalStateManagerResult<bool> {
|
||||||
@ -82,11 +95,11 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
allocation: Ipv4Net,
|
allocation: Ipv4Net,
|
||||||
opt_tag: Option<T>,
|
opt_tag: Option<T>,
|
||||||
) -> GlobalStateManagerResult<()> {
|
) -> GlobalStateManagerResult<Ipv4Net> {
|
||||||
// Ensure the allocation is in our scope
|
// Ensure the allocation is in our scope
|
||||||
if !self.is_in_scope_v4(allocation) {
|
let Some(scope) = self.find_scope_v4(allocation) else {
|
||||||
return Err(GlobalStateManagerError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Only reserve if it's not overlapping an allocation
|
// Only reserve if it's not overlapping an allocation
|
||||||
if !self.get_overlaps_v4(allocation).is_empty() {
|
if !self.get_overlaps_v4(allocation).is_empty() {
|
||||||
@ -97,18 +110,18 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
self.allocated_v4.insert_ord(allocation);
|
self.allocated_v4.insert_ord(allocation);
|
||||||
self.owner_tags_v4.insert(allocation, opt_tag);
|
self.owner_tags_v4.insert(allocation, opt_tag);
|
||||||
|
|
||||||
Ok(())
|
Ok(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_allocation_v6(
|
pub fn reserve_allocation_v6(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocation: Ipv6Net,
|
allocation: Ipv6Net,
|
||||||
opt_tag: Option<T>,
|
opt_tag: Option<T>,
|
||||||
) -> GlobalStateManagerResult<()> {
|
) -> GlobalStateManagerResult<Ipv6Net> {
|
||||||
// Ensure the allocation is in our scope
|
// Ensure the allocation is in our scope
|
||||||
if !self.is_in_scope_v6(allocation) {
|
let Some(scope) = self.find_scope_v6(allocation) else {
|
||||||
return Err(GlobalStateManagerError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Only reserve if it's not overlapping an allocation
|
// Only reserve if it's not overlapping an allocation
|
||||||
if !self.get_overlaps_v6(allocation).is_empty() {
|
if !self.get_overlaps_v6(allocation).is_empty() {
|
||||||
@ -119,7 +132,7 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
self.allocated_v6.insert_ord(allocation);
|
self.allocated_v6.insert_ord(allocation);
|
||||||
self.owner_tags_v6.insert(allocation, opt_tag);
|
self.owner_tags_v6.insert(allocation, opt_tag);
|
||||||
|
|
||||||
Ok(())
|
Ok(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_overlaps_v4(&self, allocation: Ipv4Net) -> Vec<Ipv4Net> {
|
pub fn get_overlaps_v4(&self, allocation: Ipv4Net) -> Vec<Ipv4Net> {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -48,14 +48,20 @@ pub enum GlobalStateManagerError {
|
|||||||
BlueprintNotFound(String),
|
BlueprintNotFound(String),
|
||||||
#[error("Model not found: {0}")]
|
#[error("Model not found: {0}")]
|
||||||
ModelNotFound(String),
|
ModelNotFound(String),
|
||||||
|
#[error("Allocation not found: {0}")]
|
||||||
|
AllocationNotFound(String),
|
||||||
#[error("No default model")]
|
#[error("No default model")]
|
||||||
NoDefaultModel,
|
NoDefaultModel,
|
||||||
#[error("No default network")]
|
#[error("No default network")]
|
||||||
NoDefaultNetwork,
|
NoDefaultNetwork,
|
||||||
|
#[error("No default pool")]
|
||||||
|
NoDefaultPool,
|
||||||
#[error("No allocation available")]
|
#[error("No allocation available")]
|
||||||
NoAllocation,
|
NoAllocation,
|
||||||
#[error("Resource in use: {0}")]
|
#[error("Resource in use: {0}")]
|
||||||
ResourceInUse(String),
|
ResourceInUse(String),
|
||||||
|
#[error("Invalid gateway")]
|
||||||
|
InvalidGateway,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type GlobalStateManagerResult<T> = Result<T, GlobalStateManagerError>;
|
pub type GlobalStateManagerResult<T> = Result<T, GlobalStateManagerError>;
|
||||||
|
@ -69,8 +69,8 @@ pub struct BlueprintState {
|
|||||||
pub type BlueprintStateId = StateId<BlueprintState>;
|
pub type BlueprintStateId = StateId<BlueprintState>;
|
||||||
|
|
||||||
impl BlueprintState {
|
impl BlueprintState {
|
||||||
pub fn new(id: BlueprintStateId, name: String) -> GlobalStateManagerResult<BlueprintState> {
|
pub fn new(id: BlueprintStateId, name: String) -> Self {
|
||||||
Ok(Self {
|
Self {
|
||||||
immutable: Arc::new(BlueprintStateImmutable { id, name }),
|
immutable: Arc::new(BlueprintStateImmutable { id, name }),
|
||||||
fields: Arc::new(BlueprintStateFields {
|
fields: Arc::new(BlueprintStateFields {
|
||||||
limit_network_count: None,
|
limit_network_count: None,
|
||||||
@ -79,7 +79,7 @@ impl BlueprintState {
|
|||||||
ipv4: None,
|
ipv4: None,
|
||||||
ipv6: None,
|
ipv6: None,
|
||||||
}),
|
}),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_limit_network_count(&mut self, limit_network_count: Option<usize>) {
|
pub fn set_limit_network_count(&mut self, limit_network_count: Option<usize>) {
|
||||||
@ -99,12 +99,56 @@ impl BlueprintState {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_ipv4(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
self.clear_ipv4_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
if self.fields.ipv4.is_none() {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(BlueprintStateFields {
|
||||||
|
ipv4: None,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_ipv4_gateway(
|
||||||
|
&mut self,
|
||||||
|
_gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
let Some(mut ipv4) = self.fields.ipv4.clone() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let Some(_gateway) = ipv4.gateway else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear gateway
|
||||||
|
ipv4.gateway = None;
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(BlueprintStateFields {
|
||||||
|
ipv4: Some(ipv4),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_ipv4(
|
pub fn set_ipv4(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
params: BlueprintStateIpv4Params,
|
params: BlueprintStateIpv4Params,
|
||||||
gateway_params: Option<BlueprintStateGatewayParams>,
|
) -> GlobalStateManagerResult<()> {
|
||||||
) {
|
self.clear_ipv4(gsm_inner)?;
|
||||||
let mut ipv4 = if let Some(ipv4) = self.fields.ipv4.clone() {
|
|
||||||
|
let ipv4 = if let Some(ipv4) = self.fields.ipv4.clone() {
|
||||||
BlueprintStateIpv4 { params, ..ipv4 }
|
BlueprintStateIpv4 { params, ..ipv4 }
|
||||||
} else {
|
} else {
|
||||||
BlueprintStateIpv4 {
|
BlueprintStateIpv4 {
|
||||||
@ -113,6 +157,26 @@ impl BlueprintState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(BlueprintStateFields {
|
||||||
|
ipv4: Some(ipv4),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ipv4_gateway(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
gateway_params: Option<BlueprintStateGatewayParams>,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
self.clear_ipv4_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
let Some(mut ipv4) = self.fields.ipv4.clone() else {
|
||||||
|
return Err(GlobalStateManagerError::InvalidGateway);
|
||||||
|
};
|
||||||
|
|
||||||
if ipv4.gateway.is_some() {
|
if ipv4.gateway.is_some() {
|
||||||
if let Some(gateway_params) = gateway_params {
|
if let Some(gateway_params) = gateway_params {
|
||||||
ipv4.gateway.as_mut().expect("must exist").params = gateway_params;
|
ipv4.gateway.as_mut().expect("must exist").params = gateway_params;
|
||||||
@ -130,14 +194,60 @@ impl BlueprintState {
|
|||||||
ipv4: Some(ipv4),
|
ipv4: Some(ipv4),
|
||||||
..(*self.fields).clone()
|
..(*self.fields).clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_ipv6(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
self.clear_ipv6_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
if self.fields.ipv6.is_none() {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(BlueprintStateFields {
|
||||||
|
ipv6: None,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_ipv6_gateway(
|
||||||
|
&mut self,
|
||||||
|
_gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
let Some(mut ipv6) = self.fields.ipv6.clone() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let Some(_gateway) = ipv6.gateway else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear gateway
|
||||||
|
ipv6.gateway = None;
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(BlueprintStateFields {
|
||||||
|
ipv6: Some(ipv6),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ipv6(
|
pub fn set_ipv6(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
params: BlueprintStateIpv6Params,
|
params: BlueprintStateIpv6Params,
|
||||||
gateway_params: Option<BlueprintStateGatewayParams>,
|
) -> GlobalStateManagerResult<()> {
|
||||||
) {
|
self.clear_ipv6(gsm_inner)?;
|
||||||
let mut ipv6 = if let Some(ipv6) = self.fields.ipv6.clone() {
|
|
||||||
|
let ipv6 = if let Some(ipv6) = self.fields.ipv6.clone() {
|
||||||
BlueprintStateIpv6 { params, ..ipv6 }
|
BlueprintStateIpv6 { params, ..ipv6 }
|
||||||
} else {
|
} else {
|
||||||
BlueprintStateIpv6 {
|
BlueprintStateIpv6 {
|
||||||
@ -146,6 +256,26 @@ impl BlueprintState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(BlueprintStateFields {
|
||||||
|
ipv6: Some(ipv6),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ipv6_gateway(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
gateway_params: Option<BlueprintStateGatewayParams>,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
self.clear_ipv6_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
let Some(mut ipv6) = self.fields.ipv6.clone() else {
|
||||||
|
return Err(GlobalStateManagerError::InvalidGateway);
|
||||||
|
};
|
||||||
|
|
||||||
if ipv6.gateway.is_some() {
|
if ipv6.gateway.is_some() {
|
||||||
if let Some(gateway_params) = gateway_params {
|
if let Some(gateway_params) = gateway_params {
|
||||||
ipv6.gateway.as_mut().expect("must exist").params = gateway_params;
|
ipv6.gateway.as_mut().expect("must exist").params = gateway_params;
|
||||||
@ -163,6 +293,8 @@ impl BlueprintState {
|
|||||||
ipv6: Some(ipv6),
|
ipv6: Some(ipv6),
|
||||||
..(*self.fields).clone()
|
..(*self.fields).clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_active(&self, gsm_inner: &mut GlobalStateManagerInner) -> bool {
|
pub fn is_active(&self, gsm_inner: &mut GlobalStateManagerInner) -> bool {
|
||||||
@ -197,7 +329,7 @@ impl BlueprintState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let params = NetworkStateModelParams {
|
let params = NetworkStateModelParams {
|
||||||
latency: Some(model.latency.clone()),
|
latency: model.latency.clone(),
|
||||||
distance: model.distance.clone(),
|
distance: model.distance.clone(),
|
||||||
loss: model.loss,
|
loss: model.loss,
|
||||||
};
|
};
|
||||||
@ -246,7 +378,11 @@ impl BlueprintState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get addresses for network
|
// Get addresses for network
|
||||||
let Some(NetworkLocation { subnet, super_net }) = ipv4
|
let Some(NetworkLocation {
|
||||||
|
scope,
|
||||||
|
reserve,
|
||||||
|
super_net,
|
||||||
|
}) = ipv4
|
||||||
.params
|
.params
|
||||||
.locations
|
.locations
|
||||||
.pick_v4(gsm_inner, &ipv4.params.prefix)?
|
.pick_v4(gsm_inner, &ipv4.params.prefix)?
|
||||||
@ -257,7 +393,8 @@ impl BlueprintState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let params = NetworkStateIpv4Params {
|
let params = NetworkStateIpv4Params {
|
||||||
allocation: subnet,
|
scope,
|
||||||
|
reserve,
|
||||||
super_net,
|
super_net,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -320,7 +457,10 @@ impl BlueprintState {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
network_state.set_ipv4(gsm_inner, params, gateway_params)?;
|
network_state.set_ipv4(gsm_inner, params)?;
|
||||||
|
if let Some(gateway_params) = gateway_params {
|
||||||
|
network_state.set_ipv4_gateway(gsm_inner, gateway_params)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +475,11 @@ impl BlueprintState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get addresses for network
|
// Get addresses for network
|
||||||
let Some(NetworkLocation { subnet, super_net }) = ipv6
|
let Some(NetworkLocation {
|
||||||
|
scope,
|
||||||
|
reserve,
|
||||||
|
super_net,
|
||||||
|
}) = ipv6
|
||||||
.params
|
.params
|
||||||
.locations
|
.locations
|
||||||
.pick_v6(gsm_inner, &ipv6.params.prefix)?
|
.pick_v6(gsm_inner, &ipv6.params.prefix)?
|
||||||
@ -346,7 +490,8 @@ impl BlueprintState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let params = NetworkStateIpv6Params {
|
let params = NetworkStateIpv6Params {
|
||||||
allocation: subnet,
|
scope,
|
||||||
|
reserve,
|
||||||
super_net,
|
super_net,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -409,7 +554,10 @@ impl BlueprintState {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
network_state.set_ipv6(gsm_inner, params, gateway_params)?;
|
network_state.set_ipv6(gsm_inner, params)?;
|
||||||
|
if let Some(gateway_params) = gateway_params {
|
||||||
|
network_state.set_ipv6_gateway(gsm_inner, gateway_params)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ pub enum NetworkLocationsList {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NetworkLocation<T> {
|
pub struct NetworkLocation<T> {
|
||||||
pub subnet: T,
|
pub scope: Vec<T>,
|
||||||
|
pub reserve: Vec<T>,
|
||||||
pub super_net: Option<NetworkStateId>,
|
pub super_net: Option<NetworkStateId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,37 +36,31 @@ impl NetworkLocationsList {
|
|||||||
NetworkLocationsList::Allocations { allocations } => {
|
NetworkLocationsList::Allocations { allocations } => {
|
||||||
// Get allocations which have subnets that would fit
|
// Get allocations which have subnets that would fit
|
||||||
// our maximum requested prefix
|
// our maximum requested prefix
|
||||||
let Some(alloc_subnets) = allocations.try_filter_map(|allocation_name| {
|
let Some(address_pools) = allocations.try_filter_map(|allocation_name| {
|
||||||
let allocation = gsm_inner
|
let allocation = gsm_inner
|
||||||
.allocations()
|
.allocations()
|
||||||
.get(allocation_name)
|
.get(allocation_name)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
Ok(allocation
|
if allocation.address_pool.can_allocate_v4(max_prefix)? {
|
||||||
.subnets
|
Ok(Some(allocation.address_pool.clone()))
|
||||||
.subnet4
|
} else {
|
||||||
.as_ref()
|
Ok(None)
|
||||||
.and_then(|subnet| subnet.filter(|p| p.prefix_len() <= max_prefix)))
|
}
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick an allocation
|
// Pick an address pool
|
||||||
let subnets = gsm_inner.srng().weighted_choice_ref(&alloc_subnets);
|
let mut address_pool = gsm_inner.srng().weighted_choice(address_pools);
|
||||||
|
|
||||||
// Pick a subnet
|
|
||||||
let net = *gsm_inner.srng().weighted_choice_ref(subnets);
|
|
||||||
|
|
||||||
// Pick a prefix length that would fit in the subnet
|
// Pick a prefix length that would fit in the subnet
|
||||||
let opt_subnet = prefix
|
let opt_subnet = prefix
|
||||||
.filter(|p| *p >= net.prefix_len())
|
.try_filter(|p| address_pool.can_allocate_v4(*p))?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| {
|
.map(|wl| {
|
||||||
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
||||||
|
|
||||||
// Use an address pool temporarily to pick a subnet
|
|
||||||
let mut address_pool = AddressPool::<()>::new();
|
|
||||||
address_pool.add_scope_v4(net);
|
|
||||||
address_pool.allocate_random_v4(gsm_inner.srng(), subnet_prefix, ())
|
address_pool.allocate_random_v4(gsm_inner.srng(), subnet_prefix, ())
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
@ -74,7 +69,8 @@ impl NetworkLocationsList {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
Ok(Some(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
scope: vec![subnet],
|
||||||
|
reserve: Vec::new(),
|
||||||
super_net: None,
|
super_net: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -126,7 +122,8 @@ impl NetworkLocationsList {
|
|||||||
.set_state(super_network_state);
|
.set_state(super_network_state);
|
||||||
|
|
||||||
Ok(Some(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
scope: vec![subnet],
|
||||||
|
reserve: Vec::new(),
|
||||||
super_net: Some(super_network_id),
|
super_net: Some(super_network_id),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -150,37 +147,31 @@ impl NetworkLocationsList {
|
|||||||
NetworkLocationsList::Allocations { allocations } => {
|
NetworkLocationsList::Allocations { allocations } => {
|
||||||
// Get allocations which have subnets that would fit
|
// Get allocations which have subnets that would fit
|
||||||
// our maximum requested prefix
|
// our maximum requested prefix
|
||||||
let Some(alloc_subnets) = allocations.try_filter_map(|allocation_name| {
|
let Some(address_pools) = allocations.try_filter_map(|allocation_name| {
|
||||||
let allocation = gsm_inner
|
let allocation = gsm_inner
|
||||||
.allocations()
|
.allocations()
|
||||||
.get(allocation_name)
|
.get(allocation_name)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
Ok(allocation
|
if allocation.address_pool.can_allocate_v6(max_prefix)? {
|
||||||
.subnets
|
Ok(Some(allocation.address_pool.clone()))
|
||||||
.subnet6
|
} else {
|
||||||
.as_ref()
|
Ok(None)
|
||||||
.and_then(|subnet| subnet.filter(|p| p.prefix_len() <= max_prefix)))
|
}
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick an allocation
|
// Pick an address pool
|
||||||
let subnets = gsm_inner.srng().weighted_choice_ref(&alloc_subnets);
|
let mut address_pool = gsm_inner.srng().weighted_choice(address_pools);
|
||||||
|
|
||||||
// Pick a subnet
|
|
||||||
let net = *gsm_inner.srng().weighted_choice_ref(subnets);
|
|
||||||
|
|
||||||
// Pick a prefix length that would fit in the subnet
|
// Pick a prefix length that would fit in the subnet
|
||||||
let opt_subnet = prefix
|
let opt_subnet = prefix
|
||||||
.filter(|p| *p >= net.prefix_len())
|
.try_filter(|p| address_pool.can_allocate_v6(*p))?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| {
|
.map(|wl| {
|
||||||
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
||||||
|
|
||||||
// Use an address pool temporarily to pick a subnet
|
|
||||||
let mut address_pool = AddressPool::<()>::new();
|
|
||||||
address_pool.add_scope_v6(net);
|
|
||||||
address_pool.allocate_random_v6(gsm_inner.srng(), subnet_prefix, ())
|
address_pool.allocate_random_v6(gsm_inner.srng(), subnet_prefix, ())
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
@ -189,7 +180,8 @@ impl NetworkLocationsList {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
Ok(Some(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
scope: vec![subnet],
|
||||||
|
reserve: Vec::new(),
|
||||||
super_net: None,
|
super_net: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -241,7 +233,8 @@ impl NetworkLocationsList {
|
|||||||
.set_state(super_network_state);
|
.set_state(super_network_state);
|
||||||
|
|
||||||
Ok(Some(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
scope: vec![subnet],
|
||||||
|
reserve: Vec::new(),
|
||||||
super_net: Some(super_network_id),
|
super_net: Some(super_network_id),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ struct NetworkStateModel {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NetworkStateModelParams {
|
pub struct NetworkStateModelParams {
|
||||||
/// Network latency distribution
|
/// Network latency distribution
|
||||||
pub latency: Option<config::Distribution>,
|
pub latency: config::Distribution,
|
||||||
/// Distance simulation metric
|
/// Distance simulation metric
|
||||||
pub distance: Option<config::Distance>,
|
pub distance: Option<config::Distance>,
|
||||||
/// Packet loss probability
|
/// Packet loss probability
|
||||||
@ -53,7 +53,8 @@ pub struct NetworkStateModelParams {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NetworkStateIpv4Params {
|
pub struct NetworkStateIpv4Params {
|
||||||
pub allocation: Ipv4Net,
|
pub scope: Vec<Ipv4Net>,
|
||||||
|
pub reserve: Vec<Ipv4Net>,
|
||||||
pub super_net: Option<NetworkStateId>,
|
pub super_net: Option<NetworkStateId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +66,8 @@ struct NetworkStateIpv4 {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NetworkStateIpv6Params {
|
pub struct NetworkStateIpv6Params {
|
||||||
pub allocation: Ipv6Net,
|
pub scope: Vec<Ipv6Net>,
|
||||||
|
pub reserve: Vec<Ipv6Net>,
|
||||||
pub super_net: Option<NetworkStateId>,
|
pub super_net: Option<NetworkStateId>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -126,7 +128,7 @@ impl NetworkState {
|
|||||||
address_pool: AddressPool::new(),
|
address_pool: AddressPool::new(),
|
||||||
model: NetworkStateModel {
|
model: NetworkStateModel {
|
||||||
params: NetworkStateModelParams {
|
params: NetworkStateModelParams {
|
||||||
latency: None,
|
latency: config::Distribution::default(),
|
||||||
distance: None,
|
distance: None,
|
||||||
loss: 0.0,
|
loss: 0.0,
|
||||||
},
|
},
|
||||||
@ -144,9 +146,7 @@ impl NetworkState {
|
|||||||
.get_state(generating_blueprint)
|
.get_state(generating_blueprint)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
blueprint_state.on_network_released(self.id());
|
blueprint_state.on_network_released(self.id());
|
||||||
gsm_inner
|
gsm_inner.blueprint_states_mut().set_state(blueprint_state)
|
||||||
.blueprint_states_mut()
|
|
||||||
.set_state(blueprint_state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,9 @@ impl NetworkState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
gsm_inner: &mut GlobalStateManagerInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> GlobalStateManagerResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let Some(ipv4) = self.fields.ipv4.clone() else {
|
self.clear_ipv4_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
if self.fields.ipv4.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,28 +178,6 @@ impl NetworkState {
|
|||||||
GlobalStateManagerError::ResourceInUse(format!("{}-v4", self.debug_name()))
|
GlobalStateManagerError::ResourceInUse(format!("{}-v4", self.debug_name()))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// If we have a gateway, release its external address
|
|
||||||
// if it belongs to a different network
|
|
||||||
if let Some(gateway) = ipv4.gateway.as_ref() {
|
|
||||||
if gateway.params.external_network != self.id() {
|
|
||||||
// Get the external network state
|
|
||||||
let mut external_network_state = gsm_inner
|
|
||||||
.network_states()
|
|
||||||
.get_state(gateway.params.external_network)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Release external address
|
|
||||||
external_network_state
|
|
||||||
.release_address_v4(gateway.external_interface_address.ip)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Update external network
|
|
||||||
gsm_inner
|
|
||||||
.network_states_mut()
|
|
||||||
.set_state(external_network_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update fields
|
// Update fields
|
||||||
self.fields = Arc::new(NetworkStateFields {
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
ipv4: None,
|
ipv4: None,
|
||||||
@ -208,88 +188,168 @@ impl NetworkState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_ipv4_gateway(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
let Some(mut ipv4) = self.fields.ipv4.clone() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let Some(gateway) = ipv4.gateway else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
if gateway.params.external_network != self.id() {
|
||||||
|
// Get the external network state
|
||||||
|
let mut external_network_state = gsm_inner
|
||||||
|
.network_states()
|
||||||
|
.get_state(gateway.params.external_network)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Release external address
|
||||||
|
external_network_state
|
||||||
|
.release_address_v4(gateway.external_interface_address.ip)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
gsm_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release internal address
|
||||||
|
self.release_address_v4(gateway.internal_interface_address.ip)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Clear gateway
|
||||||
|
ipv4.gateway = None;
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv4: Some(ipv4),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_ipv4(
|
pub fn set_ipv4(
|
||||||
&mut self,
|
&mut self,
|
||||||
gsm_inner: &mut GlobalStateManagerInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
params: NetworkStateIpv4Params,
|
params: NetworkStateIpv4Params,
|
||||||
gateway_params: Option<NetworkStateIpv4GatewayParams>,
|
|
||||||
) -> GlobalStateManagerResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
self.clear_ipv4(gsm_inner)?;
|
self.clear_ipv4(gsm_inner)?;
|
||||||
|
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
address_pool.add_scope_v4(params.allocation);
|
for scope in ¶ms.scope {
|
||||||
|
address_pool.add_scope_v4(*scope);
|
||||||
|
}
|
||||||
|
for reserve in ¶ms.reserve {
|
||||||
|
address_pool.reserve_allocation_v4(*reserve, None)?;
|
||||||
|
}
|
||||||
|
|
||||||
let gateway = match gateway_params {
|
let ipv4 = NetworkStateIpv4 {
|
||||||
Some(gateway_params) => {
|
params,
|
||||||
// Allocate or reserve an internal network address for the gateway
|
gateway: None,
|
||||||
let internal_address =
|
|
||||||
if let Some(internal_address) = gateway_params.internal_address {
|
|
||||||
address_pool.reserve_allocation_v4(
|
|
||||||
Ipv4Net::new(internal_address, 32).expect("must succeed"),
|
|
||||||
Some(OwnerTag::Gateway(self.id())),
|
|
||||||
)?;
|
|
||||||
internal_address
|
|
||||||
} else {
|
|
||||||
let Some(internal_address) = address_pool.allocate_random_v4(
|
|
||||||
gsm_inner.srng(),
|
|
||||||
32,
|
|
||||||
OwnerTag::Gateway(self.id()),
|
|
||||||
)?
|
|
||||||
else {
|
|
||||||
return Err(GlobalStateManagerError::NoAllocation);
|
|
||||||
};
|
|
||||||
internal_address.addr()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make internal interface address
|
|
||||||
let internal_interface_address = Ifv4Addr {
|
|
||||||
ip: internal_address,
|
|
||||||
netmask: params.allocation.netmask(),
|
|
||||||
broadcast: Some(params.allocation.broadcast()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the external network state
|
|
||||||
let mut external_network_state = gsm_inner
|
|
||||||
.network_states()
|
|
||||||
.get_state(gateway_params.external_network)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Allocate or reserve an external network address for the gateway
|
|
||||||
let external_interface_address =
|
|
||||||
if matches!(gateway_params.translation, config::Translation::None) {
|
|
||||||
// If the translation mode is 'none', then the external and internal
|
|
||||||
// addresses must be the same
|
|
||||||
external_network_state.allocate_address_v4(
|
|
||||||
gsm_inner,
|
|
||||||
OwnerTag::Gateway(self.id()),
|
|
||||||
Some(internal_address),
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
// Network translation means the internal and external addresses
|
|
||||||
// will be different
|
|
||||||
external_network_state.allocate_address_v4(
|
|
||||||
gsm_inner,
|
|
||||||
OwnerTag::Gateway(self.id()),
|
|
||||||
None,
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update external network
|
|
||||||
gsm_inner
|
|
||||||
.network_states_mut()
|
|
||||||
.set_state(external_network_state);
|
|
||||||
|
|
||||||
// Return the gateway state
|
|
||||||
Some(NetworkStateIpv4Gateway {
|
|
||||||
params: gateway_params,
|
|
||||||
internal_interface_address,
|
|
||||||
external_interface_address,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let ipv4 = NetworkStateIpv4 { params, gateway };
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv4: Some(ipv4),
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ipv4_gateway(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
gateway_params: NetworkStateIpv4GatewayParams,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
self.clear_ipv4_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
let Some(mut ipv4) = self.fields.ipv4.clone() else {
|
||||||
|
return Err(GlobalStateManagerError::InvalidGateway);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
|
||||||
|
// Allocate or reserve an internal network address for the gateway
|
||||||
|
let internal_interface_address =
|
||||||
|
if let Some(internal_address) = gateway_params.internal_address {
|
||||||
|
let scope = address_pool.reserve_allocation_v4(
|
||||||
|
Ipv4Net::new(internal_address, 32).expect("must succeed"),
|
||||||
|
Some(OwnerTag::Gateway(self.id())),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Make interface address
|
||||||
|
Ifv4Addr {
|
||||||
|
ip: internal_address,
|
||||||
|
netmask: scope.netmask(),
|
||||||
|
broadcast: Some(scope.broadcast()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let Some(internal_address) = address_pool.allocate_random_v4(
|
||||||
|
gsm_inner.srng(),
|
||||||
|
32,
|
||||||
|
OwnerTag::Gateway(self.id()),
|
||||||
|
)?
|
||||||
|
else {
|
||||||
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the scope this allocation fits in
|
||||||
|
let scope = address_pool
|
||||||
|
.find_scope_v4(internal_address)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Make interface address
|
||||||
|
let internal_address = internal_address.addr();
|
||||||
|
Ifv4Addr {
|
||||||
|
ip: internal_address,
|
||||||
|
netmask: scope.netmask(),
|
||||||
|
broadcast: Some(scope.broadcast()),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the external network state
|
||||||
|
let mut external_network_state = gsm_inner
|
||||||
|
.network_states()
|
||||||
|
.get_state(gateway_params.external_network)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Allocate or reserve an external network address for the gateway
|
||||||
|
let external_interface_address =
|
||||||
|
if matches!(gateway_params.translation, config::Translation::None) {
|
||||||
|
// If the translation mode is 'none', then the external and internal
|
||||||
|
// addresses must be the same
|
||||||
|
external_network_state.allocate_address_v4(
|
||||||
|
gsm_inner,
|
||||||
|
OwnerTag::Gateway(self.id()),
|
||||||
|
Some(internal_interface_address.ip),
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
// Network translation means the internal and external addresses
|
||||||
|
// will be different
|
||||||
|
external_network_state.allocate_address_v4(
|
||||||
|
gsm_inner,
|
||||||
|
OwnerTag::Gateway(self.id()),
|
||||||
|
None,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
gsm_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
|
||||||
|
// Set the gateway state
|
||||||
|
ipv4.gateway = Some(NetworkStateIpv4Gateway {
|
||||||
|
params: gateway_params,
|
||||||
|
internal_interface_address,
|
||||||
|
external_interface_address,
|
||||||
|
});
|
||||||
|
|
||||||
// Update fields
|
// Update fields
|
||||||
self.fields = Arc::new(NetworkStateFields {
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
@ -305,7 +365,9 @@ impl NetworkState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
gsm_inner: &mut GlobalStateManagerInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> GlobalStateManagerResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let Some(ipv6) = self.fields.ipv6.clone() else {
|
self.clear_ipv6_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
if self.fields.ipv6.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -320,28 +382,6 @@ impl NetworkState {
|
|||||||
GlobalStateManagerError::ResourceInUse(format!("{}-v6", self.debug_name()))
|
GlobalStateManagerError::ResourceInUse(format!("{}-v6", self.debug_name()))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// If we have a gateway, release its external address
|
|
||||||
// if it belongs to a different network
|
|
||||||
if let Some(gateway) = ipv6.gateway.as_ref() {
|
|
||||||
if gateway.params.external_network != self.id() {
|
|
||||||
// Get the external network state
|
|
||||||
let mut external_network_state = gsm_inner
|
|
||||||
.network_states()
|
|
||||||
.get_state(gateway.params.external_network)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Release external address
|
|
||||||
external_network_state
|
|
||||||
.release_address_v6(gateway.external_interface_address.ip)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Update external network
|
|
||||||
gsm_inner
|
|
||||||
.network_states_mut()
|
|
||||||
.set_state(external_network_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update fields
|
// Update fields
|
||||||
self.fields = Arc::new(NetworkStateFields {
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
ipv6: None,
|
ipv6: None,
|
||||||
@ -351,88 +391,166 @@ impl NetworkState {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_ipv6_gateway(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
let Some(mut ipv6) = self.fields.ipv6.clone() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let Some(gateway) = ipv6.gateway else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
if gateway.params.external_network != self.id() {
|
||||||
|
// Get the external network state
|
||||||
|
let mut external_network_state = gsm_inner
|
||||||
|
.network_states()
|
||||||
|
.get_state(gateway.params.external_network)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Release external address
|
||||||
|
external_network_state
|
||||||
|
.release_address_v6(gateway.external_interface_address.ip)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
gsm_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release internal address
|
||||||
|
self.release_address_v6(gateway.internal_interface_address.ip)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Clear gateway
|
||||||
|
ipv6.gateway = None;
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv6: Some(ipv6),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_ipv6(
|
pub fn set_ipv6(
|
||||||
&mut self,
|
&mut self,
|
||||||
gsm_inner: &mut GlobalStateManagerInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
params: NetworkStateIpv6Params,
|
params: NetworkStateIpv6Params,
|
||||||
gateway_params: Option<NetworkStateIpv6GatewayParams>,
|
|
||||||
) -> GlobalStateManagerResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
self.clear_ipv6(gsm_inner)?;
|
self.clear_ipv6(gsm_inner)?;
|
||||||
|
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
address_pool.add_scope_v6(params.allocation);
|
for scope in ¶ms.scope {
|
||||||
|
address_pool.add_scope_v6(*scope);
|
||||||
let gateway = match gateway_params {
|
}
|
||||||
Some(gateway_params) => {
|
for reserve in ¶ms.reserve {
|
||||||
// Allocate or reserve an internal network address for the gateway
|
address_pool.reserve_allocation_v6(*reserve, None)?;
|
||||||
let internal_address =
|
}
|
||||||
if let Some(internal_address) = gateway_params.internal_address {
|
let ipv6 = NetworkStateIpv6 {
|
||||||
address_pool.reserve_allocation_v6(
|
params,
|
||||||
Ipv6Net::new(internal_address, 128).expect("must succeed"),
|
gateway: None,
|
||||||
Some(OwnerTag::Gateway(self.id())),
|
|
||||||
)?;
|
|
||||||
internal_address
|
|
||||||
} else {
|
|
||||||
let Some(internal_address) = address_pool.allocate_random_v6(
|
|
||||||
gsm_inner.srng(),
|
|
||||||
128,
|
|
||||||
OwnerTag::Gateway(self.id()),
|
|
||||||
)?
|
|
||||||
else {
|
|
||||||
return Err(GlobalStateManagerError::NoAllocation);
|
|
||||||
};
|
|
||||||
internal_address.addr()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make internal interface address
|
|
||||||
let internal_interface_address = Ifv6Addr {
|
|
||||||
ip: internal_address,
|
|
||||||
netmask: params.allocation.netmask(),
|
|
||||||
broadcast: Some(params.allocation.broadcast()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the external network state
|
|
||||||
let mut external_network_state = gsm_inner
|
|
||||||
.network_states()
|
|
||||||
.get_state(gateway_params.external_network)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Allocate or reserve an external network address for the gateway
|
|
||||||
let external_interface_address =
|
|
||||||
if matches!(gateway_params.translation, config::Translation::None) {
|
|
||||||
// If the translation mode is 'none', then the external and internal
|
|
||||||
// addresses must be the same
|
|
||||||
external_network_state.allocate_address_v6(
|
|
||||||
gsm_inner,
|
|
||||||
OwnerTag::Gateway(self.id()),
|
|
||||||
Some(internal_address),
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
// Network translation means the internal and external addresses
|
|
||||||
// will be different
|
|
||||||
external_network_state.allocate_address_v6(
|
|
||||||
gsm_inner,
|
|
||||||
OwnerTag::Gateway(self.id()),
|
|
||||||
None,
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update external network
|
|
||||||
gsm_inner
|
|
||||||
.network_states_mut()
|
|
||||||
.set_state(external_network_state);
|
|
||||||
|
|
||||||
// Return the gateway state
|
|
||||||
Some(NetworkStateIpv6Gateway {
|
|
||||||
params: gateway_params,
|
|
||||||
internal_interface_address,
|
|
||||||
external_interface_address,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let ipv6 = NetworkStateIpv6 { params, gateway };
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv6: Some(ipv6),
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ipv6_gateway(
|
||||||
|
&mut self,
|
||||||
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
|
gateway_params: NetworkStateIpv6GatewayParams,
|
||||||
|
) -> GlobalStateManagerResult<()> {
|
||||||
|
self.clear_ipv6_gateway(gsm_inner)?;
|
||||||
|
|
||||||
|
let Some(mut ipv6) = self.fields.ipv6.clone() else {
|
||||||
|
return Err(GlobalStateManagerError::InvalidGateway);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
|
||||||
|
// Allocate or reserve an internal network address for the gateway
|
||||||
|
let internal_interface_address =
|
||||||
|
if let Some(internal_address) = gateway_params.internal_address {
|
||||||
|
let scope = address_pool.reserve_allocation_v6(
|
||||||
|
Ipv6Net::new(internal_address, 128).expect("must succeed"),
|
||||||
|
Some(OwnerTag::Gateway(self.id())),
|
||||||
|
)?;
|
||||||
|
// Make interface address
|
||||||
|
Ifv6Addr {
|
||||||
|
ip: internal_address,
|
||||||
|
netmask: scope.netmask(),
|
||||||
|
broadcast: Some(scope.broadcast()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let Some(internal_address) = address_pool.allocate_random_v6(
|
||||||
|
gsm_inner.srng(),
|
||||||
|
128,
|
||||||
|
OwnerTag::Gateway(self.id()),
|
||||||
|
)?
|
||||||
|
else {
|
||||||
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
|
};
|
||||||
|
// Get the scope this allocation fits in
|
||||||
|
let scope = address_pool
|
||||||
|
.find_scope_v6(internal_address)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Make interface address
|
||||||
|
let internal_address = internal_address.addr();
|
||||||
|
Ifv6Addr {
|
||||||
|
ip: internal_address,
|
||||||
|
netmask: scope.netmask(),
|
||||||
|
broadcast: Some(scope.broadcast()),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the external network state
|
||||||
|
let mut external_network_state = gsm_inner
|
||||||
|
.network_states()
|
||||||
|
.get_state(gateway_params.external_network)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Allocate or reserve an external network address for the gateway
|
||||||
|
let external_interface_address =
|
||||||
|
if matches!(gateway_params.translation, config::Translation::None) {
|
||||||
|
// If the translation mode is 'none', then the external and internal
|
||||||
|
// addresses must be the same
|
||||||
|
external_network_state.allocate_address_v6(
|
||||||
|
gsm_inner,
|
||||||
|
OwnerTag::Gateway(self.id()),
|
||||||
|
Some(internal_interface_address.ip),
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
// Network translation means the internal and external addresses
|
||||||
|
// will be different
|
||||||
|
external_network_state.allocate_address_v6(
|
||||||
|
gsm_inner,
|
||||||
|
OwnerTag::Gateway(self.id()),
|
||||||
|
None,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
gsm_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
|
||||||
|
// Set the gateway state
|
||||||
|
ipv6.gateway = Some(NetworkStateIpv6Gateway {
|
||||||
|
params: gateway_params,
|
||||||
|
internal_interface_address,
|
||||||
|
external_interface_address,
|
||||||
|
});
|
||||||
|
|
||||||
// Update fields
|
// Update fields
|
||||||
self.fields = Arc::new(NetworkStateFields {
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
@ -477,11 +595,14 @@ impl NetworkState {
|
|||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
) -> GlobalStateManagerResult<Ifv4Addr> {
|
) -> GlobalStateManagerResult<Ifv4Addr> {
|
||||||
let net = self.allocate_subnet_v4(gsm_inner, owner_tag, opt_address, 32)?;
|
let net = self.allocate_subnet_v4(gsm_inner, owner_tag, opt_address, 32)?;
|
||||||
|
let scope = self
|
||||||
|
.fields
|
||||||
|
.address_pool
|
||||||
|
.find_scope_v4(net)
|
||||||
|
.expect("must succeed");
|
||||||
let ip = net.addr();
|
let ip = net.addr();
|
||||||
|
let netmask = scope.netmask();
|
||||||
let ipv4 = self.fields.ipv4.as_ref().unwrap();
|
let broadcast = scope.broadcast();
|
||||||
let netmask = ipv4.params.allocation.netmask();
|
|
||||||
let broadcast = ipv4.params.allocation.broadcast();
|
|
||||||
|
|
||||||
let ifaddr = Ifv4Addr {
|
let ifaddr = Ifv4Addr {
|
||||||
ip,
|
ip,
|
||||||
@ -517,11 +638,8 @@ impl NetworkState {
|
|||||||
net
|
net
|
||||||
} else {
|
} else {
|
||||||
// Get a random address if available
|
// Get a random address if available
|
||||||
let Some(allocation) = address_pool.allocate_random_v4(
|
let Some(allocation) =
|
||||||
gsm_inner.srng(),
|
address_pool.allocate_random_v4(gsm_inner.srng(), prefix, owner_tag)?
|
||||||
prefix,
|
|
||||||
owner_tag,
|
|
||||||
)?
|
|
||||||
else {
|
else {
|
||||||
return Err(GlobalStateManagerError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
@ -585,11 +703,15 @@ impl NetworkState {
|
|||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
) -> GlobalStateManagerResult<Ifv6Addr> {
|
) -> GlobalStateManagerResult<Ifv6Addr> {
|
||||||
let net = self.allocate_subnet_v6(gsm_inner, owner_tag, opt_address, 128)?;
|
let net = self.allocate_subnet_v6(gsm_inner, owner_tag, opt_address, 128)?;
|
||||||
let ip = net.addr();
|
let scope = self
|
||||||
|
.fields
|
||||||
|
.address_pool
|
||||||
|
.find_scope_v6(net)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
let ipv6 = self.fields.ipv6.as_ref().unwrap();
|
let ip = net.addr();
|
||||||
let netmask = ipv6.params.allocation.netmask();
|
let netmask = scope.netmask();
|
||||||
let broadcast = ipv6.params.allocation.broadcast();
|
let broadcast = scope.broadcast();
|
||||||
|
|
||||||
let ifaddr = Ifv6Addr {
|
let ifaddr = Ifv6Addr {
|
||||||
ip,
|
ip,
|
||||||
@ -625,11 +747,8 @@ impl NetworkState {
|
|||||||
net
|
net
|
||||||
} else {
|
} else {
|
||||||
// Get a random address if available
|
// Get a random address if available
|
||||||
let Some(allocation) = address_pool.allocate_random_v6(
|
let Some(allocation) =
|
||||||
gsm_inner.srng(),
|
address_pool.allocate_random_v6(gsm_inner.srng(), prefix, owner_tag)?
|
||||||
prefix,
|
|
||||||
owner_tag,
|
|
||||||
)?
|
|
||||||
else {
|
else {
|
||||||
return Err(GlobalStateManagerError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
|
@ -65,20 +65,6 @@ impl<S: State> StateRegistry<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_or_create_by_name<F: FnOnce(StateId<S>, String) -> S>(
|
|
||||||
&mut self,
|
|
||||||
name: String,
|
|
||||||
create: F,
|
|
||||||
) -> StateId<S> {
|
|
||||||
if let Some(id) = self.get_state_id_by_name(&name) {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
let id = self.allocate_id();
|
|
||||||
let state = create(id, name);
|
|
||||||
self.attach_state(state).expect("should always attach");
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allocate_id(&mut self) -> StateId<S> {
|
pub fn allocate_id(&mut self) -> StateId<S> {
|
||||||
// Allocate new internal id
|
// Allocate new internal id
|
||||||
let state_id = self.free_state_ids.pop_back().unwrap_or_else(|| {
|
let state_id = self.free_state_ids.pop_back().unwrap_or_else(|| {
|
||||||
|
@ -14,6 +14,9 @@ default_network: "$internet"
|
|||||||
# this is '$lan')
|
# this is '$lan')
|
||||||
default_model: "$lan"
|
default_model: "$lan"
|
||||||
|
|
||||||
|
# The name of the default allocation pool that subnets are allocated from
|
||||||
|
default_pool: "$internet"
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Networks
|
# Networks
|
||||||
#
|
#
|
||||||
@ -38,54 +41,56 @@ networks:
|
|||||||
# will be used (on the 'public internet').
|
# will be used (on the 'public internet').
|
||||||
|
|
||||||
allocations:
|
allocations:
|
||||||
# Predefined networks
|
# Predefined allocations
|
||||||
$internet: {}
|
$internet:
|
||||||
|
scope4: ["0.0.0.0/0"]
|
||||||
|
scope6: ["::/0"]
|
||||||
$private:
|
$private:
|
||||||
subnet4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
scope4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
||||||
subnet6: ["fc00::/7"]
|
scope6: ["fc00::/7"]
|
||||||
$cgnat:
|
$cgnat:
|
||||||
subnet4: ["100.64.0.0/10"]
|
scope4: ["100.64.0.0/10"]
|
||||||
$linklocal:
|
$linklocal:
|
||||||
subnet4: ["169.254.0.0/16"]
|
scope4: ["169.254.0.0/16"]
|
||||||
subnet6: ["fe80::/10"]
|
scope6: ["fe80::/10"]
|
||||||
$localhost:
|
$localhost:
|
||||||
subnet4: ["127.0.0.0/8"]
|
scope4: ["127.0.0.0/8"]
|
||||||
subnet6: ["::1/128"]
|
scope6: ["::1/128"]
|
||||||
$ietf:
|
$ietf:
|
||||||
subnet4: ["192.0.0.0/24"]
|
scope4: ["192.0.0.0/24"]
|
||||||
$cellnat:
|
$cellnat:
|
||||||
subnet4: ["192.0.0.0/29"]
|
scope4: ["192.0.0.0/29"]
|
||||||
$documentation:
|
$documentation:
|
||||||
subnet4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
|
scope4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
|
||||||
subnet6: ["2001:db8::/32", "3fff::/20"]
|
scope6: ["2001:db8::/32", "3fff::/20"]
|
||||||
$benchmark:
|
$benchmark:
|
||||||
subnet4: ["198.18.0.0/15"]
|
scope4: ["198.18.0.0/15"]
|
||||||
$mulitcast:
|
$mulitcast:
|
||||||
subnet4: ["224.0.0.0/4"]
|
scope4: ["224.0.0.0/4"]
|
||||||
$mulitcasttest:
|
$mulitcasttest:
|
||||||
subnet4: ["233.252.0.0/24"]
|
scope4: ["233.252.0.0/24"]
|
||||||
subnet6: ["ff00::/8"]
|
scope6: ["ff00::/8"]
|
||||||
$unspecified:
|
$unspecified:
|
||||||
subnet4: ["0.0.0.0/8"]
|
scope4: ["0.0.0.0/8"]
|
||||||
subnet6: ["::/128"]
|
scope6: ["::/128"]
|
||||||
$reserved:
|
$reserved:
|
||||||
subnet4: ["192.88.99.0/24", "240.0.0.0/4"]
|
scope4: ["192.88.99.0/24", "240.0.0.0/4"]
|
||||||
$broadcast:
|
$broadcast:
|
||||||
subnet4: ["255.255.255.255/32"]
|
scope4: ["255.255.255.255/32"]
|
||||||
$mapped:
|
$mapped:
|
||||||
subnet6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
|
scope6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
|
||||||
$translation:
|
$translation:
|
||||||
subnet6: ["64:ff9b::/96", "64:ff9b:1::/48"]
|
scope6: ["64:ff9b::/96", "64:ff9b:1::/48"]
|
||||||
$discard:
|
$discard:
|
||||||
subnet6: ["100::/64"]
|
scope6: ["100::/64"]
|
||||||
$teredo:
|
$teredo:
|
||||||
subnet6: ["2001::/32"]
|
scope6: ["2001::/32"]
|
||||||
$orchidv2:
|
$orchidv2:
|
||||||
subnet6: ["2001:20::/28"]
|
scope6: ["2001:20::/28"]
|
||||||
$6to4:
|
$6to4:
|
||||||
subnet6: ["2002::/16"]
|
scope6: ["2002::/16"]
|
||||||
$srv6:
|
$srv6:
|
||||||
subnet6: ["5f00::/16"]
|
scope6: ["5f00::/16"]
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Models
|
# Models
|
||||||
|
@ -156,6 +156,34 @@ impl<T: fmt::Debug + Clone> WeightedList<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_map<F, S, E>(&self, mut filter: F) -> Result<WeightedList<S>, E>
|
||||||
|
where
|
||||||
|
F: FnMut(&T) -> Result<S, E>,
|
||||||
|
S: fmt::Debug + Clone,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
WeightedList::Single(v) => {
|
||||||
|
let item = filter(v)?;
|
||||||
|
Ok(WeightedList::Single(item))
|
||||||
|
}
|
||||||
|
WeightedList::List(vec) => {
|
||||||
|
let mut out = Vec::<Weighted<S>>::with_capacity(vec.len());
|
||||||
|
for v in vec {
|
||||||
|
let item = filter(v.item())?;
|
||||||
|
|
||||||
|
out.push(match v {
|
||||||
|
Weighted::Weighted { item: _, weight } => Weighted::Weighted {
|
||||||
|
item,
|
||||||
|
weight: *weight,
|
||||||
|
},
|
||||||
|
Weighted::Unweighted(_) => Weighted::Unweighted(item),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(WeightedList::List(out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> WeightedListIter<'_, T> {
|
pub fn iter(&self) -> WeightedListIter<'_, T> {
|
||||||
WeightedListIter {
|
WeightedListIter {
|
||||||
values: self,
|
values: self,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user