BUG/MEDIUM: applet: Add a flag to state an applet is using zero-copy forwarding

An issue was introduced when zero-copy forwarding was added to the stats and
cache applets. There is no test to be sure the upper layer is ready to use
the zero-copy forwarding. So these applets refuse to deliver the response
into the applet's output buffer if the zero-copy forwarding is supported by
the opposite endpoint. It is especially an issue when a filter, like the
compression, is in-use on the response channel.

Because of this bug, the response is not delivered and the applet is woken
up in loop to produce data.

To fix the issue, an appctx flag was added, APPCTX_FL_FASTFWD, to know when
the zero-copy forwarding is in-use. We rely on this flag to not fill the
outbuf in the applet's I/O handler.

No backport needed.
This commit is contained in:
Christopher Faulet 2024-02-12 22:13:23 +01:00
parent 1465eb570b
commit ece002af1d
4 changed files with 13 additions and 2 deletions

View File

@ -47,6 +47,7 @@
#define APPCTX_FL_SHUTDOWN 0x00000100 /* applet was shut down (->release() called if any). No more data exchange with SCs */
#define APPCTX_FL_WANT_DIE 0x00000200 /* applet was running and requested to die */
#define APPCTX_FL_INOUT_BUFS 0x00000400 /* applet uses its own buffers */
#define APPCTX_FL_FASTFWD 0x00000800 /* zero-copy forwarding is in-use, don't fill the outbuf */
struct appctx;
struct proxy;

View File

@ -537,6 +537,9 @@ size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsig
goto end;
}
if (flags & CO_RFL_BUF_FLUSH)
applet_fl_set(appctx, APPCTX_FL_FASTFWD);
ret = appctx->applet->rcv_buf(appctx, buf, count, flags);
if (ret)
applet_fl_clr(appctx, APPCTX_FL_OUTBLK_FULL);
@ -648,6 +651,8 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags)
TRACE_ENTER(APPLET_EV_RECV, appctx);
applet_fl_set(appctx, APPCTX_FL_FASTFWD);
/* TODO: outbuf must be empty. Find a better way to handle that but for now just return -1 */
if (b_data(&appctx->outbuf)) {
TRACE_STATE("Output buffer not empty, cannot fast-forward data", APPLET_EV_RECV, appctx);
@ -670,6 +675,7 @@ int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags)
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);
applet_fl_clr(appctx, APPCTX_FL_FASTFWD);
TRACE_DEVEL("Fast-forwarding not supported by opposite endpoint, disable it", APPLET_EV_RECV, appctx);
goto end;
}

View File

@ -1757,6 +1757,7 @@ static size_t http_cache_fastfwd(struct appctx *appctx, struct buffer *buf, size
if (!appctx->to_forward) {
se_fl_clr(appctx->sedesc, SE_FL_MAY_FASTFWD);
applet_fl_clr(appctx, APPCTX_FL_FASTFWD);
if (ctx->sent == first->len - sizeof(*cache_ptr)) {
applet_set_eoi(appctx);
applet_set_eos(appctx);
@ -1779,7 +1780,7 @@ static void http_cache_io_handler(struct appctx *appctx)
if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC|APPCTX_FL_OUTBLK_FULL))
goto exit;
if (se_fl_test(appctx->sedesc, SE_FL_MAY_FASTFWD))
if (applet_fl_test(appctx, APPCTX_FL_FASTFWD) && se_fl_test(appctx->sedesc, SE_FL_MAY_FASTFWD))
goto exit;
if (!appctx_get_buf(appctx, &appctx->outbuf)) {
@ -1853,6 +1854,7 @@ static void http_cache_io_handler(struct appctx *appctx)
res_htx->flags |= HTX_FL_EOM;
applet_set_eoi(appctx);
se_fl_clr(appctx->sedesc, SE_FL_MAY_FASTFWD);
applet_fl_clr(appctx, APPCTX_FL_FASTFWD);
appctx->st0 = HTX_CACHE_END;
}

View File

@ -4471,6 +4471,7 @@ static size_t http_stats_fastfwd(struct appctx *appctx, struct buffer *buf, size
ret = b_data(buf);
if (stats_dump_stat_to_buffer(sc, buf, NULL)) {
se_fl_clr(appctx->sedesc, SE_FL_MAY_FASTFWD);
applet_fl_clr(appctx, APPCTX_FL_FASTFWD);
appctx->st0 = STAT_HTTP_DONE;
}
@ -4495,7 +4496,7 @@ static void http_stats_io_handler(struct appctx *appctx)
if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC|APPCTX_FL_OUTBLK_FULL))
goto out;
if (se_fl_test(appctx->sedesc, SE_FL_MAY_FASTFWD))
if (applet_fl_test(appctx, APPCTX_FL_FASTFWD) && se_fl_test(appctx->sedesc, SE_FL_MAY_FASTFWD))
goto out;
if (!appctx_get_buf(appctx, &appctx->outbuf)) {
@ -4560,6 +4561,7 @@ static void http_stats_io_handler(struct appctx *appctx)
res_htx->flags |= HTX_FL_EOM;
applet_set_eoi(appctx);
se_fl_clr(appctx->sedesc, SE_FL_MAY_FASTFWD);
applet_fl_clr(appctx, APPCTX_FL_FASTFWD);
appctx->st0 = STAT_HTTP_END;
}