From 1c18d32a0dc76f16815c84a80e17e262a9e66bea Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 25 Jan 2024 14:52:08 +0100 Subject: [PATCH] MEDIUM: stconn: Nofify requested size during zero-copy forwarding nego is exact It is now possible to use a flag during zero-copy forwarding negotiation to specify the requested size is exact, it means the producer really expect to receive at least this amount of data. It can be used by consumer to prepare some processing at this stage, based on the requested size. For instance, in the H1 mux, it is used to write the next chunk size. --- include/haproxy/stconn-t.h | 1 + src/applet.c | 4 +++- src/mux_h1.c | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h index 223956058..f55472398 100644 --- a/include/haproxy/stconn-t.h +++ b/include/haproxy/stconn-t.h @@ -44,6 +44,7 @@ enum iobuf_flags { enum nego_ff_flags { NEGO_FF_FL_NONE = 0x00000000, /* For initialization purposes */ NEGO_FF_FL_MAY_SPLICE = 0x00000001, /* Consumer may choose to use kernel splicing if it supports it */ + NEGO_FF_FL_EXACT_SIZE = 0x00000002, /* Size passed for the nego is the expected exact size to forwarded */ }; struct iobuf { diff --git a/src/applet.c b/src/applet.c index ba3af6a5f..7b302f976 100644 --- a/src/applet.c +++ b/src/applet.c @@ -619,8 +619,10 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) sdo = container_of(peer, struct sedesc, xref); xref_unlock(&appctx->sedesc->xref, peer); - if (appctx->to_forward && count > appctx->to_forward) + if (appctx->to_forward && count > appctx->to_forward) { count = appctx->to_forward; + nego_flags |= NEGO_FF_FL_EXACT_SIZE; + } len = se_nego_ff(sdo, &BUF_NULL, count, nego_flags); if (sdo->iobuf.flags & IOBUF_FL_NO_FF) { diff --git a/src/mux_h1.c b/src/mux_h1.c index 0db232934..a08d08520 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -4470,9 +4470,16 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count, } else { BUG_ON(h1m->state != H1_MSG_CHUNK_CRLF && h1m->state != H1_MSG_CHUNK_SIZE); - if (!h1_make_chunk(h1s, h1m, count)) + if (flags & NEGO_FF_FL_EXACT_SIZE) { + if (!h1_make_chunk(h1s, h1m, count)) + goto out; + h1m->curr_len = count; + } + else { + /* XXX: Unsupported for now but will be added soon ! */ + h1s->sd->iobuf.flags |= IOBUF_FL_NO_FF; goto out; - h1m->curr_len = count; + } } } @@ -4655,8 +4662,10 @@ static int h1_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) retry: ret = 0; - if (h1m->state == H1_MSG_DATA && (h1m->flags & (H1_MF_CHNK|H1_MF_CLEN)) && count > h1m->curr_len) + if (h1m->state == H1_MSG_DATA && (h1m->flags & (H1_MF_CHNK|H1_MF_CLEN)) && count > h1m->curr_len) { + flags |= NEGO_FF_FL_EXACT_SIZE; count = h1m->curr_len; + } if (h1c->conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)) nego_flags |= NEGO_FF_FL_MAY_SPLICE;