| OLD | NEW |
| (Empty) |
| 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/pacing_sender.h" | |
| 6 | |
| 7 #include "net/quic/quic_flags.h" | |
| 8 | |
| 9 using std::min; | |
| 10 | |
| 11 namespace net { | |
| 12 | |
| 13 PacingSender::PacingSender(SendAlgorithmInterface* sender, | |
| 14 QuicTime::Delta alarm_granularity, | |
| 15 uint32_t initial_packet_burst) | |
| 16 : sender_(sender), | |
| 17 alarm_granularity_(alarm_granularity), | |
| 18 initial_packet_burst_(initial_packet_burst), | |
| 19 max_pacing_rate_(QuicBandwidth::Zero()), | |
| 20 burst_tokens_(initial_packet_burst), | |
| 21 last_delayed_packet_sent_time_(QuicTime::Zero()), | |
| 22 ideal_next_packet_send_time_(QuicTime::Zero()), | |
| 23 was_last_send_delayed_(false) {} | |
| 24 | |
| 25 PacingSender::~PacingSender() {} | |
| 26 | |
| 27 void PacingSender::SetFromConfig(const QuicConfig& config, | |
| 28 Perspective perspective) { | |
| 29 sender_->SetFromConfig(config, perspective); | |
| 30 } | |
| 31 | |
| 32 void PacingSender::ResumeConnectionState( | |
| 33 const CachedNetworkParameters& cached_network_params, | |
| 34 bool max_bandwidth_resumption) { | |
| 35 sender_->ResumeConnectionState(cached_network_params, | |
| 36 max_bandwidth_resumption); | |
| 37 } | |
| 38 | |
| 39 void PacingSender::SetNumEmulatedConnections(int num_connections) { | |
| 40 sender_->SetNumEmulatedConnections(num_connections); | |
| 41 } | |
| 42 | |
| 43 void PacingSender::SetMaxPacingRate(QuicBandwidth max_pacing_rate) { | |
| 44 max_pacing_rate_ = max_pacing_rate; | |
| 45 } | |
| 46 | |
| 47 void PacingSender::OnCongestionEvent(bool rtt_updated, | |
| 48 QuicByteCount bytes_in_flight, | |
| 49 const CongestionVector& acked_packets, | |
| 50 const CongestionVector& lost_packets) { | |
| 51 if (!lost_packets.empty()) { | |
| 52 // Clear any burst tokens when entering recovery. | |
| 53 burst_tokens_ = 0; | |
| 54 } | |
| 55 sender_->OnCongestionEvent(rtt_updated, bytes_in_flight, acked_packets, | |
| 56 lost_packets); | |
| 57 } | |
| 58 | |
| 59 bool PacingSender::OnPacketSent( | |
| 60 QuicTime sent_time, | |
| 61 QuicByteCount bytes_in_flight, | |
| 62 QuicPacketNumber packet_number, | |
| 63 QuicByteCount bytes, | |
| 64 HasRetransmittableData has_retransmittable_data) { | |
| 65 const bool in_flight = | |
| 66 sender_->OnPacketSent(sent_time, bytes_in_flight, packet_number, bytes, | |
| 67 has_retransmittable_data); | |
| 68 if (has_retransmittable_data != HAS_RETRANSMITTABLE_DATA) { | |
| 69 return in_flight; | |
| 70 } | |
| 71 // If in recovery, the connection is not coming out of quiescence. | |
| 72 if (bytes_in_flight == 0 && !sender_->InRecovery()) { | |
| 73 // Add more burst tokens anytime the connection is leaving quiescence, but | |
| 74 // limit it to the equivalent of a single bulk write, not exceeding the | |
| 75 // current CWND in packets. | |
| 76 burst_tokens_ = min( | |
| 77 initial_packet_burst_, | |
| 78 static_cast<uint32_t>(sender_->GetCongestionWindow() / kDefaultTCPMSS)); | |
| 79 } | |
| 80 if (burst_tokens_ > 0) { | |
| 81 --burst_tokens_; | |
| 82 was_last_send_delayed_ = false; | |
| 83 last_delayed_packet_sent_time_ = QuicTime::Zero(); | |
| 84 ideal_next_packet_send_time_ = QuicTime::Zero(); | |
| 85 return in_flight; | |
| 86 } | |
| 87 // The next packet should be sent as soon as the current packet has been | |
| 88 // transferred. PacingRate is based on bytes in flight including this packet. | |
| 89 QuicTime::Delta delay = | |
| 90 PacingRate(bytes_in_flight + bytes).TransferTime(bytes); | |
| 91 // If the last send was delayed, and the alarm took a long time to get | |
| 92 // invoked, allow the connection to make up for lost time. | |
| 93 if (was_last_send_delayed_) { | |
| 94 ideal_next_packet_send_time_ = ideal_next_packet_send_time_ + delay; | |
| 95 // The send was application limited if it takes longer than the | |
| 96 // pacing delay between sent packets. | |
| 97 const bool application_limited = | |
| 98 last_delayed_packet_sent_time_.IsInitialized() && | |
| 99 sent_time > last_delayed_packet_sent_time_ + delay; | |
| 100 const bool making_up_for_lost_time = | |
| 101 ideal_next_packet_send_time_ <= sent_time; | |
| 102 // As long as we're making up time and not application limited, | |
| 103 // continue to consider the packets delayed, allowing the packets to be | |
| 104 // sent immediately. | |
| 105 if (making_up_for_lost_time && !application_limited) { | |
| 106 last_delayed_packet_sent_time_ = sent_time; | |
| 107 } else { | |
| 108 was_last_send_delayed_ = false; | |
| 109 last_delayed_packet_sent_time_ = QuicTime::Zero(); | |
| 110 } | |
| 111 } else { | |
| 112 ideal_next_packet_send_time_ = | |
| 113 std::max(ideal_next_packet_send_time_ + delay, sent_time + delay); | |
| 114 } | |
| 115 return in_flight; | |
| 116 } | |
| 117 | |
| 118 void PacingSender::OnRetransmissionTimeout(bool packets_retransmitted) { | |
| 119 sender_->OnRetransmissionTimeout(packets_retransmitted); | |
| 120 } | |
| 121 | |
| 122 void PacingSender::OnConnectionMigration() { | |
| 123 sender_->OnConnectionMigration(); | |
| 124 } | |
| 125 | |
| 126 QuicTime::Delta PacingSender::TimeUntilSend( | |
| 127 QuicTime now, | |
| 128 QuicByteCount bytes_in_flight) const { | |
| 129 QuicTime::Delta time_until_send = | |
| 130 sender_->TimeUntilSend(now, bytes_in_flight); | |
| 131 if (burst_tokens_ > 0 || bytes_in_flight == 0) { | |
| 132 // Don't pace if we have burst tokens available or leaving quiescence. | |
| 133 return time_until_send; | |
| 134 } | |
| 135 | |
| 136 if (!time_until_send.IsZero()) { | |
| 137 DCHECK(time_until_send.IsInfinite()); | |
| 138 // The underlying sender prevents sending. | |
| 139 return time_until_send; | |
| 140 } | |
| 141 | |
| 142 // If the next send time is within the alarm granularity, send immediately. | |
| 143 if (ideal_next_packet_send_time_ > now + alarm_granularity_) { | |
| 144 DVLOG(1) << "Delaying packet: " | |
| 145 << (ideal_next_packet_send_time_ - now).ToMicroseconds(); | |
| 146 was_last_send_delayed_ = true; | |
| 147 return ideal_next_packet_send_time_ - now; | |
| 148 } | |
| 149 | |
| 150 DVLOG(1) << "Sending packet now"; | |
| 151 return QuicTime::Delta::Zero(); | |
| 152 } | |
| 153 | |
| 154 QuicBandwidth PacingSender::PacingRate(QuicByteCount bytes_in_flight) const { | |
| 155 if (!max_pacing_rate_.IsZero()) { | |
| 156 return QuicBandwidth::FromBitsPerSecond( | |
| 157 min(max_pacing_rate_.ToBitsPerSecond(), | |
| 158 sender_->PacingRate(bytes_in_flight).ToBitsPerSecond())); | |
| 159 } | |
| 160 return sender_->PacingRate(bytes_in_flight); | |
| 161 } | |
| 162 | |
| 163 QuicBandwidth PacingSender::BandwidthEstimate() const { | |
| 164 return sender_->BandwidthEstimate(); | |
| 165 } | |
| 166 | |
| 167 QuicTime::Delta PacingSender::RetransmissionDelay() const { | |
| 168 return sender_->RetransmissionDelay(); | |
| 169 } | |
| 170 | |
| 171 QuicByteCount PacingSender::GetCongestionWindow() const { | |
| 172 return sender_->GetCongestionWindow(); | |
| 173 } | |
| 174 | |
| 175 bool PacingSender::InSlowStart() const { | |
| 176 return sender_->InSlowStart(); | |
| 177 } | |
| 178 | |
| 179 bool PacingSender::InRecovery() const { | |
| 180 return sender_->InRecovery(); | |
| 181 } | |
| 182 | |
| 183 QuicByteCount PacingSender::GetSlowStartThreshold() const { | |
| 184 return sender_->GetSlowStartThreshold(); | |
| 185 } | |
| 186 | |
| 187 CongestionControlType PacingSender::GetCongestionControlType() const { | |
| 188 return sender_->GetCongestionControlType(); | |
| 189 } | |
| 190 | |
| 191 } // namespace net | |
| OLD | NEW |