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_sent_packet_manager.h" | 5 #include "net/quic/quic_sent_packet_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 // values less than or equal to 0. | 25 // values less than or equal to 0. |
26 int32 FLAGS_quic_recent_min_rtt_window_s = 60; | 26 int32 FLAGS_quic_recent_min_rtt_window_s = 60; |
27 | 27 |
28 namespace { | 28 namespace { |
29 static const int64 kDefaultRetransmissionTimeMs = 500; | 29 static const int64 kDefaultRetransmissionTimeMs = 500; |
30 // TCP RFC calls for 1 second RTO however Linux differs from this default and | 30 // TCP RFC calls for 1 second RTO however Linux differs from this default and |
31 // define the minimum RTO to 200ms, we will use the same until we have data to | 31 // define the minimum RTO to 200ms, we will use the same until we have data to |
32 // support a higher or lower value. | 32 // support a higher or lower value. |
33 static const int64 kMinRetransmissionTimeMs = 200; | 33 static const int64 kMinRetransmissionTimeMs = 200; |
34 static const int64 kMaxRetransmissionTimeMs = 60000; | 34 static const int64 kMaxRetransmissionTimeMs = 60000; |
| 35 // Maximum number of exponential backoffs used for RTO timeouts. |
35 static const size_t kMaxRetransmissions = 10; | 36 static const size_t kMaxRetransmissions = 10; |
| 37 // Maximum number of packets retransmitted upon an RTO. |
| 38 static const size_t kMaxRetransmissionsOnTimeout = 2; |
36 | 39 |
37 // Ensure the handshake timer isnt't faster than 10ms. | 40 // Ensure the handshake timer isnt't faster than 10ms. |
38 // This limits the tenth retransmitted packet to 10s after the initial CHLO. | 41 // This limits the tenth retransmitted packet to 10s after the initial CHLO. |
39 static const int64 kMinHandshakeTimeoutMs = 10; | 42 static const int64 kMinHandshakeTimeoutMs = 10; |
40 | 43 |
41 // Sends up to two tail loss probes before firing an RTO, | 44 // Sends up to two tail loss probes before firing an RTO, |
42 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. | 45 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. |
43 static const size_t kDefaultMaxTailLossProbes = 2; | 46 static const size_t kDefaultMaxTailLossProbes = 2; |
44 static const int64 kMinTailLossProbeTimeoutMs = 10; | 47 static const int64 kMinTailLossProbeTimeoutMs = 10; |
45 | 48 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 | 228 |
226 // If we have received a truncated ack, then we need to clear out some | 229 // If we have received a truncated ack, then we need to clear out some |
227 // previous transmissions to allow the peer to actually ACK new packets. | 230 // previous transmissions to allow the peer to actually ACK new packets. |
228 if (ack_frame.is_truncated) { | 231 if (ack_frame.is_truncated) { |
229 unacked_packets_.ClearAllPreviousRetransmissions(); | 232 unacked_packets_.ClearAllPreviousRetransmissions(); |
230 } | 233 } |
231 | 234 |
232 // Anytime we are making forward progress and have a new RTT estimate, reset | 235 // Anytime we are making forward progress and have a new RTT estimate, reset |
233 // the backoff counters. | 236 // the backoff counters. |
234 if (rtt_updated) { | 237 if (rtt_updated) { |
| 238 // If the ack acknowledges data sent prior to the RTO,the RTO was spurious. |
| 239 if (FLAGS_quic_use_new_rto && consecutive_rto_count_ > 0 && |
| 240 ack_frame.largest_observed >= first_rto_transmission_) { |
| 241 send_algorithm_->OnRetransmissionTimeout(true); |
| 242 } |
235 // Reset all retransmit counters any time a new packet is acked. | 243 // Reset all retransmit counters any time a new packet is acked. |
236 consecutive_rto_count_ = 0; | 244 consecutive_rto_count_ = 0; |
237 consecutive_tlp_count_ = 0; | 245 consecutive_tlp_count_ = 0; |
238 consecutive_crypto_retransmission_count_ = 0; | 246 consecutive_crypto_retransmission_count_ = 0; |
239 } | 247 } |
240 | 248 |
241 if (debug_delegate_ != nullptr) { | 249 if (debug_delegate_ != nullptr) { |
242 debug_delegate_->OnIncomingAck(ack_frame, ack_receive_time, | 250 debug_delegate_->OnIncomingAck(ack_frame, ack_receive_time, |
243 unacked_packets_.largest_observed(), | 251 unacked_packets_.largest_observed(), |
244 rtt_updated, GetLeastUnacked()); | 252 rtt_updated, GetLeastUnacked()); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 } | 366 } |
359 } | 367 } |
360 } | 368 } |
361 | 369 |
362 void QuicSentPacketManager::MarkForRetransmission( | 370 void QuicSentPacketManager::MarkForRetransmission( |
363 QuicPacketSequenceNumber sequence_number, | 371 QuicPacketSequenceNumber sequence_number, |
364 TransmissionType transmission_type) { | 372 TransmissionType transmission_type) { |
365 const TransmissionInfo& transmission_info = | 373 const TransmissionInfo& transmission_info = |
366 unacked_packets_.GetTransmissionInfo(sequence_number); | 374 unacked_packets_.GetTransmissionInfo(sequence_number); |
367 LOG_IF(DFATAL, transmission_info.retransmittable_frames == nullptr); | 375 LOG_IF(DFATAL, transmission_info.retransmittable_frames == nullptr); |
368 if (transmission_type != TLP_RETRANSMISSION) { | 376 // Both TLP and the new RTO leave the packets in flight and let the loss |
| 377 // detection decide if packets are lost. |
| 378 if (transmission_type != TLP_RETRANSMISSION && |
| 379 (!FLAGS_quic_use_new_rto || transmission_type != RTO_RETRANSMISSION)) { |
369 unacked_packets_.RemoveFromInFlight(sequence_number); | 380 unacked_packets_.RemoveFromInFlight(sequence_number); |
370 } | 381 } |
371 // TODO(ianswett): Currently the RTO can fire while there are pending NACK | 382 // TODO(ianswett): Currently the RTO can fire while there are pending NACK |
372 // retransmissions for the same data, which is not ideal. | 383 // retransmissions for the same data, which is not ideal. |
373 if (ContainsKey(pending_retransmissions_, sequence_number)) { | 384 if (ContainsKey(pending_retransmissions_, sequence_number)) { |
374 return; | 385 return; |
375 } | 386 } |
376 | 387 |
377 pending_retransmissions_[sequence_number] = transmission_type; | 388 pending_retransmissions_[sequence_number] = transmission_type; |
378 } | 389 } |
379 | 390 |
380 void QuicSentPacketManager::RecordSpuriousRetransmissions( | 391 void QuicSentPacketManager::RecordSpuriousRetransmissions( |
381 const SequenceNumberList& all_transmissions, | 392 const SequenceNumberList& all_transmissions, |
382 QuicPacketSequenceNumber acked_sequence_number) { | 393 QuicPacketSequenceNumber acked_sequence_number) { |
383 if (acked_sequence_number < first_rto_transmission_) { | 394 if (!FLAGS_quic_use_new_rto && |
| 395 acked_sequence_number < first_rto_transmission_) { |
384 // Cancel all pending RTO transmissions and restore their in flight status. | 396 // Cancel all pending RTO transmissions and restore their in flight status. |
385 // Replace SRTT with latest_rtt and increase the variance to prevent | 397 // Replace SRTT with latest_rtt and increase the variance to prevent |
386 // a spurious RTO from happening again. | 398 // a spurious RTO from happening again. |
387 rtt_stats_.ExpireSmoothedMetrics(); | 399 rtt_stats_.ExpireSmoothedMetrics(); |
388 for (PendingRetransmissionMap::const_iterator it = | 400 for (PendingRetransmissionMap::const_iterator it = |
389 pending_retransmissions_.begin(); | 401 pending_retransmissions_.begin(); |
390 it != pending_retransmissions_.end(); ++it) { | 402 it != pending_retransmissions_.end(); ++it) { |
391 DCHECK_EQ(it->second, RTO_RETRANSMISSION); | 403 DCHECK_EQ(it->second, RTO_RETRANSMISSION); |
392 unacked_packets_.RestoreInFlight(it->first); | 404 unacked_packets_.RestoreInFlight(it->first); |
393 } | 405 } |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 // If no tail loss probe can be sent, because there are no retransmittable | 628 // If no tail loss probe can be sent, because there are no retransmittable |
617 // packets, execute a conventional RTO to abandon old packets. | 629 // packets, execute a conventional RTO to abandon old packets. |
618 ++stats_->tlp_count; | 630 ++stats_->tlp_count; |
619 ++consecutive_tlp_count_; | 631 ++consecutive_tlp_count_; |
620 pending_timer_transmission_count_ = 1; | 632 pending_timer_transmission_count_ = 1; |
621 // TLPs prefer sending new data instead of retransmitting data, so | 633 // TLPs prefer sending new data instead of retransmitting data, so |
622 // give the connection a chance to write before completing the TLP. | 634 // give the connection a chance to write before completing the TLP. |
623 return; | 635 return; |
624 case RTO_MODE: | 636 case RTO_MODE: |
625 ++stats_->rto_count; | 637 ++stats_->rto_count; |
626 RetransmitAllPackets(); | 638 if (FLAGS_quic_use_new_rto) { |
| 639 RetransmitRtoPackets(); |
| 640 } else { |
| 641 RetransmitAllPackets(); |
| 642 } |
627 return; | 643 return; |
628 } | 644 } |
629 } | 645 } |
630 | 646 |
631 void QuicSentPacketManager::RetransmitCryptoPackets() { | 647 void QuicSentPacketManager::RetransmitCryptoPackets() { |
632 DCHECK_EQ(HANDSHAKE_MODE, GetRetransmissionMode()); | 648 DCHECK_EQ(HANDSHAKE_MODE, GetRetransmissionMode()); |
633 ++consecutive_crypto_retransmission_count_; | 649 ++consecutive_crypto_retransmission_count_; |
634 bool packet_retransmitted = false; | 650 bool packet_retransmitted = false; |
635 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); | 651 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); |
636 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); | 652 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
(...skipping 25 matching lines...) Expand all Loading... |
662 DCHECK_NE(IS_HANDSHAKE, it->retransmittable_frames->HasCryptoHandshake()); | 678 DCHECK_NE(IS_HANDSHAKE, it->retransmittable_frames->HasCryptoHandshake()); |
663 } | 679 } |
664 MarkForRetransmission(sequence_number, TLP_RETRANSMISSION); | 680 MarkForRetransmission(sequence_number, TLP_RETRANSMISSION); |
665 return true; | 681 return true; |
666 } | 682 } |
667 DLOG(FATAL) | 683 DLOG(FATAL) |
668 << "No retransmittable packets, so RetransmitOldestPacket failed."; | 684 << "No retransmittable packets, so RetransmitOldestPacket failed."; |
669 return false; | 685 return false; |
670 } | 686 } |
671 | 687 |
| 688 void QuicSentPacketManager::RetransmitRtoPackets() { |
| 689 LOG_IF(DFATAL, pending_timer_transmission_count_ > 0) |
| 690 << "Retransmissions already queued:" << pending_timer_transmission_count_; |
| 691 // Mark two packets for retransmission. |
| 692 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); |
| 693 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
| 694 it != unacked_packets_.end(); ++it, ++sequence_number) { |
| 695 if (it->retransmittable_frames != nullptr && |
| 696 pending_timer_transmission_count_ < kMaxRetransmissionsOnTimeout) { |
| 697 MarkForRetransmission(sequence_number, RTO_RETRANSMISSION); |
| 698 ++pending_timer_transmission_count_; |
| 699 } |
| 700 // Abandon non-retransmittable data that's in flight to ensure it doesn't |
| 701 // fill up the congestion window. |
| 702 if (it->retransmittable_frames == nullptr && it->in_flight && |
| 703 it->all_transmissions == nullptr) { |
| 704 unacked_packets_.RemoveFromInFlight(sequence_number); |
| 705 } |
| 706 } |
| 707 if (pending_timer_transmission_count_ > 0) { |
| 708 if (consecutive_rto_count_ == 0) { |
| 709 first_rto_transmission_ = unacked_packets_.largest_sent_packet() + 1; |
| 710 } |
| 711 ++consecutive_rto_count_; |
| 712 } |
| 713 } |
| 714 |
672 void QuicSentPacketManager::RetransmitAllPackets() { | 715 void QuicSentPacketManager::RetransmitAllPackets() { |
673 DVLOG(1) << "RetransmitAllPackets() called with " | 716 DVLOG(1) << "RetransmitAllPackets() called with " |
674 << unacked_packets_.GetNumUnackedPacketsDebugOnly() | 717 << unacked_packets_.GetNumUnackedPacketsDebugOnly() |
675 << " unacked packets."; | 718 << " unacked packets."; |
676 // Request retransmission of all retransmittable packets when the RTO | 719 // Request retransmission of all retransmittable packets when the RTO |
677 // fires, and let the congestion manager decide how many to send | 720 // fires, and let the congestion manager decide how many to send |
678 // immediately and the remaining packets will be queued. | 721 // immediately and the remaining packets will be queued. |
679 // Abandon any non-retransmittable packets that are sufficiently old. | 722 // Abandon any non-retransmittable packets that are sufficiently old. |
680 bool packets_retransmitted = false; | 723 bool packets_retransmitted = false; |
681 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); | 724 QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked(); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 // Set up a pacing sender with a 1 millisecond alarm granularity, the same as | 1002 // Set up a pacing sender with a 1 millisecond alarm granularity, the same as |
960 // the default granularity of the Linux kernel's FQ qdisc. | 1003 // the default granularity of the Linux kernel's FQ qdisc. |
961 using_pacing_ = true; | 1004 using_pacing_ = true; |
962 send_algorithm_.reset( | 1005 send_algorithm_.reset( |
963 new PacingSender(send_algorithm_.release(), | 1006 new PacingSender(send_algorithm_.release(), |
964 QuicTime::Delta::FromMilliseconds(1), | 1007 QuicTime::Delta::FromMilliseconds(1), |
965 kInitialUnpacedBurst)); | 1008 kInitialUnpacedBurst)); |
966 } | 1009 } |
967 | 1010 |
968 } // namespace net | 1011 } // namespace net |
OLD | NEW |