1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2b1a7c3f9SDmitri Tikhonov/* lsquic_adaptive_cc.c -- adaptive congestion controller */ 3b1a7c3f9SDmitri Tikhonov 4b1a7c3f9SDmitri Tikhonov#include <inttypes.h> 5b1a7c3f9SDmitri Tikhonov#include <math.h> 6b1a7c3f9SDmitri Tikhonov#include <stddef.h> 7b1a7c3f9SDmitri Tikhonov#include <stdlib.h> 8b1a7c3f9SDmitri Tikhonov#include <string.h> 9b1a7c3f9SDmitri Tikhonov#include <sys/queue.h> 10b1a7c3f9SDmitri Tikhonov#ifdef WIN32 11b1a7c3f9SDmitri Tikhonov#include <vc_compat.h> 12b1a7c3f9SDmitri Tikhonov#endif 13b1a7c3f9SDmitri Tikhonov 14b1a7c3f9SDmitri Tikhonov#include "lsquic_int_types.h" 15b1a7c3f9SDmitri Tikhonov#include "lsquic_types.h" 16b1a7c3f9SDmitri Tikhonov#include "lsquic_hash.h" 17b1a7c3f9SDmitri Tikhonov#include "lsquic_util.h" 18b1a7c3f9SDmitri Tikhonov#include "lsquic_cong_ctl.h" 19b1a7c3f9SDmitri Tikhonov#include "lsquic_sfcw.h" 20b1a7c3f9SDmitri Tikhonov#include "lsquic_conn_flow.h" 21b1a7c3f9SDmitri Tikhonov#include "lsquic_varint.h" 22b1a7c3f9SDmitri Tikhonov#include "lsquic_hq.h" 23b1a7c3f9SDmitri Tikhonov#include "lsquic_stream.h" 24b1a7c3f9SDmitri Tikhonov#include "lsquic_rtt.h" 25b1a7c3f9SDmitri Tikhonov#include "lsquic_conn_public.h" 26b1a7c3f9SDmitri Tikhonov#include "lsquic_packet_common.h" 27b1a7c3f9SDmitri Tikhonov#include "lsquic_packet_out.h" 28b1a7c3f9SDmitri Tikhonov#include "lsquic_bw_sampler.h" 29b1a7c3f9SDmitri Tikhonov#include "lsquic_minmax.h" 30b1a7c3f9SDmitri Tikhonov#include "lsquic_bbr.h" 31b1a7c3f9SDmitri Tikhonov#include "lsquic_cubic.h" 32b1a7c3f9SDmitri Tikhonov#include "lsquic_adaptive_cc.h" 33b1a7c3f9SDmitri Tikhonov 34b1a7c3f9SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_ADAPTIVE_CC 35b1a7c3f9SDmitri Tikhonov#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(acc->acc_cubic.cu_conn) 36b1a7c3f9SDmitri Tikhonov#include "lsquic_logger.h" 37b1a7c3f9SDmitri Tikhonov 38b1a7c3f9SDmitri Tikhonov 39b1a7c3f9SDmitri Tikhonov#define CALL_BOTH(method, ...) do { \ 40b1a7c3f9SDmitri Tikhonov lsquic_cong_bbr_if.method(&acc->acc_bbr, __VA_ARGS__); \ 41b1a7c3f9SDmitri Tikhonov lsquic_cong_cubic_if.method(&acc->acc_cubic, __VA_ARGS__); \ 42b1a7c3f9SDmitri Tikhonov} while (0) 43b1a7c3f9SDmitri Tikhonov 44b1a7c3f9SDmitri Tikhonov 45b1a7c3f9SDmitri Tikhonov#define CALL_BOTH_MAYBE(method, ...) do { \ 46b1a7c3f9SDmitri Tikhonov if (lsquic_cong_bbr_if.method) \ 47b1a7c3f9SDmitri Tikhonov lsquic_cong_bbr_if.method(&acc->acc_bbr, __VA_ARGS__); \ 48b1a7c3f9SDmitri Tikhonov if (lsquic_cong_cubic_if.method) \ 49b1a7c3f9SDmitri Tikhonov lsquic_cong_cubic_if.method(&acc->acc_cubic, __VA_ARGS__); \ 50b1a7c3f9SDmitri Tikhonov} while (0) 51b1a7c3f9SDmitri Tikhonov 52b1a7c3f9SDmitri Tikhonov 53b1a7c3f9SDmitri Tikhonov#define CALL_BOTH0(method) do { \ 54b1a7c3f9SDmitri Tikhonov lsquic_cong_bbr_if.method(&acc->acc_bbr); \ 55b1a7c3f9SDmitri Tikhonov lsquic_cong_cubic_if.method(&acc->acc_cubic); \ 56b1a7c3f9SDmitri Tikhonov} while (0) 57b1a7c3f9SDmitri Tikhonov 58b1a7c3f9SDmitri Tikhonov 59b1a7c3f9SDmitri Tikhonovstatic void 60b1a7c3f9SDmitri Tikhonovadaptive_cc_init (void *cong_ctl, const struct lsquic_conn_public *conn_pub, 61b1a7c3f9SDmitri Tikhonov enum quic_ft_bit retx_frames) 62b1a7c3f9SDmitri Tikhonov{ 63b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 64b1a7c3f9SDmitri Tikhonov 65b1a7c3f9SDmitri Tikhonov CALL_BOTH(cci_init, conn_pub, retx_frames); 66b1a7c3f9SDmitri Tikhonov LSQ_DEBUG("initialized"); 67b1a7c3f9SDmitri Tikhonov} 68b1a7c3f9SDmitri Tikhonov 69b1a7c3f9SDmitri Tikhonov 70b1a7c3f9SDmitri Tikhonovstatic void 71b1a7c3f9SDmitri Tikhonovadaptive_cc_reinit (void *cong_ctl) 72b1a7c3f9SDmitri Tikhonov{ 73b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 74b1a7c3f9SDmitri Tikhonov 75b1a7c3f9SDmitri Tikhonov CALL_BOTH0(cci_reinit); 76b1a7c3f9SDmitri Tikhonov} 77b1a7c3f9SDmitri Tikhonov 78b1a7c3f9SDmitri Tikhonov 79b1a7c3f9SDmitri Tikhonovstatic void 80b1a7c3f9SDmitri Tikhonovadaptive_cc_ack (void *cong_ctl, struct lsquic_packet_out *packet_out, 81b1a7c3f9SDmitri Tikhonov unsigned packet_sz, lsquic_time_t now, int app_limited) 82b1a7c3f9SDmitri Tikhonov{ 83b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 84b1a7c3f9SDmitri Tikhonov 85b1a7c3f9SDmitri Tikhonov CALL_BOTH(cci_ack, packet_out, packet_sz, now, app_limited); 86b1a7c3f9SDmitri Tikhonov} 87b1a7c3f9SDmitri Tikhonov 88b1a7c3f9SDmitri Tikhonov 89b1a7c3f9SDmitri Tikhonovstatic void 90b1a7c3f9SDmitri Tikhonovadaptive_cc_loss (void *cong_ctl) 91b1a7c3f9SDmitri Tikhonov{ 92b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 93b1a7c3f9SDmitri Tikhonov 94b1a7c3f9SDmitri Tikhonov CALL_BOTH0(cci_loss); 95b1a7c3f9SDmitri Tikhonov} 96b1a7c3f9SDmitri Tikhonov 97b1a7c3f9SDmitri Tikhonov 98b1a7c3f9SDmitri Tikhonovstatic void 99b1a7c3f9SDmitri Tikhonovadaptive_cc_begin_ack (void *cong_ctl, lsquic_time_t ack_time, 100b1a7c3f9SDmitri Tikhonov uint64_t in_flight) 101b1a7c3f9SDmitri Tikhonov{ 102b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 103b1a7c3f9SDmitri Tikhonov 104b1a7c3f9SDmitri Tikhonov CALL_BOTH_MAYBE(cci_begin_ack, ack_time, in_flight); 105b1a7c3f9SDmitri Tikhonov} 106b1a7c3f9SDmitri Tikhonov 107b1a7c3f9SDmitri Tikhonov 108b1a7c3f9SDmitri Tikhonovstatic void 109b1a7c3f9SDmitri Tikhonovadaptive_cc_end_ack (void *cong_ctl, uint64_t in_flight) 110b1a7c3f9SDmitri Tikhonov{ 111b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 112b1a7c3f9SDmitri Tikhonov 113b1a7c3f9SDmitri Tikhonov CALL_BOTH_MAYBE(cci_end_ack, in_flight); 114b1a7c3f9SDmitri Tikhonov} 115b1a7c3f9SDmitri Tikhonov 116b1a7c3f9SDmitri Tikhonov 117b1a7c3f9SDmitri Tikhonovstatic void 118b1a7c3f9SDmitri Tikhonovadaptive_cc_sent (void *cong_ctl, struct lsquic_packet_out *packet_out, 119b1a7c3f9SDmitri Tikhonov uint64_t in_flight, int app_limited) 120b1a7c3f9SDmitri Tikhonov{ 121b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 122b1a7c3f9SDmitri Tikhonov 123b1a7c3f9SDmitri Tikhonov CALL_BOTH_MAYBE(cci_sent, packet_out, in_flight, app_limited); 124b1a7c3f9SDmitri Tikhonov} 125b1a7c3f9SDmitri Tikhonov 126b1a7c3f9SDmitri Tikhonov 127b1a7c3f9SDmitri Tikhonovstatic void 128b1a7c3f9SDmitri Tikhonovadaptive_cc_lost (void *cong_ctl, struct lsquic_packet_out *packet_out, 129b1a7c3f9SDmitri Tikhonov unsigned packet_sz) 130b1a7c3f9SDmitri Tikhonov{ 131b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 132b1a7c3f9SDmitri Tikhonov 133b1a7c3f9SDmitri Tikhonov CALL_BOTH_MAYBE(cci_lost, packet_out, packet_sz); 134b1a7c3f9SDmitri Tikhonov} 135b1a7c3f9SDmitri Tikhonov 136b1a7c3f9SDmitri Tikhonov 137b1a7c3f9SDmitri Tikhonovstatic void 138b1a7c3f9SDmitri Tikhonovadaptive_cc_timeout (void *cong_ctl) 139b1a7c3f9SDmitri Tikhonov{ 140b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 141b1a7c3f9SDmitri Tikhonov 142b1a7c3f9SDmitri Tikhonov CALL_BOTH0(cci_timeout); 143b1a7c3f9SDmitri Tikhonov} 144b1a7c3f9SDmitri Tikhonov 145b1a7c3f9SDmitri Tikhonov 146b1a7c3f9SDmitri Tikhonovstatic void 147b1a7c3f9SDmitri Tikhonovadaptive_cc_was_quiet (void *cong_ctl, lsquic_time_t now, uint64_t in_flight) 148b1a7c3f9SDmitri Tikhonov{ 149b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 150b1a7c3f9SDmitri Tikhonov 151b1a7c3f9SDmitri Tikhonov CALL_BOTH(cci_was_quiet, now, in_flight); 152b1a7c3f9SDmitri Tikhonov} 153b1a7c3f9SDmitri Tikhonov 154b1a7c3f9SDmitri Tikhonov 155b1a7c3f9SDmitri Tikhonovstatic uint64_t 156b1a7c3f9SDmitri Tikhonovadaptive_cc_get_cwnd (void *cong_ctl) 157b1a7c3f9SDmitri Tikhonov{ 158b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 159b1a7c3f9SDmitri Tikhonov uint64_t rv[2]; 160b1a7c3f9SDmitri Tikhonov 161b1a7c3f9SDmitri Tikhonov rv[0] = lsquic_cong_cubic_if.cci_get_cwnd(&acc->acc_cubic); 162b1a7c3f9SDmitri Tikhonov rv[1] = lsquic_cong_bbr_if.cci_get_cwnd(&acc->acc_bbr); 163b1a7c3f9SDmitri Tikhonov 164b1a7c3f9SDmitri Tikhonov if (acc->acc_flags & ACC_CUBIC) 165b1a7c3f9SDmitri Tikhonov return rv[0]; 166b1a7c3f9SDmitri Tikhonov else 167b1a7c3f9SDmitri Tikhonov return rv[1]; 168b1a7c3f9SDmitri Tikhonov} 169b1a7c3f9SDmitri Tikhonov 170b1a7c3f9SDmitri Tikhonov 171b1a7c3f9SDmitri Tikhonovstatic uint64_t 172b1a7c3f9SDmitri Tikhonovadaptive_cc_pacing_rate (void *cong_ctl, int in_recovery) 173b1a7c3f9SDmitri Tikhonov{ 174b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 175b1a7c3f9SDmitri Tikhonov uint64_t rv[2]; 176b1a7c3f9SDmitri Tikhonov 177b1a7c3f9SDmitri Tikhonov rv[0] = lsquic_cong_cubic_if.cci_pacing_rate(&acc->acc_cubic, in_recovery); 178b1a7c3f9SDmitri Tikhonov rv[1] = lsquic_cong_bbr_if.cci_pacing_rate(&acc->acc_bbr, in_recovery); 179b1a7c3f9SDmitri Tikhonov 180b1a7c3f9SDmitri Tikhonov if (acc->acc_flags & ACC_CUBIC) 181b1a7c3f9SDmitri Tikhonov return rv[0]; 182b1a7c3f9SDmitri Tikhonov else 183b1a7c3f9SDmitri Tikhonov return rv[1]; 184b1a7c3f9SDmitri Tikhonov} 185b1a7c3f9SDmitri Tikhonov 186b1a7c3f9SDmitri Tikhonov 187b1a7c3f9SDmitri Tikhonovstatic void 188b1a7c3f9SDmitri Tikhonovadaptive_cc_cleanup (void *cong_ctl) 189b1a7c3f9SDmitri Tikhonov{ 190b1a7c3f9SDmitri Tikhonov struct adaptive_cc *const acc = cong_ctl; 191b1a7c3f9SDmitri Tikhonov 192b1a7c3f9SDmitri Tikhonov CALL_BOTH0(cci_cleanup); 193b1a7c3f9SDmitri Tikhonov LSQ_DEBUG("cleanup"); 194b1a7c3f9SDmitri Tikhonov} 195b1a7c3f9SDmitri Tikhonov 196b1a7c3f9SDmitri Tikhonov 197b1a7c3f9SDmitri Tikhonovconst struct cong_ctl_if lsquic_cong_adaptive_if = 198b1a7c3f9SDmitri Tikhonov{ 199b1a7c3f9SDmitri Tikhonov .cci_ack = adaptive_cc_ack, 200b1a7c3f9SDmitri Tikhonov .cci_begin_ack = adaptive_cc_begin_ack, 201b1a7c3f9SDmitri Tikhonov .cci_end_ack = adaptive_cc_end_ack, 202b1a7c3f9SDmitri Tikhonov .cci_cleanup = adaptive_cc_cleanup, 203b1a7c3f9SDmitri Tikhonov .cci_get_cwnd = adaptive_cc_get_cwnd, 204b1a7c3f9SDmitri Tikhonov .cci_init = adaptive_cc_init, 205b1a7c3f9SDmitri Tikhonov .cci_pacing_rate = adaptive_cc_pacing_rate, 206b1a7c3f9SDmitri Tikhonov .cci_loss = adaptive_cc_loss, 207b1a7c3f9SDmitri Tikhonov .cci_lost = adaptive_cc_lost, 208b1a7c3f9SDmitri Tikhonov .cci_reinit = adaptive_cc_reinit, 209b1a7c3f9SDmitri Tikhonov .cci_timeout = adaptive_cc_timeout, 210b1a7c3f9SDmitri Tikhonov .cci_sent = adaptive_cc_sent, 211b1a7c3f9SDmitri Tikhonov .cci_was_quiet = adaptive_cc_was_quiet, 212b1a7c3f9SDmitri Tikhonov}; 213