]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: support sbuf allocation in quic_stream
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 13 Jun 2024 13:26:51 +0000 (15:26 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 20 Aug 2024 16:12:27 +0000 (18:12 +0200)
This patch extends qc_stream_desc API to be able to allocate small
buffers. QUIC MUX API is similarly updated as ultimatly each application
protocol is responsible to choose between a default or a smaller buffer.

Internally, the type of allocated buffer is remembered via qc_stream_buf
instance. This is mandatory to ensure that the buffer is released in the
correct pool, in particular as small and standard buffers can be
configured with the same size.

This commit is purely an API change. For the moment, small buffers are
not used. This will changed in a dedicated patch.

include/haproxy/mux_quic.h
include/haproxy/quic_stream-t.h
include/haproxy/quic_stream.h
src/h3.c
src/hq_interop.c
src/mux_quic.c
src/quic_stream.c

index a9e571bf022df78a9d6a6814342fd27c4e580f0c..83f54f50748fc550016899cf581285a9e7745207 100644 (file)
@@ -26,7 +26,7 @@ void qcs_notify_send(struct qcs *qcs);
 void qcc_notify_buf(struct qcc *qcc, uint64_t free_size);
 
 struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs);
-struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err);
+struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err, int small);
 int qcc_realign_stream_txbuf(const struct qcs *qcs, struct buffer *out);
 int qcc_release_stream_txbuf(struct qcs *qcs);
 int qcc_stream_can_send(const struct qcs *qcs);
index 649316e3497807187ccd684a7cda482b570a3211..1a5cf47dfde5d6c447e31b824883b9710e9450d9 100644 (file)
@@ -17,6 +17,7 @@
 struct qc_stream_buf {
        struct buffer buf; /* STREAM payload */
        struct list list; /* element for qc_stream_desc list */
+       int sbuf;
 };
 
 #define QC_SD_FL_RELEASE       0x00000001 /* set when MUX has finished to use this stream */
index c7a237969571e59dafe5d86b2ccee902112c2c1b..4417ee2c92256ad99fce71dda76b88b2788844d0 100644 (file)
@@ -16,7 +16,7 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing);
 
 struct buffer *qc_stream_buf_get(struct qc_stream_desc *stream);
 struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream,
-                                   uint64_t offset);
+                                   uint64_t offset, int small);
 void qc_stream_buf_release(struct qc_stream_desc *stream);
 
 #endif /* USE_QUIC */
index f19b99ba35785166758050ec9a0491f9a0d9ac85..794c30ff848af551ea289c742f26277d6ad2d963 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1524,7 +1524,7 @@ static int h3_control_send(struct qcs *qcs, void *ctx)
                goto err;
        }
 
