diff --git a/include/haproxy/quic_cc-t.h b/include/haproxy/quic_cc-t.h index d06b22116..5293495fd 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 b9ae6ccd3..471bf57da 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 ba918267f..20ad8a2c0 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 c09b9d890..b6bfa86a7 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 9afe95709..e719b6b18 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 ef7668df9..26670a4ca 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);