Skip to content

Commit

Permalink
Add deferred datagram limit to QUIC Record Layer RX
Browse files Browse the repository at this point in the history
Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Richard Levitte <[email protected]>
(Merged from openssl#19251)
  • Loading branch information
hlandau committed Sep 22, 2022
1 parent 82d46d1 commit 0ff9813
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
6 changes: 6 additions & 0 deletions include/internal/quic_demux.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ struct quic_urxe_st {
* function was not provided).
*/
OSSL_TIME time;

/*
* Used by the QRX to mark whether a datagram has been deferred. Used by the
* QRX only; not used by the demuxer.
*/
char deferred;
};

/* Accessors for URXE buffer. */
Expand Down
14 changes: 10 additions & 4 deletions include/internal/quic_record_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ typedef struct ossl_qrx_args_st {
/* Length of connection IDs used in short-header packets in bytes. */
size_t short_conn_id_len;

/*
* Maximum number of deferred datagrams buffered at any one time.
* Suggested value: 32.
*/
size_t max_deferred;

/* Initial reference PN used for RX. */
QUIC_PN init_largest_pn[QUIC_PN_SPACE_NUM];

Expand Down Expand Up @@ -160,8 +166,8 @@ int ossl_qrx_remove_dst_conn_id(OSSL_QRX *qrx,
* as do calls made after a corresponding call to ossl_qrx_discard_enc_level for
* that EL. The secret for a EL cannot be changed after it is set because QUIC
* has no facility for introducing additional key material after an EL is setup.
* QUIC key updates are managed automatically by the QRX and do not require user
* intervention.
* QUIC key updates are managed semi-automatically by the QRX but do require
* some caller handling (see below).
*
* md is for internal use and should be NULL.
*
Expand Down Expand Up @@ -258,7 +264,7 @@ void ossl_qrx_release_pkt(OSSL_QRX *qrx, void *handle);
int ossl_qrx_processed_read_pending(OSSL_QRX *qrx);

/*
* Returns 1 if there arre any unprocessed (i.e. not yet decrypted) packets
* Returns 1 if there are any unprocessed (i.e. not yet decrypted) packets
* waiting to be processed by the QRX. These may or may not result in
* successfully decrypted packets once processed. This indicates whether
* unprocessed data is buffered by the QRX, not whether any data is available in
Expand Down Expand Up @@ -434,7 +440,7 @@ int ossl_qrx_set_early_validation_cb(OSSL_QRX *qrx,
* current substate of the PROVISIONED state is to the DISCARDED state, which is
* the terminal state.
*
* Note that non-1RTT ELs cannot undergo key update, therefore a non-1RT EL is
* Note that non-1RTT ELs cannot undergo key update, therefore a non-1RTT EL is
* always in the NORMAL substate if it is in the PROVISIONED state.
*/

Expand Down
24 changes: 21 additions & 3 deletions ssl/quic/quic_record_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ struct ossl_qrx_st {
/* Length of connection IDs used in short-header packets in bytes. */
size_t short_conn_id_len;

/* Maximum number of deferred datagrams buffered at any one time. */
size_t max_deferred;

/* Current count of deferred datagrams. */
size_t num_deferred;

/*
* List of URXEs which are filled with received encrypted data.
* These are returned to the DEMUX's free list as they are processed.
Expand Down Expand Up @@ -176,7 +182,7 @@ OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args)
OSSL_QRX *qrx;
size_t i;

if (args->demux == NULL)
if (args->demux == NULL || args->max_deferred == 0)
return 0;

qrx = OPENSSL_zalloc(sizeof(OSSL_QRX));
Expand All @@ -191,6 +197,7 @@ OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args)
qrx->demux = args->demux;
qrx->short_conn_id_len = args->short_conn_id_len;
qrx->init_key_phase_bit = args->init_key_phase_bit;
qrx->max_deferred = args->max_deferred;
return qrx;
}

Expand Down Expand Up @@ -245,6 +252,7 @@ static void qrx_on_rx(QUIC_URXE *urxe, void *arg)
/* Initialize our own fields inside the URXE and add to the pending list. */
urxe->processed = 0;
urxe->hpr_removed = 0;
urxe->deferred = 0;
ossl_quic_urxe_insert_tail(&qrx->urx_pending, urxe);
}

Expand Down Expand Up @@ -1042,10 +1050,20 @@ static int qrx_process_one_urxe(OSSL_QRX *qrx, QUIC_URXE *e)
* either the free or deferred list.
*/
ossl_quic_urxe_remove(&qrx->urx_pending, e);
if (was_deferred > 0)
if (was_deferred > 0 &&
(e->deferred || qrx->num_deferred < qrx->max_deferred)) {
ossl_quic_urxe_insert_tail(&qrx->urx_deferred, e);
else
if (!e->deferred) {
e->deferred = 1;
++qrx->num_deferred;
}
} else {
if (e->deferred) {
e->deferred = 0;
--qrx->num_deferred;
}
ossl_quic_demux_release_urxe(qrx->demux, e);
}

return 1;
}
Expand Down
3 changes: 2 additions & 1 deletion test/quic_record_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,8 @@ static int rx_state_ensure(struct rx_state *s)
NULL)))
return 0;

s->args.demux = s->demux;
s->args.demux = s->demux;
s->args.max_deferred = 32;

if (s->qrx == NULL
&& !TEST_ptr(s->qrx = ossl_qrx_new(&s->args)))
Expand Down

0 comments on commit 0ff9813

Please sign in to comment.