]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stconn: Add support for flags during zero-copy forwarding negotiation
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 24 Jan 2024 10:12:05 +0000 (11:12 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 7 Feb 2024 14:04:29 +0000 (15:04 +0100)
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).

include/haproxy/stconn-t.h
include/haproxy/stconn.h
src/applet.c
src/mux_h1.c
src/mux_h2.c
src/mux_pt.c
src/mux_quic.c

index 30f468ad7fd3c0ec5eb74bbb0a67cbbf905ee5e0..223956058d4e3149235dc6f1fa76924283b6f4fd 100644 (file)
@@ -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;
index dff604403a2dd099287c2e15de04f2a41d42f333..1a6b2509379077904fe7d1a7201b4a3dafef06f2 100644 (file)
@@ -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);
 
index abf8611939e1b838d3a293c5608b0366c3a3d053..ba3af6a5fc4fee964127d98a2f07990fb6bfd1a6 100644 (file)
@@ -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);
index b810ca6251bb7573cf1c8fe519e43e657f12ba62..20f2019dadc1ff539272c6dc367c4d0538d63d95 100644 (file)
@@ -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);
index bb1cbb87ed458a7ff17de151900182325d13b9e1..b436209b5e283e3eadff6c5f7a546df0036c4b1c 100644 (file)
@@ -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;
index 32842861e8e1344a0bf4b100a4bc45596561ded5..61e396b43fdfba97074e3a8215a17c47ceb87efb 100644 (file)
@@ -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);
index 939d5c0dae16116089e75215a0fe1be56e482a50..041a6853b4e6319f56da357864fd2126f2a02283 100644 (file)
@@ -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;