From: Amaury Denoyelle Date: Wed, 11 Dec 2024 16:55:29 +0000 (+0100) Subject: BUG/MEDIUM: mux-quic: do not mix qcc_io_send() return codes with pacing X-Git-Tag: v3.2-dev2~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e3542bec6235482e4136ddd1e23e8f7cd4b5a26;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: mux-quic: do not mix qcc_io_send() return codes with pacing With pacing implementation, qcc_send_frames() return code has been extended to report emission interruption due to pacing limitation. This is used only in qcc_io_send(). However, its invokation may be skipped using 'sent_done' label. This happens on emission failure of a STOP_SENDING or RESET_STREAM (either memory allocation failure, or transport layer rejection). In this case, return values are mixed as qcs_send() is wrongly compared against pacing interruption condition. This value corresponds to the length of the last built STREAM frames. If by mischance the last frame was 1 byte long, qcs_send() return value is equal to pacing interruption condition. This has several effects. If pacing is activated, it may lead to unneeded wakeup on QUIC MUX. Worst, if pacing is not used, a BUG_ON() crash will be triggered. Fix this by using a different variable dedicated to qcc_send_frames() return value. By default it is initialized to 0. This ensures that pacing code won't be activated in case qcc_send_frames() is not used. This must be backported up to 3.1. --- diff --git a/src/mux_quic.c b/src/mux_quic.c index 24e71ab929..6fe9461094 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -2286,7 +2286,7 @@ static int qcc_io_send(struct qcc *qcc) struct list qcs_failed = LIST_HEAD_INIT(qcs_failed); struct qcs *qcs, *qcs_tmp, *first_qcs = NULL; uint64_t window_conn = qfctl_rcap(&qcc->tx.fc); - int ret = 0, total = 0, resent; + int ret = 0, ret_sent = 0, total = 0, resent; TRACE_ENTER(QMUX_EV_QCC_SEND, qcc->conn); @@ -2408,7 +2408,7 @@ static int qcc_io_send(struct qcc *qcc) /* Retry sending until no frame to send, data rejected or connection * flow-control limit reached. */ - while ((ret = qcc_send_frames(qcc, frms, 1)) == 0 && !qfctl_rblocked(&qcc->tx.fc)) { + while ((ret_sent = qcc_send_frames(qcc, frms, 1)) == 0 && !qfctl_rblocked(&qcc->tx.fc)) { window_conn = qfctl_rcap(&qcc->tx.fc); resent = 0; @@ -2439,7 +2439,7 @@ static int qcc_io_send(struct qcc *qcc) } sent_done: - if (ret == 1) { + if (ret_sent == 1) { /* qcc_send_frames cannot return 1 if pacing not used. */ BUG_ON(!qcc_is_pacing_active(qcc->conn)); qcc_wakeup_pacing(qcc);