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 : send_algorithm(send_algorithm
),
38 last_transfer_bandwidth(QuicBandwidth::Zero()),
39 last_transfer_loss_rate(0) {}
41 SendAlgorithmSimulator::SendAlgorithmSimulator(
43 QuicBandwidth bandwidth
,
46 lose_next_ack_(false),
47 forward_loss_rate_(0),
48 reverse_loss_rate_(0),
50 bandwidth_(bandwidth
),
52 buffer_size_(1000000),
53 delayed_ack_timer_(QuicTime::Delta::FromMilliseconds(100)) {
54 uint32 seed
= base::RandInt(0, std::numeric_limits
<int32
>::max());
55 DVLOG(1) << "Seeding SendAlgorithmSimulator with " << seed
;
56 simple_random_
.set_seed(seed
);
59 SendAlgorithmSimulator::~SendAlgorithmSimulator() {}
61 void SendAlgorithmSimulator::AddTransfer(Sender
* sender
, size_t num_bytes
) {
62 AddTransfer(sender
, num_bytes
, clock_
->Now());
65 void SendAlgorithmSimulator::AddTransfer(
66 Sender
* sender
, size_t num_bytes
, QuicTime start_time
) {
67 pending_transfers_
.push_back(Transfer(sender
, num_bytes
, start_time
));
68 // Record initial stats from when the transfer begins.
69 pending_transfers_
.back().sender
->RecordStats();
72 void SendAlgorithmSimulator::TransferBytes() {
73 TransferBytes(kuint64max
, QuicTime::Delta::Infinite());
76 void SendAlgorithmSimulator::TransferBytes(QuicByteCount max_bytes
,
77 QuicTime::Delta max_time
) {
78 const QuicTime end_time
= max_time
.IsInfinite() ?
79 QuicTime::Zero().Add(QuicTime::Delta::Infinite()) :
80 clock_
->Now().Add(max_time
);
81 QuicByteCount bytes_sent
= 0;
82 while (!pending_transfers_
.empty() &&
83 clock_
->Now() < end_time
&&
84 bytes_sent
< max_bytes
) {
85 // Determine the times of next send and of the next ack arrival.
86 PacketEvent send_event
= NextSendEvent();
87 PacketEvent ack_event
= NextAckEvent();
88 // If both times are infinite, fire a TLP.
89 if (ack_event
.time_delta
.IsInfinite() &&
90 send_event
.time_delta
.IsInfinite()) {
91 DVLOG(1) << "Both times are infinite, simulating a TLP.";
92 // TODO(ianswett): Use a more sophisticated TLP timer or never lose
94 clock_
->AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
95 SendDataNow(&pending_transfers_
.front());
96 } else if (ack_event
.time_delta
< send_event
.time_delta
) {
97 DVLOG(1) << "Handling ack of largest observed:"
98 << ack_event
.transfer
->sender
->next_acked
<< ", advancing time:"
99 << ack_event
.time_delta
.ToMicroseconds() << "us";
100 // Ack data all the data up to ack time and lose any missing sequence
102 clock_
->AdvanceTime(ack_event
.time_delta
);
103 HandlePendingAck(ack_event
.transfer
);
105 DVLOG(1) << "Sending, advancing time:"
106 << send_event
.time_delta
.ToMicroseconds() << "us";
107 clock_
->AdvanceTime(send_event
.time_delta
);
108 SendDataNow(send_event
.transfer
);
109 bytes_sent
+= kPacketSize
;
114 SendAlgorithmSimulator::PacketEvent
SendAlgorithmSimulator::NextSendEvent() {
115 QuicTime::Delta next_send_time
= QuicTime::Delta::Infinite();
116 Transfer
* transfer
= nullptr;
117 for (vector
<Transfer
>::iterator it
= pending_transfers_
.begin();
118 it
!= pending_transfers_
.end(); ++it
) {
119 // If we've already sent enough bytes, wait for them to be acked.
120 if (it
->bytes_acked
+ it
->bytes_in_flight
>= it
->num_bytes
) {
123 // If the flow hasn't started, use the start time.
124 QuicTime::Delta transfer_send_time
= it
->start_time
.Subtract(clock_
->Now());
125 if (clock_
->Now() >= it
->start_time
) {
127 it
->sender
->send_algorithm
->TimeUntilSend(
128 clock_
->Now(), it
->bytes_in_flight
, HAS_RETRANSMITTABLE_DATA
);
130 if (transfer_send_time
< next_send_time
) {
131 next_send_time
= transfer_send_time
;
135 DVLOG(1) << "NextSendTime returning delta(ms):"
136 << next_send_time
.ToMilliseconds();
137 return PacketEvent(next_send_time
, transfer
);
140 // NextAck takes into account packet loss in both forward and reverse
141 // direction, as well as correlated losses. And it assumes the receiver acks
142 // every other packet when there is no loss.
143 SendAlgorithmSimulator::PacketEvent
SendAlgorithmSimulator::NextAckEvent() {
144 if (sent_packets_
.empty()) {
145 DVLOG(1) << "No outstanding packets to ack for any transfer.";
146 return PacketEvent(QuicTime::Delta::Infinite(), nullptr);
149 // For each connection, find the next acked packet.
150 QuicTime::Delta ack_time
= QuicTime::Delta::Infinite();
151 Transfer
* transfer
= nullptr;
152 for (vector
<Transfer
>::iterator it
= pending_transfers_
.begin();
153 it
!= pending_transfers_
.end(); ++it
) {
154 QuicTime::Delta transfer_ack_time
= FindNextAcked(&(*it
));
155 if (transfer_ack_time
< ack_time
) {
156 ack_time
= transfer_ack_time
;
161 return PacketEvent(ack_time
, transfer
);
164 QuicTime::Delta
SendAlgorithmSimulator::FindNextAcked(Transfer
* transfer
) {
165 Sender
* sender
= transfer
->sender
;
166 if (sender
->next_acked
== sender
->last_acked
) {
167 // Determine if the next ack is lost only once, to ensure determinism.
169 reverse_loss_rate_
* kuint64max
> simple_random_
.RandUint64();
172 QuicPacketSequenceNumber next_acked
= sender
->last_acked
;
173 QuicTime::Delta next_ack_delay
=
174 FindNextAck(transfer
, sender
->last_acked
, &next_acked
);
175 if (lose_next_ack_
) {
176 next_ack_delay
= FindNextAck(transfer
, next_acked
, &next_acked
);
178 sender
->next_acked
= next_acked
;
179 return next_ack_delay
;
182 QuicTime::Delta
SendAlgorithmSimulator::FindNextAck(
183 const Transfer
* transfer
,
184 QuicPacketSequenceNumber last_acked
,
185 QuicPacketSequenceNumber
* next_acked
) const {
186 *next_acked
= last_acked
;
187 QuicTime::Delta ack_delay
= QuicTime::Delta::Infinite();
188 // Remove any packets that are simulated as lost.
189 for (list
<SentPacket
>::const_iterator it
= sent_packets_
.begin();
190 it
!= sent_packets_
.end(); ++it
) {
191 if (transfer
!= it
->transfer
) {
194 // Skip over any packets less than or equal to last_acked.
195 if (it
->sequence_number
<= last_acked
) {
198 // Lost packets don't trigger an ack.
202 DCHECK_LT(*next_acked
, it
->sequence_number
);
203 // Consider a delayed ack for the current next_acked.
204 if (ack_delay
< it
->ack_time
.Subtract(clock_
->Now())) {
207 *next_acked
= it
->sequence_number
;
208 ack_delay
= it
->ack_time
.Subtract(clock_
->Now());
209 if (HasRecentLostPackets(transfer
, *next_acked
) ||
210 (*next_acked
- last_acked
) >= 2) {
213 ack_delay
= ack_delay
.Add(delayed_ack_timer_
);
216 DVLOG(1) << "FindNextAcked found next_acked_:"
217 << transfer
->sender
->next_acked
218 << " last_acked:" << transfer
->sender
->last_acked
219 << " ack_delay(ms):" << ack_delay
.ToMilliseconds();
223 bool SendAlgorithmSimulator::HasRecentLostPackets(
224 const Transfer
* transfer
, QuicPacketSequenceNumber next_acked
) const {
225 QuicPacketSequenceNumber last_packet
= transfer
->sender
->last_acked
;
226 for (list
<SentPacket
>::const_iterator it
= sent_packets_
.begin();
227 it
!= sent_packets_
.end() && it
->sequence_number
< next_acked
; ++it
) {
228 if (transfer
!= it
->transfer
) {
231 // Lost packets don't trigger an ack.
235 // Buffer dropped packets are skipped automatically, but still end up
236 // being lost and cause acks to be sent immediately.
237 if (it
->sequence_number
> last_packet
+ 1) {
240 last_packet
= it
->sequence_number
;
245 void SendAlgorithmSimulator::HandlePendingAck(Transfer
* transfer
) {
246 Sender
* sender
= transfer
->sender
;
247 DCHECK_LT(sender
->last_acked
, sender
->next_acked
);
248 SendAlgorithmInterface::CongestionVector acked_packets
;
249 SendAlgorithmInterface::CongestionVector lost_packets
;
250 DVLOG(1) << "Acking packets from:" << sender
->last_acked
251 << " to " << sender
->next_acked
252 << " bytes_in_flight:" << transfer
->bytes_in_flight
253 << " Now():" << (clock_
->Now().ToDebuggingValue() / 1000) << "ms";
254 // Some entries may be missing from the sent_packets_ array, if they were
255 // dropped due to buffer overruns.
256 SentPacket largest_observed
;
257 list
<SentPacket
>::iterator it
= sent_packets_
.begin();
258 while (sender
->last_acked
< sender
->next_acked
) {
259 ++sender
->last_acked
;
260 TransmissionInfo info
= TransmissionInfo();
261 info
.bytes_sent
= kPacketSize
;
262 info
.in_flight
= true;
263 // Find the next SentPacket for this transfer.
264 while (it
->transfer
!= transfer
) {
265 DCHECK(it
!= sent_packets_
.end());
268 // If it's missing from the array, it's a loss.
269 if (it
->sequence_number
> sender
->last_acked
) {
270 DVLOG(1) << "Lost packet:" << sender
->last_acked
271 << " dropped by buffer overflow.";
272 lost_packets
.push_back(make_pair(sender
->last_acked
, info
));
276 lost_packets
.push_back(make_pair(sender
->last_acked
, info
));
278 acked_packets
.push_back(make_pair(sender
->last_acked
, info
));
280 // This packet has been acked or lost, remove it from sent_packets_.
281 largest_observed
= *it
;
282 sent_packets_
.erase(it
++);
285 DCHECK(largest_observed
.ack_time
.IsInitialized());
286 DVLOG(1) << "Updating RTT from send_time:"
287 << largest_observed
.send_time
.ToDebuggingValue() << " to ack_time:"
288 << largest_observed
.ack_time
.ToDebuggingValue();
289 QuicTime::Delta measured_rtt
=
290 largest_observed
.ack_time
.Subtract(largest_observed
.send_time
);
291 DCHECK_GE(measured_rtt
.ToMicroseconds(), rtt_
.ToMicroseconds());
292 sender
->rtt_stats
->UpdateRtt(measured_rtt
,
293 QuicTime::Delta::Zero(),
295 sender
->send_algorithm
->OnCongestionEvent(
296 true, transfer
->bytes_in_flight
, acked_packets
, lost_packets
);
297 DCHECK_LE(kPacketSize
* (acked_packets
.size() + lost_packets
.size()),
298 transfer
->bytes_in_flight
);
299 transfer
->bytes_in_flight
-=
300 kPacketSize
* (acked_packets
.size() + lost_packets
.size());
302 sender
->RecordStats();
303 transfer
->bytes_acked
+= acked_packets
.size() * kPacketSize
;
304 transfer
->bytes_lost
+= lost_packets
.size() * kPacketSize
;
305 if (transfer
->bytes_acked
>= transfer
->num_bytes
) {
306 // Remove completed transfers and record transfer bandwidth.
307 QuicTime::Delta transfer_time
=
308 clock_
->Now().Subtract(transfer
->start_time
);
309 sender
->last_transfer_loss_rate
= static_cast<float>(transfer
->bytes_lost
) /
310 (transfer
->bytes_lost
+ transfer
->bytes_acked
);
311 sender
->last_transfer_bandwidth
=
312 QuicBandwidth::FromBytesAndTimeDelta(transfer
->num_bytes
,
314 DCHECK_GE(bandwidth_
.ToBitsPerSecond(),
315 sender
->last_transfer_bandwidth
.ToBitsPerSecond());
316 for (vector
<Transfer
>::iterator it
= pending_transfers_
.begin();
317 it
!= pending_transfers_
.end(); ++it
) {
318 if (transfer
== &(*it
)) {
319 pending_transfers_
.erase(it
);
326 void SendAlgorithmSimulator::SendDataNow(Transfer
* transfer
) {
327 Sender
* sender
= transfer
->sender
;
329 DVLOG(1) << "Sending packet:" << sender
->last_sent
330 << " bytes_in_flight:" << transfer
->bytes_in_flight
331 << " Now():" << (clock_
->Now().ToDebuggingValue() / 1000) << "ms";
332 sender
->send_algorithm
->OnPacketSent(
333 clock_
->Now(), transfer
->bytes_in_flight
,
334 sender
->last_sent
, kPacketSize
, HAS_RETRANSMITTABLE_DATA
);
335 // Lose the packet immediately if the buffer is full.
336 if (sent_packets_
.size() * kPacketSize
< buffer_size_
) {
337 // TODO(ianswett): This buffer simulation is an approximation.
338 // An ack time of zero means loss.
340 forward_loss_rate_
* kuint64max
> simple_random_
.RandUint64();
341 // Handle correlated loss.
342 if (!sent_packets_
.empty() && sent_packets_
.back().lost
&&
343 loss_correlation_
* kuint64max
> simple_random_
.RandUint64()) {
346 DVLOG(1) << "losing packet:" << sender
->last_sent
347 << " due to random loss.";
349 // If the number of bytes in flight are less than the bdp, there's
350 // no buffering delay. Bytes lost from the buffer are not counted.
351 QuicByteCount bdp
= bandwidth_
.ToBytesPerPeriod(rtt_
);
352 QuicTime ack_time
= clock_
->Now().Add(rtt_
);
353 if (kPacketSize
> bdp
) {
354 ack_time
= ack_time
.Add(bandwidth_
.TransferTime(kPacketSize
- bdp
));
356 QuicTime queue_ack_time
= sent_packets_
.empty() ? QuicTime::Zero() :
357 sent_packets_
.back().ack_time
.Add(bandwidth_
.TransferTime(kPacketSize
));
358 ack_time
= QuicTime::Max(ack_time
, queue_ack_time
);
359 sent_packets_
.push_back(SentPacket(
360 sender
->last_sent
, clock_
->Now(), ack_time
, packet_lost
, transfer
));
362 DVLOG(1) << "losing packet:" << sender
->last_sent
363 << " because the buffer was full.";
365 transfer
->bytes_in_flight
+= kPacketSize
;
368 // Advance the time by |delta| without sending anything.
369 void SendAlgorithmSimulator::AdvanceTime(QuicTime::Delta delta
) {
370 clock_
->AdvanceTime(delta
);