| 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "net/quic/congestion_control/pacing_sender.h" | 9 #include "net/quic/congestion_control/pacing_sender.h" |
| 10 #include "net/quic/crypto/crypto_protocol.h" | 10 #include "net/quic/crypto/crypto_protocol.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 namespace net { | 34 namespace net { |
| 35 namespace { | 35 namespace { |
| 36 static const int kDefaultRetransmissionTimeMs = 500; | 36 static const int kDefaultRetransmissionTimeMs = 500; |
| 37 // TCP RFC calls for 1 second RTO however Linux differs from this default and | 37 // TCP RFC calls for 1 second RTO however Linux differs from this default and |
| 38 // define the minimum RTO to 200ms, we will use the same until we have data to | 38 // define the minimum RTO to 200ms, we will use the same until we have data to |
| 39 // support a higher or lower value. | 39 // support a higher or lower value. |
| 40 static const int kMinRetransmissionTimeMs = 200; | 40 static const int kMinRetransmissionTimeMs = 200; |
| 41 static const int kMaxRetransmissionTimeMs = 60000; | 41 static const int kMaxRetransmissionTimeMs = 60000; |
| 42 static const size_t kMaxRetransmissions = 10; | 42 static const size_t kMaxRetransmissions = 10; |
| 43 | 43 |
| 44 // TCP retransmits after 3 nacks. | |
| 45 static const size_t kNumberOfNacksBeforeRetransmission = 3; | |
| 46 | |
| 47 // Only exponentially back off the handshake timer 5 times due to a timeout. | 44 // Only exponentially back off the handshake timer 5 times due to a timeout. |
| 48 static const size_t kMaxHandshakeRetransmissionBackoffs = 5; | 45 static const size_t kMaxHandshakeRetransmissionBackoffs = 5; |
| 49 static const size_t kMinHandshakeTimeoutMs = 10; | 46 static const size_t kMinHandshakeTimeoutMs = 10; |
| 50 | 47 |
| 51 // Sends up to two tail loss probes before firing an RTO, | 48 // Sends up to two tail loss probes before firing an RTO, |
| 52 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. | 49 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. |
| 53 static const size_t kDefaultMaxTailLossProbes = 2; | 50 static const size_t kDefaultMaxTailLossProbes = 2; |
| 54 static const int64 kMinTailLossProbeTimeoutMs = 10; | 51 static const int64 kMinTailLossProbeTimeoutMs = 10; |
| 55 | 52 |
| 56 bool HasCryptoHandshake( | 53 bool HasCryptoHandshake( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 68 | 65 |
| 69 QuicSentPacketManager::QuicSentPacketManager(bool is_server, | 66 QuicSentPacketManager::QuicSentPacketManager(bool is_server, |
| 70 const QuicClock* clock, | 67 const QuicClock* clock, |
| 71 QuicConnectionStats* stats, | 68 QuicConnectionStats* stats, |
| 72 CongestionFeedbackType type) | 69 CongestionFeedbackType type) |
| 73 : unacked_packets_(is_server), | 70 : unacked_packets_(is_server), |
| 74 is_server_(is_server), | 71 is_server_(is_server), |
| 75 clock_(clock), | 72 clock_(clock), |
| 76 stats_(stats), | 73 stats_(stats), |
| 77 send_algorithm_(SendAlgorithmInterface::Create(clock, type)), | 74 send_algorithm_(SendAlgorithmInterface::Create(clock, type)), |
| 75 loss_algorithm_(LossDetectionInterface::Create()), |
| 78 rtt_sample_(QuicTime::Delta::Infinite()), | 76 rtt_sample_(QuicTime::Delta::Infinite()), |
| 77 largest_observed_(0), |
| 79 pending_crypto_packet_count_(0), | 78 pending_crypto_packet_count_(0), |
| 80 consecutive_rto_count_(0), | 79 consecutive_rto_count_(0), |
| 81 consecutive_tlp_count_(0), | 80 consecutive_tlp_count_(0), |
| 82 consecutive_crypto_retransmission_count_(0), | 81 consecutive_crypto_retransmission_count_(0), |
| 83 max_tail_loss_probes_(kDefaultMaxTailLossProbes), | 82 max_tail_loss_probes_(kDefaultMaxTailLossProbes), |
| 84 using_pacing_(false) { | 83 using_pacing_(false) { |
| 85 } | 84 } |
| 86 | 85 |
| 87 QuicSentPacketManager::~QuicSentPacketManager() { | 86 QuicSentPacketManager::~QuicSentPacketManager() { |
| 88 } | 87 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 unacked_packets_.OnRetransmittedPacket(old_sequence_number, | 133 unacked_packets_.OnRetransmittedPacket(old_sequence_number, |
| 135 new_sequence_number); | 134 new_sequence_number); |
| 136 } | 135 } |
| 137 | 136 |
| 138 bool QuicSentPacketManager::OnIncomingAck( | 137 bool QuicSentPacketManager::OnIncomingAck( |
| 139 const ReceivedPacketInfo& received_info, QuicTime ack_receive_time) { | 138 const ReceivedPacketInfo& received_info, QuicTime ack_receive_time) { |
| 140 // We rely on delta_time_largest_observed to compute an RTT estimate, so | 139 // We rely on delta_time_largest_observed to compute an RTT estimate, so |
| 141 // we only update rtt when the largest observed gets acked. | 140 // we only update rtt when the largest observed gets acked. |
| 142 bool largest_observed_acked = | 141 bool largest_observed_acked = |
| 143 unacked_packets_.IsUnacked(received_info.largest_observed); | 142 unacked_packets_.IsUnacked(received_info.largest_observed); |
| 143 largest_observed_ = received_info.largest_observed; |
| 144 MaybeUpdateRTT(received_info, ack_receive_time); | 144 MaybeUpdateRTT(received_info, ack_receive_time); |
| 145 HandleAckForSentPackets(received_info); | 145 HandleAckForSentPackets(received_info); |
| 146 MaybeRetransmitOnAckFrame(received_info, ack_receive_time); | 146 MaybeRetransmitOnAckFrame(received_info, ack_receive_time); |
| 147 | 147 |
| 148 // Anytime we are making forward progress and have a new RTT estimate, reset | 148 // Anytime we are making forward progress and have a new RTT estimate, reset |
| 149 // the backoff counters. | 149 // the backoff counters. |
| 150 if (largest_observed_acked) { | 150 if (largest_observed_acked) { |
| 151 // Reset all retransmit counters any time a new packet is acked. | 151 // Reset all retransmit counters any time a new packet is acked. |
| 152 consecutive_rto_count_ = 0; | 152 consecutive_rto_count_ = 0; |
| 153 consecutive_tlp_count_ = 0; | 153 consecutive_tlp_count_ = 0; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 send_algorithm_->OnPacketAcked(sequence_number, | 298 send_algorithm_->OnPacketAcked(sequence_number, |
| 299 transmission_info.bytes_sent); | 299 transmission_info.bytes_sent); |
| 300 } else { | 300 } else { |
| 301 // It's been abandoned. | 301 // It's been abandoned. |
| 302 send_algorithm_->OnPacketAbandoned(sequence_number, | 302 send_algorithm_->OnPacketAbandoned(sequence_number, |
| 303 transmission_info.bytes_sent); | 303 transmission_info.bytes_sent); |
| 304 } | 304 } |
| 305 unacked_packets_.SetNotPending(sequence_number); | 305 unacked_packets_.SetNotPending(sequence_number); |
| 306 } | 306 } |
| 307 | 307 |
| 308 | |
| 309 SequenceNumberSet all_transmissions = *transmission_info.all_transmissions; | 308 SequenceNumberSet all_transmissions = *transmission_info.all_transmissions; |
| 310 SequenceNumberSet::reverse_iterator all_transmissions_it = | 309 SequenceNumberSet::reverse_iterator all_transmissions_it = |
| 311 all_transmissions.rbegin(); | 310 all_transmissions.rbegin(); |
| 312 QuicPacketSequenceNumber newest_transmission = *all_transmissions_it; | 311 QuicPacketSequenceNumber newest_transmission = *all_transmissions_it; |
| 313 if (newest_transmission != sequence_number) { | 312 if (newest_transmission != sequence_number) { |
| 314 ++stats_->packets_spuriously_retransmitted; | 313 ++stats_->packets_spuriously_retransmitted; |
| 315 } | 314 } |
| 316 | 315 |
| 317 bool has_cryto_handshake = HasCryptoHandshake( | 316 bool has_cryto_handshake = HasCryptoHandshake( |
| 318 unacked_packets_.GetTransmissionInfo(newest_transmission)); | 317 unacked_packets_.GetTransmissionInfo(newest_transmission)); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 void QuicSentPacketManager::OnIncomingQuicCongestionFeedbackFrame( | 520 void QuicSentPacketManager::OnIncomingQuicCongestionFeedbackFrame( |
| 522 const QuicCongestionFeedbackFrame& frame, | 521 const QuicCongestionFeedbackFrame& frame, |
| 523 const QuicTime& feedback_receive_time) { | 522 const QuicTime& feedback_receive_time) { |
| 524 send_algorithm_->OnIncomingQuicCongestionFeedbackFrame( | 523 send_algorithm_->OnIncomingQuicCongestionFeedbackFrame( |
| 525 frame, feedback_receive_time); | 524 frame, feedback_receive_time); |
| 526 } | 525 } |
| 527 | 526 |
| 528 void QuicSentPacketManager::MaybeRetransmitOnAckFrame( | 527 void QuicSentPacketManager::MaybeRetransmitOnAckFrame( |
| 529 const ReceivedPacketInfo& received_info, | 528 const ReceivedPacketInfo& received_info, |
| 530 const QuicTime& ack_receive_time) { | 529 const QuicTime& ack_receive_time) { |
| 531 // Go through all pending packets up to the largest observed and see if any | 530 // Go through all pending packets up to the largest observed and count nacks. |
| 532 // need to be retransmitted or lost. | |
| 533 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); | 531 for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
| 534 it != unacked_packets_.end() && | 532 it != unacked_packets_.end() && |
| 535 it->first <= received_info.largest_observed; ++it) { | 533 it->first <= received_info.largest_observed; ++it) { |
| 536 if (!it->second.pending) { | 534 if (!it->second.pending) { |
| 537 continue; | 535 continue; |
| 538 } | 536 } |
| 539 QuicPacketSequenceNumber sequence_number = it->first; | 537 QuicPacketSequenceNumber sequence_number = it->first; |
| 540 DVLOG(1) << "still missing packet " << sequence_number; | 538 DVLOG(1) << "still missing packet " << sequence_number; |
| 541 // Acks must be handled previously, so ensure it's missing and not acked. | 539 // Acks must be handled previously, so ensure it's missing and not acked. |
| 542 DCHECK(IsAwaitingPacket(received_info, sequence_number)); | 540 DCHECK(IsAwaitingPacket(received_info, sequence_number)); |
| 543 | 541 |
| 544 // Consider it multiple nacks when there is a gap between the missing packet | 542 // Consider it multiple nacks when there is a gap between the missing packet |
| 545 // and the largest observed, since the purpose of a nack threshold is to | 543 // and the largest observed, since the purpose of a nack threshold is to |
| 546 // tolerate re-ordering. This handles both StretchAcks and Forward Acks. | 544 // tolerate re-ordering. This handles both StretchAcks and Forward Acks. |
| 547 // TODO(ianswett): This relies heavily on sequential reception of packets, | |
| 548 // and makes an assumption that the congestion control uses TCP style nacks. | |
| 549 size_t min_nacks = received_info.largest_observed - sequence_number; | 545 size_t min_nacks = received_info.largest_observed - sequence_number; |
| 550 unacked_packets_.NackPacket(sequence_number, min_nacks); | 546 unacked_packets_.NackPacket(sequence_number, min_nacks); |
| 551 } | 547 } |
| 552 | 548 |
| 549 InvokeLossDetection(ack_receive_time); |
| 550 } |
| 551 |
| 552 void QuicSentPacketManager::InvokeLossDetection(QuicTime time) { |
| 553 SequenceNumberSet lost_packets = | 553 SequenceNumberSet lost_packets = |
| 554 DetectLostPackets(unacked_packets_, | 554 loss_algorithm_->DetectLostPackets(unacked_packets_, |
| 555 ack_receive_time, | 555 time, |
| 556 received_info.largest_observed); | 556 largest_observed_, |
| 557 send_algorithm_->SmoothedRtt()); |
| 557 for (SequenceNumberSet::const_iterator it = lost_packets.begin(); | 558 for (SequenceNumberSet::const_iterator it = lost_packets.begin(); |
| 558 it != lost_packets.end(); ++it) { | 559 it != lost_packets.end(); ++it) { |
| 559 QuicPacketSequenceNumber sequence_number = *it; | 560 QuicPacketSequenceNumber sequence_number = *it; |
| 560 // TODO(ianswett): If it's expected the FEC packet may repair the loss, it | 561 // TODO(ianswett): If it's expected the FEC packet may repair the loss, it |
| 561 // should be recorded as a loss to the send algorithm, but not retransmitted | 562 // should be recorded as a loss to the send algorithm, but not retransmitted |
| 562 // until it's known whether the FEC packet arrived. | 563 // until it's known whether the FEC packet arrived. |
| 563 ++stats_->packets_lost; | 564 ++stats_->packets_lost; |
| 564 send_algorithm_->OnPacketLost(sequence_number, ack_receive_time); | 565 send_algorithm_->OnPacketLost(sequence_number, time); |
| 565 OnPacketAbandoned(sequence_number); | 566 OnPacketAbandoned(sequence_number); |
| 566 | 567 |
| 567 if (unacked_packets_.HasRetransmittableFrames(sequence_number)) { | 568 if (unacked_packets_.HasRetransmittableFrames(sequence_number)) { |
| 568 MarkForRetransmission(sequence_number, NACK_RETRANSMISSION); | 569 MarkForRetransmission(sequence_number, NACK_RETRANSMISSION); |
| 569 } else { | 570 } else { |
| 570 // Since we will not retransmit this, we need to remove it from | 571 // Since we will not retransmit this, we need to remove it from |
| 571 // unacked_packets_. This is either the current transmission of | 572 // unacked_packets_. This is either the current transmission of |
| 572 // a packet whose previous transmission has been acked, or it | 573 // a packet whose previous transmission has been acked, or it |
| 573 // is a packet that has been TLP retransmitted. | 574 // is a packet that has been TLP retransmitted. |
| 574 unacked_packets_.RemovePacket(sequence_number); | 575 unacked_packets_.RemovePacket(sequence_number); |
| 575 } | 576 } |
| 576 } | 577 } |
| 577 } | 578 } |
| 578 | 579 |
| 579 // static | |
| 580 SequenceNumberSet QuicSentPacketManager::DetectLostPackets( | |
| 581 const QuicUnackedPacketMap& unacked_packets, | |
| 582 const QuicTime& time, | |
| 583 QuicPacketSequenceNumber largest_observed) { | |
| 584 SequenceNumberSet lost_packets; | |
| 585 | |
| 586 for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin(); | |
| 587 it != unacked_packets.end() && it->first <= largest_observed; ++it) { | |
| 588 if (!it->second.pending) { | |
| 589 continue; | |
| 590 } | |
| 591 size_t num_nacks_needed = kNumberOfNacksBeforeRetransmission; | |
| 592 // Check for early retransmit(RFC5827) when the last packet gets acked and | |
| 593 // the there are fewer than 4 pending packets. | |
| 594 // TODO(ianswett): Set a retransmission timer instead of losing the packet | |
| 595 // and retransmitting immediately. Also consider only invoking OnPacketLost | |
| 596 // and OnPacketAbandoned when they're actually retransmitted in case they | |
| 597 // arrive while queued for retransmission. | |
| 598 if (it->second.retransmittable_frames && | |
| 599 unacked_packets.largest_sent_packet() == largest_observed) { | |
| 600 num_nacks_needed = largest_observed - it->first; | |
| 601 } | |
| 602 | |
| 603 if (it->second.nack_count < num_nacks_needed) { | |
| 604 continue; | |
| 605 } | |
| 606 | |
| 607 lost_packets.insert(it->first); | |
| 608 } | |
| 609 | |
| 610 return lost_packets; | |
| 611 } | |
| 612 | |
| 613 void QuicSentPacketManager::MaybeUpdateRTT( | 580 void QuicSentPacketManager::MaybeUpdateRTT( |
| 614 const ReceivedPacketInfo& received_info, | 581 const ReceivedPacketInfo& received_info, |
| 615 const QuicTime& ack_receive_time) { | 582 const QuicTime& ack_receive_time) { |
| 616 if (!unacked_packets_.IsUnacked(received_info.largest_observed)) { | 583 if (!unacked_packets_.IsUnacked(received_info.largest_observed)) { |
| 617 return; | 584 return; |
| 618 } | 585 } |
| 619 // We calculate the RTT based on the highest ACKed sequence number, the lower | 586 // We calculate the RTT based on the highest ACKed sequence number, the lower |
| 620 // sequence numbers will include the ACK aggregation delay. | 587 // sequence numbers will include the ACK aggregation delay. |
| 621 const QuicUnackedPacketMap::TransmissionInfo& transmission_info = | 588 const QuicUnackedPacketMap::TransmissionInfo& transmission_info = |
| 622 unacked_packets_.GetTransmissionInfo(received_info.largest_observed); | 589 unacked_packets_.GetTransmissionInfo(received_info.largest_observed); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 return; | 731 return; |
| 765 } | 732 } |
| 766 | 733 |
| 767 using_pacing_ = true; | 734 using_pacing_ = true; |
| 768 send_algorithm_.reset( | 735 send_algorithm_.reset( |
| 769 new PacingSender(send_algorithm_.release(), | 736 new PacingSender(send_algorithm_.release(), |
| 770 QuicTime::Delta::FromMicroseconds(1))); | 737 QuicTime::Delta::FromMicroseconds(1))); |
| 771 } | 738 } |
| 772 | 739 |
| 773 } // namespace net | 740 } // namespace net |
| OLD | NEW |