]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: implement dedicated type for out-of-order stream ACK
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 1 Oct 2024 15:34:55 +0000 (17:34 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 4 Oct 2024 15:56:45 +0000 (17:56 +0200)
QUIC streamdesc layer is responsible to handle reception of ACK for
streams. It removes stream data from the underlying buffers on ACK
reception.

Streamdesc layer treats ACK in order at the stream level. Out of order
ACKs are buffered in a tree until they can be handled on older data
acknowledgement reception. Previously, qf_stream instance which comes
from the quic_tx_packet was used as tree node to buffer such ranges.

Introduce a new type dedicated to represent out of order stream ack data
range. This type is named qc_stream_ack. It contains minimal infos only
relative to the acknowledged stream data range.

This allows to reduce size of frequently used quic_frame with the
removal of tree node from qf_stream. Another side effect of this change
is that now quic_frame are always released immediately on ACK reception,
both in-order and out-of-order. This allows to also release the
quic_tx_packet instance which should reduce memory consumption.

The drawback of this change is that qc_stream_ack instance must be
allocated on out-of-order ACK reception. As such, qc_stream_desc_ack()
may fail if an error happens on allocation. For the moment, such error
is silenly recovered up to qc_treat_rx_pkts() with the dropping of the
received packet containing the ACK frame. In the future, it may be
useful to close the connection as this error may only happens on low
memory usage.

include/haproxy/quic_frame-t.h
include/haproxy/quic_frame.h
include/haproxy/quic_stream-t.h
include/haproxy/quic_stream.h
src/mux_quic.c
src/quic_frame.c
src/quic_retransmit.c
src/quic_rx.c
src/quic_stream.c
src/quic_trace.c
src/quic_tx.c

index fe80f279366770fd65f1c74ecfc66b0e96aca437..3c211e5bd00a8dee1ef37c0a1c449ce23854bb83 100644 (file)
@@ -171,7 +171,7 @@ struct qf_stream {
         */
        struct buffer *buf;
 
-       struct eb64_node offset;
+       uint64_t offset;
        uint64_t len;
 
        /* for TX pointer into <buf> field.
index 90d6b213c8a095fb8ef6f5c7b36ef3e8d145d6da..2da1ee14efcca8cd073fd27c722d916d7b93218a 100644 (file)
@@ -97,7 +97,7 @@ static inline size_t qc_frm_len(struct quic_frame *frm)
        case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F: {
                struct qf_stream *f = &frm->stream;
                len += 1 + quic_int_getsize(f->id) +
-                       ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ? quic_int_getsize(f->offset.key) : 0) +
+                       ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ? quic_int_getsize(f->offset) : 0) +
                        ((frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) ? quic_int_getsize(f->len) : 0) + f->len;
                break;
        }
@@ -267,7 +267,7 @@ static inline void qc_stream_frm_mv_fwd(struct quic_frame *frm, uint64_t data)
        struct buffer cf_buf;
 
        /* Set offset bit if not already there. */
-       strm_frm->offset.key += data;
+       strm_frm->offset += data;
        frm->type |= QUIC_STREAM_FRAME_TYPE_OFF_BIT;
 
        strm_frm->len -= data;
index 99f9d16daa6f64b67b611d05be3d9a8ec84731d1..3e55da5ee4ab004b26c0fb9c33f8a0644ae60389 100644 (file)
@@ -15,7 +15,7 @@
  * can be freed in strict order.
  */
 struct qc_stream_buf {
-       struct eb_root acked_frms; /* storage for out-of-order ACKs */
+       struct eb_root ack_tree; /* storage for out-of-order ACKs */
        struct eb64_node offset_node; /* node for qc_stream_desc buf tree */
        struct buffer buf; /* STREAM payload */
        int sbuf;
@@ -50,5 +50,12 @@ struct qc_stream_desc {
        void *ctx; /* notify context */
 };
 
+/* Represents a range of acknowledged data that cannot be immediately deleted. */
+struct qc_stream_ack {
+       struct eb64_node offset_node; /* range starting offset, used as attach point to streambuf <ack_tree>. */
+       uint64_t len;                 /* length of the acknowledged range */
+       int fin;                      /* set if the related STREAM frame had FIN bit set */
+};
+
 #endif /* USE_QUIC */
 #endif /* _HAPROXY_QUIC_STREAM_T_H_ */
index 1337a89652cbd44ecf386f60878df465e9794797..b4d56a2c7e3ca57446d2cc41e9a70a801a2e5bed 100644 (file)
@@ -7,13 +7,13 @@
 #include <haproxy/quic_stream-t.h>
 
 struct quic_conn;
-struct quic_frame;
 
 struct qc_stream_desc *qc_stream_desc_new(uint64_t id, enum qcs_type, void *ctx,
                                           struct quic_conn *qc);
 void qc_stream_desc_release(struct qc_stream_desc *stream, uint64_t final_size,
                             void *new_ctx);
-int qc_stream_desc_ack(struct qc_stream_desc *stream, struct quic_frame *frm);
+int qc_stream_desc_ack(struct qc_stream_desc *stream,
+                       uint64_t offset, uint64_t len, int fin);
 void qc_stream_desc_free(struct qc_stream_desc *stream, int closing);
 
 struct buffer *qc_stream_buf_get(struct qc_stream_desc *stream);
index 58695b0f3720d3fedd6b269bc7bda49172bf57e4..5141ee443ff1de5dbd550ea2f801e3874adc5a99 100644 (file)
@@ -1991,7 +1991,7 @@ static int qcs_build_stream_frm(struct qcs *qcs, struct buffer *out, char fin,
 
        frm->stream.stream = qcs->stream;
        frm->stream.id = qcs->id;
-       frm->stream.offset.key = 0;
+       frm->stream.offset = 0;
        frm->stream.dup = 0;
 
        if (total) {
@@ -2010,7 +2010,7 @@ static int qcs_build_stream_frm(struct qcs *qcs, struct buffer *out, char fin,
 
        if (qcs->tx.fc.off_real) {
                frm->type |= QUIC_STREAM_FRAME_TYPE_OFF_BIT;
-               frm->stream.offset.key = qcs->tx.fc.off_real;
+               frm->stream.offset = qcs->tx.fc.off_real;
        }
 
        /* Always set length bit as we do not know if there is remaining frames
@@ -2025,7 +2025,7 @@ static int qcs_build_stream_frm(struct qcs *qcs, struct buffer *out, char fin,
        {
                struct qcs_build_stream_trace_arg arg = {
                        .len = frm->stream.len, .fin = fin,
-                       .offset = frm->stream.offset.key,
+                       .offset = frm->stream.offset,
                };
                TRACE_LEAVE(QMUX_EV_QCS_SEND|QMUX_EV_QCS_BUILD_STRM,
                            qcc->conn, qcs, &arg);
index 9599b80c2e72ebb8e52454027fd71ab709f091bf..cdf14c8faa32bc913ddcccae99b45c741a0bf5ad 100644 (file)
@@ -138,7 +138,7 @@ void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm)
                chunk_appendf(&trace_buf, " uni=%d fin=%d id=%llu off=%llu len=%llu",
                              !!(strm_frm->id & QUIC_STREAM_FRAME_ID_DIR_BIT),
                              !!(frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT),
-                             (ull)strm_frm->id, (ull)strm_frm->offset.key, (ull)strm_frm->len);
+                             (ull)strm_frm->id, (ull)strm_frm->offset, (ull)strm_frm->len);
                break;
        }
        case QUIC_FT_MAX_DATA:
@@ -521,10 +521,10 @@ static int quic_build_stream_frame(unsigned char **pos, const unsigned char *end
 
        /* Caller must set OFF bit if and only if a non-null offset is used. */
        BUG_ON(!!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) !=
-              !!strm_frm->offset.key);
+              !!strm_frm->offset);
 
        if (!quic_enc_int(pos, end, strm_frm->id) ||
-           ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(pos, end, strm_frm->offset.key)) ||
+           ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(pos, end, strm_frm->offset)) ||
            ((frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) &&
             (!quic_enc_int(pos, end, strm_frm->len) || end - *pos < strm_frm->len)))
                return 0;
@@ -563,10 +563,9 @@ static int quic_parse_stream_frame(struct quic_frame *frm, struct quic_conn *qc,
                return 0;
 
        /* Offset parsing */
-       if (!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT)) {
-               strm_frm->offset.key = 0;
-       }
-       else if (!quic_dec_int((uint64_t *)&strm_frm->offset.key, pos, end))
+       if (!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT))
+               strm_frm->offset = 0;
+       else if (!quic_dec_int((uint64_t *)&strm_frm->offset, pos, end))
                return 0;
 
        /* Length parsing */
index ad653fdd977dce7c440a343776f911ea63225a3a..a8b8e99b93a97f07ceea608207951af4b3e34bed 100644 (file)
@@ -29,19 +29,19 @@ int qc_stream_frm_is_acked(struct quic_conn *qc, struct quic_frame *f)
        }
 
        /* Frame cannot advertise FIN for a smaller data range. */
