]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: realign Tx buffer if possible
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 17 Jan 2024 15:01:00 +0000 (16:01 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 31 Jan 2024 15:28:54 +0000 (16:28 +0100)
A major reorganization of QUIC MUX sending has been implemented. Now
data transfer occur over a single QCS buffer. This has improve
performance but at the cost of restrictions on snd_buf. Indeed, buffer
instances are now shared from stream callback snd_buf up to quic-conn
layer.

As such, snd_buf cannot manipulate freely already present data buffer.
In particular, realign has been completely removed by the previous
patches.

This commit reintroduces a partial realign support. This is only done if
the buffer contains only unsent data, via a new MUX function
qcc_realign_stream_txbuf() which is called during snd_buf.

include/haproxy/mux_quic.h
src/h3.c
src/mux_quic.c

index e2437c351e60d689f1d8d2c45465a6e09e030f3b..da686c1bb4788c74f7ffc60c458c94f1d03f0323 100644 (file)
@@ -25,6 +25,7 @@ int qcc_notify_buf(struct qcc *qcc);
 
 struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs);
 struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err);
+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);
 void qcc_reset_stream(struct qcs *qcs, int err);
index 69bbd8e27ee6ddd552e3976ba35456b9f6806d11..01ef2502eee1c97cf39b952d261c99d966e09d0a 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1900,8 +1900,14 @@ static int h3_resp_data_send(struct qcs *qcs, struct htx *htx,
        if (fsize > count)
                fsize = count;
 
-       /* TODO buffer can be realign only if no data waiting for ACK. */
-       outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
+       while (1) {
+               b_reset(&outbuf);
+               outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
+               if (b_size(&outbuf) > hsize || !b_space_wraps(res))
+                       break;
+               if (qcc_realign_stream_txbuf(qcs, res))
+                       break;
+       }
 
        /* Not enough room for headers and at least one data byte, try to
         * release the current buffer and allocate a new one. If not possible,
@@ -2082,7 +2088,12 @@ static size_t h3_nego_ff(struct qcs *qcs, size_t count)
 
        /* h3 DATA headers : 1-byte frame type + varint frame length */
        hsize = 1 + QUIC_VARINT_MAX_SIZE;
-       /* TODO buffer can be realign only if no data waiting for ACK. */
+       while (1) {
+               if (b_contig_space(res) >= hsize || !b_space_wraps(res))
+                       break;
+               if (qcc_realign_stream_txbuf(qcs, res))
+                       break;
+       }
 
        /* Not enough room for headers and at least one data byte, block the
         * stream. It is expected that the stream connector layer will subscribe
index 9df45b491fef30c565c59694b1d41bace6c1f82c..939d5c0dae16116089e75215a0fe1be56e482a50 100644 (file)
@@ -1019,6 +1019,21 @@ static uint64_t qcs_prep_bytes(const struct qcs *qcs)
        return b_data(out) - diff;
 }
 
+/* Try to realign <out> buffer for <qcs> stream. This is done only if there is
+ * no data waiting for ACK.
+ *
+ * Returns 0 if realign was performed else non-zero.
+ */
+int qcc_realign_stream_txbuf(const struct qcs *qcs, struct buffer *out)
+{
+       if (qcs_prep_bytes(qcs) == b_data(out)) {
+               b_slow_realign(out, trash.area, b_data(out));
+               return 0;
+       }
+
+       return 1;
+}
+
 /* Release the current <qcs> Tx buffer. This is useful if space left is not
  * enough anymore. A new instance can then be allocated to continue sending.
  *