1 // Copyright 2015 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 #ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_ 6 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_ 7 8 #include <algorithm> 9 #include <map> 10 11 #include "quiche/quic/core/congestion_control/loss_detection_interface.h" 12 #include "quiche/quic/core/quic_packets.h" 13 #include "quiche/quic/core/quic_time.h" 14 #include "quiche/quic/core/quic_types.h" 15 #include "quiche/quic/core/quic_unacked_packet_map.h" 16 #include "quiche/quic/platform/api/quic_export.h" 17 18 namespace quic { 19 20 // Class which can be configured to implement's TCP's approach of detecting loss 21 // when 3 nacks have been received for a packet or with a time threshold. 22 // Also implements TCP's early retransmit(RFC5827). 23 class QUICHE_EXPORT GeneralLossAlgorithm : public LossDetectionInterface { 24 public: 25 GeneralLossAlgorithm() = default; 26 GeneralLossAlgorithm(const GeneralLossAlgorithm&) = delete; 27 GeneralLossAlgorithm& operator=(const GeneralLossAlgorithm&) = delete; ~GeneralLossAlgorithm()28 ~GeneralLossAlgorithm() override {} 29 SetFromConfig(const QuicConfig &,Perspective)30 void SetFromConfig(const QuicConfig& /*config*/, 31 Perspective /*perspective*/) override {} 32 33 // Uses |largest_acked| and time to decide when packets are lost. 34 DetectionStats DetectLosses(const QuicUnackedPacketMap& unacked_packets, 35 QuicTime time, const RttStats& rtt_stats, 36 QuicPacketNumber largest_newly_acked, 37 const AckedPacketVector& packets_acked, 38 LostPacketVector* packets_lost) override; 39 40 // Returns a non-zero value when the early retransmit timer is active. 41 QuicTime GetLossTimeout() const override; 42 43 // Called to increases time and/or packet threshold. 44 void SpuriousLossDetected(const QuicUnackedPacketMap& unacked_packets, 45 const RttStats& rtt_stats, 46 QuicTime ack_receive_time, 47 QuicPacketNumber packet_number, 48 QuicPacketNumber previous_largest_acked) override; 49 OnConfigNegotiated()50 void OnConfigNegotiated() override { 51 QUICHE_DCHECK(false) 52 << "Unexpected call to GeneralLossAlgorithm::OnConfigNegotiated"; 53 } 54 OnMinRttAvailable()55 void OnMinRttAvailable() override { 56 QUICHE_DCHECK(false) 57 << "Unexpected call to GeneralLossAlgorithm::OnMinRttAvailable"; 58 } 59 OnUserAgentIdKnown()60 void OnUserAgentIdKnown() override { 61 QUICHE_DCHECK(false) 62 << "Unexpected call to GeneralLossAlgorithm::OnUserAgentIdKnown"; 63 } 64 OnConnectionClosed()65 void OnConnectionClosed() override { 66 QUICHE_DCHECK(false) 67 << "Unexpected call to GeneralLossAlgorithm::OnConnectionClosed"; 68 } 69 OnReorderingDetected()70 void OnReorderingDetected() override { 71 QUICHE_DCHECK(false) 72 << "Unexpected call to GeneralLossAlgorithm::OnReorderingDetected"; 73 } 74 75 void Initialize(PacketNumberSpace packet_number_space, 76 LossDetectionInterface* parent); 77 78 void Reset(); 79 reordering_threshold()80 QuicPacketCount reordering_threshold() const { return reordering_threshold_; } 81 reordering_shift()82 int reordering_shift() const { return reordering_shift_; } 83 set_reordering_shift(int reordering_shift)84 void set_reordering_shift(int reordering_shift) { 85 reordering_shift_ = reordering_shift; 86 } 87 set_reordering_threshold(QuicPacketCount reordering_threshold)88 void set_reordering_threshold(QuicPacketCount reordering_threshold) { 89 reordering_threshold_ = reordering_threshold; 90 } 91 use_adaptive_reordering_threshold()92 bool use_adaptive_reordering_threshold() const { 93 return use_adaptive_reordering_threshold_; 94 } 95 set_use_adaptive_reordering_threshold(bool value)96 void set_use_adaptive_reordering_threshold(bool value) { 97 use_adaptive_reordering_threshold_ = value; 98 } 99 use_adaptive_time_threshold()100 bool use_adaptive_time_threshold() const { 101 return use_adaptive_time_threshold_; 102 } 103 enable_adaptive_time_threshold()104 void enable_adaptive_time_threshold() { use_adaptive_time_threshold_ = true; } 105 use_packet_threshold_for_runt_packets()106 bool use_packet_threshold_for_runt_packets() const { 107 return use_packet_threshold_for_runt_packets_; 108 } 109 disable_packet_threshold_for_runt_packets()110 void disable_packet_threshold_for_runt_packets() { 111 use_packet_threshold_for_runt_packets_ = false; 112 } 113 114 private: 115 LossDetectionInterface* parent_ = nullptr; 116 QuicTime loss_detection_timeout_ = QuicTime::Zero(); 117 // Fraction of a max(SRTT, latest_rtt) to permit reordering before declaring 118 // loss. Fraction calculated by shifting max(SRTT, latest_rtt) to the right 119 // by reordering_shift. 120 int reordering_shift_ = kDefaultLossDelayShift; 121 // Reordering threshold for loss detection. 122 QuicPacketCount reordering_threshold_ = kDefaultPacketReorderingThreshold; 123 // If true, uses adaptive reordering threshold for loss detection. 124 bool use_adaptive_reordering_threshold_ = true; 125 // If true, uses adaptive time threshold for time based loss detection. 126 bool use_adaptive_time_threshold_ = false; 127 // If true, uses packet threshold when largest acked is a runt packet. 128 bool use_packet_threshold_for_runt_packets_ = true; 129 // The least in flight packet. Loss detection should start from this. Please 130 // note, least_in_flight_ could be largest packet ever sent + 1. 131 QuicPacketNumber least_in_flight_{1}; 132 PacketNumberSpace packet_number_space_ = NUM_PACKET_NUMBER_SPACES; 133 }; 134 135 } // namespace quic 136 137 #endif // QUICHE_QUIC_CORE_CONGESTION_CONTROL_GENERAL_LOSS_ALGORITHM_H_ 138