diff --git a/picoquic/bbr.c b/picoquic/bbr.c index e5b816930..0ee728a57 100644 --- a/picoquic/bbr.c +++ b/picoquic/bbr.c @@ -25,6 +25,14 @@ #include "cc_common.h" #include "picoquic_utils.h" +#ifdef BBRExperiment +#define BBRExpGate(ctx, test, action) { if (ctx->exp_flags.test) action; } +#define BBRExpTest(ctx, test) ( (ctx)->exp_flags.test ) +#else +#define BBRExpGate(ctx, test, action) {} +#define BBRExpTest(ctx, test) (1) +#endif + #define RTTJitterBuffer On #define RTTJitterBufferStartup On #define RTTJitterBufferProbe On @@ -257,6 +265,10 @@ typedef struct st_picoquic_bbr_state_t { /* Experimental extensions, may or maynot be a good idea. */ uint64_t wifi_shadow_rtt; /* Shadow RTT used for wifi connections. */ double quantum_ratio; /* allow application to use a different default than 0.1% of bandwidth (or 1ms of traffic) */ +#ifdef BBRExperiment + /* Control flags for BBR improvements */ + bbr_exp exp_flags; +#endif } picoquic_bbr_state_t; @@ -439,6 +451,11 @@ static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, bbr_state->extra_acked_delivered = 0; /* Support for the wifi_shadow_rtt hack */ bbr_state->wifi_shadow_rtt = path_x->cnx->quic->wifi_shadow_rtt; + +#ifdef BBRExperiment + /* Support for BBR Experiment */ + bbr_state->exp_flags = path_x->cnx->quic->bbr_exp_flags; +#endif /* Support for experimenting with the send_quantum ratio */ bbr_state->quantum_ratio = path_x->cnx->quic->bbr_quantum_ratio; if (bbr_state->quantum_ratio == 0) { @@ -675,7 +692,7 @@ static void BBROnExitRecovery(picoquic_bbr_state_t* bbr_state, picoquic_path_t* bbr_state->recovery_packet_number = UINT64_MAX; bbr_state->packet_conservation = 0; - if (bbr_state->is_pto_recovery) { + if (bbr_state->is_pto_recovery && BBRExpTest(bbr_state, do_handle_suspension)) { /* TODO: * we should try to enter startup with a high enough BW. However, * simple attempts to restore the BW parameters have proven ineffective. @@ -1639,7 +1656,7 @@ static int BBRCheckTimeToProbeBW(picoquic_bbr_state_t* bbr_state, picoquic_path_ { if (BBRHasElapsedInPhase(bbr_state, bbr_state->bw_probe_wait, current_time) || BBRIsRenoCoexistenceProbeTime(bbr_state, path_x) || - BBRCheckAppLimitedEnded(bbr_state, rs)) { + (BBRExpTest(bbr_state, do_enter_probeBW_after_limited) && BBRCheckAppLimitedEnded(bbr_state, rs))) { BBRStartProbeBW_REFILL(bbr_state, path_x); return 1; } @@ -1654,7 +1671,7 @@ static void BBRStartProbeBW_DOWN(picoquic_bbr_state_t* bbr_state, picoquic_path_ bbr_state->cwnd_gain = BBRProbeBwDownCwndGain; /* maintain cwnd */ BBRResetCongestionSignals(bbr_state); bbr_state->bw_probe_up_cnt = UINT32_MAX; /* not growing inflight_hi */ - if (bbr_state->probe_probe_bw_quickly) { + if (bbr_state->probe_probe_bw_quickly && BBRExpTest(bbr_state, do_rapid_start)) { BBRPickProbeWaitEarly(bbr_state); } else { @@ -1762,7 +1779,7 @@ static void BBRUpdateProbeBWCyclePhase(picoquic_bbr_state_t* bbr_state, picoquic case picoquic_bbr_alg_probe_bw_up: if (BBRHasElapsedInPhase(bbr_state, bbr_state->min_rtt, current_time) && - (bbr_state->nb_rtt_excess > 0 || + ((BBRExpTest(bbr_state, do_exit_probeBW_up_on_delay) && bbr_state->nb_rtt_excess > 0) || path_x->bytes_in_transit > BBRInflightWithBw(bbr_state, path_x, 1.25, bbr_state->max_bw))) { BBRStartProbeBW_DOWN(bbr_state, path_x, current_time); } @@ -1902,7 +1919,7 @@ static void BBRCheckStartupDone(picoquic_bbr_state_t* bbr_state, BBRCheckStartupFullBandwidth(bbr_state, rs); BBRCheckStartupHighLoss(bbr_state, path_x, rs); #ifdef RTTJitterBufferStartup - if (IsRTTTooHigh(bbr_state)) { + if (IsRTTTooHigh(bbr_state) && BBRExpTest(bbr_state, do_early_exit)) { bbr_state->filled_pipe = 1; } #endif @@ -2287,6 +2304,7 @@ static void picoquic_bbr_notify( break; case picoquic_congestion_notification_lost_feedback: /* Feedback has been lost. It will be restored at the next notification. */ + BBRExpGate(bbr_state, do_control_lost, break); BBREnterLostFeedback(bbr_state, path_x); break; case picoquic_congestion_notification_rtt_measurement: diff --git a/picoquic/picoquic.h b/picoquic/picoquic.h index a85406d12..0423e00a0 100644 --- a/picoquic/picoquic.h +++ b/picoquic/picoquic.h @@ -1528,6 +1528,24 @@ void picoquic_set_default_wifi_shadow_rtt(picoquic_quic_t* quic, uint64_t wifi_s */ void picoquic_set_default_bbr_quantum_ratio(picoquic_quic_t* quic, double quantum_ratio); +/* Temporary code, do define a set of BBR flags that +* turn on and off individual extensions. We want to use that +* to do "before/after" measurements. + */ +#define BBRExperiment on +#ifdef BBRExperiment +/* Control flags for BBR improvements */ +typedef struct st_bbr_exp { + unsigned int do_early_exit : 1; + unsigned int do_rapid_start : 1; + unsigned int do_handle_suspension : 1; + unsigned int do_control_lost : 1; + unsigned int do_exit_probeBW_up_on_delay : 1; + unsigned int do_enter_probeBW_after_limited : 1; +} bbr_exp; + +void picoquic_set_bbr_exp(picoquic_quic_t * quic, bbr_exp* exp); +#endif /* The experimental API 'picoquic_set_priority_limit_for_bypass' * instruct the stack to send the high priority streams or datagrams * immediately, even if congestion control would normally prevent it. diff --git a/picoquic/picoquic_internal.h b/picoquic/picoquic_internal.h index 827afc074..4471aa016 100644 --- a/picoquic/picoquic_internal.h +++ b/picoquic/picoquic_internal.h @@ -732,6 +732,11 @@ typedef struct st_picoquic_quic_t { struct st_picoquic_unified_logging_t* qlog_fns; picoquic_performance_log_fn perflog_fn; void* v_perflog_ctx; + +#ifdef BBRExperiment + bbr_exp bbr_exp_flags; +#endif + } picoquic_quic_t; picoquic_packet_context_enum picoquic_context_from_epoch(int epoch); diff --git a/picoquic/quicctx.c b/picoquic/quicctx.c index 3f4123924..b5dd5fe9e 100644 --- a/picoquic/quicctx.c +++ b/picoquic/quicctx.c @@ -736,7 +736,17 @@ picoquic_quic_t* picoquic_create(uint32_t max_nb_connections, } } } - +#ifdef BBRExperiment + if (ret == 0) { + quic->bbr_exp_flags.do_early_exit = 1; + quic->bbr_exp_flags.do_rapid_start = 1; + quic->bbr_exp_flags.do_handle_suspension = 1; + quic->bbr_exp_flags.do_control_lost = 1; + quic->bbr_exp_flags.do_exit_probeBW_up_on_delay = 1; + quic->bbr_exp_flags.do_enter_probeBW_after_limited = 1; + } +#endif + if (ret != 0) { picoquic_free(quic); quic = NULL; @@ -4878,6 +4888,12 @@ void picoquic_set_default_bbr_quantum_ratio(picoquic_quic_t* quic, double quantu quic->bbr_quantum_ratio = quantum_ratio; } +#ifdef BBRExperiment +void picoquic_set_bbr_exp(picoquic_quic_t* quic, bbr_exp* exp) +{ + quic->bbr_exp_flags = *exp; +} +#endif void picoquic_set_priority_limit_for_bypass(picoquic_cnx_t* cnx, uint8_t priority_limit) { cnx->priority_limit_for_bypass = priority_limit;