summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
blob: 73b26f5cda73a988a792e0b984707219f35ebdfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h"

#include <algorithm>

#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"

namespace quic {

UberLossAlgorithm::UberLossAlgorithm() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].SetPacketNumberSpace(
        static_cast<PacketNumberSpace>(i));
  }
}

void UberLossAlgorithm::DetectLosses(
    const QuicUnackedPacketMap& unacked_packets,
    QuicTime time,
    const RttStats& rtt_stats,
    QuicPacketNumber /*largest_newly_acked*/,
    const AckedPacketVector& packets_acked,
    LostPacketVector* packets_lost) {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    const QuicPacketNumber largest_acked =
        unacked_packets.GetLargestAckedOfPacketNumberSpace(
            static_cast<PacketNumberSpace>(i));
    if (!largest_acked.IsInitialized() ||
        unacked_packets.GetLeastUnacked() > largest_acked) {
      // Skip detecting losses if no packet has been received for this packet
      // number space or the least_unacked is greater than largest_acked.
      continue;
    }

    general_loss_algorithms_[i].DetectLosses(unacked_packets, time, rtt_stats,
                                             largest_acked, packets_acked,
                                             packets_lost);
  }
}

QuicTime UberLossAlgorithm::GetLossTimeout() const {
  QuicTime loss_timeout = QuicTime::Zero();
  // Returns the earliest non-zero loss timeout.
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    const QuicTime timeout = general_loss_algorithms_[i].GetLossTimeout();
    if (!loss_timeout.IsInitialized()) {
      loss_timeout = timeout;
      continue;
    }
    if (timeout.IsInitialized()) {
      loss_timeout = std::min(loss_timeout, timeout);
    }
  }
  return loss_timeout;
}

void UberLossAlgorithm::SpuriousLossDetected(
    const QuicUnackedPacketMap& unacked_packets,
    const RttStats& rtt_stats,
    QuicTime ack_receive_time,
    QuicPacketNumber packet_number,
    QuicPacketNumber previous_largest_acked) {
  general_loss_algorithms_[unacked_packets.GetPacketNumberSpace(packet_number)]
      .SpuriousLossDetected(unacked_packets, rtt_stats, ack_receive_time,
                            packet_number, previous_largest_acked);
}

void UberLossAlgorithm::SetLossDetectionTuner(
    std::unique_ptr<LossDetectionTunerInterface> tuner) {
  if (tuner_ != nullptr) {
    QUIC_BUG << "LossDetectionTuner can only be set once when session begins.";
    return;
  }
  tuner_ = std::move(tuner);
}

void UberLossAlgorithm::MaybeStartTuning() {
  if (tuner_ == nullptr || tuner_started_) {
    return;
  }

  tuner_started_ = tuner_->Start(&tuned_parameters_);
}

void UberLossAlgorithm::OnConfigNegotiated() {}

void UberLossAlgorithm::OnMinRttAvailable() {
  MaybeStartTuning();
}

void UberLossAlgorithm::OnConnectionClosed() {
  if (tuner_ != nullptr && tuner_started_) {
    tuner_->Finish(tuned_parameters_);
  }
}

void UberLossAlgorithm::SetReorderingShift(int reordering_shift) {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_reordering_shift(reordering_shift);
  }
}

void UberLossAlgorithm::SetReorderingThreshold(
    QuicPacketCount reordering_threshold) {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_reordering_threshold(reordering_threshold);
  }
}

void UberLossAlgorithm::EnableAdaptiveReorderingThreshold() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_use_adaptive_reordering_threshold(true);
  }
}

void UberLossAlgorithm::DisableAdaptiveReorderingThreshold() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_use_adaptive_reordering_threshold(false);
  }
}

void UberLossAlgorithm::EnableAdaptiveTimeThreshold() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].enable_adaptive_time_threshold();
  }
}

void UberLossAlgorithm::DisablePacketThresholdForRuntPackets() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].disable_packet_threshold_for_runt_packets();
  }
}

void UberLossAlgorithm::ResetLossDetection(PacketNumberSpace space) {
  if (space >= NUM_PACKET_NUMBER_SPACES) {
    QUIC_BUG << "Invalid packet number space: " << space;
    return;
  }
  general_loss_algorithms_[space].Reset();
}

}  // namespace quic