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 |