1 // Copyright (c) 2013 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/inter_arrival_sender.h" 6 7 namespace net { 8 9 namespace { 10 const int64 kProbeBitrateKBytesPerSecond = 1200; // 9.6 Mbit/s 11 const float kPacketLossBitrateReduction = 0.7f; 12 const float kUncertainSafetyMargin = 0.7f; 13 const float kMaxBitrateReduction = 0.9f; 14 const float kMinBitrateReduction = 0.05f; 15 const uint64 kMinBitrateKbit = 10; 16 const int kInitialRttMs = 60; // At a typical RTT 60 ms. 17 const float kAlpha = 0.125f; 18 const float kOneMinusAlpha = 1 - kAlpha; 19 20 static const int kBitrateSmoothingPeriodMs = 1000; 21 static const int kMinBitrateSmoothingPeriodMs = 500; 22 23 } // namespace 24 25 InterArrivalSender::InterArrivalSender(const QuicClock* clock) 26 : probing_(true), 27 max_segment_size_(kDefaultMaxPacketSize), 28 current_bandwidth_(QuicBandwidth::Zero()), 29 smoothed_rtt_(QuicTime::Delta::Zero()), 30 channel_estimator_(new ChannelEstimator()), 31 bitrate_ramp_up_(new InterArrivalBitrateRampUp(clock)), 32 overuse_detector_(new InterArrivalOveruseDetector()), 33 probe_(new InterArrivalProbe(max_segment_size_)), 34 state_machine_(new InterArrivalStateMachine(clock)), 35 paced_sender_(new PacedSender(QuicBandwidth::FromKBytesPerSecond( 36 kProbeBitrateKBytesPerSecond), max_segment_size_)), 37 accumulated_number_of_lost_packets_(0), 38 bandwidth_usage_state_(kBandwidthSteady), 39 back_down_time_(QuicTime::Zero()), 40 back_down_bandwidth_(QuicBandwidth::Zero()), 41 back_down_congestion_delay_(QuicTime::Delta::Zero()) { 42 } 43 44 InterArrivalSender::~InterArrivalSender() { 45 } 46 47 void InterArrivalSender::SetFromConfig(const QuicConfig& config, 48 bool is_server) { 49 } 50 51 void InterArrivalSender::SetMaxPacketSize(QuicByteCount max_packet_size) { 52 max_segment_size_ = max_packet_size; 53 paced_sender_->set_max_segment_size(max_segment_size_); 54 probe_->set_max_segment_size(max_segment_size_); 55 } 56 57 // TODO(pwestin): this is really inefficient (4% CPU on the GFE loadtest). 58 // static 59 QuicBandwidth InterArrivalSender::CalculateSentBandwidth( 60 const SendAlgorithmInterface::SentPacketsMap& sent_packets_map, 61 QuicTime feedback_receive_time) { 62 const QuicTime::Delta kBitrateSmoothingPeriod = 63 QuicTime::Delta::FromMilliseconds(kBitrateSmoothingPeriodMs); 64 const QuicTime::Delta kMinBitrateSmoothingPeriod = 65 QuicTime::Delta::FromMilliseconds(kMinBitrateSmoothingPeriodMs); 66 67 QuicByteCount sum_bytes_sent = 0; 68 69 // Sum packet from new until they are kBitrateSmoothingPeriod old. 70 SendAlgorithmInterface::SentPacketsMap::const_reverse_iterator history_rit = 71 sent_packets_map.rbegin(); 72 73 QuicTime::Delta max_diff = QuicTime::Delta::Zero(); 74 for (; history_rit != sent_packets_map.rend(); ++history_rit) { 75 QuicTime::Delta diff = 76 feedback_receive_time.Subtract(history_rit->second->send_timestamp()); 77 if (diff > kBitrateSmoothingPeriod) { 78 break; 79 } 80 sum_bytes_sent += history_rit->second->bytes_sent(); 81 max_diff = diff; 82 } 83 if (max_diff < kMinBitrateSmoothingPeriod) { 84 // No estimate. 85 return QuicBandwidth::Zero(); 86 } 87 return QuicBandwidth::FromBytesAndTimeDelta(sum_bytes_sent, max_diff); 88 } 89 90 void InterArrivalSender::OnIncomingQuicCongestionFeedbackFrame( 91 const QuicCongestionFeedbackFrame& feedback, 92 QuicTime feedback_receive_time, 93 const SentPacketsMap& sent_packets) { 94 DCHECK(feedback.type == kInterArrival); 95 96 if (feedback.type != kInterArrival) { 97 return; 98 } 99 100 QuicBandwidth sent_bandwidth = CalculateSentBandwidth(sent_packets, 101 feedback_receive_time); 102 103 TimeMap::const_iterator received_it; 104 for (received_it = feedback.inter_arrival.received_packet_times.begin(); 105 received_it != feedback.inter_arrival.received_packet_times.end(); 106 ++received_it) { 107 QuicPacketSequenceNumber sequence_number = received_it->first; 108 109 SentPacketsMap::const_iterator sent_it = sent_packets.find(sequence_number); 110 if (sent_it == sent_packets.end()) { 111 // Too old data; ignore and move forward. 112 DVLOG(1) << "Too old feedback move forward, sequence_number:" 113 << sequence_number; 114 continue; 115 } 116 QuicTime time_received = received_it->second; 117 QuicTime time_sent = sent_it->second->send_timestamp(); 118 QuicByteCount bytes_sent = sent_it->second->bytes_sent(); 119 120 channel_estimator_->OnAcknowledgedPacket( 121 sequence_number, bytes_sent, time_sent, time_received); 122 if (probing_) { 123 probe_->OnIncomingFeedback( 124 sequence_number, bytes_sent, time_sent, time_received); 125 } else { 126 bool last_of_send_time = false; 127 SentPacketsMap::const_iterator next_sent_it = ++sent_it; 128 if (next_sent_it == sent_packets.end()) { 129 // No more sent packets; hence this must be the last. 130 last_of_send_time = true; 131 } else { 132 if (time_sent != next_sent_it->second->send_timestamp()) { 133 // Next sent packet have a different send time. 134 last_of_send_time = true; 135 } 136 } 137 overuse_detector_->OnAcknowledgedPacket( 138 sequence_number, time_sent, last_of_send_time, time_received); 139 } 140 } 141 if (probing_) { 142 probing_ = ProbingPhase(feedback_receive_time); 143 return; 144 } 145 146 bool packet_loss_event = false; 147 if (accumulated_number_of_lost_packets_ != 148 feedback.inter_arrival.accumulated_number_of_lost_packets) { 149 accumulated_number_of_lost_packets_ = 150 feedback.inter_arrival.accumulated_number_of_lost_packets; 151 packet_loss_event = true; 152 } 153 InterArrivalState state = state_machine_->GetInterArrivalState(); 154 155 if (state == kInterArrivalStatePacketLoss || 156 state == kInterArrivalStateCompetingTcpFLow) { 157 if (packet_loss_event) { 158 if (!state_machine_->PacketLossEvent()) { 159 // Less than one RTT since last PacketLossEvent. 160 return; 161 } 162 EstimateBandwidthAfterLossEvent(feedback_receive_time); 163 } else { 164 EstimateNewBandwidth(feedback_receive_time, sent_bandwidth); 165 } 166 return; 167 } 168 EstimateDelayBandwidth(feedback_receive_time, sent_bandwidth); 169 } 170 171 bool InterArrivalSender::ProbingPhase(QuicTime feedback_receive_time) { 172 QuicBandwidth available_channel_estimate = QuicBandwidth::Zero(); 173 if (!probe_->GetEstimate(&available_channel_estimate)) { 174 // Continue probing phase. 175 return true; 176 } 177 QuicBandwidth channel_estimate = QuicBandwidth::Zero(); 178 ChannelEstimateState channel_estimator_state = 179 channel_estimator_->GetChannelEstimate(&channel_estimate); 180 181 QuicBandwidth new_rate = 182 available_channel_estimate.Scale(kUncertainSafetyMargin); 183 184 switch (channel_estimator_state) { 185 case kChannelEstimateUnknown: 186 channel_estimate = available_channel_estimate; 187 break; 188 case kChannelEstimateUncertain: 189 channel_estimate = channel_estimate.Scale(kUncertainSafetyMargin); 190 break; 191 case kChannelEstimateGood: 192 // Do nothing. 193 break; 194 } 195 new_rate = std::max(new_rate, 196 QuicBandwidth::FromKBitsPerSecond(kMinBitrateKbit)); 197 198 bitrate_ramp_up_->Reset(new_rate, available_channel_estimate, 199 channel_estimate); 200 201 current_bandwidth_ = new_rate; 202 paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, new_rate); 203 DVLOG(1) << "Probe result; new rate:" 204 << new_rate.ToKBitsPerSecond() << " Kbits/s " 205 << " available estimate:" 206 << available_channel_estimate.ToKBitsPerSecond() << " Kbits/s " 207 << " channel estimate:" 208 << channel_estimate.ToKBitsPerSecond() << " Kbits/s "; 209 return false; 210 } 211 212 void InterArrivalSender::OnPacketAcked( 213 QuicPacketSequenceNumber /*acked_sequence_number*/, 214 QuicByteCount acked_bytes, 215 QuicTime::Delta rtt) { 216 // RTT can't be negative. 217 DCHECK_LE(0, rtt.ToMicroseconds()); 218 219 if (probing_) { 220 probe_->OnAcknowledgedPacket(acked_bytes); 221 } 222 223 if (rtt.IsInfinite()) { 224 return; 225 } 226 227 if (smoothed_rtt_.IsZero()) { 228 smoothed_rtt_ = rtt; 229 } else { 230 smoothed_rtt_ = QuicTime::Delta::FromMicroseconds( 231 kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() + 232 kAlpha * rtt.ToMicroseconds()); 233 } 234 state_machine_->set_rtt(smoothed_rtt_); 235 } 236 237 void InterArrivalSender::OnPacketLost( 238 QuicPacketSequenceNumber /*sequence_number*/, 239 QuicTime ack_receive_time) { 240 // Packet loss was reported. 241 if (!probing_) { 242 if (!state_machine_->PacketLossEvent()) { 243 // Less than one RTT since last PacketLossEvent. 244 return; 245 } 246 // Calculate new pace rate. 247 EstimateBandwidthAfterLossEvent(ack_receive_time); 248 } 249 } 250 251 bool InterArrivalSender::OnPacketSent( 252 QuicTime sent_time, 253 QuicPacketSequenceNumber sequence_number, 254 QuicByteCount bytes, 255 TransmissionType /*transmission_type*/, 256 HasRetransmittableData /*has_retransmittable_data*/) { 257 if (probing_) { 258 probe_->OnPacketSent(bytes); 259 } 260 paced_sender_->OnPacketSent(sent_time, bytes); 261 return true; 262 } 263 264 void InterArrivalSender::OnRetransmissionTimeout() { 265 // TODO(ianswett): Decrease the available bandwidth. 266 } 267 268 void InterArrivalSender::OnPacketAbandoned( 269 QuicPacketSequenceNumber /*sequence_number*/, 270 QuicByteCount abandoned_bytes) { 271 // TODO(pwestin): use for out outer_congestion_window_ logic. 272 if (probing_) { 273 probe_->OnAcknowledgedPacket(abandoned_bytes); 274 } 275 } 276 277 QuicTime::Delta InterArrivalSender::TimeUntilSend( 278 QuicTime now, 279 TransmissionType /*transmission_type*/, 280 HasRetransmittableData has_retransmittable_data, 281 IsHandshake /*handshake*/) { 282 // TODO(pwestin): implement outer_congestion_window_ logic. 283 QuicTime::Delta outer_window = QuicTime::Delta::Zero(); 284 285 if (probing_) { 286 if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA && 287 probe_->GetAvailableCongestionWindow() == 0) { 288 outer_window = QuicTime::Delta::Infinite(); 289 } 290 } 291 return paced_sender_->TimeUntilSend(now, outer_window); 292 } 293 294 void InterArrivalSender::EstimateDelayBandwidth(QuicTime feedback_receive_time, 295 QuicBandwidth sent_bandwidth) { 296 QuicTime::Delta estimated_congestion_delay = QuicTime::Delta::Zero(); 297 BandwidthUsage new_bandwidth_usage_state = 298 overuse_detector_->GetState(&estimated_congestion_delay); 299 300 switch (new_bandwidth_usage_state) { 301 case kBandwidthDraining: 302 case kBandwidthUnderUsing: 303 // Hold our current bitrate. 304 break; 305 case kBandwidthOverUsing: 306 if (!state_machine_->IncreasingDelayEvent()) { 307 // Less than one RTT since last IncreasingDelayEvent. 308 return; 309 } 310 EstimateBandwidthAfterDelayEvent(feedback_receive_time, 311 estimated_congestion_delay); 312 break; 313 case kBandwidthSteady: 314 // Calculate new pace rate. 315 if (bandwidth_usage_state_ == kBandwidthDraining || 316 bandwidth_usage_state_ == kBandwidthOverUsing) { 317 EstimateNewBandwidthAfterDraining(feedback_receive_time, 318 estimated_congestion_delay); 319 } else { 320 EstimateNewBandwidth(feedback_receive_time, sent_bandwidth); 321 } 322 break; 323 } 324 bandwidth_usage_state_ = new_bandwidth_usage_state; 325 } 326 327 QuicBandwidth InterArrivalSender::BandwidthEstimate() const { 328 return current_bandwidth_; 329 } 330 331 QuicTime::Delta InterArrivalSender::SmoothedRtt() const { 332 if (smoothed_rtt_.IsZero()) { 333 return QuicTime::Delta::FromMilliseconds(kInitialRttMs); 334 } 335 return smoothed_rtt_; 336 } 337 338 QuicTime::Delta InterArrivalSender::RetransmissionDelay() const { 339 // TODO(pwestin): Calculate and return retransmission delay. 340 // Use 2 * the smoothed RTT for now. 341 return smoothed_rtt_.Add(smoothed_rtt_); 342 } 343 344 QuicByteCount InterArrivalSender::GetCongestionWindow() const { 345 return 0; 346 } 347 348 void InterArrivalSender::EstimateNewBandwidth(QuicTime feedback_receive_time, 349 QuicBandwidth sent_bandwidth) { 350 QuicBandwidth new_bandwidth = bitrate_ramp_up_->GetNewBitrate(sent_bandwidth); 351 if (current_bandwidth_ == new_bandwidth) { 352 return; 353 } 354 current_bandwidth_ = new_bandwidth; 355 state_machine_->IncreaseBitrateDecision(); 356 357 QuicBandwidth channel_estimate = QuicBandwidth::Zero(); 358 ChannelEstimateState channel_estimator_state = 359 channel_estimator_->GetChannelEstimate(&channel_estimate); 360 361 if (channel_estimator_state == kChannelEstimateGood) { 362 bitrate_ramp_up_->UpdateChannelEstimate(channel_estimate); 363 } 364 paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, 365 current_bandwidth_); 366 DVLOG(1) << "New bandwidth estimate in steady state:" 367 << current_bandwidth_.ToKBitsPerSecond() 368 << " Kbits/s"; 369 } 370 371 // Did we drain the network buffers in our expected pace? 372 void InterArrivalSender::EstimateNewBandwidthAfterDraining( 373 QuicTime feedback_receive_time, 374 QuicTime::Delta estimated_congestion_delay) { 375 if (current_bandwidth_ > back_down_bandwidth_) { 376 // Do nothing, our current bandwidth is higher than our bandwidth at the 377 // previous back down. 378 DVLOG(1) << "Current bandwidth estimate is higher than before draining"; 379 return; 380 } 381 if (estimated_congestion_delay >= back_down_congestion_delay_) { 382 // Do nothing, our estimated delay have increased. 383 DVLOG(1) << "Current delay estimate is higher than before draining"; 384 return; 385 } 386 DCHECK(back_down_time_.IsInitialized()); 387 QuicTime::Delta buffer_reduction = 388 back_down_congestion_delay_.Subtract(estimated_congestion_delay); 389 QuicTime::Delta elapsed_time = 390 feedback_receive_time.Subtract(back_down_time_).Subtract(SmoothedRtt()); 391 392 QuicBandwidth new_estimate = QuicBandwidth::Zero(); 393 if (buffer_reduction >= elapsed_time) { 394 // We have drained more than the elapsed time... go back to our old rate. 395 new_estimate = back_down_bandwidth_; 396 } else { 397 float fraction_of_rate = 398 static_cast<float>(buffer_reduction.ToMicroseconds()) / 399 elapsed_time.ToMicroseconds(); // < 1.0 400 401 QuicBandwidth draining_rate = back_down_bandwidth_.Scale(fraction_of_rate); 402 QuicBandwidth max_estimated_draining_rate = 403 back_down_bandwidth_.Subtract(current_bandwidth_); 404 if (draining_rate > max_estimated_draining_rate) { 405 // We drained faster than our old send rate, go back to our old rate. 406 new_estimate = back_down_bandwidth_; 407 } else { 408 // Use our drain rate and our kMinBitrateReduction to go to our 409 // new estimate. 410 new_estimate = std::max(current_bandwidth_, 411 current_bandwidth_.Add(draining_rate).Scale( 412 1.0f - kMinBitrateReduction)); 413 DVLOG(1) << "Draining calculation; current rate:" 414 << current_bandwidth_.ToKBitsPerSecond() << " Kbits/s " 415 << "draining rate:" 416 << draining_rate.ToKBitsPerSecond() << " Kbits/s " 417 << "new estimate:" 418 << new_estimate.ToKBitsPerSecond() << " Kbits/s " 419 << " buffer reduction:" 420 << buffer_reduction.ToMicroseconds() << " us " 421 << " elapsed time:" 422 << elapsed_time.ToMicroseconds() << " us "; 423 } 424 } 425 if (new_estimate == current_bandwidth_) { 426 return; 427 } 428 429 QuicBandwidth channel_estimate = QuicBandwidth::Zero(); 430 ChannelEstimateState channel_estimator_state = 431 channel_estimator_->GetChannelEstimate(&channel_estimate); 432 433 // TODO(pwestin): we need to analyze channel_estimate too. 434 switch (channel_estimator_state) { 435 case kChannelEstimateUnknown: 436 channel_estimate = current_bandwidth_; 437 break; 438 case kChannelEstimateUncertain: 439 channel_estimate = channel_estimate.Scale(kUncertainSafetyMargin); 440 break; 441 case kChannelEstimateGood: 442 // Do nothing, estimate is accurate. 443 break; 444 } 445 bitrate_ramp_up_->Reset(new_estimate, back_down_bandwidth_, channel_estimate); 446 state_machine_->IncreaseBitrateDecision(); 447 paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, new_estimate); 448 current_bandwidth_ = new_estimate; 449 DVLOG(1) << "New bandwidth estimate after draining:" 450 << new_estimate.ToKBitsPerSecond() << " Kbits/s"; 451 } 452 453 void InterArrivalSender::EstimateBandwidthAfterDelayEvent( 454 QuicTime feedback_receive_time, 455 QuicTime::Delta estimated_congestion_delay) { 456 QuicByteCount estimated_byte_buildup = 457 current_bandwidth_.ToBytesPerPeriod(estimated_congestion_delay); 458 459 // To drain all build up buffer within one RTT we need to reduce the 460 // bitrate with the following. 461 // TODO(pwestin): this is a crude first implementation. 462 int64 draining_rate_per_rtt = (estimated_byte_buildup * 463 kNumMicrosPerSecond) / SmoothedRtt().ToMicroseconds(); 464 465 float decrease_factor = 466 draining_rate_per_rtt / current_bandwidth_.ToBytesPerSecond(); 467 468 decrease_factor = std::max(decrease_factor, kMinBitrateReduction); 469 decrease_factor = std::min(decrease_factor, kMaxBitrateReduction); 470 back_down_congestion_delay_ = estimated_congestion_delay; 471 QuicBandwidth new_target_bitrate = 472 current_bandwidth_.Scale(1.0f - decrease_factor); 473 474 // While in delay sensing mode send at least one packet per RTT. 475 QuicBandwidth min_delay_bitrate = 476 QuicBandwidth::FromBytesAndTimeDelta(max_segment_size_, SmoothedRtt()); 477 new_target_bitrate = std::max(new_target_bitrate, min_delay_bitrate); 478 479 ResetCurrentBandwidth(feedback_receive_time, new_target_bitrate); 480 481 DVLOG(1) << "New bandwidth estimate after delay event:" 482 << current_bandwidth_.ToKBitsPerSecond() 483 << " Kbits/s min delay bitrate:" 484 << min_delay_bitrate.ToKBitsPerSecond() 485 << " Kbits/s RTT:" 486 << SmoothedRtt().ToMicroseconds() 487 << " us"; 488 } 489 490 void InterArrivalSender::EstimateBandwidthAfterLossEvent( 491 QuicTime feedback_receive_time) { 492 ResetCurrentBandwidth(feedback_receive_time, 493 current_bandwidth_.Scale(kPacketLossBitrateReduction)); 494 DVLOG(1) << "New bandwidth estimate after loss event:" 495 << current_bandwidth_.ToKBitsPerSecond() 496 << " Kbits/s"; 497 } 498 499 void InterArrivalSender::ResetCurrentBandwidth(QuicTime feedback_receive_time, 500 QuicBandwidth new_rate) { 501 new_rate = std::max(new_rate, 502 QuicBandwidth::FromKBitsPerSecond(kMinBitrateKbit)); 503 QuicBandwidth channel_estimate = QuicBandwidth::Zero(); 504 ChannelEstimateState channel_estimator_state = 505 channel_estimator_->GetChannelEstimate(&channel_estimate); 506 507 switch (channel_estimator_state) { 508 case kChannelEstimateUnknown: 509 channel_estimate = current_bandwidth_; 510 break; 511 case kChannelEstimateUncertain: 512 channel_estimate = channel_estimate.Scale(kUncertainSafetyMargin); 513 break; 514 case kChannelEstimateGood: 515 // Do nothing. 516 break; 517 } 518 back_down_time_ = feedback_receive_time; 519 back_down_bandwidth_ = current_bandwidth_; 520 bitrate_ramp_up_->Reset(new_rate, current_bandwidth_, channel_estimate); 521 if (new_rate != current_bandwidth_) { 522 current_bandwidth_ = new_rate; 523 paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, 524 current_bandwidth_); 525 state_machine_->DecreaseBitrateDecision(); 526 } 527 } 528 529 } // namespace net 530