| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_unacked_packet_map.h" | 5 #include "net/quic/quic_unacked_packet_map.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/quic/quic_bug_tracker.h" | 9 #include "net/quic/quic_bug_tracker.h" |
| 10 #include "net/quic/quic_connection_stats.h" | 10 #include "net/quic/quic_connection_stats.h" |
| 11 #include "net/quic/quic_flags.h" | 11 #include "net/quic/quic_flags.h" |
| 12 #include "net/quic/quic_utils.h" | 12 #include "net/quic/quic_utils.h" |
| 13 #include "net/quic/quic_utils_chromium.h" | 13 #include "net/quic/quic_utils_chromium.h" |
| 14 | 14 |
| 15 using std::max; | 15 using std::max; |
| 16 | 16 |
| 17 namespace net { | 17 namespace net { |
| 18 | 18 |
| 19 QuicUnackedPacketMap::QuicUnackedPacketMap() | 19 QuicUnackedPacketMap::QuicUnackedPacketMap() |
| 20 : largest_sent_packet_(0), | 20 : largest_sent_packet_(0), |
| 21 largest_observed_(0), | 21 largest_observed_(0), |
| 22 least_unacked_(1), | 22 least_unacked_(1), |
| 23 bytes_in_flight_(0), | 23 bytes_in_flight_(0), |
| 24 pending_crypto_packet_count_(0), | 24 pending_crypto_packet_count_(0) {} |
| 25 track_single_retransmission_(FLAGS_quic_track_single_retransmission) {} | |
| 26 | 25 |
| 27 QuicUnackedPacketMap::~QuicUnackedPacketMap() { | 26 QuicUnackedPacketMap::~QuicUnackedPacketMap() { |
| 28 QuicPacketNumber index = least_unacked_; | 27 QuicPacketNumber index = least_unacked_; |
| 29 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); | 28 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); |
| 30 it != unacked_packets_.end(); ++it, ++index) { | 29 it != unacked_packets_.end(); ++it, ++index) { |
| 31 QuicUtils::DeleteFrames(&it->retransmittable_frames); | 30 QuicUtils::DeleteFrames(&it->retransmittable_frames); |
| 32 // Only delete all_transmissions once, for the newest packet. | |
| 33 if (it->all_transmissions != nullptr && | |
| 34 index == *it->all_transmissions->rbegin()) { | |
| 35 delete it->all_transmissions; | |
| 36 } | |
| 37 } | 31 } |
| 38 } | 32 } |
| 39 | 33 |
| 40 void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet, | 34 void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet, |
| 41 QuicPacketNumber old_packet_number, | 35 QuicPacketNumber old_packet_number, |
| 42 TransmissionType transmission_type, | 36 TransmissionType transmission_type, |
| 43 QuicTime sent_time, | 37 QuicTime sent_time, |
| 44 QuicByteCount bytes_sent, | 38 QuicByteCount bytes_sent, |
| 45 bool set_in_flight) { | 39 bool set_in_flight) { |
| 46 QuicPacketNumber packet_number = packet->packet_number; | 40 QuicPacketNumber packet_number = packet->packet_number; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 info->has_crypto_handshake = transmission_info->has_crypto_handshake; | 116 info->has_crypto_handshake = transmission_info->has_crypto_handshake; |
| 123 transmission_info->has_crypto_handshake = false; | 117 transmission_info->has_crypto_handshake = false; |
| 124 info->needs_padding = transmission_info->needs_padding; | 118 info->needs_padding = transmission_info->needs_padding; |
| 125 | 119 |
| 126 // Transfer the AckListeners if any are present. | 120 // Transfer the AckListeners if any are present. |
| 127 info->ack_listeners.swap(transmission_info->ack_listeners); | 121 info->ack_listeners.swap(transmission_info->ack_listeners); |
| 128 QUIC_BUG_IF(frames == nullptr) | 122 QUIC_BUG_IF(frames == nullptr) |
| 129 << "Attempt to retransmit packet with no " | 123 << "Attempt to retransmit packet with no " |
| 130 << "retransmittable frames: " << old_packet_number; | 124 << "retransmittable frames: " << old_packet_number; |
| 131 | 125 |
| 132 // Only keep one transmission older than largest observed, because only the | |
| 133 // most recent is expected to possibly be a spurious retransmission. | |
| 134 if (!track_single_retransmission_) { | |
| 135 while (transmission_info->all_transmissions != nullptr && | |
| 136 transmission_info->all_transmissions->size() > 1 && | |
| 137 *(++transmission_info->all_transmissions->begin()) < | |
| 138 largest_observed_) { | |
| 139 QuicPacketNumber old_transmission = | |
| 140 *transmission_info->all_transmissions->begin(); | |
| 141 TransmissionInfo* old_info = | |
| 142 &unacked_packets_[old_transmission - least_unacked_]; | |
| 143 // Don't remove old packets if they're still in flight. | |
| 144 if (old_info->in_flight) { | |
| 145 break; | |
| 146 } | |
| 147 old_info->all_transmissions->pop_front(); | |
| 148 // This will cause the packet be removed in RemoveObsoletePackets. | |
| 149 old_info->all_transmissions = nullptr; | |
| 150 } | |
| 151 } | |
| 152 // Don't link old transmissions to new ones when version or | 126 // Don't link old transmissions to new ones when version or |
| 153 // encryption changes. | 127 // encryption changes. |
| 154 if (transmission_type == ALL_INITIAL_RETRANSMISSION || | 128 if (transmission_type == ALL_INITIAL_RETRANSMISSION || |
| 155 transmission_type == ALL_UNACKED_RETRANSMISSION) { | 129 transmission_type == ALL_UNACKED_RETRANSMISSION) { |
| 156 RemoveAckability(transmission_info); | 130 RemoveAckability(transmission_info); |
| 157 } else { | 131 } else { |
| 158 if (track_single_retransmission_) { | 132 transmission_info->retransmission = new_packet_number; |
| 159 transmission_info->retransmission = new_packet_number; | |
| 160 } else { | |
| 161 if (transmission_info->all_transmissions == nullptr) { | |
| 162 transmission_info->all_transmissions = new PacketNumberList(); | |
| 163 transmission_info->all_transmissions->push_back(old_packet_number); | |
| 164 } | |
| 165 transmission_info->all_transmissions->push_back(new_packet_number); | |
| 166 } | |
| 167 } | |
| 168 if (!track_single_retransmission_) { | |
| 169 info->all_transmissions = transmission_info->all_transmissions; | |
| 170 } | 133 } |
| 171 // Proactively remove obsolete packets so the least unacked can be raised. | 134 // Proactively remove obsolete packets so the least unacked can be raised. |
| 172 RemoveObsoletePackets(); | 135 RemoveObsoletePackets(); |
| 173 } | 136 } |
| 174 | 137 |
| 175 bool QuicUnackedPacketMap::HasRetransmittableFrames( | 138 bool QuicUnackedPacketMap::HasRetransmittableFrames( |
| 176 QuicPacketNumber packet_number) const { | 139 QuicPacketNumber packet_number) const { |
| 177 DCHECK_GE(packet_number, least_unacked_); | 140 DCHECK_GE(packet_number, least_unacked_); |
| 178 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | 141 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); |
| 179 return !unacked_packets_[packet_number - least_unacked_] | 142 return !unacked_packets_[packet_number - least_unacked_] |
| 180 .retransmittable_frames.empty(); | 143 .retransmittable_frames.empty(); |
| 181 } | 144 } |
| 182 | 145 |
| 183 void QuicUnackedPacketMap::NackPacket(QuicPacketNumber packet_number, | 146 void QuicUnackedPacketMap::NackPacket(QuicPacketNumber packet_number, |
| 184 uint16_t min_nacks) { | 147 uint16_t min_nacks) { |
| 185 DCHECK_GE(packet_number, least_unacked_); | 148 DCHECK_GE(packet_number, least_unacked_); |
| 186 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | 149 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); |
| 187 unacked_packets_[packet_number - least_unacked_].nack_count = max( | 150 unacked_packets_[packet_number - least_unacked_].nack_count = max( |
| 188 min_nacks, unacked_packets_[packet_number - least_unacked_].nack_count); | 151 min_nacks, unacked_packets_[packet_number - least_unacked_].nack_count); |
| 189 } | 152 } |
| 190 | 153 |
| 191 void QuicUnackedPacketMap::RemoveRetransmittability(TransmissionInfo* info) { | 154 void QuicUnackedPacketMap::RemoveRetransmittability(TransmissionInfo* info) { |
| 192 if (track_single_retransmission_) { | 155 while (info->retransmission != 0) { |
| 193 while (info->retransmission != 0) { | 156 const QuicPacketNumber retransmission = info->retransmission; |
| 194 const QuicPacketNumber retransmission = info->retransmission; | 157 info->retransmission = 0; |
| 195 info->retransmission = 0; | 158 info = &unacked_packets_[retransmission - least_unacked_]; |
| 196 info = &unacked_packets_[retransmission - least_unacked_]; | |
| 197 } | |
| 198 MaybeRemoveRetransmittableFrames(info); | |
| 199 return; | |
| 200 } | 159 } |
| 201 PacketNumberList* all_transmissions = info->all_transmissions; | 160 MaybeRemoveRetransmittableFrames(info); |
| 202 if (all_transmissions == nullptr) { | |
| 203 MaybeRemoveRetransmittableFrames(info); | |
| 204 return; | |
| 205 } | |
| 206 // TODO(ianswett): Consider adding a check to ensure there are retransmittable | |
| 207 // frames associated with this packet. | |
| 208 for (QuicPacketNumber packet_number : *all_transmissions) { | |
| 209 TransmissionInfo* transmission_info = | |
| 210 &unacked_packets_[packet_number - least_unacked_]; | |
| 211 MaybeRemoveRetransmittableFrames(transmission_info); | |
| 212 transmission_info->all_transmissions = nullptr; | |
| 213 } | |
| 214 delete all_transmissions; | |
| 215 } | 161 } |
| 216 | 162 |
| 217 void QuicUnackedPacketMap::RemoveRetransmittability( | 163 void QuicUnackedPacketMap::RemoveRetransmittability( |
| 218 QuicPacketNumber packet_number) { | 164 QuicPacketNumber packet_number) { |
| 219 DCHECK_GE(packet_number, least_unacked_); | 165 DCHECK_GE(packet_number, least_unacked_); |
| 220 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); | 166 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); |
| 221 TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_]; | 167 TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_]; |
| 222 RemoveRetransmittability(info); | 168 RemoveRetransmittability(info); |
| 223 } | 169 } |
| 224 | 170 |
| 225 void QuicUnackedPacketMap::RemoveAckability(TransmissionInfo* info) { | 171 void QuicUnackedPacketMap::RemoveAckability(TransmissionInfo* info) { |
| 226 DCHECK(info->retransmittable_frames.empty()); | 172 DCHECK(info->retransmittable_frames.empty()); |
| 173 DCHECK_EQ(0u, info->retransmission); |
| 227 info->is_unackable = true; | 174 info->is_unackable = true; |
| 228 if (track_single_retransmission_) { | |
| 229 DCHECK_EQ(0u, info->retransmission); | |
| 230 return; | |
| 231 } | |
| 232 PacketNumberList* all_transmissions = info->all_transmissions; | |
| 233 if (all_transmissions == nullptr) { | |
| 234 return; | |
| 235 } | |
| 236 for (QuicPacketNumber packet_number : *all_transmissions) { | |
| 237 TransmissionInfo* transmission_info = | |
| 238 &unacked_packets_[packet_number - least_unacked_]; | |
| 239 transmission_info->all_transmissions = nullptr; | |
| 240 transmission_info->is_unackable = true; | |
| 241 } | |
| 242 delete all_transmissions; | |
| 243 } | 175 } |
| 244 | 176 |
| 245 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( | 177 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( |
| 246 TransmissionInfo* transmission_info) { | 178 TransmissionInfo* transmission_info) { |
| 247 if (transmission_info->has_crypto_handshake) { | 179 if (transmission_info->has_crypto_handshake) { |
| 248 DCHECK(!transmission_info->retransmittable_frames.empty()); | 180 DCHECK(!transmission_info->retransmittable_frames.empty()); |
| 249 DCHECK_LT(0u, pending_crypto_packet_count_); | 181 DCHECK_LT(0u, pending_crypto_packet_count_); |
| 250 --pending_crypto_packet_count_; | 182 --pending_crypto_packet_count_; |
| 251 transmission_info->has_crypto_handshake = false; | 183 transmission_info->has_crypto_handshake = false; |
| 252 } | 184 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 271 const TransmissionInfo& info) const { | 203 const TransmissionInfo& info) const { |
| 272 // Packet contributes to congestion control if it is considered inflight. | 204 // Packet contributes to congestion control if it is considered inflight. |
| 273 return info.in_flight; | 205 return info.in_flight; |
| 274 } | 206 } |
| 275 | 207 |
| 276 bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData( | 208 bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData( |
| 277 const TransmissionInfo& info) const { | 209 const TransmissionInfo& info) const { |
| 278 // Packet may have retransmittable frames, or the data may have been | 210 // Packet may have retransmittable frames, or the data may have been |
| 279 // retransmitted with a new packet number. | 211 // retransmitted with a new packet number. |
| 280 return !info.retransmittable_frames.empty() || | 212 return !info.retransmittable_frames.empty() || |
| 281 info.all_transmissions != nullptr || | |
| 282 // Allow for an extra 1 RTT before stopping to track old packets. | 213 // Allow for an extra 1 RTT before stopping to track old packets. |
| 283 info.retransmission > largest_observed_; | 214 info.retransmission > largest_observed_; |
| 284 } | 215 } |
| 285 | 216 |
| 286 bool QuicUnackedPacketMap::IsPacketUseless(QuicPacketNumber packet_number, | 217 bool QuicUnackedPacketMap::IsPacketUseless(QuicPacketNumber packet_number, |
| 287 const TransmissionInfo& info) const { | 218 const TransmissionInfo& info) const { |
| 288 return !IsPacketUsefulForMeasuringRtt(packet_number, info) && | 219 return !IsPacketUsefulForMeasuringRtt(packet_number, info) && |
| 289 !IsPacketUsefulForCongestionControl(info) && | 220 !IsPacketUsefulForCongestionControl(info) && |
| 290 !IsPacketUsefulForRetransmittableData(info); | 221 !IsPacketUsefulForRetransmittableData(info); |
| 291 } | 222 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 } | 352 } |
| 422 } | 353 } |
| 423 return false; | 354 return false; |
| 424 } | 355 } |
| 425 | 356 |
| 426 QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const { | 357 QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const { |
| 427 return least_unacked_; | 358 return least_unacked_; |
| 428 } | 359 } |
| 429 | 360 |
| 430 } // namespace net | 361 } // namespace net |
| OLD | NEW |