From: Amaury Denoyelle Date: Tue, 11 Apr 2023 14:46:03 +0000 (+0200) Subject: MINOR: quic: delay post handshake frames after accept X-Git-Tag: v2.8-dev8~107 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1304d19dee7cf9f703a24be9e5c00b862a62a10a;p=thirdparty%2Fhaproxy.git MINOR: quic: delay post handshake frames after accept When QUIC handshake is completed on our side, some frames are prepared to be sent : * HANDSHAKE_DONE * several NEW_CONNECTION_ID with CIDs allocated This step was previously executed in quic_conn_io_cb() directly after CRYPTO frames parsing. This patch delays it to be completed after accept. Special care have been taken to ensure it is still functional with 0-RTT activated. For the moment, this patch should have no impact. However, when quic_conn thread migration on accept will be implemented, it will be easier to remap only one CID to the new thread. New CIDs will be allocated after migration on the new thread. This should be backported up to 2.7 after a period of observation. --- diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index c8c6f48d33..51337b1843 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -616,7 +616,7 @@ enum qc_mux_state { /* Flags at connection level */ #define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1U << 0) #define QUIC_FL_CONN_SPIN_BIT (1U << 1) /* Spin bit set by remote peer */ -#define QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT (1U << 2) +#define QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS (1U << 2) /* HANDSHAKE_DONE must be sent */ #define QUIC_FL_CONN_LISTENER (1U << 3) #define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4) #define QUIC_FL_CONN_TX_MUX_CONTEXT (1U << 5) /* sending in progress from the MUX layer */ diff --git a/src/quic_conn.c b/src/quic_conn.c index 2d75e9938b..74a5f327f1 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -2459,6 +2459,7 @@ static inline int qc_provide_cdata(struct quic_enc_level *el, /* I/O callback switch */ qc->wait_event.tasklet->process = quic_conn_app_io_cb; if (qc_is_listener(ctx->qc)) { + qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS; qc->state = QUIC_HS_ST_CONFIRMED; /* The connection is ready to be accepted. */ quic_accept_push_qc(qc); @@ -4141,7 +4142,7 @@ static int quic_build_post_handshake_frames(struct quic_conn *qc) } LIST_SPLICE(&qel->pktns->tx.frms, &frm_list); - qc->flags |= QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT; + qc->flags &= ~QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS; ret = 1; leave: @@ -4780,6 +4781,14 @@ int qc_send_mux(struct quic_conn *qc, struct list *frms) TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc); BUG_ON(qc->mux_state != QC_MUX_READY); /* Only MUX can uses this function so it must be ready. */ + /* Try to send post handshake frames first unless on 0-RTT. */ + if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) && + qc->state >= QUIC_HS_ST_COMPLETE) { + struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; + quic_build_post_handshake_frames(qc); + qc_send_app_pkts(qc, &qel->pktns->tx.frms); + } + TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc); qc->flags |= QUIC_FL_CONN_TX_MUX_CONTEXT; ret = qc_send_app_pkts(qc, frms); @@ -4967,6 +4976,15 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta if (qc_test_fd(qc)) qc_rcv_buf(qc); + /* Prepare post-handshake frames + * - after connection is instantiated (accept is done) + * - handshake state is completed (may not be the case here in 0-RTT) + */ + if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) && qc->conn && + qc->state >= QUIC_HS_ST_COMPLETE) { + quic_build_post_handshake_frames(qc); + } + /* Retranmissions */ if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) { TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc); @@ -5090,10 +5108,6 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) st = qc->state; if (st >= QUIC_HS_ST_COMPLETE) { - if (!(qc->flags & QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT) && - !quic_build_post_handshake_frames(qc)) - goto out; - if (!(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD)) { /* Discard the Handshake keys. */