]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h2: force reads to be HTX-aligned in HTX mode
authorWilly Tarreau <w@1wt.eu>
Wed, 12 Dec 2018 07:23:47 +0000 (08:23 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 12 Dec 2018 10:52:45 +0000 (11:52 +0100)
H2 has a 9-byte frame header, and HTX has a 40-byte frame header.
By artificially advancing the Rx header and limiting the amount of
bytes read to protect the end of the buffer, we can make the data
payload perfectly aligned with HTX blocks and optimize the copy.

src/mux_h2.c

index eeaa0c1e0eb3aff8aeafb51d8fbee3b4aa71b69f..806c817bd3ed6f7d93fd443266b055ff40175b7e 100644 (file)
@@ -2442,11 +2442,34 @@ static int h2_recv(struct h2c *h2c)
        }
 
        do {
-               max = buf->size - b_data(buf);
+               int aligned = 0;
+
+               if (!b_data(buf) && (h2c->proxy->options2 & PR_O2_USE_HTX)) {
+                       /* HTX in use : try to pre-align the buffer like the
+                        * rxbufs will be to optimize memory copies. We'll make
+                        * sure that the frame header lands at the end of the
+                        * HTX block to alias it upon recv. We cannot use the
+                        * head because rcv_buf() will realign the buffer if
+                        * it's empty. Thus we cheat and pretend we already
+                        * have a few bytes there.
+                        */
+                       max = buf_room_for_htx_data(buf) + 9;
+                       buf->head = 0;
+                       buf->data = sizeof(struct htx) - 9;
+                       aligned = 1;
+               }
+               else
+                       max = b_room(buf);
+
                if (max)
                        ret = conn->xprt->rcv_buf(conn, buf, max, 0);
                else
                        ret = 0;
+
+               if (aligned) {
+                       buf->data -= sizeof(struct htx) - 9;
+                       buf->head  = sizeof(struct htx) - 9;
+               }
        } while (ret > 0);
 
        if (h2_recv_allowed(h2c) && (b_data(buf) < buf->size))