blob: 45910659880c2cb3a7e2a701c722499a880c48b8 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/congestion_control/prr_sender.h"
6
7#include <algorithm>
8
9#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
10#include "net/third_party/quiche/src/quic/core/quic_constants.h"
11#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
12
13namespace quic {
14namespace test {
15
16namespace {
17// Constant based on TCP defaults.
18const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
19} // namespace
20
21class PrrSenderTest : public QuicTest {};
22
23TEST_F(PrrSenderTest, SingleLossResultsInSendOnEveryOtherAck) {
24 PrrSender prr;
25 QuicPacketCount num_packets_in_flight = 50;
26 QuicByteCount bytes_in_flight = num_packets_in_flight * kMaxSegmentSize;
27 const QuicPacketCount ssthresh_after_loss = num_packets_in_flight / 2;
28 const QuicByteCount congestion_window = ssthresh_after_loss * kMaxSegmentSize;
29
30 prr.OnPacketLost(bytes_in_flight);
31 // Ack a packet. PRR allows one packet to leave immediately.
32 prr.OnPacketAcked(kMaxSegmentSize);
33 bytes_in_flight -= kMaxSegmentSize;
34 EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
35 ssthresh_after_loss * kMaxSegmentSize));
36 // Send retransmission.
37 prr.OnPacketSent(kMaxSegmentSize);
38 // PRR shouldn't allow sending any more packets.
39 EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
40 ssthresh_after_loss * kMaxSegmentSize));
41
42 // One packet is lost, and one ack was consumed above. PRR now paces
43 // transmissions through the remaining 48 acks. PRR will alternatively
44 // disallow and allow a packet to be sent in response to an ack.
45 for (uint64_t i = 0; i < ssthresh_after_loss - 1; ++i) {
46 // Ack a packet. PRR shouldn't allow sending a packet in response.
47 prr.OnPacketAcked(kMaxSegmentSize);
48 bytes_in_flight -= kMaxSegmentSize;
49 EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
50 ssthresh_after_loss * kMaxSegmentSize));
51 // Ack another packet. PRR should now allow sending a packet in response.
52 prr.OnPacketAcked(kMaxSegmentSize);
53 bytes_in_flight -= kMaxSegmentSize;
54 EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
55 ssthresh_after_loss * kMaxSegmentSize));
56 // Send a packet in response.
57 prr.OnPacketSent(kMaxSegmentSize);
58 bytes_in_flight += kMaxSegmentSize;
59 }
60
61 // Since bytes_in_flight is now equal to congestion_window, PRR now maintains
62 // packet conservation, allowing one packet to be sent in response to an ack.
63 EXPECT_EQ(congestion_window, bytes_in_flight);
64 for (int i = 0; i < 10; ++i) {
65 // Ack a packet.
66 prr.OnPacketAcked(kMaxSegmentSize);
67 bytes_in_flight -= kMaxSegmentSize;
68 EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
69 ssthresh_after_loss * kMaxSegmentSize));
70 // Send a packet in response, since PRR allows it.
71 prr.OnPacketSent(kMaxSegmentSize);
72 bytes_in_flight += kMaxSegmentSize;
73
74 // Since bytes_in_flight is equal to the congestion_window,
75 // PRR disallows sending.
76 EXPECT_EQ(congestion_window, bytes_in_flight);
77 EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
78 ssthresh_after_loss * kMaxSegmentSize));
79 }
80}
81
82TEST_F(PrrSenderTest, BurstLossResultsInSlowStart) {
83 PrrSender prr;
84 QuicByteCount bytes_in_flight = 20 * kMaxSegmentSize;
85 const QuicPacketCount num_packets_lost = 13;
86 const QuicPacketCount ssthresh_after_loss = 10;
87 const QuicByteCount congestion_window = ssthresh_after_loss * kMaxSegmentSize;
88
89 // Lose 13 packets.
90 bytes_in_flight -= num_packets_lost * kMaxSegmentSize;
91 prr.OnPacketLost(bytes_in_flight);
92
93 // PRR-SSRB will allow the following 3 acks to send up to 2 packets.
94 for (int i = 0; i < 3; ++i) {
95 prr.OnPacketAcked(kMaxSegmentSize);
96 bytes_in_flight -= kMaxSegmentSize;
97 // PRR-SSRB should allow two packets to be sent.
98 for (int j = 0; j < 2; ++j) {
99 EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
100 ssthresh_after_loss * kMaxSegmentSize));
101 // Send a packet in response.
102 prr.OnPacketSent(kMaxSegmentSize);
103 bytes_in_flight += kMaxSegmentSize;
104 }
105 // PRR should allow no more than 2 packets in response to an ack.
106 EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
107 ssthresh_after_loss * kMaxSegmentSize));
108 }
109
110 // Out of SSRB mode, PRR allows one send in response to each ack.
111 for (int i = 0; i < 10; ++i) {
112 prr.OnPacketAcked(kMaxSegmentSize);
113 bytes_in_flight -= kMaxSegmentSize;
114 EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
115 ssthresh_after_loss * kMaxSegmentSize));
116 // Send a packet in response.
117 prr.OnPacketSent(kMaxSegmentSize);
118 bytes_in_flight += kMaxSegmentSize;
119 }
120}
121
122} // namespace test
123} // namespace quic