Explorar o código

Switch to a more accurate burst detection heuristic

Rod Hynes %!s(int64=5) %!d(string=hai) anos
pai
achega
07e4ed9d1b

+ 68 - 99
psiphon/common/burst.go

@@ -28,29 +28,27 @@ import (
 // BurstMonitoredConn wraps a net.Conn and monitors for data transfer bursts.
 // Upstream (read) and downstream (write) bursts are tracked independently.
 //
-// A burst is defined as a transfer of at least "threshold" bytes, across
-// multiple I/O operations where the delay between operations does not exceed
+// A burst is defined as a transfer of "target" bytes, possibly across
+// multiple I/O operations, where the total time elapsed does not exceed
 // "deadline". Both a non-zero deadline and theshold must be set to enable
 // monitoring. Four bursts are reported: the first, the last, the min (by
 // rate) and max.
 //
-// The reported rates will be more accurate for larger data transfers,
-// especially for higher transfer rates. Tune the deadline/threshold as
-// required. The threshold should be set to account for buffering (e.g, the
-// local host socket send/receive buffer) but this is not enforced by
-// BurstMonitoredConn.
-//
-// Close must be called to complete any outstanding bursts. For complete
-// results, call GetMetrics only after Close is called.
+// The burst monitoring is heuristical in nature and may not capture all
+// bursts. The reported rates will be more accurate for larger target values
+// and shorter deadlines, but these settings may fail to register bursts on
+// slower connections. Tune the deadline/target as required. The threshold
+// should be set to account for buffering (e.g, the local host socket
+// send/receive buffer) but this is not enforced by BurstMonitoredConn.
 //
 // Overhead: BurstMonitoredConn adds mutexes but does not use timers.
 type BurstMonitoredConn struct {
 	net.Conn
-	isServer            bool
-	readDeadline        time.Duration
-	readThresholdBytes  int64
-	writeDeadline       time.Duration
-	writeThresholdBytes int64
+	isServer         bool
+	readTargetBytes  int64
+	readDeadline     time.Duration
+	writeTargetBytes int64
+	writeDeadline    time.Duration
 
 	readMutex        sync.Mutex
 	currentReadBurst burst
@@ -65,10 +63,10 @@ type BurstMonitoredConn struct {
 func NewBurstMonitoredConn(
 	conn net.Conn,
 	isServer bool,
+	upstreamTargetBytes int64,
 	upstreamDeadline time.Duration,
-	upstreamThresholdBytes int64,
-	downstreamDeadline time.Duration,
-	downstreamThresholdBytes int64) *BurstMonitoredConn {
+	downstreamTargetBytes int64,
+	downstreamDeadline time.Duration) *BurstMonitoredConn {
 
 	burstConn := &BurstMonitoredConn{
 		Conn:     conn,
@@ -76,24 +74,24 @@ func NewBurstMonitoredConn(
 	}
 
 	if isServer {
+		burstConn.readTargetBytes = upstreamTargetBytes
 		burstConn.readDeadline = upstreamDeadline
-		burstConn.readThresholdBytes = upstreamThresholdBytes
+		burstConn.writeTargetBytes = downstreamTargetBytes
 		burstConn.writeDeadline = downstreamDeadline
-		burstConn.writeThresholdBytes = downstreamThresholdBytes
 	} else {
+		burstConn.readTargetBytes = downstreamTargetBytes
 		burstConn.readDeadline = downstreamDeadline
-		burstConn.readThresholdBytes = downstreamThresholdBytes
+		burstConn.writeTargetBytes = upstreamTargetBytes
 		burstConn.writeDeadline = upstreamDeadline
-		burstConn.writeThresholdBytes = upstreamThresholdBytes
 	}
 
 	return burstConn
 }
 
 type burst struct {
-	startTime    time.Time
-	lastByteTime time.Time
-	bytes        int64
+	startTime time.Time
+	endTime   time.Time
+	bytes     int64
 }
 
 func (b *burst) isZero() bool {
@@ -109,7 +107,7 @@ func (b *burst) offset(baseTime time.Time) time.Duration {
 }
 
 func (b *burst) duration() time.Duration {
-	duration := b.lastByteTime.Sub(b.startTime)
+	duration := b.endTime.Sub(b.startTime)
 	if duration <= 0 {
 		return 0
 	}
@@ -117,9 +115,19 @@ func (b *burst) duration() time.Duration {
 }
 
 func (b *burst) rate() int64 {
+	duration := b.duration()
+	if duration <= 0 {
+		return 0
+	}
 	return int64(
 		(float64(b.bytes) * float64(time.Second)) /
-			float64(b.duration()))
+			float64(duration))
+}
+
+func (b *burst) reset() {
+	b.startTime = time.Time{}
+	b.endTime = time.Time{}
+	b.bytes = 0
 }
 
 type burstHistory struct {
@@ -131,7 +139,7 @@ type burstHistory struct {
 
 func (conn *BurstMonitoredConn) Read(buffer []byte) (int, error) {
 
-	if conn.readDeadline <= 0 || conn.readThresholdBytes <= 0 {
+	if conn.readTargetBytes <= 0 || conn.readDeadline <= 0 {
 		return conn.Conn.Read(buffer)
 	}
 
@@ -145,8 +153,8 @@ func (conn *BurstMonitoredConn) Read(buffer []byte) (int, error) {
 			start,
 			end,
 			int64(n),
+			conn.readTargetBytes,
 			conn.readDeadline,
-			conn.readThresholdBytes,
 			&conn.currentReadBurst,
 			&conn.readBursts)
 		conn.readMutex.Unlock()
@@ -158,7 +166,7 @@ func (conn *BurstMonitoredConn) Read(buffer []byte) (int, error) {
 
 func (conn *BurstMonitoredConn) Write(buffer []byte) (int, error) {
 
-	if conn.writeDeadline <= 0 || conn.writeThresholdBytes <= 0 {
+	if conn.writeTargetBytes <= 0 || conn.writeDeadline <= 0 {
 		return conn.Conn.Write(buffer)
 	}
 
@@ -172,8 +180,8 @@ func (conn *BurstMonitoredConn) Write(buffer []byte) (int, error) {
 			start,
 			end,
 			int64(n),
+			conn.writeTargetBytes,
 			conn.writeDeadline,
-			conn.writeThresholdBytes,
 			&conn.currentWriteBurst,
 			&conn.writeBursts)
 		conn.writeMutex.Unlock()
@@ -183,31 +191,6 @@ func (conn *BurstMonitoredConn) Write(buffer []byte) (int, error) {
 	return n, err
 }
 
-func (conn *BurstMonitoredConn) Close() error {
-	err := conn.Conn.Close()
-
-	if conn.readDeadline > 0 && conn.readThresholdBytes > 0 {
-		conn.readMutex.Lock()
-		conn.endBurst(
-			conn.readThresholdBytes,
-			&conn.currentReadBurst,
-			&conn.readBursts)
-		conn.readMutex.Unlock()
-	}
-
-	if conn.writeDeadline > 0 && conn.writeThresholdBytes > 0 {
-		conn.writeMutex.Lock()
-		conn.endBurst(
-			conn.writeThresholdBytes,
-			&conn.currentWriteBurst,
-			&conn.writeBursts)
-		conn.writeMutex.Unlock()
-	}
-
-	// Note: no context error to preserve error type
-	return err
-}
-
 // IsClosed implements the Closer iterface. The return value indicates whether
 // the underlying conn has been closed.
 func (conn *BurstMonitoredConn) IsClosed() bool {
@@ -262,65 +245,51 @@ func (conn *BurstMonitoredConn) updateBurst(
 	operationStart time.Time,
 	operationEnd time.Time,
 	operationBytes int64,
-	deadline time.Duration,
 	thresholdBytes int64,
+	deadline time.Duration,
 	currentBurst *burst,
 	history *burstHistory) {
 
 	// Assumes the associated mutex is locked.
 
-	if currentBurst.isZero() {
-		currentBurst.startTime = operationStart
-		currentBurst.lastByteTime = operationEnd
-		currentBurst.bytes = operationBytes
-
-	} else {
-
-		if operationStart.Sub(currentBurst.lastByteTime) >
-			deadline {
-
-			conn.endBurst(thresholdBytes, currentBurst, history)
-			currentBurst.startTime = operationStart
-		}
-
-		currentBurst.lastByteTime = operationEnd
-		currentBurst.bytes += operationBytes
+	if operationEnd.Sub(currentBurst.startTime) > deadline {
+		// Partial burst failed to reach the target, so discard it.
+		currentBurst.reset()
 	}
 
-}
-
-func (conn *BurstMonitoredConn) endBurst(
-	thresholdBytes int64,
-	currentBurst *burst,
-	history *burstHistory) {
-
-	// Assumes the associated mutex is locked.
-
-	if currentBurst.isZero() {
+	if operationEnd.Sub(operationStart) > deadline {
+		// Operation exceeded deadline, so no burst.
 		return
 	}
 
-	burst := *currentBurst
+	if currentBurst.isZero() {
+		// Start a new burst.
+		currentBurst.startTime = operationStart
+	}
 
-	currentBurst.startTime = time.Time{}
-	currentBurst.lastByteTime = time.Time{}
-	currentBurst.bytes = 0
+	currentBurst.bytes += operationBytes
 
-	if burst.bytes < thresholdBytes {
-		return
-	}
+	if currentBurst.bytes >= thresholdBytes {
 
-	if history.first.isZero() {
-		history.first = burst
-	}
+		// Burst completed. Bytes in excess of the target are included in the burst
+		// for a more accurate rate calculation: we know, roughly, when the last
+		// byte arrived, but not the last target byte. For the same reason, we do
+		// not count the excess bytes towards a subsequent burst.
 
-	history.last = burst
+		currentBurst.endTime = operationEnd
 
-	if history.min.isZero() || history.min.rate() > burst.rate() {
-		history.min = burst
-	}
+		if history.first.isZero() {
+			history.first = *currentBurst
+		}
+		history.last = *currentBurst
+		rate := currentBurst.rate()
+		if history.min.isZero() || history.min.rate() > rate {
+			history.min = *currentBurst
+		}
+		if history.max.isZero() || history.max.rate() < rate {
+			history.max = *currentBurst
+		}
 
-	if history.max.isZero() || history.max.rate() < burst.rate() {
-		history.max = burst
+		currentBurst.reset()
 	}
 }

+ 20 - 20
psiphon/common/burst_test.go

@@ -26,9 +26,9 @@ import (
 
 func TestBurstMonitoredConn(t *testing.T) {
 
-	burstDeadline := 100 * time.Millisecond
-	upstreamThresholdBytes := int64(100000)
-	downstreamThresholdBytes := int64(1000000)
+	upstreamTargetBytes := int64(100000)
+	downstreamTargetBytes := int64(1000000)
+	burstDeadline := 1 * time.Second
 
 	baseTime := time.Now()
 
@@ -37,10 +37,10 @@ func TestBurstMonitoredConn(t *testing.T) {
 	conn := NewBurstMonitoredConn(
 		dummy,
 		true,
+		upstreamTargetBytes,
 		burstDeadline,
-		upstreamThresholdBytes,
-		burstDeadline,
-		downstreamThresholdBytes)
+		downstreamTargetBytes,
+		burstDeadline)
 
 	// Simulate 128KB/s up, 1MB/s down; transmit >= min bytes in segments; sets "first" and "min"
 
@@ -48,14 +48,14 @@ func TestBurstMonitoredConn(t *testing.T) {
 
 	segments := 10
 
-	b := make([]byte, int(upstreamThresholdBytes)/segments)
+	b := make([]byte, int(upstreamTargetBytes)/segments)
 	firstReadStart := time.Now()
 	for i := 0; i < segments; i++ {
 		conn.Read(b)
 	}
 	firstReadEnd := time.Now()
 
-	b = make([]byte, int(downstreamThresholdBytes)/segments)
+	b = make([]byte, int(downstreamTargetBytes)/segments)
 	firstWriteStart := time.Now()
 	for i := 0; i < segments; i++ {
 		conn.Write(b)
@@ -84,11 +84,11 @@ func TestBurstMonitoredConn(t *testing.T) {
 	dummy.SetRateLimits(524288, 5242880)
 
 	maxReadStart := time.Now()
-	conn.Read(make([]byte, upstreamThresholdBytes))
+	conn.Read(make([]byte, upstreamTargetBytes))
 	maxReadEnd := time.Now()
 
 	maxWriteStart := time.Now()
-	conn.Write(make([]byte, downstreamThresholdBytes))
+	conn.Write(make([]byte, downstreamTargetBytes))
 	maxWriteEnd := time.Now()
 
 	time.Sleep(burstDeadline * 2)
@@ -98,11 +98,11 @@ func TestBurstMonitoredConn(t *testing.T) {
 	dummy.SetRateLimits(262144, 2097152)
 
 	lastReadStart := time.Now()
-	conn.Read(make([]byte, upstreamThresholdBytes))
+	conn.Read(make([]byte, upstreamTargetBytes))
 	lastReadEnd := time.Now()
 
 	lastWriteStart := time.Now()
-	conn.Write(make([]byte, downstreamThresholdBytes))
+	conn.Write(make([]byte, downstreamTargetBytes))
 	lastWriteEnd := time.Now()
 
 	time.Sleep(burstDeadline * 2)
@@ -135,35 +135,35 @@ func TestBurstMonitoredConn(t *testing.T) {
 	for name, expectedValue := range map[string]int64{
 		"burst_upstream_first_offset":     int64(firstReadStart.Sub(baseTime) / time.Millisecond),
 		"burst_upstream_first_duration":   int64(firstReadEnd.Sub(firstReadStart) / time.Millisecond),
-		"burst_upstream_first_bytes":      upstreamThresholdBytes,
+		"burst_upstream_first_bytes":      upstreamTargetBytes,
 		"burst_upstream_first_rate":       131072,
 		"burst_upstream_last_offset":      int64(lastReadStart.Sub(baseTime) / time.Millisecond),
 		"burst_upstream_last_duration":    int64(lastReadEnd.Sub(lastReadStart) / time.Millisecond),
-		"burst_upstream_last_bytes":       upstreamThresholdBytes,
+		"burst_upstream_last_bytes":       upstreamTargetBytes,
 		"burst_upstream_last_rate":        262144,
 		"burst_upstream_min_offset":       int64(firstReadStart.Sub(baseTime) / time.Millisecond),
 		"burst_upstream_min_duration":     int64(firstReadEnd.Sub(firstReadStart) / time.Millisecond),
-		"burst_upstream_min_bytes":        upstreamThresholdBytes,
+		"burst_upstream_min_bytes":        upstreamTargetBytes,
 		"burst_upstream_min_rate":         131072,
 		"burst_upstream_max_offset":       int64(maxReadStart.Sub(baseTime) / time.Millisecond),
 		"burst_upstream_max_duration":     int64(maxReadEnd.Sub(maxReadStart) / time.Millisecond),
-		"burst_upstream_max_bytes":        upstreamThresholdBytes,
+		"burst_upstream_max_bytes":        upstreamTargetBytes,
 		"burst_upstream_max_rate":         524288,
 		"burst_downstream_first_offset":   int64(firstWriteStart.Sub(baseTime) / time.Millisecond),
 		"burst_downstream_first_duration": int64(firstWriteEnd.Sub(firstWriteStart) / time.Millisecond),
-		"burst_downstream_first_bytes":    downstreamThresholdBytes,
+		"burst_downstream_first_bytes":    downstreamTargetBytes,
 		"burst_downstream_first_rate":     1048576,
 		"burst_downstream_last_offset":    int64(lastWriteStart.Sub(baseTime) / time.Millisecond),
 		"burst_downstream_last_duration":  int64(lastWriteEnd.Sub(lastWriteStart) / time.Millisecond),
-		"burst_downstream_last_bytes":     downstreamThresholdBytes,
+		"burst_downstream_last_bytes":     downstreamTargetBytes,
 		"burst_downstream_last_rate":      2097152,
 		"burst_downstream_min_offset":     int64(firstWriteStart.Sub(baseTime) / time.Millisecond),
 		"burst_downstream_min_duration":   int64(firstWriteEnd.Sub(firstWriteStart) / time.Millisecond),
-		"burst_downstream_min_bytes":      downstreamThresholdBytes,
+		"burst_downstream_min_bytes":      downstreamTargetBytes,
 		"burst_downstream_min_rate":       1048576,
 		"burst_downstream_max_offset":     int64(maxWriteStart.Sub(baseTime) / time.Millisecond),
 		"burst_downstream_max_duration":   int64(maxWriteEnd.Sub(maxWriteStart) / time.Millisecond),
-		"burst_downstream_max_bytes":      downstreamThresholdBytes,
+		"burst_downstream_max_bytes":      downstreamTargetBytes,
 		"burst_downstream_max_rate":       5242880,
 	} {
 		value, ok := logFields[name]

+ 12 - 12
psiphon/common/parameters/parameters.go

@@ -259,13 +259,13 @@ const (
 	ServerReplayTargetDownstreamBytes                = "ServerReplayTargetDownstreamBytes"
 	ServerReplayFailedCountThreshold                 = "ServerReplayFailedCountThreshold"
 	ServerBurstUpstreamDeadline                      = "ServerBurstUpstreamDeadline"
-	ServerBurstUpstreamThresholdBytes                = "ServerBurstUpstreamThresholdBytes"
+	ServerBurstUpstreamTargetBytes                   = "ServerBurstUpstreamTargetBytes"
 	ServerBurstDownstreamDeadline                    = "ServerBurstDownstreamDeadline"
-	ServerBurstDownstreamThresholdBytes              = "ServerBurstDownstreamThresholdBytes"
+	ServerBurstDownstreamTargetBytes                 = "ServerBurstDownstreamTargetBytes"
 	ClientBurstUpstreamDeadline                      = "ClientBurstUpstreamDeadline"
-	ClientBurstUpstreamThresholdBytes                = "ClientBurstUpstreamThresholdBytes"
+	ClientBurstUpstreamTargetBytes                   = "ClientBurstUpstreamTargetBytes"
 	ClientBurstDownstreamDeadline                    = "ClientBurstDownstreamDeadline"
-	ClientBurstDownstreamThresholdBytes              = "ClientBurstDownstreamThresholdBytes"
+	ClientBurstDownstreamTargetBytes                 = "ClientBurstDownstreamTargetBytes"
 )
 
 const (
@@ -544,14 +544,14 @@ var defaultParameters = map[string]struct {
 	ServerReplayTargetDownstreamBytes: {value: 0, minimum: 0, flags: serverSideOnly},
 	ServerReplayFailedCountThreshold:  {value: 0, minimum: 0, flags: serverSideOnly},
 
-	ServerBurstUpstreamDeadline:         {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
-	ServerBurstUpstreamThresholdBytes:   {value: 0, minimum: 0, flags: serverSideOnly},
-	ServerBurstDownstreamDeadline:       {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
-	ServerBurstDownstreamThresholdBytes: {value: 0, minimum: 0, flags: serverSideOnly},
-	ClientBurstUpstreamDeadline:         {value: time.Duration(0), minimum: time.Duration(0)},
-	ClientBurstUpstreamThresholdBytes:   {value: 0, minimum: 0},
-	ClientBurstDownstreamDeadline:       {value: time.Duration(0), minimum: time.Duration(0)},
-	ClientBurstDownstreamThresholdBytes: {value: 0, minimum: 0},
+	ServerBurstUpstreamTargetBytes:   {value: 0, minimum: 0, flags: serverSideOnly},
+	ServerBurstUpstreamDeadline:      {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
+	ServerBurstDownstreamTargetBytes: {value: 0, minimum: 0, flags: serverSideOnly},
+	ServerBurstDownstreamDeadline:    {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
+	ClientBurstUpstreamTargetBytes:   {value: 0, minimum: 0},
+	ClientBurstUpstreamDeadline:      {value: time.Duration(0), minimum: time.Duration(0)},
+	ClientBurstDownstreamTargetBytes: {value: 0, minimum: 0},
+	ClientBurstDownstreamDeadline:    {value: time.Duration(0), minimum: time.Duration(0)},
 }
 
 // IsServerSideOnly indicates if the parameter specified by name is used

+ 23 - 0
psiphon/config.go

@@ -541,6 +541,13 @@ type Config struct {
 	SelectRandomizedTLSProfileProbability *float64
 	NoDefaultTLSSessionIDProbability      *float64
 
+	// ClientBurstUpstreamTargetBytes and other burst metric fields are for
+	// testing purposes.
+	ClientBurstUpstreamTargetBytes            *int
+	ClientBurstUpstreamDeadlineMilliseconds   *int
+	ClientBurstDownstreamTargetBytes          *int
+	ClientBurstDownstreamDeadlineMilliseconds *int
+
 	// ApplicationParameters is for testing purposes.
 	ApplicationParameters parameters.KeyValues
 
@@ -1581,6 +1588,22 @@ func (config *Config) makeConfigParameters() map[string]interface{} {
 		applyParameters[parameters.NoDefaultTLSSessionIDProbability] = *config.NoDefaultTLSSessionIDProbability
 	}
 
+	if config.ClientBurstUpstreamTargetBytes != nil {
+		applyParameters[parameters.ClientBurstUpstreamTargetBytes] = *config.ClientBurstUpstreamTargetBytes
+	}
+
+	if config.ClientBurstUpstreamDeadlineMilliseconds != nil {
+		applyParameters[parameters.ClientBurstUpstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstUpstreamDeadlineMilliseconds)
+	}
+
+	if config.ClientBurstDownstreamTargetBytes != nil {
+		applyParameters[parameters.ClientBurstDownstreamTargetBytes] = *config.ClientBurstDownstreamTargetBytes
+	}
+
+	if config.ClientBurstDownstreamDeadlineMilliseconds != nil {
+		applyParameters[parameters.ClientBurstDownstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstDownstreamDeadlineMilliseconds)
+	}
+
 	if config.ApplicationParameters != nil {
 		applyParameters[parameters.ApplicationParameters] = config.ApplicationParameters
 	}

+ 4 - 4
psiphon/server/server_test.go

@@ -2098,13 +2098,13 @@ func paveTacticsConfigFile(
 	if doBurstMonitor {
 		burstParameters = `
           "ServerBurstUpstreamDeadline" : "100ms",
-          "ServerBurstUpstreamThresholdBytes" : 1000,
+          "ServerBurstUpstreamTargetBytes" : 1000,
           "ServerBurstDownstreamDeadline" : "100ms",
-          "ServerBurstDownstreamThresholdBytes" : 100000,
+          "ServerBurstDownstreamTargetBytes" : 100000,
           "ClientBurstUpstreamDeadline" : "100ms",
-          "ClientBurstUpstreamThresholdBytes" : 1000,
+          "ClientBurstUpstreamTargetBytes" : 1000,
           "ClientBurstDownstreamDeadline" : "100ms",
-          "ClientBurstDownstreamThresholdBytes" : 100000,
+          "ClientBurstDownstreamTargetBytes" : 100000,
 	`
 	}
 

+ 6 - 6
psiphon/server/tunnelServer.go

@@ -1376,19 +1376,19 @@ func (sshClient *sshClient) run(
 	}
 
 	if !p.IsNil() {
+		upstreamTargetBytes := int64(p.Int(parameters.ServerBurstUpstreamTargetBytes))
 		upstreamDeadline := p.Duration(parameters.ServerBurstUpstreamDeadline)
-		upstreamThresholdBytes := int64(p.Int(parameters.ServerBurstUpstreamThresholdBytes))
+		downstreamTargetBytes := int64(p.Int(parameters.ServerBurstUpstreamTargetBytes))
 		downstreamDeadline := p.Duration(parameters.ServerBurstUpstreamDeadline)
-		downstreamThresholdBytes := int64(p.Int(parameters.ServerBurstUpstreamThresholdBytes))
 
-		if (upstreamDeadline != 0 && upstreamThresholdBytes != 0) ||
-			(downstreamDeadline != 0 && downstreamThresholdBytes != 0) {
+		if (upstreamDeadline != 0 && upstreamTargetBytes != 0) ||
+			(downstreamDeadline != 0 && downstreamTargetBytes != 0) {
 
 			burstConn = common.NewBurstMonitoredConn(
 				conn,
 				true,
-				upstreamDeadline, upstreamThresholdBytes,
-				downstreamDeadline, downstreamThresholdBytes)
+				upstreamTargetBytes, upstreamDeadline,
+				downstreamTargetBytes, downstreamDeadline)
 			conn = burstConn
 		}
 	}

+ 4 - 4
psiphon/tunnel.go

@@ -644,10 +644,10 @@ func dialTunnel(
 	livenessTestMaxUpstreamBytes := p.Int(parameters.LivenessTestMaxUpstreamBytes)
 	livenessTestMinDownstreamBytes := p.Int(parameters.LivenessTestMinDownstreamBytes)
 	livenessTestMaxDownstreamBytes := p.Int(parameters.LivenessTestMaxDownstreamBytes)
+	burstUpstreamTargetBytes := int64(p.Int(parameters.ClientBurstUpstreamTargetBytes))
 	burstUpstreamDeadline := p.Duration(parameters.ClientBurstUpstreamDeadline)
-	burstUpstreamThresholdBytes := int64(p.Int(parameters.ClientBurstUpstreamThresholdBytes))
+	burstDownstreamTargetBytes := int64(p.Int(parameters.ClientBurstDownstreamTargetBytes))
 	burstDownstreamDeadline := p.Duration(parameters.ClientBurstDownstreamDeadline)
-	burstDownstreamThresholdBytes := int64(p.Int(parameters.ClientBurstDownstreamThresholdBytes))
 	p.Close()
 
 	// Ensure that, unless the base context is cancelled, any replayed dial
@@ -791,8 +791,8 @@ func dialTunnel(
 	monitoredConn := common.NewBurstMonitoredConn(
 		dialConn,
 		false,
-		burstUpstreamDeadline, burstUpstreamThresholdBytes,
-		burstDownstreamDeadline, burstDownstreamThresholdBytes)
+		burstUpstreamTargetBytes, burstUpstreamDeadline,
+		burstDownstreamTargetBytes, burstDownstreamDeadline)
 
 	// Apply throttling (if configured)
 	throttledConn := common.NewThrottledConn(