1 // 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.
5 #include "net/quic/congestion_control/prr_sender.h"
9 #include "base/logging.h"
10 #include "net/quic/crypto/crypto_protocol.h"
11 #include "net/quic/quic_bandwidth.h"
12 #include "net/quic/quic_protocol.h"
13 #include "testing/gtest/include/gtest/gtest.h"
19 // Constant based on TCP defaults.
20 const QuicByteCount kMaxSegmentSize
= kDefaultTCPMSS
;
23 class PrrSenderTest
: public ::testing::Test
{};
25 TEST_F(PrrSenderTest
, SingleLossResultsInSendOnEveryOtherAck
) {
27 QuicPacketCount num_packets_in_flight
= 50;
28 QuicByteCount bytes_in_flight
= num_packets_in_flight
* kMaxSegmentSize
;
29 const QuicPacketCount ssthresh_after_loss
= num_packets_in_flight
/ 2;
30 const QuicByteCount congestion_window
= ssthresh_after_loss
* kMaxSegmentSize
;
32 prr
.OnPacketLost(bytes_in_flight
);
33 // Ack a packet. PRR allows one packet to leave immediately.
34 prr
.OnPacketAcked(kMaxSegmentSize
);
35 bytes_in_flight
-= kMaxSegmentSize
;
36 EXPECT_EQ(QuicTime::Delta::Zero(),
37 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
38 ssthresh_after_loss
* kMaxSegmentSize
));
39 // Send retransmission.
40 prr
.OnPacketSent(kMaxSegmentSize
);
41 // PRR shouldn't allow sending any more packets.
42 EXPECT_EQ(QuicTime::Delta::Infinite(),
43 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
44 ssthresh_after_loss
* kMaxSegmentSize
));
46 // One packet is lost, and one ack was consumed above. PRR now paces
47 // transmissions through the remaining 48 acks. PRR will alternatively
48 // disallow and allow a packet to be sent in response to an ack.
49 for (uint64 i
= 0; i
< ssthresh_after_loss
- 1; ++i
) {
50 // Ack a packet. PRR shouldn't allow sending a packet in response.
51 prr
.OnPacketAcked(kMaxSegmentSize
);
52 bytes_in_flight
-= kMaxSegmentSize
;
53 EXPECT_EQ(QuicTime::Delta::Infinite(),
54 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
55 ssthresh_after_loss
* kMaxSegmentSize
));
56 // Ack another packet. PRR should now allow sending a packet in response.
57 prr
.OnPacketAcked(kMaxSegmentSize
);
58 bytes_in_flight
-= kMaxSegmentSize
;
59 EXPECT_EQ(QuicTime::Delta::Zero(),
60 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
61 ssthresh_after_loss
* kMaxSegmentSize
));
62 // Send a packet in response.
63 prr
.OnPacketSent(kMaxSegmentSize
);
64 bytes_in_flight
+= kMaxSegmentSize
;
67 // Since bytes_in_flight is now equal to congestion_window, PRR now maintains
68 // packet conservation, allowing one packet to be sent in response to an ack.
69 EXPECT_EQ(congestion_window
, bytes_in_flight
);
70 for (int i
= 0; i
< 10; ++i
) {
72 prr
.OnPacketAcked(kMaxSegmentSize
);
73 bytes_in_flight
-= kMaxSegmentSize
;
74 EXPECT_EQ(QuicTime::Delta::Zero(),
75 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
76 ssthresh_after_loss
* kMaxSegmentSize
));
77 // Send a packet in response, since PRR allows it.
78 prr
.OnPacketSent(kMaxSegmentSize
);
79 bytes_in_flight
+= kMaxSegmentSize
;
81 // Since bytes_in_flight is equal to the congestion_window,
82 // PRR disallows sending.
83 EXPECT_EQ(congestion_window
, bytes_in_flight
);
84 EXPECT_EQ(QuicTime::Delta::Infinite(),
85 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
86 ssthresh_after_loss
* kMaxSegmentSize
));
90 TEST_F(PrrSenderTest
, BurstLossResultsInSlowStart
) {
92 QuicByteCount bytes_in_flight
= 20 * kMaxSegmentSize
;
93 const QuicPacketCount num_packets_lost
= 13;
94 const QuicPacketCount ssthresh_after_loss
= 10;
95 const QuicByteCount congestion_window
= ssthresh_after_loss
* kMaxSegmentSize
;
98 bytes_in_flight
-= num_packets_lost
* kMaxSegmentSize
;
99 prr
.OnPacketLost(bytes_in_flight
);
101 // PRR-SSRB will allow the following 3 acks to send up to 2 packets.
102 for (int i
= 0; i
< 3; ++i
) {
103 prr
.OnPacketAcked(kMaxSegmentSize
);
104 bytes_in_flight
-= kMaxSegmentSize
;
105 // PRR-SSRB should allow two packets to be sent.
106 for (int j
= 0; j
< 2; ++j
) {
107 EXPECT_EQ(QuicTime::Delta::Zero(),
108 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
109 ssthresh_after_loss
* kMaxSegmentSize
));
110 // Send a packet in response.
111 prr
.OnPacketSent(kMaxSegmentSize
);
112 bytes_in_flight
+= kMaxSegmentSize
;
114 // PRR should allow no more than 2 packets in response to an ack.
115 EXPECT_EQ(QuicTime::Delta::Infinite(),
116 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
117 ssthresh_after_loss
* kMaxSegmentSize
));
120 // Out of SSRB mode, PRR allows one send in response to each ack.
121 for (int i
= 0; i
< 10; ++i
) {
122 prr
.OnPacketAcked(kMaxSegmentSize
);
123 bytes_in_flight
-= kMaxSegmentSize
;
124 EXPECT_EQ(QuicTime::Delta::Zero(),
125 prr
.TimeUntilSend(congestion_window
, bytes_in_flight
,
126 ssthresh_after_loss
* kMaxSegmentSize
));
127 // Send a packet in response.
128 prr
.OnPacketSent(kMaxSegmentSize
);
129 bytes_in_flight
+= kMaxSegmentSize
;