From: Christopher Faulet Date: Wed, 24 Jan 2024 10:12:05 +0000 (+0100) Subject: MINOR: stconn: Add support for flags during zero-copy forwarding negotiation X-Git-Tag: v3.0-dev3~47 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2297f52734723fab08b5a953ae62c2c64999c9ff;p=thirdparty%2Fhaproxy.git MINOR: stconn: Add support for flags during zero-copy forwarding negotiation During zero-copy forwarding negotiation, a pseudo flag was already used to notify the consummer if the producer is able to use kernel splicing or not. But this was not extensible. So, now we use a true bitfield to be able to pass flags during the negotiation. NEGO_FF_FL_* flags may be used now. Of course, for now, there is only one flags, the kernel splicing support on producer side (NEGO_FF_FL_MAY_SPLICE). --- diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h index 30f468ad7f..223956058d 100644 --- a/include/haproxy/stconn-t.h +++ b/include/haproxy/stconn-t.h @@ -40,6 +40,12 @@ enum iobuf_flags { IOBUF_FL_EOI = 0x00000010, /* A EOI was encountered on producer side */ }; +/* Flags used */ +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 */ +}; + struct iobuf { struct pipe *pipe; /* non-NULL only when data present */ struct buffer *buf; diff --git a/include/haproxy/stconn.h b/include/haproxy/stconn.h index dff604403a..1a6b250937 100644 --- a/include/haproxy/stconn.h +++ b/include/haproxy/stconn.h @@ -502,7 +502,7 @@ static inline void se_need_more_data(struct sedesc *se) } -static inline size_t se_nego_ff(struct sedesc *se, struct buffer *input, size_t count, unsigned int may_splice) +static inline size_t se_nego_ff(struct sedesc *se, struct buffer *input, size_t count, unsigned int flags) { size_t ret = 0; @@ -517,7 +517,7 @@ static inline size_t se_nego_ff(struct sedesc *se, struct buffer *input, size_t goto end; } - ret = mux->nego_fastfwd(se->sc, input, count, may_splice); + ret = mux->nego_fastfwd(se->sc, input, count, flags); if (se->iobuf.flags & IOBUF_FL_FF_BLOCKED) { sc_ep_report_blocked_send(se->sc, 0); diff --git a/src/applet.c b/src/applet.c index abf8611939..ba3af6a5fc 100644 --- a/src/applet.c +++ b/src/applet.c @@ -600,7 +600,7 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) struct appctx *appctx = __sc_appctx(sc); struct xref *peer; struct sedesc *sdo = NULL; - unsigned int len; + unsigned int len, nego_flags = NEGO_FF_FL_NONE; int ret = 0; TRACE_ENTER(APPLET_EV_RECV, appctx); @@ -622,7 +622,7 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) if (appctx->to_forward && count > appctx->to_forward) count = appctx->to_forward; - len = se_nego_ff(sdo, &BUF_NULL, count, 0); + len = se_nego_ff(sdo, &BUF_NULL, count, nego_flags); if (sdo->iobuf.flags & IOBUF_FL_NO_FF) { sc_ep_clr(sc, SE_FL_MAY_FASTFWD); TRACE_DEVEL("Fast-forwarding not supported by opposite endpoint, disable it", APPLET_EV_RECV, appctx); diff --git a/src/mux_h1.c b/src/mux_h1.c index b810ca6251..20f2019dad 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -4433,7 +4433,7 @@ static inline struct sedesc *h1s_opposite_sd(struct h1s *h1s) return sdo; } -static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count, unsigned int may_splice) +static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count, unsigned int flags) { struct h1s *h1s = __sc_mux_strm(sc); struct h1c *h1c = h1s->h1c; @@ -4471,7 +4471,7 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count, * and then data in pipe, or the opposite. For now, it is not * supported to mix data. */ - if (!b_data(input) && !b_data(&h1c->obuf) && may_splice) { + if (!b_data(input) && !b_data(&h1c->obuf) && (flags & NEGO_FF_FL_MAY_SPLICE)) { #if defined(USE_LINUX_SPLICE) if (h1c->conn->xprt->snd_pipe && (h1s->sd->iobuf.pipe || (pipes_used < global.maxpipes && (h1s->sd->iobuf.pipe = get_pipe())))) { h1s->sd->iobuf.offset = 0; @@ -4608,6 +4608,7 @@ static int h1_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) struct h1m *h1m = (!(h1c->flags & H1C_F_IS_BACK) ? &h1s->req : &h1s->res); struct sedesc *sdo = NULL; size_t total = 0, try = 0; + unsigned int nego_flags = NEGO_FF_FL_NONE; int ret = 0; TRACE_ENTER(H1_EV_STRM_RECV, h1c->conn, h1s, 0, (size_t[]){count}); @@ -4645,7 +4646,10 @@ static int h1_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) if (h1m->state == H1_MSG_DATA && (h1m->flags & (H1_MF_CHNK|H1_MF_CLEN)) && count > h1m->curr_len) count = h1m->curr_len; - try = se_nego_ff(sdo, &h1c->ibuf, count, h1c->conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)); + 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; + + try = se_nego_ff(sdo, &h1c->ibuf, count, nego_flags); if (b_room(&h1c->ibuf) && (h1c->flags & H1C_F_IN_FULL)) { h1c->flags &= ~H1C_F_IN_FULL; TRACE_STATE("h1c ibuf not full anymore", H1_EV_STRM_RECV|H1_EV_H1C_BLK); diff --git a/src/mux_h2.c b/src/mux_h2.c index bb1cbb87ed..b436209b5e 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -7083,7 +7083,7 @@ static size_t h2_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, in return total; } -static size_t h2_nego_ff(struct stconn *sc, struct buffer *input, size_t count, unsigned int may_splice) +static size_t h2_nego_ff(struct stconn *sc, struct buffer *input, size_t count, unsigned int flags) { struct h2s *h2s = __sc_mux_strm(sc); struct h2c *h2c = h2s->h2c; diff --git a/src/mux_pt.c b/src/mux_pt.c index 32842861e8..61e396b43f 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -580,7 +580,7 @@ static inline struct sedesc *mux_pt_opposite_sd(struct mux_pt_ctx *ctx) return sdo; } -static size_t mux_pt_nego_ff(struct stconn *sc, struct buffer *input, size_t count, unsigned int may_splice) +static size_t mux_pt_nego_ff(struct stconn *sc, struct buffer *input, size_t count, unsigned int flags) { struct connection *conn = __sc_conn(sc); struct mux_pt_ctx *ctx = conn->ctx; @@ -595,7 +595,7 @@ static size_t mux_pt_nego_ff(struct stconn *sc, struct buffer *input, size_t cou * and then data in pipe, or the opposite. For now, it is not * supported to mix data. */ - if (!b_data(input) && may_splice) { + if (!b_data(input) && (flags & NEGO_FF_FL_MAY_SPLICE)) { if (conn->xprt->snd_pipe && (ctx->sd->iobuf.pipe || (pipes_used < global.maxpipes && (ctx->sd->iobuf.pipe = get_pipe())))) { ctx->sd->iobuf.offset = 0; ctx->sd->iobuf.data = 0; @@ -651,6 +651,7 @@ static int mux_pt_fastfwd(struct stconn *sc, unsigned int count, unsigned int fl struct mux_pt_ctx *ctx = conn->ctx; struct sedesc *sdo = NULL; size_t total = 0, try = 0; + unsigned int nego_flags = NEGO_FF_FL_NONE; int ret = 0; TRACE_ENTER(PT_EV_RX_DATA, conn, sc, 0, (size_t[]){count}); @@ -668,7 +669,10 @@ static int mux_pt_fastfwd(struct stconn *sc, unsigned int count, unsigned int fl goto out; } - try = se_nego_ff(sdo, &BUF_NULL, count, conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)); + if (conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)) + nego_flags |= NEGO_FF_FL_MAY_SPLICE; + + try = se_nego_ff(sdo, &BUF_NULL, count, nego_flags); if (sdo->iobuf.flags & IOBUF_FL_NO_FF) { /* Fast forwarding is not supported by the consumer */ se_fl_clr(ctx->sd, SE_FL_MAY_FASTFWD); diff --git a/src/mux_quic.c b/src/mux_quic.c index 939d5c0dae..041a6853b4 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -2922,7 +2922,7 @@ static size_t qmux_strm_snd_buf(struct stconn *sc, struct buffer *buf, static size_t qmux_strm_nego_ff(struct stconn *sc, struct buffer *input, - size_t count, unsigned int may_splice) + size_t count, unsigned int flags) { struct qcs *qcs = __sc_mux_strm(sc); size_t ret = 0;