Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(D)CUBIC, NewReno and Prague refactoring #1818

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions PerfAndStressTest/PerfAndStressTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ namespace PerfAndStressTest
Assert::AreEqual(ret, 0);
}

TEST_METHOD(satellite_dcubic_seed)
{
int ret = satellite_dcubic_seeded_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(satellite_prague_seed)
{
int ret = satellite_prague_seeded_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(bdp_basic)
{
int ret = bdp_basic_test();
Expand Down
6 changes: 3 additions & 3 deletions picoquic/bbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2008,15 +2008,15 @@ void BBRCheckStartupLongRtt(picoquic_bbr_state_t* bbr_state, picoquic_path_t* pa
return;
}

if (picoquic_hystart_test(&bbr_state->rtt_filter, rs->rtt_sample,
if (picoquic_cc_hystart_test(&bbr_state->rtt_filter, rs->rtt_sample,
path_x->pacing.packet_time_microsec, current_time, 0)) {
BBRExitStartupLongRtt(bbr_state, path_x, current_time);
}
else if (rs->ecn_alpha > BBRExcessiveEcnCE) {
BBRExitStartupLongRtt(bbr_state, path_x, current_time);
}
else {
int excessive_loss = picoquic_hystart_loss_volume_test(&bbr_state->rtt_filter, picoquic_congestion_notification_repeat,
int excessive_loss = picoquic_cc_hystart_loss_volume_test(&bbr_state->rtt_filter, picoquic_congestion_notification_repeat,
rs->newly_acked, rs->newly_lost);
if (excessive_loss) {
BBRExitStartupLongRtt(bbr_state, path_x, current_time);
Expand All @@ -2027,7 +2027,7 @@ void BBRCheckStartupLongRtt(picoquic_bbr_state_t* bbr_state, picoquic_path_t* pa
void BBRUpdateStartupLongRtt(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, bbr_per_ack_state_t* rs, uint64_t current_time)
{
if (path_x->last_time_acked_data_frame_sent > path_x->last_sender_limited_time) {
picoquic_hystart_increase(path_x, &bbr_state->rtt_filter, rs->newly_acked);
path_x->cwin += picoquic_cc_slow_start_increase(path_x, rs->newly_acked);
}

uint64_t max_win = path_x->peak_bandwidth_estimate * bbr_state->min_rtt / 1000000;
Expand Down
6 changes: 3 additions & 3 deletions picoquic/bbr1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ static void picoquic_bbr1_notify(
case picoquic_congestion_notification_timeout:
/* Non standard code to react to high rate of packet loss, or timeout loss */
if (ack_state->lost_packet_number >= bbr1_state->congestion_sequence &&
picoquic_hystart_loss_test(&bbr1_state->rtt_filter, notification, ack_state->lost_packet_number, 0.20)) {
picoquic_cc_hystart_loss_test(&bbr1_state->rtt_filter, notification, ack_state->lost_packet_number, 0.20)) {
picoquic_bbr1_notify_congestion(bbr1_state, cnx, path_x, current_time,
(notification == picoquic_congestion_notification_timeout) ? 1 : 0);
}
Expand All @@ -1160,7 +1160,7 @@ static void picoquic_bbr1_notify(
}

if (bbr1_state->state == picoquic_bbr1_alg_startup_long_rtt) {
if (picoquic_hystart_test(&bbr1_state->rtt_filter, (cnx->is_time_stamp_enabled) ? ack_state->one_way_delay : ack_state->rtt_measurement,
if (picoquic_cc_hystart_test(&bbr1_state->rtt_filter, (cnx->is_time_stamp_enabled) ? ack_state->one_way_delay : ack_state->rtt_measurement,
cnx->path[0]->pacing.packet_time_microsec, current_time, cnx->is_time_stamp_enabled)) {
BBR1ExitStartupLongRtt(bbr1_state, path_x, current_time);
}
Expand All @@ -1177,7 +1177,7 @@ static void picoquic_bbr1_notify(
bbr1_state->rt_prop_stamp = current_time;
}
if (path_x->last_time_acked_data_frame_sent > path_x->last_sender_limited_time) {
picoquic_hystart_increase(path_x, &bbr1_state->rtt_filter, bbr1_state->bytes_delivered);
path_x->cwin += picoquic_cc_slow_start_increase(path_x, bbr1_state->bytes_delivered);
}
bbr1_state->bytes_delivered = 0;

Expand Down
96 changes: 87 additions & 9 deletions picoquic/cc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ uint64_t picoquic_cc_get_sequence_number(picoquic_cnx_t* cnx, picoquic_path_t* p
else {
sequence_number = cnx->pkt_ctx[picoquic_packet_context_application].send_sequence;
}

return sequence_number;
}

Expand All @@ -47,6 +48,7 @@ uint64_t picoquic_cc_get_ack_number(picoquic_cnx_t* cnx, picoquic_path_t* path_x
else {
highest_acknowledged = cnx->pkt_ctx[picoquic_packet_context_application].highest_acknowledged;
}

return highest_acknowledged;
}

Expand All @@ -60,16 +62,16 @@ uint64_t picoquic_cc_get_ack_sent_time(picoquic_cnx_t* cnx, picoquic_path_t* pat
else {
latest_time_acknowledged = cnx->pkt_ctx[picoquic_packet_context_application].latest_time_acknowledged;
}

return latest_time_acknowledged;
}


void picoquic_filter_rtt_min_max(picoquic_min_max_rtt_t * rtt_track, uint64_t rtt)
void picoquic_cc_filter_rtt_min_max(picoquic_min_max_rtt_t * rtt_track, uint64_t rtt)
{
int x = rtt_track->sample_current;
int x_max;


rtt_track->samples[x] = rtt;

rtt_track->sample_current = x + 1;
Expand All @@ -92,7 +94,7 @@ void picoquic_filter_rtt_min_max(picoquic_min_max_rtt_t * rtt_track, uint64_t rt
}
}

int picoquic_hystart_loss_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event,
int picoquic_cc_hystart_loss_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event,
uint64_t lost_packet_number, double error_rate_max)
{
int ret = 0;
Expand Down Expand Up @@ -125,7 +127,7 @@ int picoquic_hystart_loss_test(picoquic_min_max_rtt_t* rtt_track, picoquic_conge
return ret;
}

int picoquic_hystart_loss_volume_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event, uint64_t nb_bytes_newly_acked, uint64_t nb_bytes_newly_lost)
int picoquic_cc_hystart_loss_volume_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event, uint64_t nb_bytes_newly_acked, uint64_t nb_bytes_newly_lost)
{
int ret = 0;

Expand Down Expand Up @@ -154,12 +156,12 @@ int picoquic_hystart_loss_volume_test(picoquic_min_max_rtt_t* rtt_track, picoqui
return ret;
}

int picoquic_hystart_test(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt_measurement, uint64_t packet_time, uint64_t current_time, int is_one_way_delay_enabled)
int picoquic_cc_hystart_test(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt_measurement, uint64_t packet_time, uint64_t current_time, int is_one_way_delay_enabled)
{
int ret = 0;

if(current_time > rtt_track->last_rtt_sample_time + 1000) {
picoquic_filter_rtt_min_max(rtt_track, rtt_measurement);
picoquic_cc_filter_rtt_min_max(rtt_track, rtt_measurement);
rtt_track->last_rtt_sample_time = current_time;

if (rtt_track->is_init) {
Expand Down Expand Up @@ -189,9 +191,85 @@ int picoquic_hystart_test(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt_measur
return ret;
}

void picoquic_hystart_increase(picoquic_path_t * path_x, picoquic_min_max_rtt_t* rtt_filter, uint64_t nb_delivered)
uint64_t picoquic_cc_slow_start_increase(picoquic_path_t * path_x, uint64_t nb_delivered) {
/* App limited. */
/* TODO discuss
* path_x->cwin < path_x->bytes_in_transit returns false in cc code
* path_x->cnx->cwin_blocked is set to true
* (path_x->cwin < path_x->bytes_in_transit) != path_x->cnx->cwin_blocked?
*/
if (!path_x->cnx->cwin_blocked) {
return 0;
}

return nb_delivered;
}

uint64_t picoquic_cc_slow_start_increase_ex(picoquic_path_t * path_x, uint64_t nb_delivered, int in_css)
{
path_x->cwin += nb_delivered;
if (in_css) {
/* In consecutive Slow Start. */
return picoquic_cc_slow_start_increase(path_x, nb_delivered / PICOQUIC_HYSTART_PP_CSS_GROWTH_DIVISOR);
}

huitema marked this conversation as resolved.
Show resolved Hide resolved
/* Fallback to traditional Slow Start. */
return picoquic_cc_slow_start_increase(path_x, nb_delivered); /* nb_delivered; */
}

uint64_t picoquic_cc_slow_start_increase_ex2(picoquic_path_t* path_x, uint64_t nb_delivered, int in_css, uint64_t prague_alpha) {
if (prague_alpha != 0) { /* monitoring of ECN */
uint64_t delta = nb_delivered;

/* Calculate delta based on prague_ahpha. */
if (path_x->smoothed_rtt <= PICOQUIC_TARGET_RENO_RTT) {
/* smoothed_rtt <= 100ms */
delta *= (1024 - prague_alpha);
delta /= 1024;
} else {
delta *= path_x->smoothed_rtt;
delta *= (1024 - prague_alpha);
delta /= PICOQUIC_TARGET_RENO_RTT;
delta /= 1024;
}

return picoquic_cc_slow_start_increase_ex(path_x, delta, in_css);
}

/* Fallback to HyStart++ Consecutive Slow Start. */
return picoquic_cc_slow_start_increase_ex(path_x, nb_delivered, in_css);
}

uint64_t picoquic_cc_update_target_cwin_estimation(picoquic_path_t* path_x) {
/* RTT measurements will happen after the bandwidth is estimated. */
uint64_t max_win = path_x->peak_bandwidth_estimate * path_x->smoothed_rtt / 1000000;
uint64_t min_win = max_win / 2;

/* Return increased cwin, if larger than current cwin. */
if (min_win > path_x->cwin) {
return min_win;
}

/* Otherwise, return current cwin. */
return path_x->cwin;
}

hfstco marked this conversation as resolved.
Show resolved Hide resolved
uint64_t picoquic_cc_update_cwin_for_long_rtt(picoquic_path_t * path_x) {
uint64_t min_cwnd;

if (path_x->rtt_min > PICOQUIC_TARGET_SATELLITE_RTT) {
min_cwnd = (uint64_t)((double)PICOQUIC_CWIN_INITIAL * (double)PICOQUIC_TARGET_SATELLITE_RTT / (double)PICOQUIC_TARGET_RENO_RTT);
}
else {
min_cwnd = (uint64_t)((double)PICOQUIC_CWIN_INITIAL * (double)path_x->rtt_min / (double)PICOQUIC_TARGET_RENO_RTT);
}

/* Return increased cwin, if larger than current cwin. */
if (min_cwnd > path_x->cwin) {
return min_cwnd;
}

/* Otherwise, return current cwin. */
return path_x->cwin;
}

uint64_t picoquic_cc_increased_window(picoquic_cnx_t* cnx, uint64_t previous_window)
Expand All @@ -203,7 +281,7 @@ uint64_t picoquic_cc_increased_window(picoquic_cnx_t* cnx, uint64_t previous_win
else {
double w = (double)previous_window;
w /= (double)PICOQUIC_TARGET_RENO_RTT;
w *= (cnx->path[0]->rtt_min > PICOQUIC_TARGET_SATELLITE_RTT)? PICOQUIC_TARGET_SATELLITE_RTT: cnx->path[0]->rtt_min;
w *= (cnx->path[0]->rtt_min > PICOQUIC_TARGET_SATELLITE_RTT) ? PICOQUIC_TARGET_SATELLITE_RTT : (double)cnx->path[0]->rtt_min;
new_window = (uint64_t)w;
hfstco marked this conversation as resolved.
Show resolved Hide resolved
}
return new_window;
Expand Down
55 changes: 50 additions & 5 deletions picoquic/cc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,33 @@ extern "C" {
#define PICOQUIC_SMOOTHED_LOSS_FACTOR (1.0/16.0)
#define PICOQUIC_SMOOTHED_LOSS_THRESHOLD (0.15)

/*
* HyStart++
*/

/* TODO HyStart++ isn't implemented yet! */
/* It is RECOMMENDED that a HyStart++ implementation use the following constants: */
/* MIN_RTT_THRESH = 4 msec
* MAX_RTT_THRESH = 16 msec
* MIN_RTT_DIVISOR = 8
* N_RTT_SAMPLE = 8
* CSS_GROWTH_DIVISOR = 4
* CSS_ROUNDS = 5
* L = infinity if paced, L = 8 if non-paced
*/
/* Take a look at the draft for more information. */
#define PICOQUIC_HYSTART_PP_MIN_RTT_THRESH 4000 /* msec */
#define PICOQUIC_HYSTART_PP_MAX_RTT_THRESH 16000 /* msec */
#define PICOQUIC_HYSTART_PP_MIN_RTT_DIVISOR 8
#define PICOQUIC_HYSTART_PP_N_RTT_SAMPLE 8
#define PICOQUIC_HYSTART_PP_CSS_GROWTH_DIVISOR 4
#define PICOQUIC_HYSTART_PP_CSS_ROUNDS 5
/* Since picoquic is always paced, L is set to infinity (UINT64_MAX).
* Because L is only used to limit the increase function, we don't need it at all. For more information, take a look at
* the picoquic_hystart_pp_increase() function.
*/
/* #define PICOQUIC_HYSTART_PP_L UINT64_MAX */ /* infinity if paced, L = 8 if non-paced */

typedef struct st_picoquic_min_max_rtt_t {
uint64_t last_rtt_sample_time;
uint64_t rtt_filtered_min;
Expand All @@ -52,15 +79,33 @@ uint64_t picoquic_cc_get_ack_number(picoquic_cnx_t* cnx, picoquic_path_t * path_

uint64_t picoquic_cc_get_ack_sent_time(picoquic_cnx_t* cnx, picoquic_path_t* path_x);

void picoquic_filter_rtt_min_max(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt);
void picoquic_cc_filter_rtt_min_max(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt);

int picoquic_cc_hystart_loss_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event, uint64_t lost_packet_number, double error_rate_max);

int picoquic_cc_hystart_loss_volume_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event, uint64_t nb_bytes_newly_acked, uint64_t nb_bytes_newly_lost);

int picoquic_hystart_loss_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event, uint64_t lost_packet_number, double error_rate_max);
int picoquic_cc_hystart_test(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt_measurement, uint64_t packet_time, uint64_t current_time, int is_one_way_delay_enabled);

int picoquic_hystart_loss_volume_test(picoquic_min_max_rtt_t* rtt_track, picoquic_congestion_notification_t event, uint64_t nb_bytes_newly_acked, uint64_t nb_bytes_newly_lost);
/*
* Slow Start
* Returns number of bytes CWIN should be increased.
*/
uint64_t picoquic_cc_slow_start_increase(picoquic_path_t* path_x, uint64_t nb_delivered);

uint64_t picoquic_cc_slow_start_increase_ex(picoquic_path_t* path_x, uint64_t nb_delivered, int in_css);

uint64_t picoquic_cc_slow_start_increase_ex2(picoquic_path_t* path_x, uint64_t nb_delivered, int in_css, uint64_t prague_alpha);

int picoquic_hystart_test(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt_measurement, uint64_t packet_time, uint64_t current_time, int is_one_way_delay_enabled);
/*
* Returns CWIN based on bandwidth estimation if larger than current CWIN. Otherwise, returns current CWIN.
*/
uint64_t picoquic_cc_update_target_cwin_estimation(picoquic_path_t* path_x);

void picoquic_hystart_increase(picoquic_path_t* path_x, picoquic_min_max_rtt_t* rtt_filter, uint64_t nb_delivered);
/*
* Returns CWIN for long RTT connections if larger than current CWIN. Otherwise, returns current CWIN.
*/
uint64_t picoquic_cc_update_cwin_for_long_rtt(picoquic_path_t * path_x);

/* Many congestion control algorithms run a parallel version of new reno in order
* to provide a lower bound estimate of either the congestion window or the
Expand Down
Loading
Loading