]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: adjust timeout to accelerate closing
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 4 Apr 2022 14:15:06 +0000 (16:15 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 7 Apr 2022 08:23:10 +0000 (10:23 +0200)
Improve timeout handling on the MUX. When releasing a stream, first
check if the connection can be considered as dead and should be freed
immediatly. This allows to liberate resources faster when possible.

If the connection is still active, ensure there is no attached
conn-stream before scheduling the timeout. To do this, add a nb_cs field
in the qcc structure.

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

index 61ff95a3bf60290be25eb92d0bc2449e6e5335d4..edc693026d8c1c948fc895d8eb3ca321f1f0dcd2 100644 (file)
@@ -27,6 +27,7 @@ enum qcs_type {
 
 struct qcc {
        struct connection *conn;
+       uint64_t nb_cs; /* number of attached conn-streams */
        uint32_t flags; /* QC_CF_* */
 
        struct {
index 715f7e9f55065de7008161c95293595aac12c6d1..c01d1560e13434a26c95adc1d1631bc970333eed 100644 (file)
@@ -115,6 +115,8 @@ static inline struct conn_stream *qc_attach_cs(struct qcs *qcs, struct buffer *b
        cs->ctx = qcs;
        stream_new(qcs->qcc->conn->owner, cs, buf);
 
+       ++qcs->qcc->nb_cs;
+
        return cs;
 }
 
index 8e91d7b4d9a0042eed55bca03bcde77fabb5dc6f..ad1a69367aaadbb2c983969767894b070511960b 100644 (file)
@@ -471,14 +471,7 @@ static inline int qcc_is_dead(const struct qcc *qcc)
 /* Return true if the mux timeout should be armed. */
 static inline int qcc_may_expire(struct qcc *qcc)
 {
-
-       /* Consider that the timeout must be set if no bidirectional streams
-        * are opened.
-        */
-       if (!qcc->strms[QCS_CLT_BIDI].nb_streams)
-               return 1;
-
-       return 0;
+       return !qcc->nb_cs;
 }
 
 /* release function. This one should be called to free all resources allocated
@@ -502,6 +495,11 @@ static void qc_release(struct qcc *qcc)
                if (qcc->app_ops && qcc->app_ops->release)
                        qcc->app_ops->release(qcc->ctx);
 
+               if (qcc->task) {
+                       task_destroy(qcc->task);
+                       qcc->task = NULL;
+               }
+
                if (qcc->wait_event.tasklet)
                        tasklet_free(qcc->wait_event.tasklet);
 
@@ -894,9 +892,14 @@ static struct task *qc_io_cb(struct task *t, void *ctx, unsigned int status)
        qc_send(qcc);
 
        if (qc_release_detached_streams(qcc)) {
-               /* Schedule the mux timeout if no bidirectional streams left. */
-               if (qcc_may_expire(qcc)) {
-                       qcc->task->expire = tick_add(now_ms, qcc->timeout);
+               if (qcc_is_dead(qcc)) {
+                       qc_release(qcc);
+               }
+               else {
+                       if (qcc_may_expire(qcc))
+                               qcc->task->expire = tick_add(now_ms, qcc->timeout);
+                       else
+                               qcc->task->expire = TICK_ETERNITY;
                        task_queue(qcc->task);
                }
        }
@@ -955,6 +958,7 @@ static int qc_init(struct connection *conn, struct proxy *prx,
 
        qcc->conn = conn;
        conn->ctx = qcc;
+       qcc->nb_cs = 0;
        qcc->flags = 0;
 
        qcc->app_ops = NULL;
@@ -1052,6 +1056,8 @@ static void qc_detach(struct conn_stream *cs)
         * managment between xprt and mux is reorganized.
         */
 
+       --qcc->nb_cs;
+
        if (b_data(&qcs->tx.buf) || qcs->tx.offset > qcs->tx.sent_offset) {
                TRACE_DEVEL("leaving with remaining data, detaching qcs", QMUX_EV_STRM_END, qcc->conn, qcs);
                qcs->flags |= QC_SF_DETACH;
@@ -1060,9 +1066,14 @@ static void qc_detach(struct conn_stream *cs)
 
        qcs_destroy(qcs);
 
-       /* Schedule the mux timeout if no bidirectional streams left. */
-       if (qcc_may_expire(qcc)) {
-               qcc->task->expire = tick_add(now_ms, qcc->timeout);
+       if (qcc_is_dead(qcc)) {
+               qc_release(qcc);
+       }
+       else {
+               if (qcc_may_expire(qcc))
+                       qcc->task->expire = tick_add(now_ms, qcc->timeout);
+               else
+                       qcc->task->expire = TICK_ETERNITY;
                task_queue(qcc->task);
        }