From 74ac535d550d30577dcefa8bc6d397356e6f65e2 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Fri, 8 Feb 2019 19:46:11 -0600 Subject: [PATCH 1/2] slightly faster switch logic, should be easier to have a useful tie-breaker for peers that are equally close to the destination via the tree metric --- misc/sim/treesim.go | 4 +++- src/yggdrasil/switch.go | 45 +++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/misc/sim/treesim.go b/misc/sim/treesim.go index f4cd75fa..a62f9ff4 100644 --- a/misc/sim/treesim.go +++ b/misc/sim/treesim.go @@ -6,13 +6,15 @@ import "os" import "strings" import "strconv" import "time" -import "log" import "runtime" import "runtime/pprof" import "flag" +import "github.com/gologme/log" + import . "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" +import . "github.com/yggdrasil-network/yggdrasil-go/src/crypto" //////////////////////////////////////////////////////////////////////////////// diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index db39d010..b777d899 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -569,23 +569,23 @@ func (t *switchTable) start() error { return nil } -// Check if a packet should go to the self node -// This means there's no node closer to the destination than us -// This is mainly used to identify packets addressed to us, or that hit a blackhole -func (t *switchTable) selfIsClosest(dest []byte) bool { +// Return a map of ports onto distance, keeping only ports closer to the destination than this node +// If the map is empty (or nil), then no peer is closer +func (t *switchTable) getCloser(dest []byte) map[switchPort]int { table := t.getTable() myDist := table.self.dist(dest) if myDist == 0 { // Skip the iteration step if it's impossible to be closer - return true + return nil } + closer := make(map[switchPort]int, len(table.elems)) for _, info := range table.elems { dist := info.locator.dist(dest) if dist < myDist { - return false + closer[info.port] = dist } } - return true + return closer } // Returns true if the peer is closer to the destination than ourself @@ -639,25 +639,26 @@ func (t *switchTable) bestPortForCoords(coords []byte) switchPort { func (t *switchTable) handleIn(packet []byte, idle map[switchPort]struct{}) bool { coords := switch_getPacketCoords(packet) ports := t.core.peers.getPorts() - if t.selfIsClosest(coords) { + closer := t.getCloser(coords) + if len(closer) == 0 { // TODO? call the router directly, and remove the whole concept of a self peer? ports[0].sendPacket(packet) return true } - table := t.getTable() - myDist := table.self.dist(coords) var best *peer - bestDist := myDist - for port := range idle { - if to := ports[port]; to != nil { - if info, isIn := table.elems[to.port]; isIn { - dist := info.locator.dist(coords) - if !(dist < bestDist) { - continue - } - best = to - bestDist = dist - } + var bestDist int + for port, dist := range closer { + to := ports[port] + _, isIdle := idle[port] + switch { + case to == nil: // skip + case !isIdle: // skip + case best == nil: // keep + fallthrough + case dist < bestDist: // keep + best = to + bestDist = dist + default: // skip } } if best != nil { @@ -696,7 +697,7 @@ func (b *switch_buffers) cleanup(t *switchTable) { // Remove queues for which we have no next hop packet := buf.packets[0] coords := switch_getPacketCoords(packet.bytes) - if t.selfIsClosest(coords) { + if len(t.getCloser(coords)) == 0 { for _, packet := range buf.packets { util.PutBytes(packet.bytes) } From 21cecf4630bf365a400ada8aa8fdcfa696029830 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sat, 9 Feb 2019 17:44:25 -0600 Subject: [PATCH 2/2] consistently prioritize which peer to forward to instead of letting it be partly random --- src/yggdrasil/switch.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index b777d899..cc989d97 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -645,20 +645,39 @@ func (t *switchTable) handleIn(packet []byte, idle map[switchPort]struct{}) bool ports[0].sendPacket(packet) return true } + table := t.getTable() var best *peer var bestDist int + var bestCoordLen int for port, dist := range closer { to := ports[port] _, isIdle := idle[port] + coordLen := len(table.elems[port].locator.coords) + var update bool switch { - case to == nil: // skip - case !isIdle: // skip - case best == nil: // keep - fallthrough - case dist < bestDist: // keep + case to == nil: + //nothing + case !isIdle: + //nothing + case best == nil: + update = true + case dist < bestDist: + update = true + case dist > bestDist: + //nothing + case coordLen < bestCoordLen: + update = true + case coordLen > bestCoordLen: + //nothing + case port < best.port: + update = true + default: + //nothing + } + if update { best = to bestDist = dist - default: // skip + bestCoordLen = coordLen } } if best != nil {