summaryrefslogtreecommitdiff
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
commit90cecc406f58b229ffa9c8e8473eaa6924c4a5d5 (patch)
treec02a56da8c5bccb7b033be06e55ec825773ed6ca
parenta6b6ea17376572e3c0227b98f21dedc48215aa9a (diff)
downloadopenssl-new-90cecc406f58b229ffa9c8e8473eaa6924c4a5d5.tar.gz
QUIC RXDP/QSM: Enforce MAX_STREAMS
Also use accept queue popping by the application as the retirement event, i.e., as the cue to increase the limit. 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_stream_map.h12
-rw-r--r--ssl/quic/quic_impl.c5
-rw-r--r--ssl/quic/quic_rx_depack.c27
-rw-r--r--ssl/quic/quic_stream_map.c21
-rw-r--r--test/quic_txp_test.c4
5 files changed, 62 insertions, 7 deletions
diff --git a/include/internal/quic_stream_map.h b/include/internal/quic_stream_map.h
index 78ec703fbc..81312e8b4a 100644
--- a/include/internal/quic_stream_map.h
+++ b/include/internal/quic_stream_map.h
@@ -138,6 +138,8 @@ typedef struct quic_stream_map_st {
QUIC_STREAM *rr_cur;
uint64_t (*get_stream_limit_cb)(int uni, void *arg);
void *get_stream_limit_cb_arg;
+ QUIC_RXFC *max_streams_bidi_rxfc;
+ QUIC_RXFC *max_streams_uni_rxfc;
} QUIC_STREAM_MAP;
/*
@@ -155,7 +157,9 @@ typedef struct quic_stream_map_st {
*/
int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
uint64_t (*get_stream_limit_cb)(int uni, void *arg),
- void *get_stream_limit_cb_arg);
+ void *get_stream_limit_cb_arg,
+ QUIC_RXFC *max_streams_bidi_rxfc,
+ QUIC_RXFC *max_streams_uni_rxfc);
/*
* Any streams still in the map will be released as though
@@ -246,12 +250,14 @@ void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm);
/*
- * Removes a stream from the accept queue.
+ * Removes a stream from the accept queue. rtt is the estimated connection RTT.
+ * The stream is retired for the purposes of MAX_STREAMS RXFC.
*
* Precondition: s is in the accept queue.
*/
void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
- QUIC_STREAM *s);
+ QUIC_STREAM *s,
+ OSSL_TIME rtt);
/* Returns the length of the accept queue. */
size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm);
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index 98f96a7703..e3402e5c65 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -2231,6 +2231,7 @@ SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags)
QUIC_STREAM_MAP *qsm;
QUIC_STREAM *qs;
QUIC_XSO *xso;
+ OSSL_RTT_INFO rtt_info;
if (!expect_quic_conn_only(s, &ctx))
return NULL;
@@ -2270,7 +2271,9 @@ SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags)
if (xso == NULL)
goto out;
- ossl_quic_stream_map_remove_from_accept_queue(qsm, qs);
+ ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(ctx.qc->ch), &rtt_info);
+ ossl_quic_stream_map_remove_from_accept_queue(qsm, qs,
+ rtt_info.smoothed_rtt);
new_s = &xso->ssl;
/* Calling this function inhibits default XSO autocreation. */
diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c
index c49a13fe89..a81f47d6d9 100644
--- a/ssl/quic/quic_rx_depack.c
+++ b/ssl/quic/quic_rx_depack.c
@@ -256,6 +256,7 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
if (stream == NULL) {
uint64_t peer_role, stream_ordinal;
uint64_t *p_next_ordinal_local, *p_next_ordinal_remote;
+ QUIC_RXFC *max_streams_fc;
int is_uni;
/*
@@ -299,6 +300,32 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
? &ch->next_remote_stream_ordinal_uni
: &ch->next_remote_stream_ordinal_bidi;
+ /* Check this isn't violating stream count flow control. */
+ max_streams_fc = is_uni
+ ? &ch->max_streams_uni_rxfc
+ : &ch->max_streams_bidi_rxfc;
+
+ if (!ossl_quic_rxfc_on_rx_stream_frame(max_streams_fc,
+ stream_ordinal + 1,
+ /*is_fin=*/0)) {
+ ossl_quic_channel_raise_protocol_error(ch,
+ QUIC_ERR_INTERNAL_ERROR,
+ frame_type,
+ "internal error (stream count RXFC)");
+ return 0;
+ }
+
+ if (ossl_quic_rxfc_get_error(max_streams_fc, 0) != QUIC_ERR_NO_ERROR) {
+ ossl_quic_channel_raise_protocol_error(ch, QUIC_ERR_STREAM_LIMIT_ERROR,
+ frame_type,
+ "exceeded maximum allowed streams");
+ return 0;
+ }
+
+ /*
+ * Create the named stream and any streams coming before it yet to
+ * be created.
+ */
while (*p_next_ordinal_remote <= stream_ordinal) {
uint64_t stream_id = (*p_next_ordinal_remote << 2) |
(frame_data.stream_id
diff --git a/ssl/quic/quic_stream_map.c b/ssl/quic/quic_stream_map.c
index 06bf1cfa34..a9c616ea9f 100644
--- a/ssl/quic/quic_stream_map.c
+++ b/ssl/quic/quic_stream_map.c
@@ -102,7 +102,9 @@ static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)
int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
uint64_t (*get_stream_limit_cb)(int uni, void *arg),
- void *get_stream_limit_cb_arg)
+ void *get_stream_limit_cb_arg,
+ QUIC_RXFC *max_streams_bidi_rxfc,
+ QUIC_RXFC *max_streams_uni_rxfc)
{
qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);
qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;
@@ -114,6 +116,8 @@ int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
qsm->get_stream_limit_cb = get_stream_limit_cb;
qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;
+ qsm->max_streams_bidi_rxfc = max_streams_bidi_rxfc;
+ qsm->max_streams_uni_rxfc = max_streams_uni_rxfc;
return 1;
}
@@ -294,11 +298,24 @@ void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
++qsm->num_accept;
}
+static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
+{
+ return ossl_quic_stream_is_bidi(s)
+ ? qsm->max_streams_bidi_rxfc
+ : qsm->max_streams_uni_rxfc;
+}
+
void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
- QUIC_STREAM *s)
+ QUIC_STREAM *s,
+ OSSL_TIME rtt)
{
+ QUIC_RXFC *max_streams_rxfc;
+
list_remove(&qsm->accept_list, &s->accept_node);
--qsm->num_accept;
+
+ if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL)
+ ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt);
}
size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm)
diff --git a/test/quic_txp_test.c b/test/quic_txp_test.c
index dd85bb5692..dca8c71398 100644
--- a/test/quic_txp_test.c
+++ b/test/quic_txp_test.c
@@ -174,7 +174,9 @@ static int helper_init(struct helper *h)
h->cc_data)))
goto err;
- if (!TEST_true(ossl_quic_stream_map_init(&h->qsm, NULL, NULL)))
+ if (!TEST_true(ossl_quic_stream_map_init(&h->qsm, NULL, NULL,
+ &h->max_streams_bidi_rxfc,
+ &h->max_streams_uni_rxfc)))
goto err;
h->have_qsm = 1;