From: Amaury Denoyelle Date: Mon, 18 Nov 2024 14:31:12 +0000 (+0100) Subject: MINOR: quic/pacing: add burst support X-Git-Tag: v3.1-dev14~85 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=886a7c475cee89f39731b3518f6a10615756636a;p=thirdparty%2Fhaproxy.git MINOR: quic/pacing: add burst support qc_send_mux() has been extended previously to support pacing emission. This will ensure that no more than one datagram will be emitted during each invokation. However, to achieve better performance, it may be necessary to emit a batch of several datagrams one one turn. A so-called burst value can be specified by the user in the configuration. However, some congestion control algos may defined their owned dynamic value. As such, a new CC callback pacing_burst is defined. quic_cc_default_pacing_burst() can be used for algo without pacing interaction, such as cubic. It will returns a static value based on user selected configuration. --- diff --git a/include/haproxy/quic_cc-t.h b/include/haproxy/quic_cc-t.h index d06b221169..5293495fd4 100644 --- a/include/haproxy/quic_cc-t.h +++ b/include/haproxy/quic_cc-t.h @@ -113,6 +113,8 @@ struct quic_cc_path { uint64_t in_flight; /* Number of in flight ack-eliciting packets. */ uint64_t ifae_pkts; + /* Burst size if pacing is used. Not used if congestion algo handle pacing itself. */ + uint32_t pacing_burst; }; struct quic_cc_algo { @@ -126,6 +128,7 @@ struct quic_cc_algo { /* Defined only if pacing is used. */ uint (*pacing_rate)(const struct quic_cc *cc); + uint (*pacing_burst)(const struct quic_cc *cc); }; #endif /* USE_QUIC */ diff --git a/include/haproxy/quic_cc.h b/include/haproxy/quic_cc.h index b9ae6ccd39..471bf57da3 100644 --- a/include/haproxy/quic_cc.h +++ b/include/haproxy/quic_cc.h @@ -39,6 +39,7 @@ void quic_cc_state_trace(struct buffer *buf, const struct quic_cc *cc); /* Pacing callbacks */ uint quic_cc_default_pacing_rate(const struct quic_cc *cc); +uint quic_cc_default_pacing_burst(const struct quic_cc *cc); static inline const char *quic_cc_state_str(enum quic_cc_algo_state_type state) { diff --git a/include/haproxy/quic_pacing.h b/include/haproxy/quic_pacing.h index ba918267fc..20ad8a2c0b 100644 --- a/include/haproxy/quic_pacing.h +++ b/include/haproxy/quic_pacing.h @@ -15,8 +15,7 @@ static inline void quic_pacing_init(struct quic_pacer *pacer, int quic_pacing_expired(const struct quic_pacer *pacer); - -void quic_pacing_sent_done(struct quic_pacer *pacer); +void quic_pacing_sent_done(struct quic_pacer *pacer, int sent); enum quic_tx_err quic_pacing_send(struct quic_pacer *pacer, struct quic_conn *qc); diff --git a/src/quic_cc.c b/src/quic_cc.c index c09b9d890e..b6bfa86a77 100644 --- a/src/quic_cc.c +++ b/src/quic_cc.c @@ -54,3 +54,12 @@ uint quic_cc_default_pacing_rate(const struct quic_cc *cc) struct quic_cc_path *path = container_of(cc, struct quic_cc_path, cc); return path->loss.srtt * 1000000 / (path->cwnd / path->mtu + 1); } + +/* Return the max number of datagrams which can be emitted in a burst with + * pacing. Must return a strictly positive value. + */ +uint quic_cc_default_pacing_burst(const struct quic_cc *cc) +{ + struct quic_cc_path *path = container_of(cc, struct quic_cc_path, cc); + return path->pacing_burst; +} diff --git a/src/quic_pacing.c b/src/quic_pacing.c index 9afe957092..e719b6b18d 100644 --- a/src/quic_pacing.c +++ b/src/quic_pacing.c @@ -8,8 +8,8 @@ int quic_pacing_expired(const struct quic_pacer *pacer) return !pacer->next || pacer->next <= now_mono_time(); } -/* Notify about an emission of one datagram. */ -void quic_pacing_sent_done(struct quic_pacer *pacer) +/* Notify about an emission of count of datagrams. */ +void quic_pacing_sent_done(struct quic_pacer *pacer, int sent) { - pacer->next = now_mono_time() + pacer->cc->algo->pacing_rate(pacer->cc); + pacer->next = now_mono_time() + pacer->cc->algo->pacing_rate(pacer->cc) * sent; } diff --git a/src/quic_tx.c b/src/quic_tx.c index ef7668df9a..26670a4ca3 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -494,8 +494,10 @@ enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms, qc_send(qc, 0, &send_list, 0); } - if (pacer) - max_dgram = 1; + if (pacer) { + max_dgram = qc->path->cc.algo->pacing_burst(&qc->path->cc); + BUG_ON(max_dgram <= 0); /* pacer must specify a positive burst value. */ + } TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc); qel_register_send(&send_list, qc->ael, frms); @@ -504,10 +506,10 @@ enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms, ret = QUIC_TX_ERR_FATAL; } else if (pacer) { - BUG_ON(sent > 1); /* burst not yet supported for pacing */ - if (!LIST_ISEMPTY(frms)) + BUG_ON(sent > max_dgram); /* Must not exceed pacing limit. */ + if (max_dgram == sent && !LIST_ISEMPTY(frms)) ret = QUIC_TX_ERR_PACING; - quic_pacing_sent_done(pacer); + quic_pacing_sent_done(pacer, sent); } TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);