| 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 9282038e980aff84d671a514ca13e8739c2d2640..65c0254434c4e93e0e6eb2a9a726c2e68a4a2a31 100644
|
| --- a/net/quic/quic_sent_packet_manager.cc
|
| +++ b/net/quic/quic_sent_packet_manager.cc
|
| @@ -21,10 +21,6 @@ using std::min;
|
| // other transmissions.
|
| bool FLAGS_track_retransmission_history = false;
|
|
|
| -// A test-only flag to prevent the RTO from backing off when multiple sequential
|
| -// tail drops occur.
|
| -bool FLAGS_limit_rto_increase_for_tests = false;
|
| -
|
| // Do not remove this flag until the Finch-trials described in b/11706275
|
| // are complete.
|
| // If true, QUIC connections will support the use of a pacing algorithm when
|
| @@ -259,6 +255,13 @@ void QuicSentPacketManager::ClearPreviousRetransmissions(size_t num_to_clear) {
|
| SequenceNumberSet* previous_transmissions =
|
| it->second.previous_transmissions;
|
| if (previous_transmissions == NULL) {
|
| + if (it->second.retransmittable_frames == NULL) {
|
| + // This is a current transmission, but a previous transmission has
|
| + // been acked, so it's safe to remove.
|
| + it = MarkPacketHandled(sequence_number, NOT_RECEIVED_BY_PEER);
|
| + --num_to_clear;
|
| + continue;
|
| + }
|
| break;
|
| }
|
| QuicPacketSequenceNumber newest_transmission =
|
| @@ -422,7 +425,6 @@ QuicSentPacketManager::MarkPacketHandled(
|
| delete newest_it->second.retransmittable_frames;
|
| newest_it->second.retransmittable_frames = NULL;
|
| newest_it->second.previous_transmissions = NULL;
|
| - pending_retransmissions_.erase(newest_transmission);
|
| }
|
|
|
| // Clear out information all previous transmissions.
|
| @@ -441,6 +443,18 @@ QuicSentPacketManager::MarkPacketHandled(
|
|
|
| delete previous_transmissions;
|
|
|
| + if (ContainsKey(pending_retransmissions_, newest_transmission)) {
|
| + pending_retransmissions_.erase(newest_transmission);
|
| + if (!ContainsKey(pending_packets_, newest_transmission)) {
|
| + // If the newest transmission has already been marked for retransmission
|
| + // and has already been abandoned, then we should remove it from
|
| + // unacked_packets_, as well as cancel the retransmission.
|
| + DCHECK(ContainsKey(unacked_packets_, newest_transmission));
|
| + DCHECK(!unacked_packets_[newest_transmission].previous_transmissions);
|
| + unacked_packets_.erase(newest_transmission);
|
| + }
|
| + }
|
| +
|
| UnackedPacketMap::iterator next_unacked = unacked_packets_.begin();
|
| while (next_unacked != unacked_packets_.end() &&
|
| next_unacked->first < sequence_number) {
|
| @@ -626,9 +640,6 @@ void QuicSentPacketManager::RetransmitOldestPacket() {
|
| void QuicSentPacketManager::RetransmitAllPackets() {
|
| // Abandon all retransmittable packets and packets older than the
|
| // retransmission delay.
|
| - QuicTime::Delta retransmission_delay = GetRetransmissionDelay();
|
| - QuicTime max_send_time =
|
| - clock_->ApproximateNow().Subtract(retransmission_delay);
|
|
|
| DVLOG(1) << "OnRetransmissionTimeout() fired with "
|
| << unacked_packets_.size() << " unacked packets.";
|
| @@ -641,18 +652,15 @@ void QuicSentPacketManager::RetransmitAllPackets() {
|
| for (UnackedPacketMap::const_iterator it = unacked_packets_.begin();
|
| it != unacked_packets_.end(); ++it) {
|
| if (it->second.retransmittable_frames != NULL) {
|
| - OnPacketAbandoned(it->first);
|
| packets_retransmitted = true;
|
| MarkForRetransmission(it->first, RTO_RETRANSMISSION);
|
| - } else if (it->second.sent_time <= max_send_time) {
|
| - OnPacketAbandoned(it->first);
|
| }
|
| }
|
|
|
| - // Only inform the send algorithm of an RTO if data was retransmitted.
|
| + pending_packets_.clear();
|
| + send_algorithm_->OnRetransmissionTimeout(packets_retransmitted);
|
| if (packets_retransmitted) {
|
| ++consecutive_rto_count_;
|
| - send_algorithm_->OnRetransmissionTimeout();
|
| }
|
| }
|
|
|
| @@ -750,7 +758,14 @@ void QuicSentPacketManager::MaybeRetransmitOnAckFrame(
|
| lost_packets.insert(sequence_number);
|
| if (transmission_info.retransmittable_frames) {
|
| ++num_retransmitted;
|
| - MarkForRetransmission(*it, NACK_RETRANSMISSION);
|
| + MarkForRetransmission(sequence_number, NACK_RETRANSMISSION);
|
| + } else {
|
| + // Since we will not retransmit this, we need to remove it from
|
| + // unacked_packets_. This is either the current transmission of
|
| + // a packet whose previous transmission has been acked, or it
|
| + // is a packet that has been TLP retransmitted.
|
| + RemovePreviousTransmission(sequence_number);
|
| + unacked_packets_.erase(sequence_number);
|
| }
|
|
|
| ++it;
|
| @@ -765,8 +780,9 @@ void QuicSentPacketManager::MaybeRetransmitOnAckFrame(
|
| // repair the loss, it should be recorded as a loss to the congestion
|
| // manager, but not retransmitted until it's known whether the FEC packet
|
| // arrived.
|
| - send_algorithm_->OnPacketLost(*it, ack_receive_time);
|
| - OnPacketAbandoned(*it);
|
| + QuicPacketSequenceNumber lost_packet = *it;
|
| + send_algorithm_->OnPacketLost(lost_packet, ack_receive_time);
|
| + OnPacketAbandoned(lost_packet);
|
| }
|
| }
|
|
|
| @@ -857,8 +873,8 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
|
| return QuicTime::Zero();
|
| }
|
|
|
| -const QuicTime::Delta
|
| -QuicSentPacketManager::GetCryptoRetransmissionDelay() const {
|
| +const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay()
|
| + const {
|
| // This is equivalent to the TailLossProbeDelay, but slightly more aggressive
|
| // because crypto handshake messages don't incur a delayed ack time.
|
| int64 delay_ms = max<int64>(kMinHandshakeTimeoutMs,
|
| @@ -879,24 +895,6 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
|
| }
|
|
|
| const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
|
| - size_t number_retransmissions = consecutive_rto_count_;
|
| - // TODO(ianswett): Remove this flag now that EndToEndTest is no longer flaky.
|
| - if (FLAGS_limit_rto_increase_for_tests) {
|
| - const size_t kTailDropWindowSize = 5;
|
| - const size_t kTailDropMaxRetransmissions = 4;
|
| - if (pending_packets_.size() <= kTailDropWindowSize) {
|
| - // Avoid exponential backoff of RTO when there are only a few packets
|
| - // outstanding. This helps avoid the situation where fake packet loss
|
| - // causes a packet and it's retransmission to be dropped causing
|
| - // test timouts.
|
| - if (number_retransmissions <= kTailDropMaxRetransmissions) {
|
| - number_retransmissions = 0;
|
| - } else {
|
| - number_retransmissions -= kTailDropMaxRetransmissions;
|
| - }
|
| - }
|
| - }
|
| -
|
| QuicTime::Delta retransmission_delay = send_algorithm_->RetransmissionDelay();
|
| if (retransmission_delay.IsZero()) {
|
| // We are in the initial state, use default timeout values.
|
| @@ -905,7 +903,7 @@ const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
|
| }
|
| // Calculate exponential back off.
|
| retransmission_delay = retransmission_delay.Multiply(
|
| - 1 << min<size_t>(number_retransmissions, kMaxRetransmissions));
|
| + 1 << min<size_t>(consecutive_rto_count_, kMaxRetransmissions));
|
|
|
| // TODO(rch): This code should move to |send_algorithm_|.
|
| if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) {
|
| @@ -965,4 +963,19 @@ void QuicSentPacketManager::MaybeEnablePacing() {
|
| QuicTime::Delta::FromMicroseconds(1)));
|
| }
|
|
|
| +void QuicSentPacketManager::RemovePreviousTransmission(
|
| + QuicPacketSequenceNumber sequence_number) {
|
| + SequenceNumberSet* previous_transmissions =
|
| + unacked_packets_[sequence_number].previous_transmissions;
|
| + if (!previous_transmissions) {
|
| + return;
|
| + }
|
| + previous_transmissions->erase(sequence_number);
|
| + if (previous_transmissions->size() == 1) {
|
| + QuicPacketSequenceNumber current = *previous_transmissions->begin();
|
| + unacked_packets_[current].previous_transmissions = NULL;
|
| + delete previous_transmissions;
|
| + }
|
| +}
|
| +
|
| } // namespace net
|
|
|