| 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 |