From: Christopher Faulet Date: Thu, 25 Jan 2024 13:52:08 +0000 (+0100) Subject: MEDIUM: stconn: Nofify requested size during zero-copy forwarding nego is exact X-Git-Tag: v3.0-dev3~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c18d32a0dc76f16815c84a80e17e262a9e66bea;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h index 223956058d..f55472398e 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 ba3af6a5fc..7b302f9768 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 0db232934f..a08d08520f 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;