1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov#include <inttypes.h> 350aadb33SDmitri Tikhonov#include <stdint.h> 450aadb33SDmitri Tikhonov#include <stdlib.h> 550aadb33SDmitri Tikhonov#include <string.h> 650aadb33SDmitri Tikhonov#include <sys/queue.h> 750aadb33SDmitri Tikhonov 850aadb33SDmitri Tikhonov#include "lsquic.h" 950aadb33SDmitri Tikhonov#include "lsquic_types.h" 1050aadb33SDmitri Tikhonov#include "lsquic_int_types.h" 1150aadb33SDmitri Tikhonov#include "lsquic_rtt.h" 1250aadb33SDmitri Tikhonov#include "lsquic_conn_flow.h" 1350aadb33SDmitri Tikhonov#include "lsquic_sfcw.h" 145392f7a3SLiteSpeed Tech#include "lsquic_varint.h" 155392f7a3SLiteSpeed Tech#include "lsquic_hq.h" 165392f7a3SLiteSpeed Tech#include "lsquic_hash.h" 1750aadb33SDmitri Tikhonov#include "lsquic_stream.h" 1850aadb33SDmitri Tikhonov#include "lsquic_conn_public.h" 1950aadb33SDmitri Tikhonov#include "lsquic_mm.h" 2050aadb33SDmitri Tikhonov#include "lsquic_engine_public.h" 2150aadb33SDmitri Tikhonov#include "lsquic_util.h" 2250aadb33SDmitri Tikhonov#include "lsquic_conn.h" 2350aadb33SDmitri Tikhonov#include "lsquic_ev_log.h" 2450aadb33SDmitri Tikhonov 2550aadb33SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_CFCW 265392f7a3SLiteSpeed Tech#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(fc->cf_conn_pub->lconn) 2750aadb33SDmitri Tikhonov#include "lsquic_logger.h" 2850aadb33SDmitri Tikhonov 2950aadb33SDmitri Tikhonov 3050aadb33SDmitri Tikhonovvoid 3150aadb33SDmitri Tikhonovlsquic_cfcw_init (struct lsquic_cfcw *fc, struct lsquic_conn_public *cpub, 3250aadb33SDmitri Tikhonov unsigned max_recv_window) 3350aadb33SDmitri Tikhonov{ 3450aadb33SDmitri Tikhonov memset(fc, 0, sizeof(*fc)); 3550aadb33SDmitri Tikhonov fc->cf_max_recv_win = max_recv_window; 3650aadb33SDmitri Tikhonov fc->cf_conn_pub = cpub; 3750aadb33SDmitri Tikhonov (void) lsquic_cfcw_fc_offsets_changed(fc); 3850aadb33SDmitri Tikhonov} 3950aadb33SDmitri Tikhonov 4050aadb33SDmitri Tikhonov 4150aadb33SDmitri Tikhonovstatic void 4250aadb33SDmitri Tikhonovcfcw_maybe_increase_max_window (struct lsquic_cfcw *fc) 4350aadb33SDmitri Tikhonov{ 4450aadb33SDmitri Tikhonov unsigned new_max_window; 4550aadb33SDmitri Tikhonov 4650aadb33SDmitri Tikhonov new_max_window = fc->cf_max_recv_win * 2; 4750aadb33SDmitri Tikhonov 4850aadb33SDmitri Tikhonov /* Do not increase past explicitly specified maximum */ 4950aadb33SDmitri Tikhonov if (new_max_window > fc->cf_conn_pub->enpub->enp_settings.es_max_cfcw) 5050aadb33SDmitri Tikhonov new_max_window = fc->cf_conn_pub->enpub->enp_settings.es_max_cfcw; 5150aadb33SDmitri Tikhonov 5250aadb33SDmitri Tikhonov if (new_max_window > fc->cf_max_recv_win) 5350aadb33SDmitri Tikhonov { 5450aadb33SDmitri Tikhonov LSQ_DEBUG("max window increase %u -> %u", fc->cf_max_recv_win, 5550aadb33SDmitri Tikhonov new_max_window); 5650aadb33SDmitri Tikhonov EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, 5750aadb33SDmitri Tikhonov "max CFCW increase %u -> %u", fc->cf_max_recv_win, 5850aadb33SDmitri Tikhonov new_max_window); 5950aadb33SDmitri Tikhonov fc->cf_max_recv_win = new_max_window; 6050aadb33SDmitri Tikhonov } 6150aadb33SDmitri Tikhonov else 6250aadb33SDmitri Tikhonov LSQ_DEBUG("max window could use an increase, but we're stuck " 6350aadb33SDmitri Tikhonov "at %u", fc->cf_max_recv_win); 6450aadb33SDmitri Tikhonov} 6550aadb33SDmitri Tikhonov 6650aadb33SDmitri Tikhonov 6750aadb33SDmitri Tikhonovint 6850aadb33SDmitri Tikhonovlsquic_cfcw_fc_offsets_changed (struct lsquic_cfcw *fc) 6950aadb33SDmitri Tikhonov{ 7050aadb33SDmitri Tikhonov lsquic_time_t now, since_last_update, srtt; 7150aadb33SDmitri Tikhonov 7250aadb33SDmitri Tikhonov if (fc->cf_recv_off - fc->cf_read_off >= fc->cf_max_recv_win / 2) 7350aadb33SDmitri Tikhonov return 0; 7450aadb33SDmitri Tikhonov 7550aadb33SDmitri Tikhonov now = lsquic_time_now(); 7650aadb33SDmitri Tikhonov since_last_update = now - fc->cf_last_updated; 7750aadb33SDmitri Tikhonov fc->cf_last_updated = now; 7850aadb33SDmitri Tikhonov 7950aadb33SDmitri Tikhonov srtt = lsquic_rtt_stats_get_srtt(&fc->cf_conn_pub->rtt_stats); 8050aadb33SDmitri Tikhonov if (since_last_update < srtt * 2) 8150aadb33SDmitri Tikhonov cfcw_maybe_increase_max_window(fc); 8250aadb33SDmitri Tikhonov 8350aadb33SDmitri Tikhonov fc->cf_recv_off = fc->cf_read_off + fc->cf_max_recv_win; 8450aadb33SDmitri Tikhonov LSQ_DEBUG("recv_off changed: read_off: %"PRIu64"; recv_off: %" 8550aadb33SDmitri Tikhonov PRIu64"", fc->cf_read_off, fc->cf_recv_off); 8650aadb33SDmitri Tikhonov return 1; 8750aadb33SDmitri Tikhonov} 8850aadb33SDmitri Tikhonov 8950aadb33SDmitri Tikhonov 9050aadb33SDmitri Tikhonovint 9150aadb33SDmitri Tikhonovlsquic_cfcw_incr_max_recv_off (struct lsquic_cfcw *fc, uint64_t incr) 9250aadb33SDmitri Tikhonov{ 9350aadb33SDmitri Tikhonov if (fc->cf_max_recv_off + incr <= fc->cf_recv_off) 9450aadb33SDmitri Tikhonov { 9550aadb33SDmitri Tikhonov fc->cf_max_recv_off += incr; 9650aadb33SDmitri Tikhonov LSQ_DEBUG("max_recv_off goes from %"PRIu64" to %"PRIu64"", 9750aadb33SDmitri Tikhonov fc->cf_max_recv_off - incr, fc->cf_max_recv_off); 9850aadb33SDmitri Tikhonov return 1; 9950aadb33SDmitri Tikhonov } 10050aadb33SDmitri Tikhonov else 10150aadb33SDmitri Tikhonov { 1028ae5ecb4SDmitri Tikhonov LSQ_INFO("flow control violation: received at offset %"PRIu64", while " 10350aadb33SDmitri Tikhonov "flow control receive offset is %"PRIu64, 10450aadb33SDmitri Tikhonov fc->cf_max_recv_off + incr, fc->cf_recv_off); 10550aadb33SDmitri Tikhonov return 0; 10650aadb33SDmitri Tikhonov } 10750aadb33SDmitri Tikhonov} 10850aadb33SDmitri Tikhonov 10950aadb33SDmitri Tikhonov 11050aadb33SDmitri Tikhonovvoid 11150aadb33SDmitri Tikhonovlsquic_cfcw_incr_read_off (struct lsquic_cfcw *fc, uint64_t incr) 11250aadb33SDmitri Tikhonov{ 11350aadb33SDmitri Tikhonov fc->cf_read_off += incr; 11450aadb33SDmitri Tikhonov LSQ_DEBUG("read_off goes from %"PRIu64" to %"PRIu64, 11550aadb33SDmitri Tikhonov fc->cf_read_off - incr, fc->cf_read_off); 11650aadb33SDmitri Tikhonov} 117