]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: quic: Dynamic allocations of packet number spaces
authorFrédéric Lécaille <flecaille@haproxy.com>
Tue, 20 Jun 2023 09:21:43 +0000 (11:21 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 30 Jun 2023 14:20:55 +0000 (16:20 +0200)
Add a pool to dynamically handle the memory used for the QUIC TLS packet number spaces.
Remove the static array of packet number spaces at QUIC connection level (struct
quic_conn) and add three new members to quic_conn struc as pointers to quic_pktns
struct, one by packet number space as follows:
     ->ipktns for Initial packet number space,
     ->hpktns for Handshake packet number space and
     ->apktns for Application packet number space.
Also add a ->pktns_list new member (struct list) to quic_conn struct to attach
the list of the packet number spaces allocated for the QUIC connection.
Implement ssl_to_quic_pktns() to map and retrieve the addresses of these pointers
from TLS stack encryption levels.
Modify quic_pktns_init() to initialize these members.
Modify ha_quic_set_encryption_secrets() and ha_quic_add_handshake_data()  to
allocate the packet numbers and initialize the encryption level.
Implement quic_pktns_release() which takes pointers to pointers to packet number
space objects to release the memory allocated for a packet number space attached
to a QUIC connection and reset their address values.

Modify qc_new_conn() to allocation only the Initial packet number space and
Initial encryption level.

Modify QUIC loss detection API (quic_loss.c) to use the new ->pktns_list
list attached to a QUIC connection in place of a static array of packet number
spaces.

Replace at several locations the use of elements of an array of packet number
spaces by one of the three pointers to packet number spaces

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

index 3107ed5dd849a874c0e7eb1448b1c92448d06bb2..3e1435aa8e9508404bee506ae4441dae9fe3cf2f 100644 (file)
@@ -598,7 +598,11 @@ struct quic_conn {
        uint64_t next_cid_seq_num;
 
        struct quic_enc_level els[QUIC_TLS_ENC_LEVEL_MAX];
-       struct quic_pktns pktns[QUIC_TLS_PKTNS_MAX];
+       struct quic_pktns *ipktns;
+       struct quic_pktns *hpktns;
+       struct quic_pktns *apktns;
+       /* List of packet number spaces attached to this connection */
+       struct list pktns_list;
 
        struct ssl_sock_ctx *xprt_ctx;
 
index e3c60325b60e5422f75e2213d2f306aa8afcf547..6e9847d310a7b5283d5989f8d48a53269747e894 100644 (file)
@@ -52,8 +52,8 @@ extern struct pool_head *pool_head_quic_connection_id;
 
 int ssl_quic_initial_ctx(struct bind_conf *bind_conf);
 struct quic_cstream *quic_cstream_new(struct quic_conn *qc);
-struct quic_cstream *quic_cstream_new(struct quic_conn *qc);
 void quic_cstream_free(struct quic_cstream *cs);
+void quic_free_arngs(struct quic_conn *qc, struct quic_arngs *arngs);
 
 /* Return the long packet type matching with <qv> version and <type> */
 static inline int quic_pkt_type(int type, uint32_t version)
index dddb0d4e903a060bddefd76847c8e0baeaf63be1..c226f1bb30ec5d91f450c9ce5d638f645953f31b 100644 (file)
@@ -52,6 +52,7 @@
 #define TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS       0x0039
 #define TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS_DRAFT 0xffa5
 
+extern struct pool_head *pool_head_quic_pktns;
 extern struct pool_head *pool_head_quic_tls_secret;
 extern struct pool_head *pool_head_quic_tls_iv;
 extern struct pool_head *pool_head_quic_tls_key;
index 77f54deeef313cd790e1462ed127c691c5846962..a7bebc668c3603b7a69502cc2febc626c1fdc1b9 100644 (file)
@@ -30,6 +30,7 @@
 #include <haproxy/quic_tls-t.h>
 #include <haproxy/trace.h>
 
+void quic_pktns_release(struct quic_conn *qc, struct quic_pktns **pktns);
 void quic_tls_keys_hexdump(struct buffer *buf,
                            const struct quic_tls_secrets *secs);
 void quic_tls_kp_keys_hexdump(struct buffer *buf,
@@ -163,6 +164,23 @@ static inline const EVP_CIPHER *tls_hp(const SSL_CIPHER *cipher)
 
 }
 
+/* These following functions map TLS implementation encryption level to ours */
+static inline struct quic_pktns **ssl_to_quic_pktns(struct quic_conn *qc,
+                                                    enum ssl_encryption_level_t level)
+{
+       switch (level) {
+       case ssl_encryption_initial:
+               return &qc->ipktns;
+       case ssl_encryption_early_data:
+               return &qc->apktns;
+       case ssl_encryption_handshake:
+               return &qc->hpktns;
+       case ssl_encryption_application:
+               return &qc->apktns;
+       default:
+               return NULL;
+       }
+}
 /* These following functions map TLS implementation encryption level to ours */
 static inline enum quic_tls_enc_level ssl_to_quic_enc_level(enum ssl_encryption_level_t level)
 {
@@ -326,8 +344,14 @@ static inline char quic_packet_type_enc_level_char(int packet_type)
 /* Initialize a QUIC packet number space.
  * Never fails.
  */
-static inline void quic_pktns_init(struct quic_pktns *pktns)
+static inline int quic_pktns_init(struct quic_conn *qc, struct quic_pktns **p)
 {
+       struct quic_pktns *pktns;
+
+       pktns = pool_alloc(pool_head_quic_pktns);
+       if (!pktns)
+               return 0;
+
        LIST_INIT(&pktns->tx.frms);
        pktns->tx.next_pn = -1;
        pktns->tx.pkts = EB_ROOT_UNIQUE;
@@ -346,6 +370,13 @@ static inline void quic_pktns_init(struct quic_pktns *pktns)
        pktns->rx.largest_time_received = 0;
 
        pktns->flags = 0;
+       if (p == &qc->hpktns && qc->apktns)
+               LIST_INSERT(&qc->ipktns->list, &pktns->list);
+       else
+               LIST_APPEND(&qc->pktns_list, &pktns->list);
+       *p = pktns;
+
+       return 1;
 }
 
 static inline void quic_pktns_tx_pkts_release(struct quic_pktns *pktns, struct quic_conn *qc)
@@ -399,7 +430,7 @@ static inline void quic_pktns_discard(struct quic_pktns *pktns,
  */
 static inline int quic_application_pktns(struct quic_pktns *pktns, struct quic_conn *qc)
 {
-       return pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT];
+       return pktns == qc->apktns;
 }
 
 /* Returns the current largest acknowledged packet number if exists, -1 if not */
@@ -420,11 +451,11 @@ static inline int64_t quic_pktns_get_largest_acked_pn(struct quic_pktns *pktns)
 static inline char quic_pktns_char(const struct quic_conn *qc,
                                    const struct quic_pktns *pktns)
 {
-       if (pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT])
+       if (pktns == qc->apktns)
                return 'A';
-       else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE])
+       else if (pktns == qc->hpktns)
                return 'H';
-       else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL])
+       else if (pktns == qc->ipktns)
                return 'I';
 
        return '-';
