]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic/pacing: add burst support
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 18 Nov 2024 14:31:12 +0000 (15:31 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 19 Nov 2024 15:16:48 +0000 (16:16 +0100)
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.

include/haproxy/quic_cc-t.h
include/haproxy/quic_cc.h
include/haproxy/quic_pacing.h
src/quic_cc.c
src/quic_pacing.c
src/quic_tx.c

index d06b221169e41b4861d00c4a27cb41c6ebdf6f02..5293495fd4a7994053f90e400e692a939c16379b 100644 (file)
@@ -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 */
index b9ae6ccd398eab053ed9ee68c121b945a55aac1e..471bf57da36bc9dc8007df19fcb9dfd5dad92554 100644 (file)
@@ -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)
 {
index ba918267fc9b6b02c3c88323d19e4cc0c9ef37f5..20ad8a2c0b25bac0d7a1604b626ba1b34c579cf2 100644 (file)
@@ -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);
 
index c09b9d890eaf76cc294baf9812b714ac575fee03..b6bfa86a771b228dfef9f2f6d2b2916f915f7af8 100644 (file)
@@ -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;
+}
index 9afe957092b162d9865a5a48a2b71c731154c1a7..e719b6b18d111161b89582ded284fce1503714c4 100644 (file)
@@ -8,8 +8,8 @@ int quic_pacing_expired(const struct quic_pacer *pacer)
        return !pacer->next || pacer->next <= now_mono_time();
 }
 
-/* Notify <pacer> about an emission of one datagram. */
-void quic_pacing_sent_done(struct quic_pacer *pacer)
+/* Notify <pacer> about an emission of <sent> 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;
 }
index ef7668df9a6b51e88d09e3d1b4c50ef9e56d21a2..26670a4ca3f6f3f23a150c2b4935755dffaabda6 100644 (file)
@@ -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);