From cdfb930703e5b1b81ccba962b9110524698cf6fa Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 21 Jan 2019 12:27:29 +0000 Subject: [PATCH 1/5] Update switch flow separation for IPv4 --- src/yggdrasil/session.go | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 4f632fa..b756ec9 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -554,20 +554,33 @@ func (sinfo *sessionInfo) doSend(bs []byte) { } // code isn't multithreaded so appending to this is safe coords := sinfo.coords - // Read IPv6 flowlabel field (20 bits). - // Assumes packet at least contains IPv6 header. - flowkey := uint64(bs[1]&0x0f)<<16 | uint64(bs[2])<<8 | uint64(bs[3]) - // Check if the flowlabel was specified + var flowkey uint64 + // Try to read IPv6 flowlabel field (20 bits) + if bs[0]&0xf0 == 0x60 { + flowkey = uint64(bs[1]&0x0f)<<16 | uint64(bs[2])<<8 | uint64(bs[3]) + } + // Check if the flowlabel was specified. If not then try to use known + // protocols' ports: protokey: proto | sport | dport if flowkey == 0 { - // Does the packet meet the minimum UDP packet size? (others are bigger) - if len(bs) >= 48 { - // Is the protocol TCP, UDP, SCTP? - if bs[6] == 0x06 || bs[6] == 0x11 || bs[6] == 0x84 { - // if flowlabel was unspecified (0), try to use known protocols' ports - // protokey: proto | sport | dport - flowkey = uint64(bs[6])<<32 /* proto */ | - uint64(bs[40])<<24 | uint64(bs[41])<<16 /* sport */ | - uint64(bs[42])<<8 | uint64(bs[43]) /* dport */ + // Is the protocol TCP, UDP, SCTP? + switch bs[0] & 0xf0 { + case 0x40: // IPv4 packet + if len(bs) >= 24 { + if bs[9] == 0x06 || bs[9] == 0x11 || bs[9] == 0x84 { + ihl := bs[0] & 0x0f * 4 // Header length + flowkey = uint64(bs[9])<<32 /* proto */ | + uint64(bs[ihl+0])<<24 | uint64(bs[ihl+1])<<16 /* sport */ | + uint64(bs[ihl+2])<<8 | uint64(bs[ihl+3]) /* dport */ + } + } + case 0x60: // IPv6 packet + // Does the packet meet the minimum UDP packet size? (others are bigger) + if len(bs) >= 48 { + if bs[6] == 0x06 || bs[6] == 0x11 || bs[6] == 0x84 { + flowkey = uint64(bs[6])<<32 /* proto */ | + uint64(bs[40])<<24 | uint64(bs[41])<<16 /* sport */ | + uint64(bs[42])<<8 | uint64(bs[43]) /* dport */ + } } } } From d3f67ad0170cba1e8f4c9d0e668875864fdcb3a5 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 21 Jan 2019 16:22:49 +0000 Subject: [PATCH 2/5] Improve command flow --- src/yggdrasil/session.go | 48 +++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index b756ec9..23b27a3 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -554,33 +554,31 @@ func (sinfo *sessionInfo) doSend(bs []byte) { } // code isn't multithreaded so appending to this is safe coords := sinfo.coords + // Work out the flowkey - this is used to determine which switch queue + // traffic will be pushed to in the event of congestion var flowkey uint64 - // Try to read IPv6 flowlabel field (20 bits) - if bs[0]&0xf0 == 0x60 { - flowkey = uint64(bs[1]&0x0f)<<16 | uint64(bs[2])<<8 | uint64(bs[3]) - } - // Check if the flowlabel was specified. If not then try to use known - // protocols' ports: protokey: proto | sport | dport - if flowkey == 0 { - // Is the protocol TCP, UDP, SCTP? - switch bs[0] & 0xf0 { - case 0x40: // IPv4 packet - if len(bs) >= 24 { - if bs[9] == 0x06 || bs[9] == 0x11 || bs[9] == 0x84 { - ihl := bs[0] & 0x0f * 4 // Header length - flowkey = uint64(bs[9])<<32 /* proto */ | - uint64(bs[ihl+0])<<24 | uint64(bs[ihl+1])<<16 /* sport */ | - uint64(bs[ihl+2])<<8 | uint64(bs[ihl+3]) /* dport */ - } + switch bs[0] & 0xf0 { + case 0x40: // IPv4 packet + // Check the packet meets minimum UDP packet length + if len(bs) >= 24 { + if bs[9] == 0x06 || bs[9] == 0x11 || bs[9] == 0x84 { + ihl := bs[0] & 0x0f * 4 // Header length + flowkey = uint64(bs[9])<<32 /* proto */ | + uint64(bs[ihl+0])<<24 | uint64(bs[ihl+1])<<16 /* sport */ | + uint64(bs[ihl+2])<<8 | uint64(bs[ihl+3]) /* dport */ } - case 0x60: // IPv6 packet - // Does the packet meet the minimum UDP packet size? (others are bigger) - if len(bs) >= 48 { - if bs[6] == 0x06 || bs[6] == 0x11 || bs[6] == 0x84 { - flowkey = uint64(bs[6])<<32 /* proto */ | - uint64(bs[40])<<24 | uint64(bs[41])<<16 /* sport */ | - uint64(bs[42])<<8 | uint64(bs[43]) /* dport */ - } + } + case 0x60: // IPv6 packet + // Check if the flowlabel was specified in the packet header + flowkey = uint64(bs[1]&0x0f)<<16 | uint64(bs[2])<<8 | uint64(bs[3]) + // If the flowlabel isn't present, make protokey from proto | sport | dport + // if the packet meets minimum UDP packet length + if flowkey == 0 && len(bs) >= 48 { + // Is the protocol TCP, UDP or SCTP? + if bs[6] == 0x06 || bs[6] == 0x11 || bs[6] == 0x84 { + flowkey = uint64(bs[6])<<32 /* proto */ | + uint64(bs[40])<<24 | uint64(bs[41])<<16 /* sport */ | + uint64(bs[42])<<8 | uint64(bs[43]) /* dport */ } } } From 62d4d62a775ca2ff624f76d2e02ea46c1628dc2d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 21 Jan 2019 16:24:29 +0000 Subject: [PATCH 3/5] Update comments --- src/yggdrasil/session.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 23b27a3..6b7f62d 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -557,10 +557,12 @@ func (sinfo *sessionInfo) doSend(bs []byte) { // Work out the flowkey - this is used to determine which switch queue // traffic will be pushed to in the event of congestion var flowkey uint64 + // Get the IP protocol version from the packet switch bs[0] & 0xf0 { case 0x40: // IPv4 packet // Check the packet meets minimum UDP packet length if len(bs) >= 24 { + // Is the protocol TCP, UDP or SCTP? if bs[9] == 0x06 || bs[9] == 0x11 || bs[9] == 0x84 { ihl := bs[0] & 0x0f * 4 // Header length flowkey = uint64(bs[9])<<32 /* proto */ | From 2baedc9bcc6fa4bd4863d84019ce652ef1037e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Christian=20Gr=C3=BCnhage?= Date: Fri, 25 Jan 2019 21:28:22 +0100 Subject: [PATCH 4/5] make ansible key generator a tiny bit faster --- contrib/ansible/genkeys.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/ansible/genkeys.go b/contrib/ansible/genkeys.go index 22418a0..7df2e58 100644 --- a/contrib/ansible/genkeys.go +++ b/contrib/ansible/genkeys.go @@ -117,6 +117,8 @@ func bubbleUpTo(sets []keySet, num int) []keySet { var tmp = sets[i] sets[i] = sets[i + 1] sets[i + 1] = tmp + } else { + break } } return sets From bca69df1f6da415c97d15c5b18a770b404ffa190 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sat, 26 Jan 2019 14:07:18 -0600 Subject: [PATCH 5/5] possible workaround to a deadlock --- src/yggdrasil/session.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 6b7f62d..cdabaf2 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -625,5 +625,8 @@ func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) { sinfo.updateNonce(&p.Nonce) sinfo.time = time.Now() sinfo.bytesRecvd += uint64(len(bs)) - sinfo.core.router.toRecv <- router_recvPacket{bs, sinfo} + select { + case sinfo.core.router.toRecv <- router_recvPacket{bs, sinfo}: + default: // avoid deadlocks, maybe do this somewhere else?... + } }