]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: mux-quic: defer stream shut if remaining tx data
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 8 Oct 2021 15:57:41 +0000 (17:57 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 13 Oct 2021 14:38:56 +0000 (16:38 +0200)
Defer the shutting of a qcs if there is still data in its tx buffers. In
this case, the conn_stream is closed but the qcs is kept with a new flag
QC_SF_DETACH.

On ACK reception, the xprt wake up the shut_tl tasklet if the stream is
flagged with QC_SF_DETACH. This tasklet is responsible to free the qcs
and possibly the qcc when all bidirectional streams are removed.

include/haproxy/mux_quic-t.h
src/mux_quic.c
src/xprt_quic.c

index 2dff82835c30e2ed6e2e2cf8b1c6f0286fb5835e..a958f45542bfe6cbf93a08c442d877e26597b05f 100644 (file)
@@ -202,6 +202,7 @@ enum qcs_tx_st {
 #define QC_SF_KILL_CONN         0x00020000  // kill the whole connection with this stream
 
 #define QC_SF_FIN_STREAM        0x00040000  // FIN bit must be set for last frame of the stream
+#define QC_SF_DETACH            0x00080000
 
 /* QUIC stream descriptor, describing the stream as it appears in the QUIC_CONN, and as
  * it is being processed in the internal HTTP representation (HTX).
index 578a59eebd55dc170022768f0947db49433c297d..df6d147960be0c975e27eca5dceb0ec1360c90ee 100644 (file)
@@ -1564,9 +1564,16 @@ static void qc_detach(struct conn_stream *cs)
        struct qcc *qcc = qcs->qcc;
 
        TRACE_ENTER(QC_EV_STRM_END, qcs ? qcs->qcc->conn : NULL, qcs);
+       if (b_data(&qcs->tx.buf) || b_data(&qcs->tx.xprt_buf)) {
+               qcs->flags |= QC_SF_DETACH;
+               goto out;
+       }
+
        qcs_destroy(qcs);
        if (qcc_is_dead(qcc))
                qc_release(qcc);
+
+ out:
        TRACE_LEAVE(QC_EV_STRM_END, qcs ? qcs->qcc->conn : NULL);
 }
 
@@ -1603,7 +1610,8 @@ static struct task *qc_deferred_shut(struct task *t, void *ctx, unsigned int sta
 
        TRACE_ENTER(QC_EV_STRM_SHUT, qcc->conn, qcs);
 
-       if (qcs->flags & QC_SF_NOTIFIED) {
+       if (qcs->flags & QC_SF_NOTIFIED ||
+           (b_data(&qcs->tx.buf) || b_data(&qcs->tx.xprt_buf))) {
                /* some data processing remains to be done first */
                goto end;
        }
index 455c83bc408a86728f5d0aceece90e9d919e7044..130652feb593da7be8196cba7af44d0d876b58cb 100644 (file)
@@ -1210,6 +1210,9 @@ static inline void qc_treat_acked_tx_frm(struct quic_frame *frm,
                        eb64_insert(&qcs->tx.acked_frms, &strm->offset);
                }
                stream_acked |= qcs_try_to_consume(qcs);
+
+               if (qcs->flags & QC_SF_DETACH)
+                       tasklet_wakeup(qcs->shut_tl);
        }
        break;
        default: