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