QUIC CFQ: Unreliable transmission for PATH_RESPONSE
authorHugo Landau <hlandau@openssl.org>
Tue, 25 Jul 2023 10:32:24 +0000 (11:32 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 8 Aug 2023 13:33:42 +0000 (14:33 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21547)

include/internal/quic_cfq.h
ssl/quic/quic_cfq.c
ssl/quic/quic_channel.c
ssl/quic/quic_rx_depack.c
test/quic_cfq_test.c
test/quic_fifd_test.c
test/quic_txp_test.c

index 6ea69c22a177b49b63145a80553a2c2d920d4af5..2256f2f0a3e636290c5c7d970c3c75cca10e3cb4 100644 (file)
@@ -38,6 +38,9 @@ struct quic_cfq_item_st {
 #  define QUIC_CFQ_STATE_NEW      0
 #  define QUIC_CFQ_STATE_TX       1
 
+/* If set, do not retransmit on loss */
+#define QUIC_CFQ_ITEM_FLAG_UNRELIABLE   (1U << 0)
+
 /* Returns the frame type of a CFQ item. */
 uint64_t ossl_quic_cfq_item_get_frame_type(const QUIC_CFQ_ITEM *item);
 
@@ -53,6 +56,9 @@ int ossl_quic_cfq_item_get_state(const QUIC_CFQ_ITEM *item);
 /* Returns the PN space for the CFQ item. */
 uint32_t ossl_quic_cfq_item_get_pn_space(const QUIC_CFQ_ITEM *item);
 
+/* Returns 1 if this is an unreliable frame. */
+int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item);
+
 /*
  * QUIC Control Frame Queue
  * ========================
@@ -88,6 +94,8 @@ void ossl_quic_cfq_free(QUIC_CFQ *cfq);
  * The frame type is duplicated as the frame_type argument here, even though it
  * is also encoded into the buffer. This allows the caller to determine the
  * frame type if desired without having to decode the frame.
+ *
+ * flags is zero or more QUIC_CFQ_ITEM_FLAG values.
  */
 typedef void (cfq_free_cb)(unsigned char *buf, size_t buf_len, void *arg);
 
@@ -95,6 +103,7 @@ QUIC_CFQ_ITEM *ossl_quic_cfq_add_frame(QUIC_CFQ            *cfq,
                                        uint32_t             priority,
                                        uint32_t             pn_space,
                                        uint64_t             frame_type,
+                                       uint32_t             flags,
                                        const unsigned char *encoded,
                                        size_t               encoded_len,
                                        cfq_free_cb         *free_cb,
index 54acbedce8810ac6df6c8f7977e11c61b410cc92..25ac36e348274eee0ba1cc0403f206a212e14ffe 100644 (file)
@@ -19,7 +19,7 @@ struct quic_cfq_item_ex_st {
     void                   *free_cb_arg;
     uint64_t                frame_type;
     size_t                  encoded_len;
-    uint32_t                priority, pn_space;
+    uint32_t                priority, pn_space, flags;
     int                     state;
 };
 
@@ -58,6 +58,13 @@ uint32_t ossl_quic_cfq_item_get_pn_space(const QUIC_CFQ_ITEM *item)
     return ex->pn_space;
 }
 
+int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item)
+{
+    QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
+
+    return (ex->flags & QUIC_CFQ_ITEM_FLAG_UNRELIABLE) != 0;
+}
+
 typedef struct quic_cfq_item_list_st {
     QUIC_CFQ_ITEM_EX *head, *tail;
 } QUIC_CFQ_ITEM_LIST;
