QUIC Stream Mapper: CSM-related changes, stream limits handling

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19703)
This commit is contained in:
Hugo Landau 2022-11-17 15:29:44 +00:00
parent 3a37c9235d
commit cbe7f586ad
3 changed files with 70 additions and 20 deletions

View File

@ -11,12 +11,14 @@
# define OSSL_INTERNAL_QUIC_STREAM_MAP_H
# pragma once
#include "internal/e_os.h"
#include "internal/time.h"
#include "internal/quic_types.h"
#include "internal/quic_stream.h"
#include "internal/quic_fc.h"
#include <openssl/lhash.h>
# include "internal/e_os.h"
# include "internal/time.h"
# include "internal/quic_types.h"
# include "internal/quic_stream.h"
# include "internal/quic_fc.h"
# include <openssl/lhash.h>
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Stream
@ -68,18 +70,23 @@ struct quic_stream_st {
unsigned int active : 1;
/*
* Has STOP_SENDING been requested? Note that this is not the same as
* want_stop_sending below, as a STOP_SENDING frame may already have been
* Has STOP_SENDING been requested (by us)? Note that this is not the same
* as want_stop_sending below, as a STOP_SENDING frame may already have been
* sent and fully acknowledged.
*/
unsigned int stop_sending : 1;
/*
* Has RESET_STREAM been requested? Works identically to STOP_SENDING for
* transmission purposes.
* Has RESET_STREAM been requested (by us)? Works identically to
* STOP_SENDING for transmission purposes.
*/
unsigned int reset_stream : 1;
/* Has our peer sent a STOP_SENDING frame? */
unsigned int peer_stop_sending : 1;
/* Has our peer sent a RESET_STREAM frame? */
unsigned int peer_reset_stream : 1;
/* Temporary flags used by TXP. */
unsigned int txp_sent_fc : 1;
unsigned int txp_sent_stop_sending : 1;
@ -91,6 +98,9 @@ struct quic_stream_st {
unsigned int want_max_stream_data : 1; /* used for regen only */
unsigned int want_stop_sending : 1; /* used for gen or regen */
unsigned int want_reset_stream : 1; /* used for gen or regen */
/* A FIN has been retired from the rstream buffer. */
unsigned int recv_fin_retired : 1;
};
/*
@ -121,9 +131,26 @@ typedef struct quic_stream_map_st {
QUIC_STREAM_LIST_NODE active_list;
size_t rr_stepping, rr_counter;
QUIC_STREAM *rr_cur;
uint64_t (*get_stream_limit_cb)(int uni, void *arg);
void *get_stream_limit_cb_arg;
} QUIC_STREAM_MAP;
int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm);
/*
* get_stream_limit is a callback which is called to retrieve the current stream
* limit for streams created by us. This mechanism is not used for
* peer-initiated streams. If a stream's stream ID is x, a stream is allowed if
* (x >> 2) < returned limit value; i.e., the returned value is exclusive.
*
* If uni is 1, get the limit for locally-initiated unidirectional streams, else
* get the limit for locally-initiated bidirectional streams.
*
* If the callback is NULL, stream limiting is not applied.
* Stream limiting is used to determine if frames can currently be produced for
* a stream.
*/
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);
/*
* Any streams still in the map will be released as though
@ -229,4 +256,6 @@ void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
*/
void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);
# endif
#endif

View File

@ -91,13 +91,18 @@ static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)
return 0;
}
int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm)
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)
{
qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);
qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;
qsm->rr_stepping = 1;
qsm->rr_counter = 0;
qsm->rr_cur = NULL;
qsm->get_stream_limit_cb = get_stream_limit_cb;
qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;
return 1;
}
@ -236,13 +241,29 @@ static int stream_has_data_to_send(QUIC_STREAM *s)
void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
{
int should_be_active
= (s->rstream != NULL
&& (s->want_max_stream_data
|| ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0)))
|| s->want_stop_sending
|| s->want_reset_stream
|| stream_has_data_to_send(s);
int should_be_active, allowed_by_stream_limit = 1;
if (qsm->get_stream_limit_cb != NULL
&& (s->type & QUIC_STREAM_INITIATOR_CLIENT) != 0) {
int uni = ((s->type & QUIC_STREAM_DIR_UNI) != 0);
uint64_t stream_limit, stream_ordinal = s->id >> 2;
stream_limit
= qsm->get_stream_limit_cb(uni, qsm->get_stream_limit_cb_arg);
allowed_by_stream_limit = (stream_ordinal < stream_limit);
}
should_be_active
= allowed_by_stream_limit
&& !s->peer_stop_sending
&& !s->peer_reset_stream
&& ((s->rstream != NULL
&& (s->want_max_stream_data
|| ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0)))
|| s->want_stop_sending
|| s->want_reset_stream
|| stream_has_data_to_send(s));
if (should_be_active)
stream_map_mark_active(qsm, s);

View File

@ -162,7 +162,7 @@ static int helper_init(struct helper *h)
h->cc_data)))
goto err;
if (!TEST_true(ossl_quic_stream_map_init(&h->qsm)))
if (!TEST_true(ossl_quic_stream_map_init(&h->qsm, NULL, NULL)))
goto err;
h->have_qsm = 1;