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