| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "net/quic/congestion_control/send_algorithm_simulator.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/rand_util.h" | |
| 11 #include "net/quic/crypto/quic_random.h" | |
| 12 | |
| 13 using std::list; | |
| 14 using std::max; | |
| 15 using std::min; | |
| 16 using std::string; | |
| 17 using std::vector; | |
| 18 | |
| 19 namespace net { | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 const QuicByteCount kPacketSize = 1200; | |
| 24 | |
| 25 } // namespace | |
| 26 | |
| 27 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface* send_algorithm, | |
| 28 RttStats* rtt_stats) | |
| 29 : Sender(send_algorithm, rtt_stats, QuicTime::Delta::Zero()) {} | |
| 30 | |
| 31 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface* send_algorithm, | |
| 32 RttStats* rtt_stats, | |
| 33 QuicTime::Delta additional_rtt) | |
| 34 : send_algorithm(send_algorithm), | |
| 35 rtt_stats(rtt_stats), | |
| 36 additional_rtt(additional_rtt), | |
| 37 last_sent(0), | |
| 38 last_acked(0), | |
| 39 next_acked(1), | |
| 40 max_cwnd(0), | |
| 41 min_cwnd(100000), | |
| 42 max_cwnd_drop(0), | |
| 43 last_cwnd(0), | |
| 44 last_transfer_bandwidth(QuicBandwidth::Zero()), | |
| 45 last_transfer_loss_rate(0) {} | |
| 46 | |
| 47 SendAlgorithmSimulator::Transfer::Transfer(Sender* sender, | |
| 48 QuicByteCount num_bytes, | |
| 49 QuicTime start_time, | |
| 50 string name) | |
| 51 : sender(sender), | |
| 52 num_bytes(num_bytes), | |
| 53 bytes_acked(0), | |
| 54 bytes_lost(0), | |
| 55 bytes_in_flight(0), | |
| 56 start_time(start_time), | |
| 57 name(name) {} | |
| 58 | |
| 59 SendAlgorithmSimulator::SendAlgorithmSimulator( | |
| 60 MockClock* clock, | |
| 61 QuicBandwidth bandwidth, | |
| 62 QuicTime::Delta rtt) | |
| 63 : clock_(clock), | |
| 64 lose_next_ack_(false), | |
| 65 forward_loss_rate_(0), | |
| 66 reverse_loss_rate_(0), | |
| 67 loss_correlation_(0), | |
| 68 bandwidth_(bandwidth), | |
| 69 rtt_(rtt), | |
| 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); | |
| 75 } | |
| 76 | |
| 77 SendAlgorithmSimulator::~SendAlgorithmSimulator() {} | |
| 78 | |
| 79 void SendAlgorithmSimulator::AddTransfer(Sender* sender, size_t num_bytes) { | |
| 80 AddTransfer(sender, num_bytes, clock_->Now(), | |
| 81 StringPrintf("#%zu", pending_transfers_.size())); | |
| 82 } | |
| 83 | |
| 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(); | |
| 89 } | |
| 90 | |
| 91 void SendAlgorithmSimulator::TransferBytes() { | |
| 92 TransferBytes(kuint64max, QuicTime::Delta::Infinite()); | |
| 93 } | |
| 94 | |
| 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 | |
| 112 // the last ack? | |
| 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 | |
| 120 // numbers. | |
| 121 clock_->AdvanceTime(ack_event.time_delta); | |
| 122 HandlePendingAck(ack_event.transfer); | |
| 123 } else { | |
| 124 DVLOG(1) << "Sending transfer '" << send_event.transfer->name | |
| 125 << "', advancing time:" << send_event.time_delta.ToMicroseconds() | |
| 126 << "us"; | |
| 127 clock_->AdvanceTime(send_event.time_delta); | |
| 128 SendDataNow(send_event.transfer); | |
| 129 bytes_sent += kPacketSize; | |
| 130 } | |
| 131 } | |
| 132 } | |
| 133 | |
| 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) { | |
| 141 continue; | |
| 142 } | |
| 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) { | |
| 146 transfer_send_time = | |
| 147 it->sender->send_algorithm->TimeUntilSend( | |
| 148 clock_->Now(), it->bytes_in_flight, HAS_RETRANSMITTABLE_DATA); | |
| 149 } | |
| 150 if (transfer_send_time < next_send_time) { | |
| 151 next_send_time = transfer_send_time; | |
| 152 transfer = &(*it); | |
| 153 } | |
| 154 } | |
| 155 DVLOG(1) << "NextSendTime returning delta(ms):" | |
| 156 << next_send_time.ToMilliseconds() << ", transfer '" | |
| 157 << transfer->name; | |
| 158 return PacketEvent(next_send_time, transfer); | |
| 159 } | |
| 160 | |
| 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); | |
| 168 } | |
| 169 | |
| 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; | |
| 178 transfer = &(*it); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 return PacketEvent(ack_time, transfer); | |
| 183 } | |
| 184 | |
| 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. | |
| 189 lose_next_ack_ = | |
| 190 reverse_loss_rate_ * kuint64max > simple_random_.RandUint64(); | |
| 191 } | |
| 192 | |
| 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); | |
| 198 } | |
| 199 sender->next_acked = next_acked; | |
| 200 return next_ack_delay; | |
| 201 } | |
| 202 | |
| 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) { | |
| 213 continue; | |
| 214 } | |
| 215 // Skip over any packets less than or equal to last_acked. | |
| 216 if (it->sequence_number <= last_acked) { | |
| 217 continue; | |
| 218 } | |
| 219 // Lost packets don't trigger an ack. | |
| 220 if (it->lost) { | |
| 221 continue; | |
| 222 } | |
| 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())) { | |
| 226 break; | |
| 227 } | |
| 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) { | |
| 232 break; | |
| 233 } | |
| 234 ack_delay = ack_delay.Add(delayed_ack_timer_); | |
| 235 } | |
| 236 | |
| 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(); | |
| 240 return ack_delay; | |
| 241 } | |
| 242 | |
| 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) { | |
| 249 continue; | |
| 250 } | |
| 251 // Lost packets don't trigger an ack. | |
| 252 if (it->lost) { | |
| 253 return true; | |
| 254 } | |
| 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) { | |
| 258 return true; | |
| 259 } | |
| 260 last_packet = it->sequence_number; | |
| 261 } | |
| 262 return false; | |
| 263 } | |
| 264 | |
| 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()); | |
| 286 ++it; | |
| 287 } | |
| 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)); | |
| 293 continue; | |
| 294 } | |
| 295 if (it->lost) { | |
| 296 lost_packets.push_back(std::make_pair(sender->last_acked, info)); | |
| 297 } else { | |
| 298 acked_packets.push_back(std::make_pair(sender->last_acked, info)); | |
| 299 } | |
| 300 // This packet has been acked or lost, remove it from sent_packets_. | |
| 301 largest_observed = *it; | |
| 302 sent_packets_.erase(it++); | |
| 303 } | |
| 304 | |
| 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(), | |
| 314 clock_->Now()); | |
| 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()); | |
| 321 | |
| 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, | |
| 333 transfer_time); | |
| 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); | |
| 340 break; | |
| 341 } | |
| 342 } | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 void SendAlgorithmSimulator::SendDataNow(Transfer* transfer) { | |
| 347 Sender* sender = transfer->sender; | |
| 348 ++sender->last_sent; | |
| 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. | |
| 361 bool packet_lost = | |
| 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()) { | |
| 366 packet_lost = true; | |
| 367 } | |
| 368 DVLOG(1) << "losing packet:" << sender->last_sent | |
| 369 << " name:" << transfer->name << " due to random loss."; | |
| 370 | |
| 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)); | |
| 377 } | |
| 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)); | |
| 383 } else { | |
| 384 DVLOG(1) << "losing packet:" << sender->last_sent | |
| 385 << " name:" << transfer->name << " because the buffer was full."; | |
| 386 } | |
| 387 transfer->bytes_in_flight += kPacketSize; | |
| 388 } | |
| 389 | |
| 390 // Advance the time by |delta| without sending anything. | |
| 391 void SendAlgorithmSimulator::AdvanceTime(QuicTime::Delta delta) { | |
| 392 clock_->AdvanceTime(delta); | |
| 393 } | |
| 394 | |
| 395 } // namespace net | |
| OLD | NEW |