]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: adjust zero-copy sending related code
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 8 Dec 2023 14:48:06 +0000 (15:48 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 12 Dec 2023 09:31:22 +0000 (10:31 +0100)
Adjust HTTP/3 data emission. First, add HTX as argument to the function
as this is used for other frames emission function. Keep the buffer
argument as this is mandatory for zero-copy. Extend comments related to
this, in particular to explain purposes of both HTX and buffer
arguments.

No function change here. This should however be useful to port a code
equivalent to hq-interop protocol.

src/h3.c

index eb4936340e8868960ef888cb2b9799c036b1c53d..0616b764ca552269b0d42efbc6f4cc4a14241230 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1737,10 +1737,17 @@ static int h3_resp_trailers_send(struct qcs *qcs, struct htx *htx)
        return 0;
 }
 
-/* Returns the total of bytes sent. */
-static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count)
+/* Convert a series of HTX data blocks from <htx> buffer of size <count> into
+ * HTTP/3 frames encoded into <qcs> Tx buffer. The caller must also specify the
+ * underlying HTX area via <buf> as this will be used if zero-copy can be
+ * performed.
+ *
+ * Returns the total bytes of encoded HTTP/3 payload. This corresponds to the
+ * total bytes of HTX block removed.
+ */
+static int h3_resp_data_send(struct qcs *qcs, struct htx *htx,
+                             struct buffer *buf, size_t count)
 {
-       struct htx *htx;
        struct buffer outbuf;
        struct buffer *res;
        size_t total = 0;
@@ -1750,8 +1757,6 @@ static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count)
 
        TRACE_ENTER(H3_EV_TX_FRAME|H3_EV_TX_DATA, qcs->qcc->conn, qcs);
 
-       htx = htx_from_buf(buf);
-
  new_frame:
        if (!count || htx_is_empty(htx))
                goto end;
@@ -1770,27 +1775,32 @@ static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count)
                /* TODO */
        }
 
+       /* If HTX contains only one DATA block, try to exchange it with MUX
+        * buffer to perform zero-copy. This is only achievable if MUX buffer
+        * is currently empty.
+        */
        if (unlikely(fsize == count &&
-                    !b_data(res) &&
-                    htx_nbblks(htx) == 1 && type == HTX_BLK_DATA)) {
+                    !b_data(res) &&
+                    htx_nbblks(htx) == 1 && type == HTX_BLK_DATA)) {
                void *old_area = res->area;
 
                TRACE_DATA("perform zero-copy DATA transfer",
                           H3_EV_TX_FRAME|H3_EV_TX_DATA, qcs->qcc->conn, qcs);
 
-               /* map an H2 frame to the HTX block so that we can put the
-                * frame header there.
-                */
-               *res = b_make(buf->area, buf->size, sizeof(struct htx) + blk->addr - hsize, fsize + hsize);
-               outbuf = b_make(b_head(res), hsize, 0, 0);
-               b_putchr(&outbuf, 0x00); /* h3 frame type = DATA */
-               b_quic_enc_int(&outbuf, fsize, QUIC_VARINT_MAX_SIZE); /* h3 frame length */
+               /* remap MUX buffer to HTX area, keep an offset for H3 header. */
+               *res = b_make(buf->area, buf->size,
+                             sizeof(struct htx) + blk->addr - hsize, 0);
+
+               /* write H3 header frame before old HTX block. */
+               b_putchr(res, 0x00); /* h3 frame type = DATA */
+               b_quic_enc_int(res, fsize, QUIC_VARINT_MAX_SIZE); /* h3 frame length */
+               b_add(res, fsize);
 
-               /* and exchange with our old area */
+               /* assign old MUX area to HTX buffer. */
                buf->area = old_area;
                buf->data = buf->head = 0;
                total += fsize;
-               fsize = 0;
+
                goto end;
        }
 
@@ -1877,9 +1887,11 @@ static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count)
                        break;
 
                case HTX_BLK_DATA:
-                       ret = h3_resp_data_send(qcs, buf, count);
+                       ret = h3_resp_data_send(qcs, htx, buf, count);
                        if (ret > 0) {
+                               /* Reload HTX. This is necessary if 0-copy was performed. */
                                htx = htx_from_buf(buf);
+
                                total += ret;
                                count -= ret;
                                if (ret < bsize)