diff --git a/src/yggdrasil/link.go b/src/yggdrasil/link.go index 875fde5e..98c080c7 100644 --- a/src/yggdrasil/link.go +++ b/src/yggdrasil/link.go @@ -291,9 +291,11 @@ func (intf *linkInterface) _cancelStallTimer() { } } -// called by an AfterFunc if we appear to have timed out +// This gets called from a time.AfterFunc, and notifies the switch that we appear +// to have gotten blocked on a write, so the switch should start routing traffic +// through other links, if alternatives exist func (intf *linkInterface) notifyBlockedSend() { - intf.Act(nil, func() { // Sent from a time.AfterFunc + intf.Act(nil, func() { if intf.sendTimer != nil { //As far as we know, we're still trying to send, and the timer fired. intf.link.core.switchTable.blockPeer(intf.peer.port) @@ -387,8 +389,12 @@ func (w *linkWriter) sendFrom(from phony.Actor, bss [][]byte, isLinkTraffic bool size += len(bs) } w.intf.notifySending(size, isLinkTraffic) + // start a timer that will fire if we get stuck in writeMsgs for an oddly long time var once sync.Once timer := time.AfterFunc(time.Millisecond, func() { + // 1 ms is kind of arbitrary + // the rationale is that this should be very long compared to a syscall + // but it's still short compared to end-to-end latency or human perception once.Do(func() { w.intf.Act(nil, w.intf._notifySyscall) }) diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index 0150e173..ba30758c 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -721,15 +721,6 @@ func (t *switchTable) _handleIn(packet []byte, idle map[switchPort]struct{}, sen ports[best.elem.port].sendPacketsFrom(t, [][]byte{packet}) return true } - //delete(idle, best.elem.port) - // Tell ourselves to send to this node later - // If another (e.g. even better) hop becomes idle in the mean time, it'll take the packet instead - // FIXME this is just a hack, but seems to help with stability... - //go t.Act(nil, func() { - // t._idleIn(best.elem.port) - //}) - //ports[best.elem.port].sendPacketsFrom(t, [][]byte{packet}) - //return true } // Didn't find anyone idle to send it to return false @@ -799,6 +790,7 @@ func (b *switch_buffers) _cleanup(t *switchTable) { // Loops over packets and sends the newest one that's OK for this peer to send // Returns true if the peer is no longer idle, false if it should be added to the idle list func (t *switchTable) _handleIdle(port switchPort) bool { + // TODO? only send packets for which this is the best next hop that isn't currently blocked sending to := t.core.peers.getPorts()[port] if to == nil { return true