diff --git a/CMakeLists.txt b/CMakeLists.txt
index a08b763da..2d0a2d2e2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ else()
endif()
project(picoquic
- VERSION 1.1.32.0
+ VERSION 1.1.33.0
DESCRIPTION "picoquic library"
LANGUAGES C CXX)
@@ -102,6 +102,7 @@ set(PICOQUIC_LIBRARY_FILES
picoquic/port_blocking.c
picoquic/prague.c
picoquic/quicctx.c
+ picoquic/register_all_cc_algorithms.c
picoquic/sacks.c
picoquic/sender.c
picoquic/sim_link.c
@@ -126,6 +127,12 @@ set(PICOQUIC_CORE_HEADERS
picoquic/picoquic_binlog.h
picoquic/picoquic_config.h
picoquic/picoquic_lb.h
+ picoquic/picoquic_newreno.h
+ picoquic/picoquic_cubic.h
+ picoquic/picoquic_bbr.h
+ picoquic/picoquic_bbr1.h
+ picoquic/picoquic_fastcc.h
+ picoquic/picoquic_prague.h
picoquic/siphash.h)
set(LOGLIB_LIBRARY_FILES
diff --git a/picoquic/bbr.c b/picoquic/bbr.c
index c7c14a45a..c51c5ee28 100644
--- a/picoquic/bbr.c
+++ b/picoquic/bbr.c
@@ -26,7 +26,7 @@
#include "picoquic_utils.h"
#ifdef BBRExperiment
-#define BBRExpGate(ctx, test, action) { if (ctx->exp_flags.test) action; }
+#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) {}
@@ -141,6 +141,22 @@ typedef enum {
#define BBRExcessiveEcnCE 0.2
+/* 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;
+#endif
typedef struct st_picoquic_bbr_state_t {
/* Algorithm state: */
picoquic_bbr_alg_state_t state;
@@ -260,13 +276,13 @@ typedef struct st_picoquic_bbr_state_t {
unsigned int probe_bdp_seed;
/* Experimental extensions, may or maynot be a good idea. */
+ char const* option_string;
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;
/* BBR v3 assumes that there is state associated with the acknowledgements.
@@ -422,13 +438,132 @@ static void BBRInitFullPipe(picoquic_bbr_state_t* bbr_state)
bbr_state->full_bw_count = 0;
}
+/* Initialization of optional variables defined in text string
+* Syntax:
+* - Single letter options that control the "BBR Experiment"
+* E: do_early_exit
+* R: do_rapid_start
+* H: do_handle_suspension
+* L: do_control_lost
+* D: do_exit_probeBW_up_on_delay
+* A: do_enter_probeBW_after_limited
+* - Complex options, ends with ':'
+* T999999999: wifi_shadow_rtt, microseconds
+* Q99999.999: quantum_ratio, %
+*
+* The "BBR Experiment" is an attempt to improve behavior of BBR for
+* realtime support on some networks, mostly Wi-Fi. The experiment was a
+* success, and the corresponding support is on by default, The individual
+* option flags can be used to turn off some parts of the experiment,
+* for example when doing before/after measurements.
+*/
+static void BBRSetOptions(picoquic_bbr_state_t* bbr_state)
+{
+ const char* x = bbr_state->option_string;
+#ifdef BBRExperiment
+ bbr_state->exp_flags.do_early_exit = 1;
+ bbr_state->exp_flags.do_rapid_start = 1;
+ bbr_state->exp_flags.do_handle_suspension = 1;
+ bbr_state->exp_flags.do_control_lost = 1;
+ bbr_state->exp_flags.do_exit_probeBW_up_on_delay = 1;
+ bbr_state->exp_flags.do_enter_probeBW_after_limited = 1;
+#endif
+
+ if (x != NULL) {
+ char c;
+ while ((c = *x) != 0) {
+ x++;
+ switch (c) {
+#ifdef BBRExperiment
+ case 'E':
+ bbr_state->exp_flags.do_early_exit = 0;
+ break;
+ case 'R':
+ bbr_state->exp_flags.do_rapid_start = 0;
+ break;
+ case 'H':
+ bbr_state->exp_flags.do_handle_suspension = 0;
+ break;
+ case 'L':
+ bbr_state->exp_flags.do_control_lost = 0;
+ break;
+ case 'D':
+ bbr_state->exp_flags.do_exit_probeBW_up_on_delay = 0;
+ break;
+ case 'A':
+ bbr_state->exp_flags.do_enter_probeBW_after_limited = 0;
+ break;
+#endif
+ case 'T': {
+ /* Reading digits into an uint64_t */
+ uint64_t u = 0;
+ while ((c = *x) != 0) {
+ if (c >= '0' && c <= '9') {
+ u *= 10;
+ u += c - '0';
+ x++;
+ }
+ else {
+ break;
+ }
+ }
+ bbr_state->wifi_shadow_rtt = u;
+ break;
+ }
+ case 'Q': {
+ /* Reading digits ad one dot into a double */
+ while ((c = *x) != 0) {
+ double d = 0;
+ double div = 1.0;
+ int dotted = 0;
+ while ((c = *x) != 0) {
+ if (c >= '0' && c <= '9') {
+ if (!dotted) {
+ d *= 10;
+ d += c - '0';
+ }
+ else {
+ div /= 10.0;
+ d += div * (c - '0');
+ }
+ x++;
+ }
+ else if (c == '.') {
+ if (dotted) {
+ break;
+ }
+ else {
+ dotted = 1;
+ x++;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ bbr_state->quantum_ratio = d;
+ break;
+ }
+ }
+ case ':':
+ /* Ignore */
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
/* Initialization of the BBR state */
-static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time)
+static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time, char const * option_string)
{
/* TODO:
init_windowed_max_filter(filter = BBR.MaxBwFilter, value = 0, time = 0)
*/
memset(bbr_state, 0, sizeof(picoquic_bbr_state_t));
+ bbr_state->option_string = option_string;
+
BBRInitRandom(bbr_state, path_x, current_time);
/* If RTT was already sampled, use it, other wise set min RTT to infinity */
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,
bbr_state->min_rtt_stamp = current_time;
bbr_state->extra_acked_interval_start = current_time;
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;
+ /* Support for the experimental options */
+ BBRSetOptions(bbr_state);
if (bbr_state->quantum_ratio == 0) {
bbr_state->quantum_ratio = 0.001;
}
@@ -469,17 +597,17 @@ static void BBROnInit(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x,
static void picoquic_bbr_reset(picoquic_bbr_state_t* bbr_state, picoquic_path_t* path_x, uint64_t current_time)
{
- BBROnInit(bbr_state, path_x, current_time);
+ BBROnInit(bbr_state, path_x, current_time, bbr_state->option_string);
}
-static void picoquic_bbr_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
+static void picoquic_bbr_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
{
/* Initialize the state of the congestion control algorithm */
picoquic_bbr_state_t* bbr_state = (picoquic_bbr_state_t*)malloc(sizeof(picoquic_bbr_state_t));
path_x->congestion_alg_state = (void*)bbr_state;
if (bbr_state != NULL) {
- BBROnInit(bbr_state, path_x, current_time);
+ BBROnInit(bbr_state, path_x, current_time, option_string);
}
}
diff --git a/picoquic/bbr1.c b/picoquic/bbr1.c
index 6ff8271e5..b1e6b0f73 100644
--- a/picoquic/bbr1.c
+++ b/picoquic/bbr1.c
@@ -278,6 +278,7 @@ typedef struct st_picoquic_bbr1_state_t {
uint64_t congestion_sequence; /* sequence number after congestion notification */
uint64_t cwin_before_suspension; /* So it can be restored if suspension stops. */
+ const char* option_string;
uint64_t wifi_shadow_rtt; /* Shadow RTT used for wifi connections. */
double quantum_ratio;
@@ -368,13 +369,89 @@ void BBR1UpdateTargetCwnd(picoquic_bbr1_state_t* bbr1_state)
bbr1_state->target_cwnd = BBR1Inflight(bbr1_state, bbr1_state->cwnd_gain);
}
-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)
+
+/* Initialization of optional variables defined in text string
+* Syntax:
+* T999999999: wifi_shadow_rtt, microseconds
+* Q99999.999: quantum_ratio,
+*
+*/
+static void picoquic_bbr1_set_options(picoquic_bbr1_state_t* bbr1_state)
+{
+ const char* x = bbr1_state->option_string;
+
+ if (x != NULL) {
+ char c;
+ while ((c = *x) != 0) {
+ x++;
+ switch (c) {
+ case 'T': {
+ /* Reading digits into an uint64_t */
+ uint64_t u = 0;
+ while ((c = *x) != 0) {
+ if (c >= '0' && c <= '9') {
+ u *= 10;
+ u += c - '0';
+ x++;
+ }
+ else {
+ break;
+ }
+ }
+ bbr1_state->wifi_shadow_rtt = u;
+ break;
+ }
+ case 'Q': {
+ /* Reading digits ad one dot into a double */
+ while ((c = *x) != 0) {
+ double d = 0;
+ double div = 1.0;
+ int dotted = 0;
+ while ((c = *x) != 0) {
+ if (c >= '0' && c <= '9') {
+ if (!dotted) {
+ d *= 10;
+ d += c - '0';
+ }
+ else {
+ div /= 10.0;
+ d += div * (c - '0');
+ }
+ x++;
+ }
+ else if (c == '.') {
+ if (dotted) {
+ break;
+ }
+ else {
+ dotted = 1;
+ x++;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ bbr1_state->quantum_ratio = d;
+ break;
+ }
+ }
+ case ':':
+ /* Ignore */
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static void picoquic_bbr1_reset(picoquic_bbr1_state_t* bbr1_state, picoquic_path_t* path_x, uint64_t current_time)
{
memset(bbr1_state, 0, sizeof(picoquic_bbr1_state_t));
path_x->cwin = PICOQUIC_CWIN_INITIAL;
- bbr1_state->rt_prop = UINT64_MAX;
- bbr1_state->wifi_shadow_rtt = path_x->cnx->quic->wifi_shadow_rtt;
- bbr1_state->quantum_ratio = path_x->cnx->quic->bbr_quantum_ratio;
+ bbr1_state->rt_prop = UINT64_MAX;
+ picoquic_bbr1_set_options(bbr1_state);
if (bbr1_state->quantum_ratio == 0) {
bbr1_state->quantum_ratio = 0.001;
}
@@ -389,14 +466,15 @@ static void picoquic_bbr1_reset(picoquic_bbr1_state_t* bbr1_state, picoquic_path
BBR1UpdateTargetCwnd(bbr1_state);
}
-static void picoquic_bbr1_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
+static void picoquic_bbr1_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
{
/* Initialize the state of the congestion control algorithm */
picoquic_bbr1_state_t* bbr1_state = (picoquic_bbr1_state_t*)malloc(sizeof(picoquic_bbr1_state_t));
path_x->congestion_alg_state = (void*)bbr1_state;
if (bbr1_state != NULL) {
- picoquic_bbr1_reset(bbr1_state, path_x, current_time, cnx->quic->wifi_shadow_rtt);
+ bbr1_state->option_string = option_string;
+ picoquic_bbr1_reset(bbr1_state, path_x, current_time);
}
}
@@ -1210,7 +1288,7 @@ static void picoquic_bbr1_notify(
case picoquic_congestion_notification_cwin_blocked:
break;
case picoquic_congestion_notification_reset:
- picoquic_bbr1_reset(bbr1_state, path_x, current_time, cnx->quic->wifi_shadow_rtt);
+ picoquic_bbr1_reset(bbr1_state, path_x, current_time);
break;
case picoquic_congestion_notification_seed_cwin:
if (bbr1_state->state == picoquic_bbr1_alg_startup_long_rtt) {
diff --git a/picoquic/config.c b/picoquic/config.c
index e8e5a9571..99ba0187f 100644
--- a/picoquic/config.c
+++ b/picoquic/config.c
@@ -34,6 +34,7 @@
#include "picoquic_unified_log.h"
#include "tls_api.h"
#include "picoquic_config.h"
+#include "picoquic_bbr.h"
typedef struct st_option_param_t {
char const * param;
@@ -64,7 +65,8 @@ static option_table_line_t option_table[] = {
{ picoquic_option_DisablePortBlocking, 'X', "disable_block", 0, "", "Disable the check for blocked ports"},
{ picoquic_option_SOLUTION_DIR, 'S', "solution_dir", 1, "folder", "Set the path to the source files to find the default files" },
{ picoquic_option_CC_ALGO, 'G', "cc_algo", 1, "cc_algorithm",
- "Use the specified congestion control algorithm: reno, cubic, bbr or fast. Defaults to bbr." },
+ "Use the specified congestion control algorithm. Defaults to bbr. Supported values are:" },
+ { picoquic_option_CC_OPTION, 'H', "cco", 1, "option", "Set option string if required by congestion control algorithm."},
{ picoquic_option_SPINBIT, 'P', "spinbit", 1, "number", "Set the default spinbit policy" },
{ picoquic_option_LOSSBIT, 'O', "lossbit", 1, "number", "Set the default lossbit policy" },
{ picoquic_option_MULTIPATH, 'M', "multipath", 0, "", "Enable QUIC multipath extension" },
@@ -291,6 +293,9 @@ static int config_set_option(option_table_line_t* option_desc, option_param_t* p
case picoquic_option_CC_ALGO:
ret = config_set_string_param(&config->cc_algo_id, params, nb_params, 0);
break;
+ case picoquic_option_CC_OPTION:
+ ret = config_set_string_param(&config->cc_algo_option_string, params, nb_params, 0);
+ break;
case picoquic_option_SPINBIT: {
int v = config_atoi(params, nb_params, 0, &ret);
if (ret != 0 || v < 0 || v > (int)picoquic_spinbit_on) {
@@ -482,6 +487,22 @@ void picoquic_config_usage_file(FILE* F)
putc(' ', F);
}
fprintf(F, " %s\n", option_table[i].option_help);
+ if (option_table[i].option_num == picoquic_option_CC_ALGO){
+ if (picoquic_congestion_control_algorithms != NULL &&
+ picoquic_nb_congestion_control_algorithms > 0) {
+ /* Add a line with supported values. */
+ for (size_t j = 0; j < 18; j++) {
+ putc(' ', F);
+ }
+ for (size_t k = 0; k < picoquic_nb_congestion_control_algorithms; k++) {
+ if (k != 0) {
+ fprintf(F, ", ");
+ }
+ fprintf(F, "%s", picoquic_congestion_control_algorithms[k]->congestion_algorithm_id);
+ }
+ fprintf(F, ".\n");
+ }
+ }
}
}
@@ -790,7 +811,7 @@ picoquic_quic_t* picoquic_create_and_configure(picoquic_quic_config_t* config,
cc_algo = picoquic_bbr_algorithm;
}
- picoquic_set_default_congestion_algorithm(quic, cc_algo);
+ picoquic_set_default_congestion_algorithm_ex(quic, cc_algo, config->cc_algo_option_string);
picoquic_set_default_spinbit_policy(quic, config->spinbit_policy);
picoquic_set_default_lossbit_policy(quic, config->lossbit_policy);
@@ -933,6 +954,10 @@ void picoquic_config_clear(picoquic_quic_config_t* config)
{
free((void*)config->cc_algo_id);
}
+ if (config->cc_algo_option_string != NULL)
+ {
+ free((void*)config->cc_algo_option_string);
+ }
if (config->cnx_id_cbdata != NULL)
{
free((void*)config->cnx_id_cbdata);
diff --git a/picoquic/cubic.c b/picoquic/cubic.c
index 7bc3fddd3..7331c5d8f 100644
--- a/picoquic/cubic.c
+++ b/picoquic/cubic.c
@@ -61,12 +61,13 @@ static void cubic_reset(picoquic_cubic_state_t* cubic_state, picoquic_path_t* pa
path_x->cwin = PICOQUIC_CWIN_INITIAL;
}
-static void cubic_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
+static void cubic_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
{
/* Initialize the state of the congestion control algorithm */
picoquic_cubic_state_t* cubic_state = (picoquic_cubic_state_t*)malloc(sizeof(picoquic_cubic_state_t));
#ifdef _WINDOWS
UNREFERENCED_PARAMETER(cnx);
+ UNREFERENCED_PARAMETER(option_string);
#endif
path_x->congestion_alg_state = (void*)cubic_state;
if (cubic_state != NULL) {
diff --git a/picoquic/fastcc.c b/picoquic/fastcc.c
index 4c26839f7..4c7646d18 100644
--- a/picoquic/fastcc.c
+++ b/picoquic/fastcc.c
@@ -91,12 +91,13 @@ void picoquic_fastcc_seed_cwin(picoquic_fastcc_state_t* fastcc_state, picoquic_p
}
}
-void picoquic_fastcc_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
+void picoquic_fastcc_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
{
/* Initialize the state of the congestion control algorithm */
picoquic_fastcc_state_t* fastcc_state = path_x->congestion_alg_state;
#ifdef _WINDOWS
UNREFERENCED_PARAMETER(cnx);
+ UNREFERENCED_PARAMETER(option_string);
#endif
if (fastcc_state == NULL) {
diff --git a/picoquic/newreno.c b/picoquic/newreno.c
index 842c76e52..a1a0f5a1f 100644
--- a/picoquic/newreno.c
+++ b/picoquic/newreno.c
@@ -186,12 +186,13 @@ static void picoquic_newreno_reset(picoquic_newreno_state_t* nr_state, picoquic_
path_x->cwin = nr_state->nrss.cwin;
}
-static void picoquic_newreno_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
+static void picoquic_newreno_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const *option_string, uint64_t current_time)
{
/* Initialize the state of the congestion control algorithm */
picoquic_newreno_state_t* nr_state = (picoquic_newreno_state_t*)malloc(sizeof(picoquic_newreno_state_t));
#ifdef _WINDOWS
UNREFERENCED_PARAMETER(current_time);
+ UNREFERENCED_PARAMETER(option_string);
UNREFERENCED_PARAMETER(cnx);
#endif
diff --git a/picoquic/picoquic.h b/picoquic/picoquic.h
index f785fd29e..e97239fcf 100644
--- a/picoquic/picoquic.h
+++ b/picoquic/picoquic.h
@@ -40,7 +40,7 @@
extern "C" {
#endif
-#define PICOQUIC_VERSION "1.1.32.0"
+#define PICOQUIC_VERSION "1.1.33.0"
#define PICOQUIC_ERROR_CLASS 0x400
#define PICOQUIC_ERROR_DUPLICATE (PICOQUIC_ERROR_CLASS + 1)
#define PICOQUIC_ERROR_AEAD_CHECK (PICOQUIC_ERROR_CLASS + 3)
@@ -1545,7 +1545,7 @@ typedef struct st_picoquic_per_ack_state_t {
unsigned int is_cwnd_limited: 1; /* path marked CWIN limited after packet was sent. */
} picoquic_per_ack_state_t;
-typedef void (*picoquic_congestion_algorithm_init)(picoquic_cnx_t* cnx, picoquic_path_t* path_x, uint64_t current_time);
+typedef void (*picoquic_congestion_algorithm_init)(picoquic_cnx_t* cnx, picoquic_path_t* path_x, char const * option_string, uint64_t current_time);
typedef void (*picoquic_congestion_algorithm_notify)(
picoquic_cnx_t* cnx,
picoquic_path_t* path_x,
@@ -1565,66 +1565,27 @@ typedef struct st_picoquic_congestion_algorithm_t {
picoquic_congestion_algorithm_observe alg_observe;
} picoquic_congestion_algorithm_t;
-extern picoquic_congestion_algorithm_t* picoquic_newreno_algorithm;
-extern picoquic_congestion_algorithm_t* picoquic_cubic_algorithm;
-extern picoquic_congestion_algorithm_t* picoquic_dcubic_algorithm;
-extern picoquic_congestion_algorithm_t* picoquic_fastcc_algorithm;
-extern picoquic_congestion_algorithm_t* picoquic_bbr_algorithm;
-extern picoquic_congestion_algorithm_t* picoquic_prague_algorithm;
-extern picoquic_congestion_algorithm_t* picoquic_bbr1_algorithm;
-
#define PICOQUIC_DEFAULT_CONGESTION_ALGORITHM picoquic_newreno_algorithm;
-picoquic_congestion_algorithm_t const* picoquic_get_congestion_algorithm(char const* alg_name);
+
+extern picoquic_congestion_algorithm_t const** picoquic_congestion_control_algorithms;
+extern size_t picoquic_nb_congestion_control_algorithms;
+/* Register a custom table of congestion control algorithms */
+void picoquic_register_congestion_control_algorithms(picoquic_congestion_algorithm_t const** alg, size_t nb_algorithms);
+/* Register a full list of congestion control algorithms */
+void picoquic_register_all_congestion_control_algorithms();
+
+picoquic_congestion_algorithm_t const* picoquic_get_congestion_algorithm(char const* alg_id);
+
void picoquic_set_default_congestion_algorithm(picoquic_quic_t* quic, picoquic_congestion_algorithm_t const* algo);
+void picoquic_set_default_congestion_algorithm_ex(picoquic_quic_t* quic, picoquic_congestion_algorithm_t const* alg, char const* alg_option_string);
void picoquic_set_default_congestion_algorithm_by_name(picoquic_quic_t* quic, char const* alg_name);
void picoquic_set_congestion_algorithm(picoquic_cnx_t* cnx, picoquic_congestion_algorithm_t const* algo);
+void picoquic_set_congestion_algorithm_ex(picoquic_cnx_t* cnx, picoquic_congestion_algorithm_t const* alg, char const* alg_option_string);
-/* Special code for Wi-Fi network. These networks are subject to occasional
- * "suspension", for power saving reasons. If the suspension is too long,
- * it causes transmission to stop after cngestion control credits are
- * exhausted. We expect that the effects of suspension are not so bad if
- * the congestion control parameters allow for transmission through the
- * suspension. The "wifi shadow RTT" parameter tells the congestion control
- * algorithm BBR to set the CWIN large enough to sustain transmission through
- * that duration. The value is in microseconds.
- *
- * This parameter should be set before the first connections are started.
- * Changing the settings will not affect existing connections.
- */
-void picoquic_set_default_wifi_shadow_rtt(picoquic_quic_t* quic, uint64_t wifi_shadow_rtt);
-
-/* The experimental API `picoquic_set_default_bbr_quantum_ratio`
-* allows application to change the "quantum ratio" parameter of the BBR
-* algorithm. The default value is 0.001 (1/1000th of the pacing rate
-* in bytes per second). Larger values like 0.01 would increase the
-* size of the "leaky bucket" used by the pacing algorithms. Whether
-* that's a good idea or not is debatable, probably depends on the
-* application.
-*/
-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.vcxproj b/picoquic/picoquic.vcxproj
index 6c52a45b3..a19db9382 100644
--- a/picoquic/picoquic.vcxproj
+++ b/picoquic/picoquic.vcxproj
@@ -171,6 +171,7 @@
+
diff --git a/picoquic/picoquic.vcxproj.filters b/picoquic/picoquic.vcxproj.filters
index ddb243a6e..ed86629b7 100644
--- a/picoquic/picoquic.vcxproj.filters
+++ b/picoquic/picoquic.vcxproj.filters
@@ -141,6 +141,9 @@
Source Files
+
+ Source Files
+
diff --git a/picoquic/picoquic_bbr.h b/picoquic/picoquic_bbr.h
new file mode 100644
index 000000000..508e8b6e2
--- /dev/null
+++ b/picoquic/picoquic_bbr.h
@@ -0,0 +1,36 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2025, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOQUIC_BBR_H
+#define PICOQUIC_BBR_H
+
+#include "picoquic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern picoquic_congestion_algorithm_t* picoquic_bbr_algorithm;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/picoquic/picoquic_bbr1.h b/picoquic/picoquic_bbr1.h
new file mode 100644
index 000000000..f42f08cc1
--- /dev/null
+++ b/picoquic/picoquic_bbr1.h
@@ -0,0 +1,29 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2025, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOQUIC_BBR1_H
+#define PICOQUIC_BBR1_H
+
+#include "picoquic.h"
+
+extern picoquic_congestion_algorithm_t* picoquic_bbr1_algorithm;
+
+#endif
diff --git a/picoquic/picoquic_config.h b/picoquic/picoquic_config.h
index a5fe09d85..f3669fbc5 100644
--- a/picoquic/picoquic_config.h
+++ b/picoquic/picoquic_config.h
@@ -44,6 +44,7 @@ typedef enum {
picoquic_option_DisablePortBlocking,
picoquic_option_SOLUTION_DIR,
picoquic_option_CC_ALGO,
+ picoquic_option_CC_OPTION,
picoquic_option_SPINBIT,
picoquic_option_LOSSBIT,
picoquic_option_MULTIPATH,
@@ -93,6 +94,7 @@ typedef struct st_picoquic_quic_config_t {
int idle_timeout;
int socket_buffer_size;
char const* cc_algo_id;
+ char const* cc_algo_option_string;
char const * cnx_id_cbdata;
/* TODO: control key logging */
picoquic_spinbit_version_enum spinbit_policy; /* control spin bit */
diff --git a/picoquic/picoquic_cubic.h b/picoquic/picoquic_cubic.h
new file mode 100644
index 000000000..acf409393
--- /dev/null
+++ b/picoquic/picoquic_cubic.h
@@ -0,0 +1,37 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2025, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOQUIC_CUBIC_H
+#define PICOQUIC_CUBIC_H
+
+#include "picoquic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern picoquic_congestion_algorithm_t* picoquic_cubic_algorithm;
+extern picoquic_congestion_algorithm_t* picoquic_dcubic_algorithm;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/picoquic/picoquic_fastcc.h b/picoquic/picoquic_fastcc.h
new file mode 100644
index 000000000..4da9a9413
--- /dev/null
+++ b/picoquic/picoquic_fastcc.h
@@ -0,0 +1,30 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2017, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOQUIC_FASTCC_H
+#define PICOQUIC_FASTCC_H
+
+#include "picoquic.h"
+
+
+extern picoquic_congestion_algorithm_t* picoquic_fastcc_algorithm;
+
+#endif
diff --git a/picoquic/picoquic_internal.h b/picoquic/picoquic_internal.h
index 4d0f59ba6..a3bd575e9 100644
--- a/picoquic/picoquic_internal.h
+++ b/picoquic/picoquic_internal.h
@@ -671,8 +671,7 @@ typedef struct st_picoquic_quic_t {
picoquic_stateless_packet_t* pending_stateless_packet;
picoquic_congestion_algorithm_t const* default_congestion_alg;
- uint64_t wifi_shadow_rtt;
- double bbr_quantum_ratio;
+ char const* default_congestion_alg_option_string;
struct st_picoquic_cnx_t* cnx_list;
struct st_picoquic_cnx_t* cnx_last;
@@ -1432,6 +1431,7 @@ typedef struct st_picoquic_cnx_t {
unsigned int stream_blocked : 1;
/* Congestion algorithm */
picoquic_congestion_algorithm_t const* congestion_alg;
+ char const* congestion_alg_option_string;
/* Management of quality signalling updates */
uint64_t rtt_update_delta;
uint64_t pacing_rate_update_delta;
diff --git a/picoquic/picoquic_newreno.h b/picoquic/picoquic_newreno.h
new file mode 100644
index 000000000..48a83a980
--- /dev/null
+++ b/picoquic/picoquic_newreno.h
@@ -0,0 +1,36 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2025, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOQUIC_NEWRENO_H
+#define PICOQUIC_NEWRENO_H
+
+#include "picoquic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern picoquic_congestion_algorithm_t* picoquic_newreno_algorithm;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/picoquic/picoquic_prague.h b/picoquic/picoquic_prague.h
new file mode 100644
index 000000000..a8aed9683
--- /dev/null
+++ b/picoquic/picoquic_prague.h
@@ -0,0 +1,36 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2025, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PICOQUIC_PRAGUE_H
+#define PICOQUIC_PRAGUE_H
+
+#include "picoquic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern picoquic_congestion_algorithm_t* picoquic_prague_algorithm;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/picoquic/prague.c b/picoquic/prague.c
index 4a3fd016a..f5f865823 100644
--- a/picoquic/prague.c
+++ b/picoquic/prague.c
@@ -121,12 +121,13 @@ static void picoquic_prague_init_reno(picoquic_prague_state_t* pr_state, picoqui
path_x->cwin = PICOQUIC_CWIN_INITIAL;
}
-void picoquic_prague_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, uint64_t current_time)
+void picoquic_prague_init(picoquic_cnx_t * cnx, picoquic_path_t* path_x, char const* option_string, uint64_t current_time)
{
/* Initialize the state of the congestion control algorithm */
picoquic_prague_state_t* pr_state = (picoquic_prague_state_t*)malloc(sizeof(picoquic_prague_state_t));
#ifdef _WINDOWS
UNREFERENCED_PARAMETER(cnx);
+ UNREFERENCED_PARAMETER(option_string);
#endif
if (pr_state != NULL) {
diff --git a/picoquic/quicctx.c b/picoquic/quicctx.c
index 5a87411c5..a05dad994 100644
--- a/picoquic/quicctx.c
+++ b/picoquic/quicctx.c
@@ -32,7 +32,7 @@
#include
#include
#endif
-
+#include "picoquic_newreno.h"
/*
* Supported versions. Specific versions may mandate different processing of different
@@ -1928,7 +1928,7 @@ void picoquic_promote_path_to_default(picoquic_cnx_t* cnx, int path_index, uint6
/* Set the congestion algorithm for the new path */
if (cnx->congestion_alg != NULL) {
- cnx->congestion_alg->alg_init(cnx, path_x, current_time);
+ cnx->congestion_alg->alg_init(cnx, path_x, cnx->congestion_alg_option_string, current_time);
}
/* Mark old path as demoted */
@@ -4011,8 +4011,9 @@ picoquic_cnx_t* picoquic_create_cnx(picoquic_quic_t* quic,
picosplay_init_tree(&cnx->stream_tree, picoquic_stream_node_compare, picoquic_stream_node_create, picoquic_stream_node_delete, picoquic_stream_node_value);
cnx->congestion_alg = cnx->quic->default_congestion_alg;
+ cnx->congestion_alg_option_string = cnx->quic->default_congestion_alg_option_string;
if (cnx->congestion_alg != NULL) {
- cnx->congestion_alg->alg_init(cnx, cnx->path[0], start_time);
+ cnx->congestion_alg->alg_init(cnx, cnx->path[0], cnx->congestion_alg_option_string, start_time);
}
}
@@ -4909,54 +4910,59 @@ picoquic_cnx_t* picoquic_cnx_by_secret(picoquic_quic_t* quic, const uint8_t* res
return ret;
}
-/* Get congestion control algorithm by name
- * TODO: if we want to minimize code size, we should not require linking a whole library
- * of congestion control algorithms. Intead, the application should have a list of
- * configured algorithms, and the configuration program should select from that list.
+/* Management of congestion control algorithms
+ * We want to minimize code size, and thus we do not want to require loading the
+ * entire list of congestion control algorithms in every executable.
+ * Instead, we require applications to provide a list of the congestion
+ * control algorithms that they support.
*/
+
+picoquic_congestion_algorithm_t const** picoquic_congestion_control_algorithms = NULL;
+size_t picoquic_nb_congestion_control_algorithms = 0;
+
+/* Register a list of congestion control algorithm */
+void picoquic_register_congestion_control_algorithms(picoquic_congestion_algorithm_t const** alg, size_t nb_algorithms)
+{
+ picoquic_congestion_control_algorithms = alg;
+ picoquic_nb_congestion_control_algorithms = nb_algorithms;
+}
+
picoquic_congestion_algorithm_t const* picoquic_get_congestion_algorithm(char const* alg_name)
{
picoquic_congestion_algorithm_t const* alg = NULL;
- if (alg_name != NULL) {
- if (strcmp(alg_name, "reno") == 0) {
- alg = picoquic_newreno_algorithm;
- }
- else if (strcmp(alg_name, "cubic") == 0) {
- alg = picoquic_cubic_algorithm;
- }
- else if (strcmp(alg_name, "dcubic") == 0) {
- alg = picoquic_dcubic_algorithm;
- }
- else if (strcmp(alg_name, "fast") == 0) {
- alg = picoquic_fastcc_algorithm;
- }
- else if (strcmp(alg_name, "bbr") == 0) {
- alg = picoquic_bbr_algorithm;
- }
- else if (strcmp(alg_name, "prague") == 0) {
- alg = picoquic_prague_algorithm;
- }
- else if (strcmp(alg_name, "bbr1") == 0) {
- alg = picoquic_bbr1_algorithm;
+
+ if (alg_name != NULL && picoquic_congestion_control_algorithms != NULL) {
+ for (size_t i = 0; i < picoquic_nb_congestion_control_algorithms; i++) {
+ if (strcmp(alg_name, picoquic_congestion_control_algorithms[i]->congestion_algorithm_id) == 0) {
+ alg = picoquic_congestion_control_algorithms[i];
+ break;
+ }
}
- else {
- alg = NULL;
+ if (alg == NULL && strcmp(alg_name, "reno") == 0) {
+ alg = picoquic_get_congestion_algorithm("newreno");
}
}
return alg;
}
+
/*
* Set or reset the congestion control algorithm
*/
-void picoquic_set_default_congestion_algorithm(picoquic_quic_t* quic, picoquic_congestion_algorithm_t const* alg)
+void picoquic_set_default_congestion_algorithm_ex(picoquic_quic_t* quic, picoquic_congestion_algorithm_t const* alg, char const * alg_option_string)
{
quic->default_congestion_alg = alg;
+ quic->default_congestion_alg_option_string = alg_option_string;
+}
+
+void picoquic_set_default_congestion_algorithm(picoquic_quic_t* quic, picoquic_congestion_algorithm_t const* alg)
+{
+ picoquic_set_default_congestion_algorithm_ex(quic, alg, NULL);
}
void picoquic_set_default_congestion_algorithm_by_name(picoquic_quic_t* quic, char const * alg_name)
{
- quic->default_congestion_alg = picoquic_get_congestion_algorithm(alg_name);
+ picoquic_set_default_congestion_algorithm_ex(quic, picoquic_get_congestion_algorithm(alg_name), NULL);
}
/*
@@ -4978,7 +4984,7 @@ void picoquic_set_preemptive_repeat_per_cnx(picoquic_cnx_t* cnx, int do_repeat)
cnx->is_preemptive_repeat_enabled = (do_repeat) ? 1 : 0;
}
-void picoquic_set_congestion_algorithm(picoquic_cnx_t* cnx, picoquic_congestion_algorithm_t const* alg)
+void picoquic_set_congestion_algorithm_ex(picoquic_cnx_t* cnx, picoquic_congestion_algorithm_t const* alg, char const* alg_option_string)
{
if (cnx->congestion_alg != NULL) {
if (cnx->path != NULL) {
@@ -4989,32 +4995,22 @@ void picoquic_set_congestion_algorithm(picoquic_cnx_t* cnx, picoquic_congestion_
}
cnx->congestion_alg = alg;
+ cnx->congestion_alg_option_string = alg_option_string;
if (cnx->congestion_alg != NULL) {
if (cnx->path != NULL) {
for (int i = 0; i < cnx->nb_paths; i++) {
- cnx->congestion_alg->alg_init(cnx, cnx->path[i], picoquic_get_quic_time(cnx->quic));
+ cnx->congestion_alg->alg_init(cnx, cnx->path[i], alg_option_string, picoquic_get_quic_time(cnx->quic));
}
}
}
}
-void picoquic_set_default_wifi_shadow_rtt(picoquic_quic_t* quic, uint64_t wifi_shadow_rtt)
-{
- quic->wifi_shadow_rtt = wifi_shadow_rtt;
-}
-
-void picoquic_set_default_bbr_quantum_ratio(picoquic_quic_t* quic, double quantum_ratio)
+void picoquic_set_congestion_algorithm(picoquic_cnx_t* cnx, picoquic_congestion_algorithm_t const* alg)
{
- quic->bbr_quantum_ratio = quantum_ratio;
+ picoquic_set_congestion_algorithm_ex(cnx, alg, NULL);
}
-#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;
diff --git a/picoquic/register_all_cc_algorithms.c b/picoquic/register_all_cc_algorithms.c
new file mode 100644
index 000000000..678de18ac
--- /dev/null
+++ b/picoquic/register_all_cc_algorithms.c
@@ -0,0 +1,49 @@
+/*
+* Author: Christian Huitema
+* Copyright (c) 2025, Private Octopus, Inc.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "picoquic.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
+
+
+/* Register a complete list of congestion control algorithms, which
+* can then be used by calls to picoquic_get_congestion_algorithm()
+* and picoquic_create_and_configure().
+ */
+
+picoquic_congestion_algorithm_t const* getter_test_cc_algo_list[7] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+void picoquic_register_all_congestion_control_algorithms()
+{
+ getter_test_cc_algo_list[0] = picoquic_newreno_algorithm;
+ getter_test_cc_algo_list[1] = picoquic_cubic_algorithm;
+ getter_test_cc_algo_list[2] = picoquic_dcubic_algorithm;
+ getter_test_cc_algo_list[3] = picoquic_fastcc_algorithm;
+ getter_test_cc_algo_list[4] = picoquic_bbr_algorithm;
+ getter_test_cc_algo_list[5] = picoquic_prague_algorithm;
+ getter_test_cc_algo_list[6] = picoquic_bbr1_algorithm;
+ picoquic_register_congestion_control_algorithms(getter_test_cc_algo_list, 7);
+}
\ No newline at end of file
diff --git a/picoquic/sender.c b/picoquic/sender.c
index 2d7eba164..d86c9fb7e 100644
--- a/picoquic/sender.c
+++ b/picoquic/sender.c
@@ -4112,7 +4112,7 @@ static int picoquic_select_next_path_mp(picoquic_cnx_t* cnx, uint64_t current_ti
int is_new_priority = 0;
/* Set the congestion algorithm for the new path */
if (cnx->congestion_alg != NULL && cnx->path[i]->congestion_alg_state == NULL) {
- cnx->congestion_alg->alg_init(cnx, cnx->path[i], current_time);
+ cnx->congestion_alg->alg_init(cnx, cnx->path[i], cnx->congestion_alg_option_string, current_time);
}
if (path_priority > highest_priority) {
diff --git a/picoquicfirst/picoquicdemo.c b/picoquicfirst/picoquicdemo.c
index 5ed146276..77cb3a634 100644
--- a/picoquicfirst/picoquicdemo.c
+++ b/picoquicfirst/picoquicdemo.c
@@ -1317,6 +1317,7 @@ int main(int argc, char** argv)
WSADATA wsaData = { 0 };
(void)WSA_START(MAKEWORD(2, 2), &wsaData);
#endif
+ picoquic_register_all_congestion_control_algorithms();
picoquic_config_init(&config);
memcpy(option_string, "A:u:f:1", 7);
ret = picoquic_config_option_letters(option_string + 7, sizeof(option_string) - 7, NULL);
diff --git a/picoquictest/ack_frequency_test.c b/picoquictest/ack_frequency_test.c
index 6097fae0a..9914af7ed 100644
--- a/picoquictest/ack_frequency_test.c
+++ b/picoquictest/ack_frequency_test.c
@@ -29,6 +29,12 @@
#include "logreader.h"
#include "qlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+
/* Verify that the ack frequency is correctly set.
*/
diff --git a/picoquictest/app_limited.c b/picoquictest/app_limited.c
index 95b3e5fb1..1c6af006a 100644
--- a/picoquictest/app_limited.c
+++ b/picoquictest/app_limited.c
@@ -29,6 +29,11 @@
#include "picoquic_binlog.h"
#include "logreader.h"
#include "qlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
/* Add a series of tests to study the behavior of rate limited
* clients, such as those sending at a sustained rate lower
diff --git a/picoquictest/cc_compete_test.c b/picoquictest/cc_compete_test.c
index 04e0d370a..fd022cf82 100644
--- a/picoquictest/cc_compete_test.c
+++ b/picoquictest/cc_compete_test.c
@@ -24,6 +24,12 @@
#include
#include
#include "picoquic_ns.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
/* Congestion compete test.
* These tests measure what happens when multiple connections fight for the same
diff --git a/picoquictest/config_test.c b/picoquictest/config_test.c
index 60ecac93e..f9bc179ab 100644
--- a/picoquictest/config_test.c
+++ b/picoquictest/config_test.c
@@ -27,11 +27,14 @@
#include "picoquic_utils.h"
#include "picoquic_config.h"
#include "picoquictest_internal.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
#ifdef PICOQUIC_WITHOUT_SSLKEYLOG
-static char* ref_option_text = "c:k:p:v:o:w:x:rR:s:XS:G:P:O:Me:C:i:l:Lb:q:m:n:a:t:zI:d:DQT:N:B:F:VU:0j:W:J:h";
+static char* ref_option_text = "c:k:p:v:o:w:x:rR:s:XS:G:H:P:O:Me:C:i:l:Lb:q:m:n:a:t:zI:d:DQT:N:B:F:VU:0j:W:J:h";
#else
-static char* ref_option_text = "c:k:p:v:o:w:x:rR:s:XS:G:P:O:Me:C:i:l:Lb:q:m:n:a:t:zI:d:DQT:N:B:F:VU:0j:W:8J:h";
+static char* ref_option_text = "c:k:p:v:o:w:x:rR:s:XS:G:H:P:O:Me:C:i:l:Lb:q:m:n:a:t:zI:d:DQT:N:B:F:VU:0j:W:8J:h";
#endif
int config_option_letters_test()
{
@@ -66,7 +69,8 @@ static picoquic_quic_config_t param1 = {
-1, /* int cnx_id_length; */
PICOQUIC_MICROSEC_HANDSHAKE_MAX/1000, /* int idle_timeout */
655360, /* Socket buffer size */
- "cubic", /* const picoquic_congestion_algorithm_t* cc_algorithm; */
+ "bbr", /* const picoquic_congestion_algorithm_t* cc_algorithm; */
+ "T250000", /* BBR option */
"0N8C-000123", /* char const* cnx_id_cbdata; */
3, /* spin bit policy */
2, /* loss bit policy */
@@ -119,7 +123,8 @@ static char const* config_argv1[] = {
"-p", "4433",
"-e", "1",
"-m", "1536",
- "-G", "cubic",
+ "-G", "bbr",
+ "-H", "T250000",
"-P", "3",
"-O", "2",
"-M",
@@ -154,6 +159,7 @@ static picoquic_quic_config_t param2 = {
1234567, /* int idle_timeout */
0, /* socket_buffer_size */
NULL, /* const picoquic_congestion_algorithm_t* cc_algorithm; */
+ NULL, /* option string */
NULL, /* char const* cnx_id_cbdata; */
0, /* spin bit policy */
0, /* loss bit policy */
@@ -285,6 +291,23 @@ static config_error_test_t config_errors[] = {
static size_t nb_config_errors = sizeof(config_errors) / sizeof(config_error_test_t);
+
+/* Register a small and stable list of congestion control algorithms,
+* sufficient to test the cc algorithm configuration functions.
+ */
+
+static picoquic_congestion_algorithm_t const* config_test_cc_algo_list[3] = {
+ NULL, NULL, NULL
+};
+
+static void config_test_register_cc_algorithms()
+{
+ config_test_cc_algo_list[0] = picoquic_newreno_algorithm;
+ config_test_cc_algo_list[1] = picoquic_cubic_algorithm;
+ config_test_cc_algo_list[2] = picoquic_bbr_algorithm;
+ picoquic_register_congestion_control_algorithms(config_test_cc_algo_list, 3);
+}
+
int config_test_compare_string(const char* title, const char* expected, const char* actual)
{
int ret = 0;
@@ -623,6 +646,11 @@ int config_quic_test_one(picoquic_quic_config_t* config)
memcmp(quic->reset_seed, config->reset_seed, sizeof(config->reset_seed)) != 0) {
ret = -1;
}
+ if (config->cc_algo_id != NULL &&
+ (quic->default_congestion_alg == NULL ||
+ strcmp(quic->default_congestion_alg->congestion_algorithm_id, config->cc_algo_id) != 0)) {
+ ret = -1;
+ }
picoquic_free(quic);
}
@@ -642,6 +670,8 @@ int config_quic_test_one(picoquic_quic_config_t* config)
int config_quic_test()
{
int ret = 0;
+ config_test_register_cc_algorithms();
+
if (config_quic_test_one(¶m1) != 0 ||
config_quic_test_one(¶m2) != 0) {
ret = -1;
@@ -659,6 +689,8 @@ int config_usage_test()
char config_usage_ref[512];
int ret = picoquic_get_input_path(config_usage_ref, sizeof(config_usage_ref), picoquic_solution_dir, CONFIG_USAGE_REF);
+ config_test_register_cc_algorithms();
+
if (ret == 0 && (F = picoquic_file_open(CONFIG_USAGE_TXT, "wt")) != NULL){
picoquic_config_usage_file(F);
F = picoquic_file_close(F);
diff --git a/picoquictest/config_usage_ref.txt b/picoquictest/config_usage_ref.txt
index 0f8bf1ba3..40e642891 100644
--- a/picoquictest/config_usage_ref.txt
+++ b/picoquictest/config_usage_ref.txt
@@ -11,7 +11,9 @@ Picoquic options:
-s <32 hex chars> Reset seed
-X Disable the check for blocked ports
-S folder Set the path to the source files to find the default files
- -G cc_algorithm Use the specified congestion control algorithm: reno, cubic, bbr or fast. Defaults to bbr.
+ -G cc_algorithm Use the specified congestion control algorithm. Defaults to bbr. Supported values are:
+ newreno, cubic, bbr.
+ -H option Set option string if required by congestion control algorithm.
-P number Set the default spinbit policy
-O number Set the default lossbit policy
-M Enable QUIC multipath extension
diff --git a/picoquictest/congestion_test.c b/picoquictest/congestion_test.c
index a8ad02654..992cc0283 100644
--- a/picoquictest/congestion_test.c
+++ b/picoquictest/congestion_test.c
@@ -30,6 +30,13 @@
#include "picoquic_logger.h"
#include "qlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
+
static test_api_stream_desc_t test_scenario_congestion[] = {
{ 4, 0, 257, 1000000 },
{ 8, 4, 257, 1000000 },
diff --git a/picoquictest/cpu_limited.c b/picoquictest/cpu_limited.c
index 884b36672..7162ceb81 100644
--- a/picoquictest/cpu_limited.c
+++ b/picoquictest/cpu_limited.c
@@ -30,6 +30,14 @@
#include "logreader.h"
#include "qlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
+
+
/* Add a series of tests to study the behavior of cpu-limited clients.
* This requires simulating clients that have cpu limitations, such
* as only being able to proceed a set number of messages per second.
diff --git a/picoquictest/datagram_tests.c b/picoquictest/datagram_tests.c
index 7defa7a71..8a625f747 100644
--- a/picoquictest/datagram_tests.c
+++ b/picoquictest/datagram_tests.c
@@ -42,7 +42,7 @@
#include "picoquic_logger.h"
#include "performance_log.h"
#include "picoquictest.h"
-
+#include "picoquic_bbr.h"
/*
* Test whether datagrams are sent and received properly
*/
diff --git a/picoquictest/delay_tolerant_test.c b/picoquictest/delay_tolerant_test.c
index 4e02d5fd4..4bae7b316 100644
--- a/picoquictest/delay_tolerant_test.c
+++ b/picoquictest/delay_tolerant_test.c
@@ -37,6 +37,7 @@
#include "picoquic_logger.h"
#include "performance_log.h"
#include "picoquictest.h"
+#include "picoquic_newreno.h"
/* Delay tolerant networking tests.
diff --git a/picoquictest/getter_test.c b/picoquictest/getter_test.c
index 14a911998..35d1795e0 100644
--- a/picoquictest/getter_test.c
+++ b/picoquictest/getter_test.c
@@ -26,6 +26,12 @@
#include "picoquic_utils.h"
#include "picoquictest_internal.h"
#include "picoquic.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
/* Verify that the getter/setter functions work as expected
*/
@@ -229,10 +235,13 @@ int getter_test()
ret = -1;
}
}
-
+ /* set the algorithm list to the complete value before the alogorithm set/get test
+ * Hopefully, nobody is going to call their algorithm "wuovipfwds".
+ */
+ picoquic_register_all_congestion_control_algorithms();
if (ret == 0) {
char const* alg_name[] = {
- "reno", "cubic", "dcubic", "fast", "bbr", "prague", "bbr1", "abracadabra", NULL
+ "reno", "cubic", "dcubic", "fast", "bbr", "prague", "bbr1", "wuovipfwds", NULL
};
picoquic_congestion_algorithm_t const* alg[] = {
picoquic_newreno_algorithm, picoquic_cubic_algorithm, picoquic_dcubic_algorithm,
diff --git a/picoquictest/h3zerotest.c b/picoquictest/h3zerotest.c
index a313a0179..48665c074 100644
--- a/picoquictest/h3zerotest.c
+++ b/picoquictest/h3zerotest.c
@@ -44,7 +44,7 @@
#endif
#include "autoqlog.h"
#include "picoquic_binlog.h"
-#include "picoquic_utils.h"
+#include "picoquic_bbr.h"
/*
* Test of the prefixed integer encoding
diff --git a/picoquictest/high_latency_test.c b/picoquictest/high_latency_test.c
index 9489a07da..e8ed73acb 100644
--- a/picoquictest/high_latency_test.c
+++ b/picoquictest/high_latency_test.c
@@ -37,7 +37,9 @@
#include "picoquic_logger.h"
#include "performance_log.h"
#include "picoquictest.h"
-
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
/* Very high latency test. This requires relaxing the handshake timer, so that it covers
* at least one rtt.
diff --git a/picoquictest/l4s_test.c b/picoquictest/l4s_test.c
index 557c2d43a..fb717e55a 100644
--- a/picoquictest/l4s_test.c
+++ b/picoquictest/l4s_test.c
@@ -30,6 +30,10 @@
#include "picoquic_binlog.h"
#include "logreader.h"
#include "qlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_prague.h"
static test_api_stream_desc_t test_scenario_l4s[] = {
{ 4, 0, 257, 1000000 },
diff --git a/picoquictest/mediatest.c b/picoquictest/mediatest.c
index cedb8fd2d..592fb185e 100644
--- a/picoquictest/mediatest.c
+++ b/picoquictest/mediatest.c
@@ -27,6 +27,8 @@
#include "picoquic_utils.h"
#include "picoquictest_internal.h"
#include "picoquic_binlog.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
/* Media tests: simulate media transmission, include cases in which
* the media bandwidth is much lower than the available bandwidth on
diff --git a/picoquictest/multipath_test.c b/picoquictest/multipath_test.c
index f3ad8f5a9..a851be4fe 100644
--- a/picoquictest/multipath_test.c
+++ b/picoquictest/multipath_test.c
@@ -28,6 +28,7 @@
#include "picoquic_binlog.h"
#include "logreader.h"
#include "qlog.h"
+#include "picoquic_bbr.h"
/* Add the additional links for multipath scenario */
static int multipath_test_add_links(picoquic_test_tls_api_ctx_t* test_ctx, int mtu_drop)
diff --git a/picoquictest/netperf_test.c b/picoquictest/netperf_test.c
index c80c42f64..6a97385ba 100644
--- a/picoquictest/netperf_test.c
+++ b/picoquictest/netperf_test.c
@@ -29,6 +29,7 @@
#include "picoquic_internal.h"
#include "tls_api.h"
#include "picoquictest_internal.h"
+#include "picoquic_bbr.h"
#ifdef _WINDOWS
#include "wincompat.h"
#else
diff --git a/picoquictest/pacing_test.c b/picoquictest/pacing_test.c
index 73815f50e..f856edf26 100644
--- a/picoquictest/pacing_test.c
+++ b/picoquictest/pacing_test.c
@@ -29,6 +29,12 @@
#include "picoquic_binlog.h"
#include "picoquic_logger.h"
#include "qlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
/* Test of the pacing functions.
*/
diff --git a/picoquictest/satellite_test.c b/picoquictest/satellite_test.c
index d4a3949ce..ad8331f0a 100644
--- a/picoquictest/satellite_test.c
+++ b/picoquictest/satellite_test.c
@@ -37,6 +37,10 @@
#include "picoquic_logger.h"
#include "performance_log.h"
#include "picoquictest.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
+#include "picoquic_prague.h"
/* This is similar to the long rtt test, but operating at a higher speed.
diff --git a/picoquictest/tls_api_test.c b/picoquictest/tls_api_test.c
index 1c67af239..a95cb8340 100644
--- a/picoquictest/tls_api_test.c
+++ b/picoquictest/tls_api_test.c
@@ -38,6 +38,11 @@
#include "picoquic_logger.h"
#include "performance_log.h"
#include "picoquictest.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_fastcc.h"
+#include "picoquic_prague.h"
static const uint8_t test_ticket_encrypt_key[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
@@ -12302,4 +12307,4 @@ int get_tls_errors_test()
}
return ret;
-}
\ No newline at end of file
+}
diff --git a/picoquictest/warptest.c b/picoquictest/warptest.c
index 5499fe5d6..64c579f1c 100644
--- a/picoquictest/warptest.c
+++ b/picoquictest/warptest.c
@@ -27,6 +27,7 @@
#include "picoquic_utils.h"
#include "picoquictest_internal.h"
#include "autoqlog.h"
+#include "picoquic_bbr.h"
/* Warp tests:
* These tests are very similar to the "media tests", with one twist.
diff --git a/picoquictest/wifitest.c b/picoquictest/wifitest.c
index 0a58d05a9..4a7f3d889 100644
--- a/picoquictest/wifitest.c
+++ b/picoquictest/wifitest.c
@@ -28,6 +28,10 @@
#include "picoquictest_internal.h"
#include "autoqlog.h"
#include "picoquic_binlog.h"
+#include "picoquic_newreno.h"
+#include "picoquic_cubic.h"
+#include "picoquic_bbr.h"
+#include "picoquic_bbr1.h"
/* Wifi test: explore the behavior of QUIC over Wi-Fi links.
*
@@ -79,9 +83,9 @@ typedef struct st_wifi_test_spec_t {
uint64_t latency;
wifi_test_suspension_t * suspension;
picoquic_congestion_algorithm_t* ccalgo;
+ const char* cc_algo_option;
uint64_t target_time;
int simulate_receive_block;
- uint64_t wifi_shadow_rtt;
uint64_t queue_max_delay;
} wifi_test_spec_t;
@@ -108,13 +112,8 @@ static int wifi_test_one(wifi_test_enum test_id, wifi_test_spec_t * spec)
}
if (ret == 0) {
- if (spec->wifi_shadow_rtt > 0) {
- picoquic_set_default_wifi_shadow_rtt(test_ctx->qserver, spec->wifi_shadow_rtt);
- picoquic_set_default_wifi_shadow_rtt(test_ctx->qclient, spec->wifi_shadow_rtt);
- }
-
- picoquic_set_default_congestion_algorithm(test_ctx->qserver, spec->ccalgo);
- picoquic_set_congestion_algorithm(test_ctx->cnx_client, spec->ccalgo);
+ picoquic_set_default_congestion_algorithm_ex(test_ctx->qserver, spec->ccalgo, spec->cc_algo_option);
+ picoquic_set_congestion_algorithm_ex(test_ctx->cnx_client, spec->ccalgo, spec->cc_algo_option);
test_ctx->c_to_s_link->microsec_latency = spec->latency;
test_ctx->s_to_c_link->microsec_latency = spec->latency;
@@ -214,7 +213,6 @@ void wifi_test_set_default_spec(wifi_test_spec_t* spec, picoquic_congestion_algo
spec->ccalgo = ccalgo;
spec->target_time = target_time;
spec->simulate_receive_block = 0;
- spec->wifi_shadow_rtt = 0;
spec->queue_max_delay = 260000;
}
@@ -273,6 +271,7 @@ int wifi_bbr_hard_test()
3000,
suspension_hard,
picoquic_bbr_algorithm,
+ NULL,
4060000,
0 };
int ret = wifi_test_one(wifi_test_bbr_hard, &spec);
@@ -287,6 +286,7 @@ int wifi_bbr1_hard_test()
3000,
suspension_hard,
picoquic_bbr1_algorithm,
+ NULL,
4060000,
0 };
int ret = wifi_test_one(wifi_test_bbr1_hard, &spec);
@@ -301,6 +301,7 @@ int wifi_cubic_hard_test()
3000,
suspension_hard,
picoquic_cubic_algorithm,
+ NULL,
4700000,
0 };
int ret = wifi_test_one(wifi_test_cubic_hard, &spec);
@@ -315,6 +316,7 @@ int wifi_reno_hard_test()
3000,
suspension_hard,
picoquic_newreno_algorithm,
+ NULL,
4250000,
0 };
int ret = wifi_test_one(wifi_test_reno_hard, &spec);
@@ -329,6 +331,7 @@ int wifi_bbr_long_test()
50000,
suspension_basic,
picoquic_bbr_algorithm,
+ NULL,
3400000,
1 };
int ret = wifi_test_one(wifi_test_bbr_long, &spec);
@@ -343,6 +346,7 @@ int wifi_bbr1_long_test()
50000,
suspension_basic,
picoquic_bbr1_algorithm,
+ NULL,
3400000,
1 };
int ret = wifi_test_one(wifi_test_bbr1_long, &spec);
@@ -377,7 +381,7 @@ int wifi_bbr_shadow_test()
{
wifi_test_spec_t spec;
wifi_test_set_default_spec(&spec, picoquic_bbr_algorithm, 2750000);
- spec.wifi_shadow_rtt = 250000;
+ spec.cc_algo_option = "T250000";
spec.queue_max_delay = 600000;
spec.simulate_receive_block = 1;
@@ -404,6 +408,7 @@ int wifi_bbr_many_test()
3000,
suspension_many,
picoquic_bbr_algorithm,
+ NULL,
4070000,
0 };
int ret = wifi_test_one(wifi_test_bbr_many, &spec);
diff --git a/quicwind/quicwind_proc.c b/quicwind/quicwind_proc.c
index e62c24b51..8c46696e4 100644
--- a/quicwind/quicwind_proc.c
+++ b/quicwind/quicwind_proc.c
@@ -19,6 +19,7 @@
#include "democlient.h"
#include "quicwind.h"
#include "autoqlog.h"
+#include "picoquic_cubic.h"
#ifndef SOCKET_TYPE
#define SOCKET_TYPE SOCKET
diff --git a/sample/sample_background.c b/sample/sample_background.c
index 6aa1f496b..b64203286 100644
--- a/sample/sample_background.c
+++ b/sample/sample_background.c
@@ -47,6 +47,7 @@
#include
#include
#include "picoquic_sample.h"
+#include "picoquic_bbr.h"
/* Background thread management:
*
diff --git a/sample/sample_client.c b/sample/sample_client.c
index 639ff3e56..656e4418c 100644
--- a/sample/sample_client.c
+++ b/sample/sample_client.c
@@ -47,6 +47,7 @@
#include
#include
#include "picoquic_sample.h"
+#include "picoquic_bbr.h"
/* Client context and callback management:
*
diff --git a/sample/sample_server.c b/sample/sample_server.c
index 1bf4058d7..26057dcf6 100644
--- a/sample/sample_server.c
+++ b/sample/sample_server.c
@@ -47,6 +47,7 @@
#include
#include "picoquic_sample.h"
#include "picoquic_packet_loop.h"
+#include "picoquic_bbr.h"
/* Server context and callback management:
*