5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-22 14:10:28 +00:00

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.

This commit is contained in:
Arceliar 2018-01-13 07:26:26 -06:00
parent ef1e0c902f
commit 75965b6da4
6 changed files with 60 additions and 28 deletions

View File

@ -274,9 +274,14 @@ func (c *Core) DEBUG_getGlobalUDPAddr() net.Addr {
} }
func (c *Core) DEBUG_maybeSendUDPKeys(saddr string) { 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() c.udp.mutex.RLock()
_, isIn := c.udp.conns[connAddr(addr)] _, isIn := c.udp.conns[addr]
c.udp.mutex.RUnlock() c.udp.mutex.RUnlock()
if !isIn { if !isIn {
c.udp.sendKeys(addr) c.udp.sendKeys(addr)

View File

@ -171,10 +171,10 @@ func (p *peer) handleTraffic(packet []byte, pTypeLen int) {
if to == nil { if to == nil {
return return
} }
newTTLSlice := wire_encode_uint64(newTTL) newTTLLen := wire_uint64_len(newTTL)
// This mutates the packet in-place if the length of the TTL changes! // This mutates the packet in-place if the length of the TTL changes!
shift := ttlLen - len(newTTLSlice) shift := ttlLen - newTTLLen
copy(packet[ttlBegin+shift:], newTTLSlice) wire_put_uint64(newTTL, packet[ttlBegin+shift:])
copy(packet[shift:], packet[:pTypeLen]) copy(packet[shift:], packet[:pTypeLen])
packet = packet[shift:] packet = packet[shift:]
to.sendPacket(packet) to.sendPacket(packet)

View File

@ -40,7 +40,7 @@ type router struct {
func (r *router) init(core *Core) { func (r *router) init(core *Core) {
r.core = core r.core = core
r.addr = *address_addrForNodeID(&r.core.dht.nodeID) 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) p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub) //, out, in)
// TODO set in/out functions on the new peer... // TODO set in/out functions on the new peer...
p.out = func(packet []byte) { in <- packet } // FIXME in theory it blocks... 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 // TODO attach these to the tun
// Maybe that's the core's job... // Maybe that's the core's job...
// It creates tun, creates the router, creates channels, sets them? // It creates tun, creates the router, creates channels, sets them?
recv := make(chan []byte, 1) recv := make(chan []byte, 1024)
send := make(chan []byte, 1) send := make(chan []byte, 1024)
r.recv = recv r.recv = recv
r.send = send r.send = send
r.core.tun.recv = recv r.core.tun.recv = recv

View File

@ -164,8 +164,8 @@ func (ss *sessions) createSession(theirPermKey *boxPubKey) *sessionInfo {
sinfo.myHandle = *newHandle() sinfo.myHandle = *newHandle()
sinfo.theirAddr = *address_addrForNodeID(getNodeID(&sinfo.theirPermPub)) sinfo.theirAddr = *address_addrForNodeID(getNodeID(&sinfo.theirPermPub))
sinfo.theirSubnet = *address_subnetForNodeID(getNodeID(&sinfo.theirPermPub)) sinfo.theirSubnet = *address_subnetForNodeID(getNodeID(&sinfo.theirPermPub))
sinfo.send = make(chan []byte, 1) sinfo.send = make(chan []byte, 1024)
sinfo.recv = make(chan *wire_trafficPacket, 1) sinfo.recv = make(chan *wire_trafficPacket, 1024)
go sinfo.doWorker() go sinfo.doWorker()
sinfo.time = time.Now() sinfo.time = time.Now()
// Do some cleanup // Do some cleanup

View File

@ -21,8 +21,31 @@ type udpInterface struct {
conns map[connAddr]*connInfo 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 { type connInfo struct {
name string
addr connAddr addr connAddr
peer *peer peer *peer
linkIn chan []byte linkIn chan []byte
@ -54,10 +77,7 @@ func (iface *udpInterface) init(core *Core, addr string) {
} }
func (iface *udpInterface) sendKeys(addr connAddr) { func (iface *udpInterface) sendKeys(addr connAddr) {
udpAddr, err := net.ResolveUDPAddr("udp", string(addr)) udpAddr := addr.toUDPAddr()
if err != nil {
panic(err)
}
msg := []byte{} msg := []byte{}
msg = udp_encode(msg, 0, 0, 0, nil) msg = udp_encode(msg, 0, 0, 0, nil)
msg = append(msg, iface.core.boxPub[:]...) msg = append(msg, iface.core.boxPub[:]...)
@ -91,7 +111,7 @@ func (iface *udpInterface) startConn(info *connInfo) {
close(info.linkIn) close(info.linkIn)
close(info.keysIn) close(info.keysIn)
close(info.out) close(info.out)
iface.core.log.Println("Removing peer:", info.addr) iface.core.log.Println("Removing peer:", info.name)
}() }()
for { for {
select { select {
@ -135,11 +155,13 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
conn, isIn := iface.conns[addr] conn, isIn := iface.conns[addr]
iface.mutex.RUnlock() // TODO? keep the lock longer?... iface.mutex.RUnlock() // TODO? keep the lock longer?...
if !isIn { if !isIn {
udpAddr, err := net.ResolveUDPAddr("udp", string(addr)) udpAddr := addr.toUDPAddr()
if err != nil { themNodeID := getNodeID(&ks.box)
panic(err) themAddr := address_addrForNodeID(themNodeID)
} themAddrString := net.IP(themAddr[:]).String()
themString := fmt.Sprintf("%s@%s", themAddrString, udpAddr.String())
conn = &connInfo{ conn = &connInfo{
name: themString,
addr: connAddr(addr), addr: connAddr(addr),
peer: iface.core.peers.newPeer(&ks.box, &ks.sig), peer: iface.core.peers.newPeer(&ks.box, &ks.sig),
linkIn: make(chan []byte, 1), linkIn: make(chan []byte, 1),
@ -208,10 +230,10 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
} }
} }
go func() { go func() {
//var chunks [][]byte
var out []byte var out []byte
for msg := range conn.out {
var chunks [][]byte var chunks [][]byte
for msg := range conn.out {
chunks = chunks[:0]
bs := msg bs := msg
for len(bs) > udp_chunkSize { for len(bs) > udp_chunkSize {
chunks, bs = append(chunks, bs[:udp_chunkSize]), 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.mutex.Lock()
iface.conns[addr] = conn iface.conns[addr] = conn
iface.mutex.Unlock() iface.mutex.Unlock()
themNodeID := getNodeID(&ks.box) iface.core.log.Println("Adding peer:", conn.name)
themAddr := address_addrForNodeID(themNodeID)
themAddrString := net.IP(themAddr[:]).String()
themString := fmt.Sprintf("%s@%s", themAddrString, addr)
iface.core.log.Println("Adding peer:", themString)
go iface.startConn(conn) go iface.startConn(conn)
go conn.peer.linkLoop(conn.linkIn) go conn.peer.linkLoop(conn.linkIn)
iface.sendKeys(conn.addr) iface.sendKeys(conn.addr)
@ -279,7 +297,8 @@ func (iface *udpInterface) reader() {
} }
//msg := append(util_getBytes(), bs[:n]...) //msg := append(util_getBytes(), bs[:n]...)
msg := bs[:n] msg := bs[:n]
addr := connAddr(udpAddr.String()) var addr connAddr
addr.fromUDPAddr(udpAddr)
if udp_isKeys(msg) { if udp_isKeys(msg) {
var them address var them address
copy(them[:], udpAddr.IP.To16()) copy(them[:], udpAddr.IP.To16())

View File

@ -44,6 +44,14 @@ func wire_put_uint64(elem uint64, out []byte) []byte {
return append(out, bs...) 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 // Decode uint64 from a []byte slice
// Returns the decoded uint64 and the number of bytes used // Returns the decoded uint64 and the number of bytes used
func wire_decode_uint64(bs []byte) (uint64, int) { func wire_decode_uint64(bs []byte) (uint64, int) {