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 | 90cecc406f58b229ffa9c8e8473eaa6924c4a5d5 (patch) | |
tree | c02a56da8c5bccb7b033be06e55ec825773ed6ca | |
parent | a6b6ea17376572e3c0227b98f21dedc48215aa9a (diff) | |
download | openssl-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.h | 12 | ||||
-rw-r--r-- | ssl/quic/quic_impl.c | 5 | ||||
-rw-r--r-- | ssl/quic/quic_rx_depack.c | 27 | ||||
-rw-r--r-- | ssl/quic/quic_stream_map.c | 21 | ||||
-rw-r--r-- | test/quic_txp_test.c | 4 |
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; |