mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-01-19 00:51:37 +01:00
MINOR: quic: remove <mux_state> field
This patch removes <mux_state> field from quic_conn structure. The purpose of this field was to indicate if MUX layer above quic_conn is not yet initialized, active, or already released. It became tedious to properly set it as initialization order of the various quic_conn/conn/MUX layers now differ between the frontend and backend sides, and also depending if 0-RTT is used or not. Recently, a new change introduced in connect_server() will allow to initialize QUIC MUX earlier if ALPN is cached on the server structure. This had another level of complexity. Thus, this patch removes <mux_state> field completely. Instead, a new flag QUIC_FL_CONN_XPRT_CLOSED is defined. It is set at a single place only on close XPRT callback invokation. It can be mixed with the new utility functions qc_wait_for_conn()/qc_is_conn_ready() to determine the status of conn/MUX layers now without an extra quic_conn field.
This commit is contained in:
parent
99a2454e9d
commit
b9809fe0d0
@ -243,17 +243,6 @@ extern const struct quic_version *quic_version_2;
|
||||
/* The maximum number of bytes of CRYPTO data in flight during handshakes. */
|
||||
#define QUIC_CRYPTO_IN_FLIGHT_MAX 4096
|
||||
|
||||
/* Status of the MUX layer. This defines how to handle app data.
|
||||
*
|
||||
* During a standard quic_conn lifetime it transitions like this :
|
||||
* QC_MUX_NULL -> QC_MUX_READY -> QC_MUX_RELEASED
|
||||
*/
|
||||
enum qc_mux_state {
|
||||
QC_MUX_NULL, /* not allocated, data should be buffered */
|
||||
QC_MUX_READY, /* allocated, ready to handle data */
|
||||
QC_MUX_RELEASED, /* released, data can be dropped */
|
||||
};
|
||||
|
||||
/* Counters at QUIC connection level */
|
||||
struct quic_conn_cntrs {
|
||||
long long dropped_pkt; /* total number of dropped packets */
|
||||
@ -333,7 +322,6 @@ struct quic_conn {
|
||||
/* QUIC transport parameters TLS extension */
|
||||
int tps_tls_ext;
|
||||
int state;
|
||||
enum qc_mux_state mux_state; /* status of the connection/mux layer */
|
||||
#ifdef HAVE_OPENSSL_QUIC
|
||||
uint32_t prot_level;
|
||||
#endif
|
||||
@ -457,6 +445,7 @@ struct quic_conn_closed {
|
||||
#define QUIC_FL_CONN_PEER_VALIDATED_ADDR (1U << 17) /* Peer address is considered as validated for this connection. */
|
||||
#define QUIC_FL_CONN_NO_TOKEN_RCVD (1U << 18) /* Client dit not send any token */
|
||||
#define QUIC_FL_CONN_SCID_RECEIVED (1U << 19) /* (client only: first Initial received. */
|
||||
#define QUIC_FL_CONN_XPRT_CLOSED (1U << 20) /* close callback of xprt layer already called */
|
||||
/* gap here */
|
||||
#define QUIC_FL_CONN_TO_KILL (1U << 24) /* Unusable connection, to be killed */
|
||||
#define QUIC_FL_CONN_TX_TP_RECEIVED (1U << 25) /* Peer transport parameters have been received (used for the transmitting part) */
|
||||
|
||||
@ -218,5 +218,9 @@ extern uint64_t (*quic_hash64_from_cid)(const unsigned char *cid, int size, cons
|
||||
/* Function pointer that can be used to derive a new CID from the previously computed hash */
|
||||
extern void (*quic_newcid_from_hash64)(unsigned char *cid, int size, uint64_t hash, const unsigned char *secret, size_t secretlen);
|
||||
|
||||
/* QUIC xprt layer functions */
|
||||
int qc_wait_for_conn(const struct quic_conn *qc);
|
||||
int qc_is_conn_ready(const struct quic_conn *qc);
|
||||
|
||||
#endif /* USE_QUIC */
|
||||
#endif /* _HAPROXY_QUIC_CONN_H */
|
||||
|
||||
@ -311,9 +311,9 @@ static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc)
|
||||
else
|
||||
chunk_appendf(&trash, " st=opened ");
|
||||
|
||||
if (qc->mux_state == QC_MUX_NULL)
|
||||
if (qc_wait_for_conn(qc))
|
||||
chunk_appendf(&trash, "mux=null ");
|
||||
else if (qc->mux_state == QC_MUX_READY)
|
||||
else if (qc_is_conn_ready(qc))
|
||||
chunk_appendf(&trash, "mux=ready ");
|
||||
else
|
||||
chunk_appendf(&trash, "mux=released ");
|
||||
@ -428,7 +428,7 @@ static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc)
|
||||
if (addnl)
|
||||
chunk_appendf(&trash, "\n");
|
||||
|
||||
if (ctx->fields & QUIC_DUMP_FLD_MUX && qc->mux_state == QC_MUX_READY)
|
||||
if ((ctx->fields & QUIC_DUMP_FLD_MUX) && qc_is_conn_ready(qc))
|
||||
qcc_show_quic(qc->qcc);
|
||||
|
||||
chunk_appendf(&trash, "\n");
|
||||
|
||||
@ -294,7 +294,7 @@ void qc_check_close_on_released_mux(struct quic_conn *qc)
|
||||
{
|
||||
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
|
||||
|
||||
if (qc->mux_state == QC_MUX_RELEASED && eb_is_empty(&qc->streams_by_id)) {
|
||||
if ((qc->flags & QUIC_FL_CONN_XPRT_CLOSED) && eb_is_empty(&qc->streams_by_id)) {
|
||||
/* Reuse errcode which should have been previously set by the MUX on release. */
|
||||
quic_set_connection_close(qc, qc->err);
|
||||
tasklet_wakeup(qc->wait_event.tasklet);
|
||||
@ -337,10 +337,11 @@ void quic_conn_closed_err_count_inc(struct quic_conn *qc, struct quic_frame *frm
|
||||
{
|
||||
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
|
||||
|
||||
if (frm->type == QUIC_FT_CONNECTION_CLOSE)
|
||||
if (frm->type == QUIC_FT_CONNECTION_CLOSE) {
|
||||
quic_stats_transp_err_count_inc(qc->prx_counters, frm->connection_close.error_code);
|
||||
}
|
||||
else if (frm->type == QUIC_FT_CONNECTION_CLOSE_APP) {
|
||||
if (qc->mux_state != QC_MUX_READY || !qc->qcc->app_ops->inc_err_cnt)
|
||||
if (!qc_is_conn_ready(qc) || !qc->qcc->app_ops->inc_err_cnt)
|
||||
goto out;
|
||||
|
||||
qc->qcc->app_ops->inc_err_cnt(qc->qcc->ctx, frm->connection_close_app.error_code);
|
||||
@ -1227,7 +1228,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
|
||||
|
||||
qc->next_cid_seq_num = 1;
|
||||
}
|
||||
qc->mux_state = QC_MUX_NULL;
|
||||
qc->err = quic_err_transport(QC_ERR_NO_ERROR);
|
||||
|
||||
/* Listener only: if connection is instantiated due to an INITIAL packet with an
|
||||
@ -1916,7 +1916,7 @@ int qc_notify_send(struct quic_conn *qc)
|
||||
/* Wake up streams layer waiting for buffer. Useful after congestion
|
||||
* window increase.
|
||||
*/
|
||||
if (qc->mux_state == QC_MUX_READY && (qc->qcc->flags & QC_CF_CONN_FULL))
|
||||
if (qc_is_conn_ready(qc) && (qc->qcc->flags & QC_CF_CONN_FULL))
|
||||
qcc_notify_buf(qc->qcc, 0);
|
||||
|
||||
return 0;
|
||||
@ -1927,7 +1927,7 @@ void qc_notify_err(struct quic_conn *qc)
|
||||
{
|
||||
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
|
||||
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
if (qc_is_conn_ready(qc)) {
|
||||
TRACE_STATE("error notified to mux", QUIC_EV_CONN_CLOSE, qc);
|
||||
|
||||
/* Mark socket as closed. */
|
||||
|
||||
@ -871,7 +871,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
break;
|
||||
}
|
||||
case QUIC_FT_RESET_STREAM:
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
if (qc_is_conn_ready(qc)) {
|
||||
struct qf_reset_stream *rs_frm = &frm->reset_stream;
|
||||
qcc_recv_reset_stream(qc->qcc, rs_frm->id, rs_frm->app_error_code, rs_frm->final_size);
|
||||
}
|
||||
@ -879,7 +879,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
case QUIC_FT_STOP_SENDING:
|
||||
{
|
||||
struct qf_stop_sending *ss_frm = &frm->stop_sending;
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
if (qc_is_conn_ready(qc)) {
|
||||
if (qcc_recv_stop_sending(qc->qcc, ss_frm->id,
|
||||
ss_frm->app_error_code)) {
|
||||
TRACE_ERROR("qcc_recv_stop_sending() failed", QUIC_EV_CONN_PRSHPKT, qc);
|
||||
@ -921,7 +921,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
qc->rx.stream_max_uni : qc->rx.stream_max_bidi;
|
||||
|
||||
/* The upper layer may not be allocated. */
|
||||
if (qc->mux_state != QC_MUX_READY) {
|
||||
if (!qc_is_conn_ready(qc)) {
|
||||
if (strm_frm->id < max) {
|
||||
TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
|
||||
}
|
||||
@ -951,13 +951,13 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
break;
|
||||
}
|
||||
case QUIC_FT_MAX_DATA:
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
if (qc_is_conn_ready(qc)) {
|
||||
struct qf_max_data *md_frm = &frm->max_data;
|
||||
qcc_recv_max_data(qc->qcc, md_frm->max_data);
|
||||
}
|
||||
break;
|
||||
case QUIC_FT_MAX_STREAM_DATA:
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
if (qc_is_conn_ready(qc)) {
|
||||
struct qf_max_stream_data *msd_frm = &frm->max_stream_data;
|
||||
if (qcc_recv_max_stream_data(qc->qcc, msd_frm->id,
|
||||
msd_frm->max_stream_data)) {
|
||||
@ -968,7 +968,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
break;
|
||||
case QUIC_FT_MAX_STREAMS_BIDI:
|
||||
case QUIC_FT_MAX_STREAMS_UNI:
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
if (qc_is_conn_ready(qc)) {
|
||||
int bidi;
|
||||
struct qf_max_streams *ms_frm;
|
||||
|
||||
@ -1207,8 +1207,7 @@ static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel)
|
||||
}
|
||||
|
||||
/* check if the connection layer is ready before using app level */
|
||||
if ((qel == qc->ael || qel == qc->eel) &&
|
||||
qc->mux_state == QC_MUX_NULL) {
|
||||
if ((qel == qc->ael || qel == qc->eel) && qc_wait_for_conn(qc)) {
|
||||
TRACE_PROTO("connection layer not ready", QUIC_EV_CONN_TRMHP, qc);
|
||||
goto cant_rm_hp;
|
||||
}
|
||||
|
||||
@ -1001,7 +1001,6 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
|
||||
|
||||
/* Wake up MUX after its creation. Operation similar to TLS+ALPN on TCP stack. */
|
||||
qc->conn->mux->wake(qc->conn);
|
||||
qc->mux_state = QC_MUX_READY;
|
||||
}
|
||||
else {
|
||||
TRACE_PROTO("could not start the mux", QUIC_EV_CONN_IO_CB, qc);
|
||||
|
||||
@ -518,7 +518,6 @@ enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms,
|
||||
int max_dgram = 0, sent;
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
|
||||
BUG_ON(qc->mux_state != QC_MUX_READY); /* Only MUX can uses this function so it must be ready. */
|
||||
|
||||
if (qc->conn->flags & CO_FL_SOCK_WR_SH) {
|
||||
qc->conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH;
|
||||
|
||||
@ -19,6 +19,19 @@
|
||||
#include <haproxy/quic_trace.h>
|
||||
#include <haproxy/trace.h>
|
||||
|
||||
/* Returns true if conn layer above <qc> has not been yet fully initialized, i.e. MUX is not yet opened. */
|
||||
int qc_wait_for_conn(const struct quic_conn *qc)
|
||||
{
|
||||
return (!qc->conn || !qc->conn->mux) &&
|
||||
!(qc->flags & QUIC_FL_CONN_XPRT_CLOSED);
|
||||
}
|
||||
|
||||
/* Returns true if conn layer above <qc> is fully initialized and available. */
|
||||
int qc_is_conn_ready(const struct quic_conn *qc)
|
||||
{
|
||||
return qc->conn && qc->conn->mux;
|
||||
}
|
||||
|
||||
static void quic_close(struct connection *conn, void *xprt_ctx)
|
||||
{
|
||||
struct ssl_sock_ctx *conn_ctx = xprt_ctx;
|
||||
@ -26,11 +39,9 @@ static void quic_close(struct connection *conn, void *xprt_ctx)
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
|
||||
|
||||
qc->flags |= QUIC_FL_CONN_XPRT_CLOSED;
|
||||
qc->conn = NULL;
|
||||
|
||||
/* Next application data can be dropped. */
|
||||
qc->mux_state = QC_MUX_RELEASED;
|
||||
|
||||
/* If the quic-conn timer has already expired or if already in "connection close"
|
||||
* state, free the quic-conn.
|
||||
*/
|
||||
@ -161,17 +172,11 @@ static int qc_xprt_start(struct connection *conn, void *ctx)
|
||||
qc = conn->handle.qc;
|
||||
TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
|
||||
|
||||
if (objt_listener(conn->target)) {
|
||||
/* mux-quic can now be considered ready. */
|
||||
qc->mux_state = QC_MUX_READY;
|
||||
}
|
||||
else {
|
||||
/* This has as side effet to create a SSL_SESSION object attached to
|
||||
* the SSL object.
|
||||
*/
|
||||
if (!qc_ssl_do_hanshake(qc, ctx))
|
||||
goto out;
|
||||
}
|
||||
/* This has as side effet to create a SSL_SESSION object attached to
|
||||
* the SSL object.
|
||||
*/
|
||||
if (qc_is_back(qc) && !qc_ssl_do_hanshake(qc, ctx))
|
||||
goto out;
|
||||
|
||||
/* Schedule quic-conn to ensure post handshake frames are emitted. This
|
||||
* is not done for 0-RTT as xprt->start happens before handshake
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user