diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 3bee5fd43..ce6bf1177 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -274,6 +274,7 @@ enum { CO_RFL_READ_ONCE = 0x0004, /* don't loop even if the request/response is small */ CO_RFL_KEEP_RECV = 0x0008, /* Instruct the mux to still wait for read events */ CO_RFL_BUF_NOT_STUCK = 0x0010, /* Buffer is not stuck. Optims are possible during data copy */ + CO_RFL_MAY_SPLICE = 0x0020, /* The producer can use the kernel splicing */ }; /* flags that can be passed to xprt->snd_buf() and mux->snd_buf() */ @@ -422,6 +423,10 @@ struct mux_ops { int (*wake)(struct connection *conn); /* mux-layer callback to report activity, mandatory */ size_t (*rcv_buf)(struct stconn *sc, struct buffer *buf, size_t count, int flags); /* Called from the upper layer to get data */ size_t (*snd_buf)(struct stconn *sc, struct buffer *buf, size_t count, int flags); /* Called from the upper layer to send data */ + size_t (*init_fastfwd)(struct stconn *sc, struct buffer *input, size_t count, unsigned int may_splice); /* Callback to fill the SD iobuf */ + void (*done_fastfwd)(struct stconn *sc); /* Callback to terminate fast data forwarding */ + int (*fastfwd)(struct stconn *sc, unsigned int count, unsigned int flags); /* Callback to init fast data forwarding */ + int (*resume_fastfwd)(struct stconn *sc, unsigned int flags); /* Callback to resume fast data forwarding */ int (*rcv_pipe)(struct stconn *sc, struct pipe *pipe, unsigned int count); /* recv-to-pipe callback */ int (*snd_pipe)(struct stconn *sc, struct pipe *pipe); /* send-to-pipe callback */ void (*shutr)(struct stconn *sc, enum co_shr_mode); /* shutr function */ diff --git a/include/haproxy/stconn.h b/include/haproxy/stconn.h index 12ac81b21..71338ada1 100644 --- a/include/haproxy/stconn.h +++ b/include/haproxy/stconn.h @@ -132,6 +132,40 @@ static inline size_t se_ff_data(struct sedesc *se) return (se->iobuf.data + (se->iobuf.pipe ? se->iobuf.pipe->data : 0)); } +static inline size_t se_init_ff(struct sedesc *se, struct buffer *input, size_t count, unsigned int may_splice) +{ + size_t ret = 0; + + if (se_fl_test(se, SE_FL_T_MUX)) { + const struct mux_ops *mux = se->conn->mux; + + se->iobuf.flags &= ~IOBUF_FL_FF_BLOCKED; + if (mux->init_fastfwd && mux->done_fastfwd) { + ret = mux->init_fastfwd(se->sc, input, count, may_splice); + if ((se->iobuf.flags & IOBUF_FL_FF_BLOCKED) && !(se->sc->wait_event.events & SUB_RETRY_SEND)) { + /* The SC must be subs for send to be notify when some + * space is made + */ + mux->subscribe(se->sc, SUB_RETRY_SEND, &se->sc->wait_event); + } + goto end; + } + } + se->iobuf.flags |= IOBUF_FL_NO_FF; + + end: + return ret; +} + +static inline void se_done_ff(struct sedesc *se) +{ + if (se_fl_test(se, SE_FL_T_MUX)) { + const struct mux_ops *mux = se->conn->mux; + + BUG_ON(!mux->done_fastfwd); + mux->done_fastfwd(se->sc); + } +} /* stream connector version */ static forceinline void sc_ep_zero(struct stconn *sc)