26
26
#include "picoquic_utils.h"
27
27
28
28
#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; }
30
30
#define BBRExpTest (ctx , test ) ( (ctx)->exp_flags.test )
31
31
#else
32
32
#define BBRExpGate (ctx , test , action ) {}
@@ -141,6 +141,22 @@ typedef enum {
141
141
142
142
#define BBRExcessiveEcnCE 0.2
143
143
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
144
160
typedef struct st_picoquic_bbr_state_t {
145
161
/* Algorithm state: */
146
162
picoquic_bbr_alg_state_t state ;
@@ -260,13 +276,13 @@ typedef struct st_picoquic_bbr_state_t {
260
276
unsigned int probe_bdp_seed ;
261
277
262
278
/* Experimental extensions, may or maynot be a good idea. */
279
+ char const * option_string ;
263
280
uint64_t wifi_shadow_rtt ; /* Shadow RTT used for wifi connections. */
264
281
double quantum_ratio ; /* allow application to use a different default than 0.1% of bandwidth (or 1ms of traffic) */
265
282
#ifdef BBRExperiment
266
283
/* Control flags for BBR improvements */
267
284
bbr_exp exp_flags ;
268
285
#endif
269
-
270
286
} picoquic_bbr_state_t ;
271
287
272
288
/* BBR v3 assumes that there is state associated with the acknowledgements.
@@ -422,13 +438,132 @@ static void BBRInitFullPipe(picoquic_bbr_state_t* bbr_state)
422
438
bbr_state -> full_bw_count = 0 ;
423
439
}
424
440
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
+
425
558
/* 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 )
427
560
{
428
561
/* TODO:
429
562
init_windowed_max_filter(filter = BBR.MaxBwFilter, value = 0, time = 0)
430
563
*/
431
564
memset (bbr_state , 0 , sizeof (picoquic_bbr_state_t ));
565
+ bbr_state -> option_string = option_string ;
566
+
432
567
BBRInitRandom (bbr_state , path_x , current_time );
433
568
/* If RTT was already sampled, use it, other wise set min RTT to infinity */
434
569
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,
446
581
bbr_state -> min_rtt_stamp = current_time ;
447
582
bbr_state -> extra_acked_interval_start = current_time ;
448
583
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 );
458
586
if (bbr_state -> quantum_ratio == 0 ) {
459
587
bbr_state -> quantum_ratio = 0.001 ;
460
588
}
@@ -469,17 +597,17 @@ static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x,
469
597
470
598
static void picoquic_bbr_reset (picoquic_bbr_state_t * bbr_state , picoquic_path_t * path_x , uint64_t current_time )
471
599
{
472
- BBROnInit (bbr_state , path_x , current_time );
600
+ BBROnInit (bbr_state , path_x , current_time , bbr_state -> option_string );
473
601
}
474
602
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 )
476
604
{
477
605
/* Initialize the state of the congestion control algorithm */
478
606
picoquic_bbr_state_t * bbr_state = (picoquic_bbr_state_t * )malloc (sizeof (picoquic_bbr_state_t ));
479
607
480
608
path_x -> congestion_alg_state = (void * )bbr_state ;
481
609
if (bbr_state != NULL ) {
482
- BBROnInit (bbr_state , path_x , current_time );
610
+ BBROnInit (bbr_state , path_x , current_time , option_string );
483
611
}
484
612
}
485
613
0 commit comments