golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/rtt_test.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  func TestRTTMinRTT(t *testing.T) {
    15  	var (
    16  		handshakeConfirmed = false
    17  		ackDelay           = 0 * time.Millisecond
    18  		maxAckDelay        = 25 * time.Millisecond
    19  		now                = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
    20  	)
    21  	rtt := &rttState{}
    22  	rtt.init()
    23  
    24  	// "min_rtt MUST be set to the latest_rtt on the first RTT sample."
    25  	// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.2-2
    26  	rtt.updateSample(now, handshakeConfirmed, initialSpace, 10*time.Millisecond, ackDelay, maxAckDelay)
    27  	if got, want := rtt.latestRTT, 10*time.Millisecond; got != want {
    28  		t.Errorf("on first sample: latest_rtt = %v, want %v", got, want)
    29  	}
    30  	if got, want := rtt.minRTT, 10*time.Millisecond; got != want {
    31  		t.Errorf("on first sample: min_rtt = %v, want %v", got, want)
    32  	}
    33  
    34  	// "min_rtt MUST be set to the lesser of min_rtt and latest_rtt [...]
    35  	// on all other samples."
    36  	rtt.updateSample(now, handshakeConfirmed, initialSpace, 20*time.Millisecond, ackDelay, maxAckDelay)
    37  	if got, want := rtt.latestRTT, 20*time.Millisecond; got != want {
    38  		t.Errorf("on increasing sample: latest_rtt = %v, want %v", got, want)
    39  	}
    40  	if got, want := rtt.minRTT, 10*time.Millisecond; got != want {
    41  		t.Errorf("on increasing sample: min_rtt = %v, want %v (no change)", got, want)
    42  	}
    43  
    44  	rtt.updateSample(now, handshakeConfirmed, initialSpace, 5*time.Millisecond, ackDelay, maxAckDelay)
    45  	if got, want := rtt.latestRTT, 5*time.Millisecond; got != want {
    46  		t.Errorf("on new minimum: latest_rtt = %v, want %v", got, want)
    47  	}
    48  	if got, want := rtt.minRTT, 5*time.Millisecond; got != want {
    49  		t.Errorf("on new minimum: min_rtt = %v, want %v", got, want)
    50  	}
    51  
    52  	// "Endpoints SHOULD set the min_rtt to the newest RTT sample
    53  	// after persistent congestion is established."
    54  	// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.2-5
    55  	rtt.updateSample(now, handshakeConfirmed, initialSpace, 15*time.Millisecond, ackDelay, maxAckDelay)
    56  	if got, want := rtt.latestRTT, 15*time.Millisecond; got != want {
    57  		t.Errorf("on increasing sample: latest_rtt = %v, want %v", got, want)
    58  	}
    59  	if got, want := rtt.minRTT, 5*time.Millisecond; got != want {
    60  		t.Errorf("on increasing sample: min_rtt = %v, want %v (no change)", got, want)
    61  	}
    62  	rtt.establishPersistentCongestion()
    63  	if got, want := rtt.minRTT, 15*time.Millisecond; got != want {
    64  		t.Errorf("after persistent congestion: min_rtt = %v, want %v", got, want)
    65  	}
    66  }
    67  
    68  func TestRTTInitialRTT(t *testing.T) {
    69  	var (
    70  		handshakeConfirmed = false
    71  		ackDelay           = 0 * time.Millisecond
    72  		maxAckDelay        = 25 * time.Millisecond
    73  		now                = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
    74  	)
    75  	rtt := &rttState{}
    76  	rtt.init()
    77  
    78  	// "When no previous RTT is available,
    79  	// the initial RTT SHOULD be set to 333 milliseconds."
    80  	// https://www.rfc-editor.org/rfc/rfc9002#section-6.2.2-1
    81  	if got, want := rtt.smoothedRTT, 333*time.Millisecond; got != want {
    82  		t.Errorf("initial smoothed_rtt = %v, want %v", got, want)
    83  	}
    84  	if got, want := rtt.rttvar, 333*time.Millisecond/2; got != want {
    85  		t.Errorf("initial rttvar = %v, want %v", got, want)
    86  	}
    87  
    88  	rtt.updateSample(now, handshakeConfirmed, initialSpace, 10*time.Millisecond, ackDelay, maxAckDelay)
    89  	smoothedRTT := 10 * time.Millisecond
    90  	if got, want := rtt.smoothedRTT, smoothedRTT; got != want {
    91  		t.Errorf("after first rtt sample of 10ms, smoothed_rtt = %v, want %v", got, want)
    92  	}
    93  	rttvar := 5 * time.Millisecond
    94  	if got, want := rtt.rttvar, rttvar; got != want {
    95  		t.Errorf("after first rtt sample of 10ms, rttvar = %v, want %v", got, want)
    96  	}
    97  
    98  	// "[...] MAY ignore the acknowledgment delay for Initial packets [...]"
    99  	// https://www.rfc-editor.org/rfc/rfc9002#section-5.3-7.1
   100  	ackDelay = 1 * time.Millisecond
   101  	rtt.updateSample(now, handshakeConfirmed, initialSpace, 10*time.Millisecond, ackDelay, maxAckDelay)
   102  	adjustedRTT := 10 * time.Millisecond
   103  	smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8
   104  	if got, want := rtt.smoothedRTT, smoothedRTT; got != want {
   105  		t.Errorf("smoothed_rtt = %v, want %v", got, want)
   106  	}
   107  	rttvarSample := abs(smoothedRTT - adjustedRTT)
   108  	rttvar = (3*rttvar + rttvarSample) / 4
   109  	if got, want := rtt.rttvar, rttvar; got != want {
   110  		t.Errorf("rttvar = %v, want %v", got, want)
   111  	}
   112  
   113  	// "[...] SHOULD ignore the peer's max_ack_delay until the handshake is confirmed [...]"
   114  	// https://www.rfc-editor.org/rfc/rfc9002#section-5.3-7.2
   115  	ackDelay = 30 * time.Millisecond
   116  	maxAckDelay = 25 * time.Millisecond
   117  	rtt.updateSample(now, handshakeConfirmed, handshakeSpace, 40*time.Millisecond, ackDelay, maxAckDelay)
   118  	adjustedRTT = 10 * time.Millisecond // latest_rtt (40ms) - ack_delay (30ms)
   119  	smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8
   120  	if got, want := rtt.smoothedRTT, smoothedRTT; got != want {
   121  		t.Errorf("smoothed_rtt = %v, want %v", got, want)
   122  	}
   123  	rttvarSample = abs(smoothedRTT - adjustedRTT)
   124  	rttvar = (3*rttvar + rttvarSample) / 4
   125  	if got, want := rtt.rttvar, rttvar; got != want {
   126  		t.Errorf("rttvar = %v, want %v", got, want)
   127  	}
   128  
   129  	// "[...] MUST use the lesser of the acknowledgment delay and
   130  	// the peer's max_ack_delay after the handshake is confirmed [...]"
   131  	// https://www.rfc-editor.org/rfc/rfc9002#section-5.3-7.3
   132  	ackDelay = 30 * time.Millisecond
   133  	maxAckDelay = 25 * time.Millisecond
   134  	handshakeConfirmed = true
   135  	rtt.updateSample(now, handshakeConfirmed, handshakeSpace, 40*time.Millisecond, ackDelay, maxAckDelay)
   136  	adjustedRTT = 15 * time.Millisecond // latest_rtt (40ms) - max_ack_delay (25ms)
   137  	rttvarSample = abs(smoothedRTT - adjustedRTT)
   138  	rttvar = (3*rttvar + rttvarSample) / 4
   139  	if got, want := rtt.rttvar, rttvar; got != want {
   140  		t.Errorf("rttvar = %v, want %v", got, want)
   141  	}
   142  	smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8
   143  	if got, want := rtt.smoothedRTT, smoothedRTT; got != want {
   144  		t.Errorf("smoothed_rtt = %v, want %v", got, want)
   145  	}
   146  
   147  	// "[...] MUST NOT subtract the acknowledgment delay from
   148  	// the RTT sample if the resulting value is smaller than the min_rtt."
   149  	// https://www.rfc-editor.org/rfc/rfc9002#section-5.3-7.4
   150  	ackDelay = 25 * time.Millisecond
   151  	maxAckDelay = 25 * time.Millisecond
   152  	handshakeConfirmed = true
   153  	rtt.updateSample(now, handshakeConfirmed, handshakeSpace, 30*time.Millisecond, ackDelay, maxAckDelay)
   154  	if got, want := rtt.minRTT, 10*time.Millisecond; got != want {
   155  		t.Errorf("min_rtt = %v, want %v", got, want)
   156  	}
   157  	// latest_rtt (30ms) - ack_delay (25ms) = 5ms, which is less than min_rtt (10ms)
   158  	adjustedRTT = 30 * time.Millisecond // latest_rtt
   159  	rttvarSample = abs(smoothedRTT - adjustedRTT)
   160  	rttvar = (3*rttvar + rttvarSample) / 4
   161  	if got, want := rtt.rttvar, rttvar; got != want {
   162  		t.Errorf("rttvar = %v, want %v", got, want)
   163  	}
   164  	smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8
   165  	if got, want := rtt.smoothedRTT, smoothedRTT; got != want {
   166  		t.Errorf("smoothed_rtt = %v, want %v", got, want)
   167  	}
   168  }