refactor switch code so calling lookupTable.lookup does most of the important work

This commit is contained in:
Arceliar 2020-03-10 01:03:07 -05:00
parent cfd8641925
commit 4809879995

View File

@ -596,14 +596,14 @@ func (t *switchTable) getCloser(dest []byte) []closerInfo {
// Skip the iteration step if it's impossible to be closer // Skip the iteration step if it's impossible to be closer
return nil return nil
} }
t.queues.closer = t.queues.closer[:0] var closer []closerInfo
for _, info := range table.elems { for _, info := range table.elems {
dist := info.locator.dist(dest) dist := info.locator.dist(dest)
if dist < myDist { if dist < myDist {
t.queues.closer = append(t.queues.closer, closerInfo{info, dist}) closer = append(closer, closerInfo{info, dist})
} }
} }
return t.queues.closer return closer
} }
// Returns true if the peer is closer to the destination than ourself // Returns true if the peer is closer to the destination than ourself
@ -645,20 +645,41 @@ func switch_getFlowLabelFromCoords(in []byte) []byte {
return []byte{} return []byte{}
} }
// Find the best port for a given set of coords // Find the best port to forward to for a given set of coords
func (t *switchTable) bestPortForCoords(coords []byte) switchPort { func (t *lookupTable) lookup(coords []byte) switchPort {
table := t.getTable() var bestPort switchPort
var best switchPort myDist := t.self.dist(coords)
bestDist := table.self.dist(coords) bestDist := myDist
for to, elem := range table.elems { var bestElem tableElem
dist := elem.locator.dist(coords) for _, info := range t.elems {
if !(dist < bestDist) { dist := info.locator.dist(coords)
if dist >= myDist {
continue continue
} }
best = to var update bool
bestDist = dist switch {
case dist < bestDist:
// Closer to destination
update = true
case dist > bestDist:
// Further from destination
case info.locator.tstamp > bestElem.locator.tstamp:
// Newer root update
update = true
case info.locator.tstamp < bestElem.locator.tstamp:
// Older root update
case info.time.Before(bestElem.time):
// Received root update via this peer sooner
update = true
default:
} }
return best if update {
bestPort = info.port
bestDist = dist
bestElem = info
}
}
return bestPort
} }
// Handle an incoming packet // Handle an incoming packet
@ -666,57 +687,22 @@ func (t *switchTable) bestPortForCoords(coords []byte) switchPort {
// Returns true if the packet has been handled somehow, false if it should be queued // Returns true if the packet has been handled somehow, false if it should be queued
func (t *switchTable) _handleIn(packet []byte, idle map[switchPort]struct{}) (bool, switchPort) { func (t *switchTable) _handleIn(packet []byte, idle map[switchPort]struct{}) (bool, switchPort) {
coords := switch_getPacketCoords(packet) coords := switch_getPacketCoords(packet)
closer := t.getCloser(coords) table := t.getTable()
var best *closerInfo port := table.lookup(coords)
ports := t.core.peers.getPorts() ports := t.core.peers.getPorts()
for _, cinfo := range closer { peer := ports[port]
to := ports[cinfo.elem.port] if peer == nil {
var update bool // FIXME hack, if the peer disappeared durring a race then don't buffer
switch {
case to == nil:
// no port was found, ignore it
case best == nil:
// this is the first idle port we've found, so select it until we find a
// better candidate port to use instead
update = true
case cinfo.dist < best.dist:
// the port takes a shorter path/is more direct than our current
// candidate, so select that instead
update = true
case cinfo.dist > best.dist:
// the port takes a longer path/is less direct than our current candidate,
// ignore it
case cinfo.elem.locator.tstamp > best.elem.locator.tstamp:
// has a newer tstamp from the root, so presumably a better path
update = true
case cinfo.elem.locator.tstamp < best.elem.locator.tstamp:
// has a n older tstamp, so presumably a worse path
case cinfo.elem.time.Before(best.elem.time):
// same tstamp, but got it earlier, so presumably a better path
//t.core.log.Println("DEBUG new best:", best.elem.time, cinfo.elem.time)
update = true
default:
// the search for a port has finished
}
if update {
b := cinfo // because cinfo gets mutated by the iteration
best = &b
}
}
if best == nil {
// No closer peers
// TODO? call the router directly, and remove the whole concept of a self peer?
self := t.core.peers.getPorts()[0]
self.sendPacketsFrom(t, [][]byte{packet})
return true, 0 return true, 0
} }
if _, isIdle := idle[best.elem.port]; isIdle { if _, isIdle := idle[port]; isIdle || port == 0 {
delete(idle, best.elem.port) // Either no closer peers, or the closest peer is idle
ports[best.elem.port].sendPacketsFrom(t, [][]byte{packet}) delete(idle, port)
return true, best.elem.port peer.sendPacketsFrom(t, [][]byte{packet})
return true, port
} }
// Best node isn't idle, so return port and let the packet be buffered // There's a closer peer, but it's not idle, so buffer it
return false, best.elem.port return false, port
} }
// Info about a buffered packet // Info about a buffered packet
@ -737,7 +723,6 @@ type switch_buffers struct {
size uint64 // Total size of all buffers, in bytes size uint64 // Total size of all buffers, in bytes
maxbufs int maxbufs int
maxsize uint64 maxsize uint64
closer []closerInfo // Scratch space
} }
func (b *switch_buffers) _cleanup(t *switchTable) { func (b *switch_buffers) _cleanup(t *switchTable) {