]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: improve sending API on retransmit
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 5 Apr 2024 15:43:38 +0000 (17:43 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 10 Apr 2024 09:06:55 +0000 (11:06 +0200)
qc_send_hdshk_pkts() is a wrapper for qc_prep_hpkts() used on
retransmission. It was restricted to use two quic_enc_level pointers as
distinct arguments. Adapt it to directly use the same list of
quic_enc_level which is passed then to qc_prep_hpkts().

Now for retransmission quic_enc_level send list is built directly into
qc_dgrams_retransmit() which calls qc_send_hdshk_pkts().

Along this change, a new utility function qel_register_send() is
defined. It is an helper to build the quic_enc_level send list. It
enfores that each quic_enc_level instance is only registered in a single
list to prevent memory issues. It is both used in qc_dgrams_retransmit()
and quic_conn_io_cb().

include/haproxy/quic_tx.h
src/quic_conn.c
src/quic_tx.c

index 8d8c5c30591745eb9914e206849bcd80b1308bab..7dc83dbfd307e2fa840b76a07e364a5dec6eb003 100644 (file)
@@ -33,6 +33,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);
 
+void qel_register_send(struct list *send_list, struct quic_enc_level *qel,
+                       struct list *frms);
 int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels);
 int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx);
 int qc_send_app_pkts(struct quic_conn *qc, struct list *frms);
index 6989de6a822f1efa0e71094a1d60e42c4c95a60d..f3ff1633827277492c33205b49d9632c7a869025 100644 (file)
@@ -795,11 +795,8 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
        }
 
        /* Insert each QEL into sending list. */
-       list_for_each_entry(qel, &qc->qel_list, list) {
-               BUG_ON(LIST_INLIST(&qel->el_send));
-               LIST_APPEND(&send_list, &qel->el_send);
-               qel->send_frms = &qel->pktns->tx.frms;
-       }
+       list_for_each_entry(qel, &qc->qel_list, list)
+               qel_register_send(&send_list, qel, &qel->pktns->tx.frms);
 
        buf = qc_get_txb(qc);
        if (!buf)
index 86cb63d1784cfdab202a6285c0bd81526450673c..ee587aca0e5b5d6f1c257644811a6560cde4f9bb 100644 (file)
@@ -860,12 +860,11 @@ int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels)
  * Returns 1 if succeeded, 0 if not.
  */
 int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
-                       struct quic_enc_level *qel1, struct quic_enc_level *qel2)
+                       struct list *send_list)
 {
        struct quic_enc_level *qel, *tmp_qel;
        int ret, status = 0;
        struct buffer *buf = qc_get_txb(qc);
-       struct list send_list = LIST_HEAD_INIT(send_list);
 
        TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
 
@@ -891,22 +890,7 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
                qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
        }
 
-       /* At least one QEL must be set or sending is unnecessary. */
-       BUG_ON(!qel1 && !qel2);
-
-       if (qel1) {
-               /* Ensure QEL is not already registered for sending. */
-               BUG_ON(LIST_INLIST(&qel1->el_send));
-               LIST_APPEND(&send_list, &qel1->el_send);
-       }
-
-       if (qel2) {
-               /* Ensure QEL is not already registered for sending. */
-               BUG_ON(LIST_INLIST(&qel2->el_send));
-               LIST_APPEND(&send_list, &qel2->el_send);
-       }
-
-       ret = qc_prep_hpkts(qc, buf, &send_list);
+       ret = qc_prep_hpkts(qc, buf, send_list);
        if (ret == -1) {
                qc_txb_release(qc);
                TRACE_ERROR("Could not build some packets", QUIC_EV_CONN_TXPKT, qc);
@@ -930,7 +914,7 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
        }
 
        /* Always reset QEL sending list. */
-       list_for_each_entry_safe(qel, tmp_qel, &send_list, el_send) {
+       list_for_each_entry_safe(qel, tmp_qel, send_list, el_send) {
                LIST_DEL_INIT(&qel->el_send);
                qel->send_frms = NULL;
        }
@@ -939,6 +923,19 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
        return status;
 }
 
+/* Insert <qel> into <send_list> in preparation for sending. Set its send
+ * frames list pointer to <frms>.
+ */
+void qel_register_send(struct list *send_list, struct quic_enc_level *qel,
+                       struct list *frms)
+{
+       /* Ensure QEL is not already registered for sending. */
+       BUG_ON(LIST_INLIST(&qel->el_send));
+
+       LIST_APPEND(send_list, &qel->el_send);
+       qel->send_frms = frms;
+}
+
 /* Retransmit up to two datagrams depending on packet number space.
  * Return 0 when failed, 0 if not.
  */
@@ -959,9 +956,9 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
                int i;
 
                for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
+                       struct list send_list = LIST_HEAD_INIT(send_list);
                        struct list ifrms = LIST_HEAD_INIT(ifrms);
                        struct list hfrms = LIST_HEAD_INIT(hfrms);
-                       struct list qels = LIST_HEAD_INIT(qels);
 
                        qc_prep_hdshk_fast_retrans(qc, &ifrms, &hfrms);
                        TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &ifrms);
@@ -970,24 +967,25 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
                                ipktns->tx.pto_probe = 1;
                                if (!LIST_ISEMPTY(&hfrms))
                                        hpktns->tx.pto_probe = 1;
-                               qc->iel->send_frms = &ifrms;
+
+                               qel_register_send(&send_list, qc->iel, &ifrms);
                                if (qc->hel)
-                                       qc->hel->send_frms = &hfrms;
-                               sret = qc_send_hdshk_pkts(qc, 1, qc->iel, qc->hel);
+                                       qel_register_send(&send_list, qc->hel, &hfrms);
+
+                               sret = qc_send_hdshk_pkts(qc, 1, &send_list);
                                qc_free_frm_list(qc, &ifrms);
                                qc_free_frm_list(qc, &hfrms);
                                if (!sret)
                                        goto leave;
                        }
                        else {
-                               /* We are in the case where the anti-amplification limit will be
-                                * reached after having sent this datagram or some handshake frames
-                                * could not be allocated. There is no need to send more than one
-                                * datagram.
+                               /* No frame to send due to amplification limit
+                                * or allocation failure. A PING frame will be
+                                * emitted for probing.
                                 */
                                ipktns->tx.pto_probe = 1;
-                               qc->iel->send_frms = &ifrms;
-                               sret = qc_send_hdshk_pkts(qc, 0, qc->iel, NULL);
+                               qel_register_send(&send_list, qc->iel, &ifrms);
+                               sret = qc_send_hdshk_pkts(qc, 0, &send_list);
                                qc_free_frm_list(qc, &ifrms);
                                qc_free_frm_list(qc, &hfrms);
                                if (!sret)
@@ -1008,14 +1006,15 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
                if (hpktns && (hpktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED)) {
                        hpktns->tx.pto_probe = 0;
                        for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
+                               struct list send_list = LIST_HEAD_INIT(send_list);
                                struct list frms1 = LIST_HEAD_INIT(frms1);
 
                                qc_prep_fast_retrans(qc, hpktns, &frms1, NULL);
                                TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
                                if (!LIST_ISEMPTY(&frms1)) {
                                        hpktns->tx.pto_probe = 1;
-                                       qc->hel->send_frms = &frms1;
-                                       sret = qc_send_hdshk_pkts(qc, 1, qc->hel, NULL);
+                                       qel_register_send(&send_list, qc->hel, &frms1);
+                                       sret = qc_send_hdshk_pkts(qc, 1, &send_list);
                                        qc_free_frm_list(qc, &frms1);
                                        if (!sret)
                                                goto leave;