]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Send PING frames when probing Initial packet number space
authorFrédéric Lécaille <flecaille@haproxy.com>
Fri, 3 Mar 2023 16:34:41 +0000 (17:34 +0100)
committerFrédéric Lécaille <flecaille@haproxy.com>
Fri, 3 Mar 2023 18:12:26 +0000 (19:12 +0100)
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.

src/quic_conn.c
src/quic_frame.c

index 81ad537896caa2a9ef058f5e4913dd9c0b25286f..60af8b8c1861d90ee327a9e9b11c8528739039c7 100644 (file)
@@ -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> */
        dglen += head_len + len_sz + len;
+       /* Note that <padding> 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))
index 530a6407703d27fb0a6646145c6f81cca0772680..2528dec70a7c43da33f394438b76960069ca0bf4 100644 (file)
@@ -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);