From f39fbb2ce254c0209a63f5b204665d1d2cadc99c Mon Sep 17 00:00:00 2001 From: "Sijie.Sun" Date: Sun, 8 Jun 2025 11:28:59 +0800 Subject: [PATCH] ipv4-peerid table should use peer with least hop (#958) sometimes route table may not be updated in time, so some dead nodes are still showing in the peer list. when generating ipv4-peer table, we should avoid these dead devices overrides the entry of healthy nodes. --- easytier/src/instance/virtual_nic.rs | 11 +++++----- easytier/src/peers/peer_ospf_route.rs | 29 +++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/easytier/src/instance/virtual_nic.rs b/easytier/src/instance/virtual_nic.rs index 029a6b6..b11342d 100644 --- a/easytier/src/instance/virtual_nic.rs +++ b/easytier/src/instance/virtual_nic.rs @@ -1,4 +1,5 @@ use std::{ + collections::BTreeSet, io, net::Ipv4Addr, pin::Pin, @@ -569,26 +570,26 @@ impl NicCtx { let ifname = nic.ifname().to_owned(); self.tasks.spawn(async move { - let mut cur_proxy_cidrs = vec![]; + let mut cur_proxy_cidrs = BTreeSet::new(); loop { - let mut proxy_cidrs = vec![]; + let mut proxy_cidrs = BTreeSet::new(); let routes = peer_mgr.list_routes().await; for r in routes { for cidr in r.proxy_cidrs { let Ok(cidr) = cidr.parse::() else { continue; }; - proxy_cidrs.push(cidr); + proxy_cidrs.insert(cidr); } } // add vpn portal cidr to proxy_cidrs if let Some(vpn_cfg) = global_ctx.config.get_vpn_portal_config() { - proxy_cidrs.push(vpn_cfg.client_cidr); + proxy_cidrs.insert(vpn_cfg.client_cidr); } if let Some(routes) = global_ctx.config.get_routes() { // if has manual routes, just override entire proxy_cidrs - proxy_cidrs = routes; + proxy_cidrs = routes.into_iter().collect(); } // if route is in cur_proxy_cidrs but not in proxy_cidrs, delete it. diff --git a/easytier/src/peers/peer_ospf_route.rs b/easytier/src/peers/peer_ospf_route.rs index 704ad03..6768b26 100644 --- a/easytier/src/peers/peer_ospf_route.rs +++ b/easytier/src/peers/peer_ospf_route.rs @@ -854,11 +854,36 @@ impl RouteTable { self.peer_infos.insert(*peer_id, info.clone()); + let is_new_peer_better = |old_peer_id: PeerId| -> bool { + let old_next_hop = self.get_next_hop(old_peer_id); + let new_next_hop = item.value(); + old_next_hop.is_none() + || new_next_hop.path_latency < old_next_hop.unwrap().path_latency + }; + if let Some(ipv4_addr) = info.ipv4_addr { - self.ipv4_peer_id_map.insert(ipv4_addr.into(), *peer_id); + self.ipv4_peer_id_map + .entry(ipv4_addr.into()) + .and_modify(|v| { + if *v != *peer_id && is_new_peer_better(*v) { + self.ipv4_peer_id_map.insert(ipv4_addr.into(), *peer_id); + } + }) + .or_insert(*peer_id); } for cidr in info.proxy_cidrs.iter() { + self.cidr_peer_id_map + .entry(cidr.parse().unwrap()) + .and_modify(|v| { + if *v != *peer_id && is_new_peer_better(*v) { + // if the next hop is not set or the new next hop is better, update it. + self.cidr_peer_id_map + .insert(cidr.parse().unwrap(), *peer_id); + } + }) + .or_insert(*peer_id); + self.cidr_peer_id_map .insert(cidr.parse().unwrap(), *peer_id); } @@ -1363,7 +1388,7 @@ impl PeerRouteServiceImpl { .dst_saved_conn_bitmap_version .get(&peer_id) .map(|item| item.get()); - if Some(*local_version) != peer_version { + if peer_version.is_none() || peer_version.unwrap() < *local_version { need_update = true; break; }