From: Amaury Denoyelle Date: Fri, 5 Apr 2024 15:43:38 +0000 (+0200) Subject: MINOR: quic: improve sending API on retransmit X-Git-Tag: v3.0-dev8~107 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a8f4761e7d37b8e6a9a0cb5600322fe92707941;p=thirdparty%2Fhaproxy.git MINOR: quic: improve sending API on retransmit 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(). --- diff --git a/include/haproxy/quic_tx.h b/include/haproxy/quic_tx.h index 8d8c5c3059..7dc83dbfd3 100644 --- a/include/haproxy/quic_tx.h +++ b/include/haproxy/quic_tx.h @@ -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); diff --git a/src/quic_conn.c b/src/quic_conn.c index 6989de6a82..f3ff163382 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -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) diff --git a/src/quic_tx.c b/src/quic_tx.c index 86cb63d178..ee587aca0e 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -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 into in preparation for sending. Set its send + * frames list pointer to . + */ +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;