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

Introduce generic slowstart algorithms for congestion control #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ SET(QUICLY_LIBRARY_FILES
lib/remote_cid.c
lib/retire_cid.c
lib/sendstate.c
lib/ss-rfc2001.c
lib/ss-search.c
lib/sentmap.c
lib/streambuf.c
${CMAKE_CURRENT_BINARY_DIR}/quicly-tracer.h)
Expand Down
5 changes: 5 additions & 0 deletions include/quicly.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extern "C" {
#include "quicly/local_cid.h"
#include "quicly/linklist.h"
#include "quicly/loss.h"
#include "quicly/ss.h"
#include "quicly/cc.h"
#include "quicly/rate.h"
#include "quicly/recvstate.h"
Expand Down Expand Up @@ -401,6 +402,10 @@ struct st_quicly_context_t {
* initializes a congestion controller for given connection.
*/
quicly_init_cc_t *init_cc;
/**
* set the slowstart function for the connection
*/
quicly_ss_type_t *cc_slowstart;
/**
* optional refcount callback
*/
Expand Down
33 changes: 33 additions & 0 deletions include/quicly/cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ extern "C" {
#define QUICLY_MIN_CWND 2
#define QUICLY_RENO_BETA 0.7

#define QUICLY_SEARCH_DELV_BIN_COUNT (10) // number of search delivered bytes bins
#define QUICLY_SEARCH_TOTAL_BIN_COUNT (25) // number of search sent bytes bins
#define QUICLY_SEARCH_WINDOW_MULTIPLIER (3.5) // search multiplier for window calculation
#define QUICLY_SEARCH_THRESH (0.35) // search threshold to exit slow start phase

/**
* Holds pointers to concrete congestion control implementation functions.
*/
Expand All @@ -58,6 +63,30 @@ typedef struct st_quicly_cc_t {
* Current slow start threshold.
*/
uint32_t ssthresh;
/**
* Slow-start specific data storage
*/
union {
struct {
/**
* Bins for the byte count sent and the byte count delivered (instantiated on init)
*/
uint64_t delv_bins[QUICLY_SEARCH_TOTAL_BIN_COUNT];
/**
* Maintains the end time of the current bin
*/
int64_t bin_end;
/**
* Holds the size of each bin (based on the handshake RTT)
*/
uint32_t bin_time;
/**
* Counts the number of times that the bin has been incremented, so we know when to
* start trying to watch for congestion
*/
uint32_t bin_rounds;
} search;
} ss_state;
/**
* Packet number indicating end of recovery period, if in recovery.
*/
Expand Down Expand Up @@ -202,6 +231,10 @@ struct st_quicly_cc_type_t {
* Switches the underlying algorithm of `cc` to that of `cc_switch`, returning a boolean if the operation was successful.
*/
int (*cc_switch)(quicly_cc_t *cc);
/*
* Defines a slowstart callback
*/
struct st_quicly_ss_type_t *cc_slowstart;
/**
*
*/
Expand Down
1 change: 1 addition & 0 deletions include/quicly/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ extern quicly_crypto_engine_t quicly_default_crypto_engine;

#define quicly_default_cc quicly_cc_type_reno
#define quicly_default_init_cc quicly_cc_reno_init
#define quicly_default_ss quicly_ss_type_rfc2001

#ifdef __cplusplus
}
Expand Down
55 changes: 55 additions & 0 deletions include/quicly/ss.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 Viasat Inc.
* Authors: Amber Cronin, Jae Won Chung, Mike Foxworthy, Vittorio Parrella, Feng Li, Mark Claypool
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#ifndef quicly_ss_h
#define quicly_ss_h

#ifdef __cplusplus
extern "C" {
#endif

#include "quicly/cc.h"
#include "quicly/constants.h"
#include <stdint.h>
#include <stdbool.h>

/**
* Holds pointers to concrete congestion control implementation functions.
*/
typedef struct st_quicly_ss_type_t quicly_ss_type_t;

struct st_quicly_ss_type_t {
const char* name;
void (*ss)(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t largest_acked, uint32_t inflight,
uint64_t next_pn, int64_t now, uint32_t max_udp_payload_size);
};

extern quicly_ss_type_t quicly_ss_type_rfc2001, quicly_ss_type_search, quicly_ss_type_disabled;

extern quicly_ss_type_t* quicly_ss_all_types[];

#ifdef __cplusplus
}
#endif

#endif
12 changes: 6 additions & 6 deletions lib/cc-cubic.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
*/
#include <math.h>
#include "quicly/cc.h"
#include "quicly/defaults.h"
#include "quicly.h"
#include "quicly/pacer.h"
#include "quicly/ss.h"

#define QUICLY_MIN_CWND 2

Expand Down Expand Up @@ -73,13 +75,11 @@ static void cubic_on_acked(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t

quicly_cc_jumpstart_on_acked(cc, 0, bytes, largest_acked, inflight, next_pn);

/* TODO: respect cc_limited */

/* Slow start. */
if (cc->cwnd < cc->ssthresh) {
cc->cwnd += bytes;
if (cc->cwnd_maximum < cc->cwnd)
cc->cwnd_maximum = cc->cwnd;
if (cc_limited) {
cc->type->cc_slowstart->ss(cc, loss, bytes, largest_acked, inflight, next_pn, now, max_udp_payload_size);
}
return;
}

Expand Down Expand Up @@ -208,5 +208,5 @@ static void cubic_init(quicly_init_cc_t *self, quicly_cc_t *cc, uint32_t initcwn

quicly_cc_type_t quicly_cc_type_cubic = {"cubic", &quicly_cc_cubic_init, cubic_on_acked,
cubic_on_lost, cubic_on_persistent_congestion, cubic_on_sent,
cubic_on_switch, quicly_cc_jumpstart_enter};
cubic_on_switch, &quicly_default_ss, quicly_cc_jumpstart_enter};
quicly_init_cc_t quicly_cc_cubic_init = {cubic_init};
3 changes: 2 additions & 1 deletion lib/cc-pico.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,6 @@ static void pico_init(quicly_init_cc_t *self, quicly_cc_t *cc, uint32_t initcwnd

quicly_cc_type_t quicly_cc_type_pico = {"pico", &quicly_cc_pico_init, pico_on_acked,
pico_on_lost, pico_on_persistent_congestion, pico_on_sent,
pico_on_switch, quicly_cc_jumpstart_enter};
pico_on_switch, &quicly_ss_type_disabled,
quicly_cc_jumpstart_enter};
quicly_init_cc_t quicly_cc_pico_init = {pico_init};
12 changes: 6 additions & 6 deletions lib/cc-reno.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* IN THE SOFTWARE.
*/
#include "quicly/cc.h"
#include "quicly/defaults.h"
#include "quicly.h"

/* TODO: Avoid increase if sender was application limited. */
Expand All @@ -38,12 +39,10 @@ static void reno_on_acked(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t b

/* Slow start. */
if (cc->cwnd < cc->ssthresh) {
if (cc_limited) {
cc->cwnd += bytes;
if (cc->cwnd_maximum < cc->cwnd)
cc->cwnd_maximum = cc->cwnd;
}
return;
if (cc_limited) {
cc->type->cc_slowstart->ss(cc, loss, bytes, largest_acked, inflight, next_pn, now, max_udp_payload_size);
}
return;
}
/* Congestion avoidance. */
if (!cc_limited)
Expand Down Expand Up @@ -143,6 +142,7 @@ quicly_cc_type_t quicly_cc_type_reno = {"reno",
quicly_cc_reno_on_persistent_congestion,
quicly_cc_reno_on_sent,
reno_on_switch,
&quicly_default_ss,
quicly_cc_jumpstart_enter};
quicly_init_cc_t quicly_cc_reno_init = {reno_init};

Expand Down
6 changes: 4 additions & 2 deletions lib/defaults.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const quicly_context_t quicly_spec_context = {NULL,
NULL,
NULL,
&quicly_default_crypto_engine,
&quicly_default_init_cc};
&quicly_default_init_cc,
&quicly_default_ss};

/* profile with a focus on reducing latency for the HTTP use case */
const quicly_context_t quicly_performant_context = {NULL, /* tls */
Expand Down Expand Up @@ -105,7 +106,8 @@ const quicly_context_t quicly_performant_context = {NULL,
NULL,
NULL,
&quicly_default_crypto_engine,
&quicly_default_init_cc};
&quicly_default_init_cc,
&quicly_default_ss};

/**
* The context of the default CID encryptor. All the contexts being used here are ECB ciphers and therefore stateless - they can be
Expand Down
5 changes: 5 additions & 0 deletions lib/quicly.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "quicly/sentmap.h"
#include "quicly/pacer.h"
#include "quicly/frame.h"
#include "quicly/ss.h"
#include "quicly/streambuf.h"
#include "quicly/cc.h"
#if QUICLY_USE_DTRACE
Expand Down Expand Up @@ -2570,6 +2571,10 @@ static quicly_conn_t *create_connection(quicly_context_t *ctx, uint32_t protocol
conn->egress.send_ack_at = INT64_MAX;
conn->egress.send_probe_at = INT64_MAX;
conn->super.ctx->init_cc->cb(conn->super.ctx->init_cc, &conn->egress.cc, initcwnd, conn->stash.now);
if (conn->super.ctx->cc_slowstart != NULL) {
conn->egress.cc.type->cc_slowstart->name = conn->super.ctx->cc_slowstart->name;
conn->egress.cc.type->cc_slowstart->ss = conn->super.ctx->cc_slowstart->ss;
}
if (pacer != NULL) {
conn->egress.pacer = pacer;
quicly_pacer_reset(conn->egress.pacer);
Expand Down
49 changes: 49 additions & 0 deletions lib/ss-rfc2001.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2024 Viasat Inc.
* Authors: Amber Cronin, Jae Won Chung, Mike Foxworthy, Vittorio Parrella, Feng Li, Mark Claypool
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "quicly/ss.h"

/*
* Default TCP Slow start (RFC 2001) algorithm implementing exponential growth
* of congestion window (cwnd) -- doubling cwnd every RTT.
* Same slow start algorithm defined in RFC 9000 for QUIC
*
*/

void ss_quicly_default(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t largest_acked, uint32_t inflight,
uint64_t next_pn, int64_t now, uint32_t max_udp_payload_size)
{
cc->cwnd += bytes;
if (cc->cwnd_maximum < cc->cwnd)
cc->cwnd_maximum = cc->cwnd;
}

quicly_ss_type_t quicly_ss_type_rfc2001= { "rfc2001", ss_quicly_default };

void ss_quicly_disabled(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t largest_acked, uint32_t inflight,
uint64_t next_pn, int64_t now, uint32_t max_udp_payload_size)
{}

quicly_ss_type_t quicly_ss_type_disabled = { "disabled", ss_quicly_disabled };

quicly_ss_type_t* quicly_ss_all_types[] = { &quicly_ss_type_disabled, &quicly_ss_type_rfc2001, &quicly_ss_type_search, NULL };
Loading