]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add deferred datagram limit to QUIC Record Layer RX
authorHugo Landau <hlandau@openssl.org>
Tue, 20 Sep 2022 19:40:36 +0000 (20:40 +0100)
committerHugo Landau <hlandau@openssl.org>
Thu, 22 Sep 2022 09:01:35 +0000 (10:01 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19251)

include/internal/quic_demux.h
include/internal/quic_record_rx.h
ssl/quic/quic_record_rx.c
test/quic_record_test.c

index 9912de7a0033a6d53a1bb70e7c95b0451899bc1e..d6d3f35bf897b0a63176b176afcd2585a9a1eb9b 100644 (file)
@@ -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. */
index c22fc089c71c2b10e37d8506e1ac3d67f017b1f6..53b7b7f458e02fab7294776cb13143153697595b 100644 (file)
@@ -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];
 
@@ -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.
  *
@@ -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
@@ -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.
  */
 
index c0bbb5f504a42547caabd8ebd6a9468c55a8f79f..ee552e83c501daad0651639549ae137e4cff8876 100644 (file)
@@ -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.
@@ -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));
@@ -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;
 }
 
@@ -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);
 }
 
@@ -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;
 }
index 523d8ec27b04bef5b4bebbc48b94ee9e9f501618..a4cafb8c21ae641f8685b8ea4da1ced478aac0ca 100644 (file)
@@ -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)))