Commit a07d1f23 authored by nanamicat's avatar nanamicat

delay

parent 43872183
Pipeline #42420 passed with stages
in 53 seconds
...@@ -66,6 +66,7 @@ async fn main() -> Result<()> { ...@@ -66,6 +66,7 @@ async fn main() -> Result<()> {
let socket = UdpSocket::bind(config.udp_bind).await?; let socket = UdpSocket::bind(config.udp_bind).await?;
println!("UDP listening on {}", config.udp_bind); println!("UDP listening on {}", config.udp_bind);
let mut buf = [0u8; u16::MAX as usize]; // Max UDP size let mut buf = [0u8; u16::MAX as usize]; // Max UDP size
let start = Instant::now();
loop { loop {
let (len, addr) = socket.recv_from(&mut buf).await?; let (len, addr) = socket.recv_from(&mut buf).await?;
...@@ -81,14 +82,15 @@ async fn main() -> Result<()> { ...@@ -81,14 +82,15 @@ async fn main() -> Result<()> {
if updating.router_id != 0 && !routers.get(&updating.router_id).context("router not found")?.is_online() { if updating.router_id != 0 && !routers.get(&updating.router_id).context("router not found")?.is_online() {
updating.router_id = 0; updating.router_id = 0;
} }
tracing::info!("recv {:?}", uplink); tracing::debug!("recv {:?}", uplink);
// 处理收到的消息 // 处理收到的消息
if let Some(router) = routers.get_mut(&uplink.id) if let Some(router) = routers.get_mut(&uplink.id)
&& let Some(downlink) = router.on_message(&mut uplink, addr, &mut updating, now) && let Some(downlink) = router.on_message(&mut uplink, addr, &mut updating, now)
{ {
tracing::info!("sync to {}: {:?}", router.id, downlink); tracing::debug!("sync to {}: {:?}", router.id, downlink);
send(&downlink, &mut buf, &socket, &addr).await?; send(&downlink, &mut buf, &socket, &addr).await?;
} else if updating.router_id == 0 } else if updating.router_id == 0
&& now.duration_since(start) >= TIMEOUT // 刚启动时静默,先学习
&& let Some(router) = routers.get(&uplink.id) && let Some(router) = routers.get(&uplink.id)
&& let Some(downlink) = router.update(&routers, &connections) && let Some(downlink) = router.update(&routers, &connections)
{ {
......
...@@ -10,13 +10,6 @@ pub struct Quality { ...@@ -10,13 +10,6 @@ pub struct Quality {
} }
impl Quality { impl Quality {
pub const UNREACHABLE: Quality = Quality {
delay: 0,
jitter: 0,
reliability: 0.0,
cost: 0,
};
pub fn concat(&mut self, next: &PeerQuality, cost: u32) { pub fn concat(&mut self, next: &PeerQuality, cost: u32) {
self.delay += next.delay as i32; self.delay += next.delay as i32;
self.jitter += next.jitter as u32; self.jitter += next.jitter as u32;
...@@ -33,8 +26,10 @@ impl Quality { ...@@ -33,8 +26,10 @@ impl Quality {
self.delay + ((1.0 - self.reliability) * 10000.0).round() as i32 + self.cost as i32 self.delay + ((1.0 - self.reliability) * 10000.0).round() as i32 + self.cost as i32
} }
} }
}
pub(crate) fn default() -> Self { impl Default for Quality {
fn default() -> Self {
Self { Self {
delay: 0, delay: 0,
jitter: 0, jitter: 0,
......
...@@ -97,6 +97,7 @@ impl Router { ...@@ -97,6 +97,7 @@ impl Router {
self.via.append(&mut uplink.via); self.via.append(&mut uplink.via);
self.plan.append(&mut uplink.plan); self.plan.append(&mut uplink.plan);
self.online(addr, now); self.online(addr, now);
tracing::info!("router {} full via={:?}", self.id, self.via);
} }
None None
} }
...@@ -136,18 +137,23 @@ impl Router { ...@@ -136,18 +137,23 @@ impl Router {
for to in routers.values().filter(|&r| r != self) { for to in routers.values().filter(|&r| r != self) {
let current_router = routers.get(self.via.get(&to.id).unwrap()).unwrap(); let current_router = routers.get(self.via.get(&to.id).unwrap()).unwrap();
let current_metric = self.route_quality(to, current_router, routers, connections).metric(); let current_metric = self.route_quality(to, current_router, routers, connections).map_or(i32::MAX, |r| r.metric());
let candidate: Vec<(&Router, i32)> = connections[&self.id] let candidate: Vec<(&Router, i32)> = connections[&self.id]
.keys() .keys()
.map(|id| routers.get(id).unwrap()) .map(|id| routers.get(id).unwrap())
.map(|r| (r, self.route_quality(to, r, routers, connections).metric())) .filter_map(|r| self.route_quality(to, r, routers, connections).map(|q| (r, q.metric())))
.collect(); .collect();
let (best_router, best_metric) = candidate.iter().min_by_key(|(_, m)| m).unwrap();
let best_router = if *best_metric == i32::MAX { to } else { best_router }; match candidate.iter().min_by_key(|(_, m)| m) {
// 无论如何都不可达就标记为直连 None if current_router != to => {
if current_router != best_router && (*best_metric == i32::MAX || *best_metric + THROTTLE < current_metric) { // 无论如何都不可达就标记为直连
changed_via.insert(to.id, best_router.id); changed_via.insert(to.id, to.id);
}
Some((best_router, best_metric)) if current_router != *best_router && (*best_metric + THROTTLE < current_metric) => {
changed_via.insert(to.id, best_router.id);
}
_ => {}
} }
} }
...@@ -164,34 +170,23 @@ impl Router { ...@@ -164,34 +170,23 @@ impl Router {
} }
} }
pub fn route_quality(&self, to: &Router, via: &Router, routers: &BTreeMap<u8, Router>, connections: &BTreeMap<u8, BTreeMap<u8, ConnectionData>>) -> Quality { pub fn route_quality(&self, to: &Router, via: &Router, routers: &BTreeMap<u8, Router>, connections: &BTreeMap<u8, BTreeMap<u8, ConnectionData>>) -> Option<Quality> {
assert!(self != to); assert!(self != to);
assert!(self != via); assert!(self != via);
let mut result: Quality = Quality::default(); let mut result: Quality = Default::default();
let mut route = vec![self, via]; let mut route = vec![self];
let mut current = self; let mut current = self;
let mut next = via; while current != to {
loop { let next = if current == self { via } else { &routers[&current.via[&to.id]] };
if !next.is_online() { match next.peers.get(&current.id).filter(|_| next.is_online() && !route.contains(&next)) {
return Quality::UNREACHABLE; None => return None,
} Some(quality) if quality.reliability == 0 => return None,
// 不通的情况 via 会标记为直连,实际不可达
match next.peers.get(&current.id) {
None => return Quality::UNREACHABLE,
Some(quality) => result.concat(quality, connections[&current.id][&next.id].metric), Some(quality) => result.concat(quality, connections[&current.id][&next.id].metric),
} }
// Next hop
current = next;
next = &routers[&current.via[&to.id]];
// 检查环路
if route.contains(&next) {
return Quality::UNREACHABLE;
}
route.push(next); route.push(next);
current = next;
} }
Some(result)
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment