213 lines
5.3 KiB
C
213 lines
5.3 KiB
C
/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */
|
|
/* lsquic_adaptive_cc.c -- adaptive congestion controller */
|
|
|
|
#include <inttypes.h>
|
|
#include <math.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/queue.h>
|
|
#ifdef WIN32
|
|
#include <vc_compat.h>
|
|
#endif
|
|
|
|
#include "lsquic_int_types.h"
|
|
#include "lsquic_types.h"
|
|
#include "lsquic_hash.h"
|
|
#include "lsquic_util.h"
|
|
#include "lsquic_cong_ctl.h"
|
|
#include "lsquic_sfcw.h"
|
|
#include "lsquic_conn_flow.h"
|
|
#include "lsquic_varint.h"
|
|
#include "lsquic_hq.h"
|
|
#include "lsquic_stream.h"
|
|
#include "lsquic_rtt.h"
|
|
#include "lsquic_conn_public.h"
|
|
#include "lsquic_packet_common.h"
|
|
#include "lsquic_packet_out.h"
|
|
#include "lsquic_bw_sampler.h"
|
|
#include "lsquic_minmax.h"
|
|
#include "lsquic_bbr.h"
|
|
#include "lsquic_cubic.h"
|
|
#include "lsquic_adaptive_cc.h"
|
|
|
|
#define LSQUIC_LOGGER_MODULE LSQLM_ADAPTIVE_CC
|
|
#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(acc->acc_cubic.cu_conn)
|
|
#include "lsquic_logger.h"
|
|
|
|
|
|
#define CALL_BOTH(method, ...) do { \
|
|
lsquic_cong_bbr_if.method(&acc->acc_bbr, __VA_ARGS__); \
|
|
lsquic_cong_cubic_if.method(&acc->acc_cubic, __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
|
|
#define CALL_BOTH_MAYBE(method, ...) do { \
|
|
if (lsquic_cong_bbr_if.method) \
|
|
lsquic_cong_bbr_if.method(&acc->acc_bbr, __VA_ARGS__); \
|
|
if (lsquic_cong_cubic_if.method) \
|
|
lsquic_cong_cubic_if.method(&acc->acc_cubic, __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
|
|
#define CALL_BOTH0(method) do { \
|
|
lsquic_cong_bbr_if.method(&acc->acc_bbr); \
|
|
lsquic_cong_cubic_if.method(&acc->acc_cubic); \
|
|
} while (0)
|
|
|
|
|
|
static void
|
|
adaptive_cc_init (void *cong_ctl, const struct lsquic_conn_public *conn_pub,
|
|
enum quic_ft_bit retx_frames)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH(cci_init, conn_pub, retx_frames);
|
|
LSQ_DEBUG("initialized");
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_reinit (void *cong_ctl)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH0(cci_reinit);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_ack (void *cong_ctl, struct lsquic_packet_out *packet_out,
|
|
unsigned packet_sz, lsquic_time_t now, int app_limited)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH(cci_ack, packet_out, packet_sz, now, app_limited);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_loss (void *cong_ctl)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH0(cci_loss);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_begin_ack (void *cong_ctl, lsquic_time_t ack_time,
|
|
uint64_t in_flight)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH_MAYBE(cci_begin_ack, ack_time, in_flight);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_end_ack (void *cong_ctl, uint64_t in_flight)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH_MAYBE(cci_end_ack, in_flight);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_sent (void *cong_ctl, struct lsquic_packet_out *packet_out,
|
|
uint64_t in_flight, int app_limited)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH_MAYBE(cci_sent, packet_out, in_flight, app_limited);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_lost (void *cong_ctl, struct lsquic_packet_out *packet_out,
|
|
unsigned packet_sz)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH_MAYBE(cci_lost, packet_out, packet_sz);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_timeout (void *cong_ctl)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH0(cci_timeout);
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_was_quiet (void *cong_ctl, lsquic_time_t now, uint64_t in_flight)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH(cci_was_quiet, now, in_flight);
|
|
}
|
|
|
|
|
|
static uint64_t
|
|
adaptive_cc_get_cwnd (void *cong_ctl)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
uint64_t rv[2];
|
|
|
|
rv[0] = lsquic_cong_cubic_if.cci_get_cwnd(&acc->acc_cubic);
|
|
rv[1] = lsquic_cong_bbr_if.cci_get_cwnd(&acc->acc_bbr);
|
|
|
|
if (acc->acc_flags & ACC_CUBIC)
|
|
return rv[0];
|
|
else
|
|
return rv[1];
|
|
}
|
|
|
|
|
|
static uint64_t
|
|
adaptive_cc_pacing_rate (void *cong_ctl, int in_recovery)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
uint64_t rv[2];
|
|
|
|
rv[0] = lsquic_cong_cubic_if.cci_pacing_rate(&acc->acc_cubic, in_recovery);
|
|
rv[1] = lsquic_cong_bbr_if.cci_pacing_rate(&acc->acc_bbr, in_recovery);
|
|
|
|
if (acc->acc_flags & ACC_CUBIC)
|
|
return rv[0];
|
|
else
|
|
return rv[1];
|
|
}
|
|
|
|
|
|
static void
|
|
adaptive_cc_cleanup (void *cong_ctl)
|
|
{
|
|
struct adaptive_cc *const acc = cong_ctl;
|
|
|
|
CALL_BOTH0(cci_cleanup);
|
|
LSQ_DEBUG("cleanup");
|
|
}
|
|
|
|
|
|
const struct cong_ctl_if lsquic_cong_adaptive_if =
|
|
{
|
|
.cci_ack = adaptive_cc_ack,
|
|
.cci_begin_ack = adaptive_cc_begin_ack,
|
|
.cci_end_ack = adaptive_cc_end_ack,
|
|
.cci_cleanup = adaptive_cc_cleanup,
|
|
.cci_get_cwnd = adaptive_cc_get_cwnd,
|
|
.cci_init = adaptive_cc_init,
|
|
.cci_pacing_rate = adaptive_cc_pacing_rate,
|
|
.cci_loss = adaptive_cc_loss,
|
|
.cci_lost = adaptive_cc_lost,
|
|
.cci_reinit = adaptive_cc_reinit,
|
|
.cci_timeout = adaptive_cc_timeout,
|
|
.cci_sent = adaptive_cc_sent,
|
|
.cci_was_quiet = adaptive_cc_was_quiet,
|
|
};
|