From: Christopher Faulet Date: Tue, 21 Sep 2021 13:50:55 +0000 (+0200) Subject: MINOR: stream-int: Notify mux when the buffer is not stuck when calling rcv_buf X-Git-Tag: v2.5-dev8~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=564e39c4c602a7ec0196e257732957bbfc3cbcae;p=thirdparty%2Fhaproxy.git MINOR: stream-int: Notify mux when the buffer is not stuck when calling rcv_buf The transient flag CO_RFL_BUF_NOT_STUCK should now be set when the mux's rcv_buf() function is called, in si_cs_recv(), to be sure the mux is able to perform some optimisation during data copy. This flag is set when we are sure the channel buffer is not stuck. Concretely, it happens when there are data scheduled to be sent. It is not a fix and this flag is not used for now. But it makes sense to have this info to be sure to be able to do some optimisations if necessary. This patch is related to the issue #1362. It may be backported to 2.4 to ease future backports. --- diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 28dbbf4b78..ed41cff824 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -276,10 +276,11 @@ enum { /* flags that can be passed to xprt->rcv_buf() and mux->rcv_buf() */ enum { - CO_RFL_BUF_WET = 0x0001, /* Buffer still has some output data present */ - CO_RFL_BUF_FLUSH = 0x0002, /* Flush mux's buffers but don't read more data */ - 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_WET = 0x0001, /* Buffer still has some output data present */ + CO_RFL_BUF_FLUSH = 0x0002, /* Flush mux's buffers but don't read more data */ + 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 */ }; /* flags that can be passed to xprt->snd_buf() and mux->snd_buf() */ diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c index 61142ab5f3..84b3aeb5df 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -3910,7 +3910,18 @@ static int fcgi_unsubscribe(struct conn_stream *cs, int event_type, struct wait_ return 0; } -/* Called from the upper layer, to receive data */ +/* Called from the upper layer, to receive data + * + * The caller is responsible for defragmenting if necessary. But + * must be tested to know the calling context. If CO_RFL_BUF_FLUSH is set, it + * means the caller wants to flush input data (from the mux buffer and the + * channel buffer) to be able to use kernel splicing or any kind of mux-to-mux + * xfer. If CO_RFL_KEEP_RECV is set, the mux must always subscribe for read + * events before giving back. CO_RFL_BUF_WET is set if is congested with + * data scheduled for leaving soon. CO_RFL_BUF_NOT_STUCK is set to instruct the + * mux it may optimize the data copy to if necessary. Otherwise, it should + * copy as much data as possible. + */ static size_t fcgi_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int flags) { struct fcgi_strm *fstrm = cs->ctx; diff --git a/src/mux_h1.c b/src/mux_h1.c index 20127cc8d0..2857545489 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -3337,7 +3337,18 @@ static int h1_subscribe(struct conn_stream *cs, int event_type, struct wait_even return 0; } -/* Called from the upper layer, to receive data */ +/* Called from the upper layer, to receive data. + * + * The caller is responsible for defragmenting if necessary. But + * must be tested to know the calling context. If CO_RFL_BUF_FLUSH is set, it + * means the caller wants to flush input data (from the mux buffer and the + * channel buffer) to be able to use kernel splicing or any kind of mux-to-mux + * xfer. If CO_RFL_KEEP_RECV is set, the mux must always subscribe for read + * events before giving back. CO_RFL_BUF_WET is set if is congested with + * data scheduled for leaving soon. CO_RFL_BUF_NOT_STUCK is set to instruct the + * mux it may optimize the data copy to if necessary. Otherwise, it should + * copy as much data as possible. + */ static size_t h1_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int flags) { struct h1s *h1s = cs->ctx; diff --git a/src/mux_h2.c b/src/mux_h2.c index 45506c65d0..dfe0b37954 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -6255,7 +6255,18 @@ static int h2_unsubscribe(struct conn_stream *cs, int event_type, struct wait_ev } -/* Called from the upper layer, to receive data */ +/* Called from the upper layer, to receive data + * + * The caller is responsible for defragmenting if necessary. But + * must be tested to know the calling context. If CO_RFL_BUF_FLUSH is set, it + * means the caller wants to flush input data (from the mux buffer and the + * channel buffer) to be able to use kernel splicing or any kind of mux-to-mux + * xfer. If CO_RFL_KEEP_RECV is set, the mux must always subscribe for read + * events before giving back. CO_RFL_BUF_WET is set if is congested with + * data scheduled for leaving soon. CO_RFL_BUF_NOT_STUCK is set to instruct the + * mux it may optimize the data copy to if necessary. Otherwise, it should + * copy as much data as possible. + */ static size_t h2_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int flags) { struct h2s *h2s = cs->ctx; diff --git a/src/mux_pt.c b/src/mux_pt.c index 86b86e28ab..713f110781 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -484,6 +484,16 @@ static void mux_pt_shutw(struct conn_stream *cs, enum cs_shw_mode mode) /* * Called from the upper layer, to get more data + * + * The caller is responsible for defragmenting if necessary. But + * must be tested to know the calling context. If CO_RFL_BUF_FLUSH is set, it + * means the caller wants to flush input data (from the mux buffer and the + * channel buffer) to be able to use kernel splicing or any kind of mux-to-mux + * xfer. If CO_RFL_KEEP_RECV is set, the mux must always subscribe for read + * events before giving back. CO_RFL_BUF_WET is set if is congested with + * data scheduled for leaving soon. CO_RFL_BUF_NOT_STUCK is set to instruct the + * mux it may optimize the data copy to if necessary. Otherwise, it should + * copy as much data as possible. */ static size_t mux_pt_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int flags) { diff --git a/src/stream_interface.c b/src/stream_interface.c index a693daa910..988bcfce31 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -1366,8 +1366,9 @@ int si_cs_recv(struct conn_stream *cs) int cur_flags = flags; /* Compute transient CO_RFL_* flags */ - if (co_data(ic)) - cur_flags |= CO_RFL_BUF_WET; + if (co_data(ic)) { + cur_flags |= (CO_RFL_BUF_WET | CO_RFL_BUF_NOT_STUCK); + } /* may be null. This is the mux responsibility to set * CS_FL_RCV_MORE on the CS if more space is needed.