-       BUG_ON(frm_fin && frm->offset.key + frm->len < s->ack_offset);
+       BUG_ON(frm_fin && frm->offset + frm->len < s->ack_offset);
 
-       if (frm->offset.key + frm->len < s->ack_offset ||
-           (frm->offset.key + frm->len == s->ack_offset &&
+       if (frm->offset + frm->len < s->ack_offset ||
+           (frm->offset + frm->len == s->ack_offset &&
             (!frm_fin || !(s->flags & QC_SD_FL_WAIT_FOR_FIN)))) {
                TRACE_DEVEL("STREAM frame already acked : fully acked range", QUIC_EV_CONN_PRSAFRM, qc, f);
                return 1;
        }
 
-       if (frm->offset.key < s->ack_offset &&
-           frm->offset.key + frm->len > s->ack_offset) {
+       if (frm->offset < s->ack_offset &&
+           frm->offset + frm->len > s->ack_offset) {
                /* Data range partially acked, remove it from STREAM frame. */
-               const uint64_t diff = s->ack_offset - frm->offset.key;
+               const uint64_t diff = s->ack_offset - frm->offset;
                TRACE_DEVEL("updated partially acked frame", QUIC_EV_CONN_PRSAFRM, qc, f);
                qc_stream_frm_mv_fwd(f, diff);
        }
index 08e73b4ec06c91d5a8e8e0091656650b1454d167..3eaf8704504061d6a7b38bd0a761fe3fff27d442 100644 (file)
@@ -203,10 +203,13 @@ static int qc_pkt_decrypt(struct quic_conn *qc, struct quic_enc_level *qel,
 
 /* Handle <frm> frame whose packet it is attached to has just been acknowledged. The memory allocated
  * for this frame will be at least released in every cases.
- * Never fail.
+ *
+ * Returns 1 on sucess else 0.
  */
-static void qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *frm)
+static int qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *frm)
 {
+       int ret = 0;
+
        TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
        TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
 
@@ -216,6 +219,7 @@ static void qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *f
                struct qf_stream *strm_frm = &frm->stream;
                struct eb64_node *node = NULL;
                struct qc_stream_desc *stream = NULL;
+               int ack;
 
                /* do not use strm_frm->stream as the qc_stream_desc instance
                 * might be freed at this stage. Use the id to do a proper
@@ -231,23 +235,33 @@ static void qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *f
                        /* early return */
                        goto leave;
                }
-               stream = eb64_entry(node, struct qc_stream_desc, by_id);
-
-               if (!qc_stream_desc_ack(stream, frm)) {
-                       TRACE_DEVEL("stream consumed on ACK received", QUIC_EV_CONN_ACKSTRM,
-                                   qc, strm_frm, stream);
+               else {
+                       stream = eb64_entry(node, struct qc_stream_desc, by_id);
+
+                       ack = qc_stream_desc_ack(stream, strm_frm->offset,
+                                                strm_frm->len,
+                                                frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT);
+                       if (!ack) {
+                               TRACE_DEVEL("stream consumed on ACK received",
+                                           QUIC_EV_CONN_ACKSTRM, qc, strm_frm, stream);
+
+                               if (qc_stream_desc_done(stream)) {
+                                       /* no need to continue if stream freed. */
+                                       TRACE_DEVEL("stream released and freed", QUIC_EV_CONN_ACKSTRM, qc);
+                                       qc_check_close_on_released_mux(qc);
+                               }
 
-                       if (qc_stream_desc_done(stream)) {
-                               /* no need to continue if stream freed. */
-                               TRACE_DEVEL("stream released and freed", QUIC_EV_CONN_ACKSTRM, qc);
-                               qc_check_close_on_released_mux(qc);
+                               qc_release_frm(qc, frm);
+                       }
+                       else if (ack > 0) {
+                               TRACE_DEVEL("handled out-of-order stream ACK",
+                                           QUIC_EV_CONN_ACKSTRM, qc, strm_frm, stream);
+                               qc_release_frm(qc, frm);
+                       }
+                       else {
+                               /* Fatal error during qc_stream_desc_ack(). */
+                               goto leave;
                        }
-
-                       qc_release_frm(qc, frm);
-               }
-               else {
-                       TRACE_DEVEL("handled out-of-order stream ACK", QUIC_EV_CONN_ACKSTRM,
-                                   qc, strm_frm, stream);
                }
        }
        break;
@@ -255,8 +269,10 @@ static void qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *f
                qc_release_frm(qc, frm);
        }
 
+       ret = 1;
  leave:
        TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
+       return ret;
 }
 
 /* Collect newly acknowledged TX packets from <pkts> ebtree into <newly_acked_pkts>
@@ -293,11 +309,15 @@ static void qc_newly_acked_pkts(struct quic_conn *qc, struct eb_root *pkts,
        TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
 }
 
-/* Handle <newly_acked_pkts> list of newly acknowledged TX packets */
-static void qc_handle_newly_acked_pkts(struct quic_conn *qc,
-                                       unsigned int *pkt_flags, struct list *newly_acked_pkts)
+/* Handle <newly_acked_pkts> list of newly acknowledged TX packets.
+ *
+ * Returns 1 on sucess else 0.
+ */
+static int qc_handle_newly_acked_pkts(struct quic_conn *qc,
+                                      unsigned int *pkt_flags, struct list *newly_acked_pkts)
 {
        struct quic_tx_packet *pkt, *tmp;
+       int ret = 0;
 
        TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
 
@@ -306,8 +326,10 @@ static void qc_handle_newly_acked_pkts(struct quic_conn *qc,
 
                *pkt_flags |= pkt->flags;
                TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
-               list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
-                       qc_handle_newly_acked_frm(qc, frm);
+               list_for_each_entry_safe(frm, frmbak, &pkt->frms, list) {
+                       if (!qc_handle_newly_acked_frm(qc, frm))
+                               goto leave;
+               }
                /* If there are others packet in the same datagram <pkt> is attached to,
                 * detach the previous one and the next one from <pkt>.
                 */
@@ -315,8 +337,10 @@ static void qc_handle_newly_acked_pkts(struct quic_conn *qc,
                eb64_delete(&pkt->pn_node);
        }
 
+       ret = 1;
  leave:
        TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
+       return ret;
 }
 
 /* Handle all frames sent from <pkt> packet and reinsert them in the same order
@@ -528,7 +552,9 @@ static int qc_parse_ack_frm(struct quic_conn *qc,
        } while (1);
 
        if (!LIST_ISEMPTY(&newly_acked_pkts)) {
-               qc_handle_newly_acked_pkts(qc, &pkt_flags, &newly_acked_pkts);
+               if (!qc_handle_newly_acked_pkts(qc, &pkt_flags, &newly_acked_pkts))
+                       goto leave;
+
                if (new_largest_acked_pn && (pkt_flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
                        *rtt_sample = tick_remain(time_sent, now_ms);
                        qel->pktns->rx.largest_acked_pn = ack_frm->largest_ack;
@@ -583,7 +609,7 @@ static int qc_handle_strm_frm(struct quic_rx_packet *pkt,
        TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
 
        ret = qcc_recv(qc->qcc, strm_frm->id, strm_frm->len,
-                      strm_frm->offset.key, fin, (char *)strm_frm->data);
+                      strm_frm->offset, fin, (char *)strm_frm->data);
 
        /* frame rejected - packet must not be acknowledeged */
        TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
index 896bf1dd152935e7cb98c4191a034b080fce4f46..a97dbebb741f3052007835687776e268600d6cc2 100644 (file)
@@ -9,13 +9,14 @@
 #include <haproxy/mux_quic.h>
 #include <haproxy/pool.h>
 #include <haproxy/quic_conn.h>
-#include <haproxy/quic_frame-t.h>
 #include <haproxy/task.h>
 
 DECLARE_STATIC_POOL(pool_head_quic_stream_desc, "qc_stream_desc",
                     sizeof(struct qc_stream_desc));
 DECLARE_STATIC_POOL(pool_head_quic_stream_buf, "qc_stream_buf",
                     sizeof(struct qc_stream_buf));
+DECLARE_STATIC_POOL(pool_head_quic_stream_ack, "qc_stream_ack",
+                    sizeof(struct qc_stream_ack));
 
 static struct pool_head *pool_head_sbuf;
 
@@ -26,7 +27,7 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream,
        uint64_t room;
 
        /* Caller is responsible to remove buffered ACK frames before destroying a buffer instance. */
-       BUG_ON(!eb_is_empty(&(*stream_buf)->acked_frms));
+       BUG_ON(!eb_is_empty(&(*stream_buf)->ack_tree));
 
        eb64_delete(&(*stream_buf)->offset_node);
 
@@ -174,7 +175,7 @@ static struct qc_stream_buf *qc_stream_buf_ack(struct qc_stream_buf *buf,
                stream->flags &= ~QC_SD_FL_WAIT_FOR_FIN;
        }
 
-       if (!b_data(&buf->buf) && eb_is_empty(&buf->acked_frms)) {
+       if (!b_data(&buf->buf) && eb_is_empty(&buf->ack_tree)) {
                qc_stream_buf_free(stream, &buf);
                /* Retrieve next buffer instance. */
                buf = !eb_is_empty(&stream->buf_tree) ?
@@ -192,33 +193,24 @@ static struct qc_stream_buf *qc_stream_buf_ack(struct qc_stream_buf *buf,
 static void qc_stream_buf_consume(struct qc_stream_buf *stream_buf,
                                   struct qc_stream_desc *stream)
 {
-       struct quic_conn *qc = stream->qc;
-       struct eb64_node *frm_node;
-       struct qf_stream *strm_frm;
-       struct quic_frame *frm;
-       uint64_t offset, len;
-       int fin;
-
-       frm_node = eb64_first(&stream_buf->acked_frms);
-       while (frm_node) {
-               strm_frm = eb64_entry(frm_node, struct qf_stream, offset);
-               frm = container_of(strm_frm, struct quic_frame, stream);
-
-               offset = strm_frm->offset.key;
-               len = strm_frm->len;
-               fin = frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
-
-               if (offset > stream->ack_offset)
+       struct qc_stream_ack *ack;
+       struct eb64_node *ack_node;
+
+       ack_node = eb64_first(&stream_buf->ack_tree);
+       while (ack_node) {
+               ack = eb64_entry(ack_node, struct qc_stream_ack, offset_node);
+               if (ack->offset_node.key > stream->ack_offset)
                        break;
 
-               /* Delete frame before acknowledged it. This prevents BUG_ON()
-                * on non-empty acked_frms tree when stream_buf is empty and removed.
+               /* Delete range before acknowledged it. This prevents BUG_ON()
+                * on non-empty ack_tree tree when stream_buf is empty and removed.
                 */
-               eb64_delete(frm_node);
-               stream_buf = qc_stream_buf_ack(stream_buf, stream, offset, len, fin);
-               qc_release_frm(qc, frm);
+               eb64_delete(ack_node);
+               stream_buf = qc_stream_buf_ack(stream_buf, stream,
+                                              ack->offset_node.key, ack->len, ack->fin);
+               pool_free(pool_head_quic_stream_ack, ack);
 
-               frm_node = stream_buf ? eb64_first(&stream_buf->acked_frms) : NULL;
+               ack_node = stream_buf ? eb64_first(&stream_buf->ack_tree) : NULL;
        }
 }
 
@@ -228,14 +220,11 @@ static void qc_stream_buf_consume(struct qc_stream_buf *stream_buf,
  * Returns 0 if the frame has been handled and can be removed.
  * Returns a positive value if acknowledgement is out-of-order and
  * corresponding STREAM frame has been buffered.
+ * Returns a negative value on fatal error.
  */
-int qc_stream_desc_ack(struct qc_stream_desc *stream, struct quic_frame *frm)
+int qc_stream_desc_ack(struct qc_stream_desc *stream,
+                       uint64_t offset, uint64_t len, int fin)
 {
-       struct qf_stream *strm_frm = &frm->stream;
-       const uint64_t offset = strm_frm->offset.key;
-       const uint64_t len = strm_frm->len;
-       const int fin = frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
-
        struct qc_stream_buf *stream_buf = NULL;
        struct eb64_node *buf_node;
        int ret = 0;
@@ -254,10 +243,21 @@ int qc_stream_desc_ack(struct qc_stream_desc *stream, struct quic_frame *frm)
                stream->flags &= ~QC_SD_FL_WAIT_FOR_FIN;
        }
        else if (offset > stream->ack_offset) {
+               struct qc_stream_ack *ack;
+
                buf_node = eb64_lookup_le(&stream->buf_tree, offset);
                BUG_ON(!buf_node); /* Cannot acknowledged a STREAM frame for a non existing buffer. */
                stream_buf = eb64_entry(buf_node, struct qc_stream_buf, offset_node);
-               eb64_insert(&stream_buf->acked_frms, &strm_frm->offset);
+
+               ack = pool_alloc(pool_head_quic_stream_ack);
+               if (!ack)
+                       return -1;
+
+               ack->offset_node.key = offset;
+               ack->len = len;
+               ack->fin = fin;
+
+               eb64_insert(&stream_buf->ack_tree, &ack->offset_node);
                ret = 1;
        }
        else if (offset + len > stream->ack_offset) {
@@ -283,8 +283,7 @@ int qc_stream_desc_ack(struct qc_stream_desc *stream, struct quic_frame *frm)
 void qc_stream_desc_free(struct qc_stream_desc *stream, int closing)
 {
        struct qc_stream_buf *buf;
-       struct quic_conn *qc = stream->qc;
-       struct eb64_node *frm_node, *buf_node;
+       struct eb64_node *ack_node, *buf_node;
        unsigned int free_count = 0;
 
        /* This function only deals with released streams. */
@@ -302,16 +301,14 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing)
                BUG_ON(b_data(&buf->buf) && !closing);
 
                /* qc_stream_desc might be freed before having received all its ACKs. */
-               while (!eb_is_empty(&buf->acked_frms)) {
-                       struct qf_stream *strm_frm;
-                       struct quic_frame *frm;
+               while (!eb_is_empty(&buf->ack_tree)) {
+                       struct qc_stream_ack *ack;
 
-                       frm_node = eb64_first(&buf->acked_frms);
-                       eb64_delete(frm_node);
+                       ack_node = eb64_first(&buf->ack_tree);
+                       eb64_delete(ack_node);
 
-                       strm_frm = eb64_entry(frm_node, struct qf_stream, offset);
-                       frm = container_of(strm_frm, struct quic_frame, stream);
-                       qc_release_frm(qc, frm);
+                       ack = eb64_entry(ack_node, struct qc_stream_ack, offset_node);
+                       pool_free(pool_head_quic_stream_ack, ack);
                }
 
                if (buf->sbuf)
@@ -358,7 +355,7 @@ struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream,
        if (!stream->buf)
                return NULL;
 
-       stream->buf->acked_frms = EB_ROOT;
+       stream->buf->ack_tree = EB_ROOT;
        stream->buf->buf = BUF_NULL;
        stream->buf->offset_node.key = offset;
 
index 5ddef1d27127db44b6ad6c3ba5e70ae2bb7c3b5c..ae61c2441f4c7919905505388519b0bb1448c3ab 100644 (file)
@@ -412,7 +412,7 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
                        const struct qc_stream_desc *stream = a3;
 
                        if (strm_frm)
-                               chunk_appendf(&trace_buf, " off=%llu len=%llu", (ull)strm_frm->offset.key, (ull)strm_frm->len);
+                               chunk_appendf(&trace_buf, " off=%llu len=%llu", (ull)strm_frm->offset, (ull)strm_frm->len);
                        if (stream)
                                chunk_appendf(&trace_buf, " ack_offset=%llu", (ull)stream->ack_offset);
                }
index e5af014ed16448d680ee1c35af357db8bd6aaeff..001a745e646f49f97e0e4e2db7625d557c2e0e4b 100644 (file)
@@ -1617,7 +1617,7 @@ static int qc_build_frms(struct list *outlist, struct list *inlist,
                         * excepting the variable ones. Note that +1 is for the type of this frame.
                         */
                        hlen = 1 + quic_int_getsize(cf->stream.id) +
-                               ((cf->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ? quic_int_getsize(cf->stream.offset.key) : 0);
+                               ((cf->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ? quic_int_getsize(cf->stream.offset) : 0);
                        /* Compute the data length of this STREAM frame. */
                        avail_room = room - hlen;
                        if ((ssize_t)avail_room <= 0)
@@ -1662,7 +1662,7 @@ static int qc_build_frms(struct list *outlist, struct list *inlist,
                                LIST_APPEND(outlist, &cf->list);
 
                                qc_stream_desc_send(cf->stream.stream,
-                                                   cf->stream.offset.key,
+                                                   cf->stream.offset,
                                                    cf->stream.len);
                        }
                        else {
@@ -1702,11 +1702,11 @@ static int qc_build_frms(struct list *outlist, struct list *inlist,
                                                b_size(cf->stream.buf),
                                                (char *)cf->stream.data - b_orig(cf->stream.buf), 0);
                                cf->stream.len -= dlen;
-                               cf->stream.offset.key += dlen;
+                               cf->stream.offset += dlen;
                                cf->stream.data = (unsigned char *)b_peek(&cf_buf, dlen);
 
                                qc_stream_desc_send(new_cf->stream.stream,
-                                                   new_cf->stream.offset.key,
+                                                   new_cf->stream.offset,
                                                    new_cf->stream.len);
                        }