diff --git a/contrib/ansible/genkeys.go b/contrib/ansible/genkeys.go index 81397386..5213e8b8 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 diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 4f632fad..cdabaf2b 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -554,17 +554,30 @@ 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 - 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? + // 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 */ | + 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 + // 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 { - // 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 */ @@ -612,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?... + } }