Skip to content

Commit

Permalink
Add Startup Resume state
Browse files Browse the repository at this point in the history
  • Loading branch information
huitema committed Feb 9, 2024
1 parent d0042bc commit 857ddc5
Showing 1 changed file with 87 additions and 14 deletions.
101 changes: 87 additions & 14 deletions picoquic/bbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ typedef enum {
picoquic_bbr_alg_probe_bw_refill,
picoquic_bbr_alg_probe_bw_up,
picoquic_bbr_alg_probe_rtt,
picoquic_bbr_alg_startup_long_rtt
picoquic_bbr_alg_startup_long_rtt,
picoquic_bbr_alg_startup_resume
} picoquic_bbr_alg_state_t;

typedef enum {
Expand All @@ -89,8 +90,9 @@ typedef enum {

/* Constants in BBRv3 */
#define BBRPacingMarginPercent 1 /* discount factor of 1% used to scale BBR.bw to produce BBR.pacing_rate */
#define BBRStartupPacingGain 2.77 /* constant, 4*ln(2), approx 2.77 */
#define BBRStartupCwndGain 2.0 /* constant */




#define BBRLossThresh 0.2 /* maximum tolerated packet loss (default: 20%) */
#define BBRBeta 0.7 /* Multiplicative decrease on packet loss (default: 0.7) */
Expand All @@ -105,6 +107,14 @@ typedef enum {
#define BBRProbeRTTDuration 200000 /* 200msec, 200000 microsecs */
#define BBRProbeRTTInterval 5000000 /* 5 seconds */

#define BBRStartupPacingGain 2.77 /* constant, 4*ln(2), approx 2.77 */
#define BBRStartupCwndGain 2.0 /* constant */
#define BBRStartupIncreaseThreshold 1.25

#define BBRStartupResumePacingGain 1.25 /* arbitrary */
#define BBRStartupResumeCwndGain 1.25 /* arbitrary */
#define BBRStartupResumeIncreaseThreshold 1.125

#define BBRProbeBwDownPacingGain 0.9
#define BBRProbeBwDownCwndGain 2.0
#define BBRProbeBwCruisePacingGain 1.0
Expand All @@ -113,6 +123,7 @@ typedef enum {
#define BBRProbeBwRefillCwndGain 2.0
#define BBRProbeBwUpPacingGain 1.25
#define BBRProbeBwUpCwndGain 2.25

#define BBRMinRttMarginPercent 5 /* Margin factor of 20% for avoiding firing RTT Probe too often */
#define BBRLongRttThreshold 250000

Expand Down Expand Up @@ -266,6 +277,7 @@ static void BBRStartProbeBW_CRUISE(picoquic_bbr_state_t* bbr_state);
static void BBRStartProbeBW_REFILL(picoquic_bbr_state_t* bbr_state, picoquic_path_t * path_x);
static void BBREnterStartup(picoquic_bbr_state_t* bbr_state);
static void BBRReEnterStartup(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time);
static void BBRCheckStartupHighLoss(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, bbr_per_ack_state_t* rs);
static void BBRUpdateRound(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x);
static void BBRStartRound(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x);
static void BBRSetRsFromAckState(picoquic_path_t* path_x, picoquic_per_ack_state_t* ack_state, bbr_per_ack_state_t* rs);
Expand Down Expand Up @@ -497,8 +509,8 @@ static void BBRSetCwnd(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x,
path_x->cwin = bbr_state->max_inflight;
}
}
else if (bbr_state->state == picoquic_bbr_alg_startup &&
bbr_state->bdp_seed > 2*path_x->cwin) {
else if (bbr_state->state == picoquic_bbr_alg_startup_resume &&
bbr_state->bdp_seed > path_x->cwin) {
path_x->cwin = bbr_state->bdp_seed;
}
else if (path_x->cwin < bbr_state->max_inflight || path_x->delivered < PICOQUIC_CWIN_INITIAL) {
Expand Down Expand Up @@ -714,7 +726,7 @@ static void BBRSetPacingRateWithGain(picoquic_bbr_state_t* bbr_state, double pac
{
double rate = pacing_gain * ((double)(bbr_state->bw * (100 - BBRPacingMarginPercent))) / (double)100;

if (bbr_state->state == picoquic_bbr_alg_startup &&
if (bbr_state->state == picoquic_bbr_alg_startup_resume &&
!bbr_state->filled_pipe &&
bbr_state->bdp_seed > 0) {
double bdp_rate = (((double)bbr_state->bdp_seed*1000000.0) / (double)bbr_state->min_rtt);
Expand Down Expand Up @@ -1481,6 +1493,59 @@ static void BBRCheckDrain(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path
}
/* End of drain specific algorithms */

/* Startup extension to support careful resume */
static void BBRCheckStartupFullBandwidthGeneric(picoquic_bbr_state_t* bbr_state,
bbr_per_ack_state_t * rs, double threshold)
{
if (bbr_state->filled_pipe ||
!bbr_state->round_start || rs->is_app_limited) {
return; /* no need to check for a full pipe now */
}

if ((double)bbr_state->max_bw >= threshold*((double)bbr_state->full_bw)) {
/* still growing? */
bbr_state->full_bw = bbr_state->max_bw; /* record new baseline level */
bbr_state->full_bw_count = 0;
return;
}
bbr_state->full_bw_count++; /* another round w/o much growth */
if (bbr_state->full_bw_count >= 3) {
bbr_state->filled_pipe = 1;
}
}

static void BBRCheckEnterStartupResume(picoquic_bbr_state_t* bbr_state)
{
/* This code is called either when the "bdp seed" is set, or
* upon "Enter Startup"
*/
bbr_state->state = picoquic_bbr_alg_startup_resume;
bbr_state->pacing_gain = BBRStartupResumePacingGain;
bbr_state->cwnd_gain = BBRStartupResumeCwndGain;
}

static void BBRCheckStartupResume(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, bbr_per_ack_state_t* rs, uint64_t current_time)
{
if (bbr_state->state == picoquic_bbr_alg_startup_resume) {
BBRCheckStartupHighLoss(bbr_state, path_x, rs);
BBRCheckStartupFullBandwidthGeneric(bbr_state, rs, BBRStartupResumeIncreaseThreshold);
if (bbr_state->filled_pipe) {
if (bbr_state->full_bw_count > 0) {
bbr_state->probe_probe_bw_quickly = 1;
bbr_state->full_bw_count = 0;
}
BBREnterDrain(bbr_state, path_x, current_time);
}
}
}

static void BBREnterStartupResume(picoquic_bbr_state_t* bbr_state)
{
bbr_state->state = picoquic_bbr_alg_startup_resume;
bbr_state->pacing_gain = BBRStartupResumePacingGain;
bbr_state->cwnd_gain = BBRStartupResumeCwndGain;
}

/* Startup specific processes for BBRv3 */
static void BBRCheckStartupHighLoss(picoquic_bbr_state_t* bbr_state, picoquic_path_t * path_x, bbr_per_ack_state_t * rs)
{
Expand Down Expand Up @@ -1522,16 +1587,18 @@ static void BBRCheckStartupFullBandwidth(picoquic_bbr_state_t* bbr_state,
static void BBRCheckStartupDone(picoquic_bbr_state_t* bbr_state,
picoquic_path_t * path_x, bbr_per_ack_state_t * rs, uint64_t current_time)
{
BBRCheckStartupFullBandwidth(bbr_state, rs);
BBRCheckStartupHighLoss(bbr_state, path_x, rs);
if (bbr_state->state == picoquic_bbr_alg_startup) {
BBRCheckStartupFullBandwidth(bbr_state, rs);
BBRCheckStartupHighLoss(bbr_state, path_x, rs);

if (bbr_state->state == picoquic_bbr_alg_startup &&
bbr_state->filled_pipe) {
if (bbr_state->full_bw_count > 0) {
bbr_state->probe_probe_bw_quickly = 1;
bbr_state->full_bw_count = 0;
if (bbr_state->state == picoquic_bbr_alg_startup &&
bbr_state->filled_pipe) {
if (bbr_state->full_bw_count > 0) {
bbr_state->probe_probe_bw_quickly = 1;
bbr_state->full_bw_count = 0;
}
BBREnterDrain(bbr_state, path_x, current_time);
}
BBREnterDrain(bbr_state, path_x, current_time);
}
}

Expand Down Expand Up @@ -1645,6 +1712,11 @@ void BBRUpdateStartupLongRtt(picoquic_bbr_state_t* bbr_state, picoquic_path_t* p
void BBRSetBdpSeed(picoquic_bbr_state_t* bbr_state, uint64_t bdp_seed)
{
bbr_state->bdp_seed = bdp_seed;
if (bbr_state->state == picoquic_bbr_alg_startup &&
bbr_state->bdp_seed > bbr_state->max_bw &&
bbr_state->min_rtt <= BBRLongRttThreshold) {
BBRCheckEnterStartupResume(bbr_state);
}
}

/* BBRv3 per loss steps.
Expand Down Expand Up @@ -1718,6 +1790,7 @@ static void BBRUpdateModelAndState(picoquic_bbr_state_t* bbr_state, picoquic_pat
BBRUpdateCongestionSignals(bbr_state, path_x, rs);
BBRUpdateACKAggregation(bbr_state, path_x, rs, current_time);
BBRCheckStartupLongRtt(bbr_state, path_x, rs, current_time);
BBRCheckStartupResume(bbr_state, path_x, rs, current_time);
BBRCheckStartupDone(bbr_state, path_x, rs, current_time);
BBRCheckRecovery(bbr_state, path_x, rs, current_time);
BBRCheckDrain(bbr_state, path_x, current_time);
Expand Down

0 comments on commit 857ddc5

Please sign in to comment.