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 3// found in the LICENSE file. 4 5#include "net/quic/congestion_control/tcp_loss_algorithm.h" 6 7#include "net/quic/congestion_control/rtt_stats.h" 8#include "net/quic/quic_protocol.h" 9 10namespace net { 11 12namespace { 13 14// TCP retransmits after 3 nacks. 15static const size_t kNumberOfNacksBeforeRetransmission = 3; 16 17// How many RTTs the algorithm waits before determining a packet is lost due 18// to early retransmission. 19static const double kEarlyRetransmitLossDelayMultiplier = 1.25; 20 21} 22 23TCPLossAlgorithm::TCPLossAlgorithm() 24 : loss_detection_timeout_(QuicTime::Zero()) { } 25 26LossDetectionType TCPLossAlgorithm::GetLossDetectionType() const { 27 return kNack; 28} 29 30// Uses nack counts to decide when packets are lost. 31SequenceNumberSet TCPLossAlgorithm::DetectLostPackets( 32 const QuicUnackedPacketMap& unacked_packets, 33 const QuicTime& time, 34 QuicPacketSequenceNumber largest_observed, 35 const RttStats& rtt_stats) { 36 SequenceNumberSet lost_packets; 37 loss_detection_timeout_ = QuicTime::Zero(); 38 QuicTime::Delta loss_delay = 39 rtt_stats.SmoothedRtt().Multiply(kEarlyRetransmitLossDelayMultiplier); 40 41 for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin(); 42 it != unacked_packets.end() && it->first <= largest_observed; ++it) { 43 if (!it->second.in_flight) { 44 continue; 45 } 46 47 LOG_IF(DFATAL, it->second.nack_count == 0) 48 << "All packets less than largest observed should have been nacked."; 49 if (it->second.nack_count >= kNumberOfNacksBeforeRetransmission) { 50 lost_packets.insert(it->first); 51 continue; 52 } 53 54 // Only early retransmit(RFC5827) when the last packet gets acked and 55 // there are retransmittable packets in flight. 56 // This also implements a timer-protected variant of FACK. 57 if (it->second.retransmittable_frames && 58 unacked_packets.largest_sent_packet() == largest_observed) { 59 // Early retransmit marks the packet as lost once 1.25RTTs have passed 60 // since the packet was sent and otherwise sets an alarm. 61 if (time >= it->second.sent_time.Add(loss_delay)) { 62 lost_packets.insert(it->first); 63 } else { 64 // Set the timeout for the earliest retransmittable packet where early 65 // retransmit applies. 66 loss_detection_timeout_ = it->second.sent_time.Add(loss_delay); 67 break; 68 } 69 } 70 } 71 72 return lost_packets; 73} 74 75QuicTime TCPLossAlgorithm::GetLossTimeout() const { 76 return loss_detection_timeout_; 77} 78 79} // namespace net 80