mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-21 15:05:21 +00:00
switch to a separate queue per stream of traffic, FIXME for some reason this makes distance calculations more expensive in handleIdle?
This commit is contained in:
parent
189628b381
commit
9c028e1d0d
@ -51,12 +51,12 @@ ip netns exec node4 ip link set lo up
|
||||
ip netns exec node5 ip link set lo up
|
||||
ip netns exec node6 ip link set lo up
|
||||
|
||||
ip netns exec node1 ./run --autoconf --pprof &> /dev/null &
|
||||
ip netns exec node2 ./run --autoconf --pprof &> /dev/null &
|
||||
ip netns exec node3 ./run --autoconf --pprof &> /dev/null &
|
||||
ip netns exec node4 ./run --autoconf --pprof &> /dev/null &
|
||||
ip netns exec node5 ./run --autoconf --pprof &> /dev/null &
|
||||
ip netns exec node6 ./run --autoconf --pprof &> /dev/null &
|
||||
ip netns exec node1 env PPROFLISTEN=localhost:6060 ./run --autoconf &> /dev/null &
|
||||
ip netns exec node2 env PPROFLISTEN=localhost:6060 ./run --autoconf &> /dev/null &
|
||||
ip netns exec node3 env PPROFLISTEN=localhost:6060 ./run --autoconf &> /dev/null &
|
||||
ip netns exec node4 env PPROFLISTEN=localhost:6060 ./run --autoconf &> /dev/null &
|
||||
ip netns exec node5 env PPROFLISTEN=localhost:6060 ./run --autoconf &> /dev/null &
|
||||
ip netns exec node6 env PPROFLISTEN=localhost:6060 ./run --autoconf &> /dev/null &
|
||||
|
||||
echo "Started, to continue you should (possibly w/ sudo):"
|
||||
echo "kill" $(jobs -p)
|
||||
|
@ -520,17 +520,39 @@ func (t *switchTable) portIsCloser(dest []byte, port switchPort) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Get the coords of a packet without decoding
|
||||
func switch_getPacketCoords(packet []byte) []byte {
|
||||
_, pTypeLen := wire_decode_uint64(packet)
|
||||
coords, _ := wire_decode_coords(packet[pTypeLen:])
|
||||
return coords
|
||||
}
|
||||
|
||||
// Returns a unique string for each stream of traffic
|
||||
// Equal to type+coords+handle for traffic packets
|
||||
// Equal to type+coords+toKey+fromKey for protocol traffic packets
|
||||
func switch_getPacketStreamID(packet []byte) string {
|
||||
pType, pTypeLen := wire_decode_uint64(packet)
|
||||
_, coordLen := wire_decode_coords(packet[pTypeLen:])
|
||||
end := pTypeLen + coordLen
|
||||
switch {
|
||||
case pType == wire_Traffic:
|
||||
end += handleLen // handle
|
||||
case pType == wire_ProtocolTraffic:
|
||||
end += 2 * boxPubKeyLen
|
||||
default:
|
||||
end = 0
|
||||
}
|
||||
if end > len(packet) {
|
||||
end = len(packet)
|
||||
}
|
||||
return string(packet[:end])
|
||||
}
|
||||
|
||||
// Handle an incoming packet
|
||||
// Either send it to ourself, or to the first idle peer that's free
|
||||
// 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 {
|
||||
// Get the coords, skipping the first byte (the pType)
|
||||
_, pTypeLen := wire_decode_uint64(packet)
|
||||
coords, coordLen := wire_decode_coords(packet[pTypeLen:])
|
||||
if coordLen >= len(packet) {
|
||||
util_putBytes(packet)
|
||||
return true
|
||||
} // No payload
|
||||
coords := switch_getPacketCoords(packet)
|
||||
ports := t.core.peers.getPorts()
|
||||
if t.selfIsClosest(coords) {
|
||||
// TODO? call the router directly, and remove the whole concept of a self peer?
|
||||
@ -564,6 +586,10 @@ func (t *switchTable) handleIn(packet []byte, idle map[switchPort]struct{}) bool
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME for some reason the new version is a *lot* slower than this one was
|
||||
It seems to be from the switchLocator.dist(coords) calls
|
||||
|
||||
// Handles incoming idle notifications
|
||||
// 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
|
||||
@ -584,10 +610,45 @@ func (t *switchTable) handleIdle(port switchPort, packets *[][]byte) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
*/
|
||||
|
||||
// Handles incoming idle notifications
|
||||
// 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, stacks map[string][][]byte) bool {
|
||||
to := t.core.peers.getPorts()[port]
|
||||
if to == nil {
|
||||
return true
|
||||
}
|
||||
var best string
|
||||
var bestSize int
|
||||
for streamID, packets := range stacks {
|
||||
// Filter over the streams that this node is closer to
|
||||
packet := packets[len(packets)-1]
|
||||
if (bestSize == 0 || len(packets) < bestSize) && t.portIsCloser(packet, port) {
|
||||
best = streamID
|
||||
bestSize = len(packets)
|
||||
}
|
||||
}
|
||||
if bestSize != 0 {
|
||||
packets := stacks[best]
|
||||
var packet []byte
|
||||
packet, packets = packets[len(packets)-1], packets[:len(packets)-1]
|
||||
if len(packets) == 0 {
|
||||
delete(stacks, best)
|
||||
} else {
|
||||
stacks[best] = packets
|
||||
}
|
||||
to.sendPacket(packet)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// The switch worker does routing lookups and sends packets to where they need to be
|
||||
func (t *switchTable) doWorker() {
|
||||
var packets [][]byte // Should really be a linked list
|
||||
stacks := make(map[string][][]byte) // Packets per PacketStreamID (string)
|
||||
idle := make(map[switchPort]struct{}) // this is to deduplicate things
|
||||
for {
|
||||
select {
|
||||
@ -595,15 +656,17 @@ func (t *switchTable) doWorker() {
|
||||
// Try to send it somewhere (or drop it if it's corrupt or at a dead end)
|
||||
if !t.handleIn(packet, idle) {
|
||||
// There's nobody free to take it right now, so queue it for later
|
||||
packets = append(packets, packet)
|
||||
streamID := switch_getPacketStreamID(packet)
|
||||
packets := append(stacks[streamID], packet)
|
||||
for len(packets) > 32 {
|
||||
util_putBytes(packets[0])
|
||||
packets = packets[1:]
|
||||
}
|
||||
stacks[streamID] = packets
|
||||
}
|
||||
case port := <-t.idleIn:
|
||||
// Try to find something to send to this peer
|
||||
if !t.handleIdle(port, &packets) {
|
||||
if !t.handleIdle(port, stacks) {
|
||||
// Didn't find anything ready to send yet, so stay idle
|
||||
idle[port] = struct{}{}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user