From c6e3d60fc12fdf3dacd0dc64af8c66520b2f47bb Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 10 Apr 2024 09:38:00 +0200 Subject: [PATCH] OPTIM: quic: do not call qc_prep_pkts() if everything sent qc_send() is implemented as a loop to repeatedly invoke qc_prep_pkts()/qc_send_ppkts(). This ensures that all data are emitted even if bigger that a single Tx buffer instance. This is useful if congestion window is empty but big enough for application data. Looping is interrupted if qc_prep_pkts() returns a negative error code, for example due to no space left in congestion window. It can also returns 0 if no input data to sent, which also interrupt the loop. To limit this last case, removed quic_enc_level from send_list each time everything already send via qc_prep_pkts(). Loop can then be interrupted as soon as send_list is empty, avoiding an extra superfluous call to qc_prep_pkts(). --- src/quic_tx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/quic_tx.c b/src/quic_tx.c index 99f2a59ca..ba81a7713 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -491,7 +491,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, unsigned char *end, *pos; uint16_t dglen; size_t total; - struct quic_enc_level *qel; + struct quic_enc_level *qel, *tmp_qel; TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); /* Currently qc_prep_pkts() does not handle buffer wrapping so the @@ -507,7 +507,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, dglen = 0; total = 0; - list_for_each_entry(qel, qels, el_send) { + list_for_each_entry_safe(qel, tmp_qel, qels, el_send) { struct quic_tls_ctx *tls_ctx; const struct quic_version *ver; struct list *frms = qel->send_frms, *next_frms; @@ -547,6 +547,10 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, probe = qel->pktns->tx.pto_probe; if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack)) { + /* Remove qel from send_list if nothing to send. */ + LIST_DEL_INIT(&qel->el_send); + qel->send_frms = NULL; + if (prv_pkt && !next_qel) { qc_txb_store(buf, dglen, first_pkt); /* Build only one datagram when an immediate close is required. */ @@ -650,7 +654,6 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, padding = 1; prv_pkt = cur_pkt; - break; } else { qc_txb_store(buf, dglen, first_pkt); @@ -724,7 +727,7 @@ int qc_send(struct quic_conn *qc, int old_data, struct list *send_list) qc_txb_release(qc); goto out; } - } while (ret > 0); + } while (ret > 0 && !LIST_ISEMPTY(send_list)); qc_txb_release(qc); if (ret < 0)