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

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

Powered by Google App Engine
This is Rietveld 408576698