1 /* 2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/packet.h" 11 #include "internal/quic_cfq.h" 12 #include "internal/quic_wire.h" 13 #include "testutil.h" 14 15 static const unsigned char ref_buf[] = { 16 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 17 }; 18 19 static const uint32_t ref_priority[] = { 20 90, 80, 70, 60, 95, 40, 94, 20, 10, 0 21 }; 22 23 static const uint32_t ref_pn_space[] = { 24 QUIC_PN_SPACE_INITIAL, 25 QUIC_PN_SPACE_HANDSHAKE, 26 QUIC_PN_SPACE_HANDSHAKE, 27 QUIC_PN_SPACE_INITIAL, 28 QUIC_PN_SPACE_INITIAL, 29 QUIC_PN_SPACE_INITIAL, 30 QUIC_PN_SPACE_INITIAL, 31 QUIC_PN_SPACE_INITIAL, 32 QUIC_PN_SPACE_APP, 33 QUIC_PN_SPACE_APP, 34 }; 35 36 static const uint64_t ref_frame_type[] = { 37 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 38 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 39 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 40 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 41 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 42 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 43 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 44 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 45 OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 46 OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID, 47 }; 48 49 static const uint32_t expect[QUIC_PN_SPACE_NUM][11] = { 50 { 4, 6, 0, 3, 5, 7, UINT32_MAX }, 51 { 1, 2, UINT32_MAX }, 52 { 8, 9, UINT32_MAX }, 53 }; 54 55 static QUIC_CFQ_ITEM *items[QUIC_PN_SPACE_NUM][10]; 56 57 static unsigned char *g_free; 58 static size_t g_free_len; 59 60 static void free_cb(unsigned char *buf, size_t buf_len, void *arg) 61 { 62 g_free = buf; 63 g_free_len = buf_len; 64 } 65 66 static int check(QUIC_CFQ *cfq) 67 { 68 int testresult = 0; 69 QUIC_CFQ_ITEM *item; 70 size_t i; 71 uint32_t pn_space; 72 73 for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) 74 for (i = 0, item = ossl_quic_cfq_get_priority_head(cfq, pn_space);; 75 ++i, item = ossl_quic_cfq_item_get_priority_next(item, pn_space)) { 76 77 if (expect[pn_space][i] == UINT32_MAX) { 78 if (!TEST_ptr_null(item)) 79 goto err; 80 81 break; 82 } 83 84 items[pn_space][i] = item; 85 86 if (!TEST_ptr(item) 87 || !TEST_ptr_eq(ossl_quic_cfq_item_get_encoded(item), 88 ref_buf + expect[pn_space][i]) 89 || !TEST_int_eq(ossl_quic_cfq_item_get_pn_space(item), pn_space) 90 || !TEST_int_eq(ossl_quic_cfq_item_get_state(item), 91 QUIC_CFQ_STATE_NEW)) 92 goto err; 93 } 94 95 testresult = 1; 96 err: 97 return testresult; 98 } 99 100 static int test_cfq(void) 101 { 102 int testresult = 0; 103 QUIC_CFQ *cfq = NULL; 104 QUIC_CFQ_ITEM *item, *inext; 105 size_t i; 106 uint32_t pn_space; 107 108 if (!TEST_ptr(cfq = ossl_quic_cfq_new())) 109 goto err; 110 111 g_free = NULL; 112 g_free_len = 0; 113 114 for (i = 0; i < OSSL_NELEM(ref_buf); ++i) { 115 if (!TEST_ptr(item = ossl_quic_cfq_add_frame(cfq, ref_priority[i], 116 ref_pn_space[i], 117 ref_frame_type[i], 0, 118 ref_buf + i, 119 1, 120 free_cb, 121 NULL)) 122 || !TEST_int_eq(ossl_quic_cfq_item_get_state(item), 123 QUIC_CFQ_STATE_NEW) 124 || !TEST_uint_eq(ossl_quic_cfq_item_get_pn_space(item), 125 ref_pn_space[i]) 126 || !TEST_uint64_t_eq(ossl_quic_cfq_item_get_frame_type(item), 127 ref_frame_type[i]) 128 || !TEST_ptr_eq(ossl_quic_cfq_item_get_encoded(item), 129 ref_buf + i) 130 || !TEST_size_t_eq(ossl_quic_cfq_item_get_encoded_len(item), 131 1)) 132 goto err; 133 } 134 135 if (!check(cfq)) 136 goto err; 137 138 for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) 139 for (item = ossl_quic_cfq_get_priority_head(cfq, pn_space); 140 item != NULL; item = inext) { 141 inext = ossl_quic_cfq_item_get_priority_next(item, pn_space); 142 143 ossl_quic_cfq_mark_tx(cfq, item); 144 } 145 146 for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) 147 if (!TEST_ptr_null(ossl_quic_cfq_get_priority_head(cfq, pn_space))) 148 goto err; 149 150 for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) 151 for (i = 0; i < OSSL_NELEM(items[0]); ++i) 152 if (items[pn_space][i] != NULL) 153 ossl_quic_cfq_mark_lost(cfq, items[pn_space][i], UINT32_MAX); 154 155 if (!check(cfq)) 156 goto err; 157 158 for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) 159 for (i = 0; i < OSSL_NELEM(items[0]); ++i) 160 if (items[pn_space][i] != NULL) 161 ossl_quic_cfq_release(cfq, items[pn_space][i]); 162 163 for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) 164 if (!TEST_ptr_null(ossl_quic_cfq_get_priority_head(cfq, pn_space))) 165 goto err; 166 167 testresult = 1; 168 err: 169 ossl_quic_cfq_free(cfq); 170 return testresult; 171 } 172 173 int setup_tests(void) 174 { 175 ADD_TEST(test_cfq); 176 return 1; 177 } 178