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