From 66ed250558559f3b06242b35c97043245a28a151 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Fri, 11 Oct 2024 17:57:57 +0200 Subject: [PATCH] MINOR: quic: support a max number of built packet per send iteration --- include/haproxy/quic_tx.h | 2 +- src/quic_conn.c | 4 ++-- src/quic_tx.c | 36 ++++++++++++++++++++++++++---------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/include/haproxy/quic_tx.h b/include/haproxy/quic_tx.h index 55530d9fca..f342ae113b 100644 --- a/include/haproxy/quic_tx.h +++ b/include/haproxy/quic_tx.h @@ -36,7 +36,7 @@ struct buffer *qc_get_txb(struct quic_conn *qc); void qel_register_send(struct list *send_list, struct quic_enc_level *qel, struct list *frms); int qel_need_sending(struct quic_enc_level *qel, struct quic_conn *qc); -int qc_send(struct quic_conn *qc, int old_data, struct list *send_list); +int qc_send(struct quic_conn *qc, int old_data, struct list *send_list, int *max_pkts); int qc_dgrams_retransmit(struct quic_conn *qc); void qc_prep_hdshk_fast_retrans(struct quic_conn *qc, diff --git a/src/quic_conn.c b/src/quic_conn.c index 5c9577e639..e6fb004e80 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -617,7 +617,7 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta if (qel_need_sending(qc->ael, qc)) qel_register_send(&send_list, qc->ael, &qc->ael->pktns->tx.frms); - if (!qc_send(qc, 0, &send_list)) { + if (!qc_send(qc, 0, &send_list, NULL)) { TRACE_DEVEL("qc_send() failed", QUIC_EV_CONN_IO_CB, qc); goto out; } @@ -877,7 +877,7 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) qel_register_send(&send_list, qel, &qel->pktns->tx.frms); } - if (!qc_send(qc, 0, &send_list)) { + if (!qc_send(qc, 0, &send_list, NULL)) { TRACE_DEVEL("qc_send() failed", QUIC_EV_CONN_IO_CB, qc); goto out; } diff --git a/src/quic_tx.c b/src/quic_tx.c index cdba917b1e..2f2201f8cc 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -487,12 +487,12 @@ int qc_send_mux(struct quic_conn *qc, struct list *frms) qc->state >= QUIC_HS_ST_COMPLETE) { quic_build_post_handshake_frames(qc); qel_register_send(&send_list, qc->ael, &qc->ael->pktns->tx.frms); - qc_send(qc, 0, &send_list); + qc_send(qc, 0, &send_list, NULL); } TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc); qel_register_send(&send_list, qc->ael, frms); - ret = qc_send(qc, 0, &send_list); + ret = qc_send(qc, 0, &send_list, NULL); TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc); return ret; @@ -530,7 +530,7 @@ static inline void qc_select_tls_ver(struct quic_conn *qc, * (may be 0), or -1 if something wrong happened. */ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, - struct list *qels) + struct list *qels, int *max_pkts) { int ret, cc, padding; struct quic_tx_packet *first_pkt, *prv_pkt; @@ -547,6 +547,8 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, */ BUG_ON_HOT(buf->head || buf->data); + BUG_ON(max_pkts && *max_pkts <= 0); + ret = -1; cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE; padding = 0; @@ -589,6 +591,15 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, TRACE_PROTO("TX prep pkts", QUIC_EV_CONN_PHPKTS, qc, qel); + /* Start to decrement after the first packet built. */ + if (!dglen && pos != (unsigned char *)b_head(buf)) { + if (max_pkts && !--(*max_pkts)) { + BUG_ON(LIST_ISEMPTY(frms)); + TRACE_PROTO("reached max allowed built datagrams", QUIC_EV_CONN_PHPKTS, qc, qel); + goto out; + } + } + if (!first_pkt) pos += QUIC_DGRAM_HEADLEN; @@ -764,7 +775,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, * Returns 1 on success else 0. Note that will always be reset * after qc_send() exit. */ -int qc_send(struct quic_conn *qc, int old_data, struct list *send_list) +int qc_send(struct quic_conn *qc, int old_data, struct list *send_list, int *max_pkts) { struct quic_enc_level *qel, *tmp_qel; int ret = 0, status = 0; @@ -801,7 +812,7 @@ int qc_send(struct quic_conn *qc, int old_data, struct list *send_list) BUG_ON_HOT(b_data(buf)); b_reset(buf); - ret = qc_prep_pkts(qc, buf, send_list); + ret = qc_prep_pkts(qc, buf, send_list, max_pkts); if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) { if (qc->flags & QUIC_FL_CONN_TO_KILL) @@ -814,6 +825,11 @@ int qc_send(struct quic_conn *qc, int old_data, struct list *send_list) break; } + if (max_pkts && !*max_pkts) { + TRACE_DEVEL("stopping for artificial pacing", QUIC_EV_CONN_TXPKT, qc); + break; + } + if ((qc->flags & QUIC_FL_CONN_DRAINING) && !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)) { TRACE_DEVEL("draining connection", QUIC_EV_CONN_TXPKT, qc); @@ -904,7 +920,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc) if (qc->hel) qel_register_send(&send_list, qc->hel, &hfrms); - sret = qc_send(qc, 1, &send_list); + sret = qc_send(qc, 1, &send_list, NULL); qc_free_frm_list(qc, &ifrms); qc_free_frm_list(qc, &hfrms); if (!sret) @@ -917,7 +933,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc) */ ipktns->tx.pto_probe = 1; qel_register_send(&send_list, qc->iel, &ifrms); - sret = qc_send(qc, 0, &send_list); + sret = qc_send(qc, 0, &send_list, NULL); qc_free_frm_list(qc, &ifrms); qc_free_frm_list(qc, &hfrms); if (!sret) @@ -946,7 +962,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc) if (!LIST_ISEMPTY(&frms1)) { hpktns->tx.pto_probe = 1; qel_register_send(&send_list, qc->hel, &frms1); - sret = qc_send(qc, 1, &send_list); + sret = qc_send(qc, 1, &send_list, NULL); qc_free_frm_list(qc, &frms1); if (!sret) goto leave; @@ -969,7 +985,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc) if (!LIST_ISEMPTY(&frms1)) { apktns->tx.pto_probe = 1; qel_register_send(&send_list, qc->ael, &frms1); - sret = qc_send(qc, 1, &send_list); + sret = qc_send(qc, 1, &send_list, NULL); qc_free_frm_list(qc, &frms1); if (!sret) { qc_free_frm_list(qc, &frms2); @@ -980,7 +996,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc) if (!LIST_ISEMPTY(&frms2)) { apktns->tx.pto_probe = 1; qel_register_send(&send_list, qc->ael, &frms2); - sret = qc_send(qc, 1, &send_list); + sret = qc_send(qc, 1, &send_list, NULL); qc_free_frm_list(qc, &frms2); if (!sret) goto leave; -- 2.47.2