github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/core/dst/windowcc.go (about)

     1  // Copyright 2014 The DST Authors. All rights reserved.
     2  // Use of this source code is governed by an MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package dst
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"os"
    11  	"time"
    12  )
    13  
    14  type windowCC struct {
    15  	minWindow     int
    16  	maxWindow     int
    17  	currentWindow int
    18  	minRate       int
    19  	maxRate       int
    20  	currentRate   int
    21  	targetRate    int
    22  
    23  	curRTT time.Duration
    24  	minRTT time.Duration
    25  
    26  	statsFile io.WriteCloser
    27  	start     time.Time
    28  }
    29  
    30  func newWindowCC() *windowCC {
    31  	var statsFile io.WriteCloser
    32  
    33  	if debugCC {
    34  		statsFile, _ = os.Create(fmt.Sprintf("cc-log-%d.csv", time.Now().Unix()))
    35  		fmt.Fprintf(statsFile, "ms,minWin,maxWin,curWin,minRate,maxRate,curRate,minRTT,curRTT\n")
    36  	}
    37  
    38  	return &windowCC{
    39  		minWindow:     1, // Packets
    40  		maxWindow:     16 << 10,
    41  		currentWindow: 1,
    42  
    43  		minRate:     100,  // PPS
    44  		maxRate:     80e3, // Roughly 1 Gbps at 1500 bytes per packet
    45  		currentRate: 100,
    46  		targetRate:  1000,
    47  
    48  		minRTT:    10 * time.Second,
    49  		statsFile: statsFile,
    50  		start:     time.Now(),
    51  	}
    52  }
    53  
    54  func (w *windowCC) Ack() {
    55  	if w.curRTT > w.minRTT+100*time.Millisecond {
    56  		return
    57  	}
    58  
    59  	changed := false
    60  
    61  	if w.currentWindow < w.maxWindow {
    62  		w.currentWindow++
    63  		changed = true
    64  	}
    65  
    66  	if w.currentRate != w.targetRate {
    67  		w.currentRate = (w.currentRate*7 + w.targetRate) / 8
    68  		changed = true
    69  	}
    70  
    71  	if changed && debugCC {
    72  		w.log()
    73  		log.Println("Ack", w.currentWindow, w.currentRate)
    74  	}
    75  }
    76  
    77  func (w *windowCC) NegAck() {
    78  	if w.currentWindow > w.minWindow {
    79  		w.currentWindow /= 2
    80  	}
    81  	if w.currentRate > w.minRate {
    82  		w.currentRate /= 2
    83  	}
    84  	if debugCC {
    85  		w.log()
    86  		log.Println("NegAck", w.currentWindow, w.currentRate)
    87  	}
    88  }
    89  
    90  func (w *windowCC) Exp() {
    91  	w.currentWindow = w.minWindow
    92  	if debugCC {
    93  		w.log()
    94  		log.Println("Exp", w.currentWindow, w.currentRate)
    95  	}
    96  }
    97  
    98  func (w *windowCC) SendWindow() int {
    99  	if w.currentWindow < w.minWindow {
   100  		return w.minWindow
   101  	}
   102  	if w.currentWindow > w.maxWindow {
   103  		return w.maxWindow
   104  	}
   105  	return w.currentWindow
   106  }
   107  
   108  func (w *windowCC) PacketRate() int {
   109  	if w.currentRate < w.minRate {
   110  		return w.minRate
   111  	}
   112  	if w.currentRate > w.maxRate {
   113  		return w.maxRate
   114  	}
   115  	return w.currentRate
   116  }
   117  
   118  func (w *windowCC) UpdateRTT(rtt time.Duration) {
   119  	w.curRTT = rtt
   120  	if w.curRTT < w.minRTT {
   121  		w.minRTT = w.curRTT
   122  		if debugCC {
   123  			log.Println("Min RTT", w.minRTT)
   124  		}
   125  	}
   126  
   127  	if w.curRTT > w.minRTT+200*time.Millisecond && w.targetRate > 2*w.minRate {
   128  		w.targetRate -= w.minRate
   129  	} else if w.curRTT < w.minRTT+20*time.Millisecond && w.targetRate < w.maxRate {
   130  		w.targetRate += w.minRate
   131  	}
   132  
   133  	if debugCC {
   134  		w.log()
   135  		log.Println("RTT", w.curRTT, "target rate", w.targetRate, "current rate", w.currentRate, "current window", w.currentWindow)
   136  	}
   137  }
   138  
   139  func (w *windowCC) log() {
   140  	if w.statsFile == nil {
   141  		return
   142  	}
   143  	fmt.Fprintf(w.statsFile, "%.02f,%d,%d,%d,%d,%d,%d,%.02f,%.02f\n", time.Since(w.start).Seconds()*1000, w.minWindow, w.maxWindow, w.currentWindow, w.minRate, w.maxRate, w.currentRate, w.minRTT.Seconds()*1000, w.curRTT.Seconds()*1000)
   144  }