Skip to content

Commit 96aef29

Browse files
capflama-denoyelle
authored andcommitted
BUG/MEDIUM: mux-quic: Don't unblock zero-copy fwding if blocked during nego
The previous fix (792a645 ["BUG/MEDIUM: mux-quic: Unblock zero-copy forwarding if the txbuf can be released"]) introduced a regression. The zero-copy data forwarding must only be unblocked if it was blocked by the producer, after a successful negotiation. It is important because during a negotiation, the consumer may be blocked for another reason. Because of the flow control for instance. In that case, there is not necessarily a TX buffer. And it unexpected to try to release an unallocated TX buf. In addition, the same may happen while a TX buf is still in-use. In that case, it must also not be released. So testing the TX buffer is not the right solution. To fix the issue, a new IOBUF flag was added (IOBUF_FL_FF_WANT_ROOM). It must be set by the producer if it is blocked after a sucessful negotiation because it needs more room. In that case, we know a buffer was provided by the consummer. In done_fastfwd() callback function, it is then possible to safely unblock the zero-copy data forwarding if this flag is set. This patch must be backported to 3.0 with the commit above. (cherry picked from commit 9748df2) Signed-off-by: Amaury Denoyelle <[email protected]>
1 parent f2384ec commit 96aef29

File tree

4 files changed

+9
-7
lines changed

4 files changed

+9
-7
lines changed

include/haproxy/stconn-t.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum iobuf_flags {
3939
* .done_fastfwd() on consumer side must take care of this flag
4040
*/
4141
IOBUF_FL_EOI = 0x00000010, /* A EOI was encountered on producer side */
42+
IOBUF_FL_FF_WANT_ROOM = 0x00000020, /* Producer need more room in the IOBUF to forward data */
4243
};
4344

4445
/* Flags used */

include/haproxy/stconn.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ static inline size_t se_nego_ff(struct sedesc *se, struct buffer *input, size_t
474474
if (se_fl_test(se, SE_FL_T_MUX)) {
475475
const struct mux_ops *mux = se->conn->mux;
476476

477-
se->iobuf.flags &= ~IOBUF_FL_FF_BLOCKED;
477+
se->iobuf.flags &= ~(IOBUF_FL_FF_BLOCKED|IOBUF_FL_FF_WANT_ROOM);
478478
if (mux->nego_fastfwd && mux->done_fastfwd) {
479479
/* Disable zero-copy forwarding if EOS or an error was reported. */
480480
if (se_fl_test(se, SE_FL_EOS|SE_FL_ERROR|SE_FL_ERR_PENDING)) {

src/applet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags)
694694

695695
if (se_fl_test(appctx->sedesc, SE_FL_WANT_ROOM)) {
696696
/* The applet request more room, report the info at the iobuf level */
697-
sdo->iobuf.flags |= IOBUF_FL_FF_BLOCKED;
697+
sdo->iobuf.flags |= (IOBUF_FL_FF_BLOCKED|IOBUF_FL_FF_WANT_ROOM);
698698
TRACE_STATE("waiting for more room", APPLET_EV_RECV|APPLET_EV_BLK, appctx);
699699
}
700700

@@ -716,7 +716,7 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags)
716716
/* else */
717717
/* applet_have_more_data(appctx); */
718718

719-
if (se_done_ff(sdo) != 0 || !(sdo->iobuf.flags & IOBUF_FL_FF_BLOCKED)) {
719+
if (se_done_ff(sdo) != 0 || !(sdo->iobuf.flags & (IOBUF_FL_FF_BLOCKED|IOBUF_FL_FF_WANT_ROOM))) {
720720
/* Something was forwarding or the consumer states it is not
721721
* blocked anyore, don't reclaim more room */
722722
se_fl_clr(appctx->sedesc, SE_FL_WANT_ROOM);

src/mux_quic.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,11 +3049,12 @@ static size_t qmux_strm_done_ff(struct stconn *sc)
30493049
if (!(qcs->flags & QC_SF_FIN_STREAM) && !sd->iobuf.data) {
30503050
TRACE_STATE("no data sent", QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
30513051

3052-
/* There is nothing to forward and the SD is blocked. Try to
3053-
* release the TXBUF to retry.
3052+
/* There is nothing to forward and the SD was blocked after a
3053+
* successful nego by the producer. We can try to release the
3054+
* TXBUF to retry. In this case, the TX buf MUST exist.
30543055
*/
3055-
if ((qcs->sd->iobuf.flags & IOBUF_FL_FF_BLOCKED) && !qcc_release_stream_txbuf(qcs))
3056-
qcs->sd->iobuf.flags &= ~IOBUF_FL_FF_BLOCKED;
3056+
if ((qcs->sd->iobuf.flags & IOBUF_FL_FF_WANT_ROOM) && !qcc_release_stream_txbuf(qcs))
3057+
qcs->sd->iobuf.flags &= ~(IOBUF_FL_FF_BLOCKED|IOBUF_FL_FF_WANT_ROOM);
30573058
goto end;
30583059
}
30593060

0 commit comments

Comments
 (0)