-       if (!(res = qcc_get_stream_txbuf(qcs, &err))) {
+       if (!(res = qcc_get_stream_txbuf(qcs, &err, 0))) {
                /* Only memory failure can cause buf alloc error for control stream due to qcs_send_metadata() usage. */
                TRACE_ERROR("cannot allocate Tx buffer", H3_EV_TX_FRAME|H3_EV_TX_SETTINGS, qcs->qcc->conn, qcs);
                goto err;
@@ -1606,7 +1606,7 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
 
        list[hdr].n = ist("");
 
-       if (!(res = qcc_get_stream_txbuf(qcs, &err))) {
+       if (!(res = qcc_get_stream_txbuf(qcs, &err, 0))) {
                if (err) {
                        TRACE_ERROR("cannot allocate Tx buffer", H3_EV_TX_FRAME|H3_EV_TX_HDR, qcs->qcc->conn, qcs);
                        goto err;
@@ -1764,7 +1764,7 @@ static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
        list[hdr].n = ist("");
 
  start:
-       if (!(res = qcc_get_stream_txbuf(qcs, &err))) {
+       if (!(res = qcc_get_stream_txbuf(qcs, &err, 0))) {
                if (err) {
                        TRACE_ERROR("cannot allocate Tx buffer", H3_EV_TX_FRAME|H3_EV_TX_HDR, qcs->qcc->conn, qcs);
                        goto err;
@@ -1898,7 +1898,7 @@ static int h3_resp_data_send(struct qcs *qcs, struct htx *htx,
        if (type != HTX_BLK_DATA)
                goto end;
 
-       if (!(res = qcc_get_stream_txbuf(qcs, &err))) {
+       if (!(res = qcc_get_stream_txbuf(qcs, &err, 0))) {
                if (err) {
                        TRACE_ERROR("cannot allocate Tx buffer", H3_EV_TX_FRAME|H3_EV_TX_DATA, qcs->qcc->conn, qcs);
                        goto err;
@@ -2109,7 +2109,7 @@ static size_t h3_nego_ff(struct qcs *qcs, size_t count)
        TRACE_ENTER(H3_EV_STRM_SEND, qcs->qcc->conn, qcs);
 
  start:
-       if (!(res = qcc_get_stream_txbuf(qcs, &err))) {
+       if (!(res = qcc_get_stream_txbuf(qcs, &err, 0))) {
                if (err) {
                        qcs->sd->iobuf.flags |= IOBUF_FL_NO_FF;
                        goto end;
@@ -2319,7 +2319,7 @@ static int h3_send_goaway(struct h3c *h3c)
        b_quic_enc_int(&pos, frm_len, 0);
        b_quic_enc_int(&pos, h3c->id_goaway, 0);
 
-       res = qcc_get_stream_txbuf(qcs, &err);
+       res = qcc_get_stream_txbuf(qcs, &err, 0);
        if (!res || b_room(res) < b_data(&pos) ||
            qfctl_sblocked(&qcs->tx.fc) || qfctl_sblocked(&h3c->qcc->tx.fc)) {
                /* Do not try forcefully to emit GOAWAY if no buffer available or not enough space left. */
index c88f888be8003fd3139ac774cb07851380321a05..d0c6b43c2df364ee4fe703dd8c430494b265f118 100644 (file)
@@ -110,7 +110,7 @@ static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
 
                switch (btype) {
                case HTX_BLK_DATA:
-                       res = qcc_get_stream_txbuf(qcs, &err);
+                       res = qcc_get_stream_txbuf(qcs, &err, 0);
                        if (!res) {
                                if (err)
                                        ABORT_NOW();
@@ -185,7 +185,7 @@ static size_t hq_interop_nego_ff(struct qcs *qcs, size_t count)
        struct buffer *res;
 
  start:
-       res = qcc_get_stream_txbuf(qcs, &err);
+       res = qcc_get_stream_txbuf(qcs, &err, 0);
        if (!res) {
                if (err)
                        ABORT_NOW();
index 66d2b59d88a836d5c2423bd76438cd49bb206b02..7b25bba6c555f5700d867b96ec6e6ab79e7307cb 100644 (file)
@@ -1037,7 +1037,7 @@ struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs)
  * Returns buffer pointer. May be NULL on allocation failure, in which case
  * <err> will refer to the cause.
  */
-struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err)
+struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err, int small)
 {
        struct qcc *qcc = qcs->qcc;
        struct buffer *out = qc_stream_buf_get(qcs->stream);
@@ -1065,7 +1065,7 @@ struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err)
                        }
                }
 
-               out = qc_stream_buf_alloc(qcs->stream, qcs->tx.fc.off_real);
+               out = qc_stream_buf_alloc(qcs->stream, qcs->tx.fc.off_real, small);
                if (!out) {
                        TRACE_ERROR("stream desc alloc failure", QMUX_EV_QCS_SEND, qcc->conn, qcs);
                        *err = 1;
@@ -1073,7 +1073,7 @@ struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err)
                }
 
                if (likely(!unlimited))
-                       qcc->tx.buf_in_flight += global.tune.bufsize;
+                       qcc->tx.buf_in_flight += b_size(out);
        }
 
  out:
index b0ad776ff2d3c27f056f41a6b7e869f7fb5d3e3f..5f1f1f4c532a4070625492558484a18435693866 100644 (file)
@@ -39,8 +39,13 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream,
                stream->buf = NULL;
 
        free_size = b_size(buf);
-       b_free(buf);
-       offer_buffers(NULL, 1);
+       if ((*stream_buf)->sbuf) {
+               pool_free(pool_head_sbuf, buf->area);
+       }
+       else {
+               b_free(buf);
+               offer_buffers(NULL, 1);
+       }
        pool_free(pool_head_quic_stream_buf, *stream_buf);
        *stream_buf = NULL;
 
@@ -213,7 +218,10 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing)
        list_for_each_entry_safe(buf, buf_back, &stream->buf_list, list) {
                if (!(b_data(&buf->buf)) || closing) {
                        free_size += b_size(&buf->buf);
-                       b_free(&buf->buf);
+                       if (buf->sbuf)
+                               pool_free(pool_head_sbuf, buf->buf.area);
+                       else
+                               b_free(&buf->buf);
                        LIST_DELETE(&buf->list);
                        pool_free(pool_head_quic_stream_buf, buf);
                        ++free_count;
@@ -269,7 +277,7 @@ struct buffer *qc_stream_buf_get(struct qc_stream_desc *stream)
  * Returns the buffer or NULL on error.
  */
 struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream,
-                                   uint64_t offset)
+                                   uint64_t offset, int small)
 {
        /* current buffer must be released first before allocate a new one. */
        BUG_ON(stream->buf);
@@ -280,10 +288,26 @@ struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream,
                return NULL;
 
        stream->buf->buf = BUF_NULL;
-       if (!b_alloc(&stream->buf->buf, DB_MUX_TX)) {
-               pool_free(pool_head_quic_stream_buf, stream->buf);
-               stream->buf = NULL;
-               return NULL;
+
+       if (!small) {
+               stream->buf->sbuf = 0;
+               if (!b_alloc(&stream->buf->buf, DB_MUX_TX)) {
+                       pool_free(pool_head_quic_stream_buf, stream->buf);
+                       stream->buf = NULL;
+                       return NULL;
+               }
+       }
+       else {
+               char *area;
+
+               if (!(area = pool_alloc(pool_head_sbuf))) {
+                       pool_free(pool_head_quic_stream_buf, stream->buf);
+                       stream->buf = NULL;
+                       return NULL;
+               }
+
+               stream->buf->sbuf = 1;
+               stream->buf->buf = b_make(area, global.tune.bufsize_small, 0, 0);
        }
 
        LIST_APPEND(&stream->buf_list, &stream->buf->list);