mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-05 22:56:57 +02:00
MEDIUM: stconn/muxes: Add an abort reason for SE shutdowns on muxes
A reason is now passed as parameter to muxes shutdowns to pass additional info about the abort, if any. No info means no abort or only generic one. For now, the reason is composed of 2 32-bits integer. The first on represents the abort code and the other one represents the info about the code (for instance the source). The code should be interpreted according to the associated info. One info is the source, encoding on 5 bits. Other bits are reserverd for now. For now, the muxes are the only supported source. But we can imagine to extend it to applets, streams, health-checks... The current design is quite simple and will most probably evolved.. But the idea is to let the opposite side forward some errors and let's a mux know why its stream was aborted. At first glance, a abort reason must only be evaluated if SE_SHW_SILENT flag is set. The main goal at short term, is to forward some H2 RST_STREAM codes because it is mandatory for gRPC applications, mainly to forward gRPC cancellation from an H2 client to an H2 server. But we can imagine to alter this reason at the applicative level to enrich it. It would also be used to report more accurate errors in logs.
This commit is contained in:
parent
28489021b3
commit
96f8b7ad08
@ -411,7 +411,7 @@ struct mux_ops {
|
||||
size_t (*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 */
|
||||
void (*shut)(struct stconn *sc, enum se_shut_mode); /* shutdown function */
|
||||
void (*shut)(struct stconn *sc, enum se_shut_mode, struct se_abort_info *reason); /* shutdown function */
|
||||
|
||||
int (*attach)(struct connection *conn, struct sedesc *, struct session *sess); /* attach a stconn to an outgoing connection */
|
||||
struct stconn *(*get_first_sc)(const struct connection *); /* retrieves any valid stconn from this connection */
|
||||
|
@ -266,6 +266,24 @@ enum sc_state_bit {
|
||||
|
||||
struct stconn;
|
||||
|
||||
/* represent the abort code, enriched with contextual info:
|
||||
* - First 5 bits are used for the source (31 possible sources)
|
||||
* - other bits are reserved for now
|
||||
*/
|
||||
#define SE_ABRT_SRC_SHIFT 0
|
||||
#define SE_ABRT_SRC_MASK 0x0000001f
|
||||
|
||||
#define SE_ABRT_SRC_MUX_PT 0x01 /* Code set by the PT mux */
|
||||
#define SE_ABRT_SRC_MUX_H1 0x02 /* Code set bu the H1 mux */
|
||||
#define SE_ABRT_SRC_MUX_H2 0x03 /* Code set bu the H2 mux */
|
||||
#define SE_ABRT_SRC_MUX_QUIC 0x04 /* Code set bu the QUIC/H3 mux */
|
||||
#define SE_ABRT_SRC_MUX_FCGI 0x05 /* Code set bu the FCGI mux */
|
||||
|
||||
struct se_abort_info {
|
||||
uint32_t info;
|
||||
uint64_t code;
|
||||
};
|
||||
|
||||
/* A Stream Endpoint Descriptor (sedesc) is the link between the stream
|
||||
* connector (ex. stconn) and the Stream Endpoint (mux or appctx).
|
||||
* It always exists for either of them, and binds them together. It also
|
||||
@ -296,6 +314,7 @@ struct sedesc {
|
||||
struct stconn *sc; /* the stream connector we're attached to, or NULL */
|
||||
struct iobuf iobuf; /* contains data forwarded by the other side and that must be sent by the stream endpoint */
|
||||
unsigned int flags; /* SE_FL_* */
|
||||
struct se_abort_info abort_info; /* Info about abort, as reported by the endpoint and eventually enriched by the app level */
|
||||
unsigned int lra; /* the last read activity */
|
||||
unsigned int fsb; /* the first send blocked */
|
||||
/* 4 bytes hole here */
|
||||
|
@ -3791,7 +3791,7 @@ struct task *fcgi_deferred_shut(struct task *t, void *ctx, unsigned int state)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fcgi_shut(struct stconn *sc, enum se_shut_mode mode)
|
||||
static void fcgi_shut(struct stconn *sc, enum se_shut_mode mode, struct se_abort_info *reason)
|
||||
{
|
||||
struct fcgi_strm *fstrm = __sc_mux_strm(sc);
|
||||
|
||||
|
@ -4291,7 +4291,7 @@ static void h1_detach(struct sedesc *sd)
|
||||
TRACE_LEAVE(H1_EV_STRM_END);
|
||||
}
|
||||
|
||||
static void h1_shut(struct stconn *sc, enum se_shut_mode mode)
|
||||
static void h1_shut(struct stconn *sc, enum se_shut_mode mode, struct se_abort_info *reason)
|
||||
{
|
||||
struct h1s *h1s = __sc_mux_strm(sc);
|
||||
struct h1c *h1c;
|
||||
|
@ -5079,7 +5079,7 @@ struct task *h2_deferred_shut(struct task *t, void *ctx, unsigned int state)
|
||||
return t;
|
||||
}
|
||||
|
||||
static void h2_shut(struct stconn *sc, enum se_shut_mode mode)
|
||||
static void h2_shut(struct stconn *sc, enum se_shut_mode mode, struct se_abort_info *reason)
|
||||
{
|
||||
struct h2s *h2s = __sc_mux_strm(sc);
|
||||
|
||||
|
@ -462,7 +462,7 @@ static int mux_pt_avail_streams(struct connection *conn)
|
||||
return 1 - mux_pt_used_streams(conn);
|
||||
}
|
||||
|
||||
static void mux_pt_shut(struct stconn *sc, enum se_shut_mode mode)
|
||||
static void mux_pt_shut(struct stconn *sc, enum se_shut_mode mode, struct se_abort_info *reason)
|
||||
{
|
||||
struct connection *conn = __sc_conn(sc);
|
||||
struct mux_pt_ctx *ctx = conn->ctx;
|
||||
|
@ -3095,7 +3095,7 @@ static int qmux_wake(struct connection *conn)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void qmux_strm_shut(struct stconn *sc, enum se_shut_mode mode)
|
||||
static void qmux_strm_shut(struct stconn *sc, enum se_shut_mode mode, struct se_abort_info *reason)
|
||||
{
|
||||
struct qcs *qcs = __sc_mux_strm(sc);
|
||||
struct qcc *qcc = qcs->qcc;
|
||||
|
19
src/stconn.c
19
src/stconn.c
@ -100,6 +100,9 @@ void sedesc_init(struct sedesc *sedesc)
|
||||
sedesc->xref.peer = NULL;
|
||||
se_fl_setall(sedesc, SE_FL_NONE);
|
||||
|
||||
sedesc->abort_info.info = 0;
|
||||
sedesc->abort_info.code = 0;
|
||||
|
||||
sedesc->iobuf.pipe = NULL;
|
||||
sedesc->iobuf.buf = NULL;
|
||||
sedesc->iobuf.offset = sedesc->iobuf.data = 0;
|
||||
@ -150,8 +153,20 @@ void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode)
|
||||
flags |= (mode & SE_SHR_DRAIN) ? SE_FL_SHRD : SE_FL_SHRR;
|
||||
|
||||
if (flags) {
|
||||
if (mux && mux->shut)
|
||||
mux->shut(sedesc->sc, mode);
|
||||
if (mux && mux->shut) {
|
||||
struct se_abort_info *reason = NULL;
|
||||
struct xref *peer = xref_get_peer_and_lock(&sedesc->xref);
|
||||
|
||||
if (peer) {
|
||||
struct sedesc *sdo = container_of(peer, struct sedesc, xref);
|
||||
|
||||
reason = &sdo->abort_info;
|
||||
xref_unlock(&sedesc->xref, peer);
|
||||
}
|
||||
|
||||
mux->shut(sedesc->sc, mode, reason);
|
||||
|
||||
}
|
||||
se_fl_set(sedesc, flags);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user