1 // Copyright 2019 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_UBER_LOSS_ALGORITHM_H_
6 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
7 
8 #include <optional>
9 
10 #include "quiche/quic/core/congestion_control/general_loss_algorithm.h"
11 #include "quiche/quic/core/quic_types.h"
12 #include "quiche/quic/platform/api/quic_flags.h"
13 
14 namespace quic {
15 
16 namespace test {
17 
18 class QuicSentPacketManagerPeer;
19 
20 }  // namespace test
21 
22 struct QUICHE_EXPORT LossDetectionParameters {
23   // See GeneralLossAlgorithm for the meaning of reordering_(shift|threshold).
24   std::optional<int> reordering_shift;
25   std::optional<QuicPacketCount> reordering_threshold;
26 };
27 
28 class QUICHE_EXPORT LossDetectionTunerInterface {
29  public:
~LossDetectionTunerInterface()30   virtual ~LossDetectionTunerInterface() {}
31 
32   // Start the tuning by choosing parameters and saving them into |*params|.
33   // Called near the start of a QUIC session, see the .cc file for exactly
34   // where.
35   virtual bool Start(LossDetectionParameters* params) = 0;
36 
37   // Finish tuning. The tuner is expected to use the actual loss detection
38   // performance(for its definition of performance) to improve the parameter
39   // selection for future QUIC sessions.
40   // Called when a QUIC session closes.
41   virtual void Finish(const LossDetectionParameters& params) = 0;
42 };
43 
44 // This class comprises multiple loss algorithms, each per packet number space.
45 class QUICHE_EXPORT UberLossAlgorithm : public LossDetectionInterface {
46  public:
47   UberLossAlgorithm();
48   UberLossAlgorithm(const UberLossAlgorithm&) = delete;
49   UberLossAlgorithm& operator=(const UberLossAlgorithm&) = delete;
~UberLossAlgorithm()50   ~UberLossAlgorithm() override {}
51 
52   void SetFromConfig(const QuicConfig& config,
53                      Perspective perspective) override;
54 
55   // Detects lost packets.
56   DetectionStats DetectLosses(const QuicUnackedPacketMap& unacked_packets,
57                               QuicTime time, const RttStats& rtt_stats,
58                               QuicPacketNumber largest_newly_acked,
59                               const AckedPacketVector& packets_acked,
60                               LostPacketVector* packets_lost) override;
61 
62   // Returns the earliest time the early retransmit timer should be active.
63   QuicTime GetLossTimeout() const override;
64 
65   // Called to increases time or packet threshold.
66   void SpuriousLossDetected(const QuicUnackedPacketMap& unacked_packets,
67                             const RttStats& rtt_stats,
68                             QuicTime ack_receive_time,
69                             QuicPacketNumber packet_number,
70                             QuicPacketNumber previous_largest_acked) override;
71 
72   void SetLossDetectionTuner(
73       std::unique_ptr<LossDetectionTunerInterface> tuner);
74   void OnConfigNegotiated() override;
75   void OnMinRttAvailable() override;
76   void OnUserAgentIdKnown() override;
77   void OnConnectionClosed() override;
78   void OnReorderingDetected() override;
79 
80   // Sets reordering_shift for all packet number spaces.
81   void SetReorderingShift(int reordering_shift);
82 
83   // Sets reordering_threshold for all packet number spaces.
84   void SetReorderingThreshold(QuicPacketCount reordering_threshold);
85 
86   // Enable adaptive reordering threshold of all packet number spaces.
87   void EnableAdaptiveReorderingThreshold();
88 
89   // Disable adaptive reordering threshold of all packet number spaces.
90   void DisableAdaptiveReorderingThreshold();
91 
92   // Enable adaptive time threshold of all packet number spaces.
93   void EnableAdaptiveTimeThreshold();
94 
95   // Get the packet reordering threshold from the APPLICATION_DATA PN space.
96   // Always 3 when adaptive reordering is not enabled.
97   QuicPacketCount GetPacketReorderingThreshold() const;
98 
99   // Get the packet reordering shift from the APPLICATION_DATA PN space.
100   int GetPacketReorderingShift() const;
101 
102   // Disable packet threshold loss detection for *runt* packets.
103   void DisablePacketThresholdForRuntPackets();
104 
105   // Called to reset loss detection of |space|.
106   void ResetLossDetection(PacketNumberSpace space);
107 
use_adaptive_reordering_threshold()108   bool use_adaptive_reordering_threshold() const {
109     return general_loss_algorithms_[APPLICATION_DATA]
110         .use_adaptive_reordering_threshold();
111   }
112 
use_adaptive_time_threshold()113   bool use_adaptive_time_threshold() const {
114     return general_loss_algorithms_[APPLICATION_DATA]
115         .use_adaptive_time_threshold();
116   }
117 
118  private:
119   friend class test::QuicSentPacketManagerPeer;
120 
121   void MaybeStartTuning();
122 
123   // One loss algorithm per packet number space.
124   GeneralLossAlgorithm general_loss_algorithms_[NUM_PACKET_NUMBER_SPACES];
125 
126   // Used to tune reordering_shift and reordering_threshold.
127   std::unique_ptr<LossDetectionTunerInterface> tuner_;
128   LossDetectionParameters tuned_parameters_;
129   bool tuner_started_ = false;
130   bool min_rtt_available_ = false;
131   // Whether user agent is known to the session.
132   bool user_agent_known_ = false;
133   // Whether tuning is configured in QuicConfig.
134   bool tuning_configured_ = false;
135   bool reorder_happened_ = false;  // Whether any reordered packet is observed.
136 };
137 
138 }  // namespace quic
139 
140 #endif  // QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
141