@@ -223,6 +230,7 @@ QUIC_CFQ_ITEM *ossl_quic_cfq_add_frame(QUIC_CFQ            *cfq,
                                        uint32_t             priority,
                                        uint32_t             pn_space,
                                        uint64_t             frame_type,
+                                       uint32_t             flags,
                                        const unsigned char *encoded,
                                        size_t               encoded_len,
                                        cfq_free_cb         *free_cb,
@@ -242,6 +250,7 @@ QUIC_CFQ_ITEM *ossl_quic_cfq_add_frame(QUIC_CFQ            *cfq,
     item->free_cb_arg   = free_cb_arg;
 
     item->state = QUIC_CFQ_STATE_NEW;
+    item->flags = flags;
     list_remove(&cfq->free_list, item);
     list_insert_sorted(&cfq->new_list, item, compare);
     return &item->public;
@@ -270,6 +279,11 @@ void ossl_quic_cfq_mark_lost(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item,
 {
     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
 
+    if (ossl_quic_cfq_item_is_unreliable(item)) {
+        ossl_quic_cfq_release(cfq, item);
+        return;
+    }
+
     switch (ex->state) {
     case QUIC_CFQ_STATE_NEW:
         if (priority != UINT32_MAX && priority != ex->priority) {
index 091b94c09910f5802fa6f9ea3167ee2faae6f1f0..220523d587a7aae847fe313f52e8d5027bf5ff17 100644 (file)
@@ -2713,7 +2713,7 @@ static int ch_enqueue_retire_conn_id(QUIC_CHANNEL *ch, uint64_t seq_num)
         goto err;
 
     if (ossl_quic_cfq_add_frame(ch->cfq, 1, QUIC_PN_SPACE_APP,
-                                OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID,
+                                OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID, 0,
                                 (unsigned char *)buf_mem->data, l,
                                 free_frame_data, NULL) == NULL)
         goto err;
index 74d84a177550233507033b8945da2591119dc1e4..d58efb2af34e1573837b9c454fbce70892d0b1cb 100644 (file)
@@ -920,6 +920,7 @@ static int depack_do_frame_path_challenge(PACKET *pkt,
 
     if (!ossl_quic_cfq_add_frame(ch->cfq, 0, QUIC_PN_SPACE_APP,
                                  OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
+                                 QUIC_CFQ_ITEM_FLAG_UNRELIABLE,
                                  encoded, encoded_len,
                                  free_path_response, NULL))
         goto err;
index dbc4eb4b7ee9d3acae9f7d391bf93772e47a94a6..44705b3507735cb7764a5e7f99664174f5f4e20c 100644 (file)
@@ -114,7 +114,7 @@ static int test_cfq(void)
     for (i = 0; i < OSSL_NELEM(ref_buf); ++i) {
         if (!TEST_ptr(item = ossl_quic_cfq_add_frame(cfq, ref_priority[i],
                                                      ref_pn_space[i],
-                                                     ref_frame_type[i],
+                                                     ref_frame_type[i], 0,
                                                      ref_buf + i,
                                                      1,
                                                      free_cb,
index bb0cd77105c7ccbdca4e2f7e8fed63d523eee9a9..de3188a929541a230539ac2b93192407d502543a 100644 (file)
@@ -162,7 +162,7 @@ static int test_generic(INFO *info, int kind)
     cfq_freed = 0;
     if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(info->cfq, 10,
                                                      pn_space,
-                                                     OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,
+                                                     OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 0,
                                                      placeholder_data,
                                                      sizeof(placeholder_data),
                                                      cfq_free_cb_, NULL))
index fa311bfa09629e4769a90d1f62760d30d7c66b6f..d92fd265185891b9d4e4108559747349d8959353 100644 (file)
@@ -421,7 +421,7 @@ static int schedule_cfq_new_conn_id(struct helper *h)
 
     if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(h->args.cfq, 1,
                                                      QUIC_PN_SPACE_APP,
-                                                     OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,
+                                                     OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 0,
                                                      (unsigned char *)buf_mem->data, l,
                                                      free_buf_mem,
                                                      buf_mem)))
@@ -497,7 +497,7 @@ static int schedule_cfq_new_token(struct helper *h)
 
     if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(h->args.cfq, 1,
                                                      QUIC_PN_SPACE_APP,
-                                                     OSSL_QUIC_FRAME_TYPE_NEW_TOKEN,
+                                                     OSSL_QUIC_FRAME_TYPE_NEW_TOKEN, 0,
                                                      (unsigned char *)buf_mem->data, l,
                                                      free_buf_mem,
                                                      buf_mem)))