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/quic_connection_stats.h"
10 #include "net/quic/quic_utils_chromium.h"
11
12 using std::max;
13
14 namespace net {
15
QuicUnackedPacketMap()16 QuicUnackedPacketMap::QuicUnackedPacketMap()
17 : largest_sent_packet_(0),
18 largest_observed_(0),
19 bytes_in_flight_(0),
20 pending_crypto_packet_count_(0) {
21 }
22
~QuicUnackedPacketMap()23 QuicUnackedPacketMap::~QuicUnackedPacketMap() {
24 for (UnackedPacketMap::iterator it = unacked_packets_.begin();
25 it != unacked_packets_.end(); ++it) {
26 delete it->second.retransmittable_frames;
27 // Only delete all_transmissions once, for the newest packet.
28 if (it->first == *it->second.all_transmissions->rbegin()) {
29 delete it->second.all_transmissions;
30 }
31 }
32 }
33
34 // TODO(ianswett): Combine this method with OnPacketSent once packets are always
35 // sent in order and the connection tracks RetransmittableFrames for longer.
AddPacket(const SerializedPacket & serialized_packet)36 void QuicUnackedPacketMap::AddPacket(
37 const SerializedPacket& serialized_packet) {
38 if (!unacked_packets_.empty()) {
39 bool is_old_packet = unacked_packets_.rbegin()->first >=
40 serialized_packet.sequence_number;
41 LOG_IF(DFATAL, is_old_packet) << "Old packet serialized: "
42 << serialized_packet.sequence_number
43 << " vs: "
44 << unacked_packets_.rbegin()->first;
45 }
46
47 unacked_packets_[serialized_packet.sequence_number] =
48 TransmissionInfo(serialized_packet.retransmittable_frames,
49 serialized_packet.sequence_number,
50 serialized_packet.sequence_number_length);
51 if (serialized_packet.retransmittable_frames != NULL &&
52 serialized_packet.retransmittable_frames->HasCryptoHandshake()
53 == IS_HANDSHAKE) {
54 ++pending_crypto_packet_count_;
55 }
56 }
57
OnRetransmittedPacket(QuicPacketSequenceNumber old_sequence_number,QuicPacketSequenceNumber new_sequence_number,TransmissionType transmission_type)58 void QuicUnackedPacketMap::OnRetransmittedPacket(
59 QuicPacketSequenceNumber old_sequence_number,
60 QuicPacketSequenceNumber new_sequence_number,
61 TransmissionType transmission_type) {
62 DCHECK(ContainsKey(unacked_packets_, old_sequence_number));
63 DCHECK(unacked_packets_.empty() ||
64 unacked_packets_.rbegin()->first < new_sequence_number);
65
66 // TODO(ianswett): Discard and lose the packet lazily instead of immediately.
67 TransmissionInfo* transmission_info =
68 FindOrNull(unacked_packets_, old_sequence_number);
69 RetransmittableFrames* frames = transmission_info->retransmittable_frames;
70 LOG_IF(DFATAL, frames == NULL) << "Attempt to retransmit packet with no "
71 << "retransmittable frames: "
72 << old_sequence_number;
73
74 // We keep the old packet in the unacked packet list until it, or one of
75 // the retransmissions of it are acked.
76 transmission_info->retransmittable_frames = NULL;
77 unacked_packets_[new_sequence_number] =
78 TransmissionInfo(frames,
79 new_sequence_number,
80 transmission_info->sequence_number_length,
81 transmission_type,
82 transmission_info->all_transmissions);
83 }
84
ClearPreviousRetransmissions(size_t num_to_clear)85 void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear) {
86 UnackedPacketMap::iterator it = unacked_packets_.begin();
87 while (it != unacked_packets_.end() && num_to_clear > 0) {
88 QuicPacketSequenceNumber sequence_number = it->first;
89 // If this packet is in flight, or has retransmittable data, then there is
90 // no point in clearing out any further packets, because they would not
91 // affect the high water mark.
92 if (it->second.in_flight || it->second.retransmittable_frames != NULL) {
93 break;
94 }
95
96 it->second.all_transmissions->erase(sequence_number);
97 LOG_IF(DFATAL, it->second.all_transmissions->empty())
98 << "Previous retransmissions must have a newer transmission.";
99 ++it;
100 unacked_packets_.erase(sequence_number);
101 --num_to_clear;
102 }
103 }
104
HasRetransmittableFrames(QuicPacketSequenceNumber sequence_number) const105 bool QuicUnackedPacketMap::HasRetransmittableFrames(
106 QuicPacketSequenceNumber sequence_number) const {
107 const TransmissionInfo* transmission_info =
108 FindOrNull(unacked_packets_, sequence_number);
109 if (transmission_info == NULL) {
110 return false;
111 }
112
113 return transmission_info->retransmittable_frames != NULL;
114 }
115
NackPacket(QuicPacketSequenceNumber sequence_number,size_t min_nacks)116 void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number,
117 size_t min_nacks) {
118 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
119 if (it == unacked_packets_.end()) {
120 LOG(DFATAL) << "NackPacket called for packet that is not unacked: "
121 << sequence_number;
122 return;
123 }
124
125 it->second.nack_count = max(min_nacks, it->second.nack_count);
126 }
127
RemoveRetransmittability(QuicPacketSequenceNumber sequence_number)128 void QuicUnackedPacketMap::RemoveRetransmittability(
129 QuicPacketSequenceNumber sequence_number) {
130 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
131 if (it == unacked_packets_.end()) {
132 DVLOG(1) << "packet is not in unacked_packets: " << sequence_number;
133 return;
134 }
135 SequenceNumberSet* all_transmissions = it->second.all_transmissions;
136 // TODO(ianswett): Consider optimizing this for lone packets.
137 // TODO(ianswett): Consider adding a check to ensure there are retransmittable
138 // frames associated with this packet.
139 for (SequenceNumberSet::reverse_iterator it = all_transmissions->rbegin();
140 it != all_transmissions->rend(); ++it) {
141 TransmissionInfo* transmission_info = FindOrNull(unacked_packets_, *it);
142 if (transmission_info == NULL) {
143 LOG(DFATAL) << "All transmissions in all_transmissions must be present "
144 << "in the unacked packet map.";
145 continue;
146 }
147 MaybeRemoveRetransmittableFrames(transmission_info);
148 if (*it <= largest_observed_ && !transmission_info->in_flight) {
149 unacked_packets_.erase(*it);
150 } else {
151 transmission_info->all_transmissions = new SequenceNumberSet();
152 transmission_info->all_transmissions->insert(*it);
153 }
154 }
155
156 delete all_transmissions;
157 }
158
MaybeRemoveRetransmittableFrames(TransmissionInfo * transmission_info)159 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames(
160 TransmissionInfo* transmission_info) {
161 if (transmission_info->retransmittable_frames != NULL) {
162 if (transmission_info->retransmittable_frames->HasCryptoHandshake()
163 == IS_HANDSHAKE) {
164 --pending_crypto_packet_count_;
165 }
166 delete transmission_info->retransmittable_frames;
167 transmission_info->retransmittable_frames = NULL;
168 }
169 }
170
IncreaseLargestObserved(QuicPacketSequenceNumber largest_observed)171 void QuicUnackedPacketMap::IncreaseLargestObserved(
172 QuicPacketSequenceNumber largest_observed) {
173 DCHECK_LT(largest_observed_, largest_observed);
174 largest_observed_ = largest_observed;
175 UnackedPacketMap::iterator it = unacked_packets_.begin();
176 while (it != unacked_packets_.end() && it->first <= largest_observed_) {
177 if (!IsPacketUseless(it)) {
178 ++it;
179 continue;
180 }
181 delete it->second.all_transmissions;
182 QuicPacketSequenceNumber sequence_number = it->first;
183 ++it;
184 unacked_packets_.erase(sequence_number);
185 }
186 }
187
IsPacketUseless(UnackedPacketMap::const_iterator it) const188 bool QuicUnackedPacketMap::IsPacketUseless(
189 UnackedPacketMap::const_iterator it) const {
190 return it->first <= largest_observed_ &&
191 !it->second.in_flight &&
192 it->second.retransmittable_frames == NULL &&
193 it->second.all_transmissions->size() == 1;
194 }
195
IsUnacked(QuicPacketSequenceNumber sequence_number) const196 bool QuicUnackedPacketMap::IsUnacked(
197 QuicPacketSequenceNumber sequence_number) const {
198 return ContainsKey(unacked_packets_, sequence_number);
199 }
200
RemoveFromInFlight(QuicPacketSequenceNumber sequence_number)201 void QuicUnackedPacketMap::RemoveFromInFlight(
202 QuicPacketSequenceNumber sequence_number) {
203 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
204 if (it == unacked_packets_.end()) {
205 LOG(DFATAL) << "RemoveFromFlight called for packet that is not unacked: "
206 << sequence_number;
207 return;
208 }
209 if (it->second.in_flight) {
210 LOG_IF(DFATAL, bytes_in_flight_ < it->second.bytes_sent);
211 bytes_in_flight_ -= it->second.bytes_sent;
212 it->second.in_flight = false;
213 }
214 if (IsPacketUseless(it)) {
215 delete it->second.all_transmissions;
216 unacked_packets_.erase(it);
217 }
218 }
219
HasUnackedPackets() const220 bool QuicUnackedPacketMap::HasUnackedPackets() const {
221 return !unacked_packets_.empty();
222 }
223
HasInFlightPackets() const224 bool QuicUnackedPacketMap::HasInFlightPackets() const {
225 return bytes_in_flight_ > 0;
226 }
227
GetTransmissionInfo(QuicPacketSequenceNumber sequence_number) const228 const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
229 QuicPacketSequenceNumber sequence_number) const {
230 return unacked_packets_.find(sequence_number)->second;
231 }
232
GetLastPacketSentTime() const233 QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const {
234 UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
235 while (it != unacked_packets_.rend()) {
236 if (it->second.in_flight) {
237 LOG_IF(DFATAL, it->second.sent_time == QuicTime::Zero())
238 << "Sent time can never be zero for a packet in flight.";
239 return it->second.sent_time;
240 }
241 ++it;
242 }
243 LOG(DFATAL) << "GetLastPacketSentTime requires in flight packets.";
244 return QuicTime::Zero();
245 }
246
GetFirstInFlightPacketSentTime() const247 QuicTime QuicUnackedPacketMap::GetFirstInFlightPacketSentTime() const {
248 UnackedPacketMap::const_iterator it = unacked_packets_.begin();
249 while (it != unacked_packets_.end() && !it->second.in_flight) {
250 ++it;
251 }
252 if (it == unacked_packets_.end()) {
253 LOG(DFATAL) << "GetFirstInFlightPacketSentTime requires in flight packets.";
254 return QuicTime::Zero();
255 }
256 return it->second.sent_time;
257 }
258
GetNumUnackedPackets() const259 size_t QuicUnackedPacketMap::GetNumUnackedPackets() const {
260 return unacked_packets_.size();
261 }
262
HasMultipleInFlightPackets() const263 bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
264 size_t num_in_flight = 0;
265 for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
266 it != unacked_packets_.rend(); ++it) {
267 if (it->second.in_flight) {
268 ++num_in_flight;
269 }
270 if (num_in_flight > 1) {
271 return true;
272 }
273 }
274 return false;
275 }
276
HasPendingCryptoPackets() const277 bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
278 return pending_crypto_packet_count_ > 0;
279 }
280
HasUnackedRetransmittableFrames() const281 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
282 for (UnackedPacketMap::const_reverse_iterator it =
283 unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) {
284 if (it->second.in_flight && it->second.retransmittable_frames) {
285 return true;
286 }
287 }
288 return false;
289 }
290
291 QuicPacketSequenceNumber
GetLeastUnackedSentPacket() const292 QuicUnackedPacketMap::GetLeastUnackedSentPacket() const {
293 if (unacked_packets_.empty()) {
294 // If there are no unacked packets, return 0.
295 return 0;
296 }
297
298 return unacked_packets_.begin()->first;
299 }
300
SetSent(QuicPacketSequenceNumber sequence_number,QuicTime sent_time,QuicByteCount bytes_sent,bool set_in_flight)301 void QuicUnackedPacketMap::SetSent(QuicPacketSequenceNumber sequence_number,
302 QuicTime sent_time,
303 QuicByteCount bytes_sent,
304 bool set_in_flight) {
305 DCHECK_LT(0u, sequence_number);
306 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
307 if (it == unacked_packets_.end()) {
308 LOG(DFATAL) << "OnPacketSent called for packet that is not unacked: "
309 << sequence_number;
310 return;
311 }
312 DCHECK(!it->second.in_flight);
313
314 largest_sent_packet_ = max(sequence_number, largest_sent_packet_);
315 it->second.sent_time = sent_time;
316 if (set_in_flight) {
317 bytes_in_flight_ += bytes_sent;
318 it->second.bytes_sent = bytes_sent;
319 it->second.in_flight = true;
320 }
321 }
322
323 } // namespace net
324