diff --git a/include/haproxy/quic_stream-t.h b/include/haproxy/quic_stream-t.h index 78ec8b562..a3dd550c1 100644 --- a/include/haproxy/quic_stream-t.h +++ b/include/haproxy/quic_stream-t.h @@ -15,8 +15,8 @@ * can be freed in strict order. */ struct qc_stream_buf { + struct eb64_node offset_node; /* node for qc_stream_desc buf tree */ struct buffer buf; /* STREAM payload */ - struct list list; /* element for qc_stream_desc list */ int sbuf; }; @@ -36,11 +36,11 @@ struct qc_stream_desc { struct eb64_node by_id; /* node for quic_conn tree */ struct quic_conn *qc; - struct list buf_list; /* buffers waiting for ACK, oldest offset first */ struct qc_stream_buf *buf; /* current buffer used by the MUX */ uint64_t buf_offset; /* base offset of current buffer */ uint64_t ack_offset; /* last acknowledged offset */ + struct eb_root buf_tree; /* list of active and released buffers */ struct eb_root acked_frms; /* ACK frames tree for non-contiguous ACK ranges */ int flags; /* QC_SD_FL_* values */ diff --git a/include/haproxy/quic_stream.h b/include/haproxy/quic_stream.h index cf06abb4d..b6ff47039 100644 --- a/include/haproxy/quic_stream.h +++ b/include/haproxy/quic_stream.h @@ -25,7 +25,7 @@ void qc_stream_buf_release(struct qc_stream_desc *stream); static inline int qc_stream_desc_done(const struct qc_stream_desc *s) { return (s->flags & (QC_SD_FL_RELEASE|QC_SD_FL_WAIT_FOR_FIN)) == QC_SD_FL_RELEASE && - LIST_ISEMPTY(&s->buf_list); + eb_is_empty(&s->buf_tree); } /* Reports emission of STREAM frame starting at and of length , diff --git a/src/mux_quic.c b/src/mux_quic.c index ed951c3d3..09f883349 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -849,7 +849,7 @@ void qcs_send_metadata(struct qcs *qcs) /* Reserved for stream with Tx capability. */ BUG_ON(!qcs->stream); /* Cannot use if some data already transferred for this stream. */ - BUG_ON(qcs->stream->ack_offset || !LIST_ISEMPTY(&qcs->stream->buf_list)); + BUG_ON(qcs->stream->ack_offset || !eb_is_empty(&qcs->stream->buf_tree)); qcs->flags |= QC_SF_TXBUB_OOB; qc_stream_desc_sub_room(qcs->stream, NULL); diff --git a/src/quic_stream.c b/src/quic_stream.c index 7d54fab43..8f189a538 100644 --- a/src/quic_stream.c +++ b/src/quic_stream.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -25,7 +24,7 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream, struct buffer *buf = &(*stream_buf)->buf; uint64_t free_size; - LIST_DEL_INIT(&(*stream_buf)->list); + eb64_delete(&(*stream_buf)->offset_node); /* Reset current buf ptr if deleted instance is the same one. */ if (*stream_buf == stream->buf) @@ -73,7 +72,7 @@ struct qc_stream_desc *qc_stream_desc_new(uint64_t id, enum qcs_type type, void stream->qc = qc; stream->buf = NULL; - LIST_INIT(&stream->buf_list); + stream->buf_tree = EB_ROOT_UNIQUE; stream->buf_offset = 0; stream->acked_frms = EB_ROOT; @@ -156,10 +155,10 @@ int qc_stream_desc_ack(struct qc_stream_desc *stream, size_t offset, size_t len, diff = offset + len - stream->ack_offset; if (diff) { /* Buf list cannot be empty if there is still unacked data. */ - BUG_ON(LIST_ISEMPTY(&stream->buf_list)); + BUG_ON(eb_is_empty(&stream->buf_tree)); - /* get oldest buffer from buf_list */ - stream_buf = LIST_NEXT(&stream->buf_list, struct qc_stream_buf *, list); + /* get oldest buffer from buf tree */ + stream_buf = eb64_entry(eb64_first(&stream->buf_tree), struct qc_stream_buf, offset_node); buf = &stream_buf->buf; stream->ack_offset += diff; @@ -186,16 +185,18 @@ int qc_stream_desc_ack(struct qc_stream_desc *stream, size_t offset, size_t len, */ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing) { - struct qc_stream_buf *buf, *buf_back; + struct qc_stream_buf *buf; struct quic_conn *qc = stream->qc; - struct eb64_node *frm_node; + struct eb64_node *frm_node, *buf_node; unsigned int free_count = 0; /* This function only deals with released streams. */ BUG_ON(!(stream->flags & QC_SD_FL_RELEASE)); /* free remaining stream buffers */ - list_for_each_entry_safe(buf, buf_back, &stream->buf_list, list) { + while (!eb_is_empty(&stream->buf_tree)) { + buf_node = eb64_first(&stream->buf_tree); + buf = eb64_entry(buf_node, struct qc_stream_buf, offset_node); /* qc_stream_desc_free() can only be used after all data is * acknowledged or on connection shutdown. In the contrary @@ -208,7 +209,7 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing) else b_free(&buf->buf); - LIST_DELETE(&buf->list); + eb64_delete(&buf->offset_node); pool_free(pool_head_quic_stream_buf, buf); ++free_count; } @@ -265,6 +266,7 @@ struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream, return NULL; stream->buf->buf = BUF_NULL; + stream->buf->offset_node.key = offset; if (!small) { stream->buf->sbuf = 0; @@ -287,7 +289,7 @@ struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream, stream->buf->buf = b_make(area, global.tune.bufsize_small, 0, 0); } - LIST_APPEND(&stream->buf_list, &stream->buf->list); + eb64_insert(&stream->buf_tree, &stream->buf->offset_node); return &stream->buf->buf; } @@ -311,7 +313,7 @@ struct buffer *qc_stream_buf_realloc(struct qc_stream_desc *stream) stream->buf->sbuf = 0; if (!b_alloc(&stream->buf->buf, DB_MUX_TX)) { - LIST_DEL_INIT(&stream->buf->list); + eb64_delete(&stream->buf->offset_node); pool_free(pool_head_quic_stream_buf, stream->buf); stream->buf = NULL; return NULL;