1 // Copyright 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/send_algorithm_simulator.h"
9 #include "base/logging.h"
10 #include "base/rand_util.h"
11 #include "net/quic/crypto/quic_random.h"
23 const QuicByteCount kPacketSize
= 1200;
27 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface
* send_algorithm
,
29 : Sender(send_algorithm
, rtt_stats
, QuicTime::Delta::Zero()) {}
31 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface
* send_algorithm
,
33 QuicTime::Delta additional_rtt
)
34 : send_algorithm(send_algorithm
),
36 additional_rtt(additional_rtt
),
44 last_transfer_bandwidth(QuicBandwidth::Zero()),
45 last_transfer_loss_rate(0) {}
47 SendAlgorithmSimulator::Transfer::Transfer(Sender
* sender
,
48 QuicByteCount num_bytes
,
56 start_time(start_time
),
59 SendAlgorithmSimulator::SendAlgorithmSimulator(
61 QuicBandwidth bandwidth
,
64 lose_next_ack_(false),
65 forward_loss_rate_(0),
66 reverse_loss_rate_(0),
68 bandwidth_(bandwidth
),
70 buffer_size_(1000000),
71 delayed_ack_timer_(QuicTime::Delta::FromMilliseconds(100)) {
72 uint32 seed
= base::RandInt(0, std::numeric_limits
<int32
>::max());
73 DVLOG(1) << "Seeding SendAlgorithmSimulator with " << seed
;
74 simple_random_
.set_seed(seed
);
77 SendAlgorithmSimulator::~SendAlgorithmSimulator() {}
79 void SendAlgorithmSimulator::AddTransfer(Sender
* sender
, size_t num_bytes
) {
80 AddTransfer(sender
, num_bytes
, clock_
->Now(),
81 StringPrintf("#%zu", pending_transfers_
.size()));
84 void SendAlgorithmSimulator::AddTransfer(
85 Sender
* sender
, size_t num_bytes
, QuicTime start_time
, string name
) {
86 pending_transfers_
.push_back(Transfer(sender
, num_bytes
, start_time
, name
));
87 // Record initial stats from when the transfer begins.
88 pending_transfers_
.back().sender
->RecordStats();
91 void SendAlgorithmSimulator::TransferBytes() {
92 TransferBytes(kuint64max
, QuicTime::Delta::Infinite());
95 void SendAlgorithmSimulator::TransferBytes(QuicByteCount max_bytes
,
96 QuicTime::Delta max_time
) {
97 const QuicTime end_time
= max_time
.IsInfinite() ?
98 QuicTime::Zero().Add(QuicTime::Delta::Infinite()) :
99 clock_
->Now().Add(max_time
);
100 QuicByteCount bytes_sent
= 0;
101 while (!pending_transfers_
.empty() &&
102 clock_
->Now() < end_time
&&
103 bytes_sent
< max_bytes
) {
104 // Determine the times of next send and of the next ack arrival.
105 PacketEvent send_event
= NextSendEvent();
106 PacketEvent ack_event
= NextAckEvent();
107 // If both times are infinite, fire a TLP.
108 if (ack_event
.time_delta
.IsInfinite() &&
109 send_event
.time_delta
.IsInfinite()) {
110 DVLOG(1) << "Both times are infinite, simulating a TLP.";
111 // TODO(ianswett): Use a more sophisticated TLP timer or never lose
113 clock_
->AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
114 SendDataNow(&pending_transfers_
.front());
115 } else if (ack_event
.time_delta
< send_event
.time_delta
) {
116 DVLOG(1) << "Handling ack of largest observed:"
117 << ack_event
.transfer
->sender
->next_acked
<< ", advancing time:"
118 << ack_event
.time_delta
.ToMicroseconds() << "us";
119 // Ack data all the data up to ack time and lose any missing sequence
121 clock_
->AdvanceTime(ack_event
.time_delta
);
122 HandlePendingAck(ack_event
.transfer
);
124 DVLOG(1) << "Sending transfer '" << send_event
.transfer
->name
125 << "', advancing time:" << send_event
.time_delta
.ToMicroseconds()
127 clock_
->AdvanceTime(send_event
.time_delta
);
128 SendDataNow(send_event
.transfer
);
129 bytes_sent
+= kPacketSize
;
134 SendAlgorithmSimulator::PacketEvent
SendAlgorithmSimulator::NextSendEvent() {
135 QuicTime::Delta next_send_time
= QuicTime::Delta::Infinite();
136 Transfer
* transfer
= nullptr;
137 for (vector
<Transfer
>::iterator it
= pending_transfers_
.begin();
138 it
!= pending_transfers_
.end(); ++it
) {
139 // If we've already sent enough bytes, wait for them to be acked.
140 if (it
->bytes_acked
+ it
->bytes_in_flight
>= it
->num_bytes
) {
143 // If the flow hasn't started, use the start time.
144 QuicTime::Delta transfer_send_time
= it
->start_time
.Subtract(clock_
->Now());
145 if (clock_
->Now() >= it
->start_time
) {
147 it
->sender
->send_algorithm
->TimeUntilSend(
148 clock_
->Now(), it
->bytes_in_flight
, HAS_RETRANSMITTABLE_DATA
);
150 if (transfer_send_time
< next_send_time
) {
151 next_send_time
= transfer_send_time
;
155 DVLOG(1) << "NextSendTime returning delta(ms):"
156 << next_send_time
.ToMilliseconds() << ", transfer '"
158 return PacketEvent(next_send_time
, transfer
);
161 // NextAck takes into account packet loss in both forward and reverse
162 // direction, as well as correlated losses. And it assumes the receiver acks
163 // every other packet when there is no loss.
164 SendAlgorithmSimulator::PacketEvent
SendAlgorithmSimulator::NextAckEvent() {
165 if (sent_packets_
.empty()) {
166 DVLOG(1) << "No outstanding packets to ack for any transfer.";
167 return PacketEvent(QuicTime::Delta::Infinite(), nullptr);
170 // For each connection, find the next acked packet.
171 QuicTime::Delta ack_time
= QuicTime::Delta::Infinite();
172 Transfer
* transfer
= nullptr;
173 for (vector
<Transfer
>::iterator it
= pending_transfers_
.begin();
174 it
!= pending_transfers_
.end(); ++it
) {
175 QuicTime::Delta transfer_ack_time
= FindNextAcked(&(*it
));
176 if (transfer_ack_time
< ack_time
) {
177 ack_time
= transfer_ack_time
;
182 return PacketEvent(ack_time
, transfer
);
185 QuicTime::Delta
SendAlgorithmSimulator::FindNextAcked(Transfer
* transfer
) {
186 Sender
* sender
= transfer
->sender
;
187 if (sender
->next_acked
== sender
->last_acked
) {
188 // Determine if the next ack is lost only once, to ensure determinism.
190 reverse_loss_rate_
* kuint64max
> simple_random_
.RandUint64();
193 QuicPacketSequenceNumber next_acked
= sender
->last_acked
;
194 QuicTime::Delta next_ack_delay
=
195 FindNextAck(transfer
, sender
->last_acked
, &next_acked
);
196 if (lose_next_ack_
) {
197 next_ack_delay
= FindNextAck(transfer
, next_acked
, &next_acked
);
199 sender
->next_acked
= next_acked
;
200 return next_ack_delay
;
203 QuicTime::Delta
SendAlgorithmSimulator::FindNextAck(
204 const Transfer
* transfer
,
205 QuicPacketSequenceNumber last_acked
,
206 QuicPacketSequenceNumber
* next_acked
) const {
207 *next_acked
= last_acked
;
208 QuicTime::Delta ack_delay
= QuicTime::Delta::Infinite();
209 // Remove any packets that are simulated as lost.
210 for (list
<SentPacket
>::const_iterator it
= sent_packets_
.begin();
211 it
!= sent_packets_
.end(); ++it
) {
212 if (transfer
!= it
->transfer
) {
215 // Skip over any packets less than or equal to last_acked.
216 if (it
->sequence_number
<= last_acked
) {
219 // Lost packets don't trigger an ack.
223 DCHECK_LT(*next_acked
, it
->sequence_number
);
224 // Consider a delayed ack for the current next_acked.
225 if (ack_delay
< it
->ack_time
.Subtract(clock_
->Now())) {
228 *next_acked
= it
->sequence_number
;
229 ack_delay
= it
->ack_time
.Subtract(clock_
->Now());
230 if (HasRecentLostPackets(transfer
, *next_acked
) ||
231 (*next_acked
- last_acked
) >= 2) {
234 ack_delay
= ack_delay
.Add(delayed_ack_timer_
);
237 DVLOG(1) << "FindNextAck found next_acked_:" << transfer
->sender
->next_acked
238 << " last_acked:" << transfer
->sender
->last_acked
239 << " ack_time(ms):" << ack_delay
.ToMilliseconds();
243 bool SendAlgorithmSimulator::HasRecentLostPackets(
244 const Transfer
* transfer
, QuicPacketSequenceNumber next_acked
) const {
245 QuicPacketSequenceNumber last_packet
= transfer
->sender
->last_acked
;
246 for (list
<SentPacket
>::const_iterator it
= sent_packets_
.begin();
247 it
!= sent_packets_
.end() && it
->sequence_number
< next_acked
; ++it
) {
248 if (transfer
!= it
->transfer
) {
251 // Lost packets don't trigger an ack.
255 // Buffer dropped packets are skipped automatically, but still end up
256 // being lost and cause acks to be sent immediately.
257 if (it
->sequence_number
> last_packet
+ 1) {
260 last_packet
= it
->sequence_number
;
265 void SendAlgorithmSimulator::HandlePendingAck(Transfer
* transfer
) {
266 Sender
* sender
= transfer
->sender
;
267 DCHECK_LT(sender
->last_acked
, sender
->next_acked
);
268 SendAlgorithmInterface::CongestionVector acked_packets
;
269 SendAlgorithmInterface::CongestionVector lost_packets
;
270 DVLOG(1) << "Acking packets from:" << sender
->last_acked
271 << " to " << sender
->next_acked
272 << " bytes_in_flight:" << transfer
->bytes_in_flight
273 << " Now():" << (clock_
->Now().ToDebuggingValue() / 1000) << "ms";
274 // Some entries may be missing from the sent_packets_ array, if they were
275 // dropped due to buffer overruns.
276 SentPacket largest_observed
;
277 list
<SentPacket
>::iterator it
= sent_packets_
.begin();
278 while (sender
->last_acked
< sender
->next_acked
) {
279 ++sender
->last_acked
;
280 TransmissionInfo info
= TransmissionInfo();
281 info
.bytes_sent
= kPacketSize
;
282 info
.in_flight
= true;
283 // Find the next SentPacket for this transfer.
284 while (it
->transfer
!= transfer
) {
285 DCHECK(it
!= sent_packets_
.end());
288 // If it's missing from the array, it's a loss.
289 if (it
->sequence_number
> sender
->last_acked
) {
290 DVLOG(1) << "Lost packet:" << sender
->last_acked
291 << " dropped by buffer overflow.";
292 lost_packets
.push_back(std::make_pair(sender
->last_acked
, info
));
296 lost_packets
.push_back(std::make_pair(sender
->last_acked
, info
));
298 acked_packets
.push_back(std::make_pair(sender
->last_acked
, info
));
300 // This packet has been acked or lost, remove it from sent_packets_.
301 largest_observed
= *it
;
302 sent_packets_
.erase(it
++);
305 DCHECK(!largest_observed
.lost
);
306 DVLOG(1) << "Updating RTT from send_time:"
307 << largest_observed
.send_time
.ToDebuggingValue() << " to ack_time:"
308 << largest_observed
.ack_time
.ToDebuggingValue();
309 QuicTime::Delta measured_rtt
=
310 largest_observed
.ack_time
.Subtract(largest_observed
.send_time
);
311 DCHECK_GE(measured_rtt
.ToMicroseconds(), rtt_
.ToMicroseconds());
312 sender
->rtt_stats
->UpdateRtt(measured_rtt
,
313 QuicTime::Delta::Zero(),
315 sender
->send_algorithm
->OnCongestionEvent(
316 true, transfer
->bytes_in_flight
, acked_packets
, lost_packets
);
317 DCHECK_LE(kPacketSize
* (acked_packets
.size() + lost_packets
.size()),
318 transfer
->bytes_in_flight
);
319 transfer
->bytes_in_flight
-=
320 kPacketSize
* (acked_packets
.size() + lost_packets
.size());
322 sender
->RecordStats();
323 transfer
->bytes_acked
+= acked_packets
.size() * kPacketSize
;
324 transfer
->bytes_lost
+= lost_packets
.size() * kPacketSize
;
325 if (transfer
->bytes_acked
>= transfer
->num_bytes
) {
326 // Remove completed transfers and record transfer bandwidth.
327 QuicTime::Delta transfer_time
=
328 clock_
->Now().Subtract(transfer
->start_time
);
329 sender
->last_transfer_loss_rate
= static_cast<float>(transfer
->bytes_lost
) /
330 (transfer
->bytes_lost
+ transfer
->bytes_acked
);
331 sender
->last_transfer_bandwidth
=
332 QuicBandwidth::FromBytesAndTimeDelta(transfer
->num_bytes
,
334 DCHECK_GE(bandwidth_
.ToBitsPerSecond(),
335 sender
->last_transfer_bandwidth
.ToBitsPerSecond());
336 for (vector
<Transfer
>::iterator it
= pending_transfers_
.begin();
337 it
!= pending_transfers_
.end(); ++it
) {
338 if (transfer
== &(*it
)) {
339 pending_transfers_
.erase(it
);
346 void SendAlgorithmSimulator::SendDataNow(Transfer
* transfer
) {
347 Sender
* sender
= transfer
->sender
;
349 DVLOG(1) << "Sending packet:" << sender
->last_sent
350 << " name:" << transfer
->name
351 << " bytes_in_flight:" << transfer
->bytes_in_flight
352 << " cwnd:" << sender
->send_algorithm
->GetCongestionWindow()
353 << " Now():" << (clock_
->Now().ToDebuggingValue() / 1000) << "ms";
354 sender
->send_algorithm
->OnPacketSent(
355 clock_
->Now(), transfer
->bytes_in_flight
,
356 sender
->last_sent
, kPacketSize
, HAS_RETRANSMITTABLE_DATA
);
357 // Lose the packet immediately if the buffer is full.
358 if (sent_packets_
.size() * kPacketSize
< buffer_size_
) {
359 // TODO(ianswett): This buffer simulation is an approximation.
360 // An ack time of zero means loss.
362 forward_loss_rate_
* kuint64max
> simple_random_
.RandUint64();
363 // Handle correlated loss.
364 if (!sent_packets_
.empty() && sent_packets_
.back().lost
&&
365 loss_correlation_
* kuint64max
> simple_random_
.RandUint64()) {
368 DVLOG(1) << "losing packet:" << sender
->last_sent
369 << " name:" << transfer
->name
<< " due to random loss.";
371 // If the number of bytes in flight are less than the bdp, there's
372 // no buffering delay. Bytes lost from the buffer are not counted.
373 QuicByteCount bdp
= bandwidth_
.ToBytesPerPeriod(rtt_
);
374 QuicTime ack_time
= clock_
->Now().Add(rtt_
).Add(sender
->additional_rtt
);
375 if (kPacketSize
> bdp
) {
376 ack_time
= ack_time
.Add(bandwidth_
.TransferTime(kPacketSize
- bdp
));
378 QuicTime queue_ack_time
= sent_packets_
.empty() ? QuicTime::Zero() :
379 sent_packets_
.back().ack_time
.Add(bandwidth_
.TransferTime(kPacketSize
));
380 ack_time
= QuicTime::Max(ack_time
, queue_ack_time
);
381 sent_packets_
.push_back(SentPacket(
382 sender
->last_sent
, clock_
->Now(), ack_time
, packet_lost
, transfer
));
384 DVLOG(1) << "losing packet:" << sender
->last_sent
385 << " name:" << transfer
->name
<< " because the buffer was full.";
387 transfer
->bytes_in_flight
+= kPacketSize
;