Skip to content

Commit

Permalink
🎈 perf: code structure and logic
Browse files Browse the repository at this point in the history
attempt to switch ip when local ip conflicts occur
  • Loading branch information
m1m1sha committed May 17, 2024
1 parent ff14bb4 commit c904a2d
Showing 1 changed file with 40 additions and 44 deletions.
84 changes: 40 additions & 44 deletions easytier/src/instance/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::borrow::BorrowMut;
use std::collections::HashSet;
use std::net::Ipv4Addr;
use std::pin::Pin;
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Weak};

Expand Down Expand Up @@ -290,6 +289,7 @@ impl Instance {

// Warning, if there is an IP conflict in the network when using DHCP, the IP will be automatically changed.
fn check_dhcp_ip_conflict(&self) {
use rand::Rng;
let peer_manager_c = self.peer_manager.clone();
let global_ctx_c = self.get_global_ctx();
let nic_c = self.virtual_nic.as_ref().unwrap().clone();
Expand All @@ -301,7 +301,11 @@ impl Instance {
let mut ipv4_addr: Option<Ipv4Inet> = None;
let mut unique_ipv4 = HashSet::new();

'tries: for i in 0..tries {
for i in 0..tries {
if dhcp_ip.is_none() {
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
}

for route in peer_manager_c.list_routes().await {
if !route.ipv4_addr.is_empty() {
if let Ok(ip) = Ipv4Inet::new(
Expand All @@ -317,83 +321,75 @@ impl Instance {
}
}

if dhcp_ip.is_none() {
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
if i == 5 {
unique_ipv4
.insert(Ipv4Inet::new(default_ipv4_addr, 24).unwrap());
}
if i == 5 && unique_ipv4.is_empty() {
unique_ipv4.insert(Ipv4Inet::new(default_ipv4_addr, 24).unwrap());
}

if let Some(ip) = dhcp_ip {
if !unique_ipv4.contains(&ip) {
ipv4_addr = dhcp_ip;
break;
} else {
unique_ipv4
.insert(Ipv4Inet::new(default_ipv4_addr, 24).unwrap());
}
}

for net in unique_ipv4.iter().map(|inet| inet.network()) {
for net in unique_ipv4.iter().map(|inet| inet.network()).take(1) {
if let Some(ip) = net.iter().find(|ip| {
ip.address() != net.first_address()
&& ip.address() != net.last_address()
&& !unique_ipv4.contains(ip)
}) {
ipv4_addr = Some(ip);
break 'tries;
}
}
}

if dhcp_ip != ipv4_addr {
let last_ip = if let Some(last_ip) = dhcp_ip {
Some(last_ip.address())
} else {
None
};

nic_c.remove_ip(last_ip).await.unwrap();
let last_ip = dhcp_ip.map(|p| p.address());
println!("last_ip: {:?}", last_ip);
let _ = nic_c.remove_ip(last_ip).await;
#[cfg(target_os = "macos")]
if last_ip.is_some() {
let _g = global_ctx_c.net_ns.guard();
let ret = nic_c
.get_ifcfg()
.remove_ipv4_route(nic_c.ifname(), last_ip.unwrap(), 24)
.await;

if ret.is_err() {
tracing::trace!(
cidr = 24,
err = ?ret,
"remove route failed.",
);
}
}

if let Some(ip) = ipv4_addr {
global_ctx_c.set_ipv4(Some(ip.address()));
nic_c.link_up().await.unwrap();
nic_c.add_ip(ip.address(), 24).await.unwrap();
let _ = nic_c.link_up().await;
dhcp_ip = Some(ip);
tries = 1;
if nic_c.add_ip(ip.address(), 24).await.is_err() {
global_ctx_c.set_ipv4(None);
let sleep: u64 = rand::thread_rng().gen_range(200..500);
tokio::time::sleep(std::time::Duration::from_millis(sleep)).await;
continue;
}
#[cfg(target_os = "macos")]
nic_c.add_route(ip.address(), 24).await.unwrap();
let _ = nic_c.add_route(ip.address(), 24).await;
global_ctx_c.set_ipv4(Some(ip.address()));
global_ctx_c.issue_event(GlobalCtxEvent::DhcpIpv4Changed(
last_ip,
Some(ip.address()),
));
dhcp_ip = Some(ip);
tries = 1;
} else {
#[cfg(target_os = "macos")]
if last_ip.is_some() {
let _g = global_ctx_c.net_ns.guard();
let ret = nic_c
.get_ifcfg()
.remove_ipv4_route(nic_c.ifname(), last_ip.unwrap(), 24)
.await;

if ret.is_err() {
tracing::trace!(
cidr = 24,
err = ?ret,
"remove route failed.",
);
}
}
global_ctx_c.set_ipv4(None);
global_ctx_c.issue_event(GlobalCtxEvent::DhcpIpv4Conflicted(last_ip));
dhcp_ip = None;
tries = 6;
}
}

use rand::Rng;
let sleep: u64 = rand::thread_rng().gen_range(10..20);
let sleep: u64 = rand::thread_rng().gen_range(5..10);

// check every 10 ~ 20 seconds
tokio::time::sleep(std::time::Duration::from_secs(sleep)).await;
Expand Down

0 comments on commit c904a2d

Please sign in to comment.