diff --git a/doc/configuration.txt b/doc/configuration.txt index 5ebeb2c68..6a164bb3e 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1888,11 +1888,19 @@ The following keywords are supported in the "global" section : - tune.pool-high-fd-ratio - tune.pool-low-fd-ratio - tune.pt.zero-copy-forwarding + - tune.quic.be.cc.cubic-min-losses + - tune.quic.be.cc.hystart + - tune.quic.be.cc.max-frame-loss + - tune.quic.be.cc.reorder-ratio - tune.quic.be.sec.glitches-threshold - - tune.quic.cc-hystart - - tune.quic.cc.cubic.min-losses + - tune.quic.cc.cubic.min-losses (deprecated) + - tune.quic.cc-hystart (deprecated) - tune.quic.disable-tx-pacing - tune.quic.disable-udp-gso + - tune.quic.fe.cc.cubic-min-losses + - tune.quic.fe.cc.hystart + - tune.quic.fe.cc.max-frame-loss + - tune.quic.fe.cc.reorder-ratio - tune.quic.fe.sec.glitches-threshold - tune.quic.frontend.glitches-threshold (deprecated) - tune.quic.frontend.max-data-size @@ -1902,8 +1910,8 @@ The following keywords are supported in the "global" section : - tune.quic.frontend.stream-data-ratio - tune.quic.frontend.default-max-window-size - tune.quic.listen - - tune.quic.max-frame-loss - - tune.quic.reorder-ratio + - tune.quic.max-frame-loss (deprecated) + - tune.quic.reorder-ratio (deprecated) - tune.quic.retry-threshold - tune.quic.socket-owner - tune.quic.zero-copy-fwd-send @@ -4689,12 +4697,24 @@ tune.pt.zero-copy-forwarding { on | off } See also: tune.disable-zero-copy-forwarding, option splice-auto, option splice-request and option splice-response -tune.quic.cc-hystart { on | off } - Enables ('on') or disabled ('off') the HyStart++ (RFC 9406) algorithm for - QUIC connections used as a replacement for the slow start phase of congestion - control algorithms which may cause high packet loss. It is disabled by default. +tune.quic.disable-tx-pacing + Disables pacing support for QUIC emission. The purpose of pacing is to smooth + emission of data to reduce network losses. In most scenario, it will + significantly improve network throughput by avoiding retransmissions. + However, it can be useful to deactivate it for networks with very high + bandwidth/low latency characteristics to prevent unwanted delay and reduce + CPU consumption. -tune.quic.cc.cubic.min-losses + See also the "quic-cc-algo" bind option. + +tune.quic.disable-udp-gso + Disable UDP GSO emission. This kernel feature allows to emit multiple + datagrams via a single system call which is more efficient for large + transfer. It may be useful to disable it on developers suggestion when + suspecting an issue on emission. + +tune.quic.be.cc.cubic-min-losses +tune.quic.fe.cc.cubic-min-losses Defines how many lost packets are needed for the Cubic congestion control algorithm to really consider a loss event. Normally, any loss event is considered as the result of a congestion and is sufficient for Cubic to @@ -4713,21 +4733,45 @@ tune.quic.cc.cubic.min-losses compare some metrics. Never go beyond 2 without an expert's prior analysis of the situation. The default and minimum value is 1. Always use 1. -tune.quic.disable-tx-pacing - Disables pacing support for QUIC emission. The purpose of pacing is to smooth - emission of data to reduce network losses. In most scenario, it will - significantly improve network throughput by avoiding retransmissions. - However, it can be useful to deactivate it for networks with very high - bandwidth/low latency characteristics to prevent unwanted delay and reduce - CPU consumption. +tune.quic.cc.cubic.min-losses (deprecated) + This keyword has been deprecated in 3.3 and will be removed in 3.5. It is + part of the streamlining process apply on QUIC configuration. If used, this + setting will only be applied on frontend connections. - See also the "quic-cc-algo" bind option. +tune.quic.be.cc.hystart { on | off } +tune.quic.fe.cc.hystart { on | off } + Enables ('on') or disabled ('off') the HyStart++ (RFC 9406) algorithm for + QUIC connections used as a replacement for the slow start phase of congestion + control algorithms which may cause high packet loss. It is disabled by default. -tune.quic.disable-udp-gso - Disable UDP GSO emission. This kernel feature allows to emit multiple - datagrams via a single system call which is more efficient for large - transfer. It may be useful to disable it on developers suggestion when - suspecting an issue on emission. +tune.quic.cc-hystart { on | off } (deprecated) + This keyword has been deprecated in 3.3 and will be removed in 3.5. It is + part of the streamlining process apply on QUIC configuration. If used, this + setting will only be applied on frontend connections. + +tune.quic.be.cc.max-frame-loss +tune.quic.fe.cc.max-frame-loss + Sets the limit for which a single QUIC frame can be marked as lost. If + exceeded, the connection is considered as failing and is closed immediately. + + The default value is 10. + +tune.quic.max-frame-loss (deprecated) + This keyword has been deprecated in 3.3 and will be removed in 3.5. It is + part of the streamlining process apply on QUIC configuration. If used, this + setting will only be applied on frontend connections. + +tune.quic.be.cc.reorder-ratio <0..100, in percent> +tune.quic.fe.cc.reorder-ratio <0..100, in percent> + The ratio applied to the packet reordering threshold calculated. It may + trigger a high packet loss detection when too small. + + The default value is 50. + +tune.quic.reorder-ratio <0..100, in percent> (deprecated) + This keyword has been deprecated in 3.3 and will be removed in 3.5. It is + part of the streamlining process apply on QUIC configuration. If used, this + setting will only be applied on frontend connections. tune.quic.be.sec.glitches-threshold tune.quic.fe.sec.glitches-threshold @@ -4840,18 +4884,6 @@ tune.quic.listen { on | off } See also "quic_enabled" sample fetch. -tune.quic.max-frame-loss - Sets the limit for which a single QUIC frame can be marked as lost. If - exceeded, the connection is considered as failing and is closed immediately. - - The default value is 10. - -tune.quic.reorder-ratio <0..100, in percent> - The ratio applied to the packet reordering threshold calculated. It may - trigger a high packet loss detection when too small. - - The default value is 50. - tune.quic.retry-threshold Dynamically enables the Retry feature for all the configured QUIC listeners as soon as this number of half open connections is reached. A half open diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 5d943de66..53293103a 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -223,9 +223,6 @@ struct global { size_t quic_frontend_max_window_size; unsigned int quic_frontend_stream_data_ratio; unsigned int quic_retry_threshold; - unsigned int quic_reorder_ratio; - unsigned int quic_max_frame_loss; - unsigned int quic_cubic_loss_tol; #endif /* USE_QUIC */ } tune; struct { diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 890c06641..cb80d3e73 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -93,10 +93,6 @@ typedef unsigned long long ull; #define QUIC_RETRY_DURATION_SEC 10 /* Default Retry threshold */ #define QUIC_DFLT_RETRY_THRESHOLD 100 /* in connection openings */ -/* Default ratio value applied to a dynamic Packet reorder threshold. */ -#define QUIC_DFLT_REORDER_RATIO 50 /* in percent */ -/* Default limit of loss detection on a single frame. If exceeded, connection is closed. */ -#define QUIC_DFLT_MAX_FRAME_LOSS 10 /* Default congestion window size. 480 kB, equivalent to the legacy value which was 30*bufsize */ #define QUIC_DFLT_MAX_WINDOW_SIZE 491520 diff --git a/include/haproxy/quic_tune-t.h b/include/haproxy/quic_tune-t.h index 63d7959ba..8a6ba9137 100644 --- a/include/haproxy/quic_tune-t.h +++ b/include/haproxy/quic_tune-t.h @@ -6,21 +6,35 @@ #error "Must define USE_OPENSSL" #endif + +/* Default limit of loss detection on a single frame. If exceeded, connection is closed. */ +#define QUIC_DFLT_CC_MAX_FRAME_LOSS 10 +/* Default ratio value applied to a dynamic Packet reorder threshold. */ +#define QUIC_DFLT_CC_REORDER_RATIO 50 /* in percent */ + + #define QUIC_TUNE_FE_LISTEN_OFF 0x00000001 #define QUIC_TUNE_NO_PACING 0x00000001 #define QUIC_TUNE_NO_UDP_GSO 0x00000002 #define QUIC_TUNE_SOCK_PER_CONN 0x00000004 -#define QUIC_TUNE_CC_HYSTART 0x00000008 + +#define QUIC_TUNE_FB_CC_HYSTART 0x00000001 struct quic_tune { struct { + uint cc_cubic_min_losses; + uint cc_max_frame_loss; + uint cc_reorder_ratio; uint sec_glitches_threshold; uint opts; /* QUIC_TUNE_FE_* options specific to FE side */ uint fb_opts; /* QUIC_TUNE_FB_* options shared by both side */ } fe; struct { + uint cc_cubic_min_losses; + uint cc_max_frame_loss; + uint cc_reorder_ratio; uint sec_glitches_threshold; uint fb_opts; /* QUIC_TUNE_FB_* options shared by both side */ } be; diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index 180270921..15fc94322 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -23,7 +23,16 @@ #define QUIC_CC_BBR_STR "bbr" #define QUIC_CC_NO_CC_STR "nocc" -struct quic_tune quic_tune; +struct quic_tune quic_tune = { + .fe = { + .cc_max_frame_loss = QUIC_DFLT_CC_MAX_FRAME_LOSS, + .cc_reorder_ratio = QUIC_DFLT_CC_REORDER_RATIO, + }, + .be = { + .cc_max_frame_loss = QUIC_DFLT_CC_MAX_FRAME_LOSS, + .cc_reorder_ratio = QUIC_DFLT_CC_REORDER_RATIO, + }, +}; static int bind_parse_quic_force_retry(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) { @@ -298,8 +307,24 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type, } suffix = args[0] + prefix_len; - if (strcmp(suffix, "cc.cubic.min-losses") == 0) - global.tune.quic_cubic_loss_tol = arg - 1; + if (strcmp(suffix, "be.cc.cubic-min-losses") == 0 || + strcmp(suffix, "fe.cc.cubic-min-losses") == 0) { + uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.cc_cubic_min_losses : + &quic_tune.fe.cc_cubic_min_losses; + *ptr = arg - 1; + } + else if (strcmp(suffix, "be.cc.max-frame-loss") == 0 || + strcmp(suffix, "fe.cc.max-frame-loss") == 0) { + uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.cc_max_frame_loss : + &quic_tune.fe.cc_max_frame_loss; + *ptr = arg; + } + else if (strcmp(suffix, "be.cc.reorder-ratio") == 0 || + strcmp(suffix, "fe.cc.reorder-ratio") == 0) { + uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.cc_reorder_ratio : + &quic_tune.fe.cc_reorder_ratio; + *ptr = arg; + } else if (strcmp(suffix, "be.sec.glitches-threshold") == 0 || strcmp(suffix, "fe.sec.glitches-threshold") == 0) { uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.sec_glitches_threshold : @@ -349,24 +374,37 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type, } global.tune.quic_frontend_stream_data_ratio = arg; } - else if (strcmp(suffix, "max-frame-loss") == 0) - global.tune.quic_max_frame_loss = arg; + else if (strcmp(suffix, "retry-threshold") == 0) + global.tune.quic_retry_threshold = arg; + + /* legacy options */ + else if (strcmp(suffix, "cc.cubic.min-losses") == 0) { + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.cc.cubic-min-losses'.", args[0]); + quic_tune.fe.cc_cubic_min_losses = arg - 1; + ret = 1; + } + else if (strcmp(suffix, "frontend.glitches-threshold") == 0) { + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.sec.glitches-threshold'.", args[0]); + quic_tune.fe.sec_glitches_threshold = arg; + ret = 1; + } + else if (strcmp(suffix, "max-frame-loss") == 0) { + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.cc.max-frame-loss'.", args[0]); + quic_tune.fe.cc_max_frame_loss = arg; + ret = 1; + } else if (strcmp(suffix, "reorder-ratio") == 0) { + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.cc.reorder-ratio'.", args[0]); if (arg > 100) { memprintf(err, "'%s' expects an integer argument between 0 and 100.", args[0]); return -1; } - global.tune.quic_reorder_ratio = arg; - } - else if (strcmp(suffix, "retry-threshold") == 0) - global.tune.quic_retry_threshold = arg; - - /* legacy options */ - else if (strcmp(suffix, "frontend.glitches-threshold") == 0) { - memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " - "Please use the newer keyword syntax 'tune.quic.fe.sec.glitches-threshold'.", args[0]); - quic_tune.fe.sec_glitches_threshold = arg; + quic_tune.fe.cc_reorder_ratio = arg; ret = 1; } else { @@ -411,6 +449,7 @@ static int cfg_parse_quic_tune_on_off(char **args, int section_type, struct prox int on; int prefix_len = strlen("tune.quic."); const char *suffix; + int ret = 0; if (too_many_args(1, args, err, NULL)) return -1; @@ -437,40 +476,60 @@ static int cfg_parse_quic_tune_on_off(char **args, int section_type, struct prox else global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_QUIC_SND; } - else if (strcmp(suffix, "cc-hystart") == 0) { + else if (strcmp(suffix, "be.cc.hystart") == 0 || + strcmp(suffix, "fe.cc.hystart") == 0) { + uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.fb_opts : + &quic_tune.fe.fb_opts; if (on) - quic_tune.options |= QUIC_TUNE_CC_HYSTART; + *ptr |= QUIC_TUNE_FB_CC_HYSTART; else - quic_tune.options &= ~QUIC_TUNE_CC_HYSTART; + *ptr &= ~QUIC_TUNE_FB_CC_HYSTART; + } + else if (strcmp(suffix, "cc-hystart") == 0) { + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.cc.hystart'.", args[0]); + if (on) + quic_tune.fe.fb_opts |= QUIC_TUNE_FB_CC_HYSTART; + else + quic_tune.fe.fb_opts &= ~QUIC_TUNE_FB_CC_HYSTART; + ret = 1; } - return 0; + return ret; } static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "tune.quic.listen", cfg_parse_quic_tune_on_off }, { CFG_GLOBAL, "tune.quic.socket-owner", cfg_parse_quic_tune_socket_owner }, - { CFG_GLOBAL, "tune.quic.cc-hystart", cfg_parse_quic_tune_on_off }, - { CFG_GLOBAL, "tune.quic.cc.cubic.min-losses", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.max-data-size", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.max-streams-bidi", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.max-idle-timeout", cfg_parse_quic_time }, { CFG_GLOBAL, "tune.quic.frontend.max-tx-mem", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.default-max-window-size", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.stream-data-ratio", cfg_parse_quic_tune_setting }, - { CFG_GLOBAL, "tune.quic.max-frame-loss", cfg_parse_quic_tune_setting }, - { CFG_GLOBAL, "tune.quic.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.retry-threshold", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.disable-tx-pacing", cfg_parse_quic_tune_setting0 }, { CFG_GLOBAL, "tune.quic.disable-udp-gso", cfg_parse_quic_tune_setting0 }, { CFG_GLOBAL, "tune.quic.zero-copy-fwd-send", cfg_parse_quic_tune_on_off }, + { CFG_GLOBAL, "tune.quic.fe.cc.cubic-min-losses", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.fe.cc.hystart", cfg_parse_quic_tune_on_off }, + { CFG_GLOBAL, "tune.quic.fe.cc.max-frame-loss", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.fe.cc.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.fe.sec.glitches-threshold", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.be.cc.cubic-min-losses", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.be.cc.hystart", cfg_parse_quic_tune_on_off }, + { CFG_GLOBAL, "tune.quic.be.cc.max-frame-loss", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.be.cc.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.be.sec.glitches-threshold", cfg_parse_quic_tune_setting }, /* legacy options */ + { CFG_GLOBAL, "tune.quic.cc-hystart", cfg_parse_quic_tune_on_off }, + { CFG_GLOBAL, "tune.quic.cc.cubic.min-losses", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.glitches-threshold", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.max-frame-loss", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.reorder-ratio", cfg_parse_quic_tune_setting }, { 0, NULL, NULL } }}; diff --git a/src/haproxy.c b/src/haproxy.c index d6d7b1319..d1a746b3b 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -206,9 +206,7 @@ struct global global = { .quic_frontend_max_tx_mem = QUIC_MAX_TX_MEM, .quic_frontend_max_window_size = QUIC_DFLT_MAX_WINDOW_SIZE, .quic_frontend_stream_data_ratio = QUIC_DFLT_FRONT_STREAM_DATA_RATIO, - .quic_reorder_ratio = QUIC_DFLT_REORDER_RATIO, .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD, - .quic_max_frame_loss = QUIC_DFLT_MAX_FRAME_LOSS, #endif /* USE_QUIC */ }, #ifdef USE_OPENSSL diff --git a/src/quic_cc_cubic.c b/src/quic_cc_cubic.c index df81ab97f..bae7605c6 100644 --- a/src/quic_cc_cubic.c +++ b/src/quic_cc_cubic.c @@ -103,7 +103,7 @@ static void quic_cc_cubic_reset(struct quic_cc *cc) c->last_w_max = 0; c->W_est = 0; c->recovery_start_time = 0; - if (quic_tune.options & QUIC_TUNE_CC_HYSTART) + if (quic_tune_test(QUIC_TUNE_FB_CC_HYSTART, cc->qc)) quic_cc_hystart_reset(&c->hystart); TRACE_LEAVE(QUIC_EV_CONN_CC, cc->qc); } @@ -445,7 +445,7 @@ static void quic_cc_cubic_ss_cb(struct quic_cc *cc, struct quic_cc_event *ev) TRACE_PROTO("CC cubic", QUIC_EV_CONN_CC, cc->qc, ev); switch (ev->type) { case QUIC_CC_EVT_ACK: - if (quic_tune.options & QUIC_TUNE_CC_HYSTART) { + if (quic_tune_test(QUIC_TUNE_FB_CC_HYSTART, cc->qc)) { struct quic_hystart *h = &c->hystart; unsigned int acked = QUIC_MIN(ev->ack.acked, (uint64_t)HYSTART_LIMIT * path->mtu); @@ -507,7 +507,7 @@ static void quic_cc_cubic_ca_cb(struct quic_cc *cc, struct quic_cc_event *ev) * though. */ c->consecutive_losses += ev->loss.count; - if (c->consecutive_losses <= global.tune.quic_cubic_loss_tol) + if (c->consecutive_losses <= QUIC_TUNE_FB_GET(cc_cubic_min_losses, cc->qc)) goto out; quic_enter_recovery(cc); break; diff --git a/src/quic_loss.c b/src/quic_loss.c index 87c888a22..e45efabce 100644 --- a/src/quic_loss.c +++ b/src/quic_loss.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -159,6 +160,7 @@ void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc, struct quic_loss *ql; unsigned int loss_delay; uint64_t pktthresh; + int reorder_ratio; TRACE_ENTER(QUIC_EV_CONN_PKTLOSS, qc); TRACE_PROTO("TX loss", QUIC_EV_CONN_PKTLOSS, qc, pktns); @@ -192,8 +194,9 @@ void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc, * flight before loss detection. */ pktthresh = pktns->tx.next_pn - 1 - eb64_entry(node, struct quic_tx_packet, pn_node)->pn_node.key; + reorder_ratio = QUIC_TUNE_FB_GET(cc_reorder_ratio, qc); /* Apply a ratio to this threshold and add it to QUIC_LOSS_PACKET_THRESHOLD. */ - pktthresh = pktthresh * global.tune.quic_reorder_ratio / 100 + QUIC_LOSS_PACKET_THRESHOLD; + pktthresh = pktthresh * reorder_ratio / 100 + QUIC_LOSS_PACKET_THRESHOLD; while (node) { struct quic_tx_packet *pkt; int64_t largest_acked_pn; diff --git a/src/quic_rx.c b/src/quic_rx.c index 5dd14add0..1200d04e6 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -404,7 +405,9 @@ int qc_handle_frms_of_lost_pkt(struct quic_conn *qc, qc_frm_free(qc, &frm); } else { - if (++frm->loss_count >= global.tune.quic_max_frame_loss) { + const uint max_frame_loss = QUIC_TUNE_FB_GET(cc_max_frame_loss, qc); + + if (++frm->loss_count >= max_frame_loss) { TRACE_ERROR("retransmission limit reached, closing the connection", QUIC_EV_CONN_PRSAFRM, qc); quic_set_connection_close(qc, quic_err_transport(QC_ERR_INTERNAL_ERROR)); qc_notify_err(qc); diff --git a/src/quic_tx.c b/src/quic_tx.c index 92348834f..1b6497b43 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -441,7 +441,7 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx) } qc->path->in_flight += pkt->in_flight_len; pkt->pktns->tx.in_flight += pkt->in_flight_len; - if ((quic_tune.options & QUIC_TUNE_CC_HYSTART) && pkt->pktns == qc->apktns) + if (quic_tune_test(QUIC_TUNE_FB_CC_HYSTART, qc) && pkt->pktns == qc->apktns) cc->algo->hystart_start_round(cc, pkt->pn_node.key); if (pkt->in_flight_len) qc_set_timer(qc);