summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-04-18 19:30:55 +0100
committerHugo Landau <hlandau@openssl.org>2023-05-12 14:47:12 +0100
commita6b6ea17376572e3c0227b98f21dedc48215aa9a (patch)
treeab532445df770379e066e5a3e46ed588e7dba7e6 /ssl
parent5bd9ddd86e714705840215b8d2bbb0aedc598e96 (diff)
QUIC TXP/CHANNEL: Generate MAX_STREAMS using RXFC
Though the RXFC was designed for stream flow control, its logic is generic enough to use to control MAX_STREAMS generation. Control of when _we_ can open streams is already done in a bespoke fashion and doesn't use a TXFC, however (see ossl_quic_stream_map_update_state). Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20765)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_channel.c49
-rw-r--r--ssl/quic/quic_channel_local.h6
-rw-r--r--ssl/quic/quic_txp.c37
3 files changed, 61 insertions, 31 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index 3e099e9d93..c689166805 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -111,6 +111,8 @@ static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid)
#define DEFAULT_INIT_STREAM_RXFC_WND (2 * 1024 * 1024)
#define DEFAULT_STREAM_RXFC_MAX_WND_MUL 5
+#define DEFAULT_INIT_CONN_MAX_STREAMS 100
+
static int ch_init(QUIC_CHANNEL *ch)
{
OSSL_QUIC_TX_PACKETISER_ARGS txp_args = {0};
@@ -160,6 +162,16 @@ static int ch_init(QUIC_CHANNEL *ch)
get_time, ch))
goto err;
+ if (!ossl_quic_rxfc_init_for_stream_count(&ch->max_streams_bidi_rxfc,
+ DEFAULT_INIT_CONN_MAX_STREAMS,
+ get_time, ch))
+ goto err;
+
+ if (!ossl_quic_rxfc_init_for_stream_count(&ch->max_streams_uni_rxfc,
+ DEFAULT_INIT_CONN_MAX_STREAMS,
+ get_time, ch))
+ goto err;
+
if (!ossl_statm_init(&ch->statm))
goto err;
@@ -172,25 +184,29 @@ static int ch_init(QUIC_CHANNEL *ch)
ch->cc_method, ch->cc_data)) == NULL)
goto err;
- if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch))
+ if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch,
+ &ch->max_streams_bidi_rxfc,
+ &ch->max_streams_uni_rxfc))
goto err;
ch->have_qsm = 1;
/* We use a zero-length SCID. */
- txp_args.cur_dcid = ch->init_dcid;
- txp_args.ack_delay_exponent = 3;
- txp_args.qtx = ch->qtx;
- txp_args.txpim = ch->txpim;
- txp_args.cfq = ch->cfq;
- txp_args.ackm = ch->ackm;
- txp_args.qsm = &ch->qsm;
- txp_args.conn_txfc = &ch->conn_txfc;
- txp_args.conn_rxfc = &ch->conn_rxfc;
- txp_args.cc_method = ch->cc_method;
- txp_args.cc_data = ch->cc_data;
- txp_args.now = get_time;
- txp_args.now_arg = ch;
+ txp_args.cur_dcid = ch->init_dcid;
+ txp_args.ack_delay_exponent = 3;
+ txp_args.qtx = ch->qtx;
+ txp_args.txpim = ch->txpim;
+ txp_args.cfq = ch->cfq;
+ txp_args.ackm = ch->ackm;
+ txp_args.qsm = &ch->qsm;
+ txp_args.conn_txfc = &ch->conn_txfc;
+ txp_args.conn_rxfc = &ch->conn_rxfc;
+ txp_args.max_streams_bidi_rxfc = &ch->max_streams_bidi_rxfc;
+ txp_args.max_streams_uni_rxfc = &ch->max_streams_uni_rxfc;
+ txp_args.cc_method = ch->cc_method;
+ txp_args.cc_data = ch->cc_data;
+ txp_args.now = get_time;
+ txp_args.now_arg = ch;
for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {
ch->crypto_send[pn_space] = ossl_quic_sstream_new(INIT_CRYPTO_BUF_LEN);
if (ch->crypto_send[pn_space] == NULL)
@@ -1215,13 +1231,12 @@ static int ch_generate_transport_params(QUIC_CHANNEL *ch)
ch->tx_init_max_stream_data_uni))
goto err;
- /* TODO(QUIC): MAX_STREAMS modelling */
if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAMS_BIDI,
- ch->is_server ? 100 : 100))
+ ossl_quic_rxfc_get_cwm(&ch->max_streams_bidi_rxfc)))
goto err;
if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_STREAMS_UNI,
- 100))
+ ossl_quic_rxfc_get_cwm(&ch->max_streams_uni_rxfc)))
goto err;
if (!WPACKET_get_total_written(&wpkt, &buf_len))
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
index f13d0118ee..379528b516 100644
--- a/ssl/quic/quic_channel_local.h
+++ b/ssl/quic/quic_channel_local.h
@@ -69,9 +69,13 @@ struct quic_channel_st {
OSSL_QUIC_TX_PACKETISER *txp;
QUIC_TXPIM *txpim;
QUIC_CFQ *cfq;
- /* Connection level FC. */
+ /*
+ * Connection level FC. The stream_count RXFCs is used to manage
+ * MAX_STREAMS signalling.
+ */
QUIC_TXFC conn_txfc;
QUIC_RXFC conn_rxfc;
+ QUIC_RXFC max_streams_bidi_rxfc, max_streams_uni_rxfc;
QUIC_STREAM_MAP qsm;
OSSL_STATM statm;
OSSL_CC_DATA *cc_data;
diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c
index 97a88c3ff1..10a1a5f18e 100644
--- a/ssl/quic/quic_txp.c
+++ b/ssl/quic/quic_txp.c
@@ -351,7 +351,9 @@ OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETIS
|| args->ackm == NULL
|| args->qsm == NULL
|| args->conn_txfc == NULL
- || args->conn_rxfc == NULL) {
+ || args->conn_rxfc == NULL
+ || args->max_streams_bidi_rxfc == NULL
+ || args->max_streams_uni_rxfc == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
@@ -807,8 +809,13 @@ static int txp_el_pending(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level,
return 1;
/* Do we want to produce a MAX_STREAMS frame? */
- if (a.allow_conn_fc && (txp->want_max_streams_bidi
- || txp->want_max_streams_uni))
+ if (a.allow_conn_fc
+ && (txp->want_max_streams_bidi
+ || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc,
+ 0)
+ || txp->want_max_streams_uni
+ || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc,
+ 0)))
return 1;
/* Do we want to produce a HANDSHAKE_DONE frame? */
@@ -1927,15 +1934,13 @@ static int txp_generate_for_el_actual(OSSL_QUIC_TX_PACKETISER *txp,
}
/* MAX_STREAMS_BIDI (Regenerate) */
- /*
- * TODO(STREAMS): Once we support multiple streams, add stream count FC
- * and plug this in.
- */
if (a.allow_conn_fc
- && txp->want_max_streams_bidi
+ && (txp->want_max_streams_bidi
+ || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 0))
&& tx_helper_get_space_left(&h) >= MIN_FRAME_SIZE_MAX_STREAMS_BIDI) {
WPACKET *wpkt = tx_helper_begin(&h);
- uint64_t max_streams = 1; /* TODO */
+ uint64_t max_streams
+ = ossl_quic_rxfc_get_cwm(txp->args.max_streams_bidi_rxfc);
if (wpkt == NULL)
goto fatal_err;
@@ -1956,10 +1961,12 @@ static int txp_generate_for_el_actual(OSSL_QUIC_TX_PACKETISER *txp,
/* MAX_STREAMS_UNI (Regenerate) */
if (a.allow_conn_fc
- && txp->want_max_streams_uni
+ && (txp->want_max_streams_uni
+ || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 0))
&& tx_helper_get_space_left(&h) >= MIN_FRAME_SIZE_MAX_STREAMS_UNI) {
WPACKET *wpkt = tx_helper_begin(&h);
- uint64_t max_streams = 0; /* TODO */
+ uint64_t max_streams
+ = ossl_quic_rxfc_get_cwm(txp->args.max_streams_uni_rxfc);
if (wpkt == NULL)
goto fatal_err;
@@ -2209,11 +2216,15 @@ static int txp_generate_for_el_actual(OSSL_QUIC_TX_PACKETISER *txp,
ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 1);
}
- if (tpkt->had_max_streams_bidi_frame)
+ if (tpkt->had_max_streams_bidi_frame) {
txp->want_max_streams_bidi = 0;
+ ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 1);
+ }
- if (tpkt->had_max_streams_uni_frame)
+ if (tpkt->had_max_streams_uni_frame) {
txp->want_max_streams_uni = 0;
+ ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 1);
+ }
if (tpkt->had_ack_frame)
txp->want_ack &= ~(1UL << pn_space);