Measure roundtrip times on link

This commit is contained in:
Asim Aslam 2019-10-22 18:43:09 +01:00
parent 418b8648bb
commit 407694232a
2 changed files with 61 additions and 3 deletions

View File

@ -966,7 +966,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
c.mode = options.Mode
// set the dial timeout
c.timeout = options.Timeout
// get the current time
now := time.Now()
after := func() time.Duration {
@ -980,6 +980,8 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
}
var links []string
// did we measure the rtt
var measured bool
// non multicast so we need to find the link
if id := options.Link; id != "" {
@ -1021,6 +1023,9 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
// shit fuck
if !c.discovered {
// piggy back roundtrip
nowRTT := time.Now()
// create a new discovery message for this channel
msg := c.newMessage("discover")
msg.mode = Broadcast
@ -1075,12 +1080,31 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
return nil, err
}
// set roundtrip
d := time.Since(nowRTT)
// set the link time
t.RLock()
link, ok := t.links[msg.link]
t.RUnlock()
if ok {
// set the rountrip time
link.setRTT(d)
}
// set measured to true
measured = true
// set discovered to true
c.discovered = true
}
// a unicast session so we call "open" and wait for an "accept"
// reset now in case we use it
now = time.Now()
// try to open the session
err := c.Open()
if err != nil {
@ -1089,6 +1113,18 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
return nil, err
}
// if we haven't measured the roundtrip do it now
if !measured && c.mode == Unicast {
// set the link time
t.RLock()
link, ok := t.links[c.link]
t.RUnlock()
if ok {
// set the rountrip time
link.setRTT(time.Since(now))
}
}
return c, nil
}

View File

@ -32,6 +32,9 @@ type link struct {
// channels keeps a mapping of channels and last seen
channels map[string]time.Time
// the weighed moving average roundtrip
rtt int64
// keep an error count on the link
errCount int
}
@ -48,6 +51,21 @@ func newLink(s transport.Socket) *link {
return l
}
func (l *link) setRTT(d time.Duration) {
l.Lock()
defer l.Unlock()
if l.rtt < 0 {
l.rtt = d.Nanoseconds()
return
}
// https://fishi.devtail.io/weblog/2015/04/12/measuring-bandwidth-and-round-trip-time-tcp-connection-inside-application-layer/
rtt := 0.8*float64(l.rtt) + 0.2*float64(d.Nanoseconds())
// set new rtt
l.rtt = int64(rtt)
}
// watches the channel expiry
func (l *link) expiry() {
t := time.NewTicker(time.Minute)
@ -95,9 +113,13 @@ func (l *link) Rate() float64 {
return float64(10e8)
}
// Length returns the roundtrip time as nanoseconds (lower is better)
// Length returns the roundtrip time as nanoseconds (lower is better).
// Returns 0 where no measurement has been taken.
func (l *link) Length() int64 {
return time.Second.Nanoseconds()
l.RLock()
defer l.RUnlock()
return l.rtt
}
func (l *link) Id() string {