-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
05e3967
commit aceee7e
Showing
11 changed files
with
365 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
#include "vegas_sender.h" | ||
#include "../model/ns3-quic-congestion-factory.h" | ||
#include <limits> | ||
#include <stdexcept> | ||
#include <sstream> | ||
#include <string> | ||
|
||
#include "gquiche/quic/core/congestion_control/rtt_stats.h" | ||
#include "gquiche/quic/core/quic_time.h" | ||
#include "gquiche/quic/core/quic_time_accumulator.h" | ||
#include "gquiche/quic/platform/api/quic_bug_tracker.h" | ||
#include "gquiche/quic/platform/api/quic_flag_utils.h" | ||
#include "gquiche/quic/platform/api/quic_flags.h" | ||
#include "gquiche/quic/platform/api/quic_logging.h" | ||
|
||
namespace quic{ | ||
namespace{ | ||
const QuicByteCount kDefaultMinimumCongestionWindow = 4 *kDefaultTCPMSS; | ||
const QuicByteCount kAlphaCongestionWindow=2*kDefaultTCPMSS; | ||
const QuicByteCount kBetaCongestionWindow=4*kDefaultTCPMSS; | ||
const QuicByteCount kGammaCongestionWindow=1*kDefaultTCPMSS; | ||
const QuicTime::Delta kMinRTTWindowLength = QuicTime::Delta::FromSeconds(10); | ||
} | ||
|
||
VegasSender::VegasSender(QuicTime now, | ||
const RttStats* rtt_stats, | ||
const QuicUnackedPacketMap* unacked_packets, | ||
QuicPacketCount initial_tcp_congestion_window, | ||
QuicPacketCount max_tcp_congestion_window, | ||
QuicRandom* random, | ||
QuicConnectionStats* stats): | ||
rtt_stats_(rtt_stats), | ||
unacked_packets_(unacked_packets), | ||
random_(random), | ||
stats_(stats), | ||
congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), | ||
initial_congestion_window_(initial_tcp_congestion_window *kDefaultTCPMSS), | ||
max_congestion_window_(max_tcp_congestion_window * kDefaultTCPMSS), | ||
min_congestion_window_(kDefaultMinimumCongestionWindow), | ||
slowstart_threshold_(max_tcp_congestion_window * kDefaultTCPMSS), | ||
pacing_rate_(QuicBandwidth::Zero()), | ||
baseRTTFilter_(kMinRTTWindowLength.ToMicroseconds(),QuicTime::Delta::Zero(),0), | ||
min_rtt_(QuicTime::Delta::Infinite()), | ||
rtt_count_(0), | ||
num_acked_packets_(0), | ||
vegas_mode_(true){ | ||
if (stats_) { | ||
// Clear some startup stats if |stats_| has been used by another sender, | ||
// which happens e.g. when QuicConnection switch send algorithms. | ||
stats_->slowstart_count = 0; | ||
stats_->slowstart_duration = QuicTimeAccumulator(); | ||
} | ||
} | ||
VegasSender::~VegasSender(){} | ||
|
||
bool VegasSender::InSlowStart() const{ | ||
return GetCongestionWindow() < GetSlowStartThreshold(); | ||
} | ||
bool VegasSender::InRecovery() const{ | ||
return largest_acked_packet_number_.IsInitialized() && | ||
largest_sent_at_last_cutback_.IsInitialized() && | ||
largest_acked_packet_number_ <= largest_sent_at_last_cutback_; | ||
} | ||
bool VegasSender::ShouldSendProbingPacket() const{ | ||
return false; | ||
} | ||
void VegasSender::SetInitialCongestionWindowInPackets(QuicPacketCount congestion_window){ | ||
if(InSlowStart()){ | ||
initial_congestion_window_ = congestion_window * kDefaultTCPMSS; | ||
congestion_window_ = congestion_window * kDefaultTCPMSS; | ||
} | ||
} | ||
|
||
void VegasSender::OnCongestionEvent(bool rtt_updated, | ||
QuicByteCount prior_in_flight, | ||
QuicTime event_time, | ||
const AckedPacketVector& acked_packets, | ||
const LostPacketVector& lost_packets){ | ||
if(acked_packets.size()>0){ | ||
auto vrtt=rtt_stats_->latest_rtt()+QuicTime::Delta::FromMicroseconds(1); | ||
QuicTime::Delta wall_time=event_time-QuicTime::Zero(); | ||
baseRTTFilter_.Update(vrtt,wall_time.ToMicroseconds()); | ||
if(min_rtt_>vrtt){ | ||
min_rtt_=vrtt; | ||
} | ||
rtt_count_++; | ||
} | ||
bool before=InRecovery(); | ||
|
||
for (const LostPacket& lost_packet : lost_packets) { | ||
OnPacketLost(lost_packet.packet_number, lost_packet.bytes_lost, | ||
prior_in_flight); | ||
} | ||
for (const AckedPacket& acked_packet : acked_packets) { | ||
OnPacketAcked(acked_packet.packet_number, acked_packet.bytes_acked, | ||
prior_in_flight, event_time); | ||
} | ||
if(InRecovery()!=before){ | ||
if(InRecovery()){ | ||
//vegas_disable | ||
vegas_mode_=false; | ||
}else{ | ||
//vegas_enable | ||
vegas_mode_=true; | ||
beg_send_next_=largest_sent_packet_number_; | ||
min_rtt_=QuicTime::Delta::Infinite(); | ||
rtt_count_=0; | ||
} | ||
} | ||
} | ||
void VegasSender::OnPacketSent(QuicTime sent_time, | ||
QuicByteCount bytes_in_flight, | ||
QuicPacketNumber packet_number, | ||
QuicByteCount bytes, | ||
HasRetransmittableData is_retransmittable){ | ||
QUICHE_DCHECK(!largest_sent_packet_number_.IsInitialized() || | ||
largest_sent_packet_number_ < packet_number); | ||
largest_sent_packet_number_ = packet_number; | ||
if(!beg_send_next_.IsInitialized()){ | ||
beg_send_next_=largest_sent_packet_number_; | ||
} | ||
} | ||
void VegasSender::OnRetransmissionTimeout(bool /*packets_retransmitted*/){ | ||
|
||
} | ||
bool VegasSender::CanSend(QuicByteCount bytes_in_flight){ | ||
return bytes_in_flight<GetCongestionWindow(); | ||
} | ||
QuicBandwidth VegasSender::PacingRate(QuicByteCount bytes_in_flight) const{ | ||
QuicTime::Delta srtt = rtt_stats_->SmoothedOrInitialRtt(); | ||
const QuicBandwidth bandwidth = | ||
QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt); | ||
return bandwidth * (InSlowStart() ? 2 : (InRecovery() ? 1 : 1.25)); | ||
} | ||
QuicBandwidth VegasSender::BandwidthEstimate() const { | ||
QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); | ||
if (srtt.IsZero()) { | ||
// If we haven't measured an rtt, the bandwidth estimate is unknown. | ||
return QuicBandwidth::Zero(); | ||
} | ||
return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt); | ||
} | ||
QuicByteCount VegasSender::GetCongestionWindow() const { | ||
return congestion_window_; | ||
} | ||
QuicByteCount VegasSender::GetSlowStartThreshold() const{ | ||
return slowstart_threshold_; | ||
} | ||
CongestionControlType VegasSender::GetCongestionControlType() const{ | ||
return (CongestionControlType)kVegas; | ||
} | ||
std::string VegasSender::GetDebugState() const{ | ||
return "copa"; | ||
} | ||
void VegasSender::OnPacketLost(QuicPacketNumber packet_number, | ||
QuicByteCount lost_bytes, | ||
QuicByteCount prior_in_flight){ | ||
if (largest_sent_at_last_cutback_.IsInitialized() &&packet_number <= largest_sent_at_last_cutback_) { | ||
return; | ||
} | ||
congestion_window_=congestion_window_/2; | ||
congestion_window_=std::max(congestion_window_,min_congestion_window_); | ||
slowstart_threshold_ = congestion_window_; | ||
largest_sent_at_last_cutback_=largest_sent_packet_number_; | ||
num_acked_packets_ = 0; | ||
} | ||
void VegasSender::OnPacketAcked(QuicPacketNumber acked_packet_number, | ||
QuicByteCount acked_bytes, | ||
QuicByteCount prior_in_flight, | ||
QuicTime event_time){ | ||
largest_acked_packet_number_.UpdateMax(acked_packet_number); | ||
if(!vegas_mode_){ | ||
//reno mode | ||
IncreaseCongestionWindowAsReno(); | ||
return ; | ||
} | ||
QUICHE_CHECK(beg_send_next_.IsInitialized()); | ||
if(acked_packet_number>=beg_send_next_){ | ||
beg_send_next_=largest_sent_packet_number_; | ||
if(rtt_count_<=2){ | ||
IncreaseCongestionWindowAsReno(); | ||
}else{ | ||
QuicTime::Delta base_rtt=baseRTTFilter_.GetBest(); | ||
QuicByteCount target_cwnd=congestion_window_*base_rtt.ToMicroseconds()/min_rtt_.ToMicroseconds(); | ||
target_cwnd=((target_cwnd+kDefaultTCPMSS-1)/kDefaultTCPMSS)*kDefaultTCPMSS; | ||
QUICHE_CHECK(min_rtt_>=base_rtt); | ||
QuicByteCount diff=congestion_window_*(min_rtt_.ToMicroseconds()-base_rtt.ToMicroseconds())/base_rtt.ToMicroseconds(); | ||
if(diff>kGammaCongestionWindow&&InSlowStart()){ | ||
/* Going too fast. Time to slow down | ||
* and switch to congestion avoidance. | ||
*/ | ||
|
||
/* Set cwnd to match the actual rate | ||
* exactly: | ||
* cwnd = (actual rate) * baseRTT | ||
* Then we add 1 because the integer | ||
* truncation robs us of full link | ||
* utilization. | ||
*/ | ||
congestion_window_=std::min(congestion_window_,target_cwnd); | ||
slowstart_threshold_=congestion_window_; | ||
}else if(InSlowStart()){ | ||
congestion_window_ += kDefaultTCPMSS; | ||
}else{ | ||
if(diff>kBetaCongestionWindow){ | ||
if(congestion_window_>min_congestion_window_){ | ||
congestion_window_-=kDefaultTCPMSS; | ||
} | ||
}else if(diff<kAlphaCongestionWindow){ | ||
congestion_window_+=kDefaultTCPMSS; | ||
}else{ | ||
//hold | ||
} | ||
} | ||
} | ||
min_rtt_=QuicTime::Delta::Infinite(); | ||
rtt_count_=0; | ||
}else if(InSlowStart()){ | ||
congestion_window_ += kDefaultTCPMSS; | ||
} | ||
congestion_window_=std::max(congestion_window_,min_congestion_window_); | ||
} | ||
void VegasSender::IncreaseCongestionWindowAsReno(){ | ||
if(InSlowStart()){ | ||
congestion_window_ += kDefaultTCPMSS; | ||
}else{ | ||
++num_acked_packets_; | ||
if (num_acked_packets_*kDefaultTCPMSS>=congestion_window_) { | ||
congestion_window_ += kDefaultTCPMSS; | ||
num_acked_packets_ = 0; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#pragma once | ||
#include <cstdint> | ||
#include <ostream> | ||
#include <string> | ||
|
||
#include "gquiche/quic/core/congestion_control/bandwidth_sampler.h" | ||
#include "gquiche/quic/core/congestion_control/send_algorithm_interface.h" | ||
#include "gquiche/quic/core/congestion_control/windowed_filter.h" | ||
#include "gquiche/quic/core/crypto/quic_random.h" | ||
#include "gquiche/quic/core/quic_bandwidth.h" | ||
#include "gquiche/quic/core/quic_packet_number.h" | ||
#include "gquiche/quic/core/quic_packets.h" | ||
#include "gquiche/quic/core/quic_time.h" | ||
#include "gquiche/quic/core/quic_unacked_packet_map.h" | ||
#include "gquiche/quic/platform/api/quic_export.h" | ||
#include "gquiche/quic/platform/api/quic_flags.h" | ||
namespace quic{ | ||
class RttStats; | ||
QUIC_EXPORT_PRIVATE class VegasSender:public SendAlgorithmInterface{ | ||
public: | ||
VegasSender(QuicTime now, | ||
const RttStats* rtt_stats, | ||
const QuicUnackedPacketMap* unacked_packets, | ||
QuicPacketCount initial_tcp_congestion_window, | ||
QuicPacketCount max_tcp_congestion_window, | ||
QuicRandom* random, | ||
QuicConnectionStats* stats); | ||
VegasSender(const VegasSender&) = delete; | ||
VegasSender& operator=(const VegasSender&) = delete; | ||
~VegasSender() override; | ||
|
||
// Start implementation of SendAlgorithmInterface. | ||
bool InSlowStart() const override; | ||
bool InRecovery() const override; | ||
bool ShouldSendProbingPacket() const override; | ||
|
||
void SetFromConfig(const QuicConfig& config, | ||
Perspective perspective) override{} | ||
void ApplyConnectionOptions(const QuicTagVector& connection_options) override{} | ||
|
||
void AdjustNetworkParameters(const NetworkParams& params) override{} | ||
void SetInitialCongestionWindowInPackets( | ||
QuicPacketCount congestion_window) override; | ||
void OnCongestionEvent(bool rtt_updated, | ||
QuicByteCount prior_in_flight, | ||
QuicTime event_time, | ||
const AckedPacketVector& acked_packets, | ||
const LostPacketVector& lost_packets) override; | ||
void OnPacketSent(QuicTime sent_time, | ||
QuicByteCount bytes_in_flight, | ||
QuicPacketNumber packet_number, | ||
QuicByteCount bytes, | ||
HasRetransmittableData is_retransmittable) override; | ||
void OnPacketNeutered(QuicPacketNumber packet_number) override{} | ||
void OnRetransmissionTimeout(bool /*packets_retransmitted*/) override; | ||
void OnConnectionMigration() override {} | ||
bool CanSend(QuicByteCount bytes_in_flight) override; | ||
QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override; | ||
QuicBandwidth BandwidthEstimate() const override; | ||
QuicByteCount GetCongestionWindow() const override; | ||
QuicByteCount GetSlowStartThreshold() const override; | ||
CongestionControlType GetCongestionControlType() const override; | ||
std::string GetDebugState() const override; | ||
void OnApplicationLimited(QuicByteCount bytes_in_flight) override{} | ||
void PopulateConnectionStats(QuicConnectionStats* stats) const override{} | ||
// End implementation of SendAlgorithmInterface. | ||
|
||
private: | ||
|
||
void OnPacketLost(QuicPacketNumber largest_loss, | ||
QuicByteCount lost_bytes, | ||
QuicByteCount prior_in_flight); | ||
void OnPacketAcked(QuicPacketNumber acked_packet_number, | ||
QuicByteCount acked_bytes, | ||
QuicByteCount prior_in_flight, | ||
QuicTime event_time); | ||
void IncreaseCongestionWindowAsReno(); | ||
// Determines the appropriate pacing rate for the connection. | ||
void CalculatePacingRate(); | ||
|
||
const RttStats* rtt_stats_; | ||
const QuicUnackedPacketMap* unacked_packets_; | ||
QuicRandom* random_; | ||
QuicConnectionStats* stats_; | ||
|
||
// Track the largest packet that has been sent. | ||
QuicPacketNumber largest_sent_packet_number_; | ||
// Track the largest packet that has been acked. | ||
QuicPacketNumber largest_acked_packet_number_; | ||
// Track the largest packet number outstanding when a CWND cutback occurs. | ||
QuicPacketNumber largest_sent_at_last_cutback_; | ||
// The maximum allowed number of bytes in flight. | ||
QuicByteCount congestion_window_; | ||
// The initial value of the |congestion_window_|. | ||
QuicByteCount initial_congestion_window_; | ||
// The largest value the |congestion_window_| can achieve. | ||
QuicByteCount max_congestion_window_; | ||
// The smallest value the |congestion_window_| can achieve. | ||
QuicByteCount min_congestion_window_; | ||
// Slow start congestion window in bytes, aka ssthresh. | ||
QuicByteCount slowstart_threshold_; | ||
// The current pacing rate of the connection. | ||
QuicBandwidth pacing_rate_; | ||
using RTTFilter=WindowedFilter<QuicTime::Delta,MinFilter<QuicTime::Delta>,uint64_t,uint64_t> ; | ||
RTTFilter baseRTTFilter_; | ||
QuicTime::Delta min_rtt_; | ||
int32_t rtt_count_; | ||
QuicPacketNumber beg_send_next_; | ||
uint64_t num_acked_packets_; | ||
bool vegas_mode_; | ||
|
||
}; | ||
} |
Oops, something went wrong.