]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-quic: do not mix qcc_io_send() return codes with pacing
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 11 Dec 2024 16:55:29 +0000 (17:55 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 18 Dec 2024 08:18:48 +0000 (09:18 +0100)
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.

src/mux_quic.c

index 24e71ab92937557c55c8cffef12051b6db4bc954..6fe9461094650a1b8688670ec29d3254c138e269 100644 (file)
@@ -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);