mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
MINOR: mux-quic: refactor wait-for-handshake support
This commit refactors wait-for-handshake support from QUIC MUX. The flag logic QC_CF_WAIT_HS is inverted : it is now positionned only if MUX is instantiated before handshake completion. When the handshake is completed, the flag is removed. The flag is now set directly on initialization via qmux_init(). Removal via qcc_wait_for_hs() is moved from qcc_io_process() to qcc_io_recv(). This is deemed more logical as QUIC MUX is scheduled on RECV to be notify by the transport layer about handshake termination. Moreover, qcc_wait_for_hs() is now called if recv subscription is still active. This commit is the first of a serie which aims to refactor QUIC MUX I/O handler and improves its overall performance. The ultimate objective is to be able to stream qcc_io_cb() by removing pacing specific code path via qcc_purge_sending(). This should be backported up to 3.1.
This commit is contained in:
parent
9dcd2369e2
commit
0a53a008d0
@ -219,7 +219,7 @@ struct qcc_app_ops {
|
||||
#define QC_CF_CONN_FULL 0x00000008 /* no stream buffers available on connection */
|
||||
#define QC_CF_APP_SHUT 0x00000010 /* Application layer shutdown done. */
|
||||
#define QC_CF_ERR_CONN 0x00000020 /* fatal error reported by transport layer */
|
||||
#define QC_CF_WAIT_FOR_HS 0x00000040 /* QUIC handshake has been completed */
|
||||
#define QC_CF_WAIT_HS 0x00000040 /* MUX init before QUIC handshake completed (0-RTT) */
|
||||
|
||||
/* This function is used to report flags in debugging tools. Please reflect
|
||||
* below any single-bit flag addition above in the same order via the
|
||||
@ -236,7 +236,7 @@ static forceinline char *qcc_show_flags(char *buf, size_t len, const char *delim
|
||||
_(QC_CF_CONN_FULL,
|
||||
_(QC_CF_APP_SHUT,
|
||||
_(QC_CF_ERR_CONN,
|
||||
_(QC_CF_WAIT_FOR_HS))))));
|
||||
_(QC_CF_WAIT_HS))))));
|
||||
/* epilogue */
|
||||
_(~0U);
|
||||
return buf;
|
||||
|
@ -2476,6 +2476,39 @@ static int qcc_io_send(struct qcc *qcc)
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Detects QUIC handshake completion. Any SE_FL_WAIT_FOR_HS streams are woken
|
||||
* up if wait-for-handshake is active.
|
||||
*/
|
||||
static void qcc_wait_for_hs(struct qcc *qcc)
|
||||
{
|
||||
struct connection *conn = qcc->conn;
|
||||
struct quic_conn *qc = conn->handle.qc;
|
||||
struct eb64_node *node;
|
||||
struct qcs *qcs;
|
||||
|
||||
TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
|
||||
|
||||
if (qc->state >= QUIC_HS_ST_COMPLETE) {
|
||||
if (conn->flags & CO_FL_EARLY_SSL_HS) {
|
||||
TRACE_STATE("mark early data as ready", QMUX_EV_QCC_WAKE, conn);
|
||||
conn->flags &= ~CO_FL_EARLY_SSL_HS;
|
||||
}
|
||||
|
||||
/* wake-up any stream blocked on early data transfer */
|
||||
node = eb64_first(&qcc->streams_by_id);
|
||||
while (node) {
|
||||
qcs = container_of(node, struct qcs, by_id);
|
||||
if (se_fl_test(qcs->sd, SE_FL_WAIT_FOR_HS))
|
||||
qcs_notify_recv(qcs);
|
||||
node = eb64_next(node);
|
||||
}
|
||||
|
||||
qcc->flags &= ~QC_CF_WAIT_HS;
|
||||
}
|
||||
|
||||
TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
|
||||
}
|
||||
|
||||
/* Proceed on receiving. Loop through all streams from <qcc> and use decode_qcs
|
||||
* operation.
|
||||
*
|
||||
@ -2494,6 +2527,9 @@ static int qcc_io_recv(struct qcc *qcc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((qcc->flags & QC_CF_WAIT_HS) && !(qcc->wait_event.events & SUB_RETRY_RECV))
|
||||
qcc_wait_for_hs(qcc);
|
||||
|
||||
node = eb64_first(&qcc->streams_by_id);
|
||||
while (node) {
|
||||
uint64_t id;
|
||||
@ -2626,44 +2662,6 @@ static int qcc_wake_some_streams(struct qcc *qcc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks whether QUIC handshake is still active or not. This is necessary to
|
||||
* mark that connection may convey early data to delay stream processing if
|
||||
* wait-for-handshake is active. On handshake completion, any SE_FL_WAIT_FOR_HS
|
||||
* streams are woken up to restart their processing.
|
||||
*/
|
||||
static void qcc_wait_for_hs(struct qcc *qcc)
|
||||
{
|
||||
struct connection *conn = qcc->conn;
|
||||
struct quic_conn *qc = conn->handle.qc;
|
||||
struct eb64_node *node;
|
||||
struct qcs *qcs;
|
||||
|
||||
if (qc->state < QUIC_HS_ST_COMPLETE) {
|
||||
if (!(conn->flags & CO_FL_EARLY_SSL_HS)) {
|
||||
TRACE_STATE("flag connection with early data", QMUX_EV_QCC_WAKE, conn);
|
||||
conn->flags |= CO_FL_EARLY_SSL_HS;
|
||||
/* subscribe for handshake completion */
|
||||
conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_RECV,
|
||||
&qcc->wait_event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (conn->flags & CO_FL_EARLY_SSL_HS) {
|
||||
TRACE_STATE("mark early data as ready", QMUX_EV_QCC_WAKE, conn);
|
||||
conn->flags &= ~CO_FL_EARLY_SSL_HS;
|
||||
}
|
||||
qcc->flags |= QC_CF_WAIT_FOR_HS;
|
||||
|
||||
node = eb64_first(&qcc->streams_by_id);
|
||||
while (node) {
|
||||
qcs = container_of(node, struct qcs, by_id);
|
||||
if (se_fl_test(qcs->sd, SE_FL_WAIT_FOR_HS))
|
||||
qcs_notify_recv(qcs);
|
||||
node = eb64_next(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Conduct operations which should be made for <qcc> connection after
|
||||
* input/output. Most notably, closed streams are purged which may leave the
|
||||
* connection has ready to be released.
|
||||
@ -2674,9 +2672,6 @@ static int qcc_io_process(struct qcc *qcc)
|
||||
{
|
||||
qcc_purge_streams(qcc);
|
||||
|
||||
if (!(qcc->flags & QC_CF_WAIT_FOR_HS))
|
||||
qcc_wait_for_hs(qcc);
|
||||
|
||||
/* Check if a soft-stop is in progress.
|
||||
*
|
||||
* TODO this is relevant for frontend connections only.
|
||||
@ -3060,6 +3055,21 @@ static int qmux_init(struct connection *conn, struct proxy *prx,
|
||||
/* init read cycle */
|
||||
qcc_wakeup(qcc);
|
||||
|
||||
/* MUX is initialized before QUIC handshake completion if early data
|
||||
* received. Flag connection to delay stream processing if
|
||||
* wait-for-handshake is active.
|
||||
*/
|
||||
if (conn->handle.qc->state < QUIC_HS_ST_COMPLETE) {
|
||||
if (!(conn->flags & CO_FL_EARLY_SSL_HS)) {
|
||||
TRACE_STATE("flag connection with early data", QMUX_EV_QCC_WAKE, conn);
|
||||
conn->flags |= CO_FL_EARLY_SSL_HS;
|
||||
/* subscribe for handshake completion */
|
||||
conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_RECV,
|
||||
&qcc->wait_event);
|
||||
qcc->flags |= QC_CF_WAIT_HS;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_LEAVE(QMUX_EV_QCC_NEW, conn);
|
||||
return 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user