From: Frédéric Lécaille Date: Fri, 3 Mar 2023 16:34:41 +0000 (+0100) Subject: MINOR: quic: Send PING frames when probing Initial packet number space X-Git-Tag: v2.8-dev5~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec93721fb04d92c2331e28898470bed187000acc;p=thirdparty%2Fhaproxy.git MINOR: quic: Send PING frames when probing Initial packet number space In very very rare cases, it is possible the Initial packet number space must be probed even if it there is no more in flight CRYPTO frames. In such cases, a PING frame is sent into an Initial packet. As this packet is ack-eliciting, it must be padded by the server. qc_do_build_pkt() is modified to do so. Take the opportunity of this patch to modify the trace for TX frames to easily distinguished them from other frame relative traces. Must be backported to 2.7. --- diff --git a/src/quic_conn.c b/src/quic_conn.c index 81ad537896..60af8b8c18 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -3429,7 +3429,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, /* Pad this Initial packet if there is no ack-eliciting frames to send from * the next packet number space. */ - if (LIST_ISEMPTY(next_tel_frms)) + if (!next_tel_frms || LIST_ISEMPTY(next_tel_frms)) padding = 1; } @@ -4539,6 +4539,14 @@ static int qc_dgrams_retransmit(struct quic_conn *qc) LIST_SPLICE(&iqel->pktns->tx.frms, &ifrms); LIST_SPLICE(&hqel->pktns->tx.frms, &hfrms); } + else { + if (!(qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED)) { + iqel->pktns->tx.pto_probe = 1; + if (!qc_send_hdshk_pkts(qc, 0, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms, + QUIC_TLS_ENC_LEVEL_NONE, NULL)) + goto leave; + } + } } TRACE_STATE("no more need to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc); @@ -7456,6 +7464,9 @@ static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end, len_sz = quic_int_getsize(len); /* Add this packet size to */ dglen += head_len + len_sz + len; + /* Note that is true only when building an Handshake packet + * coalesced to an Initial packet. + */ if (padding && dglen < QUIC_INITIAL_PACKET_MINLEN) { /* This is a maximum padding size */ padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen; @@ -7475,10 +7486,22 @@ static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end, /* If we cannot send a frame, we send a PING frame. */ add_ping_frm = 1; len += 1; + dglen += 1; + /* Note that only we are in the case where this Initial packet + * is not coalesced to an Handshake packet. We must directly + * pad the datragram. + */ + if (pkt->type == QUIC_PACKET_TYPE_INITIAL && dglen < QUIC_INITIAL_PACKET_MINLEN) { + padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen; + padding_len -= quic_int_getsize(len + padding_len) - len_sz; + len += padding_len; + } + } + else { + /* If there is no frame at all to follow, add at least a PADDING frame. */ + if (!ack_frm_len && !cc) + len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len; } - /* If there is no frame at all to follow, add at least a PADDING frame. */ - if (!ack_frm_len && !cc) - len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len; } if (pkt->type != QUIC_PACKET_TYPE_SHORT && !quic_enc_int(&pos, end, len)) diff --git a/src/quic_frame.c b/src/quic_frame.c index 530a640770..2528dec70a 100644 --- a/src/quic_frame.c +++ b/src/quic_frame.c @@ -1155,7 +1155,7 @@ int qc_build_frm(unsigned char **buf, const unsigned char *end, goto leave; } - TRACE_PROTO("frame", QUIC_EV_CONN_BFRM, qc, frm); + TRACE_PROTO("TX frame", QUIC_EV_CONN_BFRM, qc, frm); *pos++ = frm->type; if (!quic_frame_builders[frm->type].func(&pos, end, frm, qc)) { TRACE_DEVEL("frame building error", QUIC_EV_CONN_BFRM, qc, frm);