OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/quic_unacked_packet_map.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/stl_util.h" | |
9 #include "net/quic/chromium/quic_utils_chromium.h" | |
10 #include "net/quic/quic_bug_tracker.h" | |
11 #include "net/quic/quic_connection_stats.h" | |
12 #include "net/quic/quic_flags.h" | |
13 #include "net/quic/quic_utils.h" | |
14 | |
15 using std::max; | |
16 | |
17 namespace net { | |
18 | |
19 QuicUnackedPacketMap::QuicUnackedPacketMap() | |
20 : largest_sent_packet_(0), | |
21 largest_observed_(0), | |
22 least_unacked_(1), | |
23 bytes_in_flight_(0), | |
24 pending_crypto_packet_count_(0) {} | |
25 | |
26 QuicUnackedPacketMap::~QuicUnackedPacketMap() { | |
27 QuicPacketNumber index = least_unacked_; | |
28 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); | |
29 it != unacked_packets_.end(); ++it, ++index) { | |
30 QuicUtils::DeleteFrames(&it->retransmittable_frames); | |
31 } | |
32 } | |
33 | |
34 void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet, | |
35 QuicPacketNumber old_packet_number, | |
36 TransmissionType transmission_type, | |
37 QuicTime sent_time, | |
38 bool set_in_flight) { | |
39 QuicPacketNumber packet_number = packet->packet_number; | |
40 QuicPacketLength bytes_sent = packet->encrypted_length; | |
41 QUIC_BUG_IF(largest_sent_packet_ >= packet_number) << packet_number; | |
42 DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size()); | |
43 while (least_unacked_ + unacked_packets_.size() < packet_number) { | |
44 unacked_packets_.push_back(TransmissionInfo()); | |
45 unacked_packets_.back().is_unackable = true; | |
46 } | |
47 | |
48 const bool has_crypto_handshake = | |
49 packet->has_crypto_handshake == IS_HANDSHAKE; | |
50 TransmissionInfo info(packet->encryption_level, packet->packet_number_length, | |
51 transmission_type, sent_time, bytes_sent, | |
52 has_crypto_handshake, packet->num_padding_bytes); | |
53 if (old_packet_number > 0) { | |
54 TransferRetransmissionInfo(old_packet_number, packet_number, | |
55 transmission_type, &info); | |
56 } | |
57 | |
58 largest_sent_packet_ = packet_number; | |
59 if (set_in_flight) { | |
60 bytes_in_flight_ += bytes_sent; | |
61 info.in_flight = true; | |
62 } | |
63 unacked_packets_.push_back(info); | |
64 // Swap the ack listeners and retransmittable frames to avoid allocations. | |
65 // TODO(ianswett): Could use emplace_back when Chromium can. | |
66 if (old_packet_number == 0) { | |
67 if (has_crypto_handshake) { | |
68 ++pending_crypto_packet_count_; | |
69 } | |
70 | |
71 packet->retransmittable_frames.swap( | |
72 unacked_packets_.back().retransmittable_frames); | |
73 unacked_packets_.back().ack_listeners.swap(packet->listeners); | |
74 } | |
75 } | |
76 | |
77 void QuicUnackedPacketMap::RemoveObsoletePackets() { | |
78 while (!unacked_packets_.empty()) { | |
79 if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) { | |
80 break; | |
81 } | |
82 | |
83 unacked_packets_.pop_front(); | |
84 ++least_unacked_; | |
85 } | |
86 } | |
87 | |
88 void QuicUnackedPacketMap::TransferRetransmissionInfo( | |
89 QuicPacketNumber old_packet_number, | |
90 QuicPacketNumber new_packet_number, | |
91 TransmissionType transmission_type, | |
92 TransmissionInfo* info) { | |
93 if (old_packet_number < least_unacked_) { | |
94 // This can happen when a retransmission packet is queued because of write | |
95 // blocked socket, and the original packet gets acked before the | |
96 // retransmission gets sent. | |
97 return; | |
98 } | |
99 if (old_packet_number > largest_sent_packet_) { | |
100 QUIC_BUG << "Old TransmissionInfo never existed for :" << old_packet_number | |
101 << " largest_sent:" << largest_sent_packet_; | |
102 return; | |
103 } | |
104 DCHECK_GE(new_packet_number, least_unacked_ + unacked_packets_.size()); | |
105 DCHECK_NE(NOT_RETRANSMISSION, transmission_type); | |
106 | |
107 TransmissionInfo* transmission_info = | |
108 &unacked_packets_.at(old_packet_number - least_unacked_); | |
109 QuicFrames* frames = &transmission_info->retransmittable_frames; | |
110 for (AckListenerWrapper& wrapper : transmission_info->ack_listeners) { | |
111 wrapper.ack_listener->OnPacketRetransmitted(wrapper.length); | |
112 } | |
113 | |
114 // Swap the frames and preserve num_padding_bytes and has_crypto_handshake. | |
115 frames->swap(info->retransmittable_frames); | |
116 info->has_crypto_handshake = transmission_info->has_crypto_handshake; | |
117 transmission_info->has_crypto_handshake = false; | |
118 info->num_padding_bytes = transmission_info->num_padding_bytes; | |
119 | |
120 // Transfer the AckListeners if any are present. | |
121 info->ack_listeners.swap(transmission_info->ack_listeners); | |
122 QUIC_BUG_IF(frames == nullptr) | |
123 << "Attempt to retransmit packet with no " | |
124 << "retransmittable frames: " << old_packet_number; | |
125 | |
126 // Don't link old transmissions to new ones when version or | |
127 // encryption changes. | |
128 if (transmission_type == ALL_INITIAL_RETRANSMISSION || | |
129 transmission_type == ALL_UNACKED_RETRANSMISSION) { | |
130 transmission_info->is_unackable = true; | |
131 } else { | |
132 transmission_info->retransmission = new_packet_number; | |
133 } | |
134 // Proactively remove obsolete packets so the least unacked can be raised. | |
135 RemoveObsoletePackets(); | |
136 } | |
137 | |
138 bool QuicUnackedPacketMap::HasRetransmittableFrames( | |
139 QuicPacketNumber packet_number) const { | |
140 DCHECK_GE(packet_number, least_unacked_); | |
141 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | |
142 return !unacked_packets_[packet_number - least_unacked_] | |
143 .retransmittable_frames.empty(); | |
144 } | |
145 | |
146 void QuicUnackedPacketMap::RemoveRetransmittability(TransmissionInfo* info) { | |
147 while (info->retransmission != 0) { | |
148 const QuicPacketNumber retransmission = info->retransmission; | |
149 info->retransmission = 0; | |
150 info = &unacked_packets_[retransmission - least_unacked_]; | |
151 } | |
152 MaybeRemoveRetransmittableFrames(info); | |
153 } | |
154 | |
155 void QuicUnackedPacketMap::RemoveRetransmittability( | |
156 QuicPacketNumber packet_number) { | |
157 DCHECK_GE(packet_number, least_unacked_); | |
158 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | |
159 TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_]; | |
160 RemoveRetransmittability(info); | |
161 } | |
162 | |
163 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( | |
164 TransmissionInfo* transmission_info) { | |
165 if (transmission_info->has_crypto_handshake) { | |
166 DCHECK(!transmission_info->retransmittable_frames.empty()); | |
167 DCHECK_LT(0u, pending_crypto_packet_count_); | |
168 --pending_crypto_packet_count_; | |
169 transmission_info->has_crypto_handshake = false; | |
170 } | |
171 QuicUtils::DeleteFrames(&transmission_info->retransmittable_frames); | |
172 } | |
173 | |
174 void QuicUnackedPacketMap::IncreaseLargestObserved( | |
175 QuicPacketNumber largest_observed) { | |
176 DCHECK_LE(largest_observed_, largest_observed); | |
177 largest_observed_ = largest_observed; | |
178 } | |
179 | |
180 bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt( | |
181 QuicPacketNumber packet_number, | |
182 const TransmissionInfo& info) const { | |
183 // Packet can be used for RTT measurement if it may yet be acked as the | |
184 // largest observed packet by the receiver. | |
185 return !info.is_unackable && packet_number > largest_observed_; | |
186 } | |
187 | |
188 bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl( | |
189 const TransmissionInfo& info) const { | |
190 // Packet contributes to congestion control if it is considered inflight. | |
191 return info.in_flight; | |
192 } | |
193 | |
194 bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData( | |
195 const TransmissionInfo& info) const { | |
196 // Packet may have retransmittable frames, or the data may have been | |
197 // retransmitted with a new packet number. | |
198 return !info.retransmittable_frames.empty() || | |
199 // Allow for an extra 1 RTT before stopping to track old packets. | |
200 info.retransmission > largest_observed_; | |
201 } | |
202 | |
203 bool QuicUnackedPacketMap::IsPacketUseless(QuicPacketNumber packet_number, | |
204 const TransmissionInfo& info) const { | |
205 return !IsPacketUsefulForMeasuringRtt(packet_number, info) && | |
206 !IsPacketUsefulForCongestionControl(info) && | |
207 !IsPacketUsefulForRetransmittableData(info); | |
208 } | |
209 | |
210 bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const { | |
211 if (packet_number < least_unacked_ || | |
212 packet_number >= least_unacked_ + unacked_packets_.size()) { | |
213 return false; | |
214 } | |
215 return !IsPacketUseless(packet_number, | |
216 unacked_packets_[packet_number - least_unacked_]); | |
217 } | |
218 | |
219 void QuicUnackedPacketMap::NotifyAndClearListeners( | |
220 std::list<AckListenerWrapper>* ack_listeners, | |
221 QuicTime::Delta ack_delay_time) { | |
222 for (const AckListenerWrapper& wrapper : *ack_listeners) { | |
223 wrapper.ack_listener->OnPacketAcked(wrapper.length, ack_delay_time); | |
224 } | |
225 ack_listeners->clear(); | |
226 } | |
227 | |
228 void QuicUnackedPacketMap::NotifyAndClearListeners( | |
229 QuicPacketNumber packet_number, | |
230 QuicTime::Delta ack_delay_time) { | |
231 DCHECK_GE(packet_number, least_unacked_); | |
232 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | |
233 TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_]; | |
234 NotifyAndClearListeners(&info->ack_listeners, ack_delay_time); | |
235 } | |
236 | |
237 void QuicUnackedPacketMap::RemoveFromInFlight(TransmissionInfo* info) { | |
238 if (info->in_flight) { | |
239 QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent); | |
240 bytes_in_flight_ -= info->bytes_sent; | |
241 info->in_flight = false; | |
242 } | |
243 } | |
244 | |
245 void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) { | |
246 DCHECK_GE(packet_number, least_unacked_); | |
247 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | |
248 TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_]; | |
249 RemoveFromInFlight(info); | |
250 } | |
251 | |
252 void QuicUnackedPacketMap::RestoreToInFlight(QuicPacketNumber packet_number) { | |
253 DCHECK_GE(packet_number, least_unacked_); | |
254 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | |
255 TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_]; | |
256 DCHECK(!info->is_unackable); | |
257 bytes_in_flight_ += info->bytes_sent; | |
258 info->in_flight = true; | |
259 } | |
260 | |
261 void QuicUnackedPacketMap::CancelRetransmissionsForStream( | |
262 QuicStreamId stream_id) { | |
263 QuicPacketNumber packet_number = least_unacked_; | |
264 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); | |
265 it != unacked_packets_.end(); ++it, ++packet_number) { | |
266 QuicFrames* frames = &it->retransmittable_frames; | |
267 if (frames->empty()) { | |
268 continue; | |
269 } | |
270 QuicUtils::RemoveFramesForStream(frames, stream_id); | |
271 if (frames->empty()) { | |
272 RemoveRetransmittability(packet_number); | |
273 } | |
274 } | |
275 } | |
276 | |
277 bool QuicUnackedPacketMap::HasUnackedPackets() const { | |
278 return !unacked_packets_.empty(); | |
279 } | |
280 | |
281 bool QuicUnackedPacketMap::HasInFlightPackets() const { | |
282 return bytes_in_flight_ > 0; | |
283 } | |
284 | |
285 const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo( | |
286 QuicPacketNumber packet_number) const { | |
287 return unacked_packets_[packet_number - least_unacked_]; | |
288 } | |
289 | |
290 TransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo( | |
291 QuicPacketNumber packet_number) { | |
292 return &unacked_packets_[packet_number - least_unacked_]; | |
293 } | |
294 | |
295 QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const { | |
296 UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); | |
297 while (it != unacked_packets_.rend()) { | |
298 if (it->in_flight) { | |
299 QUIC_BUG_IF(it->sent_time == QuicTime::Zero()) | |
300 << "Sent time can never be zero for a packet in flight."; | |
301 return it->sent_time; | |
302 } | |
303 ++it; | |
304 } | |
305 QUIC_BUG << "GetLastPacketSentTime requires in flight packets."; | |
306 return QuicTime::Zero(); | |
307 } | |
308 | |
309 size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const { | |
310 size_t unacked_packet_count = 0; | |
311 QuicPacketNumber packet_number = least_unacked_; | |
312 for (UnackedPacketMap::const_iterator it = unacked_packets_.begin(); | |
313 it != unacked_packets_.end(); ++it, ++packet_number) { | |
314 if (!IsPacketUseless(packet_number, *it)) { | |
315 ++unacked_packet_count; | |
316 } | |
317 } | |
318 return unacked_packet_count; | |
319 } | |
320 | |
321 bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const { | |
322 if (bytes_in_flight_ > kDefaultTCPMSS) { | |
323 return true; | |
324 } | |
325 size_t num_in_flight = 0; | |
326 for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); | |
327 it != unacked_packets_.rend(); ++it) { | |
328 if (it->in_flight) { | |
329 ++num_in_flight; | |
330 } | |
331 if (num_in_flight > 1) { | |
332 return true; | |
333 } | |
334 } | |
335 return false; | |
336 } | |
337 | |
338 bool QuicUnackedPacketMap::HasPendingCryptoPackets() const { | |
339 return pending_crypto_packet_count_ > 0; | |
340 } | |
341 | |
342 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const { | |
343 for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); | |
344 it != unacked_packets_.rend(); ++it) { | |
345 if (it->in_flight && !it->retransmittable_frames.empty()) { | |
346 return true; | |
347 } | |
348 } | |
349 return false; | |
350 } | |
351 | |
352 QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const { | |
353 return least_unacked_; | |
354 } | |
355 | |
356 } // namespace net | |
OLD | NEW |