| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/congestion_control/tcp_cubic_sender.h" | 5 #include "net/quic/congestion_control/tcp_cubic_sender.h" |
| 6 | 6 |
| 7 namespace net { | 7 namespace net { |
| 8 | 8 |
| 9 namespace { | 9 namespace { |
| 10 // Constants based on TCP defaults. | 10 // Constants based on TCP defaults. |
| 11 const int64 kHybridStartLowWindow = 16; | 11 const int64 kHybridStartLowWindow = 16; |
| 12 const QuicByteCount kMaxSegmentSize = kMaxPacketSize; | 12 const QuicByteCount kMaxSegmentSize = kMaxPacketSize; |
| 13 const QuicByteCount kDefaultReceiveWindow = 64000; | 13 const QuicByteCount kDefaultReceiveWindow = 64000; |
| 14 const int64 kInitialCongestionWindow = 10; | 14 const int64 kInitialCongestionWindow = 10; |
| 15 const int64 kMaxCongestionWindow = 10000; | 15 const int64 kMaxCongestionWindow = 10000; |
| 16 const int kMaxBurstLength = 3; | 16 const int kMaxBurstLength = 3; |
| 17 const int kInitialRttMs = 60; // At a typical RTT 60 ms. | 17 const int kInitialRttMs = 60; // At a typical RTT 60 ms. |
| 18 }; | 18 const float kAlpha = 0.125f; |
| 19 const float kOneMinusAlpha = (1 - kAlpha); |
| 20 const float kBeta = 0.25f; |
| 21 const float kOneMinusBeta = (1 - kBeta); |
| 22 }; // namespace |
| 19 | 23 |
| 20 TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno) | 24 TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno) |
| 21 : hybrid_slow_start_(clock), | 25 : hybrid_slow_start_(clock), |
| 22 cubic_(clock), | 26 cubic_(clock), |
| 23 reno_(reno), | 27 reno_(reno), |
| 24 congestion_window_count_(0), | 28 congestion_window_count_(0), |
| 25 receiver_congestion_window_(kDefaultReceiveWindow), | 29 receiver_congestion_window_(kDefaultReceiveWindow), |
| 26 last_received_accumulated_number_of_lost_packets_(0), | 30 last_received_accumulated_number_of_lost_packets_(0), |
| 27 bytes_in_flight_(0), | 31 bytes_in_flight_(0), |
| 28 update_end_sequence_number_(true), | 32 update_end_sequence_number_(true), |
| 29 end_sequence_number_(0), | 33 end_sequence_number_(0), |
| 30 congestion_window_(kInitialCongestionWindow), | 34 congestion_window_(kInitialCongestionWindow), |
| 31 slowstart_threshold_(kMaxCongestionWindow), | 35 slowstart_threshold_(kMaxCongestionWindow), |
| 32 delay_min_(QuicTime::Delta::Zero()) { | 36 delay_min_(QuicTime::Delta::Zero()), |
| 37 smoothed_rtt_(QuicTime::Delta::Zero()), |
| 38 mean_deviation_(QuicTime::Delta::Zero()) { |
| 39 } |
| 40 |
| 41 TcpCubicSender::~TcpCubicSender() { |
| 33 } | 42 } |
| 34 | 43 |
| 35 void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame( | 44 void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame( |
| 36 const QuicCongestionFeedbackFrame& feedback, | 45 const QuicCongestionFeedbackFrame& feedback, |
| 37 QuicTime feedback_receive_time, | 46 QuicTime feedback_receive_time, |
| 38 const SentPacketsMap& /*sent_packets*/) { | 47 const SentPacketsMap& /*sent_packets*/) { |
| 39 if (last_received_accumulated_number_of_lost_packets_ != | 48 if (last_received_accumulated_number_of_lost_packets_ != |
| 40 feedback.tcp.accumulated_number_of_lost_packets) { | 49 feedback.tcp.accumulated_number_of_lost_packets) { |
| 41 int recovered_lost_packets = | 50 int recovered_lost_packets = |
| 42 last_received_accumulated_number_of_lost_packets_ - | 51 last_received_accumulated_number_of_lost_packets_ - |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 } | 138 } |
| 130 | 139 |
| 131 QuicBandwidth TcpCubicSender::BandwidthEstimate() { | 140 QuicBandwidth TcpCubicSender::BandwidthEstimate() { |
| 132 // TODO(pwestin): make a long term estimate, based on RTT and loss rate? or | 141 // TODO(pwestin): make a long term estimate, based on RTT and loss rate? or |
| 133 // instantaneous estimate? | 142 // instantaneous estimate? |
| 134 // Throughput ~= (1/RTT)*sqrt(3/2p) | 143 // Throughput ~= (1/RTT)*sqrt(3/2p) |
| 135 return QuicBandwidth::Zero(); | 144 return QuicBandwidth::Zero(); |
| 136 } | 145 } |
| 137 | 146 |
| 138 QuicTime::Delta TcpCubicSender::SmoothedRtt() { | 147 QuicTime::Delta TcpCubicSender::SmoothedRtt() { |
| 139 // TODO(satyamshekhar): Return the smoothed averaged RTT. | 148 if (smoothed_rtt_.IsZero()) { |
| 140 if (delay_min_.IsZero()) { | |
| 141 return QuicTime::Delta::FromMilliseconds(kInitialRttMs); | 149 return QuicTime::Delta::FromMilliseconds(kInitialRttMs); |
| 142 } | 150 } |
| 143 return delay_min_; | 151 return smoothed_rtt_; |
| 152 } |
| 153 |
| 154 QuicTime::Delta TcpCubicSender::RetransmissionDelay() { |
| 155 return QuicTime::Delta::FromMicroseconds( |
| 156 smoothed_rtt_.ToMicroseconds() + 4 * mean_deviation_.ToMicroseconds()); |
| 144 } | 157 } |
| 145 | 158 |
| 146 void TcpCubicSender::Reset() { | 159 void TcpCubicSender::Reset() { |
| 147 delay_min_ = QuicTime::Delta::Zero(); | 160 delay_min_ = QuicTime::Delta::Zero(); |
| 148 hybrid_slow_start_.Restart(); | 161 hybrid_slow_start_.Restart(); |
| 149 } | 162 } |
| 150 | 163 |
| 151 bool TcpCubicSender::IsCwndLimited() const { | 164 bool TcpCubicSender::IsCwndLimited() const { |
| 152 const QuicByteCount congestion_window_bytes = congestion_window_ * | 165 const QuicByteCount congestion_window_bytes = congestion_window_ * |
| 153 kMaxSegmentSize; | 166 kMaxSegmentSize; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 // RTT can't be negative. | 224 // RTT can't be negative. |
| 212 DCHECK_LT(0, rtt.ToMicroseconds()); | 225 DCHECK_LT(0, rtt.ToMicroseconds()); |
| 213 | 226 |
| 214 // TODO(pwestin): Discard delay samples right after fast recovery, | 227 // TODO(pwestin): Discard delay samples right after fast recovery, |
| 215 // during 1 second?. | 228 // during 1 second?. |
| 216 | 229 |
| 217 // First time call or link delay decreases. | 230 // First time call or link delay decreases. |
| 218 if (delay_min_.IsZero() || delay_min_ > rtt) { | 231 if (delay_min_.IsZero() || delay_min_ > rtt) { |
| 219 delay_min_ = rtt; | 232 delay_min_ = rtt; |
| 220 } | 233 } |
| 234 // First time call. |
| 235 if (smoothed_rtt_.IsZero()) { |
| 236 smoothed_rtt_ = rtt; |
| 237 mean_deviation_ = QuicTime::Delta::FromMicroseconds( |
| 238 rtt.ToMicroseconds() / 2); |
| 239 } else { |
| 240 mean_deviation_ = QuicTime::Delta::FromMicroseconds( |
| 241 kOneMinusBeta * mean_deviation_.ToMicroseconds() + |
| 242 kBeta * abs(smoothed_rtt_.ToMicroseconds() - rtt.ToMicroseconds())); |
| 243 smoothed_rtt_ = QuicTime::Delta::FromMicroseconds( |
| 244 kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() + |
| 245 kAlpha * rtt.ToMicroseconds()); |
| 246 DLOG(INFO) << "Cubic; mean_deviation_:" << mean_deviation_.ToMicroseconds(); |
| 247 } |
| 248 |
| 221 // Hybrid start triggers when cwnd is larger than some threshold. | 249 // Hybrid start triggers when cwnd is larger than some threshold. |
| 222 if (congestion_window_ <= slowstart_threshold_ && | 250 if (congestion_window_ <= slowstart_threshold_ && |
| 223 congestion_window_ >= kHybridStartLowWindow) { | 251 congestion_window_ >= kHybridStartLowWindow) { |
| 224 if (!hybrid_slow_start_.started()) { | 252 if (!hybrid_slow_start_.started()) { |
| 225 // Time to start the hybrid slow start. | 253 // Time to start the hybrid slow start. |
| 226 hybrid_slow_start_.Reset(end_sequence_number_); | 254 hybrid_slow_start_.Reset(end_sequence_number_); |
| 227 } | 255 } |
| 228 hybrid_slow_start_.Update(rtt, delay_min_); | 256 hybrid_slow_start_.Update(rtt, delay_min_); |
| 229 if (hybrid_slow_start_.Exit()) { | 257 if (hybrid_slow_start_.Exit()) { |
| 230 slowstart_threshold_ = congestion_window_; | 258 slowstart_threshold_ = congestion_window_; |
| 231 } | 259 } |
| 232 } | 260 } |
| 233 } | 261 } |
| 234 | 262 |
| 235 } // namespace net | 263 } // namespace net |
| OLD | NEW |