| Index: net/quic/quic_sent_packet_manager.cc
|
| diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
|
| index f2c514b4bcc0b09891ab4413d256e9ac9279be26..20256cfcaecaffd6812bbc36cdfc34f94eddc0c5 100644
|
| --- a/net/quic/quic_sent_packet_manager.cc
|
| +++ b/net/quic/quic_sent_packet_manager.cc
|
| @@ -32,7 +32,10 @@ static const int64 kDefaultRetransmissionTimeMs = 500;
|
| // support a higher or lower value.
|
| static const int64 kMinRetransmissionTimeMs = 200;
|
| static const int64 kMaxRetransmissionTimeMs = 60000;
|
| +// Maximum number of exponential backoffs used for RTO timeouts.
|
| static const size_t kMaxRetransmissions = 10;
|
| +// Maximum number of packets retransmitted upon an RTO.
|
| +static const size_t kMaxRetransmissionsOnTimeout = 2;
|
|
|
| // Ensure the handshake timer isnt't faster than 10ms.
|
| // This limits the tenth retransmitted packet to 10s after the initial CHLO.
|
| @@ -232,6 +235,17 @@ void QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
|
| // Anytime we are making forward progress and have a new RTT estimate, reset
|
| // the backoff counters.
|
| if (rtt_updated) {
|
| + if (FLAGS_quic_use_new_rto && consecutive_rto_count_ > 0) {
|
| + // If the ack acknowledges data sent prior to the RTO,
|
| + // the RTO was spurious.
|
| + if (ack_frame.largest_observed < first_rto_transmission_) {
|
| + // Replace SRTT with latest_rtt and increase the variance to prevent
|
| + // a spurious RTO from happening again.
|
| + rtt_stats_.ExpireSmoothedMetrics();
|
| + } else {
|
| + send_algorithm_->OnRetransmissionTimeout(true);
|
| + }
|
| + }
|
| // Reset all retransmit counters any time a new packet is acked.
|
| consecutive_rto_count_ = 0;
|
| consecutive_tlp_count_ = 0;
|
| @@ -365,7 +379,10 @@ void QuicSentPacketManager::MarkForRetransmission(
|
| const TransmissionInfo& transmission_info =
|
| unacked_packets_.GetTransmissionInfo(sequence_number);
|
| LOG_IF(DFATAL, transmission_info.retransmittable_frames == nullptr);
|
| - if (transmission_type != TLP_RETRANSMISSION) {
|
| + // Both TLP and the new RTO leave the packets in flight and let the loss
|
| + // detection decide if packets are lost.
|
| + if (transmission_type != TLP_RETRANSMISSION &&
|
| + (!FLAGS_quic_use_new_rto || transmission_type != RTO_RETRANSMISSION)) {
|
| unacked_packets_.RemoveFromInFlight(sequence_number);
|
| }
|
| // TODO(ianswett): Currently the RTO can fire while there are pending NACK
|
| @@ -380,7 +397,8 @@ void QuicSentPacketManager::MarkForRetransmission(
|
| void QuicSentPacketManager::RecordSpuriousRetransmissions(
|
| const SequenceNumberList& all_transmissions,
|
| QuicPacketSequenceNumber acked_sequence_number) {
|
| - if (acked_sequence_number < first_rto_transmission_) {
|
| + if (!FLAGS_quic_use_new_rto &&
|
| + acked_sequence_number < first_rto_transmission_) {
|
| // Cancel all pending RTO transmissions and restore their in flight status.
|
| // Replace SRTT with latest_rtt and increase the variance to prevent
|
| // a spurious RTO from happening again.
|
| @@ -405,9 +423,8 @@ void QuicSentPacketManager::RecordSpuriousRetransmissions(
|
| stats_->bytes_spuriously_retransmitted += retransmit_info.bytes_sent;
|
| ++stats_->packets_spuriously_retransmitted;
|
| if (debug_delegate_ != nullptr) {
|
| - debug_delegate_->OnSpuriousPacketRetransmition(
|
| - retransmit_info.transmission_type,
|
| - retransmit_info.bytes_sent);
|
| + debug_delegate_->OnSpuriousPacketRetransmission(
|
| + retransmit_info.transmission_type, retransmit_info.bytes_sent);
|
| }
|
| }
|
| }
|
| @@ -535,7 +552,8 @@ bool QuicSentPacketManager::OnPacketSent(
|
| LOG_IF(DFATAL, bytes == 0) << "Cannot send empty packets.";
|
|
|
| if (original_sequence_number == 0) {
|
| - if (serialized_packet->retransmittable_frames) {
|
| + if (!FLAGS_quic_ack_notifier_informed_on_serialized &&
|
| + serialized_packet->retransmittable_frames) {
|
| ack_notifier_manager_.OnSerializedPacket(*serialized_packet);
|
| }
|
| } else {
|
| @@ -623,7 +641,11 @@ void QuicSentPacketManager::OnRetransmissionTimeout() {
|
| return;
|
| case RTO_MODE:
|
| ++stats_->rto_count;
|
| - RetransmitAllPackets();
|
| + if (FLAGS_quic_use_new_rto) {
|
| + RetransmitRtoPackets();
|
| + } else {
|
| + RetransmitAllPackets();
|
| + }
|
| return;
|
| }
|
| }
|
| @@ -669,6 +691,33 @@ bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() {
|
| return false;
|
| }
|
|
|
| +void QuicSentPacketManager::RetransmitRtoPackets() {
|
| + LOG_IF(DFATAL, pending_timer_transmission_count_ > 0)
|
| + << "Retransmissions already queued:" << pending_timer_transmission_count_;
|
| + // Mark two packets for retransmission.
|
| + QuicPacketSequenceNumber sequence_number = unacked_packets_.GetLeastUnacked();
|
| + for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
|
| + it != unacked_packets_.end(); ++it, ++sequence_number) {
|
| + if (it->retransmittable_frames != nullptr &&
|
| + pending_timer_transmission_count_ < kMaxRetransmissionsOnTimeout) {
|
| + MarkForRetransmission(sequence_number, RTO_RETRANSMISSION);
|
| + ++pending_timer_transmission_count_;
|
| + }
|
| + // Abandon non-retransmittable data that's in flight to ensure it doesn't
|
| + // fill up the congestion window.
|
| + if (it->retransmittable_frames == nullptr && it->in_flight &&
|
| + it->all_transmissions == nullptr) {
|
| + unacked_packets_.RemoveFromInFlight(sequence_number);
|
| + }
|
| + }
|
| + if (pending_timer_transmission_count_ > 0) {
|
| + if (consecutive_rto_count_ == 0) {
|
| + first_rto_transmission_ = unacked_packets_.largest_sent_packet() + 1;
|
| + }
|
| + ++consecutive_rto_count_;
|
| + }
|
| +}
|
| +
|
| void QuicSentPacketManager::RetransmitAllPackets() {
|
| DVLOG(1) << "RetransmitAllPackets() called with "
|
| << unacked_packets_.GetNumUnackedPacketsDebugOnly()
|
| @@ -946,6 +995,11 @@ QuicPacketCount QuicSentPacketManager::GetSlowStartThresholdInTcpMss() const {
|
| return send_algorithm_->GetSlowStartThreshold() / kDefaultTCPMSS;
|
| }
|
|
|
| +void QuicSentPacketManager::OnSerializedPacket(
|
| + const SerializedPacket& serialized_packet) {
|
| + ack_notifier_manager_.OnSerializedPacket(serialized_packet);
|
| +}
|
| +
|
| void QuicSentPacketManager::EnablePacing() {
|
| if (using_pacing_) {
|
| return;
|
|
|