| 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/quic_received_packet_manager.h" | 5 #include "net/quic/quic_received_packet_manager.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "net/base/linked_hash_map.h" | 9 #include "net/base/linked_hash_map.h" |
| 10 #include "net/quic/quic_connection_stats.h" | 10 #include "net/quic/quic_connection_stats.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 QuicReceivedPacketManager::EntropyTracker::~EntropyTracker() {} | 35 QuicReceivedPacketManager::EntropyTracker::~EntropyTracker() {} |
| 36 | 36 |
| 37 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyTracker::EntropyHash( | 37 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyTracker::EntropyHash( |
| 38 QuicPacketSequenceNumber sequence_number) const { | 38 QuicPacketSequenceNumber sequence_number) const { |
| 39 DCHECK_LE(sequence_number, largest_observed_); | 39 DCHECK_LE(sequence_number, largest_observed_); |
| 40 if (sequence_number == largest_observed_) { | 40 if (sequence_number == largest_observed_) { |
| 41 return packets_entropy_hash_; | 41 return packets_entropy_hash_; |
| 42 } | 42 } |
| 43 | 43 |
| 44 DCHECK_GE(sequence_number, first_gap_); | 44 DCHECK_GE(sequence_number, first_gap_); |
| 45 ReceivedEntropyMap::const_iterator it = | 45 DCHECK_EQ(first_gap_ + packets_entropy_.size() - 1, largest_observed_); |
| 46 packets_entropy_.upper_bound(sequence_number); | |
| 47 // When this map is empty we should only query entropy for | |
| 48 // largest_observed_, since no other entropy can be correctly | |
| 49 // calculated, because we're not storing the entropy for any prior packets. | |
| 50 // TODO(rtenneti): add support for LOG_IF_EVERY_N_SEC to chromium. | |
| 51 // LOG_IF_EVERY_N_SEC(DFATAL, it == packets_entropy_.end(), 10) | |
| 52 LOG_IF(DFATAL, it == packets_entropy_.end()) | |
| 53 << "EntropyHash may be unknown. largest_received: " | |
| 54 << largest_observed_ | |
| 55 << " sequence_number: " << sequence_number; | |
| 56 | |
| 57 // TODO(satyamshekhar): Make this O(1). | |
| 58 QuicPacketEntropyHash hash = packets_entropy_hash_; | 46 QuicPacketEntropyHash hash = packets_entropy_hash_; |
| 59 for (; it != packets_entropy_.end(); ++it) { | 47 ReceivedEntropyHashes::const_reverse_iterator it = packets_entropy_.rbegin(); |
| 60 hash ^= it->second; | 48 for (QuicPacketSequenceNumber i = 0; |
| 49 i < (largest_observed_ - sequence_number); ++i, ++it) { |
| 50 hash ^= it->first; |
| 61 } | 51 } |
| 62 return hash; | 52 return hash; |
| 63 } | 53 } |
| 64 | 54 |
| 65 void QuicReceivedPacketManager::EntropyTracker::RecordPacketEntropyHash( | 55 void QuicReceivedPacketManager::EntropyTracker::RecordPacketEntropyHash( |
| 66 QuicPacketSequenceNumber sequence_number, | 56 QuicPacketSequenceNumber sequence_number, |
| 67 QuicPacketEntropyHash entropy_hash) { | 57 QuicPacketEntropyHash entropy_hash) { |
| 68 if (sequence_number < first_gap_) { | 58 if (sequence_number < first_gap_) { |
| 69 DVLOG(1) << "Ignoring received packet entropy for sequence_number:" | 59 DVLOG(1) << "Ignoring received packet entropy for sequence_number:" |
| 70 << sequence_number << " less than largest_peer_sequence_number:" | 60 << sequence_number << " less than largest_peer_sequence_number:" |
| 71 << first_gap_; | 61 << first_gap_; |
| 72 return; | 62 return; |
| 73 } | 63 } |
| 64 // RecordPacketEntropyHash is only intended to be called once per packet. |
| 65 DCHECK(sequence_number > largest_observed_ || |
| 66 !packets_entropy_[sequence_number - first_gap_].second); |
| 74 | 67 |
| 68 packets_entropy_hash_ ^= entropy_hash; |
| 69 |
| 70 // Optimize the typical case of no gaps. |
| 71 if (sequence_number == largest_observed_ + 1 && packets_entropy_.empty()) { |
| 72 ++first_gap_; |
| 73 largest_observed_ = sequence_number; |
| 74 return; |
| 75 } |
| 75 if (sequence_number > largest_observed_) { | 76 if (sequence_number > largest_observed_) { |
| 77 for (QuicPacketSequenceNumber i = 0; |
| 78 i < (sequence_number - largest_observed_ - 1); ++i) { |
| 79 packets_entropy_.push_back(make_pair(0, false)); |
| 80 } |
| 81 packets_entropy_.push_back(make_pair(entropy_hash, true)); |
| 76 largest_observed_ = sequence_number; | 82 largest_observed_ = sequence_number; |
| 83 } else { |
| 84 packets_entropy_[sequence_number - first_gap_] = |
| 85 make_pair(entropy_hash, true); |
| 86 AdvanceFirstGapAndGarbageCollectEntropyMap(); |
| 77 } | 87 } |
| 78 | 88 |
| 79 packets_entropy_hash_ ^= entropy_hash; | |
| 80 DVLOG(2) << "setting cumulative received entropy hash to: " | 89 DVLOG(2) << "setting cumulative received entropy hash to: " |
| 81 << static_cast<int>(packets_entropy_hash_) | 90 << static_cast<int>(packets_entropy_hash_) |
| 82 << " updated with sequence number " << sequence_number | 91 << " updated with sequence number " << sequence_number |
| 83 << " entropy hash: " << static_cast<int>(entropy_hash); | 92 << " entropy hash: " << static_cast<int>(entropy_hash); |
| 84 | |
| 85 packets_entropy_.insert(make_pair(sequence_number, entropy_hash)); | |
| 86 AdvanceFirstGapAndGarbageCollectEntropyMap(); | |
| 87 } | 93 } |
| 88 | 94 |
| 89 void QuicReceivedPacketManager::EntropyTracker::SetCumulativeEntropyUpTo( | 95 void QuicReceivedPacketManager::EntropyTracker::SetCumulativeEntropyUpTo( |
| 90 QuicPacketSequenceNumber sequence_number, | 96 QuicPacketSequenceNumber sequence_number, |
| 91 QuicPacketEntropyHash entropy_hash) { | 97 QuicPacketEntropyHash entropy_hash) { |
| 92 DCHECK_LE(sequence_number, largest_observed_); | 98 DCHECK_LE(sequence_number, largest_observed_); |
| 93 if (sequence_number < first_gap_) { | 99 if (sequence_number < first_gap_) { |
| 94 DVLOG(1) << "Ignoring set entropy at:" << sequence_number | 100 DVLOG(1) << "Ignoring set entropy at:" << sequence_number |
| 95 << " less than first_gap_:" << first_gap_; | 101 << " less than first_gap_:" << first_gap_; |
| 96 return; | 102 return; |
| 97 } | 103 } |
| 98 // Compute the current entropy based on the hash. | 104 while (first_gap_ < sequence_number) { |
| 105 ++first_gap_; |
| 106 if (!packets_entropy_.empty()) { |
| 107 packets_entropy_.pop_front(); |
| 108 } |
| 109 } |
| 110 // Compute the current entropy by XORing in all entropies received including |
| 111 // and since sequence_number. |
| 99 packets_entropy_hash_ = entropy_hash; | 112 packets_entropy_hash_ = entropy_hash; |
| 100 ReceivedEntropyMap::iterator it = | 113 for (ReceivedEntropyHashes::const_iterator it = packets_entropy_.begin(); |
| 101 packets_entropy_.lower_bound(sequence_number); | 114 it != packets_entropy_.end(); ++it) { |
| 102 // TODO(satyamshekhar): Make this O(1). | 115 packets_entropy_hash_ ^= it->first; |
| 103 for (; it != packets_entropy_.end(); ++it) { | |
| 104 packets_entropy_hash_ ^= it->second; | |
| 105 } | 116 } |
| 106 // Update first_gap_ and discard old entropies. | |
| 107 first_gap_ = sequence_number; | |
| 108 packets_entropy_.erase( | |
| 109 packets_entropy_.begin(), | |
| 110 packets_entropy_.lower_bound(sequence_number)); | |
| 111 | 117 |
| 112 // Garbage collect entries from the beginning of the map. | 118 // Garbage collect entries from the beginning of the map. |
| 113 AdvanceFirstGapAndGarbageCollectEntropyMap(); | 119 AdvanceFirstGapAndGarbageCollectEntropyMap(); |
| 114 } | 120 } |
| 115 | 121 |
| 116 void QuicReceivedPacketManager::EntropyTracker:: | 122 void QuicReceivedPacketManager::EntropyTracker:: |
| 117 AdvanceFirstGapAndGarbageCollectEntropyMap() { | 123 AdvanceFirstGapAndGarbageCollectEntropyMap() { |
| 118 while (!packets_entropy_.empty()) { | 124 while (!packets_entropy_.empty() && packets_entropy_.front().second) { |
| 119 ReceivedEntropyMap::iterator it = packets_entropy_.begin(); | |
| 120 if (it->first != first_gap_) { | |
| 121 DCHECK_GT(it->first, first_gap_); | |
| 122 break; | |
| 123 } | |
| 124 packets_entropy_.erase(it); | |
| 125 ++first_gap_; | 125 ++first_gap_; |
| 126 packets_entropy_.pop_front(); |
| 126 } | 127 } |
| 127 } | 128 } |
| 128 | 129 |
| 129 QuicReceivedPacketManager::QuicReceivedPacketManager( | 130 QuicReceivedPacketManager::QuicReceivedPacketManager( |
| 130 CongestionFeedbackType congestion_type, | 131 CongestionFeedbackType congestion_type, |
| 131 QuicConnectionStats* stats) | 132 QuicConnectionStats* stats) |
| 132 : peer_largest_observed_packet_(0), | 133 : peer_least_packet_awaiting_ack_(0), |
| 133 least_packet_awaited_by_peer_(1), | |
| 134 peer_least_packet_awaiting_ack_(0), | |
| 135 time_largest_observed_(QuicTime::Zero()), | 134 time_largest_observed_(QuicTime::Zero()), |
| 136 receive_algorithm_(ReceiveAlgorithmInterface::Create(congestion_type)), | 135 receive_algorithm_(ReceiveAlgorithmInterface::Create(congestion_type)), |
| 137 stats_(stats) { | 136 stats_(stats) { |
| 138 ack_frame_.largest_observed = 0; | 137 ack_frame_.largest_observed = 0; |
| 139 ack_frame_.entropy_hash = 0; | 138 ack_frame_.entropy_hash = 0; |
| 140 } | 139 } |
| 141 | 140 |
| 142 QuicReceivedPacketManager::~QuicReceivedPacketManager() {} | 141 QuicReceivedPacketManager::~QuicReceivedPacketManager() {} |
| 143 | 142 |
| 144 void QuicReceivedPacketManager::RecordPacketReceived( | 143 void QuicReceivedPacketManager::RecordPacketReceived( |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 bool QuicReceivedPacketManager::GenerateCongestionFeedback( | 221 bool QuicReceivedPacketManager::GenerateCongestionFeedback( |
| 223 QuicCongestionFeedbackFrame* feedback) { | 222 QuicCongestionFeedbackFrame* feedback) { |
| 224 return receive_algorithm_->GenerateCongestionFeedback(feedback); | 223 return receive_algorithm_->GenerateCongestionFeedback(feedback); |
| 225 } | 224 } |
| 226 | 225 |
| 227 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( | 226 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( |
| 228 QuicPacketSequenceNumber sequence_number) const { | 227 QuicPacketSequenceNumber sequence_number) const { |
| 229 return entropy_tracker_.EntropyHash(sequence_number); | 228 return entropy_tracker_.EntropyHash(sequence_number); |
| 230 } | 229 } |
| 231 | 230 |
| 232 void QuicReceivedPacketManager::UpdatePacketInformationReceivedByPeer( | |
| 233 const QuicAckFrame& ack_frame) { | |
| 234 // ValidateAck should fail if largest_observed ever shrinks. | |
| 235 DCHECK_LE(peer_largest_observed_packet_, ack_frame.largest_observed); | |
| 236 peer_largest_observed_packet_ = ack_frame.largest_observed; | |
| 237 | |
| 238 if (ack_frame.missing_packets.empty()) { | |
| 239 least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1; | |
| 240 } else { | |
| 241 least_packet_awaited_by_peer_ = *(ack_frame.missing_packets.begin()); | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 bool QuicReceivedPacketManager::DontWaitForPacketsBefore( | 231 bool QuicReceivedPacketManager::DontWaitForPacketsBefore( |
| 246 QuicPacketSequenceNumber least_unacked) { | 232 QuicPacketSequenceNumber least_unacked) { |
| 247 ack_frame_.revived_packets.erase( | 233 ack_frame_.revived_packets.erase( |
| 248 ack_frame_.revived_packets.begin(), | 234 ack_frame_.revived_packets.begin(), |
| 249 ack_frame_.revived_packets.lower_bound(least_unacked)); | 235 ack_frame_.revived_packets.lower_bound(least_unacked)); |
| 250 size_t missing_packets_count = ack_frame_.missing_packets.size(); | 236 size_t missing_packets_count = ack_frame_.missing_packets.size(); |
| 251 ack_frame_.missing_packets.erase( | 237 ack_frame_.missing_packets.erase( |
| 252 ack_frame_.missing_packets.begin(), | 238 ack_frame_.missing_packets.begin(), |
| 253 ack_frame_.missing_packets.lower_bound(least_unacked)); | 239 ack_frame_.missing_packets.lower_bound(least_unacked)); |
| 254 return missing_packets_count != ack_frame_.missing_packets.size(); | 240 return missing_packets_count != ack_frame_.missing_packets.size(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 267 entropy_tracker_.SetCumulativeEntropyUpTo(stop_waiting.least_unacked, | 253 entropy_tracker_.SetCumulativeEntropyUpTo(stop_waiting.least_unacked, |
| 268 stop_waiting.entropy_hash); | 254 stop_waiting.entropy_hash); |
| 269 } | 255 } |
| 270 peer_least_packet_awaiting_ack_ = stop_waiting.least_unacked; | 256 peer_least_packet_awaiting_ack_ = stop_waiting.least_unacked; |
| 271 } | 257 } |
| 272 DCHECK(ack_frame_.missing_packets.empty() || | 258 DCHECK(ack_frame_.missing_packets.empty() || |
| 273 *ack_frame_.missing_packets.begin() >= | 259 *ack_frame_.missing_packets.begin() >= |
| 274 peer_least_packet_awaiting_ack_); | 260 peer_least_packet_awaiting_ack_); |
| 275 } | 261 } |
| 276 | 262 |
| 277 bool QuicReceivedPacketManager::HasMissingPackets() { | |
| 278 return !ack_frame_.missing_packets.empty(); | |
| 279 } | |
| 280 | |
| 281 bool QuicReceivedPacketManager::HasNewMissingPackets() { | 263 bool QuicReceivedPacketManager::HasNewMissingPackets() { |
| 282 return HasMissingPackets() && | 264 return !ack_frame_.missing_packets.empty() && |
| 283 (ack_frame_.largest_observed - | 265 (ack_frame_.largest_observed - |
| 284 *ack_frame_.missing_packets.rbegin()) <= kMaxPacketsAfterNewMissing; | 266 *ack_frame_.missing_packets.rbegin()) <= kMaxPacketsAfterNewMissing; |
| 285 } | 267 } |
| 286 | 268 |
| 287 } // namespace net | 269 } // namespace net |
| OLD | NEW |