mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
MEDIUM: mux-quic: implement be connection reuse
Implement support for QUIC connection reuse on the backend side. The main change is done during detach stream operation. If a connection is idle, it is inserted in the server list. Else, it is stored in the server avail tree if there is room for more streams. For non idle connection, qmux_avail_streams() is reused to detect that stream flow-control limit is not yet reached. If this is the case, the connection is not inserted in the avail tree, so it cannot be reuse, even if flow-control is unblocked later by the peer. This latter point could be improved in the future. Note that support for QUIC private connections is still missing. Reuse code will evolved to fully support this case.
This commit is contained in:
parent
3bf37596ba
commit
3217835b1d
@ -3133,6 +3133,15 @@ static int qmux_avail_streams(struct connection *conn)
|
||||
return qcc_fctl_avail_streams(qcc, 1);
|
||||
}
|
||||
|
||||
/* Returns the number of streams currently attached into <conn> connection.
|
||||
* Used to determine if a connection can be considered as idle or not.
|
||||
*/
|
||||
static int qmux_used_streams(struct connection *conn)
|
||||
{
|
||||
struct qcc *qcc = conn->ctx;
|
||||
return qcc->nb_sc;
|
||||
}
|
||||
|
||||
/* Release all streams which have their transfer operation achieved. */
|
||||
static void qcc_purge_streams(struct qcc *qcc)
|
||||
{
|
||||
@ -3734,8 +3743,9 @@ static void qmux_strm_detach(struct sedesc *sd)
|
||||
{
|
||||
struct qcs *qcs = sd->se;
|
||||
struct qcc *qcc = qcs->qcc;
|
||||
struct connection *conn = qcc->conn;
|
||||
|
||||
TRACE_ENTER(QMUX_EV_STRM_END, qcc->conn, qcs);
|
||||
TRACE_ENTER(QMUX_EV_STRM_END, conn, qcs);
|
||||
|
||||
/* TODO this BUG_ON_HOT() is not correct as the stconn layer may detach
|
||||
* from the stream even if it is not closed remotely at the QUIC layer.
|
||||
@ -3750,7 +3760,7 @@ static void qmux_strm_detach(struct sedesc *sd)
|
||||
|
||||
if (!qcs_is_close_local(qcs) &&
|
||||
!(qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL))) {
|
||||
TRACE_STATE("remaining data, detaching qcs", QMUX_EV_STRM_END, qcc->conn, qcs);
|
||||
TRACE_STATE("remaining data, detaching qcs", QMUX_EV_STRM_END, conn, qcs);
|
||||
qcs->flags |= QC_SF_DETACH;
|
||||
qcc_refresh_timeout(qcc);
|
||||
|
||||
@ -3760,16 +3770,38 @@ static void qmux_strm_detach(struct sedesc *sd)
|
||||
|
||||
qcs_destroy(qcs);
|
||||
|
||||
/* Backend connection can be reused unless it is already on error/closed. */
|
||||
if (qcc->flags & QC_CF_IS_BACK && !qcc_is_dead(qcc)) {
|
||||
if (!(conn->flags & CO_FL_PRIVATE)) {
|
||||
if (!qcc->nb_sc) {
|
||||
TRACE_DEVEL("prepare for idle connection reuse", QMUX_EV_STRM_END, conn);
|
||||
if (!srv_add_to_idle_list(objt_server(conn->target), conn, 1)) {
|
||||
/* Idle conn insert failure, gracefully close the connection. */
|
||||
TRACE_DEVEL("idle connection cannot be kept on the server", QMUX_EV_STRM_END, conn);
|
||||
qcc_shutdown(qcc);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
else if (!conn->hash_node->node.node.leaf_p &&
|
||||
qmux_avail_streams(conn) &&
|
||||
objt_server(conn->target)) {
|
||||
TRACE_DEVEL("mark connection as available for reuse", QMUX_EV_STRM_END, conn);
|
||||
srv_add_to_avail_list(__objt_server(conn->target), conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qcc_is_dead(qcc)) {
|
||||
TRACE_STATE("killing dead connection", QMUX_EV_STRM_END, qcc->conn);
|
||||
TRACE_STATE("killing dead connection", QMUX_EV_STRM_END, conn);
|
||||
goto release;
|
||||
}
|
||||
else {
|
||||
TRACE_DEVEL("refreshing connection's timeout", QMUX_EV_STRM_END, qcc->conn);
|
||||
TRACE_DEVEL("refreshing connection's timeout", QMUX_EV_STRM_END, conn);
|
||||
qcc_refresh_timeout(qcc);
|
||||
}
|
||||
|
||||
TRACE_LEAVE(QMUX_EV_STRM_END, qcc->conn);
|
||||
end:
|
||||
TRACE_LEAVE(QMUX_EV_STRM_END, conn);
|
||||
return;
|
||||
|
||||
release:
|
||||
@ -4253,6 +4285,8 @@ static const struct mux_ops qmux_ops = {
|
||||
.unsubscribe = qmux_strm_unsubscribe,
|
||||
.wake = qmux_wake,
|
||||
.avail_streams = qmux_avail_streams,
|
||||
.used_streams = qmux_used_streams,
|
||||
.takeover = NULL, /* QUIC takeover support not implemented yet */
|
||||
.attach = qmux_strm_attach,
|
||||
.shut = qmux_strm_shut,
|
||||
.ctl = qmux_ctl,
|
||||
|
Loading…
Reference in New Issue
Block a user