OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/quic/quic_received_packet_manager.h" | |
6 | |
7 #include <limits> | |
8 #include <utility> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/stl_util.h" | |
12 #include "net/base/linked_hash_map.h" | |
13 #include "net/quic/crypto/crypto_protocol.h" | |
14 #include "net/quic/quic_connection_stats.h" | |
15 | |
16 using std::max; | |
17 using std::min; | |
18 using std::numeric_limits; | |
19 | |
20 namespace net { | |
21 | |
22 namespace { | |
23 | |
24 // The maximum number of packets to ack immediately after a missing packet for | |
25 // fast retransmission to kick in at the sender. This limit is created to | |
26 // reduce the number of acks sent that have no benefit for fast retransmission. | |
27 // Set to the number of nacks needed for fast retransmit plus one for protection | |
28 // against an ack loss | |
29 const size_t kMaxPacketsAfterNewMissing = 4; | |
30 | |
31 } | |
32 | |
33 QuicReceivedPacketManager::EntropyTracker::EntropyTracker() | |
34 : packets_entropy_hash_(0), | |
35 first_gap_(1), | |
36 largest_observed_(0) { | |
37 } | |
38 | |
39 QuicReceivedPacketManager::EntropyTracker::~EntropyTracker() {} | |
40 | |
41 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyTracker::EntropyHash( | |
42 QuicPacketSequenceNumber sequence_number) const { | |
43 DCHECK_LE(sequence_number, largest_observed_); | |
44 if (sequence_number == largest_observed_) { | |
45 return packets_entropy_hash_; | |
46 } | |
47 | |
48 DCHECK_GE(sequence_number, first_gap_); | |
49 DCHECK_EQ(first_gap_ + packets_entropy_.size() - 1, largest_observed_); | |
50 QuicPacketEntropyHash hash = packets_entropy_hash_; | |
51 ReceivedEntropyHashes::const_reverse_iterator it = packets_entropy_.rbegin(); | |
52 for (QuicPacketSequenceNumber i = 0; | |
53 i < (largest_observed_ - sequence_number); ++i, ++it) { | |
54 hash ^= it->first; | |
55 } | |
56 return hash; | |
57 } | |
58 | |
59 void QuicReceivedPacketManager::EntropyTracker::RecordPacketEntropyHash( | |
60 QuicPacketSequenceNumber sequence_number, | |
61 QuicPacketEntropyHash entropy_hash) { | |
62 if (sequence_number < first_gap_) { | |
63 DVLOG(1) << "Ignoring received packet entropy for sequence_number:" | |
64 << sequence_number << " less than largest_peer_sequence_number:" | |
65 << first_gap_; | |
66 return; | |
67 } | |
68 // RecordPacketEntropyHash is only intended to be called once per packet. | |
69 DCHECK(sequence_number > largest_observed_ || | |
70 !packets_entropy_[sequence_number - first_gap_].second); | |
71 | |
72 packets_entropy_hash_ ^= entropy_hash; | |
73 | |
74 // Optimize the typical case of no gaps. | |
75 if (sequence_number == largest_observed_ + 1 && packets_entropy_.empty()) { | |
76 ++first_gap_; | |
77 largest_observed_ = sequence_number; | |
78 return; | |
79 } | |
80 if (sequence_number > largest_observed_) { | |
81 for (QuicPacketSequenceNumber i = 0; | |
82 i < (sequence_number - largest_observed_ - 1); ++i) { | |
83 packets_entropy_.push_back(std::make_pair(0, false)); | |
84 } | |
85 packets_entropy_.push_back(std::make_pair(entropy_hash, true)); | |
86 largest_observed_ = sequence_number; | |
87 } else { | |
88 packets_entropy_[sequence_number - first_gap_] = | |
89 std::make_pair(entropy_hash, true); | |
90 AdvanceFirstGapAndGarbageCollectEntropyMap(); | |
91 } | |
92 | |
93 DVLOG(2) << "setting cumulative received entropy hash to: " | |
94 << static_cast<int>(packets_entropy_hash_) | |
95 << " updated with sequence number " << sequence_number | |
96 << " entropy hash: " << static_cast<int>(entropy_hash); | |
97 } | |
98 | |
99 void QuicReceivedPacketManager::EntropyTracker::SetCumulativeEntropyUpTo( | |
100 QuicPacketSequenceNumber sequence_number, | |
101 QuicPacketEntropyHash entropy_hash) { | |
102 DCHECK_LE(sequence_number, largest_observed_); | |
103 if (sequence_number < first_gap_) { | |
104 DVLOG(1) << "Ignoring set entropy at:" << sequence_number | |
105 << " less than first_gap_:" << first_gap_; | |
106 return; | |
107 } | |
108 while (first_gap_ < sequence_number) { | |
109 ++first_gap_; | |
110 if (!packets_entropy_.empty()) { | |
111 packets_entropy_.pop_front(); | |
112 } | |
113 } | |
114 // Compute the current entropy by XORing in all entropies received including | |
115 // and since sequence_number. | |
116 packets_entropy_hash_ = entropy_hash; | |
117 for (ReceivedEntropyHashes::const_iterator it = packets_entropy_.begin(); | |
118 it != packets_entropy_.end(); ++it) { | |
119 packets_entropy_hash_ ^= it->first; | |
120 } | |
121 | |
122 // Garbage collect entries from the beginning of the map. | |
123 AdvanceFirstGapAndGarbageCollectEntropyMap(); | |
124 } | |
125 | |
126 void QuicReceivedPacketManager::EntropyTracker:: | |
127 AdvanceFirstGapAndGarbageCollectEntropyMap() { | |
128 while (!packets_entropy_.empty() && packets_entropy_.front().second) { | |
129 ++first_gap_; | |
130 packets_entropy_.pop_front(); | |
131 } | |
132 } | |
133 | |
134 QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats) | |
135 : peer_least_packet_awaiting_ack_(0), | |
136 time_largest_observed_(QuicTime::Zero()), | |
137 stats_(stats) { | |
138 ack_frame_.largest_observed = 0; | |
139 ack_frame_.entropy_hash = 0; | |
140 } | |
141 | |
142 QuicReceivedPacketManager::~QuicReceivedPacketManager() {} | |
143 | |
144 void QuicReceivedPacketManager::RecordPacketReceived( | |
145 QuicByteCount bytes, | |
146 const QuicPacketHeader& header, | |
147 QuicTime receipt_time) { | |
148 QuicPacketSequenceNumber sequence_number = header.packet_sequence_number; | |
149 DCHECK(IsAwaitingPacket(sequence_number)); | |
150 | |
151 InsertMissingPacketsBetween( | |
152 &ack_frame_, | |
153 max(ack_frame_.largest_observed + 1, peer_least_packet_awaiting_ack_), | |
154 sequence_number); | |
155 | |
156 if (ack_frame_.largest_observed > sequence_number) { | |
157 // We've gotten one of the out of order packets - remove it from our | |
158 // "missing packets" list. | |
159 DVLOG(1) << "Removing " << sequence_number << " from missing list"; | |
160 ack_frame_.missing_packets.erase(sequence_number); | |
161 | |
162 // Record how out of order stats. | |
163 ++stats_->packets_reordered; | |
164 stats_->max_sequence_reordering = | |
165 max(stats_->max_sequence_reordering, | |
166 ack_frame_.largest_observed - sequence_number); | |
167 int64 reordering_time_us = | |
168 receipt_time.Subtract(time_largest_observed_).ToMicroseconds(); | |
169 stats_->max_time_reordering_us = max(stats_->max_time_reordering_us, | |
170 reordering_time_us); | |
171 } | |
172 if (sequence_number > ack_frame_.largest_observed) { | |
173 ack_frame_.largest_observed = sequence_number; | |
174 time_largest_observed_ = receipt_time; | |
175 } | |
176 entropy_tracker_.RecordPacketEntropyHash(sequence_number, | |
177 header.entropy_hash); | |
178 | |
179 received_packet_times_.push_back( | |
180 std::make_pair(sequence_number, receipt_time)); | |
181 | |
182 ack_frame_.revived_packets.erase(sequence_number); | |
183 } | |
184 | |
185 void QuicReceivedPacketManager::RecordPacketRevived( | |
186 QuicPacketSequenceNumber sequence_number) { | |
187 LOG_IF(DFATAL, !IsAwaitingPacket(sequence_number)); | |
188 ack_frame_.revived_packets.insert(sequence_number); | |
189 } | |
190 | |
191 bool QuicReceivedPacketManager::IsMissing( | |
192 QuicPacketSequenceNumber sequence_number) { | |
193 return ContainsKey(ack_frame_.missing_packets, sequence_number); | |
194 } | |
195 | |
196 bool QuicReceivedPacketManager::IsAwaitingPacket( | |
197 QuicPacketSequenceNumber sequence_number) { | |
198 return ::net::IsAwaitingPacket(ack_frame_, sequence_number); | |
199 } | |
200 | |
201 namespace { | |
202 struct isTooLarge { | |
203 explicit isTooLarge(QuicPacketSequenceNumber n) : largest_observed_(n) {} | |
204 QuicPacketSequenceNumber largest_observed_; | |
205 | |
206 // Return true if the packet in p is too different from largest_observed_ | |
207 // to express. | |
208 bool operator() ( | |
209 const std::pair<QuicPacketSequenceNumber, QuicTime>& p) const { | |
210 return largest_observed_ - p.first >= numeric_limits<uint8>::max(); | |
211 } | |
212 }; | |
213 } // namespace | |
214 | |
215 void QuicReceivedPacketManager::UpdateReceivedPacketInfo( | |
216 QuicAckFrame* ack_frame, QuicTime approximate_now) { | |
217 *ack_frame = ack_frame_; | |
218 ack_frame->entropy_hash = EntropyHash(ack_frame_.largest_observed); | |
219 | |
220 if (time_largest_observed_ == QuicTime::Zero()) { | |
221 // We have received no packets. | |
222 ack_frame->delta_time_largest_observed = QuicTime::Delta::Infinite(); | |
223 return; | |
224 } | |
225 | |
226 // Ensure the delta is zero if approximate now is "in the past". | |
227 ack_frame->delta_time_largest_observed = | |
228 approximate_now < time_largest_observed_ ? | |
229 QuicTime::Delta::Zero() : | |
230 approximate_now.Subtract(time_largest_observed_); | |
231 | |
232 // Remove all packets that are too far from largest_observed to express. | |
233 received_packet_times_.remove_if(isTooLarge(ack_frame_.largest_observed)); | |
234 | |
235 ack_frame->received_packet_times.clear(); | |
236 ack_frame->received_packet_times.swap(received_packet_times_); | |
237 } | |
238 | |
239 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( | |
240 QuicPacketSequenceNumber sequence_number) const { | |
241 return entropy_tracker_.EntropyHash(sequence_number); | |
242 } | |
243 | |
244 bool QuicReceivedPacketManager::DontWaitForPacketsBefore( | |
245 QuicPacketSequenceNumber least_unacked) { | |
246 ack_frame_.revived_packets.erase( | |
247 ack_frame_.revived_packets.begin(), | |
248 ack_frame_.revived_packets.lower_bound(least_unacked)); | |
249 size_t missing_packets_count = ack_frame_.missing_packets.size(); | |
250 ack_frame_.missing_packets.erase( | |
251 ack_frame_.missing_packets.begin(), | |
252 ack_frame_.missing_packets.lower_bound(least_unacked)); | |
253 return missing_packets_count != ack_frame_.missing_packets.size(); | |
254 } | |
255 | |
256 void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer( | |
257 const QuicStopWaitingFrame& stop_waiting) { | |
258 // ValidateAck() should fail if peer_least_packet_awaiting_ack_ shrinks. | |
259 DCHECK_LE(peer_least_packet_awaiting_ack_, stop_waiting.least_unacked); | |
260 if (stop_waiting.least_unacked > peer_least_packet_awaiting_ack_) { | |
261 bool missed_packets = DontWaitForPacketsBefore(stop_waiting.least_unacked); | |
262 if (missed_packets) { | |
263 DVLOG(1) << "Updating entropy hashed since we missed packets"; | |
264 // There were some missing packets that we won't ever get now. Recalculate | |
265 // the received entropy hash. | |
266 entropy_tracker_.SetCumulativeEntropyUpTo(stop_waiting.least_unacked, | |
267 stop_waiting.entropy_hash); | |
268 } | |
269 peer_least_packet_awaiting_ack_ = stop_waiting.least_unacked; | |
270 } | |
271 DCHECK(ack_frame_.missing_packets.empty() || | |
272 *ack_frame_.missing_packets.begin() >= | |
273 peer_least_packet_awaiting_ack_); | |
274 } | |
275 | |
276 bool QuicReceivedPacketManager::HasNewMissingPackets() const { | |
277 return !ack_frame_.missing_packets.empty() && | |
278 (ack_frame_.largest_observed - | |
279 *ack_frame_.missing_packets.rbegin()) <= kMaxPacketsAfterNewMissing; | |
280 } | |
281 | |
282 size_t QuicReceivedPacketManager::NumTrackedPackets() const { | |
283 return entropy_tracker_.size(); | |
284 } | |
285 | |
286 } // namespace net | |
OLD | NEW |