OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/core/quic_received_packet_manager.h" | 5 #include "net/quic/core/quic_received_packet_manager.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 namespace { | 24 namespace { |
25 | 25 |
26 // The maximum number of packets to ack immediately after a missing packet for | 26 // The maximum number of packets to ack immediately after a missing packet for |
27 // fast retransmission to kick in at the sender. This limit is created to | 27 // fast retransmission to kick in at the sender. This limit is created to |
28 // reduce the number of acks sent that have no benefit for fast retransmission. | 28 // reduce the number of acks sent that have no benefit for fast retransmission. |
29 // Set to the number of nacks needed for fast retransmit plus one for protection | 29 // Set to the number of nacks needed for fast retransmit plus one for protection |
30 // against an ack loss | 30 // against an ack loss |
31 const size_t kMaxPacketsAfterNewMissing = 4; | 31 const size_t kMaxPacketsAfterNewMissing = 4; |
32 } | 32 } |
33 | 33 |
34 QuicReceivedPacketManager::EntropyTracker::EntropyTracker() | |
35 : packets_entropy_hash_(0), first_gap_(1), largest_observed_(0) {} | |
36 | |
37 QuicReceivedPacketManager::EntropyTracker::~EntropyTracker() {} | |
38 | |
39 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyTracker::EntropyHash( | |
40 QuicPacketNumber packet_number) const { | |
41 DCHECK_LE(packet_number, largest_observed_); | |
42 if (packet_number == largest_observed_) { | |
43 return packets_entropy_hash_; | |
44 } | |
45 | |
46 DCHECK_GE(packet_number, first_gap_); | |
47 DCHECK_EQ(first_gap_ + packets_entropy_.size() - 1, largest_observed_); | |
48 QuicPacketEntropyHash hash = packets_entropy_hash_; | |
49 ReceivedEntropyHashes::const_reverse_iterator it = packets_entropy_.rbegin(); | |
50 for (QuicPacketNumber i = 0; i < (largest_observed_ - packet_number); | |
51 ++i, ++it) { | |
52 hash ^= it->first; | |
53 } | |
54 return hash; | |
55 } | |
56 | |
57 void QuicReceivedPacketManager::EntropyTracker::RecordPacketEntropyHash( | |
58 QuicPacketNumber packet_number, | |
59 QuicPacketEntropyHash entropy_hash) { | |
60 if (packet_number < first_gap_) { | |
61 DVLOG(1) << "Ignoring received packet entropy for packet_number:" | |
62 << packet_number | |
63 << " less than largest_peer_packet_number:" << first_gap_; | |
64 return; | |
65 } | |
66 // RecordPacketEntropyHash is only intended to be called once per packet. | |
67 DCHECK(packet_number > largest_observed_ || | |
68 !packets_entropy_[packet_number - first_gap_].second); | |
69 | |
70 packets_entropy_hash_ ^= entropy_hash; | |
71 | |
72 // Optimize the typical case of no gaps. | |
73 if (packet_number == largest_observed_ + 1 && packets_entropy_.empty()) { | |
74 ++first_gap_; | |
75 largest_observed_ = packet_number; | |
76 return; | |
77 } | |
78 if (packet_number > largest_observed_) { | |
79 for (QuicPacketNumber i = 0; i < (packet_number - largest_observed_ - 1); | |
80 ++i) { | |
81 packets_entropy_.push_back(std::make_pair(0, false)); | |
82 } | |
83 packets_entropy_.push_back(std::make_pair(entropy_hash, true)); | |
84 largest_observed_ = packet_number; | |
85 } else { | |
86 packets_entropy_[packet_number - first_gap_] = | |
87 std::make_pair(entropy_hash, true); | |
88 AdvanceFirstGapAndGarbageCollectEntropyMap(); | |
89 } | |
90 | |
91 DVLOG(2) << "setting cumulative received entropy hash to: " | |
92 << static_cast<int>(packets_entropy_hash_) | |
93 << " updated with packet number " << packet_number | |
94 << " entropy hash: " << static_cast<int>(entropy_hash); | |
95 } | |
96 | |
97 void QuicReceivedPacketManager::EntropyTracker::SetCumulativeEntropyUpTo( | |
98 QuicPacketNumber packet_number, | |
99 QuicPacketEntropyHash entropy_hash) { | |
100 DCHECK_LE(packet_number, largest_observed_); | |
101 if (packet_number < first_gap_) { | |
102 DVLOG(1) << "Ignoring set entropy at:" << packet_number | |
103 << " less than first_gap_:" << first_gap_; | |
104 return; | |
105 } | |
106 while (first_gap_ < packet_number) { | |
107 ++first_gap_; | |
108 if (!packets_entropy_.empty()) { | |
109 packets_entropy_.pop_front(); | |
110 } | |
111 } | |
112 // Compute the current entropy by XORing in all entropies received including | |
113 // and since packet_number. | |
114 packets_entropy_hash_ = entropy_hash; | |
115 for (ReceivedEntropyHashes::const_iterator it = packets_entropy_.begin(); | |
116 it != packets_entropy_.end(); ++it) { | |
117 packets_entropy_hash_ ^= it->first; | |
118 } | |
119 | |
120 // Garbage collect entries from the beginning of the map. | |
121 AdvanceFirstGapAndGarbageCollectEntropyMap(); | |
122 } | |
123 | |
124 void QuicReceivedPacketManager::EntropyTracker:: | |
125 AdvanceFirstGapAndGarbageCollectEntropyMap() { | |
126 while (!packets_entropy_.empty() && packets_entropy_.front().second) { | |
127 ++first_gap_; | |
128 packets_entropy_.pop_front(); | |
129 } | |
130 } | |
131 | |
132 QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats) | 34 QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats) |
133 : peer_least_packet_awaiting_ack_(0), | 35 : peer_least_packet_awaiting_ack_(0), |
134 ack_frame_updated_(false), | 36 ack_frame_updated_(false), |
135 time_largest_observed_(QuicTime::Zero()), | 37 time_largest_observed_(QuicTime::Zero()), |
136 stats_(stats) { | 38 stats_(stats) { |
137 ack_frame_.largest_observed = 0; | 39 ack_frame_.largest_observed = 0; |
138 ack_frame_.entropy_hash = 0; | |
139 } | 40 } |
140 | 41 |
141 QuicReceivedPacketManager::~QuicReceivedPacketManager() {} | 42 QuicReceivedPacketManager::~QuicReceivedPacketManager() {} |
142 | 43 |
143 void QuicReceivedPacketManager::RecordPacketReceived( | 44 void QuicReceivedPacketManager::RecordPacketReceived( |
144 const QuicPacketHeader& header, | 45 const QuicPacketHeader& header, |
145 QuicTime receipt_time) { | 46 QuicTime receipt_time) { |
146 QuicPacketNumber packet_number = header.packet_number; | 47 QuicPacketNumber packet_number = header.packet_number; |
147 DCHECK(IsAwaitingPacket(packet_number)) << " packet_number:" << packet_number; | 48 DCHECK(IsAwaitingPacket(packet_number)) << " packet_number:" << packet_number; |
148 if (!ack_frame_updated_) { | 49 if (!ack_frame_updated_) { |
149 ack_frame_.received_packet_times.clear(); | 50 ack_frame_.received_packet_times.clear(); |
150 } | 51 } |
151 ack_frame_updated_ = true; | 52 ack_frame_updated_ = true; |
152 if (ack_frame_.missing) { | 53 ack_frame_.packets.Add(header.packet_number); |
153 // Adds the range of packet numbers from max(largest observed + 1, least | |
154 // awaiting ack) up to packet_number not including packet_number. | |
155 ack_frame_.packets.Add( | |
156 max(ack_frame_.largest_observed + 1, peer_least_packet_awaiting_ack_), | |
157 packet_number); | |
158 } else { | |
159 ack_frame_.packets.Add(header.packet_number); | |
160 } | |
161 | 54 |
162 if (ack_frame_.largest_observed > packet_number) { | 55 if (ack_frame_.largest_observed > packet_number) { |
163 if (ack_frame_.missing) { | |
164 // We've gotten one of the out of order packets - remove it from our | |
165 // "missing packets" list. | |
166 DVLOG(1) << "Removing " << packet_number << " from missing list"; | |
167 ack_frame_.packets.Remove(packet_number); | |
168 } | |
169 | |
170 // Record how out of order stats. | 56 // Record how out of order stats. |
171 ++stats_->packets_reordered; | 57 ++stats_->packets_reordered; |
172 stats_->max_sequence_reordering = | 58 stats_->max_sequence_reordering = |
173 max(stats_->max_sequence_reordering, | 59 max(stats_->max_sequence_reordering, |
174 ack_frame_.largest_observed - packet_number); | 60 ack_frame_.largest_observed - packet_number); |
175 int64_t reordering_time_us = | 61 int64_t reordering_time_us = |
176 (receipt_time - time_largest_observed_).ToMicroseconds(); | 62 (receipt_time - time_largest_observed_).ToMicroseconds(); |
177 stats_->max_time_reordering_us = | 63 stats_->max_time_reordering_us = |
178 max(stats_->max_time_reordering_us, reordering_time_us); | 64 max(stats_->max_time_reordering_us, reordering_time_us); |
179 } | 65 } |
180 if (packet_number > ack_frame_.largest_observed) { | 66 if (packet_number > ack_frame_.largest_observed) { |
181 ack_frame_.largest_observed = packet_number; | 67 ack_frame_.largest_observed = packet_number; |
182 time_largest_observed_ = receipt_time; | 68 time_largest_observed_ = receipt_time; |
183 } | 69 } |
184 if (ack_frame_.missing) { | |
185 entropy_tracker_.RecordPacketEntropyHash(packet_number, | |
186 header.entropy_hash); | |
187 } | |
188 | 70 |
189 ack_frame_.received_packet_times.push_back( | 71 ack_frame_.received_packet_times.push_back( |
190 std::make_pair(packet_number, receipt_time)); | 72 std::make_pair(packet_number, receipt_time)); |
191 } | 73 } |
192 | 74 |
193 bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) { | 75 bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) { |
194 if (ack_frame_.missing) { | |
195 return ack_frame_.packets.Contains(packet_number); | |
196 } | |
197 return packet_number < ack_frame_.largest_observed && | 76 return packet_number < ack_frame_.largest_observed && |
198 !ack_frame_.packets.Contains(packet_number); | 77 !ack_frame_.packets.Contains(packet_number); |
199 } | 78 } |
200 | 79 |
201 bool QuicReceivedPacketManager::IsAwaitingPacket( | 80 bool QuicReceivedPacketManager::IsAwaitingPacket( |
202 QuicPacketNumber packet_number) { | 81 QuicPacketNumber packet_number) { |
203 return ::net::IsAwaitingPacket(ack_frame_, packet_number, | 82 return ::net::IsAwaitingPacket(ack_frame_, packet_number, |
204 peer_least_packet_awaiting_ack_); | 83 peer_least_packet_awaiting_ack_); |
205 } | 84 } |
206 | 85 |
207 namespace { | 86 namespace { |
208 struct isTooLarge { | 87 struct isTooLarge { |
209 explicit isTooLarge(QuicPacketNumber n) : largest_observed_(n) {} | 88 explicit isTooLarge(QuicPacketNumber n) : largest_observed_(n) {} |
210 QuicPacketNumber largest_observed_; | 89 QuicPacketNumber largest_observed_; |
211 | 90 |
212 // Return true if the packet in p is too different from largest_observed_ | 91 // Return true if the packet in p is too different from largest_observed_ |
213 // to express. | 92 // to express. |
214 bool operator()(const std::pair<QuicPacketNumber, QuicTime>& p) const { | 93 bool operator()(const std::pair<QuicPacketNumber, QuicTime>& p) const { |
215 return largest_observed_ - p.first >= std::numeric_limits<uint8_t>::max(); | 94 return largest_observed_ - p.first >= std::numeric_limits<uint8_t>::max(); |
216 } | 95 } |
217 }; | 96 }; |
218 } // namespace | 97 } // namespace |
219 | 98 |
220 const QuicFrame QuicReceivedPacketManager::GetUpdatedAckFrame( | 99 const QuicFrame QuicReceivedPacketManager::GetUpdatedAckFrame( |
221 QuicTime approximate_now) { | 100 QuicTime approximate_now) { |
222 ack_frame_updated_ = false; | 101 ack_frame_updated_ = false; |
223 if (ack_frame_.missing) { | |
224 ack_frame_.entropy_hash = EntropyHash(ack_frame_.largest_observed); | |
225 } | |
226 | |
227 if (time_largest_observed_ == QuicTime::Zero()) { | 102 if (time_largest_observed_ == QuicTime::Zero()) { |
228 // We have received no packets. | 103 // We have received no packets. |
229 ack_frame_.ack_delay_time = QuicTime::Delta::Infinite(); | 104 ack_frame_.ack_delay_time = QuicTime::Delta::Infinite(); |
230 } else { | 105 } else { |
231 // Ensure the delta is zero if approximate now is "in the past". | 106 // Ensure the delta is zero if approximate now is "in the past". |
232 ack_frame_.ack_delay_time = approximate_now < time_largest_observed_ | 107 ack_frame_.ack_delay_time = approximate_now < time_largest_observed_ |
233 ? QuicTime::Delta::Zero() | 108 ? QuicTime::Delta::Zero() |
234 : approximate_now - time_largest_observed_; | 109 : approximate_now - time_largest_observed_; |
235 } | 110 } |
236 | 111 |
237 // Clear all packet times if any are too far from largest observed. | 112 // Clear all packet times if any are too far from largest observed. |
238 // It's expected this is extremely rare. | 113 // It's expected this is extremely rare. |
239 for (PacketTimeVector::iterator it = ack_frame_.received_packet_times.begin(); | 114 for (PacketTimeVector::iterator it = ack_frame_.received_packet_times.begin(); |
240 it != ack_frame_.received_packet_times.end();) { | 115 it != ack_frame_.received_packet_times.end();) { |
241 if (ack_frame_.largest_observed - it->first >= | 116 if (ack_frame_.largest_observed - it->first >= |
242 std::numeric_limits<uint8_t>::max()) { | 117 std::numeric_limits<uint8_t>::max()) { |
243 it = ack_frame_.received_packet_times.erase(it); | 118 it = ack_frame_.received_packet_times.erase(it); |
244 } else { | 119 } else { |
245 ++it; | 120 ++it; |
246 } | 121 } |
247 } | 122 } |
248 | 123 |
249 return QuicFrame(&ack_frame_); | 124 return QuicFrame(&ack_frame_); |
250 } | 125 } |
251 | 126 |
252 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( | |
253 QuicPacketNumber packet_number) const { | |
254 return entropy_tracker_.EntropyHash(packet_number); | |
255 } | |
256 | |
257 bool QuicReceivedPacketManager::DontWaitForPacketsBefore( | 127 bool QuicReceivedPacketManager::DontWaitForPacketsBefore( |
258 QuicPacketNumber least_unacked) { | 128 QuicPacketNumber least_unacked) { |
259 peer_least_packet_awaiting_ack_ = least_unacked; | 129 peer_least_packet_awaiting_ack_ = least_unacked; |
260 return ack_frame_.packets.RemoveUpTo(least_unacked); | 130 return ack_frame_.packets.RemoveUpTo(least_unacked); |
261 } | 131 } |
262 | 132 |
263 void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer( | 133 void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer( |
264 const QuicStopWaitingFrame& stop_waiting) { | 134 const QuicStopWaitingFrame& stop_waiting) { |
265 // ValidateAck() should fail if peer_least_packet_awaiting_ack shrinks. | 135 // ValidateAck() should fail if peer_least_packet_awaiting_ack shrinks. |
266 DCHECK_LE(peer_least_packet_awaiting_ack_, stop_waiting.least_unacked); | 136 DCHECK_LE(peer_least_packet_awaiting_ack_, stop_waiting.least_unacked); |
267 if (stop_waiting.least_unacked > peer_least_packet_awaiting_ack_) { | 137 if (stop_waiting.least_unacked > peer_least_packet_awaiting_ack_) { |
268 bool packets_updated = DontWaitForPacketsBefore(stop_waiting.least_unacked); | 138 bool packets_updated = DontWaitForPacketsBefore(stop_waiting.least_unacked); |
269 if (packets_updated) { | 139 if (packets_updated) { |
270 if (ack_frame_.missing) { | |
271 DVLOG(1) << "Updating entropy hashed since we missed packets"; | |
272 // There were some missing packets that we won't ever get now. | |
273 // Recalculate the received entropy hash. | |
274 entropy_tracker_.SetCumulativeEntropyUpTo(stop_waiting.least_unacked, | |
275 stop_waiting.entropy_hash); | |
276 } | |
277 // Ack frame gets updated because packets set is updated because of stop | 140 // Ack frame gets updated because packets set is updated because of stop |
278 // waiting frame. | 141 // waiting frame. |
279 ack_frame_updated_ = true; | 142 ack_frame_updated_ = true; |
280 } | 143 } |
281 } | 144 } |
282 DCHECK(ack_frame_.packets.Empty() || | 145 DCHECK(ack_frame_.packets.Empty() || |
283 ack_frame_.packets.Min() >= peer_least_packet_awaiting_ack_); | 146 ack_frame_.packets.Min() >= peer_least_packet_awaiting_ack_); |
284 } | 147 } |
285 | 148 |
286 bool QuicReceivedPacketManager::HasMissingPackets() const { | 149 bool QuicReceivedPacketManager::HasMissingPackets() const { |
287 if (ack_frame_.missing) { | |
288 return !ack_frame_.packets.Empty(); | |
289 } | |
290 | |
291 return ack_frame_.packets.NumIntervals() > 1 || | 150 return ack_frame_.packets.NumIntervals() > 1 || |
292 (!ack_frame_.packets.Empty() && | 151 (!ack_frame_.packets.Empty() && |
293 ack_frame_.packets.Min() > | 152 ack_frame_.packets.Min() > |
294 max(QuicPacketNumber(1), peer_least_packet_awaiting_ack_)); | 153 max(QuicPacketNumber(1), peer_least_packet_awaiting_ack_)); |
295 } | 154 } |
296 | 155 |
297 bool QuicReceivedPacketManager::HasNewMissingPackets() const { | 156 bool QuicReceivedPacketManager::HasNewMissingPackets() const { |
298 if (ack_frame_.missing) { | |
299 return !ack_frame_.packets.Empty() && | |
300 (ack_frame_.largest_observed - ack_frame_.packets.Max()) <= | |
301 kMaxPacketsAfterNewMissing; | |
302 } | |
303 | |
304 return HasMissingPackets() && | 157 return HasMissingPackets() && |
305 ack_frame_.packets.LastIntervalLength() <= kMaxPacketsAfterNewMissing; | 158 ack_frame_.packets.LastIntervalLength() <= kMaxPacketsAfterNewMissing; |
306 } | 159 } |
307 | 160 |
308 size_t QuicReceivedPacketManager::NumTrackedPackets() const { | |
309 return entropy_tracker_.size(); | |
310 } | |
311 | |
312 void QuicReceivedPacketManager::SetVersion(QuicVersion version) { | |
313 ack_frame_.missing = version <= QUIC_VERSION_33; | |
314 } | |
315 | |
316 bool QuicReceivedPacketManager::ack_frame_updated() const { | 161 bool QuicReceivedPacketManager::ack_frame_updated() const { |
317 return ack_frame_updated_; | 162 return ack_frame_updated_; |
318 } | 163 } |
319 | 164 |
320 QuicPacketNumber QuicReceivedPacketManager::GetLargestObserved() const { | 165 QuicPacketNumber QuicReceivedPacketManager::GetLargestObserved() const { |
321 return ack_frame_.largest_observed; | 166 return ack_frame_.largest_observed; |
322 } | 167 } |
323 | 168 |
324 } // namespace net | 169 } // namespace net |
OLD | NEW |