index 847046f50bf5c361fe8167c40e6bda6da220b0e6..a1d65508527d08a121932b2822a1ea9a486f3ab1 100644 (file)
@@ -227,6 +227,9 @@ DECLARE_STATIC_POOL(pool_head_quic_cstream, "quic_cstream", sizeof(struct quic_c
 DECLARE_POOL(pool_head_quic_frame, "quic_frame", sizeof(struct quic_frame));
 DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng", sizeof(struct quic_arng_node));
 
+static int quic_conn_enc_level_init(struct quic_conn *qc,
+                                    struct quic_pktns *pktns,
+                                    enum quic_tls_enc_level level);
 static struct quic_connection_id *new_quic_cid(struct eb_root *root,
                                                struct quic_conn *qc,
                                                const struct quic_cid *odcid,
@@ -813,15 +816,11 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
 /* Returns 1 if the peer has validated <qc> QUIC connection address, 0 if not. */
 static inline int quic_peer_validated_addr(struct quic_conn *qc)
 {
-       struct quic_pktns *hdshk_pktns, *app_pktns;
-
        if (!qc_is_listener(qc))
                return 1;
 
-       hdshk_pktns = qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns;
-       app_pktns = qc->els[QUIC_TLS_ENC_LEVEL_APP].pktns;
-       if ((hdshk_pktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED) ||
-           (app_pktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED) ||
+       if ((qc->hpktns && (qc->hpktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED)) ||
+           (qc->apktns && (qc->apktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED)) ||
            qc->state >= QUIC_HS_ST_COMPLETE)
                return 1;
 
@@ -1052,7 +1051,9 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
                                    const uint8_t *write_secret, size_t secret_len)
 {
        struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
-       struct quic_tls_ctx *tls_ctx = &qc->els[ssl_to_quic_enc_level(level)].tls_ctx;
+       enum quic_tls_enc_level tel = ssl_to_quic_enc_level(level);
+       struct quic_enc_level *qel = &qc->els[tel];
+       struct quic_tls_ctx *tls_ctx = &qel->tls_ctx;
        const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
        struct quic_tls_secrets *rx = NULL, *tx = NULL;
        const struct quic_version *ver =
@@ -1062,6 +1063,17 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
        TRACE_ENTER(QUIC_EV_CONN_RWSEC, qc);
        BUG_ON(secret_len > QUIC_TLS_SECRET_LEN);
 
+       if (!qel->pktns) {
+               struct quic_pktns **pktns = ssl_to_quic_pktns(qc, level);
+
+               if (pktns == NULL ||
+                   !quic_pktns_init(qc, pktns) ||
+                   !quic_conn_enc_level_init(qc, *pktns, tel)) {
+                       TRACE_ERROR("Could not initialized the packet number space", QUIC_EV_CONN_ADDDATA, qc);
+                       goto leave;
+               }
+       }
+
        if (qc->flags & QUIC_FL_CONN_TO_KILL) {
                TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc);
                goto out;
@@ -1379,6 +1391,17 @@ int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level,
        }
 
        qel = &qc->els[tel];
+       if (!qel->pktns) {
+               struct quic_pktns **pktns = ssl_to_quic_pktns(qc, level);
+
+               if (pktns == NULL ||
+                   !quic_pktns_init(qc, pktns) ||
+                   !quic_conn_enc_level_init(qc, *pktns, tel)) {
+                       TRACE_ERROR("Could not initialized the packet number space", QUIC_EV_CONN_ADDDATA, qc);
+                       goto leave;
+               }
+       }
+
        if (!quic_crypto_data_cpy(qc, qel, data, len)) {
                TRACE_ERROR("Could not bufferize", QUIC_EV_CONN_ADDDATA, qc);
                goto leave;
@@ -4600,7 +4623,7 @@ int qc_treat_rx_pkts(struct quic_conn *qc, struct quic_enc_level *cur_el,
                                if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) {
                                        int arm_ack_timer =
                                                qc->state >= QUIC_HS_ST_COMPLETE &&
-                                               qel->pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT];
+                                               qel->pktns == qc->apktns;
 
                                        qel->pktns->flags |= QUIC_FL_PKTNS_ACK_REQUIRED;
                                        qel->pktns->rx.nb_aepkts_since_last_ack++;
@@ -5323,7 +5346,7 @@ struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
                        goto out;
                }
 
-               if (pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL]) {
+               if (pktns == qc->ipktns) {
                        if (qc_may_probe_ipktns(qc)) {
                                qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
                                pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
@@ -5332,19 +5355,19 @@ struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
                        else {
                                TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
                        }
-                       if (qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].tx.in_flight) {
+                       if (qc->hpktns->tx.in_flight) {
                                qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
-                               qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
+                               qc->hpktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
                                TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
                        }
                }
-               else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE]) {
+               else if (pktns == qc->hpktns) {
                        TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
                        qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
                        pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
-                       if (qc->pktns[QUIC_TLS_PKTNS_INITIAL].tx.in_flight) {
+                       if (qc->ipktns->tx.in_flight) {
                                if (qc_may_probe_ipktns(qc)) {
-                                       qc->pktns[QUIC_TLS_PKTNS_INITIAL].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
+                                       qc->ipktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
                                        TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
                                }
                                else {
@@ -5352,7 +5375,7 @@ struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
                                }
                        }
                }
-               else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT]) {
+               else if (pktns == qc->apktns) {
                        pktns->tx.pto_probe = QUIC_MAX_NB_PTO_DGRAMS;
                        /* Wake up upper layer if waiting to send new data. */
                        if (!qc_notify_send(qc)) {
@@ -5517,23 +5540,16 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
                qel->pktns = NULL;
        }
 
+       /* Packet number spaces */
+       qc->ipktns = qc->hpktns = qc->apktns = NULL;
+       LIST_INIT(&qc->pktns_list);
+
        quic_tls_ctx_reset(&qc->negotiated_ictx);
 
        app_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
        app_ctx->rx.secret = NULL;
        app_ctx->tx.secret = NULL;
 
-       /* Packet number spaces: required to safely call quic_pktns_tx_pkts_release()
-        * from quic_conn_release().
-        */
-       for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++) {
-               struct quic_pktns *pktns = &qc->pktns[i];
-
-               LIST_INIT(&pktns->tx.frms);
-               pktns->tx.pkts = EB_ROOT_UNIQUE;
-               pktns->rx.arngs.root = EB_ROOT_UNIQUE;
-       }
-
        /* Required to safely call quic_conn_prx_cntrs_update() from quic_conn_release(). */
        qc->prx_counters = NULL;
 
@@ -5591,17 +5607,14 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
        /* Select our SCID which is the first CID with 0 as sequence number. */
        qc->scid = conn_id->cid;
 
-       /* Packet number spaces initialization. */
-       for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++)
-               quic_pktns_init(&qc->pktns[i]);
-       /* QUIC encryption level context initialization. */
-       for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
-               if (!quic_conn_enc_level_init(qc, i)) {
-                       TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc);
-                       goto err;
-               }
-               /* Initialize the packet number space. */
-               qc->els[i].pktns = &qc->pktns[quic_tls_pktns(i)];
+       /* Initial packet number spaces initialization. */
+       if (!quic_pktns_init(qc, &qc->ipktns))
+               goto err;
+
+       /* Initial encryption level initialization */
+       if (!quic_conn_enc_level_init(qc, qc->ipktns, QUIC_TLS_ENC_LEVEL_INITIAL)) {
+               TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc);
+               goto err;
        }
 
        qc->original_version = qv;
@@ -5789,10 +5802,9 @@ void quic_conn_release(struct quic_conn *qc)
        pool_free(pool_head_quic_tls_secret, app_tls_ctx->rx.secret);
        pool_free(pool_head_quic_tls_secret, app_tls_ctx->tx.secret);
 
-       for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++) {
-               quic_pktns_tx_pkts_release(&qc->pktns[i], qc);
-               quic_free_arngs(qc, &qc->pktns[i].rx.arngs);
-       }
+       quic_pktns_release(qc, &qc->ipktns);
+       quic_pktns_release(qc, &qc->hpktns);
+       quic_pktns_release(qc, &qc->apktns);
 
        qc_detach_th_ctx_list(qc, 0);
 
