Skip to content

Commit 965b8ad

Browse files
authored
Merge pull request #1856 from private-octopus/modular-cc-algorithms
Make addition of CC algorithms modular
2 parents d2a4f98 + ef7af05 commit 965b8ad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+723
-153
lines changed

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ else()
88
endif()
99

1010
project(picoquic
11-
VERSION 1.1.32.0
11+
VERSION 1.1.33.0
1212
DESCRIPTION "picoquic library"
1313
LANGUAGES C CXX)
1414

@@ -102,6 +102,7 @@ set(PICOQUIC_LIBRARY_FILES
102102
picoquic/port_blocking.c
103103
picoquic/prague.c
104104
picoquic/quicctx.c
105+
picoquic/register_all_cc_algorithms.c
105106
picoquic/sacks.c
106107
picoquic/sender.c
107108
picoquic/sim_link.c
@@ -126,6 +127,12 @@ set(PICOQUIC_CORE_HEADERS
126127
picoquic/picoquic_binlog.h
127128
picoquic/picoquic_config.h
128129
picoquic/picoquic_lb.h
130+
picoquic/picoquic_newreno.h
131+
picoquic/picoquic_cubic.h
132+
picoquic/picoquic_bbr.h
133+
picoquic/picoquic_bbr1.h
134+
picoquic/picoquic_fastcc.h
135+
picoquic/picoquic_prague.h
129136
picoquic/siphash.h)
130137

131138
set(LOGLIB_LIBRARY_FILES

picoquic/bbr.c

Lines changed: 143 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "picoquic_utils.h"
2727

2828
#ifdef BBRExperiment
29-
#define BBRExpGate(ctx, test, action) { if (ctx->exp_flags.test) action; }
29+
#define BBRExpGate(ctx, test, action) { if (!ctx->exp_flags.test) action; }
3030
#define BBRExpTest(ctx, test) ( (ctx)->exp_flags.test )
3131
#else
3232
#define BBRExpGate(ctx, test, action) {}
@@ -141,6 +141,22 @@ typedef enum {
141141

142142
#define BBRExcessiveEcnCE 0.2
143143

144+
/* Temporary code, do define a set of BBR flags that
145+
* turn on and off individual extensions. We want to use that
146+
* to do "before/after" measurements.
147+
*/
148+
#define BBRExperiment on
149+
#ifdef BBRExperiment
150+
/* Control flags for BBR improvements */
151+
typedef struct st_bbr_exp {
152+
unsigned int do_early_exit : 1;
153+
unsigned int do_rapid_start : 1;
154+
unsigned int do_handle_suspension : 1;
155+
unsigned int do_control_lost : 1;
156+
unsigned int do_exit_probeBW_up_on_delay : 1;
157+
unsigned int do_enter_probeBW_after_limited : 1;
158+
} bbr_exp;
159+
#endif
144160
typedef struct st_picoquic_bbr_state_t {
145161
/* Algorithm state: */
146162
picoquic_bbr_alg_state_t state;
@@ -260,13 +276,13 @@ typedef struct st_picoquic_bbr_state_t {
260276
unsigned int probe_bdp_seed;
261277

262278
/* Experimental extensions, may or maynot be a good idea. */
279+
char const* option_string;
263280
uint64_t wifi_shadow_rtt; /* Shadow RTT used for wifi connections. */
264281
double quantum_ratio; /* allow application to use a different default than 0.1% of bandwidth (or 1ms of traffic) */
265282
#ifdef BBRExperiment
266283
/* Control flags for BBR improvements */
267284
bbr_exp exp_flags;
268285
#endif
269-
270286
} picoquic_bbr_state_t;
271287

272288
/* BBR v3 assumes that there is state associated with the acknowledgements.
@@ -422,13 +438,132 @@ static void BBRInitFullPipe(picoquic_bbr_state_t* bbr_state)
422438
bbr_state->full_bw_count = 0;
423439
}
424440

441+
/* Initialization of optional variables defined in text string
442+
* Syntax:
443+
* - Single letter options that control the "BBR Experiment"
444+
* E: do_early_exit
445+
* R: do_rapid_start
446+
* H: do_handle_suspension
447+
* L: do_control_lost
448+
* D: do_exit_probeBW_up_on_delay
449+
* A: do_enter_probeBW_after_limited
450+
* - Complex options, ends with ':'
451+
* T999999999: wifi_shadow_rtt, microseconds
452+
* Q99999.999: quantum_ratio, %
453+
*
454+
* The "BBR Experiment" is an attempt to improve behavior of BBR for
455+
* realtime support on some networks, mostly Wi-Fi. The experiment was a
456+
* success, and the corresponding support is on by default, The individual
457+
* option flags can be used to turn off some parts of the experiment,
458+
* for example when doing before/after measurements.
459+
*/
460+
static void BBRSetOptions(picoquic_bbr_state_t* bbr_state)
461+
{
462+
const char* x = bbr_state->option_string;
463+
#ifdef BBRExperiment
464+
bbr_state->exp_flags.do_early_exit = 1;
465+
bbr_state->exp_flags.do_rapid_start = 1;
466+
bbr_state->exp_flags.do_handle_suspension = 1;
467+
bbr_state->exp_flags.do_control_lost = 1;
468+
bbr_state->exp_flags.do_exit_probeBW_up_on_delay = 1;
469+
bbr_state->exp_flags.do_enter_probeBW_after_limited = 1;
470+
#endif
471+
472+
if (x != NULL) {
473+
char c;
474+
while ((c = *x) != 0) {
475+
x++;
476+
switch (c) {
477+
#ifdef BBRExperiment
478+
case 'E':
479+
bbr_state->exp_flags.do_early_exit = 0;
480+
break;
481+
case 'R':
482+
bbr_state->exp_flags.do_rapid_start = 0;
483+
break;
484+
case 'H':
485+
bbr_state->exp_flags.do_handle_suspension = 0;
486+
break;
487+
case 'L':
488+
bbr_state->exp_flags.do_control_lost = 0;
489+
break;
490+
case 'D':
491+
bbr_state->exp_flags.do_exit_probeBW_up_on_delay = 0;
492+
break;
493+
case 'A':
494+
bbr_state->exp_flags.do_enter_probeBW_after_limited = 0;
495+
break;
496+
#endif
497+
case 'T': {
498+
/* Reading digits into an uint64_t */
499+
uint64_t u = 0;
500+
while ((c = *x) != 0) {
501+
if (c >= '0' && c <= '9') {
502+
u *= 10;
503+
u += c - '0';
504+
x++;
505+
}
506+
else {
507+
break;
508+
}
509+
}
510+
bbr_state->wifi_shadow_rtt = u;
511+
break;
512+
}
513+
case 'Q': {
514+
/* Reading digits ad one dot into a double */
515+
while ((c = *x) != 0) {
516+
double d = 0;
517+
double div = 1.0;
518+
int dotted = 0;
519+
while ((c = *x) != 0) {
520+
if (c >= '0' && c <= '9') {
521+
if (!dotted) {
522+
d *= 10;
523+
d += c - '0';
524+
}
525+
else {
526+
div /= 10.0;
527+
d += div * (c - '0');
528+
}
529+
x++;
530+
}
531+
else if (c == '.') {
532+
if (dotted) {
533+
break;
534+
}
535+
else {
536+
dotted = 1;
537+
x++;
538+
}
539+
}
540+
else {
541+
break;
542+
}
543+
}
544+
bbr_state->quantum_ratio = d;
545+
break;
546+
}
547+
}
548+
case ':':
549+
/* Ignore */
550+
break;
551+
default:
552+
break;
553+
}
554+
}
555+
}
556+
}
557+
425558
/* Initialization of the BBR state */
426-
static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time)
559+
static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time, char const * option_string)
427560
{
428561
/* TODO:
429562
init_windowed_max_filter(filter = BBR.MaxBwFilter, value = 0, time = 0)
430563
*/
431564
memset(bbr_state, 0, sizeof(picoquic_bbr_state_t));
565+
bbr_state->option_string = option_string;
566+
432567
BBRInitRandom(bbr_state, path_x, current_time);
433568
/* If RTT was already sampled, use it, other wise set min RTT to infinity */
434569
if (path_x->smoothed_rtt == PICOQUIC_INITIAL_RTT
@@ -446,15 +581,8 @@ static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x,
446581
bbr_state->min_rtt_stamp = current_time;
447582
bbr_state->extra_acked_interval_start = current_time;
448583
bbr_state->extra_acked_delivered = 0;
449-
/* Support for the wifi_shadow_rtt hack */
450-
bbr_state->wifi_shadow_rtt = path_x->cnx->quic->wifi_shadow_rtt;
451-
452-
#ifdef BBRExperiment
453-
/* Support for BBR Experiment */
454-
bbr_state->exp_flags = path_x->cnx->quic->bbr_exp_flags;
455-
#endif
456-
/* Support for experimenting with the send_quantum ratio */
457-
bbr_state->quantum_ratio = path_x->cnx->quic->bbr_quantum_ratio;
584+
/* Support for the experimental options */
585+
BBRSetOptions(bbr_state);
458586
if (bbr_state->quantum_ratio == 0) {
459587
bbr_state->quantum_ratio = 0.001;
460588
}
@@ -469,17 +597,17 @@ static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x,
469597

470598
static void picoquic_bbr_reset(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time)
471599
{
472-
BBROnInit(bbr_state, path_x, current_time);
600+
BBROnInit(bbr_state, path_x, current_time, bbr_state->option_string);
473601
}
474602

475-
static void picoquic_bbr_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
603+
static void picoquic_bbr_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
476604
{
477605
/* Initialize the state of the congestion control algorithm */
478606
picoquic_bbr_state_t* bbr_state = (picoquic_bbr_state_t*)malloc(sizeof(picoquic_bbr_state_t));
479607

480608
path_x->congestion_alg_state = (void*)bbr_state;
481609
if (bbr_state != NULL) {
482-
BBROnInit(bbr_state, path_x, current_time);
610+
BBROnInit(bbr_state, path_x, current_time, option_string);
483611
}
484612
}
485613

picoquic/bbr1.c

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ typedef struct st_picoquic_bbr1_state_t {
278278
uint64_t congestion_sequence; /* sequence number after congestion notification */
279279
uint64_t cwin_before_suspension; /* So it can be restored if suspension stops. */
280280

281+
const char* option_string;
281282
uint64_t wifi_shadow_rtt; /* Shadow RTT used for wifi connections. */
282283
double quantum_ratio;
283284

@@ -368,13 +369,89 @@ void BBR1UpdateTargetCwnd(picoquic_bbr1_state_t* bbr1_state)
368369
bbr1_state->target_cwnd = BBR1Inflight(bbr1_state, bbr1_state->cwnd_gain);
369370
}
370371

371-
static void picoquic_bbr1_reset(picoquic_bbr1_state_t* bbr1_state, picoquic_path_t* path_x, uint64_t current_time, uint64_t wifi_shadow_rtt)
372+
373+
/* Initialization of optional variables defined in text string
374+
* Syntax:
375+
* T999999999: wifi_shadow_rtt, microseconds
376+
* Q99999.999: quantum_ratio,
377+
*
378+
*/
379+
static void picoquic_bbr1_set_options(picoquic_bbr1_state_t* bbr1_state)
380+
{
381+
const char* x = bbr1_state->option_string;
382+
383+
if (x != NULL) {
384+
char c;
385+
while ((c = *x) != 0) {
386+
x++;
387+
switch (c) {
388+
case 'T': {
389+
/* Reading digits into an uint64_t */
390+
uint64_t u = 0;
391+
while ((c = *x) != 0) {
392+
if (c >= '0' && c <= '9') {
393+
u *= 10;
394+
u += c - '0';
395+
x++;
396+
}
397+
else {
398+
break;
399+
}
400+
}
401+
bbr1_state->wifi_shadow_rtt = u;
402+
break;
403+
}
404+
case 'Q': {
405+
/* Reading digits ad one dot into a double */
406+
while ((c = *x) != 0) {
407+
double d = 0;
408+
double div = 1.0;
409+
int dotted = 0;
410+
while ((c = *x) != 0) {
411+
if (c >= '0' && c <= '9') {
412+
if (!dotted) {
413+
d *= 10;
414+
d += c - '0';
415+
}
416+
else {
417+
div /= 10.0;
418+
d += div * (c - '0');
419+
}
420+
x++;
421+
}
422+
else if (c == '.') {
423+
if (dotted) {
424+
break;
425+
}
426+
else {
427+
dotted = 1;
428+
x++;
429+
}
430+
}
431+
else {
432+
break;
433+
}
434+
}
435+
bbr1_state->quantum_ratio = d;
436+
break;
437+
}
438+
}
439+
case ':':
440+
/* Ignore */
441+
break;
442+
default:
443+
break;
444+
}
445+
}
446+
}
447+
}
448+
449+
static void picoquic_bbr1_reset(picoquic_bbr1_state_t* bbr1_state, picoquic_path_t* path_x, uint64_t current_time)
372450
{
373451
memset(bbr1_state, 0, sizeof(picoquic_bbr1_state_t));
374452
path_x->cwin = PICOQUIC_CWIN_INITIAL;
375-
bbr1_state->rt_prop = UINT64_MAX;
376-
bbr1_state->wifi_shadow_rtt = path_x->cnx->quic->wifi_shadow_rtt;
377-
bbr1_state->quantum_ratio = path_x->cnx->quic->bbr_quantum_ratio;
453+
bbr1_state->rt_prop = UINT64_MAX;
454+
picoquic_bbr1_set_options(bbr1_state);
378455
if (bbr1_state->quantum_ratio == 0) {
379456
bbr1_state->quantum_ratio = 0.001;
380457
}
@@ -389,14 +466,15 @@ static void picoquic_bbr1_reset(picoquic_bbr1_state_t* bbr1_state, picoquic_path
389466
BBR1UpdateTargetCwnd(bbr1_state);
390467
}
391468

392-
static void picoquic_bbr1_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
469+
static void picoquic_bbr1_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
393470
{
394471
/* Initialize the state of the congestion control algorithm */
395472
picoquic_bbr1_state_t* bbr1_state = (picoquic_bbr1_state_t*)malloc(sizeof(picoquic_bbr1_state_t));
396473

397474
path_x->congestion_alg_state = (void*)bbr1_state;
398475
if (bbr1_state != NULL) {
399-
picoquic_bbr1_reset(bbr1_state, path_x, current_time, cnx->quic->wifi_shadow_rtt);
476+
bbr1_state->option_string = option_string;
477+
picoquic_bbr1_reset(bbr1_state, path_x, current_time);
400478
}
401479
}
402480

@@ -1210,7 +1288,7 @@ static void picoquic_bbr1_notify(
12101288
case picoquic_congestion_notification_cwin_blocked:
12111289
break;
12121290
case picoquic_congestion_notification_reset:
1213-
picoquic_bbr1_reset(bbr1_state, path_x, current_time, cnx->quic->wifi_shadow_rtt);
1291+
picoquic_bbr1_reset(bbr1_state, path_x, current_time);
12141292
break;
12151293
case picoquic_congestion_notification_seed_cwin:
12161294
if (bbr1_state->state == picoquic_bbr1_alg_startup_long_rtt) {

0 commit comments

Comments
 (0)