From fb7b1f2c20a7c2a77d9a1755a522d6dc27b0a3ed Mon Sep 17 00:00:00 2001 From: vadym Date: Sun, 11 Jul 2021 12:40:00 +0300 Subject: [PATCH] 1. added FlowKeyMessage type --- src/util/util.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/util/util.go b/src/util/util.go index 507426d0..f4331e4d 100644 --- a/src/util/util.go +++ b/src/util/util.go @@ -8,6 +8,11 @@ import ( "time" ) +type FlowKeyMessage struct { + FlowKey uint64 + Message []byte +} + // TimerStop stops a timer and makes sure the channel is drained, returns true if the timer was stopped before firing. func TimerStop(t *time.Timer) bool { stopped := t.Stop() @@ -35,3 +40,41 @@ func FuncTimeout(timeout time.Duration, f func()) bool { return false } } + +// GetFlowKey takes an IP packet as an argument and returns some information about the traffic flow. +// For IPv4 packets, this is derived from the source and destination protocol and port numbers. +// For IPv6 packets, this is derived from the FlowLabel field of the packet if this was set, otherwise it's handled like IPv4. +// The FlowKey is then used internally by Yggdrasil for congestion control. +func GetFlowKey(bs []byte) uint64 { + // 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 + ihl := (bs[0] & 0x0f) * 4 // whole IPv4 header length (min 20) + // 8 is minimum UDP packet length + if ihl >= 20 && len(bs)-int(ihl) >= 8 { + switch bs[9] /* protocol */ { + case 0x06 /* TCP */, 0x11 /* UDP */, 0x84 /* SCTP */ : + 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 { + switch bs[9] /* protocol */ { + case 0x06 /* TCP */, 0x11 /* UDP */, 0x84 /* SCTP */ : + flowkey = uint64(bs[6])<<32 /* proto */ | + uint64(bs[40])<<24 | uint64(bs[41])<<16 /* sport */ | + uint64(bs[42])<<8 | uint64(bs[43]) /* dport */ + } + } + } + return flowkey +}