Skip to content

Commit

Permalink
vegas
Browse files Browse the repository at this point in the history
  • Loading branch information
SoonyangZhang committed Jan 27, 2023
1 parent 05e3967 commit aceee7e
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 9 deletions.
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,7 @@ source /etc/profile
```
# Run example
1 put the file quic-main.cc(scratch) to ns3.33/scratch/
2 set string varible quic_cert_path in quic-main.cc
3 set string varible log_path in quic-main.cc to collect traced data.
```
std::string quic_cert_path("/home/xxx/quiche/utils/data/quic-cert/");
std::string log_path=std::string("/home/xxx/traces/")+algo+"/";
```
3 Run example(BBR)
2 Run example(BBR)
```
source /etc/profile
./waf --run "scratch/quic-main --cc=bbr"
Expand All @@ -73,8 +67,8 @@ data can be found under folder ("/home/xxx/traces/")
copy the file plot-script/data_plot.sh to "/home/xxx/traces/bbr"
plot the results:
```
chmod 777 data_plot.sh
./data_plot.sh
chmod 777 data-plot.sh
./data-plot.sh
```
## bbr
inflight packets:
Expand All @@ -95,3 +89,8 @@ one way delay:
![avatar](https://github.com/SoonyangZhang/quic-on-ns3/blob/main/results/1-copa-owd.png)
goodput:
![avatar](https://github.com/SoonyangZhang/quic-on-ns3/blob/main/results/1-copa-goodput.png)
## vegas
one way delay:
![avatar](https://github.com/SoonyangZhang/quic-on-ns3/blob/main/results/1-vegas-owd.png)
goodput:
![avatar](https://github.com/SoonyangZhang/quic-on-ns3/blob/main/results/1-vegas-goodput.png)
234 changes: 234 additions & 0 deletions quic/model/cc-algo/vegas_sender.cc
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;
}
}
}
}
113 changes: 113 additions & 0 deletions quic/model/cc-algo/vegas_sender.h
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_;

};
}
Loading

0 comments on commit aceee7e

Please sign in to comment.