From 02b1892cc583a554cb1a63f9db15790d17b3a092 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 7 Mar 2019 21:36:12 -0600 Subject: [PATCH] try to switch parents if a parent link is blocked --- src/yggdrasil/link.go | 1 + src/yggdrasil/switch.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/yggdrasil/link.go b/src/yggdrasil/link.go index 6fc7687b..253e077f 100644 --- a/src/yggdrasil/link.go +++ b/src/yggdrasil/link.go @@ -309,6 +309,7 @@ func (intf *linkInterface) handler() error { case <-recvTimer.C: // We haven't received anything, so assume there's a problem and don't return this node to the switch until they start responding isAlive = false + intf.link.core.switchTable.blockPeer(intf.peer.port) case <-closeTimer.C: // We haven't received anything in a really long time, so things have died at the switch level and then some... // Just close the connection at this point... diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index bf6b9194..1576ef53 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -131,6 +131,7 @@ type peerInfo struct { faster map[switchPort]uint64 // Counter of how often a node is faster than the current parent, penalized extra if slower port switchPort // Interface number of this peer msg switchMsg // The wire switchMsg used + blocked bool // True if the link is blocked, used to avoid parenting a blocked link } // This is just a uint64 with a named type for clarity reasons. @@ -256,6 +257,29 @@ func (t *switchTable) cleanRoot() { } } +// Blocks and, if possible, unparents a peer +func (t *switchTable) blockPeer(port switchPort) { + t.mutex.Lock() + defer t.mutex.Unlock() + peer, isIn := t.data.peers[port] + if !isIn { + return + } + peer.blocked = true + t.data.peers[port] = peer + if port != t.parent { + return + } + t.parent = 0 + for _, info := range t.data.peers { + if info.port == port { + continue + } + t.unlockedHandleMsg(&info.msg, info.port, true) + } + t.unlockedHandleMsg(&peer.msg, peer.port, true) +} + // Removes a peer. // Must be called by the router mainLoop goroutine, e.g. call router.doAdmin with a lambda that calls this. // If the removed peer was this node's parent, it immediately tries to find a new parent. @@ -395,6 +419,7 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort, rep if reprocessing { sender.faster = oldSender.faster sender.time = oldSender.time + sender.blocked = oldSender.blocked } else { sender.faster = make(map[switchPort]uint64, len(oldSender.faster)) for port, peer := range t.data.peers { @@ -454,6 +479,11 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort, rep case sender.faster[t.parent] >= switch_faster_threshold: // The is reliably faster than the current parent. updateRoot = true + case !sender.blocked && oldParent.blocked: + // Replace a blocked parent + updateRoot = true + case reprocessing && sender.blocked && !oldParent.blocked: + // Don't replace an unblocked parent when reprocessing case reprocessing && sender.faster[t.parent] > oldParent.faster[sender.port]: // The sender seems to be reliably faster than the current parent, so switch to them instead. updateRoot = true