blob: 8db151b2efffc1b41c8b496d64ae9bc85627d145 [file] [log] [blame]
// 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>
namespace quic {
UberLossAlgorithm::UberLossAlgorithm() : UberLossAlgorithm(kNack) {}
UberLossAlgorithm::UberLossAlgorithm(LossDetectionType loss_type)
: loss_type_(loss_type) {
SetLossDetectionType(loss_type);
for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
general_loss_algorithms_[i].SetPacketNumberSpace(
static_cast<PacketNumberSpace>(i));
}
}
LossDetectionType UberLossAlgorithm::GetLossDetectionType() const {
return loss_type_;
}
void UberLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) {
loss_type_ = loss_type;
for (auto& loss_algorithm : general_loss_algorithms_) {
loss_algorithm.SetLossDetectionType(loss_type);
}
}
void UberLossAlgorithm::DetectLosses(
const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
const RttStats& rtt_stats,
QuicPacketNumber /*largest_newly_acked*/,
const AckedPacketVector& packets_acked,
LostPacketVector* packets_lost) {
DCHECK(unacked_packets.use_uber_loss_algorithm());
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::SpuriousRetransmitDetected(
const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
const RttStats& rtt_stats,
QuicPacketNumber spurious_retransmission) {
DCHECK(unacked_packets.use_uber_loss_algorithm());
general_loss_algorithms_[unacked_packets.GetPacketNumberSpace(
spurious_retransmission)]
.SpuriousRetransmitDetected(unacked_packets, time, rtt_stats,
spurious_retransmission);
}
} // namespace quic