MINOR: quic: New quic_cstream object implementation

Add new quic_cstream struct definition to implement the CRYPTO data stream.
This is a simplication of the qcs object (QUIC streams) for the CRYPTO data
without any information about the flow control. They are not attached to any
tree, but to a QUIC encryption level, one by encryption level except for
the early data encryption level (for 0RTT). A stream descriptor is also allocated
for each CRYPTO data stream.

Must be backported to 2.6

(cherry picked from commit 7e3f7c47e9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
This commit is contained in:
Frédéric Lécaille 2022-09-09 18:05:45 +02:00 committed by Christopher Faulet
parent 2f824716d3
commit 6b84c17d99
3 changed files with 88 additions and 5 deletions

View File

@ -510,6 +510,21 @@ struct q_buf {
struct list pkts;
};
/* Crypto data stream (one by encryption level) */
struct quic_cstream {
struct {
uint64_t offset; /* absolute current base offset of ncbuf */
struct ncbuf ncbuf; /* receive buffer - can handle out-of-order offset frames */
} rx;
struct {
uint64_t offset; /* last offset of data ready to be sent */
uint64_t sent_offset; /* last offset sent by transport layer */
struct buffer buf; /* transmit buffer before sending via xprt */
} tx;
struct qc_stream_desc *desc;
};
struct quic_enc_level {
enum ssl_encryption_level_t level;
struct quic_tls_ctx tls_ctx;
@ -536,6 +551,8 @@ struct quic_enc_level {
uint64_t offset;
} crypto;
} tx;
/* Crypto data stream */
struct quic_cstream *cstream;
struct quic_pktns *pktns;
};

View File

@ -210,6 +210,7 @@ DECLARE_POOL(pool_head_quic_rx_packet, "quic_rx_packet", sizeof(struct quic_rx_p
DECLARE_POOL(pool_head_quic_tx_packet, "quic_tx_packet", sizeof(struct quic_tx_packet));
DECLARE_STATIC_POOL(pool_head_quic_rx_crypto_frm, "quic_rx_crypto_frm", sizeof(struct quic_rx_crypto_frm));
DECLARE_STATIC_POOL(pool_head_quic_crypto_buf, "quic_crypto_buf", sizeof(struct quic_crypto_buf));
DECLARE_STATIC_POOL(pool_head_quic_cstream, "quic_cstream", sizeof(struct quic_cstream));
DECLARE_POOL(pool_head_quic_frame, "quic_frame", sizeof(struct quic_frame));
DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng", sizeof(struct quic_arng_node));
@ -4396,6 +4397,55 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
return t;
}
/* Release the memory allocated for <cs> CRYPTO stream */
void quic_cstream_free(struct quic_cstream *cs)
{
if (!cs) {
/* This is the case for ORTT encryption level */
return;
}
qc_stream_desc_release(cs->desc);
pool_free(pool_head_quic_cstream, cs);
}
/* Allocate a new QUIC stream for <qc>.
* Return it if succeeded, NULL if not.
*/
struct quic_cstream *quic_cstream_new(struct quic_conn *qc)
{
struct quic_cstream *cs, *ret_cs = NULL;
TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
cs = pool_alloc(pool_head_quic_cstream);
if (!cs) {
TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
goto leave;
}
cs->rx.offset = 0;
cs->rx.ncbuf = NCBUF_NULL;
cs->rx.offset = 0;
cs->tx.offset = 0;
cs->tx.sent_offset = 0;
cs->tx.buf = BUF_NULL;
cs->desc = qc_stream_desc_new((uint64_t)-1, -1, cs, qc);
if (!cs->desc) {
TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
goto err;
}
ret_cs = cs;
leave:
TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
return ret_cs;
err:
pool_free(pool_head_quic_cstream, cs);
goto leave;
}
/* Uninitialize <qel> QUIC encryption level. Never fails. */
static void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel)
{
@ -4410,6 +4460,7 @@ static void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_lev
}
}
ha_free(&qel->tx.crypto.bufs);
quic_cstream_free(qel->cstream);
TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
}
@ -4453,6 +4504,14 @@ static int quic_conn_enc_level_init(struct quic_conn *qc,
qel->tx.crypto.sz = 0;
qel->tx.crypto.offset = 0;
/* No CRYPTO data for early data TLS encryption level */
if (level == QUIC_TLS_ENC_LEVEL_EARLY_DATA)
qel->cstream = NULL;
else {
qel->cstream = quic_cstream_new(qc);
if (!qel->cstream)
goto err;
}
ret = 1;
leave:

View File

@ -18,7 +18,8 @@ DECLARE_STATIC_POOL(pool_head_quic_stream_buf, "qc_stream_buf",
/* Allocate a new stream descriptor with id <id>. The caller is responsible to
* store the stream in the appropriate tree.
* store the stream in the appropriate tree. -1 special value must be used for
* a CRYPTO data stream, the type being ignored.
*
* Returns the newly allocated instance on success or else NULL.
*/
@ -31,9 +32,14 @@ struct qc_stream_desc *qc_stream_desc_new(uint64_t id, enum qcs_type type, void
if (!stream)
return NULL;
stream->by_id.key = id;
eb64_insert(&qc->streams_by_id, &stream->by_id);
qc->rx.strms[type].nb_streams++;
if (id == (uint64_t)-1) {
stream->by_id.key = (uint64_t)-1;
}
else {
stream->by_id.key = id;
eb64_insert(&qc->streams_by_id, &stream->by_id);
qc->rx.strms[type].nb_streams++;
}
stream->qc = qc;
stream->buf = NULL;
@ -195,7 +201,8 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing)
qc_release_frm(qc, frm);
}
eb64_delete(&stream->by_id);
if (stream->by_id.key != (uint64_t)-1)
eb64_delete(&stream->by_id);
pool_free(pool_head_quic_stream_desc, stream);
}