Makes BBR more like the Quic implementation.
Bug: webrtc:8415 Change-Id: I2c21fbe88afec88726cbdd7c6e7626cccb07ce71 Reviewed-on: https://webrtc-review.googlesource.com/77762 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23420}
This commit is contained in:
parent
535bde3752
commit
7645b18c04
@ -27,7 +27,7 @@ rtc_source_set("bbr_controller") {
|
||||
"bbr_network_controller.h",
|
||||
]
|
||||
deps = [
|
||||
":data_transfer_tracker",
|
||||
":bandwidth_sampler",
|
||||
":rtt_stats",
|
||||
":windowed_filter",
|
||||
"../../../api:optional",
|
||||
|
||||
@ -156,22 +156,49 @@ BbrNetworkController::DebugState::DebugState(const BbrNetworkController& sender)
|
||||
recovery_state(sender.recovery_state_),
|
||||
recovery_window(sender.recovery_window_),
|
||||
last_sample_is_app_limited(sender.last_sample_is_app_limited_),
|
||||
end_of_app_limited_phase(sender.end_of_app_limited_phase_) {}
|
||||
end_of_app_limited_phase(sender.sampler_->end_of_app_limited_phase()) {}
|
||||
|
||||
BbrNetworkController::DebugState::DebugState(const DebugState& state) = default;
|
||||
|
||||
BbrNetworkController::BbrNetworkController(NetworkControllerConfig config)
|
||||
: random_(10),
|
||||
: rtt_stats_(),
|
||||
random_(10),
|
||||
mode_(STARTUP),
|
||||
sampler_(new BandwidthSampler()),
|
||||
round_trip_count_(0),
|
||||
last_sent_packet_(0),
|
||||
current_round_trip_end_(0),
|
||||
max_bandwidth_(kBandwidthWindowSize, DataRate::Zero(), 0),
|
||||
default_bandwidth_(DataRate::kbps(kInitialBandwidthKbps)),
|
||||
max_ack_height_(kBandwidthWindowSize, DataSize::Zero(), 0),
|
||||
aggregation_epoch_start_time_(),
|
||||
aggregation_epoch_bytes_(DataSize::Zero()),
|
||||
bytes_acked_since_queue_drained_(DataSize::Zero()),
|
||||
max_aggregation_bytes_multiplier_(0),
|
||||
min_rtt_(TimeDelta::Zero()),
|
||||
last_rtt_(TimeDelta::Zero()),
|
||||
min_rtt_timestamp_(Timestamp::ms(0)),
|
||||
congestion_window_(DataSize::bytes(kInitialCongestionWindowBytes)),
|
||||
initial_congestion_window_(
|
||||
DataSize::bytes(kInitialCongestionWindowBytes)),
|
||||
max_congestion_window_(DataSize::bytes(kDefaultMaxCongestionWindowBytes)),
|
||||
pacing_rate_(DataRate::Zero()),
|
||||
pacing_gain_(1),
|
||||
congestion_window_gain_constant_(kProbeBWCongestionWindowGain),
|
||||
rtt_variance_weight_(kBbrRttVariationWeight),
|
||||
recovery_window_(max_congestion_window_) {
|
||||
cycle_current_offset_(0),
|
||||
last_cycle_start_(Timestamp::ms(0)),
|
||||
is_at_full_bandwidth_(false),
|
||||
rounds_without_bandwidth_gain_(0),
|
||||
bandwidth_at_last_round_(DataRate::Zero()),
|
||||
exit_probe_rtt_at_(),
|
||||
probe_rtt_round_passed_(false),
|
||||
last_sample_is_app_limited_(false),
|
||||
recovery_state_(NOT_IN_RECOVERY),
|
||||
end_recovery_at_(),
|
||||
recovery_window_(max_congestion_window_),
|
||||
app_limited_since_last_probe_rtt_(false),
|
||||
min_rtt_since_last_probe_rtt_(TimeDelta::PlusInfinity()) {
|
||||
RTC_LOG(LS_INFO) << "Creating BBR controller";
|
||||
config_ = BbrControllerConfig::ExperimentConfig();
|
||||
if (config.starting_bandwidth.IsFinite())
|
||||
@ -181,6 +208,7 @@ BbrNetworkController::BbrNetworkController(NetworkControllerConfig config)
|
||||
if (config_.num_startup_rtts > 0) {
|
||||
EnterStartupMode();
|
||||
} else {
|
||||
is_at_full_bandwidth_ = true;
|
||||
EnterProbeBandwidthMode(constraints_->at_time);
|
||||
}
|
||||
}
|
||||
@ -292,11 +320,14 @@ bool BbrNetworkController::InSlowStart() const {
|
||||
}
|
||||
|
||||
NetworkControlUpdate BbrNetworkController::OnSentPacket(SentPacket msg) {
|
||||
last_send_time_ = msg.send_time;
|
||||
last_sent_packet_ = msg.sequence_number;
|
||||
|
||||
if (!aggregation_epoch_start_time_) {
|
||||
aggregation_epoch_start_time_ = msg.send_time;
|
||||
aggregation_epoch_bytes_ = DataSize::Zero();
|
||||
}
|
||||
|
||||
sampler_->OnPacketSent(msg.send_time, msg.sequence_number, msg.size,
|
||||
msg.data_in_flight);
|
||||
return NetworkControlUpdate();
|
||||
}
|
||||
|
||||
@ -358,44 +389,39 @@ NetworkControlUpdate BbrNetworkController::OnTransportPacketsFeedback(
|
||||
rtt_stats_.UpdateRtt(send_delta, TimeDelta::Zero(), feedback_recv_time);
|
||||
}
|
||||
|
||||
DataSize bytes_in_flight = msg.data_in_flight;
|
||||
DataSize total_acked_size = DataSize::Zero();
|
||||
const DataSize total_data_acked_before = sampler_->total_data_acked();
|
||||
|
||||
bool is_round_start = false;
|
||||
bool min_rtt_expired = false;
|
||||
|
||||
std::vector<PacketResult> acked_packets = msg.ReceivedWithSendInfo();
|
||||
std::vector<PacketResult> lost_packets = msg.LostWithSendInfo();
|
||||
DiscardLostPackets(lost_packets);
|
||||
|
||||
std::vector<PacketResult> acked_packets = msg.ReceivedWithSendInfo();
|
||||
// Input the new data into the BBR model of the connection.
|
||||
if (!acked_packets.empty()) {
|
||||
for (const PacketResult& packet : acked_packets) {
|
||||
const SentPacket& sent_packet = *packet.sent_packet;
|
||||
send_ack_tracker_.AddSample(sent_packet.size, sent_packet.send_time,
|
||||
msg.feedback_time);
|
||||
total_acked_size += sent_packet.size;
|
||||
}
|
||||
Timestamp last_acked_send_time =
|
||||
acked_packets.rbegin()->sent_packet->send_time;
|
||||
is_round_start = UpdateRoundTripCounter(last_acked_send_time);
|
||||
UpdateBandwidth(msg.feedback_time, acked_packets);
|
||||
// Min rtt will be the rtt for the last packet, since all packets are acked
|
||||
// at the same time.
|
||||
Timestamp last_send_time = acked_packets.back().sent_packet->send_time;
|
||||
min_rtt_expired = UpdateMinRtt(msg.feedback_time, last_send_time);
|
||||
UpdateRecoveryState(last_acked_send_time, !lost_packets.empty(),
|
||||
int64_t last_acked_packet =
|
||||
acked_packets.rbegin()->sent_packet->sequence_number;
|
||||
|
||||
is_round_start = UpdateRoundTripCounter(last_acked_packet);
|
||||
min_rtt_expired =
|
||||
UpdateBandwidthAndMinRtt(msg.feedback_time, acked_packets);
|
||||
UpdateRecoveryState(last_acked_packet, !lost_packets.empty(),
|
||||
is_round_start);
|
||||
|
||||
UpdateAckAggregationBytes(msg.feedback_time, total_acked_size);
|
||||
const DataSize data_acked =
|
||||
sampler_->total_data_acked() - total_data_acked_before;
|
||||
|
||||
UpdateAckAggregationBytes(msg.feedback_time, data_acked);
|
||||
if (max_aggregation_bytes_multiplier_ > 0) {
|
||||
if (msg.data_in_flight <=
|
||||
1.25 * GetTargetCongestionWindow(pacing_gain_)) {
|
||||
bytes_acked_since_queue_drained_ = DataSize::Zero();
|
||||
} else {
|
||||
bytes_acked_since_queue_drained_ += total_acked_size;
|
||||
bytes_acked_since_queue_drained_ += data_acked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
total_bytes_acked_ += total_acked_size;
|
||||
|
||||
// Handle logic specific to PROBE_BW mode.
|
||||
if (mode_ == PROBE_BW) {
|
||||
@ -413,16 +439,22 @@ NetworkControlUpdate BbrNetworkController::OnTransportPacketsFeedback(
|
||||
MaybeEnterOrExitProbeRtt(msg, is_round_start, min_rtt_expired);
|
||||
|
||||
// Calculate number of packets acked and lost.
|
||||
DataSize bytes_lost = DataSize::Zero();
|
||||
DataSize data_acked = sampler_->total_data_acked() - total_data_acked_before;
|
||||
DataSize data_lost = DataSize::Zero();
|
||||
for (const PacketResult& packet : lost_packets) {
|
||||
bytes_lost += packet.sent_packet->size;
|
||||
data_lost += packet.sent_packet->size;
|
||||
}
|
||||
|
||||
// After the model is updated, recalculate the pacing rate and congestion
|
||||
// window.
|
||||
CalculatePacingRate();
|
||||
CalculateCongestionWindow(total_acked_size);
|
||||
CalculateRecoveryWindow(total_acked_size, bytes_lost, bytes_in_flight);
|
||||
CalculateCongestionWindow(data_acked);
|
||||
CalculateRecoveryWindow(data_acked, data_lost, msg.data_in_flight);
|
||||
// Cleanup internal state.
|
||||
if (!acked_packets.empty()) {
|
||||
sampler_->RemoveObsoletePackets(
|
||||
acked_packets.back().sent_packet->sequence_number);
|
||||
}
|
||||
return CreateRateUpdate(msg.feedback_time);
|
||||
}
|
||||
|
||||
@ -485,32 +517,54 @@ void BbrNetworkController::EnterProbeBandwidthMode(Timestamp now) {
|
||||
pacing_gain_ = GetPacingGain(cycle_current_offset_);
|
||||
}
|
||||
|
||||
bool BbrNetworkController::UpdateRoundTripCounter(
|
||||
Timestamp last_acked_send_time) {
|
||||
if (last_acked_send_time > current_round_trip_end_) {
|
||||
void BbrNetworkController::DiscardLostPackets(
|
||||
const std::vector<PacketResult>& lost_packets) {
|
||||
for (const PacketResult& packet : lost_packets) {
|
||||
sampler_->OnPacketLost(packet.sent_packet->sequence_number);
|
||||
}
|
||||
}
|
||||
|
||||
bool BbrNetworkController::UpdateRoundTripCounter(int64_t last_acked_packet) {
|
||||
if (last_acked_packet > current_round_trip_end_) {
|
||||
round_trip_count_++;
|
||||
current_round_trip_end_ = last_send_time_;
|
||||
current_round_trip_end_ = last_sent_packet_;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BbrNetworkController::UpdateMinRtt(Timestamp ack_time,
|
||||
Timestamp last_packet_send_time) {
|
||||
// Note: This sample does not account for delayed acknowledgement time. This
|
||||
// means that the RTT measurements here can be artificially high, especially
|
||||
// on low bandwidth connections.
|
||||
TimeDelta sample_rtt = ack_time - last_packet_send_time;
|
||||
bool BbrNetworkController::UpdateBandwidthAndMinRtt(
|
||||
Timestamp now,
|
||||
const std::vector<PacketResult>& acked_packets) {
|
||||
TimeDelta sample_rtt = TimeDelta::PlusInfinity();
|
||||
for (const auto& packet : acked_packets) {
|
||||
BandwidthSample bandwidth_sample = sampler_->OnPacketAcknowledged(
|
||||
now, packet.sent_packet->sequence_number);
|
||||
last_sample_is_app_limited_ = bandwidth_sample.is_app_limited;
|
||||
if (!bandwidth_sample.rtt.IsZero()) {
|
||||
sample_rtt = std::min(sample_rtt, bandwidth_sample.rtt);
|
||||
}
|
||||
|
||||
if (!bandwidth_sample.is_app_limited ||
|
||||
bandwidth_sample.bandwidth > BandwidthEstimate()) {
|
||||
max_bandwidth_.Update(bandwidth_sample.bandwidth, round_trip_count_);
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the RTT samples are valid, return immediately.
|
||||
if (sample_rtt.IsInfinite()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
last_rtt_ = sample_rtt;
|
||||
min_rtt_since_last_probe_rtt_ =
|
||||
std::min(min_rtt_since_last_probe_rtt_, sample_rtt);
|
||||
|
||||
const TimeDelta kMinRttExpiry = TimeDelta::seconds(kMinRttExpirySeconds);
|
||||
// Do not expire min_rtt if none was ever available.
|
||||
bool min_rtt_expired =
|
||||
!min_rtt_.IsZero() &&
|
||||
(ack_time >
|
||||
(min_rtt_timestamp_ + TimeDelta::seconds(kMinRttExpirySeconds)));
|
||||
!min_rtt_.IsZero() && (now > (min_rtt_timestamp_ + kMinRttExpiry));
|
||||
|
||||
if (min_rtt_expired || sample_rtt < min_rtt_ || min_rtt_.IsZero()) {
|
||||
if (ShouldExtendMinRttExpiry()) {
|
||||
@ -518,7 +572,7 @@ bool BbrNetworkController::UpdateMinRtt(Timestamp ack_time,
|
||||
} else {
|
||||
min_rtt_ = sample_rtt;
|
||||
}
|
||||
min_rtt_timestamp_ = ack_time;
|
||||
min_rtt_timestamp_ = now;
|
||||
// Reset since_last_probe_rtt fields.
|
||||
min_rtt_since_last_probe_rtt_ = TimeDelta::PlusInfinity();
|
||||
app_limited_since_last_probe_rtt_ = false;
|
||||
@ -527,37 +581,6 @@ bool BbrNetworkController::UpdateMinRtt(Timestamp ack_time,
|
||||
return min_rtt_expired;
|
||||
}
|
||||
|
||||
void BbrNetworkController::UpdateBandwidth(
|
||||
Timestamp ack_time,
|
||||
const std::vector<PacketResult>& acked_packets) {
|
||||
// There are two possible maximum receive bandwidths based on the duration
|
||||
// from send to ack of a packet, either including or excluding the time until
|
||||
// the current ack was received. Therefore looking at the last and the first
|
||||
// packet is enough. This holds if at most one feedback was received during
|
||||
// the sending of the acked packets.
|
||||
std::array<const PacketResult, 2> packets = {
|
||||
{acked_packets.front(), acked_packets.back()}};
|
||||
for (const PacketResult& packet : packets) {
|
||||
const Timestamp& send_time = packet.sent_packet->send_time;
|
||||
is_app_limited_ = send_time > end_of_app_limited_phase_;
|
||||
auto result = send_ack_tracker_.GetRatesByAckTime(send_time, ack_time);
|
||||
if (result.acked_data == DataSize::Zero())
|
||||
continue;
|
||||
send_ack_tracker_.ClearOldSamples(send_time);
|
||||
|
||||
DataRate ack_rate = result.acked_data / result.ack_timespan;
|
||||
DataRate send_rate = result.send_timespan.IsZero()
|
||||
? DataRate::Infinity()
|
||||
: result.acked_data / result.send_timespan;
|
||||
DataRate bandwidth = std::min(send_rate, ack_rate);
|
||||
if (!bandwidth.IsFinite())
|
||||
continue;
|
||||
if (!is_app_limited_ || bandwidth > BandwidthEstimate()) {
|
||||
max_bandwidth_.Update(bandwidth, round_trip_count_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BbrNetworkController::ShouldExtendMinRttExpiry() const {
|
||||
if (config_.probe_rtt_disabled_if_app_limited &&
|
||||
app_limited_since_last_probe_rtt_) {
|
||||
@ -629,7 +652,7 @@ void BbrNetworkController::CheckIfFullBandwidthReached() {
|
||||
|
||||
rounds_without_bandwidth_gain_++;
|
||||
if ((rounds_without_bandwidth_gain_ >= config_.num_startup_rtts) ||
|
||||
(exit_startup_on_loss_ && InRecovery())) {
|
||||
(config_.exit_startup_on_loss && InRecovery())) {
|
||||
is_at_full_bandwidth_ = true;
|
||||
}
|
||||
}
|
||||
@ -667,8 +690,7 @@ void BbrNetworkController::MaybeEnterOrExitProbeRtt(
|
||||
}
|
||||
|
||||
if (mode_ == PROBE_RTT) {
|
||||
is_app_limited_ = true;
|
||||
end_of_app_limited_phase_ = last_send_time_;
|
||||
sampler_->OnAppLimited();
|
||||
|
||||
if (!exit_probe_rtt_at_) {
|
||||
// If the window has reached the appropriate size, schedule exiting
|
||||
@ -695,12 +717,12 @@ void BbrNetworkController::MaybeEnterOrExitProbeRtt(
|
||||
}
|
||||
}
|
||||
|
||||
void BbrNetworkController::UpdateRecoveryState(Timestamp last_acked_send_time,
|
||||
void BbrNetworkController::UpdateRecoveryState(int64_t last_acked_packet,
|
||||
bool has_losses,
|
||||
bool is_round_start) {
|
||||
// Exit recovery when there are no losses for a round.
|
||||
if (has_losses) {
|
||||
end_recovery_at_ = last_acked_send_time;
|
||||
end_recovery_at_ = last_sent_packet_;
|
||||
}
|
||||
|
||||
switch (recovery_state_) {
|
||||
@ -716,7 +738,7 @@ void BbrNetworkController::UpdateRecoveryState(Timestamp last_acked_send_time,
|
||||
recovery_window_ = DataSize::Zero();
|
||||
// Since the conservation phase is meant to be lasting for a whole
|
||||
// round, extend the current round as if it were started right now.
|
||||
current_round_trip_end_ = last_send_time_;
|
||||
current_round_trip_end_ = last_sent_packet_;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -729,7 +751,7 @@ void BbrNetworkController::UpdateRecoveryState(Timestamp last_acked_send_time,
|
||||
case GROWTH:
|
||||
// Exit recovery if appropriate.
|
||||
if (!has_losses && end_recovery_at_ &&
|
||||
last_acked_send_time > *end_recovery_at_) {
|
||||
last_acked_packet > *end_recovery_at_) {
|
||||
recovery_state_ = NOT_IN_RECOVERY;
|
||||
}
|
||||
|
||||
@ -828,7 +850,7 @@ void BbrNetworkController::CalculateCongestionWindow(DataSize bytes_acked) {
|
||||
congestion_window_ =
|
||||
std::min(target_window, congestion_window_ + bytes_acked);
|
||||
} else if (congestion_window_ < target_window ||
|
||||
total_bytes_acked_ < initial_congestion_window_) {
|
||||
sampler_->total_data_acked() < initial_congestion_window_) {
|
||||
// If the connection is not yet out of startup phase, do not decrease the
|
||||
// window.
|
||||
congestion_window_ = congestion_window_ + bytes_acked;
|
||||
@ -873,7 +895,7 @@ void BbrNetworkController::CalculateRecoveryWindow(DataSize bytes_acked,
|
||||
recovery_window_ += bytes_acked / 2;
|
||||
}
|
||||
|
||||
// Sanity checks. Ensure that we always allow to send at leastś
|
||||
// Sanity checks. Ensure that we always allow to send at least
|
||||
// |bytes_acked| in response.
|
||||
recovery_window_ = std::max(recovery_window_, bytes_in_flight + bytes_acked);
|
||||
recovery_window_ = std::max(kMinimumCongestionWindow, recovery_window_);
|
||||
@ -885,12 +907,10 @@ void BbrNetworkController::OnApplicationLimited(DataSize bytes_in_flight) {
|
||||
}
|
||||
|
||||
app_limited_since_last_probe_rtt_ = true;
|
||||
sampler_->OnAppLimited();
|
||||
|
||||
is_app_limited_ = true;
|
||||
end_of_app_limited_phase_ = last_send_time_;
|
||||
|
||||
RTC_LOG(LS_INFO) << "Becoming application limited. Last sent time: "
|
||||
<< ToString(last_send_time_)
|
||||
RTC_LOG(LS_INFO) << "Becoming application limited. Last sent packet: "
|
||||
<< last_sent_packet_
|
||||
<< ", CWND: " << ToString(GetCongestionWindow());
|
||||
}
|
||||
} // namespace bbr
|
||||
|
||||
@ -15,12 +15,13 @@
|
||||
#define MODULES_CONGESTION_CONTROLLER_BBR_BBR_NETWORK_CONTROLLER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/transport/network_types.h"
|
||||
#include "modules/congestion_controller/bbr/data_transfer_tracker.h"
|
||||
#include "modules/congestion_controller/bbr/bandwidth_sampler.h"
|
||||
#include "modules/congestion_controller/bbr/rtt_stats.h"
|
||||
#include "modules/congestion_controller/bbr/windowed_filter.h"
|
||||
|
||||
@ -91,7 +92,7 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
DataSize recovery_window;
|
||||
|
||||
bool last_sample_is_app_limited;
|
||||
Timestamp end_of_app_limited_phase;
|
||||
int64_t end_of_app_limited_phase;
|
||||
};
|
||||
|
||||
explicit BbrNetworkController(NetworkControllerConfig config);
|
||||
@ -114,49 +115,6 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
NetworkControlUpdate OnTransportLossReport(TransportLossReport msg) override;
|
||||
|
||||
private:
|
||||
struct BbrControllerConfig {
|
||||
// Default config based on default QUIC config
|
||||
static BbrControllerConfig DefaultConfig();
|
||||
static BbrControllerConfig ExperimentConfig();
|
||||
|
||||
double probe_bw_pacing_gain_offset;
|
||||
double encoder_rate_gain;
|
||||
double encoder_rate_gain_in_probe_rtt;
|
||||
// RTT delta to determine if startup should be exited due to increased RTT.
|
||||
int64_t exit_startup_rtt_threshold_ms;
|
||||
|
||||
double probe_rtt_congestion_window_gain;
|
||||
|
||||
// Configurable in QUIC BBR:
|
||||
bool exit_startup_on_loss;
|
||||
// The number of RTTs to stay in STARTUP mode. Defaults to 3.
|
||||
BbrRoundTripCount num_startup_rtts;
|
||||
// When true, recovery is rate based rather than congestion window based.
|
||||
bool rate_based_recovery;
|
||||
double max_aggregation_bytes_multiplier;
|
||||
// When true, pace at 1.5x and disable packet conservation in STARTUP.
|
||||
bool slower_startup;
|
||||
// When true, disables packet conservation in STARTUP.
|
||||
bool rate_based_startup;
|
||||
// If true, will not exit low gain mode until bytes_in_flight drops below
|
||||
// BDP or it's time for high gain mode.
|
||||
bool fully_drain_queue;
|
||||
// Used as the initial packet conservation mode when first entering
|
||||
// recovery.
|
||||
RecoveryState initial_conservation_in_startup;
|
||||
|
||||
double max_ack_height_window_multiplier;
|
||||
// If true, use a CWND of 0.75*BDP during probe_rtt instead of 4 packets.
|
||||
bool probe_rtt_based_on_bdp;
|
||||
// If true, skip probe_rtt and update the timestamp of the existing min_rtt
|
||||
// to now if min_rtt over the last cycle is within 12.5% of the current
|
||||
// min_rtt. Even if the min_rtt is 12.5% too low, the 25% gain cycling and
|
||||
// 2x CWND gain should overcome an overly small min_rtt.
|
||||
bool probe_rtt_skipped_if_similar_rtt;
|
||||
// If true, disable PROBE_RTT entirely as long as the connection was
|
||||
// recently app limited.
|
||||
bool probe_rtt_disabled_if_app_limited;
|
||||
};
|
||||
void Reset();
|
||||
NetworkControlUpdate CreateRateUpdate(Timestamp at_time);
|
||||
|
||||
@ -195,7 +153,9 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
// Returns the current estimate of the RTT of the connection. Outside of the
|
||||
// edge cases, this is minimum RTT.
|
||||
TimeDelta GetMinRtt() const;
|
||||
|
||||
// Returns whether the connection has achieved full bandwidth required to exit
|
||||
// the slow start.
|
||||
bool IsAtFullBandwidth() const;
|
||||
// Computes the target congestion window using the specified gain.
|
||||
DataSize GetTargetCongestionWindow(double gain) const;
|
||||
// The target congestion window during PROBE_RTT.
|
||||
@ -209,14 +169,16 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
// Enters the PROBE_BW mode.
|
||||
void EnterProbeBandwidthMode(Timestamp now);
|
||||
|
||||
// Discards the lost packets from BandwidthSampler state.
|
||||
void DiscardLostPackets(const std::vector<PacketResult>& lost_packets);
|
||||
// Updates the round-trip counter if a round-trip has passed. Returns true if
|
||||
// the counter has been advanced.
|
||||
bool UpdateRoundTripCounter(Timestamp last_acked_timestamp);
|
||||
// |last_acked_packet| is the sequence number of the last acked packet.
|
||||
bool UpdateRoundTripCounter(int64_t last_acked_packet);
|
||||
// Updates the current bandwidth and min_rtt estimate based on the samples for
|
||||
// the received acknowledgements. Returns true if min_rtt has expired.
|
||||
void UpdateBandwidth(Timestamp now,
|
||||
const std::vector<PacketResult>& acked_packets);
|
||||
bool UpdateMinRtt(Timestamp ack_time, Timestamp last_packet_send_time);
|
||||
bool UpdateBandwidthAndMinRtt(Timestamp now,
|
||||
const std::vector<PacketResult>& acked_packets);
|
||||
// Updates the current gain used in PROBE_BW mode.
|
||||
void UpdateGainCyclePhase(Timestamp now,
|
||||
DataSize prior_in_flight,
|
||||
@ -233,7 +195,7 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
bool min_rtt_expired);
|
||||
// Determines whether BBR needs to enter, exit or advance state of the
|
||||
// recovery.
|
||||
void UpdateRecoveryState(Timestamp last_acked_send_time,
|
||||
void UpdateRecoveryState(int64_t last_acked_packet,
|
||||
bool has_losses,
|
||||
bool is_round_start);
|
||||
|
||||
@ -245,7 +207,7 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
void CalculatePacingRate();
|
||||
// Determines the appropriate congestion window for the connection.
|
||||
void CalculateCongestionWindow(DataSize bytes_acked);
|
||||
// Determines the approriate wQuicPacketNumberindow that constrains the
|
||||
// Determines the approriate window that constrains the
|
||||
// in-flight during recovery.
|
||||
void CalculateRecoveryWindow(DataSize bytes_acked,
|
||||
DataSize bytes_lost,
|
||||
@ -254,38 +216,22 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
RttStats rtt_stats_;
|
||||
webrtc::Random random_;
|
||||
|
||||
DataTransferTracker send_ack_tracker_;
|
||||
|
||||
rtc::Optional<TargetRateConstraints> constraints_;
|
||||
|
||||
Mode mode_ = STARTUP;
|
||||
Mode mode_;
|
||||
|
||||
BbrControllerConfig config_;
|
||||
|
||||
// The total number of congestion controlled bytes which were acknowledged.
|
||||
DataSize total_bytes_acked_ = DataSize::Zero();
|
||||
// The time at which the last acknowledged packet was sent. Set to
|
||||
// Timestamp::ms(0) if no valid timestamp is available.
|
||||
Timestamp last_acked_packet_sent_time_ = Timestamp::ms(0);
|
||||
|
||||
// The time at which the most recent packet was acknowledged.
|
||||
Timestamp last_acked_packet_ack_time_ = Timestamp::ms(0);
|
||||
|
||||
bool is_app_limited_ = false;
|
||||
|
||||
// The packet that will be acknowledged after this one will cause the sampler
|
||||
// to exit the app-limited phase.
|
||||
Timestamp end_of_app_limited_phase_ = Timestamp::ms(0);
|
||||
// Bandwidth sampler provides BBR with the bandwidth measurements at
|
||||
// individual points.
|
||||
std::unique_ptr<BandwidthSampler> sampler_;
|
||||
|
||||
// The number of the round trips that have occurred during the connection.
|
||||
BbrRoundTripCount round_trip_count_ = 0;
|
||||
|
||||
// The send time of the most recently sent packet.
|
||||
Timestamp last_send_time_ = Timestamp::ms(0);
|
||||
|
||||
// The packet number of the most recently sent packet.
|
||||
int64_t last_sent_packet_;
|
||||
// Acknowledgement of any packet after |current_round_trip_end_| will cause
|
||||
// the round trip counter to advance.
|
||||
Timestamp current_round_trip_end_ = Timestamp::ms(0);
|
||||
int64_t current_round_trip_end_;
|
||||
|
||||
// The filter that tracks the maximum bandwidth over the multiple recent
|
||||
// round-trips.
|
||||
@ -298,22 +244,22 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
|
||||
// The time this aggregation started and the number of bytes acked during it.
|
||||
rtc::Optional<Timestamp> aggregation_epoch_start_time_;
|
||||
DataSize aggregation_epoch_bytes_ = DataSize::Zero();
|
||||
DataSize aggregation_epoch_bytes_;
|
||||
|
||||
// The number of bytes acknowledged since the last time bytes in flight
|
||||
// dropped below the target window.
|
||||
DataSize bytes_acked_since_queue_drained_ = DataSize::Zero();
|
||||
DataSize bytes_acked_since_queue_drained_;
|
||||
|
||||
// The muliplier for calculating the max amount of extra CWND to add to
|
||||
// compensate for ack aggregation.
|
||||
double max_aggregation_bytes_multiplier_ = 0;
|
||||
double max_aggregation_bytes_multiplier_;
|
||||
|
||||
// Minimum RTT estimate. Automatically expires within 10 seconds (and
|
||||
// triggers PROBE_RTT mode) if no new value is sampled during that period.
|
||||
TimeDelta min_rtt_ = TimeDelta::Zero();
|
||||
TimeDelta last_rtt_ = TimeDelta::Zero();
|
||||
TimeDelta min_rtt_;
|
||||
TimeDelta last_rtt_;
|
||||
// The time at which the current value of |min_rtt_| was assigned.
|
||||
Timestamp min_rtt_timestamp_ = Timestamp::ms(0);
|
||||
Timestamp min_rtt_timestamp_;
|
||||
|
||||
// The maximum allowed number of bytes in flight.
|
||||
DataSize congestion_window_;
|
||||
@ -325,12 +271,12 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
DataSize max_congestion_window_;
|
||||
|
||||
// The current pacing rate of the connection.
|
||||
DataRate pacing_rate_ = DataRate::Zero();
|
||||
DataRate pacing_rate_;
|
||||
|
||||
// The gain currently applied to the pacing rate.
|
||||
double pacing_gain_ = 1;
|
||||
double pacing_gain_;
|
||||
// The gain currently applied to the congestion window.
|
||||
double congestion_window_gain_ = 1;
|
||||
double congestion_window_gain_;
|
||||
|
||||
// The gain used for the congestion window during PROBE_BW. Latched from
|
||||
// quic_bbr_cwnd_gain flag.
|
||||
@ -338,45 +284,88 @@ class BbrNetworkController : public NetworkControllerInterface {
|
||||
// The coefficient by which mean RTT variance is added to the congestion
|
||||
// window. Latched from quic_bbr_rtt_variation_weight flag.
|
||||
const double rtt_variance_weight_;
|
||||
// If true, exit startup if 1RTT has passed with no bandwidth increase and
|
||||
// the connection is in recovery.
|
||||
bool exit_startup_on_loss_ = false;
|
||||
|
||||
// Number of round-trips in PROBE_BW mode, used for determining the current
|
||||
// pacing gain cycle.
|
||||
int cycle_current_offset_ = 0;
|
||||
int cycle_current_offset_;
|
||||
// The time at which the last pacing gain cycle was started.
|
||||
Timestamp last_cycle_start_ = Timestamp::ms(0);
|
||||
Timestamp last_cycle_start_;
|
||||
|
||||
// Indicates whether the connection has reached the full bandwidth mode.
|
||||
bool is_at_full_bandwidth_ = false;
|
||||
bool is_at_full_bandwidth_;
|
||||
// Number of rounds during which there was no significant bandwidth increase.
|
||||
BbrRoundTripCount rounds_without_bandwidth_gain_ = 0;
|
||||
BbrRoundTripCount rounds_without_bandwidth_gain_;
|
||||
// The bandwidth compared to which the increase is measured.
|
||||
DataRate bandwidth_at_last_round_ = DataRate::Zero();
|
||||
DataRate bandwidth_at_last_round_;
|
||||
|
||||
// Time at which PROBE_RTT has to be exited. Setting it to zero indicates
|
||||
// that the time is yet unknown as the number of packets in flight has not
|
||||
// reached the required value.
|
||||
rtc::Optional<Timestamp> exit_probe_rtt_at_;
|
||||
// Indicates whether a round-trip has passed since PROBE_RTT became active.
|
||||
bool probe_rtt_round_passed_ = false;
|
||||
bool probe_rtt_round_passed_;
|
||||
|
||||
// Indicates whether the most recent bandwidth sample was marked as
|
||||
// app-limited.
|
||||
bool last_sample_is_app_limited_ = false;
|
||||
bool last_sample_is_app_limited_;
|
||||
|
||||
// Current state of recovery.
|
||||
RecoveryState recovery_state_ = NOT_IN_RECOVERY;
|
||||
RecoveryState recovery_state_;
|
||||
// Receiving acknowledgement of a packet after |end_recovery_at_| will cause
|
||||
// BBR to exit the recovery mode. A value after epoch indicates at least one
|
||||
// loss has been detected, so it must not be set back to epoch.
|
||||
rtc::Optional<Timestamp> end_recovery_at_;
|
||||
// BBR to exit the recovery mode. An unset value indicates at least one
|
||||
// loss has been detected, so it must not be reset.
|
||||
rtc::Optional<int64_t> end_recovery_at_;
|
||||
// A window used to limit the number of bytes in flight during loss recovery.
|
||||
DataSize recovery_window_;
|
||||
|
||||
bool app_limited_since_last_probe_rtt_ = false;
|
||||
TimeDelta min_rtt_since_last_probe_rtt_ = TimeDelta::PlusInfinity();
|
||||
struct BbrControllerConfig {
|
||||
// Default config based on default QUIC config
|
||||
static BbrControllerConfig DefaultConfig();
|
||||
static BbrControllerConfig ExperimentConfig();
|
||||
|
||||
double probe_bw_pacing_gain_offset;
|
||||
double encoder_rate_gain;
|
||||
double encoder_rate_gain_in_probe_rtt;
|
||||
// RTT delta to determine if startup should be exited due to increased RTT.
|
||||
int64_t exit_startup_rtt_threshold_ms;
|
||||
|
||||
double probe_rtt_congestion_window_gain;
|
||||
|
||||
// Configurable in QUIC BBR:
|
||||
bool exit_startup_on_loss;
|
||||
// The number of RTTs to stay in STARTUP mode. Defaults to 3.
|
||||
BbrRoundTripCount num_startup_rtts;
|
||||
// When true, recovery is rate based rather than congestion window based.
|
||||
bool rate_based_recovery;
|
||||
double max_aggregation_bytes_multiplier;
|
||||
// When true, pace at 1.5x and disable packet conservation in STARTUP.
|
||||
bool slower_startup;
|
||||
// When true, disables packet conservation in STARTUP.
|
||||
bool rate_based_startup;
|
||||
// Used as the initial packet conservation mode when first entering
|
||||
// recovery.
|
||||
RecoveryState initial_conservation_in_startup;
|
||||
// If true, will not exit low gain mode until bytes_in_flight drops below
|
||||
// BDP or it's time for high gain mode.
|
||||
bool fully_drain_queue;
|
||||
|
||||
double max_ack_height_window_multiplier;
|
||||
// If true, use a CWND of 0.75*BDP during probe_rtt instead of 4 packets.
|
||||
bool probe_rtt_based_on_bdp;
|
||||
// If true, skip probe_rtt and update the timestamp of the existing min_rtt
|
||||
// to now if min_rtt over the last cycle is within 12.5% of the current
|
||||
// min_rtt. Even if the min_rtt is 12.5% too low, the 25% gain cycling and
|
||||
// 2x CWND gain should overcome an overly small min_rtt.
|
||||
bool probe_rtt_skipped_if_similar_rtt;
|
||||
// If true, disable PROBE_RTT entirely as long as the connection was
|
||||
// recently app limited.
|
||||
bool probe_rtt_disabled_if_app_limited;
|
||||
};
|
||||
|
||||
BbrControllerConfig config_;
|
||||
|
||||
bool app_limited_since_last_probe_rtt_;
|
||||
TimeDelta min_rtt_since_last_probe_rtt_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(BbrNetworkController);
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user