@@ -8506,7 +8518,7 @@ void qc_notify_err(struct quic_conn *qc)
  */
 int qc_notify_send(struct quic_conn *qc)
 {
-       const struct quic_pktns *pktns = &qc->pktns[QUIC_TLS_PKTNS_01RTT];
+       const struct quic_pktns *pktns = qc->apktns;
 
        if (qc->subs && qc->subs->events & SUB_RETRY_SEND) {
                /* RFC 9002 7.5. Probe Timeout
@@ -8830,13 +8842,13 @@ static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc)
        chunk_appendf(&trash, "\n");
 
        /* Packet number spaces information */
-       pktns = &qc->pktns[QUIC_TLS_PKTNS_INITIAL];
+       pktns = qc->ipktns;
        chunk_appendf(&trash, "  [initl]             rx.ackrng=%-6zu tx.inflight=%-6zu",
                      pktns->rx.arngs.sz, pktns->tx.in_flight);
-       pktns = &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE];
+       pktns = qc->hpktns;
        chunk_appendf(&trash, "           [hndshk] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
                      pktns->rx.arngs.sz, pktns->tx.in_flight);
-       pktns = &qc->pktns[QUIC_TLS_PKTNS_01RTT];
+       pktns = qc->apktns;
        chunk_appendf(&trash, "  [01rtt]             rx.ackrng=%-6zu tx.inflight=%-6zu\n",
                      pktns->rx.arngs.sz, pktns->tx.in_flight);
 
index 37b40cc7b4c27e886de9157ee7c04b4f02aa9291..04de92430c8acc00a2dec8d4ae0ce8262dee6e11 100644 (file)
@@ -56,19 +56,21 @@ void quic_loss_srtt_update(struct quic_loss *ql,
  */
 struct quic_pktns *quic_loss_pktns(struct quic_conn *qc)
 {
-       enum quic_tls_pktns i;
-       struct quic_pktns *pktns;
+       struct quic_pktns *pktns, *p;
 
        TRACE_ENTER(QUIC_EV_CONN_SPTO, qc);
 
-       pktns = &qc->pktns[QUIC_TLS_PKTNS_INITIAL];
-       TRACE_PROTO("TX loss pktns", QUIC_EV_CONN_SPTO, qc, pktns);
-       for (i = QUIC_TLS_PKTNS_HANDSHAKE; i < QUIC_TLS_PKTNS_MAX; i++) {
-               TRACE_PROTO("TX loss pktns", QUIC_EV_CONN_SPTO, qc, &qc->pktns[i]);
+       BUG_ON(LIST_ISEMPTY(&qc->pktns_list));
+       pktns = p = LIST_NEXT(&qc->pktns_list, struct quic_pktns *, list);
+
+       do {
+               TRACE_PROTO("TX loss pktns", QUIC_EV_CONN_SPTO, qc, p);
                if (!tick_isset(pktns->tx.loss_time) ||
-                   tick_is_lt(qc->pktns[i].tx.loss_time, pktns->tx.loss_time))
-                       pktns = &qc->pktns[i];
-       }
+                   tick_is_lt(p->tx.loss_time, pktns->tx.loss_time)) {
+                       pktns = p;
+               }
+               p = LIST_NEXT(&p->list, struct quic_pktns *, list);
+       } while (&p->list != &qc->pktns_list);
 
        TRACE_LEAVE(QUIC_EV_CONN_SPTO, qc);
 
@@ -83,12 +85,13 @@ struct quic_pktns *quic_pto_pktns(struct quic_conn *qc,
                                   int handshake_confirmed,
                                   unsigned int *pto)
 {
-       int i;
        unsigned int duration, lpto;
        struct quic_loss *ql = &qc->path->loss;
        struct quic_pktns *pktns, *p;
 
        TRACE_ENTER(QUIC_EV_CONN_SPTO, qc);
+
+       BUG_ON(LIST_ISEMPTY(&qc->pktns_list));
        duration =
                (ql->srtt >> 3) +
                (QUIC_MAX(ql->rtt_var, QUIC_TIMER_GRANULARITY) << ql->pto_count);
@@ -107,32 +110,32 @@ struct quic_pktns *quic_pto_pktns(struct quic_conn *qc,
         */
 
        lpto = TICK_ETERNITY;
-       pktns = p = &qc->pktns[QUIC_TLS_PKTNS_INITIAL];
+       pktns = p = LIST_NEXT(&qc->pktns_list, struct quic_pktns *, list);
 
-       for (i = QUIC_TLS_PKTNS_INITIAL; i < QUIC_TLS_PKTNS_MAX; i++) {
+       do {
                unsigned int tmp_pto;
 
-               if (!qc->pktns[i].tx.in_flight)
-                       continue;
+               if (p->tx.in_flight) {
+                       if (p == qc->apktns) {
+                               if (!handshake_confirmed) {
+                                       TRACE_STATE("TX PTO handshake not already confirmed", QUIC_EV_CONN_SPTO, qc);
+                                       goto out;
+                               }
 
-               if (i == QUIC_TLS_PKTNS_01RTT) {
-                       if (!handshake_confirmed) {
-                               TRACE_STATE("TX PTO handshake not already confirmed", QUIC_EV_CONN_SPTO, qc);
+                               duration += qc->max_ack_delay << ql->pto_count;
+                       }
+
+                       tmp_pto = tick_add(p->tx.time_of_last_eliciting, duration);
+                       if (!tick_isset(lpto) || tick_is_lt(tmp_pto, lpto)) {
+                               lpto = tmp_pto;
                                pktns = p;
-                               goto out;
                        }
 
-                       duration += qc->max_ack_delay << ql->pto_count;
+                       TRACE_PROTO("TX PTO", QUIC_EV_CONN_SPTO, qc, p);
                }
 
-               p = &qc->pktns[i];
-               tmp_pto = tick_add(p->tx.time_of_last_eliciting, duration);
-               if (!tick_isset(lpto) || tick_is_lt(tmp_pto, lpto)) {
-                       lpto = tmp_pto;
-                       pktns = p;
-               }
-               TRACE_PROTO("TX PTO", QUIC_EV_CONN_SPTO, qc, p);
-       }
+               p = LIST_NEXT(&p->list, struct quic_pktns *, list);
+       } while (&p->list != &qc->pktns_list);
 
  out:
        if (pto)
index e417764787ad68c0c554ead2f31e4fb9a045998b..592a10613f39e89662769d82c73840ec82711de4 100644 (file)
@@ -12,6 +12,7 @@
 #include <haproxy/quic_conn.h>
 
 
+DECLARE_POOL(pool_head_quic_pktns,      "quic_pktns",      sizeof(struct quic_pktns));
 DECLARE_POOL(pool_head_quic_tls_secret, "quic_tls_secret", QUIC_TLS_SECRET_LEN);
 DECLARE_POOL(pool_head_quic_tls_iv,     "quic_tls_iv",     QUIC_TLS_IV_LEN);
 DECLARE_POOL(pool_head_quic_tls_key,    "quic_tls_key",    QUIC_TLS_KEY_LEN);
@@ -74,6 +75,19 @@ void quic_tls_kp_keys_hexdump(struct buffer *buf,
                chunk_appendf(buf, "%02x", kp->iv[i]);
 }
 
+/* Release the memory of <pktns> packet number space attached to <qc> QUIC connection. */
+void quic_pktns_release(struct quic_conn *qc, struct quic_pktns **pktns)
+{
+       if (!*pktns)
+               return;
+
+       quic_pktns_tx_pkts_release(*pktns, qc);
+       quic_free_arngs(qc, &(*pktns)->rx.arngs);
+       LIST_DEL_INIT(&(*pktns)->list);
+       pool_free(pool_head_quic_pktns, *pktns);
+       *pktns = NULL;
+}
+
 /* Dump <secret> TLS secret. */
 void quic_tls_secret_hexdump(struct buffer *buf,
                              const unsigned char *secret, size_t secret_len)