]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Non optimal first datagram.
authorFrederic Lecaille <flecaille@haproxy.com>
Fri, 19 Jul 2024 14:06:55 +0000 (16:06 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Fri, 19 Jul 2024 14:22:00 +0000 (16:22 +0200)
This bug arrived with this commit:

     b068e758f MINOR: quic: simplify rescheduling for handshake

This commit introduced a bad side effect. Haproxy always replied by an ACK-only
datagram when it received the first client Initial packet. Then it handled
the CRYPTO data insided. And finally, it sent its own CRYPTO data. This broke
the packet coalescing rule whose aim is to optimally build and send as more
as QUIC packets by datagram.

To fix this, simply partially reverts this commit, to make the low level I/O
task return again if some CRYPTO were received. This will delay the
acknowledgement which will be sent with the CRYPTO data from the same
datagram again.

Must be backported to 3.0.

src/quic_conn.c

index 73b6430d2e59d55a6cde12890ebc2873408997c7..9c6a090461858ac6bfc025c8d79b8157bd6602f4 100644 (file)
@@ -755,6 +755,7 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
        st = qc->state;
        TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st);
 
+       /* TASK_HEAVY is set when received CRYPTO data have to be handled. */
        if (HA_ATOMIC_LOAD(&tl->state) & TASK_HEAVY) {
                qc_ssl_provide_all_quic_data(qc, qc->xprt_ctx);
                HA_ATOMIC_AND(&tl->state, ~TASK_HEAVY);
@@ -774,6 +775,16 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
        if (!qc_treat_rx_pkts(qc))
                goto out;
 
+       /* TASK_HEAVY is set when received CRYPTO data have to be handled. These data
+        * must be acknowledged asap and replied to with others CRYPTO data. In this
+        * case, it is more optimal to delay the ACK to send it with the CRYPTO data
+        * from the same datagram.
+        */
+       if (HA_ATOMIC_LOAD(&tl->state) & TASK_HEAVY) {
+               tasklet_wakeup(tl);
+               goto out;
+       }
+
        if (qc->flags & QUIC_FL_CONN_TO_KILL) {
                TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_PHPKTS, qc);
                goto out;