From 75965b6da4f898a5d4785ae85271e8a588df82c8 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sat, 13 Jan 2018 07:26:26 -0600 Subject: [PATCH] Switch connAddr (udp map key) from string to a struct that allocates less. Reduce some other allocations. Use larger channel buffers to reduce backpressure from runtime jitter. --- src/yggdrasil/debug.go | 9 +++++-- src/yggdrasil/peer.go | 6 ++--- src/yggdrasil/router.go | 6 ++--- src/yggdrasil/session.go | 4 +-- src/yggdrasil/udp.go | 55 +++++++++++++++++++++++++++------------- src/yggdrasil/wire.go | 8 ++++++ 6 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index a6caefec..e182276d 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -274,9 +274,14 @@ func (c *Core) DEBUG_getGlobalUDPAddr() net.Addr { } func (c *Core) DEBUG_maybeSendUDPKeys(saddr string) { - addr := connAddr(saddr) + udpAddr, err := net.ResolveUDPAddr("udp", saddr) + if err != nil { + panic(err) + } + var addr connAddr + addr.fromUDPAddr(udpAddr) c.udp.mutex.RLock() - _, isIn := c.udp.conns[connAddr(addr)] + _, isIn := c.udp.conns[addr] c.udp.mutex.RUnlock() if !isIn { c.udp.sendKeys(addr) diff --git a/src/yggdrasil/peer.go b/src/yggdrasil/peer.go index e5c98f78..2b757bbe 100644 --- a/src/yggdrasil/peer.go +++ b/src/yggdrasil/peer.go @@ -171,10 +171,10 @@ func (p *peer) handleTraffic(packet []byte, pTypeLen int) { if to == nil { return } - newTTLSlice := wire_encode_uint64(newTTL) + newTTLLen := wire_uint64_len(newTTL) // This mutates the packet in-place if the length of the TTL changes! - shift := ttlLen - len(newTTLSlice) - copy(packet[ttlBegin+shift:], newTTLSlice) + shift := ttlLen - newTTLLen + wire_put_uint64(newTTL, packet[ttlBegin+shift:]) copy(packet[shift:], packet[:pTypeLen]) packet = packet[shift:] to.sendPacket(packet) diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index e68ecb38..5d13b8d2 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -40,7 +40,7 @@ type router struct { func (r *router) init(core *Core) { r.core = core r.addr = *address_addrForNodeID(&r.core.dht.nodeID) - in := make(chan []byte, 1) // TODO something better than this... + in := make(chan []byte, 1024) // TODO something better than this... p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub) //, out, in) // TODO set in/out functions on the new peer... p.out = func(packet []byte) { in <- packet } // FIXME in theory it blocks... @@ -50,8 +50,8 @@ func (r *router) init(core *Core) { // TODO attach these to the tun // Maybe that's the core's job... // It creates tun, creates the router, creates channels, sets them? - recv := make(chan []byte, 1) - send := make(chan []byte, 1) + recv := make(chan []byte, 1024) + send := make(chan []byte, 1024) r.recv = recv r.send = send r.core.tun.recv = recv diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 5f998e9c..3a0703cd 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -164,8 +164,8 @@ func (ss *sessions) createSession(theirPermKey *boxPubKey) *sessionInfo { sinfo.myHandle = *newHandle() sinfo.theirAddr = *address_addrForNodeID(getNodeID(&sinfo.theirPermPub)) sinfo.theirSubnet = *address_subnetForNodeID(getNodeID(&sinfo.theirPermPub)) - sinfo.send = make(chan []byte, 1) - sinfo.recv = make(chan *wire_trafficPacket, 1) + sinfo.send = make(chan []byte, 1024) + sinfo.recv = make(chan *wire_trafficPacket, 1024) go sinfo.doWorker() sinfo.time = time.Now() // Do some cleanup diff --git a/src/yggdrasil/udp.go b/src/yggdrasil/udp.go index dd6f5702..5a16c7ed 100644 --- a/src/yggdrasil/udp.go +++ b/src/yggdrasil/udp.go @@ -21,8 +21,31 @@ type udpInterface struct { conns map[connAddr]*connInfo } -type connAddr string // TODO something more efficient, but still a valid map key +//type connAddr string // TODO something more efficient, but still a valid map key + +type connAddr struct { + ip [16]byte + port int + zone string +} + +func (c *connAddr) fromUDPAddr(u *net.UDPAddr) { + copy(c.ip[:], u.IP.To16()) + c.port = u.Port + c.zone = u.Zone +} + +func (c *connAddr) toUDPAddr() *net.UDPAddr { + var u net.UDPAddr + u.IP = make([]byte, 16) + copy(u.IP, c.ip[:]) + u.Port = c.port + u.Zone = c.zone + return &u +} + type connInfo struct { + name string addr connAddr peer *peer linkIn chan []byte @@ -54,10 +77,7 @@ func (iface *udpInterface) init(core *Core, addr string) { } func (iface *udpInterface) sendKeys(addr connAddr) { - udpAddr, err := net.ResolveUDPAddr("udp", string(addr)) - if err != nil { - panic(err) - } + udpAddr := addr.toUDPAddr() msg := []byte{} msg = udp_encode(msg, 0, 0, 0, nil) msg = append(msg, iface.core.boxPub[:]...) @@ -91,7 +111,7 @@ func (iface *udpInterface) startConn(info *connInfo) { close(info.linkIn) close(info.keysIn) close(info.out) - iface.core.log.Println("Removing peer:", info.addr) + iface.core.log.Println("Removing peer:", info.name) }() for { select { @@ -135,11 +155,13 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) { conn, isIn := iface.conns[addr] iface.mutex.RUnlock() // TODO? keep the lock longer?... if !isIn { - udpAddr, err := net.ResolveUDPAddr("udp", string(addr)) - if err != nil { - panic(err) - } + udpAddr := addr.toUDPAddr() + themNodeID := getNodeID(&ks.box) + themAddr := address_addrForNodeID(themNodeID) + themAddrString := net.IP(themAddr[:]).String() + themString := fmt.Sprintf("%s@%s", themAddrString, udpAddr.String()) conn = &connInfo{ + name: themString, addr: connAddr(addr), peer: iface.core.peers.newPeer(&ks.box, &ks.sig), linkIn: make(chan []byte, 1), @@ -208,10 +230,10 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) { } } go func() { - //var chunks [][]byte var out []byte + var chunks [][]byte for msg := range conn.out { - var chunks [][]byte + chunks = chunks[:0] bs := msg for len(bs) > udp_chunkSize { chunks, bs = append(chunks, bs[:udp_chunkSize]), bs[udp_chunkSize:] @@ -238,11 +260,7 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) { iface.mutex.Lock() iface.conns[addr] = conn iface.mutex.Unlock() - themNodeID := getNodeID(&ks.box) - themAddr := address_addrForNodeID(themNodeID) - themAddrString := net.IP(themAddr[:]).String() - themString := fmt.Sprintf("%s@%s", themAddrString, addr) - iface.core.log.Println("Adding peer:", themString) + iface.core.log.Println("Adding peer:", conn.name) go iface.startConn(conn) go conn.peer.linkLoop(conn.linkIn) iface.sendKeys(conn.addr) @@ -279,7 +297,8 @@ func (iface *udpInterface) reader() { } //msg := append(util_getBytes(), bs[:n]...) msg := bs[:n] - addr := connAddr(udpAddr.String()) + var addr connAddr + addr.fromUDPAddr(udpAddr) if udp_isKeys(msg) { var them address copy(them[:], udpAddr.IP.To16()) diff --git a/src/yggdrasil/wire.go b/src/yggdrasil/wire.go index f896452d..cd9e059f 100644 --- a/src/yggdrasil/wire.go +++ b/src/yggdrasil/wire.go @@ -44,6 +44,14 @@ func wire_put_uint64(elem uint64, out []byte) []byte { return append(out, bs...) } +func wire_uint64_len(elem uint64) int { + l := 1 + for e := elem >> 7; e > 0; e >>= 7 { + l++ + } + return l +} + // Decode uint64 from a []byte slice // Returns the decoded uint64 and the number of bytes used func wire_decode_uint64(bs []byte) (uint64, int) {