mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-09-03 17:45:44 +00:00
refactor: add shared virtual nic registry
Add a small registry keyed by dev_name so shared-mode setup can reuse one SharedVirtualNic per device name. Track invalid shared NICs through a shared flag and replace them on the next get_or_create call.
This commit is contained in:
@@ -2,6 +2,7 @@ use std::{
|
|||||||
collections::{BTreeMap, BTreeSet},
|
collections::{BTreeMap, BTreeSet},
|
||||||
net::{Ipv4Addr, Ipv6Addr},
|
net::{Ipv4Addr, Ipv6Addr},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use cidr::{Ipv4Inet, Ipv6Inet};
|
use cidr::{Ipv4Inet, Ipv6Inet};
|
||||||
@@ -232,6 +233,7 @@ impl SharedIfConfig {
|
|||||||
pub struct SharedVirtualNic {
|
pub struct SharedVirtualNic {
|
||||||
nic: Arc<Mutex<VirtualNic>>,
|
nic: Arc<Mutex<VirtualNic>>,
|
||||||
ifcfg: SharedIfConfig,
|
ifcfg: SharedIfConfig,
|
||||||
|
valid: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedVirtualNic {
|
impl SharedVirtualNic {
|
||||||
@@ -239,9 +241,18 @@ impl SharedVirtualNic {
|
|||||||
Self {
|
Self {
|
||||||
nic: Arc::new(Mutex::new(VirtualNic::new(config))),
|
nic: Arc::new(Mutex::new(VirtualNic::new(config))),
|
||||||
ifcfg: SharedIfConfig::default(),
|
ifcfg: SharedIfConfig::default(),
|
||||||
|
valid: Arc::new(AtomicBool::new(true)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mark_invalid(&self) {
|
||||||
|
self.valid.store(false, Ordering::Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_valid(&self) -> bool {
|
||||||
|
self.valid.load(Ordering::Acquire)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ifcfg(&self) -> &SharedIfConfig {
|
pub fn ifcfg(&self) -> &SharedIfConfig {
|
||||||
&self.ifcfg
|
&self.ifcfg
|
||||||
}
|
}
|
||||||
@@ -253,6 +264,65 @@ impl SharedVirtualNic {
|
|||||||
pub fn nic(&self) -> Arc<Mutex<VirtualNic>> {
|
pub fn nic(&self) -> Arc<Mutex<VirtualNic>> {
|
||||||
self.nic.clone()
|
self.nic.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn valid_flag(&self) -> Arc<AtomicBool> {
|
||||||
|
self.valid.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct SharedVirtualNicRegistry {
|
||||||
|
nics: BTreeMap<String, SharedVirtualNicRegistryEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SharedVirtualNicRegistryEntry {
|
||||||
|
nic: Arc<Mutex<SharedVirtualNic>>,
|
||||||
|
valid: Arc<AtomicBool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SharedVirtualNicRegistryEntry {
|
||||||
|
fn new(nic: SharedVirtualNic) -> Self {
|
||||||
|
Self {
|
||||||
|
valid: nic.valid_flag(),
|
||||||
|
nic: Arc::new(Mutex::new(nic)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid(&self) -> bool {
|
||||||
|
self.valid.load(Ordering::Acquire)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nic(&self) -> Arc<Mutex<SharedVirtualNic>> {
|
||||||
|
self.nic.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SharedVirtualNicRegistry {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, dev_name: &str) -> Option<Arc<Mutex<SharedVirtualNic>>> {
|
||||||
|
self.nics
|
||||||
|
.get(dev_name)
|
||||||
|
.filter(|entry| entry.is_valid())
|
||||||
|
.map(|entry| entry.nic())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_create(
|
||||||
|
&mut self,
|
||||||
|
dev_name: String,
|
||||||
|
config: VirtualNicConfig,
|
||||||
|
) -> Arc<Mutex<SharedVirtualNic>> {
|
||||||
|
if let Some(nic) = self.get(&dev_name) {
|
||||||
|
return nic;
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry = SharedVirtualNicRegistryEntry::new(SharedVirtualNic::new(config));
|
||||||
|
let nic = entry.nic();
|
||||||
|
self.nics.insert(dev_name, entry);
|
||||||
|
nic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_owned_items<T>(
|
fn update_owned_items<T>(
|
||||||
@@ -485,4 +555,40 @@ mod tests {
|
|||||||
);
|
);
|
||||||
drop(shared_nic.nic());
|
drop(shared_nic.nic());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn registry_reuses_shared_virtual_nic_for_same_dev_name() {
|
||||||
|
let mut registry = SharedVirtualNicRegistry::new();
|
||||||
|
|
||||||
|
let first = registry.get_or_create("et0".to_string(), virtual_nic_config());
|
||||||
|
let second = registry.get_or_create("et0".to_string(), virtual_nic_config());
|
||||||
|
|
||||||
|
assert!(Arc::ptr_eq(&first, &second));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn registry_keeps_different_dev_names_separate() {
|
||||||
|
let mut registry = SharedVirtualNicRegistry::new();
|
||||||
|
|
||||||
|
let first = registry.get_or_create("et0".to_string(), virtual_nic_config());
|
||||||
|
let second = registry.get_or_create("et1".to_string(), virtual_nic_config());
|
||||||
|
|
||||||
|
assert!(!Arc::ptr_eq(&first, &second));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn registry_replaces_invalid_shared_virtual_nic() {
|
||||||
|
let mut registry = SharedVirtualNicRegistry::new();
|
||||||
|
|
||||||
|
let first = registry.get_or_create("et0".to_string(), virtual_nic_config());
|
||||||
|
first.try_lock().unwrap().mark_invalid();
|
||||||
|
let second = registry.get_or_create("et0".to_string(), virtual_nic_config());
|
||||||
|
|
||||||
|
assert!(!Arc::ptr_eq(&first, &second));
|
||||||
|
assert!(
|
||||||
|
registry
|
||||||
|
.get("et0")
|
||||||
|
.is_some_and(|nic| Arc::ptr_eq(&nic, &second))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user