blob: 3d40e0a2217cf7816a234d5cbfee99dc480eff23 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2016 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/bbr_sender.h"
6
7#include <algorithm>
8#include <map>
9#include <memory>
10
11#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
12#include "net/third_party/quiche/src/quic/core/quic_packets.h"
13#include "net/third_party/quiche/src/quic/core/quic_utils.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
17#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
18#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
19#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
20#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
21#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
22#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
23#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
24#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
25
wub967ba572019-04-01 09:27:52 -070026using testing::AllOf;
27using testing::Ge;
28using testing::Le;
29
QUICHE teama6ef0a62019-03-07 20:34:33 -050030namespace quic {
31namespace test {
32
33// Use the initial CWND of 10, as 32 is too much for the test network.
34const uint32_t kInitialCongestionWindowPackets = 10;
35const uint32_t kDefaultWindowTCP =
36 kInitialCongestionWindowPackets * kDefaultTCPMSS;
37
38// Test network parameters. Here, the topology of the network is:
39//
40// BBR sender
41// |
42// | <-- local link (10 Mbps, 2 ms delay)
43// |
44// Network switch
45// * <-- the bottleneck queue in the direction
46// | of the receiver
47// |
48// | <-- test link (4 Mbps, 30 ms delay)
49// |
50// |
51// Receiver
52//
53// The reason the bandwidths chosen are relatively low is the fact that the
54// connection simulator uses QuicTime for its internal clock, and as such has
55// the granularity of 1us, meaning that at bandwidth higher than 20 Mbps the
56// packets can start to land on the same timestamp.
57const QuicBandwidth kTestLinkBandwidth =
58 QuicBandwidth::FromKBitsPerSecond(4000);
59const QuicBandwidth kLocalLinkBandwidth =
60 QuicBandwidth::FromKBitsPerSecond(10000);
61const QuicTime::Delta kTestPropagationDelay =
62 QuicTime::Delta::FromMilliseconds(30);
63const QuicTime::Delta kLocalPropagationDelay =
64 QuicTime::Delta::FromMilliseconds(2);
65const QuicTime::Delta kTestTransferTime =
dschinazi66dea072019-04-09 11:41:06 -070066 kTestLinkBandwidth.TransferTime(kMaxOutgoingPacketSize) +
67 kLocalLinkBandwidth.TransferTime(kMaxOutgoingPacketSize);
QUICHE teama6ef0a62019-03-07 20:34:33 -050068const QuicTime::Delta kTestRtt =
69 (kTestPropagationDelay + kLocalPropagationDelay + kTestTransferTime) * 2;
70const QuicByteCount kTestBdp = kTestRtt * kTestLinkBandwidth;
71
72class BbrSenderTest : public QuicTest {
73 protected:
74 BbrSenderTest()
75 : simulator_(),
76 bbr_sender_(&simulator_,
77 "BBR sender",
78 "Receiver",
79 Perspective::IS_CLIENT,
80 /*connection_id=*/TestConnectionId(42)),
81 competing_sender_(&simulator_,
82 "Competing sender",
83 "Competing receiver",
84 Perspective::IS_CLIENT,
85 /*connection_id=*/TestConnectionId(43)),
86 receiver_(&simulator_,
87 "Receiver",
88 "BBR sender",
89 Perspective::IS_SERVER,
90 /*connection_id=*/TestConnectionId(42)),
91 competing_receiver_(&simulator_,
92 "Competing receiver",
93 "Competing sender",
94 Perspective::IS_SERVER,
95 /*connection_id=*/TestConnectionId(43)),
96 receiver_multiplexer_("Receiver multiplexer",
97 {&receiver_, &competing_receiver_}) {
98 rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats();
99 sender_ = SetupBbrSender(&bbr_sender_);
100
101 clock_ = simulator_.GetClock();
102 simulator_.set_random_generator(&random_);
103
104 uint64_t seed = QuicRandom::GetInstance()->RandUint64();
105 random_.set_seed(seed);
106 QUIC_LOG(INFO) << "BbrSenderTest simulator set up. Seed: " << seed;
107 }
108
109 simulator::Simulator simulator_;
110 simulator::QuicEndpoint bbr_sender_;
111 simulator::QuicEndpoint competing_sender_;
112 simulator::QuicEndpoint receiver_;
113 simulator::QuicEndpoint competing_receiver_;
114 simulator::QuicEndpointMultiplexer receiver_multiplexer_;
115 std::unique_ptr<simulator::Switch> switch_;
116 std::unique_ptr<simulator::SymmetricLink> bbr_sender_link_;
117 std::unique_ptr<simulator::SymmetricLink> competing_sender_link_;
118 std::unique_ptr<simulator::SymmetricLink> receiver_link_;
119
120 SimpleRandom random_;
121
122 // Owned by different components of the connection.
123 const QuicClock* clock_;
124 const RttStats* rtt_stats_;
125 BbrSender* sender_;
126
127 // Enables BBR on |endpoint| and returns the associated BBR congestion
128 // controller.
129 BbrSender* SetupBbrSender(simulator::QuicEndpoint* endpoint) {
130 const RttStats* rtt_stats =
131 endpoint->connection()->sent_packet_manager().GetRttStats();
132 // Ownership of the sender will be overtaken by the endpoint.
133 BbrSender* sender = new BbrSender(
wub967ba572019-04-01 09:27:52 -0700134 endpoint->connection()->clock()->Now(), rtt_stats,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 QuicSentPacketManagerPeer::GetUnackedPacketMap(
136 QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
137 kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets,
wub967ba572019-04-01 09:27:52 -0700138 &random_, QuicConnectionPeer::GetStats(endpoint->connection()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
140 endpoint->RecordTrace();
141 return sender;
142 }
143
144 // Creates a default setup, which is a network with a bottleneck between the
145 // receiver and the switch. The switch has the buffers four times larger than
146 // the bottleneck BDP, which should guarantee a lack of losses.
147 void CreateDefaultSetup() {
148 switch_ = QuicMakeUnique<simulator::Switch>(&simulator_, "Switch", 8,
149 2 * kTestBdp);
150 bbr_sender_link_ = QuicMakeUnique<simulator::SymmetricLink>(
151 &bbr_sender_, switch_->port(1), kLocalLinkBandwidth,
152 kLocalPropagationDelay);
153 receiver_link_ = QuicMakeUnique<simulator::SymmetricLink>(
154 &receiver_, switch_->port(2), kTestLinkBandwidth,
155 kTestPropagationDelay);
156 }
157
158 // Same as the default setup, except the buffer now is half of the BDP.
159 void CreateSmallBufferSetup() {
160 switch_ = QuicMakeUnique<simulator::Switch>(&simulator_, "Switch", 8,
161 0.5 * kTestBdp);
162 bbr_sender_link_ = QuicMakeUnique<simulator::SymmetricLink>(
163 &bbr_sender_, switch_->port(1), kLocalLinkBandwidth,
164 kTestPropagationDelay);
165 receiver_link_ = QuicMakeUnique<simulator::SymmetricLink>(
166 &receiver_, switch_->port(2), kTestLinkBandwidth,
167 kTestPropagationDelay);
168 }
169
170 // Creates the variation of the default setup in which there is another sender
171 // that competes for the same bottleneck link.
172 void CreateCompetitionSetup() {
173 switch_ = QuicMakeUnique<simulator::Switch>(&simulator_, "Switch", 8,
174 2 * kTestBdp);
175
176 // Add a small offset to the competing link in order to avoid
177 // synchronization effects.
178 const QuicTime::Delta small_offset = QuicTime::Delta::FromMicroseconds(3);
179 bbr_sender_link_ = QuicMakeUnique<simulator::SymmetricLink>(
180 &bbr_sender_, switch_->port(1), kLocalLinkBandwidth,
181 kLocalPropagationDelay);
182 competing_sender_link_ = QuicMakeUnique<simulator::SymmetricLink>(
183 &competing_sender_, switch_->port(3), kLocalLinkBandwidth,
184 kLocalPropagationDelay + small_offset);
185 receiver_link_ = QuicMakeUnique<simulator::SymmetricLink>(
186 &receiver_multiplexer_, switch_->port(2), kTestLinkBandwidth,
187 kTestPropagationDelay);
188 }
189
190 // Creates a BBR vs BBR competition setup.
191 void CreateBbrVsBbrSetup() {
192 SetupBbrSender(&competing_sender_);
193 CreateCompetitionSetup();
194 }
195
196 void EnableAggregation(QuicByteCount aggregation_bytes,
197 QuicTime::Delta aggregation_timeout) {
198 // Enable aggregation on the path from the receiver to the sender.
199 switch_->port_queue(1)->EnableAggregation(aggregation_bytes,
200 aggregation_timeout);
201 }
202
203 void DoSimpleTransfer(QuicByteCount transfer_size, QuicTime::Delta deadline) {
204 bbr_sender_.AddBytesToTransfer(transfer_size);
205 // TODO(vasilvv): consider rewriting this to run until the receiver actually
206 // receives the intended amount of bytes.
207 bool simulator_result = simulator_.RunUntilOrTimeout(
208 [this]() { return bbr_sender_.bytes_to_transfer() == 0; }, deadline);
209 EXPECT_TRUE(simulator_result)
210 << "Simple transfer failed. Bytes remaining: "
211 << bbr_sender_.bytes_to_transfer();
212 QUIC_LOG(INFO) << "Simple transfer state: " << sender_->ExportDebugState();
213 }
214
215 // Drive the simulator by sending enough data to enter PROBE_BW.
216 void DriveOutOfStartup() {
217 ASSERT_FALSE(sender_->ExportDebugState().is_at_full_bandwidth);
218 DoSimpleTransfer(1024 * 1024, QuicTime::Delta::FromSeconds(15));
219 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
220 ExpectApproxEq(kTestLinkBandwidth,
221 sender_->ExportDebugState().max_bandwidth, 0.02f);
222 }
223
224 // Send |bytes|-sized bursts of data |number_of_bursts| times, waiting for
225 // |wait_time| between each burst.
226 void SendBursts(size_t number_of_bursts,
227 QuicByteCount bytes,
228 QuicTime::Delta wait_time) {
229 ASSERT_EQ(0u, bbr_sender_.bytes_to_transfer());
230 for (size_t i = 0; i < number_of_bursts; i++) {
231 bbr_sender_.AddBytesToTransfer(bytes);
232
233 // Transfer data and wait for three seconds between each transfer.
234 simulator_.RunFor(wait_time);
235
236 // Ensure the connection did not time out.
237 ASSERT_TRUE(bbr_sender_.connection()->connected());
238 ASSERT_TRUE(receiver_.connection()->connected());
239 }
240
241 simulator_.RunFor(wait_time + kTestRtt);
242 ASSERT_EQ(0u, bbr_sender_.bytes_to_transfer());
243 }
244
245 void SetConnectionOption(QuicTag option) {
246 QuicConfig config;
247 QuicTagVector options;
248 options.push_back(option);
249 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
250 sender_->SetFromConfig(config, Perspective::IS_SERVER);
251 }
252};
253
254TEST_F(BbrSenderTest, SetInitialCongestionWindow) {
255 EXPECT_NE(3u * kDefaultTCPMSS, sender_->GetCongestionWindow());
256 sender_->SetInitialCongestionWindowInPackets(3);
257 EXPECT_EQ(3u * kDefaultTCPMSS, sender_->GetCongestionWindow());
258}
259
260// Test a simple long data transfer in the default setup.
261TEST_F(BbrSenderTest, SimpleTransfer) {
262 // Disable Ack Decimation on the receiver, because it can increase srtt.
263 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
264 CreateDefaultSetup();
265
266 // At startup make sure we are at the default.
267 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
268 // At startup make sure we can send.
269 EXPECT_TRUE(sender_->CanSend(0));
270 // And that window is un-affected.
271 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
272
273 // Verify that Sender is in slow start.
274 EXPECT_TRUE(sender_->InSlowStart());
275
276 // Verify that pacing rate is based on the initial RTT.
277 QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
278 2.885 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
279 ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
280 sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
281
282 ASSERT_GE(kTestBdp, kDefaultWindowTCP + kDefaultTCPMSS);
283
284 DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(30));
285 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
286 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
287 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
288
289 // The margin here is quite high, since there exists a possibility that the
290 // connection just exited high gain cycle.
291 ExpectApproxEq(kTestRtt, rtt_stats_->smoothed_rtt(), 0.2f);
292}
293
294// Test a simple transfer in a situation when the buffer is less than BDP.
295TEST_F(BbrSenderTest, SimpleTransferSmallBuffer) {
296 CreateSmallBufferSetup();
297
298 DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(30));
299 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
300 ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
301 0.01f);
302 EXPECT_GE(bbr_sender_.connection()->GetStats().packets_lost, 0u);
303 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
304}
305
306TEST_F(BbrSenderTest, SimpleTransferEarlyPacketLoss) {
307 SetQuicReloadableFlag(quic_bbr_no_bytes_acked_in_startup_recovery, true);
308 // Enable rate based startup so the recovery window doesn't hide the true
309 // congestion_window_ in GetCongestionWindow().
310 SetConnectionOption(kBBS1);
311 // Disable Ack Decimation on the receiver, because it can increase srtt.
312 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
313 CreateDefaultSetup();
314
315 // At startup make sure we are at the default.
316 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
317 // Verify that Sender is in slow start.
318 EXPECT_TRUE(sender_->InSlowStart());
319 // At startup make sure we can send.
320 EXPECT_TRUE(sender_->CanSend(0));
321 // And that window is un-affected.
322 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
323
324 // Transfer 12MB.
325 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
326 // Drop the first packet.
327 receiver_.DropNextIncomingPacket();
328 bool simulator_result = simulator_.RunUntilOrTimeout(
329 [this]() {
330 if (sender_->InRecovery()) {
331 // Two packets are acked before the first is declared lost.
332 EXPECT_LE(sender_->GetCongestionWindow(),
333 (kDefaultWindowTCP + 2 * kDefaultTCPMSS));
334 }
335 return bbr_sender_.bytes_to_transfer() == 0 || !sender_->InSlowStart();
336 },
337 QuicTime::Delta::FromSeconds(30));
338 EXPECT_TRUE(simulator_result) << "Simple transfer failed. Bytes remaining: "
339 << bbr_sender_.bytes_to_transfer();
340 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
341 EXPECT_EQ(1u, bbr_sender_.connection()->GetStats().packets_lost);
342 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
343}
344
345// Test a simple long data transfer with 2 rtts of aggregation.
346TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) {
347 CreateDefaultSetup();
348 // 2 RTTs of aggregation, with a max of 10kb.
349 EnableAggregation(10 * 1024, 2 * kTestRtt);
350
351 // Transfer 12MB.
352 DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
353 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
354 // It's possible to read a bandwidth as much as 50% too high with aggregation.
355 EXPECT_LE(kTestLinkBandwidth * 0.99f,
356 sender_->ExportDebugState().max_bandwidth);
357 // TODO(ianswett): Tighten this bound once we understand why BBR is
358 // overestimating bandwidth with aggregation. b/36022633
359 EXPECT_GE(kTestLinkBandwidth * 1.5f,
360 sender_->ExportDebugState().max_bandwidth);
361 // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
362 // bandwidth higher than the link rate.
363 // The margin here is high, because the aggregation greatly increases
364 // smoothed rtt.
365 EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
366 ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.2f);
367}
368
369// Test a simple long data transfer with 2 rtts of aggregation.
370TEST_F(BbrSenderTest, SimpleTransferAckDecimation) {
371 // Decrease the CWND gain so extra CWND is required with stretch acks.
372 FLAGS_quic_bbr_cwnd_gain = 1.0;
373 sender_ = new BbrSender(
wub967ba572019-04-01 09:27:52 -0700374 bbr_sender_.connection()->clock()->Now(), rtt_stats_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500375 QuicSentPacketManagerPeer::GetUnackedPacketMap(
376 QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())),
377 kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets,
wub967ba572019-04-01 09:27:52 -0700378 &random_, QuicConnectionPeer::GetStats(bbr_sender_.connection()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500379 QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_);
380 // Enable Ack Decimation on the receiver.
381 QuicConnectionPeer::SetAckMode(receiver_.connection(),
382 AckMode::ACK_DECIMATION);
383 CreateDefaultSetup();
384
385 // Transfer 12MB.
386 DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
387 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
388 // It's possible to read a bandwidth as much as 50% too high with aggregation.
389 EXPECT_LE(kTestLinkBandwidth * 0.99f,
390 sender_->ExportDebugState().max_bandwidth);
391 // TODO(ianswett): Tighten this bound once we understand why BBR is
392 // overestimating bandwidth with aggregation. b/36022633
393 EXPECT_GE(kTestLinkBandwidth * 1.5f,
394 sender_->ExportDebugState().max_bandwidth);
395 // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
396 // bandwidth higher than the link rate.
397 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
398 // The margin here is high, because the aggregation greatly increases
399 // smoothed rtt.
400 EXPECT_GE(kTestRtt * 2, rtt_stats_->smoothed_rtt());
401 ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f);
402}
403
404// Test a simple long data transfer with 2 rtts of aggregation.
405TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes20RTTWindow) {
406 // Disable Ack Decimation on the receiver, because it can increase srtt.
407 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
408 CreateDefaultSetup();
409 SetConnectionOption(kBBR4);
410 // 2 RTTs of aggregation, with a max of 10kb.
411 EnableAggregation(10 * 1024, 2 * kTestRtt);
412
413 // Transfer 12MB.
414 DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
415 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
416 // It's possible to read a bandwidth as much as 50% too high with aggregation.
417 EXPECT_LE(kTestLinkBandwidth * 0.99f,
418 sender_->ExportDebugState().max_bandwidth);
419 // TODO(ianswett): Tighten this bound once we understand why BBR is
420 // overestimating bandwidth with aggregation. b/36022633
421 EXPECT_GE(kTestLinkBandwidth * 1.5f,
422 sender_->ExportDebugState().max_bandwidth);
423 // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
424 // bandwidth higher than the link rate.
425 // The margin here is high, because the aggregation greatly increases
426 // smoothed rtt.
427 EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
428 ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f);
429}
430
431// Test a simple long data transfer with 2 rtts of aggregation.
432TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes40RTTWindow) {
433 // Disable Ack Decimation on the receiver, because it can increase srtt.
434 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
435 CreateDefaultSetup();
436 SetConnectionOption(kBBR5);
437 // 2 RTTs of aggregation, with a max of 10kb.
438 EnableAggregation(10 * 1024, 2 * kTestRtt);
439
440 // Transfer 12MB.
441 DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
442 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
443 // It's possible to read a bandwidth as much as 50% too high with aggregation.
444 EXPECT_LE(kTestLinkBandwidth * 0.99f,
445 sender_->ExportDebugState().max_bandwidth);
446 // TODO(ianswett): Tighten this bound once we understand why BBR is
447 // overestimating bandwidth with aggregation. b/36022633
448 EXPECT_GE(kTestLinkBandwidth * 1.5f,
449 sender_->ExportDebugState().max_bandwidth);
450 // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
451 // bandwidth higher than the link rate.
452 // The margin here is high, because the aggregation greatly increases
453 // smoothed rtt.
454 EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
455 ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f);
456}
457
458// Test the number of losses incurred by the startup phase in a situation when
459// the buffer is less than BDP.
460TEST_F(BbrSenderTest, PacketLossOnSmallBufferStartup) {
461 CreateSmallBufferSetup();
462
463 DriveOutOfStartup();
464 float loss_rate =
465 static_cast<float>(bbr_sender_.connection()->GetStats().packets_lost) /
466 bbr_sender_.connection()->GetStats().packets_sent;
467 EXPECT_LE(loss_rate, 0.31);
468}
469
470// Ensures the code transitions loss recovery states correctly (NOT_IN_RECOVERY
471// -> CONSERVATION -> GROWTH -> NOT_IN_RECOVERY).
472TEST_F(BbrSenderTest, RecoveryStates) {
473 // Set seed to the position where the gain cycling causes the sender go
474 // into conservation upon entering PROBE_BW.
475 //
476 // TODO(vasilvv): there should be a better way to test this.
477 random_.set_seed(UINT64_C(14719894707049085006));
478
479 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
480 bool simulator_result;
481 CreateSmallBufferSetup();
482
483 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
484 ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
485 sender_->ExportDebugState().recovery_state);
486
487 simulator_result = simulator_.RunUntilOrTimeout(
488 [this]() {
489 return sender_->ExportDebugState().recovery_state !=
490 BbrSender::NOT_IN_RECOVERY;
491 },
492 timeout);
493 ASSERT_TRUE(simulator_result);
494 ASSERT_EQ(BbrSender::CONSERVATION,
495 sender_->ExportDebugState().recovery_state);
496
497 simulator_result = simulator_.RunUntilOrTimeout(
498 [this]() {
499 return sender_->ExportDebugState().recovery_state !=
500 BbrSender::CONSERVATION;
501 },
502 timeout);
503 ASSERT_TRUE(simulator_result);
504 ASSERT_EQ(BbrSender::GROWTH, sender_->ExportDebugState().recovery_state);
505
506 simulator_result = simulator_.RunUntilOrTimeout(
507 [this]() {
508 return sender_->ExportDebugState().recovery_state != BbrSender::GROWTH;
509 },
510 timeout);
511
512 ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
513 ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
514 sender_->ExportDebugState().recovery_state);
515 ASSERT_TRUE(simulator_result);
516}
517
518// Verify the behavior of the algorithm in the case when the connection sends
519// small bursts of data after sending continuously for a while.
520TEST_F(BbrSenderTest, ApplicationLimitedBursts) {
521 CreateDefaultSetup();
522
523 DriveOutOfStartup();
524 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
525
526 SendBursts(20, 512, QuicTime::Delta::FromSeconds(3));
527 EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
528 ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
529 0.01f);
530}
531
532// Verify the behavior of the algorithm in the case when the connection sends
533// small bursts of data and then starts sending continuously.
534TEST_F(BbrSenderTest, ApplicationLimitedBurstsWithoutPrior) {
535 CreateDefaultSetup();
536
537 SendBursts(40, 512, QuicTime::Delta::FromSeconds(3));
538 EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
539
540 DriveOutOfStartup();
541 ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
542 0.01f);
543 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
544}
545
546// Verify that the DRAIN phase works correctly.
547TEST_F(BbrSenderTest, Drain) {
548 // Disable Ack Decimation on the receiver, because it can increase srtt.
549 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
550 CreateDefaultSetup();
551 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
552 // Get the queue at the bottleneck, which is the outgoing queue at the port to
553 // which the receiver is connected.
554 const simulator::Queue* queue = switch_->port_queue(2);
555 bool simulator_result;
556
557 // We have no intention of ever finishing this transfer.
558 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
559
560 // Run the startup, and verify that it fills up the queue.
561 ASSERT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
562 simulator_result = simulator_.RunUntilOrTimeout(
563 [this]() {
564 return sender_->ExportDebugState().mode != BbrSender::STARTUP;
565 },
566 timeout);
567 ASSERT_TRUE(simulator_result);
568 ASSERT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
569 ExpectApproxEq(sender_->BandwidthEstimate() * (1 / 2.885f),
570 sender_->PacingRate(0), 0.01f);
571 // BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
572 // with approximately 1.88 BDPs. Here, we use 1.5 to give some margin for
573 // error.
574 EXPECT_GE(queue->bytes_queued(), 1.5 * kTestBdp);
575
576 // Observe increased RTT due to bufferbloat.
577 const QuicTime::Delta queueing_delay =
578 kTestLinkBandwidth.TransferTime(queue->bytes_queued());
579 ExpectApproxEq(kTestRtt + queueing_delay, rtt_stats_->latest_rtt(), 0.1f);
580
581 // Transition to the drain phase and verify that it makes the queue
582 // have at most a BDP worth of packets.
583 simulator_result = simulator_.RunUntilOrTimeout(
584 [this]() { return sender_->ExportDebugState().mode != BbrSender::DRAIN; },
585 timeout);
586 ASSERT_TRUE(simulator_result);
587 ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
588 EXPECT_LE(queue->bytes_queued(), kTestBdp);
589
590 // Wait for a few round trips and ensure we're in appropriate phase of gain
591 // cycling before taking an RTT measurement.
592 const QuicRoundTripCount start_round_trip =
593 sender_->ExportDebugState().round_trip_count;
594 simulator_result = simulator_.RunUntilOrTimeout(
595 [this, start_round_trip]() {
596 QuicRoundTripCount rounds_passed =
597 sender_->ExportDebugState().round_trip_count - start_round_trip;
598 return rounds_passed >= 4 &&
599 sender_->ExportDebugState().gain_cycle_index == 7;
600 },
601 timeout);
602 ASSERT_TRUE(simulator_result);
603
604 // Observe the bufferbloat go away.
605 ExpectApproxEq(kTestRtt, rtt_stats_->smoothed_rtt(), 0.1f);
606}
607
608// Verify that the DRAIN phase works correctly.
609TEST_F(BbrSenderTest, ShallowDrain) {
610 SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
611 // Disable Ack Decimation on the receiver, because it can increase srtt.
612 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
613
614 CreateDefaultSetup();
615 // BBQ4 increases the pacing gain in DRAIN to 0.75
616 SetConnectionOption(kBBQ4);
617 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
618 // Get the queue at the bottleneck, which is the outgoing queue at the port to
619 // which the receiver is connected.
620 const simulator::Queue* queue = switch_->port_queue(2);
621 bool simulator_result;
622
623 // We have no intention of ever finishing this transfer.
624 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
625
626 // Run the startup, and verify that it fills up the queue.
627 ASSERT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
628 simulator_result = simulator_.RunUntilOrTimeout(
629 [this]() {
630 return sender_->ExportDebugState().mode != BbrSender::STARTUP;
631 },
632 timeout);
633 ASSERT_TRUE(simulator_result);
634 ASSERT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
635 EXPECT_EQ(0.75 * sender_->BandwidthEstimate(), sender_->PacingRate(0));
636 // BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
637 // with approximately 1.88 BDPs. Here, we use 1.5 to give some margin for
638 // error.
639 EXPECT_GE(queue->bytes_queued(), 1.5 * kTestBdp);
640
641 // Observe increased RTT due to bufferbloat.
642 const QuicTime::Delta queueing_delay =
643 kTestLinkBandwidth.TransferTime(queue->bytes_queued());
644 ExpectApproxEq(kTestRtt + queueing_delay, rtt_stats_->latest_rtt(), 0.1f);
645
646 // Transition to the drain phase and verify that it makes the queue
647 // have at most a BDP worth of packets.
648 simulator_result = simulator_.RunUntilOrTimeout(
649 [this]() { return sender_->ExportDebugState().mode != BbrSender::DRAIN; },
650 timeout);
651 ASSERT_TRUE(simulator_result);
652 ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
653 EXPECT_LE(queue->bytes_queued(), kTestBdp);
654
655 // Wait for a few round trips and ensure we're in appropriate phase of gain
656 // cycling before taking an RTT measurement.
657 const QuicRoundTripCount start_round_trip =
658 sender_->ExportDebugState().round_trip_count;
659 simulator_result = simulator_.RunUntilOrTimeout(
660 [this, start_round_trip]() {
661 QuicRoundTripCount rounds_passed =
662 sender_->ExportDebugState().round_trip_count - start_round_trip;
663 return rounds_passed >= 4 &&
664 sender_->ExportDebugState().gain_cycle_index == 7;
665 },
666 timeout);
667 ASSERT_TRUE(simulator_result);
668
669 // Observe the bufferbloat go away.
670 ExpectApproxEq(kTestRtt, rtt_stats_->smoothed_rtt(), 0.1f);
671}
672
673// Verify that the connection enters and exits PROBE_RTT correctly.
674TEST_F(BbrSenderTest, ProbeRtt) {
675 CreateDefaultSetup();
676 DriveOutOfStartup();
677
678 // We have no intention of ever finishing this transfer.
679 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
680
681 // Wait until the connection enters PROBE_RTT.
682 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
683 bool simulator_result = simulator_.RunUntilOrTimeout(
684 [this]() {
685 return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
686 },
687 timeout);
688 ASSERT_TRUE(simulator_result);
689 ASSERT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
690
691 // Exit PROBE_RTT.
692 const QuicTime probe_rtt_start = clock_->Now();
693 const QuicTime::Delta time_to_exit_probe_rtt =
694 kTestRtt + QuicTime::Delta::FromMilliseconds(200);
695 simulator_.RunFor(1.5 * time_to_exit_probe_rtt);
696 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
697 EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
698}
699
700// Verify that the first sample after PROBE_RTT is not used as the bandwidth,
701// because the round counter doesn't advance during PROBE_RTT.
702TEST_F(BbrSenderTest, AppLimitedRecoveryNoBandwidthDecrease) {
703 SetQuicReloadableFlag(quic_bbr_app_limited_recovery, true);
704 CreateDefaultSetup();
705 DriveOutOfStartup();
706
707 // We have no intention of ever finishing this transfer.
708 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
709
710 // Wait until the connection enters PROBE_RTT.
711 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
712 bool simulator_result = simulator_.RunUntilOrTimeout(
713 [this]() {
714 return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
715 },
716 timeout);
717 ASSERT_TRUE(simulator_result);
718 ASSERT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
719
720 const QuicBandwidth beginning_bw = sender_->BandwidthEstimate();
721
722 // Run for most of PROBE_RTT.
723 const QuicTime probe_rtt_start = clock_->Now();
724 const QuicTime::Delta time_to_exit_probe_rtt =
725 kTestRtt + QuicTime::Delta::FromMilliseconds(200);
726 simulator_.RunFor(0.60 * time_to_exit_probe_rtt);
727 EXPECT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
728 // Lose a packet before exiting PROBE_RTT, which puts us in packet
729 // conservation and then continue there for a while and ensure the bandwidth
730 // estimate doesn't decrease.
731 for (int i = 0; i < 20; ++i) {
732 receiver_.DropNextIncomingPacket();
733 simulator_.RunFor(0.9 * kTestRtt);
734 // Ensure the bandwidth didn't decrease and the samples are app limited.
735 EXPECT_LE(beginning_bw, sender_->BandwidthEstimate());
736 EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
737 }
738 EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
739}
740
741// Verify that the connection enters and exits PROBE_RTT correctly.
742TEST_F(BbrSenderTest, ProbeRttBDPBasedCWNDTarget) {
743 CreateDefaultSetup();
744 SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
745 SetConnectionOption(kBBR6);
746 DriveOutOfStartup();
747
748 // We have no intention of ever finishing this transfer.
749 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
750
751 // Wait until the connection enters PROBE_RTT.
752 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
753 bool simulator_result = simulator_.RunUntilOrTimeout(
754 [this]() {
755 return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
756 },
757 timeout);
758 ASSERT_TRUE(simulator_result);
759 ASSERT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
760
761 // Exit PROBE_RTT.
762 const QuicTime probe_rtt_start = clock_->Now();
763 const QuicTime::Delta time_to_exit_probe_rtt =
764 kTestRtt + QuicTime::Delta::FromMilliseconds(200);
765 simulator_.RunFor(1.5 * time_to_exit_probe_rtt);
766 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
767 EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
768}
769
770// Verify that the connection enters does not enter PROBE_RTT.
771TEST_F(BbrSenderTest, ProbeRttSkippedAfterAppLimitedAndStableRtt) {
772 CreateDefaultSetup();
773 SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
774 SetConnectionOption(kBBR7);
775 DriveOutOfStartup();
776
777 // We have no intention of ever finishing this transfer.
778 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
779
780 // Wait until the connection enters PROBE_RTT.
781 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
782 bool simulator_result = simulator_.RunUntilOrTimeout(
783 [this]() {
784 return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
785 },
786 timeout);
787 ASSERT_FALSE(simulator_result);
788 ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
789}
790
791// Verify that the connection enters does not enter PROBE_RTT.
792TEST_F(BbrSenderTest, ProbeRttSkippedAfterAppLimited) {
793 CreateDefaultSetup();
794 SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
795 SetConnectionOption(kBBR8);
796 DriveOutOfStartup();
797
798 // We have no intention of ever finishing this transfer.
799 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
800
801 // Wait until the connection enters PROBE_RTT.
802 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
803 bool simulator_result = simulator_.RunUntilOrTimeout(
804 [this]() {
805 return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
806 },
807 timeout);
808 ASSERT_FALSE(simulator_result);
809 ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
810}
811
812// Ensure that a connection that is app-limited and is at sufficiently low
813// bandwidth will not exit high gain phase, and similarly ensure that the
814// connection will exit low gain early if the number of bytes in flight is low.
815TEST_F(BbrSenderTest, InFlightAwareGainCycling) {
816 // Disable Ack Decimation on the receiver, because it can increase srtt.
817 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
818 CreateDefaultSetup();
819 DriveOutOfStartup();
820
821 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
822 bool simulator_result;
823
824 // Start a few cycles prior to the high gain one.
825 simulator_result = simulator_.RunUntilOrTimeout(
826 [this]() { return sender_->ExportDebugState().gain_cycle_index == 6; },
827 timeout);
828
829 // Send at 10% of available rate. Run for 3 seconds, checking in the middle
830 // and at the end. The pacing gain should be high throughout.
831 QuicBandwidth target_bandwidth = 0.1f * kTestLinkBandwidth;
832 QuicTime::Delta burst_interval = QuicTime::Delta::FromMilliseconds(300);
833 for (int i = 0; i < 2; i++) {
834 SendBursts(5, target_bandwidth * burst_interval, burst_interval);
835 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
836 EXPECT_EQ(0, sender_->ExportDebugState().gain_cycle_index);
837 ExpectApproxEq(kTestLinkBandwidth,
838 sender_->ExportDebugState().max_bandwidth, 0.01f);
839 }
840
841 // Now that in-flight is almost zero and the pacing gain is still above 1,
842 // send approximately 1.25 BDPs worth of data. This should cause the
843 // PROBE_BW mode to enter low gain cycle, and exit it earlier than one min_rtt
844 // due to running out of data to send.
845 bbr_sender_.AddBytesToTransfer(1.3 * kTestBdp);
846 simulator_result = simulator_.RunUntilOrTimeout(
847 [this]() { return sender_->ExportDebugState().gain_cycle_index == 1; },
848 timeout);
849 ASSERT_TRUE(simulator_result);
850 simulator_.RunFor(0.75 * sender_->ExportDebugState().min_rtt);
851 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
852 EXPECT_EQ(2, sender_->ExportDebugState().gain_cycle_index);
853}
854
855// Ensure that the pacing rate does not drop at startup.
856TEST_F(BbrSenderTest, NoBandwidthDropOnStartup) {
857 CreateDefaultSetup();
858
859 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
860 bool simulator_result;
861
862 QuicBandwidth initial_rate = QuicBandwidth::FromBytesAndTimeDelta(
863 kInitialCongestionWindowPackets * kDefaultTCPMSS,
864 rtt_stats_->initial_rtt());
865 EXPECT_GE(sender_->PacingRate(0), initial_rate);
866
867 // Send a packet.
868 bbr_sender_.AddBytesToTransfer(1000);
869 simulator_result = simulator_.RunUntilOrTimeout(
870 [this]() { return receiver_.bytes_received() == 1000; }, timeout);
871 ASSERT_TRUE(simulator_result);
872 EXPECT_GE(sender_->PacingRate(0), initial_rate);
873
874 // Wait for a while.
875 simulator_.RunFor(QuicTime::Delta::FromSeconds(2));
876 EXPECT_GE(sender_->PacingRate(0), initial_rate);
877
878 // Send another packet.
879 bbr_sender_.AddBytesToTransfer(1000);
880 simulator_result = simulator_.RunUntilOrTimeout(
881 [this]() { return receiver_.bytes_received() == 2000; }, timeout);
882 ASSERT_TRUE(simulator_result);
883 EXPECT_GE(sender_->PacingRate(0), initial_rate);
884}
885
886// Test exiting STARTUP earlier due to the 1RTT connection option.
887TEST_F(BbrSenderTest, SimpleTransfer1RTTStartup) {
888 CreateDefaultSetup();
889
890 SetConnectionOption(k1RTT);
891 EXPECT_EQ(1u, sender_->num_startup_rtts());
892
893 // Run until the full bandwidth is reached and check how many rounds it was.
894 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
895 QuicRoundTripCount max_bw_round = 0;
896 QuicBandwidth max_bw(QuicBandwidth::Zero());
897 bool simulator_result = simulator_.RunUntilOrTimeout(
898 [this, &max_bw, &max_bw_round]() {
899 if (max_bw < sender_->ExportDebugState().max_bandwidth) {
900 max_bw = sender_->ExportDebugState().max_bandwidth;
901 max_bw_round = sender_->ExportDebugState().round_trip_count;
902 }
903 return sender_->ExportDebugState().is_at_full_bandwidth;
904 },
905 QuicTime::Delta::FromSeconds(5));
906 ASSERT_TRUE(simulator_result);
907 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
908 EXPECT_EQ(1u, sender_->ExportDebugState().round_trip_count - max_bw_round);
909 EXPECT_EQ(1u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
910 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
911 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
912}
913
914// Test exiting STARTUP earlier due to the 2RTT connection option.
915TEST_F(BbrSenderTest, SimpleTransfer2RTTStartup) {
916 CreateDefaultSetup();
917
918 SetConnectionOption(k2RTT);
919 EXPECT_EQ(2u, sender_->num_startup_rtts());
920
921 // Run until the full bandwidth is reached and check how many rounds it was.
922 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
923 QuicRoundTripCount max_bw_round = 0;
924 QuicBandwidth max_bw(QuicBandwidth::Zero());
925 bool simulator_result = simulator_.RunUntilOrTimeout(
926 [this, &max_bw, &max_bw_round]() {
927 if (max_bw < sender_->ExportDebugState().max_bandwidth) {
928 max_bw = sender_->ExportDebugState().max_bandwidth;
929 max_bw_round = sender_->ExportDebugState().round_trip_count;
930 }
931 return sender_->ExportDebugState().is_at_full_bandwidth;
932 },
933 QuicTime::Delta::FromSeconds(5));
934 ASSERT_TRUE(simulator_result);
935 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
936 EXPECT_EQ(2u, sender_->ExportDebugState().round_trip_count - max_bw_round);
937 EXPECT_EQ(2u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
938 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
939 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
940}
941
942// Test exiting STARTUP earlier upon loss due to the LRTT connection option.
943TEST_F(BbrSenderTest, SimpleTransferLRTTStartup) {
944 CreateDefaultSetup();
945
946 SetConnectionOption(kLRTT);
947 EXPECT_EQ(3u, sender_->num_startup_rtts());
948
949 // Run until the full bandwidth is reached and check how many rounds it was.
950 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
951 QuicRoundTripCount max_bw_round = 0;
952 QuicBandwidth max_bw(QuicBandwidth::Zero());
953 bool simulator_result = simulator_.RunUntilOrTimeout(
954 [this, &max_bw, &max_bw_round]() {
955 if (max_bw < sender_->ExportDebugState().max_bandwidth) {
956 max_bw = sender_->ExportDebugState().max_bandwidth;
957 max_bw_round = sender_->ExportDebugState().round_trip_count;
958 }
959 return sender_->ExportDebugState().is_at_full_bandwidth;
960 },
961 QuicTime::Delta::FromSeconds(5));
962 ASSERT_TRUE(simulator_result);
963 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
964 EXPECT_EQ(3u, sender_->ExportDebugState().round_trip_count - max_bw_round);
965 EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
966 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
967 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
968}
969
970// Test exiting STARTUP earlier upon loss due to the LRTT connection option.
971TEST_F(BbrSenderTest, SimpleTransferLRTTStartupSmallBuffer) {
972 CreateSmallBufferSetup();
973
974 SetConnectionOption(kLRTT);
975 EXPECT_EQ(3u, sender_->num_startup_rtts());
976
977 // Run until the full bandwidth is reached and check how many rounds it was.
978 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
979 QuicRoundTripCount max_bw_round = 0;
980 QuicBandwidth max_bw(QuicBandwidth::Zero());
981 bool simulator_result = simulator_.RunUntilOrTimeout(
982 [this, &max_bw, &max_bw_round]() {
983 if (max_bw < sender_->ExportDebugState().max_bandwidth) {
984 max_bw = sender_->ExportDebugState().max_bandwidth;
985 max_bw_round = sender_->ExportDebugState().round_trip_count;
986 }
987 return sender_->ExportDebugState().is_at_full_bandwidth;
988 },
989 QuicTime::Delta::FromSeconds(5));
990 ASSERT_TRUE(simulator_result);
991 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
992 EXPECT_GE(2u, sender_->ExportDebugState().round_trip_count - max_bw_round);
993 EXPECT_EQ(1u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
994 EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
995 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
996}
997
998// Test slower pacing after loss in STARTUP due to the BBRS connection option.
999TEST_F(BbrSenderTest, SimpleTransferSlowerStartup) {
1000 CreateSmallBufferSetup();
1001
1002 SetConnectionOption(kBBRS);
1003 EXPECT_EQ(3u, sender_->num_startup_rtts());
1004
1005 // Run until the full bandwidth is reached and check how many rounds it was.
1006 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1007 QuicRoundTripCount max_bw_round = 0;
1008 QuicBandwidth max_bw(QuicBandwidth::Zero());
1009 bool simulator_result = simulator_.RunUntilOrTimeout(
1010 [this, &max_bw, &max_bw_round]() {
1011 if (max_bw < sender_->ExportDebugState().max_bandwidth) {
1012 max_bw = sender_->ExportDebugState().max_bandwidth;
1013 max_bw_round = sender_->ExportDebugState().round_trip_count;
1014 }
1015 // Expect the pacing rate in STARTUP to decrease once packet loss
1016 // is observed, but the CWND does not.
1017 if (bbr_sender_.connection()->GetStats().packets_lost > 0 &&
1018 !sender_->ExportDebugState().is_at_full_bandwidth &&
1019 sender_->has_non_app_limited_sample()) {
1020 EXPECT_EQ(1.5f * max_bw, sender_->PacingRate(0));
1021 }
1022 return sender_->ExportDebugState().is_at_full_bandwidth;
1023 },
1024 QuicTime::Delta::FromSeconds(5));
1025 ASSERT_TRUE(simulator_result);
1026 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
1027 EXPECT_GE(3u, sender_->ExportDebugState().round_trip_count - max_bw_round);
1028 EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
1029 EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
1030 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
1031}
1032
1033// Ensures no change in congestion window in STARTUP after loss.
1034TEST_F(BbrSenderTest, SimpleTransferNoConservationInStartup) {
1035 CreateSmallBufferSetup();
1036
1037 SetConnectionOption(kBBS1);
1038
1039 // Run until the full bandwidth is reached and check how many rounds it was.
1040 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1041 bool used_conservation_cwnd = false;
1042 bool simulator_result = simulator_.RunUntilOrTimeout(
1043 [this, &used_conservation_cwnd]() {
1044 if (!sender_->ExportDebugState().is_at_full_bandwidth &&
1045 sender_->GetCongestionWindow() <
1046 sender_->ExportDebugState().congestion_window) {
1047 used_conservation_cwnd = true;
1048 }
1049 return sender_->ExportDebugState().is_at_full_bandwidth;
1050 },
1051 QuicTime::Delta::FromSeconds(5));
1052 ASSERT_TRUE(simulator_result);
1053 EXPECT_FALSE(used_conservation_cwnd);
1054 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
1055 EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
1056 EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
1057 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
1058}
1059
1060// Ensures no change in congestion window in STARTUP after loss, but that the
1061// rate decreases.
1062TEST_F(BbrSenderTest, SimpleTransferStartupRateReduction) {
1063 SetQuicReloadableFlag(quic_bbr_startup_rate_reduction, true);
1064 CreateSmallBufferSetup();
1065
1066 SetConnectionOption(kBBS4);
1067
1068 // Run until the full bandwidth is reached and check how many rounds it was.
1069 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1070 bool used_conservation_cwnd = false;
1071 bool simulator_result = simulator_.RunUntilOrTimeout(
1072 [this, &used_conservation_cwnd]() {
1073 if (!sender_->ExportDebugState().is_at_full_bandwidth &&
1074 sender_->GetCongestionWindow() <
1075 sender_->ExportDebugState().congestion_window) {
1076 used_conservation_cwnd = true;
1077 }
1078 // Exit once a loss is hit.
1079 return bbr_sender_.connection()->GetStats().packets_lost > 0 ||
1080 sender_->ExportDebugState().is_at_full_bandwidth;
1081 },
1082 QuicTime::Delta::FromSeconds(5));
1083 ASSERT_TRUE(simulator_result);
1084 EXPECT_TRUE(sender_->InRecovery());
1085 EXPECT_FALSE(used_conservation_cwnd);
1086 EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
1087 EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
1088
1089 // Lose each outstanding packet and the pacing rate decreases.
1090 const QuicBandwidth original_pacing_rate = sender_->PacingRate(0);
1091 QuicBandwidth pacing_rate = original_pacing_rate;
1092 const QuicByteCount original_cwnd = sender_->GetCongestionWindow();
1093 LostPacketVector lost_packets;
dschinazi66dea072019-04-09 11:41:06 -07001094 lost_packets.push_back(
1095 LostPacket(QuicPacketNumber(), kMaxOutgoingPacketSize));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001096 QuicPacketNumber largest_sent =
1097 bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
1098 for (QuicPacketNumber packet_number =
1099 bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked();
1100 packet_number <= largest_sent; ++packet_number) {
1101 lost_packets[0].packet_number = packet_number;
1102 sender_->OnCongestionEvent(false, 0, clock_->Now(), {}, lost_packets);
1103 EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow());
1104 EXPECT_GT(original_pacing_rate, sender_->PacingRate(0));
1105 EXPECT_GE(pacing_rate, sender_->PacingRate(0));
1106 EXPECT_LE(1.25 * sender_->BandwidthEstimate(), sender_->PacingRate(0));
1107 pacing_rate = sender_->PacingRate(0);
1108 }
1109}
1110
1111// Ensures no change in congestion window in STARTUP after loss, but that the
1112// rate decreases twice as fast as BBS4.
1113TEST_F(BbrSenderTest, SimpleTransferDoubleStartupRateReduction) {
1114 SetQuicReloadableFlag(quic_bbr_startup_rate_reduction, true);
1115 CreateSmallBufferSetup();
1116
1117 SetConnectionOption(kBBS5);
1118
1119 // Run until the full bandwidth is reached and check how many rounds it was.
1120 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1121 bool used_conservation_cwnd = false;
1122 bool simulator_result = simulator_.RunUntilOrTimeout(
1123 [this, &used_conservation_cwnd]() {
1124 if (!sender_->ExportDebugState().is_at_full_bandwidth &&
1125 sender_->GetCongestionWindow() <
1126 sender_->ExportDebugState().congestion_window) {
1127 used_conservation_cwnd = true;
1128 }
1129 // Exit once a loss is hit.
1130 return bbr_sender_.connection()->GetStats().packets_lost > 0 ||
1131 sender_->ExportDebugState().is_at_full_bandwidth;
1132 },
1133 QuicTime::Delta::FromSeconds(5));
1134 ASSERT_TRUE(simulator_result);
1135 EXPECT_TRUE(sender_->InRecovery());
1136 EXPECT_FALSE(used_conservation_cwnd);
1137 EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
1138 EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
1139
1140 // Lose each outstanding packet and the pacing rate decreases.
1141 const QuicBandwidth original_pacing_rate = sender_->PacingRate(0);
1142 QuicBandwidth pacing_rate = original_pacing_rate;
1143 const QuicByteCount original_cwnd = sender_->GetCongestionWindow();
1144 LostPacketVector lost_packets;
dschinazi66dea072019-04-09 11:41:06 -07001145 lost_packets.push_back(
1146 LostPacket(QuicPacketNumber(), kMaxOutgoingPacketSize));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001147 QuicPacketNumber largest_sent =
1148 bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
1149 for (QuicPacketNumber packet_number =
1150 bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked();
1151 packet_number <= largest_sent; ++packet_number) {
1152 lost_packets[0].packet_number = packet_number;
1153 sender_->OnCongestionEvent(false, 0, clock_->Now(), {}, lost_packets);
1154 EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow());
1155 EXPECT_GT(original_pacing_rate, sender_->PacingRate(0));
1156 EXPECT_GE(pacing_rate, sender_->PacingRate(0));
1157 EXPECT_LE(1.25 * sender_->BandwidthEstimate(), sender_->PacingRate(0));
1158 pacing_rate = sender_->PacingRate(0);
1159 }
1160}
1161
1162TEST_F(BbrSenderTest, DerivedPacingGainStartup) {
1163 SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
1164 CreateDefaultSetup();
1165
1166 SetConnectionOption(kBBQ1);
1167 EXPECT_EQ(3u, sender_->num_startup_rtts());
1168 // Verify that Sender is in slow start.
1169 EXPECT_TRUE(sender_->InSlowStart());
1170 // Verify that pacing rate is based on the initial RTT.
1171 QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
1172 2.773 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
1173 ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
1174 sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
1175
1176 // Run until the full bandwidth is reached and check how many rounds it was.
1177 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1178 bool simulator_result = simulator_.RunUntilOrTimeout(
1179 [this]() { return sender_->ExportDebugState().is_at_full_bandwidth; },
1180 QuicTime::Delta::FromSeconds(5));
1181 ASSERT_TRUE(simulator_result);
1182 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
1183 EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
1184 ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
1185 0.01f);
1186 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
1187 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
1188}
1189
1190TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
1191 SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
1192 CreateDefaultSetup();
1193
1194 SetConnectionOption(kBBQ2);
1195 EXPECT_EQ(3u, sender_->num_startup_rtts());
1196 // Verify that Sender is in slow start.
1197 EXPECT_TRUE(sender_->InSlowStart());
1198 // Verify that pacing rate is based on the initial RTT.
1199 QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
1200 2.885 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
1201 ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
1202 sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
1203
1204 // Run until the full bandwidth is reached and check how many rounds it was.
1205 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1206 bool simulator_result = simulator_.RunUntilOrTimeout(
1207 [this]() { return sender_->ExportDebugState().is_at_full_bandwidth; },
1208 QuicTime::Delta::FromSeconds(5));
1209 ASSERT_TRUE(simulator_result);
1210 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
1211 EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
1212 ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
1213 0.01f);
1214 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
1215 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
1216 // Expect an SRTT less than 2.7 * Min RTT on exit from STARTUP.
1217 EXPECT_GT(kTestRtt * 2.7, rtt_stats_->smoothed_rtt());
1218}
1219
1220TEST_F(BbrSenderTest, AckAggregationInStartup) {
1221 SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
1222 // Disable Ack Decimation on the receiver to avoid loss and make results
1223 // consistent.
1224 QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
1225 CreateDefaultSetup();
1226
1227 SetConnectionOption(kBBQ3);
1228 EXPECT_EQ(3u, sender_->num_startup_rtts());
1229 // Verify that Sender is in slow start.
1230 EXPECT_TRUE(sender_->InSlowStart());
1231 // Verify that pacing rate is based on the initial RTT.
1232 QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
1233 2.885 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
1234 ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
1235 sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
1236
1237 // Run until the full bandwidth is reached and check how many rounds it was.
1238 bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
1239 bool simulator_result = simulator_.RunUntilOrTimeout(
1240 [this]() { return sender_->ExportDebugState().is_at_full_bandwidth; },
1241 QuicTime::Delta::FromSeconds(5));
1242 ASSERT_TRUE(simulator_result);
1243 EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
1244 EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
1245 ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
1246 0.01f);
1247 EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
1248 EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
1249}
1250
1251// Test that two BBR flows started slightly apart from each other terminate.
1252TEST_F(BbrSenderTest, SimpleCompetition) {
1253 const QuicByteCount transfer_size = 10 * 1024 * 1024;
1254 const QuicTime::Delta transfer_time =
1255 kTestLinkBandwidth.TransferTime(transfer_size);
1256 CreateBbrVsBbrSetup();
1257
1258 // Transfer 10% of data in first transfer.
1259 bbr_sender_.AddBytesToTransfer(transfer_size);
1260 bool simulator_result = simulator_.RunUntilOrTimeout(
1261 [this]() { return receiver_.bytes_received() >= 0.1 * transfer_size; },
1262 transfer_time);
1263 ASSERT_TRUE(simulator_result);
1264
1265 // Start the second transfer and wait until both finish.
1266 competing_sender_.AddBytesToTransfer(transfer_size);
1267 simulator_result = simulator_.RunUntilOrTimeout(
1268 [this]() {
1269 return receiver_.bytes_received() == transfer_size &&
1270 competing_receiver_.bytes_received() == transfer_size;
1271 },
1272 3 * transfer_time);
1273 ASSERT_TRUE(simulator_result);
1274}
1275
1276// Test that BBR can resume bandwidth from cached network parameters.
1277TEST_F(BbrSenderTest, ResumeConnectionState) {
1278 CreateDefaultSetup();
1279
1280 bbr_sender_.connection()->AdjustNetworkParameters(kTestLinkBandwidth,
1281 kTestRtt);
1282 EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
1283 EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
1284 ExpectApproxEq(kTestRtt, sender_->ExportDebugState().min_rtt, 0.01f);
1285
1286 DriveOutOfStartup();
1287}
1288
1289// Test with a min CWND of 1 instead of 4 packets.
1290TEST_F(BbrSenderTest, ProbeRTTMinCWND1) {
1291 CreateDefaultSetup();
1292 SetConnectionOption(kMIN1);
1293 DriveOutOfStartup();
1294
1295 // We have no intention of ever finishing this transfer.
1296 bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
1297
1298 // Wait until the connection enters PROBE_RTT.
1299 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
1300 bool simulator_result = simulator_.RunUntilOrTimeout(
1301 [this]() {
1302 return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
1303 },
1304 timeout);
1305 ASSERT_TRUE(simulator_result);
1306 ASSERT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
1307 // The PROBE_RTT CWND should be 1 if the min CWND is 1.
1308 EXPECT_EQ(kDefaultTCPMSS, sender_->GetCongestionWindow());
1309
1310 // Exit PROBE_RTT.
1311 const QuicTime probe_rtt_start = clock_->Now();
1312 const QuicTime::Delta time_to_exit_probe_rtt =
1313 kTestRtt + QuicTime::Delta::FromMilliseconds(200);
1314 simulator_.RunFor(1.5 * time_to_exit_probe_rtt);
1315 EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
1316 EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
1317}
1318
wub967ba572019-04-01 09:27:52 -07001319TEST_F(BbrSenderTest, StartupStats) {
1320 CreateDefaultSetup();
1321
1322 DriveOutOfStartup();
1323 ASSERT_FALSE(sender_->InSlowStart());
1324
1325 const QuicConnectionStats& stats = bbr_sender_.connection()->GetStats();
wuba8d93552019-04-03 12:06:01 -07001326 EXPECT_EQ(1u, stats.slowstart_count);
1327 EXPECT_THAT(stats.slowstart_num_rtts, AllOf(Ge(5u), Le(15u)));
1328 EXPECT_THAT(stats.slowstart_packets_sent, AllOf(Ge(100u), Le(1000u)));
1329 EXPECT_THAT(stats.slowstart_bytes_sent, AllOf(Ge(100000u), Le(1000000u)));
1330 EXPECT_LE(stats.slowstart_packets_lost, 10u);
1331 EXPECT_LE(stats.slowstart_bytes_lost, 10000u);
wub967ba572019-04-01 09:27:52 -07001332 EXPECT_THAT(stats.slowstart_duration,
1333 AllOf(Ge(QuicTime::Delta::FromMilliseconds(500)),
1334 Le(QuicTime::Delta::FromMilliseconds(1500))));
1335 EXPECT_EQ(QuicTime::Zero(), stats.slowstart_start_time);
1336 EXPECT_EQ(stats.slowstart_duration,
1337 QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())
1338 ->GetSlowStartDuration());
1339}
1340
QUICHE teama6ef0a62019-03-07 20:34:33 -05001341} // namespace test
1342} // namespace quic