| 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 { |
| 8 |
| 7 namespace { | 9 namespace { |
| 8 // Constants based on TCP defaults. | 10 // Constants based on TCP defaults. |
| 9 const int64 kHybridStartLowWindow = 16; | 11 const int64 kHybridStartLowWindow = 16; |
| 10 const net::QuicByteCount kMaxSegmentSize = net::kMaxPacketSize; | 12 const QuicByteCount kMaxSegmentSize = kMaxPacketSize; |
| 11 const net::QuicByteCount kDefaultReceiveWindow = 64000; | 13 const QuicByteCount kDefaultReceiveWindow = 64000; |
| 12 const int64 kInitialCongestionWindow = 10; | 14 const int64 kInitialCongestionWindow = 10; |
| 13 const int64 kMaxCongestionWindow = 10000; | 15 const int64 kMaxCongestionWindow = 10000; |
| 14 const int kMaxBurstLength = 3; | 16 const int kMaxBurstLength = 3; |
| 15 }; | 17 }; |
| 16 | 18 |
| 17 namespace net { | |
| 18 | |
| 19 TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno) | 19 TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno) |
| 20 : hybrid_slow_start_(clock), | 20 : hybrid_slow_start_(clock), |
| 21 cubic_(clock), | 21 cubic_(clock), |
| 22 reno_(reno), | 22 reno_(reno), |
| 23 congestion_window_count_(0), | 23 congestion_window_count_(0), |
| 24 receiver_congestion_window_(kDefaultReceiveWindow), | 24 receiver_congestion_window_(kDefaultReceiveWindow), |
| 25 last_received_accumulated_number_of_lost_packets_(0), | 25 last_received_accumulated_number_of_lost_packets_(0), |
| 26 bytes_in_flight_(0), | 26 bytes_in_flight_(0), |
| 27 update_end_sequence_number_(true), | 27 update_end_sequence_number_(true), |
| 28 end_sequence_number_(0), | 28 end_sequence_number_(0), |
| 29 congestion_window_(kInitialCongestionWindow), | 29 congestion_window_(kInitialCongestionWindow), |
| 30 slowstart_threshold_(kMaxCongestionWindow), | 30 slowstart_threshold_(kMaxCongestionWindow), |
| 31 delay_min_(QuicTime::Delta::Zero()) { | 31 delay_min_(QuicTime::Delta::Zero()) { |
| 32 } | 32 } |
| 33 | 33 |
| 34 void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame( | 34 void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame( |
| 35 const QuicCongestionFeedbackFrame& feedback, | 35 const QuicCongestionFeedbackFrame& feedback, |
| 36 QuicTime feedback_receive_time, |
| 37 QuicBandwidth /*sent_bandwidth*/, |
| 36 const SentPacketsMap& /*sent_packets*/) { | 38 const SentPacketsMap& /*sent_packets*/) { |
| 37 if (last_received_accumulated_number_of_lost_packets_ != | 39 if (last_received_accumulated_number_of_lost_packets_ != |
| 38 feedback.tcp.accumulated_number_of_lost_packets) { | 40 feedback.tcp.accumulated_number_of_lost_packets) { |
| 39 int recovered_lost_packets = | 41 int recovered_lost_packets = |
| 40 last_received_accumulated_number_of_lost_packets_ - | 42 last_received_accumulated_number_of_lost_packets_ - |
| 41 feedback.tcp.accumulated_number_of_lost_packets; | 43 feedback.tcp.accumulated_number_of_lost_packets; |
| 42 last_received_accumulated_number_of_lost_packets_ = | 44 last_received_accumulated_number_of_lost_packets_ = |
| 43 feedback.tcp.accumulated_number_of_lost_packets; | 45 feedback.tcp.accumulated_number_of_lost_packets; |
| 44 if (recovered_lost_packets > 0) { | 46 if (recovered_lost_packets > 0) { |
| 45 OnIncomingLoss(recovered_lost_packets); | 47 OnIncomingLoss(feedback_receive_time); |
| 46 } | 48 } |
| 47 } | 49 } |
| 48 receiver_congestion_window_ = feedback.tcp.receive_window; | 50 receiver_congestion_window_ = feedback.tcp.receive_window; |
| 49 } | 51 } |
| 50 | 52 |
| 51 void TcpCubicSender::OnIncomingAck( | 53 void TcpCubicSender::OnIncomingAck( |
| 52 QuicPacketSequenceNumber acked_sequence_number, QuicByteCount acked_bytes, | 54 QuicPacketSequenceNumber acked_sequence_number, QuicByteCount acked_bytes, |
| 53 QuicTime::Delta rtt) { | 55 QuicTime::Delta rtt) { |
| 54 bytes_in_flight_ -= acked_bytes; | 56 bytes_in_flight_ -= acked_bytes; |
| 55 CongestionAvoidance(acked_sequence_number); | 57 CongestionAvoidance(acked_sequence_number); |
| 56 AckAccounting(rtt); | 58 AckAccounting(rtt); |
| 57 if (end_sequence_number_ == acked_sequence_number) { | 59 if (end_sequence_number_ == acked_sequence_number) { |
| 58 DLOG(INFO) << "Start update end sequence number @" << acked_sequence_number; | 60 DLOG(INFO) << "Start update end sequence number @" << acked_sequence_number; |
| 59 update_end_sequence_number_ = true; | 61 update_end_sequence_number_ = true; |
| 60 } | 62 } |
| 61 } | 63 } |
| 62 | 64 |
| 63 void TcpCubicSender::OnIncomingLoss(int /*number_of_lost_packets*/) { | 65 void TcpCubicSender::OnIncomingLoss(QuicTime /*ack_receive_time*/) { |
| 64 // In a normal TCP we would need to know the lowest missing packet to detect | 66 // In a normal TCP we would need to know the lowest missing packet to detect |
| 65 // if we receive 3 missing packets. Here we get a missing packet for which we | 67 // if we receive 3 missing packets. Here we get a missing packet for which we |
| 66 // enter TCP Fast Retransmit immediately. | 68 // enter TCP Fast Retransmit immediately. |
| 67 if (reno_) { | 69 if (reno_) { |
| 68 congestion_window_ = congestion_window_ >> 1; | 70 congestion_window_ = congestion_window_ >> 1; |
| 69 slowstart_threshold_ = congestion_window_; | 71 slowstart_threshold_ = congestion_window_; |
| 70 } else { | 72 } else { |
| 71 congestion_window_ = | 73 congestion_window_ = |
| 72 cubic_.CongestionWindowAfterPacketLoss(congestion_window_); | 74 cubic_.CongestionWindowAfterPacketLoss(congestion_window_); |
| 73 slowstart_threshold_ = congestion_window_; | 75 slowstart_threshold_ = congestion_window_; |
| 74 } | 76 } |
| 75 // Sanity, make sure that we don't end up with an empty window. | 77 // Sanity, make sure that we don't end up with an empty window. |
| 76 if (congestion_window_ == 0) { | 78 if (congestion_window_ == 0) { |
| 77 congestion_window_ = 1; | 79 congestion_window_ = 1; |
| 78 } | 80 } |
| 81 DLOG(INFO) << "Incoming loss; congestion window:" << congestion_window_; |
| 79 } | 82 } |
| 80 | 83 |
| 81 void TcpCubicSender::SentPacket(QuicPacketSequenceNumber sequence_number, | 84 void TcpCubicSender::SentPacket(QuicTime /*sent_time*/, |
| 85 QuicPacketSequenceNumber sequence_number, |
| 82 QuicByteCount bytes, | 86 QuicByteCount bytes, |
| 83 bool is_retransmission) { | 87 bool is_retransmission) { |
| 84 if (!is_retransmission) { | 88 if (!is_retransmission) { |
| 85 bytes_in_flight_ += bytes; | 89 bytes_in_flight_ += bytes; |
| 86 } | 90 } |
| 87 if (!is_retransmission && update_end_sequence_number_) { | 91 if (!is_retransmission && update_end_sequence_number_) { |
| 88 end_sequence_number_ = sequence_number; | 92 end_sequence_number_ = sequence_number; |
| 89 if (AvailableCongestionWindow() == 0) { | 93 if (AvailableCongestionWindow() == 0) { |
| 90 update_end_sequence_number_ = false; | 94 update_end_sequence_number_ = false; |
| 91 DLOG(INFO) << "Stop update end sequence number @" << sequence_number; | 95 DLOG(INFO) << "Stop update end sequence number @" << sequence_number; |
| 92 } | 96 } |
| 93 } | 97 } |
| 94 } | 98 } |
| 95 | 99 |
| 96 QuicTime::Delta TcpCubicSender::TimeUntilSend(bool is_retransmission) { | 100 QuicTime::Delta TcpCubicSender::TimeUntilSend(QuicTime now, |
| 101 bool is_retransmission) { |
| 97 if (is_retransmission) { | 102 if (is_retransmission) { |
| 98 // For TCP we can always send a retransmission immediately. | 103 // For TCP we can always send a retransmission immediately. |
| 99 return QuicTime::Delta::Zero(); | 104 return QuicTime::Delta::Zero(); |
| 100 } | 105 } |
| 101 if (AvailableCongestionWindow() == 0) { | 106 if (AvailableCongestionWindow() == 0) { |
| 102 return QuicTime::Delta::Infinite(); | 107 return QuicTime::Delta::Infinite(); |
| 103 } | 108 } |
| 104 return QuicTime::Delta::Zero(); | 109 return QuicTime::Delta::Zero(); |
| 105 } | 110 } |
| 106 | 111 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 const QuicByteCount left = congestion_window_bytes - bytes_in_flight_; | 144 const QuicByteCount left = congestion_window_bytes - bytes_in_flight_; |
| 140 return left <= tcp_max_burst; | 145 return left <= tcp_max_burst; |
| 141 } | 146 } |
| 142 | 147 |
| 143 // Called when we receive and ack. Normal TCP tracks how many packets one ack | 148 // Called when we receive and ack. Normal TCP tracks how many packets one ack |
| 144 // represents, but quic has a separate ack for each packet. | 149 // represents, but quic has a separate ack for each packet. |
| 145 void TcpCubicSender::CongestionAvoidance(QuicPacketSequenceNumber ack) { | 150 void TcpCubicSender::CongestionAvoidance(QuicPacketSequenceNumber ack) { |
| 146 if (!IsCwndLimited()) { | 151 if (!IsCwndLimited()) { |
| 147 // We don't update the congestion window unless we are close to using the | 152 // We don't update the congestion window unless we are close to using the |
| 148 // window we have available. | 153 // window we have available. |
| 149 DLOG(INFO) << "Congestion avoidance window not limited"; | |
| 150 return; | 154 return; |
| 151 } | 155 } |
| 152 if (congestion_window_ < slowstart_threshold_) { | 156 if (congestion_window_ < slowstart_threshold_) { |
| 153 // Slow start. | 157 // Slow start. |
| 154 if (hybrid_slow_start_.EndOfRound(ack)) { | 158 if (hybrid_slow_start_.EndOfRound(ack)) { |
| 155 hybrid_slow_start_.Reset(end_sequence_number_); | 159 hybrid_slow_start_.Reset(end_sequence_number_); |
| 156 } | 160 } |
| 157 // congestion_window_cnt is the number of acks since last change of snd_cwnd | 161 // congestion_window_cnt is the number of acks since last change of snd_cwnd |
| 158 if (congestion_window_ < kMaxCongestionWindow) { | 162 if (congestion_window_ < kMaxCongestionWindow) { |
| 159 // TCP slow start, exponentail growth, increase by one for each ACK. | 163 // TCP slow start, exponentail growth, increase by one for each ACK. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 hybrid_slow_start_.Reset(end_sequence_number_); | 210 hybrid_slow_start_.Reset(end_sequence_number_); |
| 207 } | 211 } |
| 208 hybrid_slow_start_.Update(rtt, delay_min_); | 212 hybrid_slow_start_.Update(rtt, delay_min_); |
| 209 if (hybrid_slow_start_.Exit()) { | 213 if (hybrid_slow_start_.Exit()) { |
| 210 slowstart_threshold_ = congestion_window_; | 214 slowstart_threshold_ = congestion_window_; |
| 211 } | 215 } |
| 212 } | 216 } |
| 213 } | 217 } |
| 214 | 218 |
| 215 } // namespace net | 219 } // namespace net |
| OLD | NEW |