]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Add spin bit support
authorFrédéric Lécaille <flecaille@haproxy.com>
Tue, 7 Mar 2023 10:53:43 +0000 (11:53 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 8 Mar 2023 07:50:54 +0000 (08:50 +0100)
Add QUIC_FL_RX_PACKET_SPIN_BIT new RX packet flag to mark an RX packet as having
the spin bit set. Idem for the connection with QUIC_FL_CONN_SPIN_BIT flag.
Implement qc_handle_spin_bit() to set/unset QUIC_FL_CONN_SPIN_BIT for the connection
as soon as a packet number could be deciphered.
Modify quic_build_packet_short_header() to set the spin bit when building
a short packet header.

Validated by quic-tracker spin bit test.

Must be backported to 2.7.

include/haproxy/quic_conn-t.h
src/quic_conn.c

index f5fc207ba0ea86c12726e01e2c132afa8455fc00..d85dc6fd39665fa9c1e26436a8a8a84d6676958b 100644 (file)
@@ -398,6 +398,8 @@ struct quic_dgram {
 #define QUIC_FL_RX_PACKET_ACK_ELICITING (1UL << 0)
 /* Packet is the first one in the containing datagram. */
 #define QUIC_FL_RX_PACKET_DGRAM_FIRST   (1UL << 1)
+/* Spin bit set */
+#define QUIC_FL_RX_PACKET_SPIN_BIT   (1UL << 2)
 
 struct quic_rx_packet {
        struct list list;
@@ -608,6 +610,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_LISTENER                    (1U << 3)
 #define QUIC_FL_CONN_ACCEPT_REGISTERED           (1U << 4)
index b6344db2b9a5e056c53fa2d69d7037ed4c88a0f1..2cae51cc3e888d781be97100b0569cb1158b2b0a 100644 (file)
@@ -4190,6 +4190,31 @@ int quic_update_ack_ranges_list(struct quic_conn *qc,
        TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
        return ret;
 }
+
+/* Detect the value of the spin bit to be used. */
+static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packet *pkt,
+                                      struct quic_enc_level *qel)
+{
+       uint64_t largest_pn = qel->pktns->rx.largest_pn;
+
+       if (qel != &qc->els[QUIC_TLS_ENC_LEVEL_APP] || largest_pn == -1 ||
+           pkt->pn <= largest_pn)
+               return;
+
+       if (qc_is_listener(qc)) {
+               if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
+                       qc->flags |= QUIC_FL_CONN_SPIN_BIT;
+               else
+                       qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
+       }
+       else {
+               if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
+                       qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
+               else
+                       qc->flags |= QUIC_FL_CONN_SPIN_BIT;
+       }
+}
+
 /* Remove the header protection of packets at <el> encryption level.
  * Always succeeds.
  */
@@ -4216,6 +4241,7 @@ static inline void qc_rm_hp_pkts(struct quic_conn *qc, struct quic_enc_level *el
                        TRACE_ERROR("hp removing error", QUIC_EV_CONN_ELRMHP, qc);
                }
                else {
+                       qc_handle_spin_bit(qc, pqpkt, el);
                        /* The AAD includes the packet number field */
                        pqpkt->aad_len = pqpkt->pn_offset + pqpkt->pnl;
                        /* Store the packet into the tree of packets to decrypt. */
@@ -5763,6 +5789,7 @@ static inline int qc_try_rm_hp(struct quic_conn *qc,
                        goto out;
                }
 
+               qc_handle_spin_bit(qc, pkt, qel);
                /* The AAD includes the packet number field. */
                pkt->aad_len = pkt->pn_offset + pkt->pnl;
                if (pkt->len - pkt->aad_len < QUIC_TLS_TAG_LEN) {
@@ -5845,6 +5872,8 @@ static inline int qc_parse_hd_form(struct quic_rx_packet *pkt,
                }
        }
        else {
+               if (byte0 & QUIC_PACKET_SPIN_BIT)
+                       pkt->flags |= QUIC_FL_RX_PACKET_SPIN_BIT;
                pkt->type = QUIC_PACKET_TYPE_SHORT;
                *long_header = 0;
        }
@@ -7023,6 +7052,8 @@ static int quic_build_packet_short_header(unsigned char **buf, const unsigned ch
                                           unsigned char tls_flags)
 {
        int ret = 0;
+       unsigned char spin_bit =
+               (qc->flags & QUIC_FL_CONN_SPIN_BIT) ? QUIC_PACKET_SPIN_BIT : 0;
 
        TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
 
@@ -7032,7 +7063,7 @@ static int quic_build_packet_short_header(unsigned char **buf, const unsigned ch
        }
 
        /* #0 byte flags */
-       *(*buf)++ = QUIC_PACKET_FIXED_BIT |
+       *(*buf)++ = QUIC_PACKET_FIXED_BIT | spin_bit |
                ((tls_flags & QUIC_FL_TLS_KP_BIT_SET) ? QUIC_PACKET_KEY_PHASE_BIT : 0) | (pn_len - 1);
        /* Destination connection ID */
        if (qc->dcid.len) {