From: Frédéric Lécaille Date: Thu, 30 Dec 2021 15:14:20 +0000 (+0100) Subject: MINOR: quic: Speeding up Handshake Completion X-Git-Tag: v2.6-dev1~174 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3bb457c4ba0f16fa620d6502bc337156aa453714;p=thirdparty%2Fhaproxy.git MINOR: quic: Speeding up Handshake Completion According to RFC 9002 par. 6.2.3. when receving duplicate Initial CRYPTO data a server may a packet containing non unacknowledged before the PTO expiry. --- diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 630f8d16d5..5d9b82e25f 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -2170,6 +2170,34 @@ static inline int qc_handle_strm_frm(struct quic_rx_packet *pkt, return qc_handle_bidi_strm_frm(pkt, strm_frm, qc); } +/* Prepare a fast retransmission from encryption level + * which must be Initial encryption level. + */ +static void qc_prep_fast_retrans(struct quic_enc_level *qel, + struct quic_conn *qc) +{ + struct eb_root *pkts = &qel->pktns->tx.pkts; + struct eb64_node *node = eb64_first(pkts); + struct quic_tx_packet *pkt; + struct quic_frame *frm, *frmbak; + + start: + pkts = &qel->pktns->tx.pkts; + node = eb64_first(pkts); + if (!node) + return; + + pkt = eb64_entry(&node->node, struct quic_tx_packet, pn_node); + list_for_each_entry_safe(frm, frmbak, &pkt->frms, list) + qc_treat_nacked_tx_frm(qc, frm, qel->pktns); + if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] && + qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->tx.in_flight) { + qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->tx.pto_probe = 1; + qel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; + goto start; + } +} + /* Parse all the frames of QUIC packet for QUIC connection with * as I/O handler context and as encryption level. * Returns 1 if succeeded, 0 if failed. @@ -2180,6 +2208,7 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct struct quic_frame frm; const unsigned char *pos, *end; struct quic_conn *qc = ctx->qc; + int fast_retrans = 0; TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc); /* Skip the AAD */ @@ -2231,6 +2260,9 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct /* Nothing to do */ TRACE_PROTO("Already received CRYPTO data", QUIC_EV_CONN_ELRXPKTS, qc, pkt, &cfdebug); + if (objt_listener(ctx->conn->target) && + qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]) + fast_retrans = 1; break; } else { @@ -2321,6 +2353,12 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct } } + if (fast_retrans) { + qc_prep_fast_retrans(qel, qc); + if (qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->tx.in_flight) + qc_prep_fast_retrans(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE], qc); + } + /* The server must switch from INITIAL to HANDSHAKE handshake state when it * has successfully parse a Handshake packet. The Initial encryption must also * be discarded.