From: Amaury Denoyelle Date: Thu, 24 Oct 2024 14:06:48 +0000 (+0200) Subject: MINOR: quic: support pacing emission on quic_conn layer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=724eb107f0bdbe585dc377dda27f65d94038f3b5;p=thirdparty%2Fhaproxy.git MINOR: quic: support pacing emission on quic_conn layer --- diff --git a/include/haproxy/quic_pacing-t.h b/include/haproxy/quic_pacing-t.h index 220066994b..25e6eecdba 100644 --- a/include/haproxy/quic_pacing-t.h +++ b/include/haproxy/quic_pacing-t.h @@ -7,6 +7,7 @@ struct quic_pacer { struct list frms; const struct quic_cc_path *path; + ullong next; }; #endif /* _HAPROXY_QUIC_PACING_T_H */ diff --git a/include/haproxy/quic_pacing.h b/include/haproxy/quic_pacing.h index f58c3a3402..e760d475ca 100644 --- a/include/haproxy/quic_pacing.h +++ b/include/haproxy/quic_pacing.h @@ -11,6 +11,7 @@ static inline void quic_pacing_init(struct quic_pacer *pacer, { LIST_INIT(&pacer->frms); pacer->path = path; + pacer->next = 0; } static inline void quic_pacing_reset(struct quic_pacer *pacer) @@ -29,4 +30,13 @@ static inline struct list *quic_pacing_frms(struct quic_pacer *pacer) return &pacer->frms; } +static inline ullong quic_pacing_ns_pkt(const struct quic_pacer *pacer) +{ + return pacer->path->loss.srtt * 1000000 / (pacer->path->cwnd / pacer->path->mtu + 1); +} + +int quic_pacing_expired(const struct quic_pacer *pacer); + +void quic_pacing_sent_done(struct quic_pacer *pacer, int sent); + #endif /* _HAPROXY_QUIC_PACING_H */ diff --git a/include/haproxy/quic_tx-t.h b/include/haproxy/quic_tx-t.h index 359869a314..5f7e234226 100644 --- a/include/haproxy/quic_tx-t.h +++ b/include/haproxy/quic_tx-t.h @@ -66,6 +66,7 @@ enum qc_build_pkt_err { enum quic_tx_err { QUIC_TX_ERR_NONE, + QUIC_TX_ERR_AGAIN, QUIC_TX_ERR_FATAL, }; diff --git a/include/haproxy/quic_tx.h b/include/haproxy/quic_tx.h index 21f7eecf3a..970d8d598b 100644 --- a/include/haproxy/quic_tx.h +++ b/include/haproxy/quic_tx.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,8 @@ void qc_txb_release(struct quic_conn *qc); int qc_purge_txbuf(struct quic_conn *qc, struct buffer *buf); struct buffer *qc_get_txb(struct quic_conn *qc); -enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms); +enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms, + struct quic_pacer *pacer); void qel_register_send(struct list *send_list, struct quic_enc_level *qel, struct list *frms); diff --git a/src/mux_quic.c b/src/mux_quic.c index 23aa00559f..fd3c10365f 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -2084,7 +2084,7 @@ static int qcc_send_frames(struct qcc *qcc, struct list *frms) return 1; } - ret = qc_send_mux(qcc->conn->handle.qc, frms); + ret = qc_send_mux(qcc->conn->handle.qc, frms, NULL); if (ret == QUIC_TX_ERR_FATAL) { TRACE_DEVEL("error on sending", QMUX_EV_QCC_SEND, qcc->conn); qcc_subscribe_send(qcc); diff --git a/src/quic_pacing.c b/src/quic_pacing.c index faee5e81c2..df3fedb585 100644 --- a/src/quic_pacing.c +++ b/src/quic_pacing.c @@ -1 +1,15 @@ #include + +#include + +struct quic_conn; + +int quic_pacing_expired(const struct quic_pacer *pacer) +{ + return !pacer->next || pacer->next <= now_mono_time(); +} + +void quic_pacing_sent_done(struct quic_pacer *pacer, int sent) +{ + pacer->next = now_mono_time() + quic_pacing_ns_pkt(pacer) * sent; +} diff --git a/src/quic_tx.c b/src/quic_tx.c index 654cc688f3..e33d74dc36 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -469,11 +470,12 @@ int qc_purge_txbuf(struct quic_conn *qc, struct buffer *buf) * * Returns the result from qc_send() function. */ -enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms) +enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms, + struct quic_pacer *pacer) { struct list send_list = LIST_HEAD_INIT(send_list); enum quic_tx_err ret = QUIC_TX_ERR_NONE; - int sent; + int max_dgram = 0, sent; TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc); BUG_ON(qc->mux_state != QC_MUX_READY); /* Only MUX can uses this function so it must be ready. */ @@ -492,11 +494,20 @@ 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; + TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc); qel_register_send(&send_list, qc->ael, frms); - sent = qc_send(qc, 0, &send_list, 0); - if (sent <= 0) + sent = qc_send(qc, 0, &send_list, max_dgram); + if (sent <= 0) { ret = QUIC_TX_ERR_FATAL; + } + else if (pacer) { + if (max_dgram && max_dgram == sent && !LIST_ISEMPTY(frms)) + ret = QUIC_TX_ERR_AGAIN; + quic_pacing_sent_done(pacer, sent); + } TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc); return ret;