MINOR: mux-quic: define a QCC application state member

Introduce a new QCC field to track the current application layer state.
For the moment, only INIT and SHUT state are defined. This allows to
replace the older flag QC_CF_APP_SHUT.

This commit does not bring major changes. It is only necessary to permit
future evolutions on QUIC MUX. The only noticeable change is that QMUX
traces can now display this new field.
This commit is contained in:
Amaury Denoyelle 2025-02-18 11:42:59 +01:00
parent 4a99f15f0c
commit 188fc45b95
3 changed files with 27 additions and 10 deletions

View File

@ -32,11 +32,17 @@ enum qcs_type {
QCS_MAX_TYPES
};
enum qcc_app_st {
QCC_APP_ST_INIT,
QCC_APP_ST_SHUT,
} __attribute__((packed));
struct qcc {
struct connection *conn;
uint64_t nb_sc; /* number of attached stream connectors */
uint64_t nb_hreq; /* number of in-progress http requests */
uint32_t flags; /* QC_CF_* */
enum qcc_app_st app_st; /* application layer state */
int glitches; /* total number of glitches on this connection */
/* flow-control fields set by us enforced on our side. */
@ -221,7 +227,7 @@ struct qcc_app_ops {
#define QC_CF_ERRL_DONE 0x00000002 /* local error properly handled, connection can be released */
/* unused 0x00000004 */
#define QC_CF_CONN_FULL 0x00000008 /* no stream buffers available on connection */
#define QC_CF_APP_SHUT 0x00000010 /* Application layer shutdown done. */
/* unused 0x00000010 */
#define QC_CF_ERR_CONN 0x00000020 /* fatal error reported by transport layer */
#define QC_CF_WAIT_HS 0x00000040 /* MUX init before QUIC handshake completed (0-RTT) */
@ -238,9 +244,8 @@ static forceinline char *qcc_show_flags(char *buf, size_t len, const char *delim
_(QC_CF_ERRL,
_(QC_CF_ERRL_DONE,
_(QC_CF_CONN_FULL,
_(QC_CF_APP_SHUT,
_(QC_CF_ERR_CONN,
_(QC_CF_WAIT_HS))))));
_(QC_CF_WAIT_HS)))));
/* epilogue */
_(~0U);
return buf;

View File

@ -309,7 +309,7 @@ static void qcc_refresh_timeout(struct qcc *qcc)
* processed if shutdown already one or connection is idle.
*/
if (!conn_is_back(qcc->conn)) {
if (qcc->nb_hreq && !(qcc->flags & QC_CF_APP_SHUT)) {
if (qcc->nb_hreq && qcc->app_st < QCC_APP_ST_SHUT) {
TRACE_DEVEL("one or more requests still in progress", QMUX_EV_QCC_WAKE, qcc->conn);
qcc->task->expire = tick_add_ifset(now_ms, qcc->timeout);
task_queue(qcc->task);
@ -317,7 +317,7 @@ static void qcc_refresh_timeout(struct qcc *qcc)
}
if ((!LIST_ISEMPTY(&qcc->opening_list) || unlikely(!qcc->largest_bidi_r)) &&
!(qcc->flags & QC_CF_APP_SHUT)) {
qcc->app_st < QCC_APP_ST_SHUT) {
int timeout = px->timeout.httpreq;
struct qcs *qcs = NULL;
int base_time;
@ -333,7 +333,7 @@ static void qcc_refresh_timeout(struct qcc *qcc)
qcc->task->expire = tick_add_ifset(base_time, timeout);
}
else {
if (qcc->flags & QC_CF_APP_SHUT) {
if (qcc->app_st >= QCC_APP_ST_SHUT) {
TRACE_DEVEL("connection in closing", QMUX_EV_QCC_WAKE, qcc->conn);
qcc->task->expire = tick_add_ifset(now_ms,
qcc->shut_timeout);
@ -2704,7 +2704,7 @@ static void qcc_purge_streams(struct qcc *qcc)
/* Execute application layer shutdown. If this operation is not defined, a
* CONNECTION_CLOSE will be prepared as a fallback. This function is protected
* against multiple invocation with the flag QC_CF_APP_SHUT.
* against multiple invocation thanks to <qcc> application state context.
*/
static void qcc_shutdown(struct qcc *qcc)
{
@ -2715,7 +2715,7 @@ static void qcc_shutdown(struct qcc *qcc)
goto out;
}
if (qcc->flags & QC_CF_APP_SHUT)
if (qcc->app_st >= QCC_APP_ST_SHUT)
goto out;
TRACE_STATE("perform graceful shutdown", QMUX_EV_QCC_END, qcc->conn);
@ -2738,7 +2738,7 @@ static void qcc_shutdown(struct qcc *qcc)
qcc->conn->handle.qc->err = qcc->err;
out:
qcc->flags |= QC_CF_APP_SHUT;
qcc->app_st = QCC_APP_ST_SHUT;
TRACE_LEAVE(QMUX_EV_QCC_END, qcc->conn);
}
@ -3042,6 +3042,7 @@ static int qmux_init(struct connection *conn, struct proxy *prx,
conn->ctx = qcc;
qcc->nb_hreq = qcc->nb_sc = 0;
qcc->flags = 0;
qcc->app_st = QCC_APP_ST_INIT;
qcc->glitches = 0;
qcc->err = quic_err_transport(QC_ERR_NO_ERROR);

View File

@ -130,6 +130,15 @@ static void qmux_trace_fill_ctx(struct trace_ctx *ctx, const struct trace_source
/* register qmux traces */
INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
static char *qcc_app_st_to_str(const enum qcc_app_st st)
{
switch (st) {
case QCC_APP_ST_INIT: return "INIT";
case QCC_APP_ST_SHUT: return "SHUT";
default: return "";
}
}
void qmux_dump_qcc_info(struct buffer *msg, const struct qcc *qcc)
{
const struct quic_conn *qc = qcc->conn->handle.qc;
@ -137,7 +146,9 @@ void qmux_dump_qcc_info(struct buffer *msg, const struct qcc *qcc)
chunk_appendf(msg, " qcc=%p(F)", qcc);
if (qcc->conn->handle.qc)
chunk_appendf(msg, " qc=%p", qcc->conn->handle.qc);
chunk_appendf(msg, " .sc=%llu .hreq=%llu .flg=0x%04x", (ullong)qcc->nb_sc, (ullong)qcc->nb_hreq, qcc->flags);
chunk_appendf(msg, " .st=%s .sc=%llu .hreq=%llu .flg=0x%04x",
qcc_app_st_to_str(qcc->app_st), (ullong)qcc->nb_sc,
(ullong)qcc->nb_hreq, qcc->flags);
chunk_appendf(msg, " .tx=%llu %llu/%llu bwnd=%llu/%llu",
(ullong)qcc->tx.fc.off_soft, (ullong)qcc->tx.fc.off_real, (ullong)qcc->tx.fc.limit,