diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-04-18 19:30:55 +0100 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-05-12 14:47:12 +0100 |
commit | a6b6ea17376572e3c0227b98f21dedc48215aa9a (patch) | |
tree | ab532445df770379e066e5a3e46ed588e7dba7e6 | |
parent | 5bd9ddd86e714705840215b8d2bbb0aedc598e96 (diff) | |
download | openssl-new-a6b6ea17376572e3c0227b98f21dedc48215aa9a.tar.gz |
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)
-rw-r--r-- | include/internal/quic_txp.h | 2 | ||||
-rw-r--r-- | ssl/quic/quic_channel.c | 49 | ||||
-rw-r--r-- | ssl/quic/quic_channel_local.h | 6 | ||||
-rw-r--r-- | ssl/quic/quic_txp.c | 37 | ||||
-rw-r--r-- | test/quic_txp_test.c | 30 |
5 files changed, 85 insertions, 39 deletions
diff --git a/include/internal/quic_txp.h b/include/internal/quic_txp.h index fb553f97e5..0e4fd5cc49 100644 --- a/include/internal/quic_txp.h +++ b/include/internal/quic_txp.h @@ -42,6 +42,8 @@ typedef struct ossl_quic_tx_packetiser_args_st { QUIC_STREAM_MAP *qsm; /* QUIC Streams Map */ QUIC_TXFC *conn_txfc; /* QUIC Connection-Level TX Flow Controller */ QUIC_RXFC *conn_rxfc; /* QUIC Connection-Level RX Flow Controller */ + QUIC_RXFC *max_streams_bidi_rxfc; /* QUIC RXFC for MAX_STREAMS generation */ + QUIC_RXFC *max_streams_uni_rxfc; const OSSL_CC_METHOD *cc_method; /* QUIC Congestion Controller */ OSSL_CC_DATA *cc_data; /* QUIC Congestion Controller Instance */ OSSL_TIME (*now)(void *arg); /* Callback to get current time. */ 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); diff --git a/test/quic_txp_test.c b/test/quic_txp_test.c index 265c23fabc..dd85bb5692 100644 --- a/test/quic_txp_test.c +++ b/test/quic_txp_test.c @@ -47,6 +47,7 @@ struct helper { BIO *bio1, *bio2; QUIC_TXFC conn_txfc; QUIC_RXFC conn_rxfc, stream_rxfc; + QUIC_RXFC max_streams_bidi_rxfc, max_streams_uni_rxfc; OSSL_STATM statm; OSSL_CC_DATA *cc_data; const OSSL_CC_METHOD *cc_method; @@ -147,6 +148,17 @@ static int helper_init(struct helper *h) NULL))) goto err; + if (!TEST_true(ossl_quic_rxfc_init(&h->max_streams_bidi_rxfc, NULL, + 100, 100, + fake_now, + NULL))) + goto err; + + if (!TEST_true(ossl_quic_rxfc_init(&h->max_streams_uni_rxfc, NULL, + 100, 100, + fake_now, + NULL))) + if (!TEST_true(ossl_statm_init(&h->statm))) goto err; @@ -171,14 +183,16 @@ static int helper_init(struct helper *h) if (!TEST_ptr(h->args.crypto[i] = ossl_quic_sstream_new(4096))) goto err; - h->args.cur_scid = scid_1; - h->args.cur_dcid = dcid_1; - h->args.qsm = &h->qsm; - h->args.conn_txfc = &h->conn_txfc; - h->args.conn_rxfc = &h->conn_rxfc; - h->args.cc_method = h->cc_method; - h->args.cc_data = h->cc_data; - h->args.now = fake_now; + h->args.cur_scid = scid_1; + h->args.cur_dcid = dcid_1; + h->args.qsm = &h->qsm; + h->args.conn_txfc = &h->conn_txfc; + h->args.conn_rxfc = &h->conn_rxfc; + h->args.max_streams_bidi_rxfc = &h->max_streams_bidi_rxfc; + h->args.max_streams_uni_rxfc = &h->max_streams_uni_rxfc; + h->args.cc_method = h->cc_method; + h->args.cc_data = h->cc_data; + h->args.now = fake_now; if (!TEST_ptr(h->txp = ossl_quic_tx_packetiser_new(&h->args))) goto err; |