blob: 5ff10503025511d7903a4dd4668855220eb5fd61 [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/bbr2_startup.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
namespace quic {
Bbr2StartupMode::Bbr2StartupMode(const Bbr2Sender* sender,
Bbr2NetworkModel* model)
: Bbr2ModeBase(sender, model),
full_bandwidth_reached_(false),
full_bandwidth_baseline_(QuicBandwidth::Zero()),
rounds_without_bandwidth_growth_(0),
loss_events_in_round_(0) {}
void Bbr2StartupMode::Enter(const Bbr2CongestionEvent& /*congestion_event*/) {
QUIC_BUG << "Bbr2StartupMode::Enter should not be called";
}
Bbr2Mode Bbr2StartupMode::OnCongestionEvent(
QuicByteCount /*prior_in_flight*/,
QuicTime /*event_time*/,
const AckedPacketVector& /*acked_packets*/,
const LostPacketVector& lost_packets,
const Bbr2CongestionEvent& congestion_event) {
CheckFullBandwidthReached(congestion_event);
CheckExcessiveLosses(lost_packets, congestion_event);
model_->set_pacing_gain(Params().startup_gain);
model_->set_cwnd_gain(Params().startup_gain);
// TODO(wub): Maybe implement STARTUP => PROBE_RTT.
return full_bandwidth_reached_ ? Bbr2Mode::DRAIN : Bbr2Mode::STARTUP;
}
void Bbr2StartupMode::CheckFullBandwidthReached(
const Bbr2CongestionEvent& congestion_event) {
DCHECK(!full_bandwidth_reached_);
if (full_bandwidth_reached_ || !congestion_event.end_of_round_trip ||
congestion_event.last_sample_is_app_limited) {
return;
}
QuicBandwidth threshold =
full_bandwidth_baseline_ * Params().startup_full_bw_threshold;
if (model_->MaxBandwidth() >= threshold) {
QUIC_DVLOG(3)
<< sender_
<< " CheckFullBandwidthReached at end of round. max_bandwidth:"
<< model_->MaxBandwidth() << ", threshold:" << threshold
<< " (Still growing) @ " << congestion_event.event_time;
full_bandwidth_baseline_ = model_->MaxBandwidth();
rounds_without_bandwidth_growth_ = 0;
return;
}
++rounds_without_bandwidth_growth_;
full_bandwidth_reached_ =
rounds_without_bandwidth_growth_ >= Params().startup_full_bw_rounds;
QUIC_DVLOG(3) << sender_
<< " CheckFullBandwidthReached at end of round. max_bandwidth:"
<< model_->MaxBandwidth() << ", threshold:" << threshold
<< " rounds_without_growth:" << rounds_without_bandwidth_growth_
<< " full_bw_reached:" << full_bandwidth_reached_ << " @ "
<< congestion_event.event_time;
}
void Bbr2StartupMode::CheckExcessiveLosses(
const LostPacketVector& lost_packets,
const Bbr2CongestionEvent& congestion_event) {
if (full_bandwidth_reached_) {
return;
}
if (!lost_packets.empty()) {
++loss_events_in_round_;
}
// TODO(wub): In TCP, loss based exit only happens at end of a loss round, in
// QUIC we use the end of the normal round here. It is possible to exit after
// any congestion event, using information of the "rolling round".
if (!congestion_event.end_of_round_trip) {
return;
}
QUIC_DVLOG(3)
<< sender_
<< " CheckExcessiveLosses at end of round. loss_events_in_round_:"
<< loss_events_in_round_
<< ", threshold:" << Params().startup_full_loss_count << " @ "
<< congestion_event.event_time;
// At the end of a round trip. Check if loss is too high in this round.
if (loss_events_in_round_ >= Params().startup_full_loss_count &&
model_->IsInflightTooHigh(congestion_event)) {
const QuicByteCount bdp = model_->BDP(model_->MaxBandwidth());
QUIC_DVLOG(3) << sender_
<< " Exiting STARTUP due to loss. inflight_hi:" << bdp;
model_->set_inflight_hi(bdp);
full_bandwidth_reached_ = true;
}
loss_events_in_round_ = 0;
}
Bbr2StartupMode::DebugState Bbr2StartupMode::ExportDebugState() const {
DebugState s;
s.full_bandwidth_reached = full_bandwidth_reached_;
s.full_bandwidth_baseline = full_bandwidth_baseline_;
s.round_trips_without_bandwidth_growth = rounds_without_bandwidth_growth_;
return s;
}
std::ostream& operator<<(std::ostream& os,
const Bbr2StartupMode::DebugState& state) {
os << "[STARTUP] full_bandwidth_reached: " << state.full_bandwidth_reached
<< "\n";
os << "[STARTUP] full_bandwidth_baseline: " << state.full_bandwidth_baseline
<< "\n";
os << "[STARTUP] round_trips_without_bandwidth_growth: "
<< state.round_trips_without_bandwidth_growth << "\n";
return os;
}
const Bbr2Params& Bbr2StartupMode::Params() const {
return sender_->Params();
}
} // namespace quic