machine state work

This commit is contained in:
Christien Rioux 2025-01-01 16:31:17 -05:00
parent 693b9d185b
commit 3cb880c0bf
4 changed files with 312 additions and 151 deletions

View File

@ -139,7 +139,7 @@ impl MachineRegistryInner {
} }
}; };
break Ok(machine_state_id.0); break Ok(machine_state_id.external_id());
} }
} }

View File

@ -1,60 +1,69 @@
use super::*; use super::*;
#[derive(Debug)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
struct MachineStateInner { pub enum MachineOrigin {
/// The template generating this machine InitialConfig,
generating_template: Option<TemplateStateId>, Direct,
Template(TemplateStateId),
}
#[derive(Debug, Clone)]
struct MachineStateFields {
/// The current network interfaces definition /// The current network interfaces definition
interfaces: HashMap<String, MachineStateInterface>, interfaces: imbl::HashMap<Arc<String>, MachineStateInterface>,
/// Capabilities to disable on this machine /// Capabilities to disable on this machine
disable_capabilities: Vec<String>, disable_capabilities: imbl::Vector<String>,
/// If this machine is a bootstrap /// If this machine is a bootstrap
bootstrap: bool, bootstrap: bool,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct MachineStateInterface { pub struct MachineStateInterface {
/// The network this interface belongs to /// The network this interface belongs to
pub network_id: Option<NetworkStateId>, pub network_id: Option<NetworkStateId>,
/// The veilid NetworkInterface state /// The veilid NetworkInterface state
pub network_interface: NetworkInterface, pub network_interface: Arc<NetworkInterface>,
} }
#[derive(Debug)] #[derive(Debug)]
struct MachineStateUnlockedInner { struct MachineStateImmutable {
/// The id of this machine /// The id of this machine
id: MachineStateId, id: MachineStateId,
/// The name of this machine if it is named /// The name of this machine if it is named
opt_name: Option<String>, opt_name: Option<String>,
/// Where this machine came for housekeeping purposes
origin: MachineOrigin,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MachineState { pub struct MachineState {
xxx convert to immutable state immutable: Arc<MachineStateImmutable>,
unlocked_inner: Arc<MachineStateUnlockedInner>, fields: Arc<MachineStateFields>,
inner: Arc<Mutex<MachineStateInner>>,
} }
pub type MachineStateId = StateId<MachineState>; pub type MachineStateId = StateId<MachineState>;
impl MachineState { impl MachineState {
pub fn new(id: MachineStateId, opt_name: Option<String>) -> Self { pub fn new(id: MachineStateId, opt_name: Option<String>, origin: MachineOrigin) -> Self {
// Create a localhost interface for this machine // Create a localhost interface for this machine
Self { Self {
unlocked_inner: Arc::new(MachineStateUnlockedInner { id, opt_name }), immutable: Arc::new(MachineStateImmutable {
inner: Arc::new(Mutex::new(MachineStateInner { id,
generating_template: None, opt_name,
interfaces: HashMap::new(), origin,
disable_capabilities: Vec::new(), }),
fields: Arc::new(MachineStateFields {
interfaces: imbl::HashMap::new(),
disable_capabilities: imbl::Vector::new(),
bootstrap: false, bootstrap: false,
})), }),
} }
} }
pub fn release(&self, machine_registry_inner: &mut MachineRegistryInner) { pub fn release(mut self, machine_registry_inner: &mut MachineRegistryInner) {
self.release_all_interfaces(machine_registry_inner); self.release_all_interfaces(machine_registry_inner);
let inner = self.inner.lock();
if let Some(generating_template) = inner.generating_template { if let MachineOrigin::Template(generating_template) = self.immutable.origin {
let template_state = machine_registry_inner let template_state = machine_registry_inner
.template_states_mut() .template_states_mut()
.get_state(generating_template) .get_state(generating_template)
@ -63,44 +72,40 @@ impl MachineState {
} }
} }
pub fn external_id(&self) -> MachineId { pub fn set_disable_capabilities(&mut self, disable_capabilities: Vec<String>) {
self.unlocked_inner.id.0 self.fields = Arc::new(MachineStateFields {
disable_capabilities: disable_capabilities.into(),
..(*self.fields).clone()
});
} }
pub fn set_generating_template(&self, generating_template: TemplateStateId) { pub fn set_bootstrap(&mut self, bootstrap: bool) {
let mut inner = self.inner.lock(); self.fields = Arc::new(MachineStateFields {
inner.generating_template = Some(generating_template); bootstrap,
..(*self.fields).clone()
});
} }
pub fn set_disable_capabilities(&self, disable_capabilities: Vec<String>) { fn next_free_interface_key(&self) -> Arc<String> {
let mut inner = self.inner.lock();
inner.disable_capabilities = disable_capabilities;
}
pub fn set_bootstrap(&self, bootstrap: bool) {
let mut inner = self.inner.lock();
inner.bootstrap = bootstrap
}
fn next_free_interface_name_inner(inner: &MachineStateInner) -> String {
let mut inum = 0usize; let mut inum = 0usize;
loop { loop {
let name = format!("vin{}", inum); let name = format!("vin{}", inum);
if !inner.interfaces.contains_key(&name) { if !self.fields.interfaces.contains_key(&name) {
return name; return Arc::new(name);
} }
inum += 1; inum += 1;
} }
} }
pub fn allocate_interface( pub fn allocate_interface(
&self, &mut self,
opt_name: Option<String>, interface_name: Option<String>,
opt_interface_flags: Option<InterfaceFlags>, opt_interface_flags: Option<InterfaceFlags>,
) -> MachineRegistryResult<String> { ) -> MachineRegistryResult<Arc<String>> {
let mut inner = self.inner.lock(); let interface_key = interface_name
let name = opt_name.unwrap_or_else(|| Self::next_free_interface_name_inner(&*inner)); .map(Arc::new)
if inner.interfaces.contains_key(&name) { .unwrap_or_else(|| self.next_free_interface_key());
if self.fields.interfaces.contains_key(&interface_key) {
return Err(MachineRegistryError::DuplicateName); return Err(MachineRegistryError::DuplicateName);
} }
let flags = opt_interface_flags.unwrap_or_else(|| InterfaceFlags { let flags = opt_interface_flags.unwrap_or_else(|| InterfaceFlags {
@ -109,44 +114,50 @@ impl MachineState {
is_point_to_point: false, is_point_to_point: false,
has_default_route: true, has_default_route: true,
}); });
inner.interfaces.insert( let interfaces = self.fields.interfaces.update(
name.clone(), interface_key.clone(),
MachineStateInterface { MachineStateInterface {
network_id: None, network_id: None,
network_interface: NetworkInterface { network_interface: Arc::new(NetworkInterface {
name: name.clone(), name: (*interface_key).clone(),
flags, flags,
addrs: Vec::new(), addrs: Vec::new(),
}, }),
}, },
); );
Ok(name) self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(interface_key)
} }
pub fn interfaces(&self) -> Vec<String> { pub fn interfaces(&self) -> Vec<Arc<String>> {
let mut intfs: Vec<String> = self.inner.lock().interfaces.keys().cloned().collect(); let mut intfs: Vec<_> = self.fields.interfaces.keys().cloned().collect();
intfs.sort(); intfs.sort();
intfs intfs
} }
pub fn allocate_address_ipv4( pub fn allocate_address_ipv4(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
opt_address: Option<Ipv4Addr>, opt_address: Option<Ipv4Addr>,
opt_address_flags: Option<AddressFlags>, opt_address_flags: Option<AddressFlags>,
) -> MachineRegistryResult<Ifv4Addr> { ) -> MachineRegistryResult<Ifv4Addr> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_string());
let Some(intf) = inner.interfaces.get_mut(interface) else { let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
else {
return Err(MachineRegistryError::InvalidName); return Err(MachineRegistryError::InvalidName);
}; };
// Get the network state // Get the network state
let Some(network_id) = intf.network_id else { let Some(network_id) = machine_state_interface.network_id else {
return Err(MachineRegistryError::NetworkNotFound); return Err(MachineRegistryError::NetworkNotFound);
}; };
let network_state = machine_registry_inner let mut network_state = machine_registry_inner
.network_states() .network_states()
.get_state(network_id)?; .get_state(network_id)?;
@ -158,6 +169,11 @@ impl MachineState {
opt_address, opt_address,
)?; )?;
// Update the network state
machine_registry_inner
.network_states_mut()
.set_state(network_state);
// Get address flags // Get address flags
let flags = opt_address_flags.unwrap_or_else(|| AddressFlags { let flags = opt_address_flags.unwrap_or_else(|| AddressFlags {
is_dynamic, is_dynamic,
@ -165,31 +181,49 @@ impl MachineState {
is_preferred: true, is_preferred: true,
}); });
intf.network_interface.addrs.push(InterfaceAddress { // Update interface addresses
let mut new_intf = (*machine_state_interface.network_interface).clone();
new_intf.addrs.push(InterfaceAddress {
if_addr: IfAddr::V4(ifv4_addr.clone()), if_addr: IfAddr::V4(ifv4_addr.clone()),
flags, flags,
}); });
// Update interface
machine_state_interface.network_interface = Arc::new(new_intf);
// Update interfaces map
let interfaces = self
.fields
.interfaces
.update(interface_key, machine_state_interface);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(ifv4_addr) Ok(ifv4_addr)
} }
pub fn allocate_address_ipv6( pub fn allocate_address_ipv6(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
opt_address: Option<Ipv6Addr>, opt_address: Option<Ipv6Addr>,
opt_address_flags: Option<AddressFlags>, opt_address_flags: Option<AddressFlags>,
) -> MachineRegistryResult<Ifv6Addr> { ) -> MachineRegistryResult<Ifv6Addr> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_string());
let Some(intf) = inner.interfaces.get_mut(interface) else { let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
else {
return Err(MachineRegistryError::InvalidName); return Err(MachineRegistryError::InvalidName);
}; };
// Get the network state // Get the network state
let Some(network_id) = intf.network_id else { let Some(network_id) = machine_state_interface.network_id else {
return Err(MachineRegistryError::NetworkNotFound); return Err(MachineRegistryError::NetworkNotFound);
}; };
let network_state = machine_registry_inner let mut network_state = machine_registry_inner
.network_states() .network_states()
.get_state(network_id)?; .get_state(network_id)?;
@ -200,6 +234,10 @@ impl MachineState {
OwnerTag::Machine(self.id()), OwnerTag::Machine(self.id()),
opt_address, opt_address,
)?; )?;
// Update the network state
machine_registry_inner
.network_states_mut()
.set_state(network_state);
// Get address flags // Get address flags
let flags = opt_address_flags.unwrap_or_else(|| AddressFlags { let flags = opt_address_flags.unwrap_or_else(|| AddressFlags {
@ -208,48 +246,98 @@ impl MachineState {
is_preferred: true, is_preferred: true,
}); });
intf.network_interface.addrs.push(InterfaceAddress { // Update interface addresses
let mut new_intf = (*machine_state_interface.network_interface).clone();
new_intf.addrs.push(InterfaceAddress {
if_addr: IfAddr::V6(ifv6_addr.clone()), if_addr: IfAddr::V6(ifv6_addr.clone()),
flags, flags,
}); });
// Update interface
machine_state_interface.network_interface = Arc::new(new_intf);
// Update interfaces map
let interfaces = self
.fields
.interfaces
.update(interface_key, machine_state_interface);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(ifv6_addr) Ok(ifv6_addr)
} }
pub fn attach_network( pub fn attach_network(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
network_id: NetworkStateId, network_id: NetworkStateId,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_string());
let Some(intf) = inner.interfaces.get_mut(interface) else { let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
else {
return Err(MachineRegistryError::InvalidName); return Err(MachineRegistryError::InvalidName);
}; };
if intf.network_id.is_some() {
self.detach_network(machine_registry_inner, interface); if machine_state_interface.network_id.is_some() {
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
} }
intf.network_id = Some(network_id);
machine_state_interface.network_id = Some(network_id);
// Update interfaces map
let interfaces = self
.fields
.interfaces
.update(interface_key, machine_state_interface);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(()) Ok(())
} }
pub fn detach_network( pub fn detach_network(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_string());
Self::detach_network_inner(&mut *inner, machine_registry_inner, interface) let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
else {
return Err(MachineRegistryError::InvalidName);
};
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
// Update interfaces map
let interfaces = self
.fields
.interfaces
.update(interface_key, machine_state_interface);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(())
} }
pub fn attached_network_interfaces( pub fn attached_network_interfaces(
&self, &self,
network_id: NetworkStateId, network_id: NetworkStateId,
) -> MachineRegistryResult<Vec<String>> { ) -> MachineRegistryResult<Vec<Arc<String>>> {
let mut out = Vec::new(); let mut out = Vec::new();
let inner = self.inner.lock(); for intf in &self.fields.interfaces {
for intf in &inner.interfaces {
if intf.1.network_id == Some(network_id) { if intf.1.network_id == Some(network_id) {
out.push(intf.0.clone()); out.push(intf.0.clone());
} }
@ -258,22 +346,23 @@ impl MachineState {
} }
pub fn release_address( pub fn release_address(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
address: IpAddr, address: IpAddr,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_owned());
let Some(intf) = inner.interfaces.get_mut(interface) else { let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
else {
return Err(MachineRegistryError::InvalidName); return Err(MachineRegistryError::InvalidName);
}; };
let Some(network_id) = intf.network_id else { let Some(network_id) = machine_state_interface.network_id else {
return Err(MachineRegistryError::NetworkNotFound); return Err(MachineRegistryError::NetworkNotFound);
}; };
// Get the network state // Get the network state
let network_state = machine_registry_inner let mut network_state = machine_registry_inner
.network_states() .network_states()
.get_state(network_id)?; .get_state(network_id)?;
@ -283,92 +372,168 @@ impl MachineState {
IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?, IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?,
}; };
// Update the network state
machine_registry_inner
.network_states_mut()
.set_state(network_state);
// Remove the address from the interface // Remove the address from the interface
intf.network_interface let addrs: Vec<_> = machine_state_interface
.network_interface
.addrs .addrs
.retain(|x| x.if_addr().ip() != address); .iter()
.filter(|x| x.if_addr().ip() != address)
.cloned()
.collect();
// Update network interface
machine_state_interface.network_interface = Arc::new(NetworkInterface {
addrs,
..(*machine_state_interface.network_interface).clone()
});
// Update interfaces map
let interfaces = self
.fields
.interfaces
.update(interface_key, machine_state_interface);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(()) Ok(())
} }
pub fn release_all_addresses( pub fn release_all_addresses(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_string());
Self::release_all_addresses_inner(&mut *inner, machine_registry_inner, interface) let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
} else {
fn detach_network_inner(
inner: &mut MachineStateInner,
machine_registry_inner: &mut MachineRegistryInner,
interface: &str,
) -> MachineRegistryResult<()> {
Self::release_all_addresses_inner(inner, machine_registry_inner, interface)?;
let Some(intf) = inner.interfaces.get_mut(interface) else {
return Err(MachineRegistryError::InvalidName); return Err(MachineRegistryError::InvalidName);
}; };
intf.network_id = None;
Self::release_all_addresses_inner(machine_registry_inner, &mut machine_state_interface)?;
// Update interfaces map
let interfaces = self
.fields
.interfaces
.update(interface_key, machine_state_interface);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(())
}
////////////////////////////////////////////////////////////////////////
fn detach_network_inner(
machine_registry_inner: &mut MachineRegistryInner,
machine_state_interface: &mut MachineStateInterface,
) -> MachineRegistryResult<()> {
Self::release_all_addresses_inner(machine_registry_inner, machine_state_interface)?;
machine_state_interface.network_id = None;
Ok(()) Ok(())
} }
fn release_all_addresses_inner( fn release_all_addresses_inner(
inner: &mut MachineStateInner,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, machine_state_interface: &mut MachineStateInterface,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let Some(intf) = inner.interfaces.get_mut(interface) else { let Some(network_id) = machine_state_interface.network_id else {
return Err(MachineRegistryError::InvalidName);
};
let Some(network_id) = intf.network_id else {
return Ok(()); return Ok(());
}; };
// Get the network state // Get the network state
let network_state = machine_registry_inner let mut network_state = machine_registry_inner
.network_states() .network_states()
.get_state(network_id)?; .get_state(network_id)?;
// Release the addresses from the network // Release the addresses from the network
for addr in &intf.network_interface.addrs { for addr in &machine_state_interface.network_interface.addrs {
match addr.if_addr.ip() { match addr.if_addr.ip() {
IpAddr::V4(ipv4_addr) => network_state.release_address_v4(ipv4_addr)?, IpAddr::V4(ipv4_addr) => network_state.release_address_v4(ipv4_addr)?,
IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?, IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?,
}; };
} }
// Update the network state
machine_registry_inner
.network_states_mut()
.set_state(network_state);
// Remove the addresses from the interface // Remove the addresses from the interface
intf.network_interface.addrs.clear(); let mut new_intf = (*machine_state_interface.network_interface).clone();
new_intf.addrs.clear();
// Update interface
machine_state_interface.network_interface = Arc::new(new_intf);
Ok(()) Ok(())
} }
pub fn release_interface( pub fn release_interface(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
interface: &str, interface_name: &str,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let mut inner = self.inner.lock(); let interface_key = Arc::new(interface_name.to_string());
Self::detach_network_inner(&mut *inner, machine_registry_inner, interface)?; let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
inner else {
.interfaces return Err(MachineRegistryError::InvalidName);
.remove(interface) };
.expect("interface must exist");
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
// Update interfaces map
let interfaces = self.fields.interfaces.without(&interface_key);
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces,
..(*self.fields).clone()
});
Ok(()) Ok(())
} }
pub fn release_all_interfaces( pub fn release_all_interfaces(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
) -> MachineRegistryResult<()> { ) -> MachineRegistryResult<()> {
let mut inner = self.inner.lock(); let interface_names: Vec<String> = self
let interfaces: Vec<String> = inner.interfaces.keys().cloned().collect(); .fields
for interface in interfaces { .interfaces
Self::release_all_addresses_inner(&mut *inner, machine_registry_inner, &interface)?; .keys()
.map(|x| (**x).clone())
.collect();
for interface_name in interface_names {
let interface_key = Arc::new(interface_name);
let Some(mut machine_state_interface) =
self.fields.interfaces.get(&interface_key).cloned()
else {
return Err(MachineRegistryError::InvalidName);
};
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
} }
inner.interfaces.clear();
// Update fields
self.fields = Arc::new(MachineStateFields {
interfaces: imbl::HashMap::new(),
..(*self.fields).clone()
});
Ok(()) Ok(())
} }
@ -467,10 +632,10 @@ impl MachineState {
impl State for MachineState { impl State for MachineState {
fn id(&self) -> StateId<Self> { fn id(&self) -> StateId<Self> {
self.unlocked_inner.id.clone() self.immutable.id.clone()
} }
fn name(&self) -> Option<String> { fn name(&self) -> Option<String> {
self.unlocked_inner.opt_name.clone() self.immutable.opt_name.clone()
} }
} }

View File

@ -148,18 +148,11 @@ impl NetworkState {
} }
} }
pub fn with_model( pub fn set_model(&mut self, params: NetworkStateModelParams) {
self, self.fields = Arc::new(NetworkStateFields {
machine_registry_inner: &mut MachineRegistryInner, model: NetworkStateModel { params },
params: NetworkStateModelParams, ..(*self.fields).clone()
) -> Self { });
Self {
fields: Arc::new(NetworkStateFields {
model: NetworkStateModel { params },
..(*self.fields).clone()
}),
..self.clone()
}
} }
pub fn clear_ipv4( pub fn clear_ipv4(
@ -365,10 +358,6 @@ impl NetworkState {
Ok(()) Ok(())
} }
pub fn set_generating_blueprint(&self, generating_blueprint: BlueprintStateId) {
inner.generating_blueprint = Some(generating_blueprint);
}
pub fn is_ipv4(&self) -> bool { pub fn is_ipv4(&self) -> bool {
self.fields.lock().ipv4.is_some() self.fields.lock().ipv4.is_some()
} }
@ -396,7 +385,7 @@ impl NetworkState {
} }
pub fn allocate_address_v4( pub fn allocate_address_v4(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
owner_tag: OwnerTag, owner_tag: OwnerTag,
opt_address: Option<Ipv4Addr>, opt_address: Option<Ipv4Addr>,
@ -447,16 +436,19 @@ impl NetworkState {
Self::can_allocate_net_v4_inner(&*inner, opt_address, prefix) Self::can_allocate_net_v4_inner(&*inner, opt_address, prefix)
} }
pub fn release_address_v4(&self, addr: Ipv4Addr) -> MachineRegistryResult<Option<OwnerTag>> { pub fn release_address_v4(
&mut self,
addr: Ipv4Addr,
) -> MachineRegistryResult<Option<OwnerTag>> {
Self::release_subnet_v4_inner(&mut *inner, Ipv4Net::new(addr, 32).expect("must succeed")) Self::release_subnet_v4_inner(&mut *inner, Ipv4Net::new(addr, 32).expect("must succeed"))
} }
pub fn release_subnet_v4(&self, net: Ipv4Net) -> MachineRegistryResult<Option<OwnerTag>> { pub fn release_subnet_v4(&mut self, net: Ipv4Net) -> MachineRegistryResult<Option<OwnerTag>> {
Self::release_subnet_v4_inner(&mut *inner, net) Self::release_subnet_v4_inner(&mut *inner, net)
} }
pub fn allocate_address_v6( pub fn allocate_address_v6(
&self, &mut self,
machine_registry_inner: &mut MachineRegistryInner, machine_registry_inner: &mut MachineRegistryInner,
owner_tag: OwnerTag, owner_tag: OwnerTag,
opt_address: Option<Ipv6Addr>, opt_address: Option<Ipv6Addr>,

View File

@ -14,6 +14,10 @@ impl<S: State> StateId<S> {
pub fn new(external_id: u64) -> Self { pub fn new(external_id: u64) -> Self {
Self(external_id, PhantomData {}) Self(external_id, PhantomData {})
} }
pub fn external_id(&self) -> u64 {
self.0
}
} }
impl<S: State> Copy for StateId<S> {} impl<S: State> Copy for StateId<S> {}