Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(747)

Side by Side Diff: net/quic/quic_unacked_packet_map.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_unacked_packet_map.h ('k') | net/quic/quic_unacked_packet_map_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « net/quic/quic_unacked_packet_map.h ('k') | net/quic/quic_unacked_packet_map_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698