Add flap dampening to parent selection

Track parent switch frequency in a sliding window. When switches exceed
a configurable threshold (default 4 in 60s), impose an extended hold-down
period (default 120s) that prevents non-mandatory parent changes.

Mandatory switches (parent loss, root change, shouldn't-be-root) bypass
dampening. The flap counter resets when the window expires naturally.

Implements TASK-2026-0030 / IDEA-0013.
This commit is contained in:
Johnathan Corgan
2026-02-23 20:00:58 +00:00
parent 5d72e7cee1
commit 94c0e19951
5 changed files with 340 additions and 4 deletions
+8 -2
View File
@@ -207,7 +207,7 @@ impl Node {
.map(|d| d.as_secs())
.unwrap_or(0);
self.tree_state.set_parent(new_parent, new_seq, timestamp);
let flap_dampened = self.tree_state.set_parent(new_parent, new_seq, timestamp);
if let Err(e) = self.tree_state.sign_declaration(&self.identity) {
warn!(error = %e, "Failed to sign declaration after parent switch");
return;
@@ -222,6 +222,9 @@ impl Node {
depth = self.tree_state.my_coords().depth(),
"Parent switched, flushed coord cache, announcing to all peers"
);
if flap_dampened {
warn!("Flap dampening engaged: excessive parent switches detected");
}
self.send_tree_announce_to_all().await;
@@ -318,7 +321,7 @@ impl Node {
.map(|d| d.as_secs())
.unwrap_or(0);
self.tree_state.set_parent(new_parent, new_seq, timestamp);
let flap_dampened = self.tree_state.set_parent(new_parent, new_seq, timestamp);
if let Err(e) = self.tree_state.sign_declaration(&self.identity) {
warn!(error = %e, "Failed to sign declaration after periodic parent re-eval");
return;
@@ -334,6 +337,9 @@ impl Node {
trigger = "periodic",
"Parent switched via periodic cost re-evaluation"
);
if flap_dampened {
warn!("Flap dampening engaged: excessive parent switches detected");
}
self.send_tree_announce_to_all().await;