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 "base/logging.h" 8 #include "base/stl_util.h" 9 #include "net/base/linked_hash_map.h" 10 11 using std::make_pair; 12 using std::max; 13 using std::min; 14 15 namespace net { 16 17 namespace { 18 19 // The maximum number of packets to ack immediately after a missing packet for 20 // fast retransmission to kick in at the sender. This limit is created to 21 // reduce the number of acks sent that have no benefit for fast retransmission. 22 // Set to the number of nacks needed for fast retransmit plus one for protection 23 // against an ack loss 24 const size_t kMaxPacketsAfterNewMissing = 4; 25 26 } 27 28 QuicReceivedPacketManager::QuicReceivedPacketManager( 29 CongestionFeedbackType congestion_type) 30 : packets_entropy_hash_(0), 31 largest_sequence_number_(0), 32 peer_largest_observed_packet_(0), 33 least_packet_awaited_by_peer_(1), 34 peer_least_packet_awaiting_ack_(0), 35 time_largest_observed_(QuicTime::Zero()), 36 receive_algorithm_(ReceiveAlgorithmInterface::Create(congestion_type)) { 37 received_info_.largest_observed = 0; 38 received_info_.entropy_hash = 0; 39 } 40 41 QuicReceivedPacketManager::~QuicReceivedPacketManager() {} 42 43 void QuicReceivedPacketManager::RecordPacketReceived( 44 QuicByteCount bytes, 45 const QuicPacketHeader& header, 46 QuicTime receipt_time, 47 bool revived) { 48 QuicPacketSequenceNumber sequence_number = header.packet_sequence_number; 49 DCHECK(IsAwaitingPacket(sequence_number)); 50 51 InsertMissingPacketsBetween( 52 &received_info_, 53 max(received_info_.largest_observed + 1, peer_least_packet_awaiting_ack_), 54 header.packet_sequence_number); 55 56 if (received_info_.largest_observed > header.packet_sequence_number) { 57 // We've gotten one of the out of order packets - remove it from our 58 // "missing packets" list. 59 DVLOG(1) << "Removing " << sequence_number << " from missing list"; 60 received_info_.missing_packets.erase(sequence_number); 61 } 62 if (header.packet_sequence_number > received_info_.largest_observed) { 63 received_info_.largest_observed = header.packet_sequence_number; 64 time_largest_observed_ = receipt_time; 65 } 66 RecordPacketEntropyHash(sequence_number, header.entropy_hash); 67 68 // Don't update the receive algorithm for revived packets. 69 if (!revived) { 70 receive_algorithm_->RecordIncomingPacket( 71 bytes, sequence_number, receipt_time, revived); 72 } 73 } 74 75 bool QuicReceivedPacketManager::IsMissing( 76 QuicPacketSequenceNumber sequence_number) { 77 return ContainsKey(received_info_.missing_packets, sequence_number); 78 } 79 80 bool QuicReceivedPacketManager::IsAwaitingPacket( 81 QuicPacketSequenceNumber sequence_number) { 82 return ::net::IsAwaitingPacket(received_info_, sequence_number); 83 } 84 85 void QuicReceivedPacketManager::UpdateReceivedPacketInfo( 86 ReceivedPacketInfo* received_info, 87 QuicTime approximate_now) { 88 *received_info = received_info_; 89 received_info->entropy_hash = EntropyHash(received_info_.largest_observed); 90 91 if (time_largest_observed_ == QuicTime::Zero()) { 92 // We have received no packets. 93 received_info->delta_time_largest_observed = QuicTime::Delta::Infinite(); 94 return; 95 } 96 97 if (approximate_now < time_largest_observed_) { 98 // Approximate now may well be "in the past". 99 received_info->delta_time_largest_observed = QuicTime::Delta::Zero(); 100 return; 101 } 102 103 received_info->delta_time_largest_observed = 104 approximate_now.Subtract(time_largest_observed_); 105 } 106 107 void QuicReceivedPacketManager::RecordPacketEntropyHash( 108 QuicPacketSequenceNumber sequence_number, 109 QuicPacketEntropyHash entropy_hash) { 110 if (sequence_number < largest_sequence_number_) { 111 DVLOG(1) << "Ignoring received packet entropy for sequence_number:" 112 << sequence_number << " less than largest_peer_sequence_number:" 113 << largest_sequence_number_; 114 return; 115 } 116 packets_entropy_.insert(make_pair(sequence_number, entropy_hash)); 117 packets_entropy_hash_ ^= entropy_hash; 118 DVLOG(2) << "setting cumulative received entropy hash to: " 119 << static_cast<int>(packets_entropy_hash_) 120 << " updated with sequence number " << sequence_number 121 << " entropy hash: " << static_cast<int>(entropy_hash); 122 } 123 124 bool QuicReceivedPacketManager::GenerateCongestionFeedback( 125 QuicCongestionFeedbackFrame* feedback) { 126 return receive_algorithm_->GenerateCongestionFeedback(feedback); 127 } 128 129 QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( 130 QuicPacketSequenceNumber sequence_number) const { 131 DCHECK_LE(sequence_number, received_info_.largest_observed); 132 DCHECK_GE(sequence_number, largest_sequence_number_); 133 if (sequence_number == received_info_.largest_observed) { 134 return packets_entropy_hash_; 135 } 136 137 ReceivedEntropyMap::const_iterator it = 138 packets_entropy_.upper_bound(sequence_number); 139 // When this map is empty we should only query entropy for 140 // received_info_.largest_observed, since no other entropy can be correctly 141 // calculated, because we're not storing the entropy for any prior packets. 142 // TODO(rtenneti): add support for LOG_IF_EVERY_N_SEC to chromium. 143 // LOG_IF_EVERY_N_SEC(DFATAL, it == packets_entropy_.end(), 10) 144 LOG_IF(DFATAL, it == packets_entropy_.end()) 145 << "EntropyHash may be unknown. largest_received: " 146 << received_info_.largest_observed 147 << " sequence_number: " << sequence_number; 148 149 // TODO(satyamshekhar): Make this O(1). 150 QuicPacketEntropyHash hash = packets_entropy_hash_; 151 for (; it != packets_entropy_.end(); ++it) { 152 hash ^= it->second; 153 } 154 return hash; 155 } 156 157 void QuicReceivedPacketManager::RecalculateEntropyHash( 158 QuicPacketSequenceNumber peer_least_unacked, 159 QuicPacketEntropyHash entropy_hash) { 160 DCHECK_LE(peer_least_unacked, received_info_.largest_observed); 161 if (peer_least_unacked < largest_sequence_number_) { 162 DVLOG(1) << "Ignoring received peer_least_unacked:" << peer_least_unacked 163 << " less than largest_peer_sequence_number:" 164 << largest_sequence_number_; 165 return; 166 } 167 largest_sequence_number_ = peer_least_unacked; 168 packets_entropy_hash_ = entropy_hash; 169 ReceivedEntropyMap::iterator it = 170 packets_entropy_.lower_bound(peer_least_unacked); 171 // TODO(satyamshekhar): Make this O(1). 172 for (; it != packets_entropy_.end(); ++it) { 173 packets_entropy_hash_ ^= it->second; 174 } 175 // Discard entropies before least unacked. 176 packets_entropy_.erase( 177 packets_entropy_.begin(), 178 packets_entropy_.lower_bound( 179 min(peer_least_unacked, received_info_.largest_observed))); 180 } 181 182 void QuicReceivedPacketManager::UpdatePacketInformationReceivedByPeer( 183 const QuicAckFrame& incoming_ack) { 184 // ValidateAck should fail if largest_observed ever shrinks. 185 DCHECK_LE(peer_largest_observed_packet_, 186 incoming_ack.received_info.largest_observed); 187 peer_largest_observed_packet_ = incoming_ack.received_info.largest_observed; 188 189 if (incoming_ack.received_info.missing_packets.empty()) { 190 least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1; 191 } else { 192 least_packet_awaited_by_peer_ = 193 *(incoming_ack.received_info.missing_packets.begin()); 194 } 195 } 196 197 bool QuicReceivedPacketManager::DontWaitForPacketsBefore( 198 QuicPacketSequenceNumber least_unacked) { 199 size_t missing_packets_count = received_info_.missing_packets.size(); 200 received_info_.missing_packets.erase( 201 received_info_.missing_packets.begin(), 202 received_info_.missing_packets.lower_bound(least_unacked)); 203 return missing_packets_count != received_info_.missing_packets.size(); 204 } 205 206 void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer( 207 const QuicAckFrame& incoming_ack) { 208 // ValidateAck() should fail if peer_least_packet_awaiting_ack_ shrinks. 209 DCHECK_LE(peer_least_packet_awaiting_ack_, 210 incoming_ack.sent_info.least_unacked); 211 if (incoming_ack.sent_info.least_unacked > peer_least_packet_awaiting_ack_) { 212 bool missed_packets = 213 DontWaitForPacketsBefore(incoming_ack.sent_info.least_unacked); 214 if (missed_packets || incoming_ack.sent_info.least_unacked > 215 received_info_.largest_observed + 1) { 216 DVLOG(1) << "Updating entropy hashed since we missed packets"; 217 // There were some missing packets that we won't ever get now. Recalculate 218 // the received entropy hash. 219 RecalculateEntropyHash(incoming_ack.sent_info.least_unacked, 220 incoming_ack.sent_info.entropy_hash); 221 } 222 peer_least_packet_awaiting_ack_ = incoming_ack.sent_info.least_unacked; 223 } 224 DCHECK(received_info_.missing_packets.empty() || 225 *received_info_.missing_packets.begin() >= 226 peer_least_packet_awaiting_ack_); 227 } 228 229 bool QuicReceivedPacketManager::HasMissingPackets() { 230 return !received_info_.missing_packets.empty(); 231 } 232 233 bool QuicReceivedPacketManager::HasNewMissingPackets() { 234 return HasMissingPackets() && 235 (received_info_.largest_observed - 236 *received_info_.missing_packets.rbegin()) <= kMaxPacketsAfterNewMissing; 237 } 238 239 } // namespace net 240