mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-06 17:59:11 +00:00
fix: reconcile webhook-managed configs and make disable_p2p more intelligent (#2057)
* reconcile infra configs on webhook validate * make disable_p2p more intelligent * fix stats
This commit is contained in:
@@ -244,6 +244,7 @@ impl GlobalCtx {
|
||||
feature_flags.quic_input = !flags.disable_quic_input;
|
||||
feature_flags.no_relay_quic = flags.disable_relay_quic;
|
||||
feature_flags.need_p2p = flags.need_p2p;
|
||||
feature_flags.disable_p2p = flags.disable_p2p;
|
||||
feature_flags
|
||||
}
|
||||
|
||||
@@ -743,12 +744,13 @@ pub mod tests {
|
||||
feature_flags.is_public_server = true;
|
||||
global_ctx.set_feature_flags(feature_flags);
|
||||
|
||||
let mut flags = global_ctx.get_flags();
|
||||
let mut flags = global_ctx.get_flags().clone();
|
||||
flags.disable_kcp_input = true;
|
||||
flags.disable_relay_kcp = true;
|
||||
flags.disable_quic_input = true;
|
||||
flags.disable_relay_quic = true;
|
||||
flags.need_p2p = true;
|
||||
flags.disable_p2p = true;
|
||||
global_ctx.set_flags(flags);
|
||||
|
||||
let feature_flags = global_ctx.get_feature_flags();
|
||||
@@ -757,6 +759,7 @@ pub mod tests {
|
||||
assert!(!feature_flags.quic_input);
|
||||
assert!(feature_flags.no_relay_quic);
|
||||
assert!(feature_flags.need_p2p);
|
||||
assert!(feature_flags.disable_p2p);
|
||||
assert!(feature_flags.support_conn_list_sync);
|
||||
assert!(feature_flags.avoid_relay_data);
|
||||
assert!(feature_flags.is_public_server);
|
||||
|
||||
@@ -581,9 +581,9 @@ impl StatsManager {
|
||||
break;
|
||||
};
|
||||
|
||||
// Remove entries that haven't been updated for 3 minutes
|
||||
counters.retain(|_, metric_data: &mut Arc<MetricData>| unsafe {
|
||||
metric_data.get_last_updated() > cutoff_time
|
||||
counters.retain(|_, metric_data: &mut Arc<MetricData>| {
|
||||
Arc::strong_count(metric_data) > 1
|
||||
|| unsafe { metric_data.get_last_updated() > cutoff_time }
|
||||
});
|
||||
counters.shrink_to_fit();
|
||||
}
|
||||
@@ -900,6 +900,33 @@ mod tests {
|
||||
assert_eq!(counter2.get(), 25);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_cleanup_keeps_metrics_with_live_handles() {
|
||||
let stats = StatsManager::new();
|
||||
let counter = stats.get_simple_counter(MetricName::TrafficBytesForwarded);
|
||||
counter.set(1);
|
||||
|
||||
let cutoff_time = Instant::now().checked_add(Duration::from_secs(1)).unwrap();
|
||||
stats
|
||||
.counters
|
||||
.retain(|_, metric_data: &mut Arc<MetricData>| {
|
||||
Arc::strong_count(metric_data) > 1
|
||||
|| unsafe { metric_data.get_last_updated() > cutoff_time }
|
||||
});
|
||||
|
||||
assert_eq!(stats.metric_count(), 1);
|
||||
assert_eq!(stats.get_all_metrics().len(), 1);
|
||||
|
||||
drop(counter);
|
||||
stats
|
||||
.counters
|
||||
.retain(|_, metric_data: &mut Arc<MetricData>| {
|
||||
Arc::strong_count(metric_data) > 1
|
||||
|| unsafe { metric_data.get_last_updated() > cutoff_time }
|
||||
});
|
||||
assert_eq!(stats.metric_count(), 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_stats_rpc_data_structures() {
|
||||
// Test GetStatsRequest
|
||||
|
||||
@@ -62,7 +62,8 @@ impl PeerManagerForDirectConnector for PeerManager {
|
||||
async fn list_peers(&self) -> Vec<PeerId> {
|
||||
let mut ret = vec![];
|
||||
let allow_public_server = use_global_var!(DIRECT_CONNECT_TO_PUBLIC_SERVER);
|
||||
let lazy_p2p = self.get_global_ctx().get_flags().lazy_p2p;
|
||||
let flags = self.get_global_ctx().get_flags();
|
||||
let lazy_p2p = flags.lazy_p2p;
|
||||
let now = Instant::now();
|
||||
|
||||
let routes = self.list_routes().await;
|
||||
@@ -71,10 +72,15 @@ impl PeerManagerForDirectConnector for PeerManager {
|
||||
route.feature_flag.as_ref(),
|
||||
allow_public_server,
|
||||
lazy_p2p,
|
||||
flags.disable_p2p,
|
||||
flags.need_p2p,
|
||||
);
|
||||
let dynamic_allowed =
|
||||
should_try_p2p_with_peer(route.feature_flag.as_ref(), allow_public_server)
|
||||
&& self.has_recent_traffic(route.peer_id, now);
|
||||
let dynamic_allowed = should_try_p2p_with_peer(
|
||||
route.feature_flag.as_ref(),
|
||||
allow_public_server,
|
||||
flags.disable_p2p,
|
||||
flags.need_p2p,
|
||||
) && self.has_recent_traffic(route.peer_id, now);
|
||||
if static_allowed || dynamic_allowed {
|
||||
ret.push(route.peer_id);
|
||||
}
|
||||
@@ -650,10 +656,6 @@ impl DirectConnectorManager {
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
if self.global_ctx.get_flags().disable_p2p {
|
||||
return;
|
||||
}
|
||||
|
||||
self.run_as_server();
|
||||
self.run_as_client();
|
||||
}
|
||||
|
||||
@@ -26,19 +26,31 @@ pub mod http_connector;
|
||||
pub(crate) fn should_try_p2p_with_peer(
|
||||
feature_flag: Option<&PeerFeatureFlag>,
|
||||
allow_public_server: bool,
|
||||
local_disable_p2p: bool,
|
||||
local_need_p2p: bool,
|
||||
) -> bool {
|
||||
feature_flag
|
||||
.map(|flag| allow_public_server || !flag.is_public_server)
|
||||
.unwrap_or(true)
|
||||
.map(|flag| {
|
||||
(allow_public_server || !flag.is_public_server)
|
||||
&& (!local_disable_p2p || flag.need_p2p)
|
||||
&& (!flag.disable_p2p || local_need_p2p)
|
||||
})
|
||||
.unwrap_or(!local_disable_p2p)
|
||||
}
|
||||
|
||||
pub(crate) fn should_background_p2p_with_peer(
|
||||
feature_flag: Option<&PeerFeatureFlag>,
|
||||
allow_public_server: bool,
|
||||
lazy_p2p: bool,
|
||||
local_disable_p2p: bool,
|
||||
local_need_p2p: bool,
|
||||
) -> bool {
|
||||
should_try_p2p_with_peer(feature_flag, allow_public_server)
|
||||
&& (!lazy_p2p || feature_flag.map(|flag| flag.need_p2p).unwrap_or(false))
|
||||
should_try_p2p_with_peer(
|
||||
feature_flag,
|
||||
allow_public_server,
|
||||
local_disable_p2p,
|
||||
local_need_p2p,
|
||||
) && (!lazy_p2p || feature_flag.map(|flag| flag.need_p2p).unwrap_or(false))
|
||||
}
|
||||
|
||||
async fn set_bind_addr_for_peer_connector(
|
||||
@@ -162,17 +174,23 @@ mod tests {
|
||||
assert!(should_background_p2p_with_peer(
|
||||
Some(&no_need_p2p),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(!should_background_p2p_with_peer(
|
||||
Some(&no_need_p2p),
|
||||
false,
|
||||
true
|
||||
true,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(should_background_p2p_with_peer(
|
||||
Some(&need_p2p),
|
||||
false,
|
||||
true
|
||||
true,
|
||||
false,
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
@@ -183,16 +201,93 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert!(!should_try_p2p_with_peer(Some(&public_server), false));
|
||||
assert!(should_try_p2p_with_peer(Some(&public_server), true));
|
||||
assert!(!should_try_p2p_with_peer(
|
||||
Some(&public_server),
|
||||
false,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(should_try_p2p_with_peer(
|
||||
Some(&public_server),
|
||||
true,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(!should_background_p2p_with_peer(
|
||||
Some(&public_server),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(should_background_p2p_with_peer(
|
||||
Some(&public_server),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disable_p2p_only_allows_need_p2p_exceptions() {
|
||||
let normal_peer = PeerFeatureFlag::default();
|
||||
let need_peer = PeerFeatureFlag {
|
||||
need_p2p: true,
|
||||
..Default::default()
|
||||
};
|
||||
let disable_peer = PeerFeatureFlag {
|
||||
disable_p2p: true,
|
||||
..Default::default()
|
||||
};
|
||||
let disable_need_peer = PeerFeatureFlag {
|
||||
disable_p2p: true,
|
||||
need_p2p: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert!(should_try_p2p_with_peer(
|
||||
Some(&normal_peer),
|
||||
false,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(should_try_p2p_with_peer(None, false, false, false));
|
||||
assert!(!should_try_p2p_with_peer(None, false, true, false));
|
||||
assert!(!should_try_p2p_with_peer(
|
||||
Some(&normal_peer),
|
||||
false,
|
||||
true,
|
||||
false
|
||||
));
|
||||
assert!(should_try_p2p_with_peer(
|
||||
Some(&need_peer),
|
||||
false,
|
||||
true,
|
||||
false
|
||||
));
|
||||
assert!(!should_try_p2p_with_peer(
|
||||
Some(&disable_peer),
|
||||
false,
|
||||
false,
|
||||
false
|
||||
));
|
||||
assert!(should_try_p2p_with_peer(
|
||||
Some(&disable_peer),
|
||||
false,
|
||||
false,
|
||||
true
|
||||
));
|
||||
assert!(should_try_p2p_with_peer(
|
||||
Some(&disable_need_peer),
|
||||
false,
|
||||
true,
|
||||
true
|
||||
));
|
||||
assert!(!should_try_p2p_with_peer(
|
||||
Some(&disable_need_peer),
|
||||
false,
|
||||
true,
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
@@ -420,7 +420,8 @@ impl PeerTaskLauncher for TcpHolePunchPeerTaskLauncher {
|
||||
#[tracing::instrument(skip(self, data))]
|
||||
async fn collect_peers_need_task(&self, data: &Self::Data) -> Vec<Self::CollectPeerItem> {
|
||||
let global_ctx = data.peer_mgr.get_global_ctx();
|
||||
let lazy_p2p = global_ctx.get_flags().lazy_p2p;
|
||||
let flags = global_ctx.get_flags();
|
||||
let lazy_p2p = flags.lazy_p2p;
|
||||
let my_tcp_nat_type = NatType::try_from(
|
||||
global_ctx
|
||||
.get_stun_info_collector()
|
||||
@@ -443,10 +444,19 @@ impl PeerTaskLauncher for TcpHolePunchPeerTaskLauncher {
|
||||
|
||||
let mut peers_to_connect = Vec::new();
|
||||
for route in data.peer_mgr.list_routes().await.iter() {
|
||||
let static_allowed =
|
||||
should_background_p2p_with_peer(route.feature_flag.as_ref(), false, lazy_p2p);
|
||||
let dynamic_allowed = should_try_p2p_with_peer(route.feature_flag.as_ref(), false)
|
||||
&& data.peer_mgr.has_recent_traffic(route.peer_id, now);
|
||||
let static_allowed = should_background_p2p_with_peer(
|
||||
route.feature_flag.as_ref(),
|
||||
false,
|
||||
lazy_p2p,
|
||||
flags.disable_p2p,
|
||||
flags.need_p2p,
|
||||
);
|
||||
let dynamic_allowed = should_try_p2p_with_peer(
|
||||
route.feature_flag.as_ref(),
|
||||
false,
|
||||
flags.disable_p2p,
|
||||
flags.need_p2p,
|
||||
) && data.peer_mgr.has_recent_traffic(route.peer_id, now);
|
||||
if !static_allowed && !dynamic_allowed {
|
||||
continue;
|
||||
}
|
||||
@@ -554,10 +564,9 @@ impl TcpHolePunchConnector {
|
||||
|
||||
pub async fn run(&mut self) -> Result<(), Error> {
|
||||
let flags = self.peer_mgr.get_global_ctx().get_flags();
|
||||
if flags.disable_p2p || flags.disable_tcp_hole_punching {
|
||||
if flags.disable_tcp_hole_punching {
|
||||
tracing::debug!(
|
||||
"tcp hole punch disabled by disable_p2p(={}) or disable_tcp_hole_punching(={});",
|
||||
flags.disable_p2p,
|
||||
"tcp hole punch disabled by disable_tcp_hole_punching(={});",
|
||||
flags.disable_tcp_hole_punching
|
||||
);
|
||||
return Ok(());
|
||||
|
||||
@@ -428,7 +428,8 @@ impl PeerTaskLauncher for UdpHolePunchPeerTaskLauncher {
|
||||
}
|
||||
|
||||
let my_peer_id = data.peer_mgr.my_peer_id();
|
||||
let lazy_p2p = data.peer_mgr.get_global_ctx().get_flags().lazy_p2p;
|
||||
let flags = data.peer_mgr.get_global_ctx().get_flags();
|
||||
let lazy_p2p = flags.lazy_p2p;
|
||||
let now = Instant::now();
|
||||
|
||||
data.blacklist.cleanup();
|
||||
@@ -438,10 +439,19 @@ impl PeerTaskLauncher for UdpHolePunchPeerTaskLauncher {
|
||||
// 2. peers is full cone (any restricted type);
|
||||
// 3. peers not in blacklist;
|
||||
for route in data.peer_mgr.list_routes().await.iter() {
|
||||
let static_allowed =
|
||||
should_background_p2p_with_peer(route.feature_flag.as_ref(), false, lazy_p2p);
|
||||
let dynamic_allowed = should_try_p2p_with_peer(route.feature_flag.as_ref(), false)
|
||||
&& data.peer_mgr.has_recent_traffic(route.peer_id, now);
|
||||
let static_allowed = should_background_p2p_with_peer(
|
||||
route.feature_flag.as_ref(),
|
||||
false,
|
||||
lazy_p2p,
|
||||
flags.disable_p2p,
|
||||
flags.need_p2p,
|
||||
);
|
||||
let dynamic_allowed = should_try_p2p_with_peer(
|
||||
route.feature_flag.as_ref(),
|
||||
false,
|
||||
flags.disable_p2p,
|
||||
flags.need_p2p,
|
||||
) && data.peer_mgr.has_recent_traffic(route.peer_id, now);
|
||||
if !static_allowed && !dynamic_allowed {
|
||||
continue;
|
||||
}
|
||||
@@ -565,9 +575,6 @@ impl UdpHolePunchConnector {
|
||||
pub async fn run(&mut self) -> Result<(), Error> {
|
||||
let global_ctx = self.peer_mgr.get_global_ctx();
|
||||
|
||||
if global_ctx.get_flags().disable_p2p {
|
||||
return Ok(());
|
||||
}
|
||||
if global_ctx.get_flags().disable_udp_hole_punching {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -222,6 +222,7 @@ message PeerFeatureFlag {
|
||||
bool no_relay_quic = 7;
|
||||
bool is_credential_peer = 8;
|
||||
bool need_p2p = 9;
|
||||
bool disable_p2p = 10;
|
||||
}
|
||||
|
||||
enum SocketType {
|
||||
|
||||
@@ -2565,6 +2565,73 @@ pub async fn need_p2p_overrides_lazy_p2p() {
|
||||
drop_insts(insts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn disable_p2p_still_connects_to_need_p2p_peers() {
|
||||
let insts = init_lazy_p2p_three_node_ex("udp", |cfg| {
|
||||
let mut flags = cfg.get_flags();
|
||||
if cfg.get_inst_name() == "inst1" {
|
||||
flags.disable_p2p = true;
|
||||
}
|
||||
if cfg.get_inst_name() == "inst3" {
|
||||
flags.need_p2p = true;
|
||||
}
|
||||
cfg.set_flags(flags);
|
||||
cfg
|
||||
})
|
||||
.await;
|
||||
|
||||
let inst3_peer_id = insts[2].peer_id();
|
||||
wait_route_cost(&insts[0], inst3_peer_id, 2, Duration::from_secs(5)).await;
|
||||
wait_for_condition(
|
||||
|| async {
|
||||
insts[0]
|
||||
.get_peer_manager()
|
||||
.get_peer_map()
|
||||
.has_peer(inst3_peer_id)
|
||||
},
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.await;
|
||||
wait_route_cost(&insts[0], inst3_peer_id, 1, Duration::from_secs(10)).await;
|
||||
|
||||
drop_insts(insts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn ordinary_nodes_do_not_proactively_connect_to_disable_p2p_peers() {
|
||||
let insts = init_lazy_p2p_three_node_ex("udp", |cfg| {
|
||||
if cfg.get_inst_name() == "inst3" {
|
||||
let mut flags = cfg.get_flags();
|
||||
flags.disable_p2p = true;
|
||||
cfg.set_flags(flags);
|
||||
}
|
||||
cfg
|
||||
})
|
||||
.await;
|
||||
|
||||
let inst3_peer_id = insts[2].peer_id();
|
||||
wait_route_cost(&insts[0], inst3_peer_id, 2, Duration::from_secs(5)).await;
|
||||
assert!(
|
||||
ping_test("net_a", "10.144.144.3", None).await,
|
||||
"relay traffic to disable-p2p peers should still succeed"
|
||||
);
|
||||
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
assert!(
|
||||
!insts[0]
|
||||
.get_peer_manager()
|
||||
.get_peer_map()
|
||||
.has_peer(inst3_peer_id),
|
||||
"ordinary nodes should not proactively establish p2p with disable-p2p peers"
|
||||
);
|
||||
wait_route_cost(&insts[0], inst3_peer_id, 2, Duration::from_secs(3)).await;
|
||||
|
||||
drop_insts(insts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
pub async fn lazy_p2p_warms_up_before_p2p_only_send() {
|
||||
|
||||
Reference in New Issue
Block a user