1 1.1 christos /* 2 1.1 christos * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include "internal/quic_txp.h" 11 1.1 christos #include "internal/quic_fifd.h" 12 1.1 christos #include "internal/quic_stream_map.h" 13 1.1 christos #include "internal/quic_error.h" 14 1.1 christos #include "internal/common.h" 15 1.1 christos #include <openssl/err.h> 16 1.1 christos 17 1.1.1.2 christos #define MIN_CRYPTO_HDR_SIZE 3 18 1.1 christos 19 1.1.1.2 christos #define MIN_FRAME_SIZE_HANDSHAKE_DONE 1 20 1.1.1.2 christos #define MIN_FRAME_SIZE_MAX_DATA 2 21 1.1.1.2 christos #define MIN_FRAME_SIZE_ACK 5 22 1.1.1.2 christos #define MIN_FRAME_SIZE_CRYPTO (MIN_CRYPTO_HDR_SIZE + 1) 23 1.1.1.2 christos #define MIN_FRAME_SIZE_STREAM 3 /* minimum useful size (for non-FIN) */ 24 1.1 christos #define MIN_FRAME_SIZE_MAX_STREAMS_BIDI 2 25 1.1.1.2 christos #define MIN_FRAME_SIZE_MAX_STREAMS_UNI 2 26 1.1 christos 27 1.1 christos /* 28 1.1 christos * Packet Archetypes 29 1.1 christos * ================= 30 1.1 christos */ 31 1.1 christos 32 1.1 christos /* Generate normal packets containing most frame types, subject to EL. */ 33 1.1.1.2 christos #define TX_PACKETISER_ARCHETYPE_NORMAL 0 34 1.1 christos 35 1.1 christos /* 36 1.1 christos * A probe packet is different in that: 37 1.1 christos * - It bypasses CC, but *is* counted as in flight for purposes of CC; 38 1.1 christos * - It must be ACK-eliciting. 39 1.1 christos */ 40 1.1.1.2 christos #define TX_PACKETISER_ARCHETYPE_PROBE 1 41 1.1 christos 42 1.1 christos /* 43 1.1 christos * An ACK-only packet is different in that: 44 1.1 christos * - It bypasses CC, and is considered a 'non-inflight' packet; 45 1.1 christos * - It may not contain anything other than an ACK frame, not even padding. 46 1.1 christos */ 47 1.1.1.2 christos #define TX_PACKETISER_ARCHETYPE_ACK_ONLY 2 48 1.1 christos 49 1.1.1.2 christos #define TX_PACKETISER_ARCHETYPE_NUM 3 50 1.1 christos 51 1.1 christos struct ossl_quic_tx_packetiser_st { 52 1.1 christos OSSL_QUIC_TX_PACKETISER_ARGS args; 53 1.1 christos 54 1.1 christos /* 55 1.1 christos * Opaque initial token blob provided by caller. TXP frees using the 56 1.1 christos * callback when it is no longer needed. 57 1.1 christos */ 58 1.1.1.2 christos const unsigned char *initial_token; 59 1.1.1.2 christos size_t initial_token_len; 60 1.1 christos ossl_quic_initial_token_free_fn *initial_token_free_cb; 61 1.1.1.2 christos void *initial_token_free_cb_arg; 62 1.1 christos 63 1.1 christos /* Subcomponents of the TXP that we own. */ 64 1.1.1.2 christos QUIC_FIFD fifd; /* QUIC Frame-in-Flight Dispatcher */ 65 1.1 christos 66 1.1 christos /* Internal state. */ 67 1.1.1.2 christos uint64_t next_pn[QUIC_PN_SPACE_NUM]; /* Next PN to use in given PN space. */ 68 1.1.1.2 christos OSSL_TIME last_tx_time; /* Last time a packet was generated, or 0. */ 69 1.1 christos 70 1.1.1.2 christos size_t unvalidated_credit; /* Limit of data we can send until validated */ 71 1.1 christos 72 1.1 christos /* Internal state - frame (re)generation flags. */ 73 1.1.1.2 christos unsigned int want_handshake_done : 1; 74 1.1.1.2 christos unsigned int want_max_data : 1; 75 1.1.1.2 christos unsigned int want_max_streams_bidi : 1; 76 1.1.1.2 christos unsigned int want_max_streams_uni : 1; 77 1.1 christos 78 1.1 christos /* Internal state - frame (re)generation flags - per PN space. */ 79 1.1.1.2 christos unsigned int want_ack : QUIC_PN_SPACE_NUM; 80 1.1.1.2 christos unsigned int force_ack_eliciting : QUIC_PN_SPACE_NUM; 81 1.1 christos 82 1.1 christos /* 83 1.1 christos * Internal state - connection close terminal state. 84 1.1 christos * Once this is set, it is not unset unlike other want_ flags - we keep 85 1.1 christos * sending it in every packet. 86 1.1 christos */ 87 1.1.1.2 christos unsigned int want_conn_close : 1; 88 1.1 christos 89 1.1 christos /* Has the handshake been completed? */ 90 1.1.1.2 christos unsigned int handshake_complete : 1; 91 1.1 christos 92 1.1.1.2 christos OSSL_QUIC_FRAME_CONN_CLOSE conn_close_frame; 93 1.1 christos 94 1.1 christos /* 95 1.1 christos * Counts of the number of bytes received and sent while in the closing 96 1.1 christos * state. 97 1.1 christos */ 98 1.1.1.2 christos uint64_t closing_bytes_recv; 99 1.1.1.2 christos uint64_t closing_bytes_xmit; 100 1.1 christos 101 1.1 christos /* Internal state - packet assembly. */ 102 1.1 christos struct txp_el { 103 1.1.1.2 christos unsigned char *scratch; /* scratch buffer for packet assembly */ 104 1.1.1.2 christos size_t scratch_len; /* number of bytes allocated for scratch */ 105 1.1.1.2 christos OSSL_QTX_IOVEC *iovec; /* scratch iovec array for use with QTX */ 106 1.1.1.2 christos size_t alloc_iovec; /* size of iovec array */ 107 1.1 christos } el[QUIC_ENC_LEVEL_NUM]; 108 1.1 christos 109 1.1 christos /* Message callback related arguments */ 110 1.1 christos ossl_msg_cb msg_callback; 111 1.1 christos void *msg_callback_arg; 112 1.1 christos SSL *msg_callback_ssl; 113 1.1 christos 114 1.1 christos /* Callbacks. */ 115 1.1.1.2 christos void (*ack_tx_cb)(const OSSL_QUIC_FRAME_ACK *ack, 116 1.1.1.2 christos uint32_t pn_space, 117 1.1.1.2 christos void *arg); 118 1.1.1.2 christos void *ack_tx_cb_arg; 119 1.1 christos }; 120 1.1 christos 121 1.1 christos /* 122 1.1 christos * The TX helper records state used while generating frames into packets. It 123 1.1 christos * enables serialization into the packet to be done "transactionally" where 124 1.1 christos * serialization of a frame can be rolled back if it fails midway (e.g. if it 125 1.1 christos * does not fit). 126 1.1 christos */ 127 1.1 christos struct tx_helper { 128 1.1 christos OSSL_QUIC_TX_PACKETISER *txp; 129 1.1 christos /* 130 1.1 christos * The Maximum Packet Payload Length in bytes. This is the amount of 131 1.1 christos * space we have to generate frames into. 132 1.1 christos */ 133 1.1 christos size_t max_ppl; 134 1.1 christos /* 135 1.1 christos * Number of bytes we have generated so far. 136 1.1 christos */ 137 1.1 christos size_t bytes_appended; 138 1.1 christos /* 139 1.1 christos * Number of scratch bytes in txp->scratch we have used so far. Some iovecs 140 1.1 christos * will reference this scratch buffer. When we need to use more of it (e.g. 141 1.1 christos * when we need to put frame headers somewhere), we append to the scratch 142 1.1 christos * buffer, resizing if necessary, and increase this accordingly. 143 1.1 christos */ 144 1.1 christos size_t scratch_bytes; 145 1.1 christos /* 146 1.1 christos * Bytes reserved in the MaxPPL budget. We keep this number of bytes spare 147 1.1 christos * until reserve_allowed is set to 1. Currently this is always at most 1, as 148 1.1 christos * a PING frame takes up one byte and this mechanism is only used to ensure 149 1.1 christos * we can encode a PING frame if we have been asked to ensure a packet is 150 1.1 christos * ACK-eliciting and we are unusure if we are going to add any other 151 1.1 christos * ACK-eliciting frames before we reach our MaxPPL budget. 152 1.1 christos */ 153 1.1 christos size_t reserve; 154 1.1 christos /* 155 1.1 christos * Number of iovecs we have currently appended. This is the number of 156 1.1 christos * entries valid in txp->iovec. 157 1.1 christos */ 158 1.1 christos size_t num_iovec; 159 1.1 christos /* The EL this TX helper is being used for. */ 160 1.1 christos uint32_t enc_level; 161 1.1 christos /* 162 1.1 christos * Whether we are allowed to make use of the reserve bytes in our MaxPPL 163 1.1 christos * budget. This is used to ensure we have room to append a PING frame later 164 1.1 christos * if we need to. Once we know we will not need to append a PING frame, this 165 1.1 christos * is set to 1. 166 1.1 christos */ 167 1.1 christos unsigned int reserve_allowed : 1; 168 1.1 christos /* 169 1.1 christos * Set to 1 if we have appended a STREAM frame with an implicit length. If 170 1.1 christos * this happens we should never append another frame after that frame as it 171 1.1 christos * cannot be validly encoded. This is just a safety check. 172 1.1 christos */ 173 1.1 christos unsigned int done_implicit : 1; 174 1.1 christos struct { 175 1.1 christos /* 176 1.1 christos * The fields in this structure are valid if active is set, which means 177 1.1 christos * that a serialization transaction is currently in progress. 178 1.1 christos */ 179 1.1.1.2 christos unsigned char *data; 180 1.1.1.2 christos WPACKET wpkt; 181 1.1.1.2 christos unsigned int active : 1; 182 1.1 christos } txn; 183 1.1 christos }; 184 1.1 christos 185 1.1 christos static void tx_helper_rollback(struct tx_helper *h); 186 1.1 christos static int txp_el_ensure_iovec(struct txp_el *el, size_t num); 187 1.1 christos 188 1.1 christos /* Initialises the TX helper. */ 189 1.1 christos static int tx_helper_init(struct tx_helper *h, OSSL_QUIC_TX_PACKETISER *txp, 190 1.1.1.2 christos uint32_t enc_level, size_t max_ppl, size_t reserve) 191 1.1 christos { 192 1.1 christos if (reserve > max_ppl) 193 1.1 christos return 0; 194 1.1 christos 195 1.1.1.2 christos h->txp = txp; 196 1.1.1.2 christos h->enc_level = enc_level; 197 1.1.1.2 christos h->max_ppl = max_ppl; 198 1.1.1.2 christos h->reserve = reserve; 199 1.1.1.2 christos h->num_iovec = 0; 200 1.1.1.2 christos h->bytes_appended = 0; 201 1.1.1.2 christos h->scratch_bytes = 0; 202 1.1.1.2 christos h->reserve_allowed = 0; 203 1.1.1.2 christos h->done_implicit = 0; 204 1.1.1.2 christos h->txn.data = NULL; 205 1.1.1.2 christos h->txn.active = 0; 206 1.1 christos 207 1.1 christos if (max_ppl > h->txp->el[enc_level].scratch_len) { 208 1.1 christos unsigned char *scratch; 209 1.1 christos 210 1.1 christos scratch = OPENSSL_realloc(h->txp->el[enc_level].scratch, max_ppl); 211 1.1 christos if (scratch == NULL) 212 1.1 christos return 0; 213 1.1 christos 214 1.1.1.2 christos h->txp->el[enc_level].scratch = scratch; 215 1.1 christos h->txp->el[enc_level].scratch_len = max_ppl; 216 1.1 christos } 217 1.1 christos 218 1.1 christos return 1; 219 1.1 christos } 220 1.1 christos 221 1.1 christos static void tx_helper_cleanup(struct tx_helper *h) 222 1.1 christos { 223 1.1 christos if (h->txn.active) 224 1.1 christos tx_helper_rollback(h); 225 1.1 christos 226 1.1 christos h->txp = NULL; 227 1.1 christos } 228 1.1 christos 229 1.1 christos static void tx_helper_unrestrict(struct tx_helper *h) 230 1.1 christos { 231 1.1 christos h->reserve_allowed = 1; 232 1.1 christos } 233 1.1 christos 234 1.1 christos /* 235 1.1 christos * Append an extent of memory to the iovec list. The memory must remain 236 1.1 christos * allocated until we finish generating the packet and call the QTX. 237 1.1 christos * 238 1.1 christos * In general, the buffers passed to this function will be from one of two 239 1.1 christos * ranges: 240 1.1 christos * 241 1.1 christos * - Application data contained in stream buffers managed elsewhere 242 1.1 christos * in the QUIC stack; or 243 1.1 christos * 244 1.1 christos * - Control frame data appended into txp->scratch using tx_helper_begin and 245 1.1 christos * tx_helper_commit. 246 1.1 christos * 247 1.1 christos */ 248 1.1 christos static int tx_helper_append_iovec(struct tx_helper *h, 249 1.1.1.2 christos const unsigned char *buf, 250 1.1.1.2 christos size_t buf_len) 251 1.1 christos { 252 1.1 christos struct txp_el *el = &h->txp->el[h->enc_level]; 253 1.1 christos 254 1.1 christos if (buf_len == 0) 255 1.1 christos return 1; 256 1.1 christos 257 1.1 christos if (!ossl_assert(!h->done_implicit)) 258 1.1 christos return 0; 259 1.1 christos 260 1.1 christos if (!txp_el_ensure_iovec(el, h->num_iovec + 1)) 261 1.1 christos return 0; 262 1.1 christos 263 1.1.1.2 christos el->iovec[h->num_iovec].buf = buf; 264 1.1 christos el->iovec[h->num_iovec].buf_len = buf_len; 265 1.1 christos 266 1.1 christos ++h->num_iovec; 267 1.1 christos h->bytes_appended += buf_len; 268 1.1 christos return 1; 269 1.1 christos } 270 1.1 christos 271 1.1 christos /* 272 1.1 christos * How many more bytes of space do we have left in our plaintext packet payload? 273 1.1 christos */ 274 1.1 christos static size_t tx_helper_get_space_left(struct tx_helper *h) 275 1.1 christos { 276 1.1 christos return h->max_ppl 277 1.1 christos - (h->reserve_allowed ? 0 : h->reserve) - h->bytes_appended; 278 1.1 christos } 279 1.1 christos 280 1.1 christos /* 281 1.1 christos * Begin a control frame serialization transaction. This allows the 282 1.1 christos * serialization of the control frame to be backed out if it turns out it won't 283 1.1 christos * fit. Write the control frame to the returned WPACKET. Ensure you always 284 1.1 christos * call tx_helper_rollback or tx_helper_commit (or tx_helper_cleanup). Returns 285 1.1 christos * NULL on failure. 286 1.1 christos */ 287 1.1 christos static WPACKET *tx_helper_begin(struct tx_helper *h) 288 1.1 christos { 289 1.1 christos size_t space_left, len; 290 1.1 christos unsigned char *data; 291 1.1 christos struct txp_el *el = &h->txp->el[h->enc_level]; 292 1.1 christos 293 1.1 christos if (!ossl_assert(!h->txn.active)) 294 1.1 christos return NULL; 295 1.1 christos 296 1.1 christos if (!ossl_assert(!h->done_implicit)) 297 1.1 christos return NULL; 298 1.1 christos 299 1.1 christos data = (unsigned char *)el->scratch + h->scratch_bytes; 300 1.1.1.2 christos len = el->scratch_len - h->scratch_bytes; 301 1.1 christos 302 1.1 christos space_left = tx_helper_get_space_left(h); 303 1.1 christos if (!ossl_assert(space_left <= len)) 304 1.1 christos return NULL; 305 1.1 christos 306 1.1 christos if (!WPACKET_init_static_len(&h->txn.wpkt, data, len, 0)) 307 1.1 christos return NULL; 308 1.1 christos 309 1.1 christos if (!WPACKET_set_max_size(&h->txn.wpkt, space_left)) { 310 1.1 christos WPACKET_cleanup(&h->txn.wpkt); 311 1.1 christos return NULL; 312 1.1 christos } 313 1.1 christos 314 1.1.1.2 christos h->txn.data = data; 315 1.1.1.2 christos h->txn.active = 1; 316 1.1 christos return &h->txn.wpkt; 317 1.1 christos } 318 1.1 christos 319 1.1 christos static void tx_helper_end(struct tx_helper *h, int success) 320 1.1 christos { 321 1.1 christos if (success) 322 1.1 christos WPACKET_finish(&h->txn.wpkt); 323 1.1 christos else 324 1.1 christos WPACKET_cleanup(&h->txn.wpkt); 325 1.1 christos 326 1.1.1.2 christos h->txn.active = 0; 327 1.1.1.2 christos h->txn.data = NULL; 328 1.1 christos } 329 1.1 christos 330 1.1 christos /* Abort a control frame serialization transaction. */ 331 1.1 christos static void tx_helper_rollback(struct tx_helper *h) 332 1.1 christos { 333 1.1 christos if (!h->txn.active) 334 1.1 christos return; 335 1.1 christos 336 1.1 christos tx_helper_end(h, 0); 337 1.1 christos } 338 1.1 christos 339 1.1 christos /* Commit a control frame. */ 340 1.1 christos static int tx_helper_commit(struct tx_helper *h) 341 1.1 christos { 342 1.1 christos size_t l = 0; 343 1.1 christos 344 1.1 christos if (!h->txn.active) 345 1.1 christos return 0; 346 1.1 christos 347 1.1 christos if (!WPACKET_get_total_written(&h->txn.wpkt, &l)) { 348 1.1 christos tx_helper_end(h, 0); 349 1.1 christos return 0; 350 1.1 christos } 351 1.1 christos 352 1.1 christos if (!tx_helper_append_iovec(h, h->txn.data, l)) { 353 1.1 christos tx_helper_end(h, 0); 354 1.1 christos return 0; 355 1.1 christos } 356 1.1 christos 357 1.1 christos if (h->txp->msg_callback != NULL && l > 0) { 358 1.1 christos uint64_t ftype; 359 1.1 christos int ctype = SSL3_RT_QUIC_FRAME_FULL; 360 1.1 christos PACKET pkt; 361 1.1 christos 362 1.1 christos if (!PACKET_buf_init(&pkt, h->txn.data, l) 363 1.1.1.2 christos || !ossl_quic_wire_peek_frame_header(&pkt, &ftype, NULL)) { 364 1.1 christos tx_helper_end(h, 0); 365 1.1 christos return 0; 366 1.1 christos } 367 1.1 christos 368 1.1 christos if (ftype == OSSL_QUIC_FRAME_TYPE_PADDING) 369 1.1 christos ctype = SSL3_RT_QUIC_FRAME_PADDING; 370 1.1 christos else if (OSSL_QUIC_FRAME_TYPE_IS_STREAM(ftype) 371 1.1.1.2 christos || ftype == OSSL_QUIC_FRAME_TYPE_CRYPTO) 372 1.1 christos ctype = SSL3_RT_QUIC_FRAME_HEADER; 373 1.1 christos 374 1.1 christos h->txp->msg_callback(1, OSSL_QUIC1_VERSION, ctype, h->txn.data, l, 375 1.1.1.2 christos h->txp->msg_callback_ssl, 376 1.1.1.2 christos h->txp->msg_callback_arg); 377 1.1 christos } 378 1.1 christos 379 1.1 christos h->scratch_bytes += l; 380 1.1 christos tx_helper_end(h, 1); 381 1.1 christos return 1; 382 1.1 christos } 383 1.1 christos 384 1.1 christos struct archetype_data { 385 1.1.1.2 christos unsigned int allow_ack : 1; 386 1.1.1.2 christos unsigned int allow_ping : 1; 387 1.1.1.2 christos unsigned int allow_crypto : 1; 388 1.1.1.2 christos unsigned int allow_handshake_done : 1; 389 1.1.1.2 christos unsigned int allow_path_challenge : 1; 390 1.1.1.2 christos unsigned int allow_path_response : 1; 391 1.1.1.2 christos unsigned int allow_new_conn_id : 1; 392 1.1.1.2 christos unsigned int allow_retire_conn_id : 1; 393 1.1.1.2 christos unsigned int allow_stream_rel : 1; 394 1.1.1.2 christos unsigned int allow_conn_fc : 1; 395 1.1.1.2 christos unsigned int allow_conn_close : 1; 396 1.1.1.2 christos unsigned int allow_cfq_other : 1; 397 1.1.1.2 christos unsigned int allow_new_token : 1; 398 1.1.1.2 christos unsigned int allow_force_ack_eliciting : 1; 399 1.1.1.2 christos unsigned int allow_padding : 1; 400 1.1.1.2 christos unsigned int require_ack_eliciting : 1; 401 1.1.1.2 christos unsigned int bypass_cc : 1; 402 1.1 christos }; 403 1.1 christos 404 1.1 christos struct txp_pkt_geom { 405 1.1.1.2 christos size_t cmpl, cmppl, hwm, pkt_overhead; 406 1.1.1.2 christos uint32_t archetype; 407 1.1.1.2 christos struct archetype_data adata; 408 1.1 christos }; 409 1.1 christos 410 1.1 christos struct txp_pkt { 411 1.1.1.2 christos struct tx_helper h; 412 1.1.1.2 christos int h_valid; 413 1.1.1.2 christos QUIC_TXPIM_PKT *tpkt; 414 1.1.1.2 christos QUIC_STREAM *stream_head; 415 1.1.1.2 christos QUIC_PKT_HDR phdr; 416 1.1 christos struct txp_pkt_geom geom; 417 1.1.1.2 christos int force_pad; 418 1.1 christos }; 419 1.1 christos 420 1.1 christos static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space, 421 1.1.1.2 christos void *arg); 422 1.1 christos static void on_regen_notify(uint64_t frame_type, uint64_t stream_id, 423 1.1.1.2 christos QUIC_TXPIM_PKT *pkt, void *arg); 424 1.1 christos static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id, 425 1.1.1.2 christos QUIC_TXPIM_PKT *pkt, void *arg); 426 1.1 christos static void on_sstream_updated(uint64_t stream_id, void *arg); 427 1.1 christos static int sstream_is_pending(QUIC_SSTREAM *sstream); 428 1.1 christos static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp, 429 1.1.1.2 christos uint32_t enc_level, 430 1.1.1.2 christos uint32_t archetype, 431 1.1.1.2 christos uint64_t cc_limit, 432 1.1.1.2 christos uint32_t *conn_close_enc_level); 433 1.1 christos static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp); 434 1.1 christos static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp, 435 1.1.1.2 christos size_t pl, 436 1.1.1.2 christos uint32_t enc_level, 437 1.1.1.2 christos size_t hdr_len, 438 1.1.1.2 christos size_t *r); 439 1.1 christos static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp); 440 1.1 christos static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp, 441 1.1.1.2 christos struct txp_pkt *pkt, 442 1.1.1.2 christos int chosen_for_conn_close); 443 1.1 christos static int txp_pkt_init(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp, 444 1.1.1.2 christos uint32_t enc_level, uint32_t archetype, 445 1.1.1.2 christos size_t running_total); 446 1.1 christos static void txp_pkt_cleanup(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp); 447 1.1 christos static int txp_pkt_postgen_update_pkt_overhead(struct txp_pkt *pkt, 448 1.1.1.2 christos OSSL_QUIC_TX_PACKETISER *txp); 449 1.1 christos static int txp_pkt_append_padding(struct txp_pkt *pkt, 450 1.1.1.2 christos OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes); 451 1.1 christos static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, struct txp_pkt *pkt, 452 1.1.1.2 christos uint32_t archetype, int *txpim_pkt_reffed); 453 1.1 christos static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp, 454 1.1.1.2 christos uint64_t cc_limit); 455 1.1 christos 456 1.1 christos /** 457 1.1 christos * Sets the validated state of a QUIC TX packetiser. 458 1.1 christos * 459 1.1 christos * This function marks the provided QUIC TX packetiser as having its credit 460 1.1 christos * fully validated by setting its `unvalidated_credit` field to `SIZE_MAX`. 461 1.1 christos * 462 1.1 christos * @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update. 463 1.1 christos */ 464 1.1 christos void ossl_quic_tx_packetiser_set_validated(OSSL_QUIC_TX_PACKETISER *txp) 465 1.1 christos { 466 1.1 christos txp->unvalidated_credit = SIZE_MAX; 467 1.1 christos return; 468 1.1 christos } 469 1.1 christos 470 1.1 christos /** 471 1.1 christos * Adds unvalidated credit to a QUIC TX packetiser. 472 1.1 christos * 473 1.1 christos * This function increases the unvalidated credit of the provided QUIC TX 474 1.1 christos * packetiser. If the current unvalidated credit is not `SIZE_MAX`, the 475 1.1 christos * function adds three times the specified `credit` value, ensuring it does 476 1.1 christos * not exceed the maximum allowable value (`SIZE_MAX - 1`). If the addition 477 1.1 christos * would cause an overflow, the unvalidated credit is capped at 478 1.1 christos * `SIZE_MAX - 1`. If the current unvalidated credit is already `SIZE_MAX`, 479 1.1 christos * the function does nothing. 480 1.1 christos * 481 1.1 christos * @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update. 482 1.1 christos * @param credit The amount of credit to add, multiplied by 3. 483 1.1 christos */ 484 1.1 christos void ossl_quic_tx_packetiser_add_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp, 485 1.1.1.2 christos size_t credit) 486 1.1 christos { 487 1.1 christos if (txp->unvalidated_credit != SIZE_MAX) { 488 1.1 christos if ((SIZE_MAX - txp->unvalidated_credit) > (credit * 3)) 489 1.1 christos txp->unvalidated_credit += credit * 3; 490 1.1 christos else 491 1.1 christos txp->unvalidated_credit = SIZE_MAX - 1; 492 1.1 christos } 493 1.1 christos 494 1.1 christos return; 495 1.1 christos } 496 1.1 christos 497 1.1 christos /** 498 1.1 christos * Consumes unvalidated credit from a QUIC TX packetiser. 499 1.1 christos * 500 1.1 christos * This function decreases the unvalidated credit of the specified 501 1.1 christos * QUIC TX packetiser by the given `credit` value. If the unvalidated credit 502 1.1 christos * is set to `SIZE_MAX`, the function does nothing, as `SIZE_MAX` represents 503 1.1 christos * an unlimited credit state. 504 1.1 christos * 505 1.1 christos * @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update. 506 1.1 christos * @param credit The amount of credit to consume. 507 1.1 christos */ 508 1.1 christos void ossl_quic_tx_packetiser_consume_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp, 509 1.1.1.2 christos size_t credit) 510 1.1 christos { 511 1.1 christos if (txp->unvalidated_credit != SIZE_MAX) { 512 1.1 christos if (txp->unvalidated_credit < credit) 513 1.1 christos txp->unvalidated_credit = 0; 514 1.1 christos else 515 1.1 christos txp->unvalidated_credit -= credit; 516 1.1 christos } 517 1.1 christos } 518 1.1 christos 519 1.1 christos /** 520 1.1 christos * Checks if the QUIC TX packetiser has sufficient unvalidated credit. 521 1.1 christos * 522 1.1 christos * This function determines whether the unvalidated credit of the specified 523 1.1 christos * QUIC TX packetiser exceeds the required credit value (`req_credit`). 524 1.1 christos * If the unvalidated credit is greater than `req_credit`, the function 525 1.1 christos * returns 1 (true); otherwise, it returns 0 (false). 526 1.1 christos * 527 1.1 christos * @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to check. 528 1.1 christos * @param req_credit The required credit value to compare against. 529 1.1 christos * 530 1.1 christos * @return 1 if the unvalidated credit exceeds `req_credit`, 0 otherwise. 531 1.1 christos */ 532 1.1 christos int ossl_quic_tx_packetiser_check_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp, 533 1.1.1.2 christos size_t req_credit) 534 1.1 christos { 535 1.1 christos return (txp->unvalidated_credit > req_credit); 536 1.1 christos } 537 1.1 christos 538 1.1 christos OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args) 539 1.1 christos { 540 1.1 christos OSSL_QUIC_TX_PACKETISER *txp; 541 1.1 christos 542 1.1 christos if (args == NULL 543 1.1 christos || args->qtx == NULL 544 1.1 christos || args->txpim == NULL 545 1.1 christos || args->cfq == NULL 546 1.1 christos || args->ackm == NULL 547 1.1 christos || args->qsm == NULL 548 1.1 christos || args->conn_txfc == NULL 549 1.1 christos || args->conn_rxfc == NULL 550 1.1 christos || args->max_streams_bidi_rxfc == NULL 551 1.1 christos || args->max_streams_uni_rxfc == NULL 552 1.1 christos || args->protocol_version == 0) { 553 1.1 christos ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 554 1.1 christos return NULL; 555 1.1 christos } 556 1.1 christos 557 1.1 christos txp = OPENSSL_zalloc(sizeof(*txp)); 558 1.1 christos if (txp == NULL) 559 1.1 christos return NULL; 560 1.1 christos 561 1.1.1.2 christos txp->args = *args; 562 1.1.1.2 christos txp->last_tx_time = ossl_time_zero(); 563 1.1 christos 564 1.1 christos if (!ossl_quic_fifd_init(&txp->fifd, 565 1.1.1.2 christos txp->args.cfq, txp->args.ackm, txp->args.txpim, 566 1.1.1.2 christos get_sstream_by_id, txp, 567 1.1.1.2 christos on_regen_notify, txp, 568 1.1.1.2 christos on_confirm_notify, txp, 569 1.1.1.2 christos on_sstream_updated, txp, 570 1.1.1.2 christos args->get_qlog_cb, 571 1.1.1.2 christos args->get_qlog_cb_arg)) { 572 1.1 christos OPENSSL_free(txp); 573 1.1 christos return NULL; 574 1.1 christos } 575 1.1 christos 576 1.1 christos return txp; 577 1.1 christos } 578 1.1 christos 579 1.1 christos void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *txp) 580 1.1 christos { 581 1.1 christos uint32_t enc_level; 582 1.1 christos 583 1.1 christos if (txp == NULL) 584 1.1 christos return; 585 1.1 christos 586 1.1 christos ossl_quic_tx_packetiser_set_initial_token(txp, NULL, 0, NULL, NULL); 587 1.1 christos ossl_quic_fifd_cleanup(&txp->fifd); 588 1.1 christos OPENSSL_free(txp->conn_close_frame.reason); 589 1.1 christos 590 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 591 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 592 1.1.1.2 christos ++enc_level) { 593 1.1 christos OPENSSL_free(txp->el[enc_level].iovec); 594 1.1 christos OPENSSL_free(txp->el[enc_level].scratch); 595 1.1 christos } 596 1.1 christos 597 1.1 christos OPENSSL_free(txp); 598 1.1 christos } 599 1.1 christos 600 1.1 christos /* 601 1.1 christos * Determine if an Initial packet token length is reasonable based on the 602 1.1 christos * current MDPL, returning 1 if it is OK. 603 1.1 christos * 604 1.1 christos * The real PMTU to the peer could differ from our (pessimistic) understanding 605 1.1 christos * of the PMTU, therefore it is possible we could receive an Initial token from 606 1.1 christos * a server in a Retry packet which is bigger than the MDPL. In this case it is 607 1.1 christos * impossible for us ever to make forward progress and we need to error out 608 1.1 christos * and fail the connection attempt. 609 1.1 christos * 610 1.1 christos * The specific boundary condition is complex: for example, after the size of 611 1.1 christos * the Initial token, there are the Initial packet header overheads and then 612 1.1 christos * encryption/AEAD tag overheads. After that, the minimum room for frame data in 613 1.1 christos * order to guarantee forward progress must be guaranteed. For example, a crypto 614 1.1 christos * stream needs to always be able to serialize at least one byte in a CRYPTO 615 1.1 christos * frame in order to make forward progress. Because the offset field of a CRYPTO 616 1.1 christos * frame uses a variable-length integer, the number of bytes needed to ensure 617 1.1 christos * this also varies. 618 1.1 christos * 619 1.1 christos * Rather than trying to get this boundary condition check actually right, 620 1.1 christos * require a reasonable amount of slack to avoid pathological behaviours. (After 621 1.1 christos * all, transmitting a CRYPTO stream one byte at a time is probably not 622 1.1 christos * desirable anyway.) 623 1.1 christos * 624 1.1 christos * We choose 160 bytes as the required margin, which is double the rough 625 1.1 christos * estimation of the minimum we would require to guarantee forward progress 626 1.1 christos * under worst case packet overheads. 627 1.1 christos */ 628 1.1.1.2 christos #define TXP_REQUIRED_TOKEN_MARGIN 160 629 1.1 christos 630 1.1 christos static int txp_check_token_len(size_t token_len, size_t mdpl) 631 1.1 christos { 632 1.1 christos if (token_len == 0) 633 1.1 christos return 1; 634 1.1 christos 635 1.1 christos if (token_len >= mdpl) 636 1.1 christos return 0; 637 1.1 christos 638 1.1 christos if (TXP_REQUIRED_TOKEN_MARGIN >= mdpl) 639 1.1 christos /* (should not be possible because MDPL must be at least 1200) */ 640 1.1 christos return 0; 641 1.1 christos 642 1.1 christos if (token_len > mdpl - TXP_REQUIRED_TOKEN_MARGIN) 643 1.1 christos return 0; 644 1.1 christos 645 1.1 christos return 1; 646 1.1 christos } 647 1.1 christos 648 1.1 christos int ossl_quic_tx_packetiser_set_initial_token(OSSL_QUIC_TX_PACKETISER *txp, 649 1.1.1.2 christos const unsigned char *token, 650 1.1.1.2 christos size_t token_len, 651 1.1.1.2 christos ossl_quic_initial_token_free_fn *free_cb, 652 1.1.1.2 christos void *free_cb_arg) 653 1.1 christos { 654 1.1 christos if (!txp_check_token_len(token_len, txp_get_mdpl(txp))) 655 1.1 christos return 0; 656 1.1 christos 657 1.1 christos if (txp->initial_token != NULL && txp->initial_token_free_cb != NULL) 658 1.1 christos txp->initial_token_free_cb(txp->initial_token, txp->initial_token_len, 659 1.1.1.2 christos txp->initial_token_free_cb_arg); 660 1.1 christos 661 1.1.1.2 christos txp->initial_token = token; 662 1.1.1.2 christos txp->initial_token_len = token_len; 663 1.1.1.2 christos txp->initial_token_free_cb = free_cb; 664 1.1.1.2 christos txp->initial_token_free_cb_arg = free_cb_arg; 665 1.1 christos return 1; 666 1.1 christos } 667 1.1 christos 668 1.1 christos int ossl_quic_tx_packetiser_set_protocol_version(OSSL_QUIC_TX_PACKETISER *txp, 669 1.1.1.2 christos uint32_t protocol_version) 670 1.1 christos { 671 1.1 christos txp->args.protocol_version = protocol_version; 672 1.1 christos return 1; 673 1.1 christos } 674 1.1 christos 675 1.1 christos int ossl_quic_tx_packetiser_set_cur_dcid(OSSL_QUIC_TX_PACKETISER *txp, 676 1.1.1.2 christos const QUIC_CONN_ID *dcid) 677 1.1 christos { 678 1.1 christos if (dcid == NULL) { 679 1.1 christos ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 680 1.1 christos return 0; 681 1.1 christos } 682 1.1 christos 683 1.1 christos txp->args.cur_dcid = *dcid; 684 1.1 christos return 1; 685 1.1 christos } 686 1.1 christos 687 1.1 christos int ossl_quic_tx_packetiser_set_cur_scid(OSSL_QUIC_TX_PACKETISER *txp, 688 1.1.1.2 christos const QUIC_CONN_ID *scid) 689 1.1 christos { 690 1.1 christos if (scid == NULL) { 691 1.1 christos ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 692 1.1 christos return 0; 693 1.1 christos } 694 1.1 christos 695 1.1 christos txp->args.cur_scid = *scid; 696 1.1 christos return 1; 697 1.1 christos } 698 1.1 christos 699 1.1 christos /* Change the destination L4 address the TXP uses to send datagrams. */ 700 1.1 christos int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp, 701 1.1.1.2 christos const BIO_ADDR *peer) 702 1.1 christos { 703 1.1 christos if (peer == NULL) { 704 1.1 christos BIO_ADDR_clear(&txp->args.peer); 705 1.1 christos return 1; 706 1.1 christos } 707 1.1 christos 708 1.1 christos return BIO_ADDR_copy(&txp->args.peer, peer); 709 1.1 christos } 710 1.1 christos 711 1.1 christos void ossl_quic_tx_packetiser_set_ack_tx_cb(OSSL_QUIC_TX_PACKETISER *txp, 712 1.1.1.2 christos void (*cb)(const OSSL_QUIC_FRAME_ACK *ack, 713 1.1.1.2 christos uint32_t pn_space, 714 1.1.1.2 christos void *arg), 715 1.1.1.2 christos void *cb_arg) 716 1.1 christos { 717 1.1.1.2 christos txp->ack_tx_cb = cb; 718 1.1.1.2 christos txp->ack_tx_cb_arg = cb_arg; 719 1.1 christos } 720 1.1 christos 721 1.1 christos void ossl_quic_tx_packetiser_set_qlog_cb(OSSL_QUIC_TX_PACKETISER *txp, 722 1.1.1.2 christos QLOG *(*get_qlog_cb)(void *arg), 723 1.1.1.2 christos void *get_qlog_cb_arg) 724 1.1 christos { 725 1.1 christos ossl_quic_fifd_set_qlog_cb(&txp->fifd, get_qlog_cb, get_qlog_cb_arg); 726 1.1 christos } 727 1.1 christos 728 1.1 christos int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp, 729 1.1.1.2 christos uint32_t enc_level) 730 1.1 christos { 731 1.1 christos if (enc_level >= QUIC_ENC_LEVEL_NUM) { 732 1.1 christos ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); 733 1.1 christos return 0; 734 1.1 christos } 735 1.1 christos 736 1.1 christos if (enc_level != QUIC_ENC_LEVEL_0RTT) 737 1.1 christos txp->args.crypto[ossl_quic_enc_level_to_pn_space(enc_level)] = NULL; 738 1.1 christos 739 1.1 christos return 1; 740 1.1 christos } 741 1.1 christos 742 1.1 christos void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp) 743 1.1 christos { 744 1.1 christos txp->handshake_complete = 1; 745 1.1 christos } 746 1.1 christos 747 1.1 christos void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp) 748 1.1 christos { 749 1.1 christos txp->want_handshake_done = 1; 750 1.1 christos } 751 1.1 christos 752 1.1 christos void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp, 753 1.1.1.2 christos uint32_t pn_space) 754 1.1 christos { 755 1.1 christos txp->force_ack_eliciting |= (1UL << pn_space); 756 1.1 christos } 757 1.1 christos 758 1.1 christos void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp, 759 1.1.1.2 christos uint32_t pn_space) 760 1.1 christos { 761 1.1 christos txp->want_ack |= (1UL << pn_space); 762 1.1 christos } 763 1.1 christos 764 1.1.1.2 christos #define TXP_ERR_INTERNAL 0 /* Internal (e.g. alloc) error */ 765 1.1.1.2 christos #define TXP_ERR_SUCCESS 1 /* Success */ 766 1.1.1.2 christos #define TXP_ERR_SPACE 2 /* Not enough room for another packet */ 767 1.1.1.2 christos #define TXP_ERR_INPUT 3 /* Invalid/malformed input */ 768 1.1 christos 769 1.1 christos /* 770 1.1 christos * Generates a datagram by polling the various ELs to determine if they want to 771 1.1 christos * generate any frames, and generating a datagram which coalesces packets for 772 1.1 christos * any ELs which do. 773 1.1 christos */ 774 1.1 christos int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp, 775 1.1.1.2 christos QUIC_TXP_STATUS *status) 776 1.1 christos { 777 1.1 christos /* 778 1.1 christos * Called to generate one or more datagrams, each containing one or more 779 1.1 christos * packets. 780 1.1 christos * 781 1.1 christos * There are some tricky things to note here: 782 1.1 christos * 783 1.1 christos * - The TXP is only concerned with generating encrypted packets; 784 1.1 christos * other packets use a different path. 785 1.1 christos * 786 1.1 christos * - Any datagram containing an Initial packet must have a payload length 787 1.1 christos * (DPL) of at least 1200 bytes. This padding need not necessarily be 788 1.1 christos * found in the Initial packet. 789 1.1 christos * 790 1.1 christos * - It is desirable to be able to coalesce an Initial packet 791 1.1 christos * with a Handshake packet. Since, before generating the Handshake 792 1.1 christos * packet, we do not know how long it will be, we cannot know the 793 1.1 christos * correct amount of padding to ensure a DPL of at least 1200 bytes. 794 1.1 christos * Thus this padding must added to the Handshake packet (or whatever 795 1.1 christos * packet is the last in the datagram). 796 1.1 christos * 797 1.1 christos * - However, at the time that we generate the Initial packet, 798 1.1 christos * we do not actually know for sure that we will be followed 799 1.1 christos * in the datagram by another packet. For example, suppose we have 800 1.1 christos * some queued data (e.g. crypto stream data for the HANDSHAKE EL) 801 1.1 christos * it looks like we will want to send on the HANDSHAKE EL. 802 1.1 christos * We could assume padding will be placed in the Handshake packet 803 1.1 christos * subsequently and avoid adding any padding to the Initial packet 804 1.1 christos * (which would leave no room for the Handshake packet in the 805 1.1 christos * datagram). 806 1.1 christos * 807 1.1 christos * However, this is not actually a safe assumption. Suppose that we 808 1.1 christos * are using a link with a MDPL of 1200 bytes, the minimum allowed by 809 1.1 christos * QUIC. Suppose that the Initial packet consumes 1195 bytes in total. 810 1.1 christos * Since it is not possible to fit a Handshake packet in just 5 bytes, 811 1.1 christos * upon trying to add a Handshake packet after generating the Initial 812 1.1 christos * packet, we will discover we have no room to fit it! This is not a 813 1.1 christos * problem in itself as another datagram can be sent subsequently, but 814 1.1 christos * it is a problem because we were counting to use that packet to hold 815 1.1 christos * the essential padding. But if we have already finished encrypting 816 1.1 christos * the Initial packet, we cannot go and add padding to it anymore. 817 1.1 christos * This leaves us stuck. 818 1.1 christos * 819 1.1 christos * Because of this, we have to plan multiple packets simultaneously, such 820 1.1 christos * that we can start generating a Handshake (or 0-RTT or 1-RTT, or so on) 821 1.1 christos * packet while still having the option to go back and add padding to the 822 1.1 christos * Initial packet if it turns out to be needed. 823 1.1 christos * 824 1.1 christos * Trying to predict ahead of time (e.g. during Initial packet generation) 825 1.1 christos * whether we will successfully generate a subsequent packet is fraught with 826 1.1 christos * error as it relies on a large number of variables: 827 1.1 christos * 828 1.1 christos * - Do we have room to fit a packet header? (Consider that due to 829 1.1 christos * variable-length integer encoding this is highly variable and can even 830 1.1 christos * depend on payload length due to a variable-length Length field.) 831 1.1 christos * 832 1.1 christos * - Can we fit even a single one of the frames we want to put in this 833 1.1 christos * packet in the packet? (Each frame type has a bespoke encoding. While 834 1.1 christos * our encodings of some frame types are adaptive based on the available 835 1.1 christos * room - e.g. STREAM frames - ultimately all frame types have some 836 1.1 christos * absolute minimum number of bytes to be successfully encoded. For 837 1.1 christos * example, if after an Initial packet there is enough room to encode 838 1.1 christos * only one byte of frame data, it is quite likely we can't send any of 839 1.1 christos * the frames we wanted to send.) While this is not strictly a problem 840 1.1 christos * because we could just fill the packet with padding frames, this is a 841 1.1 christos * pointless packet and is wasteful. 842 1.1 christos * 843 1.1 christos * Thus we adopt a multi-phase architecture: 844 1.1 christos * 845 1.1 christos * 1. Archetype Selection: Determine desired packet archetype. 846 1.1 christos * 847 1.1 christos * 2. Packet Staging: Generation of packet information and packet payload 848 1.1 christos * data (frame data) into staging areas. 849 1.1 christos * 850 1.1 christos * 3. Packet Adjustment: Adjustment of staged packets, adding padding to 851 1.1 christos * the staged packets if needed. 852 1.1 christos * 853 1.1 christos * 4. Commit: The packets are sent to the QTX and recorded as having been 854 1.1 christos * sent to the FIFM. 855 1.1 christos * 856 1.1 christos */ 857 1.1 christos int res = 0, rc; 858 1.1 christos uint32_t archetype, enc_level; 859 1.1 christos uint32_t conn_close_enc_level = QUIC_ENC_LEVEL_NUM; 860 1.1 christos struct txp_pkt pkt[QUIC_ENC_LEVEL_NUM]; 861 1.1 christos size_t pkts_done = 0; 862 1.1 christos uint64_t cc_limit = txp->args.cc_method->get_tx_allowance(txp->args.cc_data); 863 1.1 christos int need_padding = 0, txpim_pkt_reffed; 864 1.1 christos 865 1.1 christos memset(status, 0, sizeof(*status)); 866 1.1 christos 867 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 868 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 869 1.1.1.2 christos ++enc_level) 870 1.1 christos pkt[enc_level].h_valid = 0; 871 1.1 christos 872 1.1 christos /* 873 1.1 christos * Should not be needed, but a sanity check in case anyone else has been 874 1.1 christos * using the QTX. 875 1.1 christos */ 876 1.1 christos ossl_qtx_finish_dgram(txp->args.qtx); 877 1.1 christos 878 1.1 christos /* 1. Archetype Selection */ 879 1.1 christos archetype = txp_determine_archetype(txp, cc_limit); 880 1.1 christos 881 1.1 christos /* 2. Packet Staging */ 882 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 883 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 884 1.1.1.2 christos ++enc_level) { 885 1.1 christos size_t running_total = (enc_level > QUIC_ENC_LEVEL_INITIAL) 886 1.1.1.2 christos ? pkt[enc_level - 1].geom.hwm 887 1.1.1.2 christos : 0; 888 1.1 christos 889 1.1 christos pkt[enc_level].geom.hwm = running_total; 890 1.1 christos 891 1.1 christos if (!txp_should_try_staging(txp, enc_level, archetype, cc_limit, 892 1.1.1.2 christos &conn_close_enc_level)) 893 1.1 christos continue; 894 1.1 christos 895 1.1 christos if (!txp_pkt_init(&pkt[enc_level], txp, enc_level, archetype, 896 1.1.1.2 christos running_total)) 897 1.1 christos /* 898 1.1 christos * If this fails this is not a fatal error - it means the geometry 899 1.1 christos * planning determined there was not enough space for another 900 1.1 christos * packet. So just proceed with what we've already planned for. 901 1.1 christos */ 902 1.1 christos break; 903 1.1 christos 904 1.1 christos rc = txp_generate_for_el(txp, &pkt[enc_level], 905 1.1.1.2 christos conn_close_enc_level == enc_level); 906 1.1 christos if (rc != TXP_ERR_SUCCESS) 907 1.1 christos goto out; 908 1.1 christos 909 1.1 christos if (pkt[enc_level].force_pad) 910 1.1 christos /* 911 1.1 christos * txp_generate_for_el emitted a frame which forces packet padding. 912 1.1 christos */ 913 1.1 christos need_padding = 1; 914 1.1 christos 915 1.1 christos pkt[enc_level].geom.hwm = running_total 916 1.1 christos + pkt[enc_level].h.bytes_appended 917 1.1 christos + pkt[enc_level].geom.pkt_overhead; 918 1.1 christos } 919 1.1 christos 920 1.1 christos /* 3. Packet Adjustment */ 921 1.1 christos if (pkt[QUIC_ENC_LEVEL_INITIAL].h_valid 922 1.1 christos && pkt[QUIC_ENC_LEVEL_INITIAL].h.bytes_appended > 0) 923 1.1 christos /* 924 1.1 christos * We have an Initial packet in this datagram, so we need to make sure 925 1.1 christos * the total size of the datagram is adequate. 926 1.1 christos */ 927 1.1 christos need_padding = 1; 928 1.1 christos 929 1.1 christos if (need_padding) { 930 1.1 christos size_t total_dgram_size = 0; 931 1.1 christos const size_t min_dpl = QUIC_MIN_INITIAL_DGRAM_LEN; 932 1.1 christos uint32_t pad_el = QUIC_ENC_LEVEL_NUM; 933 1.1 christos 934 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 935 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 936 1.1.1.2 christos ++enc_level) 937 1.1 christos if (pkt[enc_level].h_valid && pkt[enc_level].h.bytes_appended > 0) { 938 1.1 christos if (pad_el == QUIC_ENC_LEVEL_NUM 939 1.1 christos /* 940 1.1 christos * We might not be able to add padding, for example if we 941 1.1 christos * are using the ACK_ONLY archetype. 942 1.1 christos */ 943 1.1 christos && pkt[enc_level].geom.adata.allow_padding 944 1.1 christos && !pkt[enc_level].h.done_implicit) 945 1.1 christos pad_el = enc_level; 946 1.1 christos 947 1.1 christos txp_pkt_postgen_update_pkt_overhead(&pkt[enc_level], txp); 948 1.1 christos total_dgram_size += pkt[enc_level].geom.pkt_overhead 949 1.1 christos + pkt[enc_level].h.bytes_appended; 950 1.1 christos } 951 1.1 christos 952 1.1 christos if (pad_el != QUIC_ENC_LEVEL_NUM && total_dgram_size < min_dpl) { 953 1.1 christos size_t deficit = min_dpl - total_dgram_size; 954 1.1 christos 955 1.1 christos if (!txp_pkt_append_padding(&pkt[pad_el], txp, deficit)) 956 1.1 christos goto out; 957 1.1 christos 958 1.1 christos total_dgram_size += deficit; 959 1.1 christos 960 1.1 christos /* 961 1.1 christos * Padding frames make a packet ineligible for being a non-inflight 962 1.1 christos * packet. 963 1.1 christos */ 964 1.1 christos pkt[pad_el].tpkt->ackm_pkt.is_inflight = 1; 965 1.1 christos } 966 1.1 christos 967 1.1 christos /* 968 1.1 christos * If we have failed to make a datagram of adequate size, for example 969 1.1 christos * because we have a padding requirement but are using the ACK_ONLY 970 1.1 christos * archetype (because we are CC limited), which precludes us from 971 1.1 christos * sending padding, give up on generating the datagram - there is 972 1.1 christos * nothing we can do. 973 1.1 christos */ 974 1.1 christos if (total_dgram_size < min_dpl) { 975 1.1 christos res = 1; 976 1.1 christos goto out; 977 1.1 christos } 978 1.1 christos } 979 1.1 christos 980 1.1 christos /* 4. Commit */ 981 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 982 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 983 1.1.1.2 christos ++enc_level) { 984 1.1 christos 985 1.1 christos if (!pkt[enc_level].h_valid) 986 1.1 christos /* Did not attempt to generate a packet for this EL. */ 987 1.1 christos continue; 988 1.1 christos 989 1.1 christos if (pkt[enc_level].h.bytes_appended == 0) 990 1.1 christos /* Nothing was generated for this EL, so skip. */ 991 1.1 christos continue; 992 1.1 christos 993 1.1 christos if (!ossl_quic_tx_packetiser_check_unvalidated_credit(txp, 994 1.1.1.2 christos pkt[enc_level].h.bytes_appended)) { 995 1.1 christos res = TXP_ERR_SPACE; 996 1.1 christos goto out; 997 1.1 christos } 998 1.1 christos ossl_quic_tx_packetiser_consume_unvalidated_credit(txp, pkt[enc_level].h.bytes_appended); 999 1.1 christos 1000 1.1 christos rc = txp_pkt_commit(txp, &pkt[enc_level], archetype, 1001 1.1.1.2 christos &txpim_pkt_reffed); 1002 1.1 christos if (rc) { 1003 1.1 christos status->sent_ack_eliciting 1004 1.1 christos = status->sent_ack_eliciting 1005 1.1 christos || pkt[enc_level].tpkt->ackm_pkt.is_ack_eliciting; 1006 1.1 christos 1007 1.1 christos if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE) 1008 1.1 christos status->sent_handshake 1009 1.1 christos = (pkt[enc_level].h_valid 1010 1.1.1.2 christos && pkt[enc_level].h.bytes_appended > 0); 1011 1.1 christos } 1012 1.1 christos 1013 1.1 christos if (txpim_pkt_reffed) 1014 1.1 christos pkt[enc_level].tpkt = NULL; /* don't free */ 1015 1.1 christos 1016 1.1 christos if (!rc) 1017 1.1 christos goto out; 1018 1.1 christos 1019 1.1 christos ++pkts_done; 1020 1.1 christos } 1021 1.1 christos 1022 1.1 christos /* Flush & Cleanup */ 1023 1.1 christos res = 1; 1024 1.1 christos out: 1025 1.1 christos ossl_qtx_finish_dgram(txp->args.qtx); 1026 1.1 christos 1027 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 1028 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 1029 1.1.1.2 christos ++enc_level) 1030 1.1 christos txp_pkt_cleanup(&pkt[enc_level], txp); 1031 1.1 christos 1032 1.1 christos status->sent_pkt = pkts_done; 1033 1.1 christos 1034 1.1 christos return res; 1035 1.1 christos } 1036 1.1 christos 1037 1.1 christos static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_ARCHETYPE_NUM] = { 1038 1.1 christos /* EL 0(INITIAL) */ 1039 1.1 christos { 1040 1.1 christos /* EL 0(INITIAL) - Archetype 0(NORMAL) */ 1041 1.1 christos { 1042 1.1.1.2 christos /*allow_ack =*/1, 1043 1.1.1.2 christos /*allow_ping =*/1, 1044 1.1.1.2 christos /*allow_crypto =*/1, 1045 1.1.1.2 christos /*allow_handshake_done =*/0, 1046 1.1.1.2 christos /*allow_path_challenge =*/0, 1047 1.1.1.2 christos /*allow_path_response =*/0, 1048 1.1.1.2 christos /*allow_new_conn_id =*/0, 1049 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1050 1.1.1.2 christos /*allow_stream_rel =*/0, 1051 1.1.1.2 christos /*allow_conn_fc =*/0, 1052 1.1.1.2 christos /*allow_conn_close =*/1, 1053 1.1.1.2 christos /*allow_cfq_other =*/0, 1054 1.1.1.2 christos /*allow_new_token =*/0, 1055 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1056 1.1.1.2 christos /*allow_padding =*/1, 1057 1.1.1.2 christos /*require_ack_eliciting =*/0, 1058 1.1.1.2 christos /*bypass_cc =*/0, 1059 1.1 christos }, 1060 1.1 christos /* EL 0(INITIAL) - Archetype 1(PROBE) */ 1061 1.1 christos { 1062 1.1.1.2 christos /*allow_ack =*/1, 1063 1.1.1.2 christos /*allow_ping =*/1, 1064 1.1.1.2 christos /*allow_crypto =*/1, 1065 1.1.1.2 christos /*allow_handshake_done =*/0, 1066 1.1.1.2 christos /*allow_path_challenge =*/0, 1067 1.1.1.2 christos /*allow_path_response =*/0, 1068 1.1.1.2 christos /*allow_new_conn_id =*/0, 1069 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1070 1.1.1.2 christos /*allow_stream_rel =*/0, 1071 1.1.1.2 christos /*allow_conn_fc =*/0, 1072 1.1.1.2 christos /*allow_conn_close =*/1, 1073 1.1.1.2 christos /*allow_cfq_other =*/0, 1074 1.1.1.2 christos /*allow_new_token =*/0, 1075 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1076 1.1.1.2 christos /*allow_padding =*/1, 1077 1.1.1.2 christos /*require_ack_eliciting =*/1, 1078 1.1.1.2 christos /*bypass_cc =*/1, 1079 1.1 christos }, 1080 1.1 christos /* EL 0(INITIAL) - Archetype 2(ACK_ONLY) */ 1081 1.1 christos { 1082 1.1.1.2 christos /*allow_ack =*/1, 1083 1.1.1.2 christos /*allow_ping =*/0, 1084 1.1.1.2 christos /*allow_crypto =*/0, 1085 1.1.1.2 christos /*allow_handshake_done =*/0, 1086 1.1.1.2 christos /*allow_path_challenge =*/0, 1087 1.1.1.2 christos /*allow_path_response =*/0, 1088 1.1.1.2 christos /*allow_new_conn_id =*/0, 1089 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1090 1.1.1.2 christos /*allow_stream_rel =*/0, 1091 1.1.1.2 christos /*allow_conn_fc =*/0, 1092 1.1.1.2 christos /*allow_conn_close =*/0, 1093 1.1.1.2 christos /*allow_cfq_other =*/0, 1094 1.1.1.2 christos /*allow_new_token =*/0, 1095 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1096 1.1.1.2 christos /*allow_padding =*/0, 1097 1.1.1.2 christos /*require_ack_eliciting =*/0, 1098 1.1.1.2 christos /*bypass_cc =*/1, 1099 1.1 christos }, 1100 1.1 christos }, 1101 1.1 christos /* EL 1(0RTT) */ 1102 1.1 christos { 1103 1.1 christos /* EL 1(0RTT) - Archetype 0(NORMAL) */ 1104 1.1 christos { 1105 1.1.1.2 christos /*allow_ack =*/0, 1106 1.1.1.2 christos /*allow_ping =*/1, 1107 1.1.1.2 christos /*allow_crypto =*/0, 1108 1.1.1.2 christos /*allow_handshake_done =*/0, 1109 1.1.1.2 christos /*allow_path_challenge =*/0, 1110 1.1.1.2 christos /*allow_path_response =*/0, 1111 1.1.1.2 christos /*allow_new_conn_id =*/1, 1112 1.1.1.2 christos /*allow_retire_conn_id =*/1, 1113 1.1.1.2 christos /*allow_stream_rel =*/1, 1114 1.1.1.2 christos /*allow_conn_fc =*/1, 1115 1.1.1.2 christos /*allow_conn_close =*/1, 1116 1.1.1.2 christos /*allow_cfq_other =*/0, 1117 1.1.1.2 christos /*allow_new_token =*/0, 1118 1.1.1.2 christos /*allow_force_ack_eliciting =*/0, 1119 1.1.1.2 christos /*allow_padding =*/1, 1120 1.1.1.2 christos /*require_ack_eliciting =*/0, 1121 1.1.1.2 christos /*bypass_cc =*/0, 1122 1.1 christos }, 1123 1.1 christos /* EL 1(0RTT) - Archetype 1(PROBE) */ 1124 1.1 christos { 1125 1.1.1.2 christos /*allow_ack =*/0, 1126 1.1.1.2 christos /*allow_ping =*/1, 1127 1.1.1.2 christos /*allow_crypto =*/0, 1128 1.1.1.2 christos /*allow_handshake_done =*/0, 1129 1.1.1.2 christos /*allow_path_challenge =*/0, 1130 1.1.1.2 christos /*allow_path_response =*/0, 1131 1.1.1.2 christos /*allow_new_conn_id =*/1, 1132 1.1.1.2 christos /*allow_retire_conn_id =*/1, 1133 1.1.1.2 christos /*allow_stream_rel =*/1, 1134 1.1.1.2 christos /*allow_conn_fc =*/1, 1135 1.1.1.2 christos /*allow_conn_close =*/1, 1136 1.1.1.2 christos /*allow_cfq_other =*/0, 1137 1.1.1.2 christos /*allow_new_token =*/0, 1138 1.1.1.2 christos /*allow_force_ack_eliciting =*/0, 1139 1.1.1.2 christos /*allow_padding =*/1, 1140 1.1.1.2 christos /*require_ack_eliciting =*/1, 1141 1.1.1.2 christos /*bypass_cc =*/1, 1142 1.1 christos }, 1143 1.1 christos /* EL 1(0RTT) - Archetype 2(ACK_ONLY) */ 1144 1.1 christos { 1145 1.1.1.2 christos /*allow_ack =*/0, 1146 1.1.1.2 christos /*allow_ping =*/0, 1147 1.1.1.2 christos /*allow_crypto =*/0, 1148 1.1.1.2 christos /*allow_handshake_done =*/0, 1149 1.1.1.2 christos /*allow_path_challenge =*/0, 1150 1.1.1.2 christos /*allow_path_response =*/0, 1151 1.1.1.2 christos /*allow_new_conn_id =*/0, 1152 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1153 1.1.1.2 christos /*allow_stream_rel =*/0, 1154 1.1.1.2 christos /*allow_conn_fc =*/0, 1155 1.1.1.2 christos /*allow_conn_close =*/0, 1156 1.1.1.2 christos /*allow_cfq_other =*/0, 1157 1.1.1.2 christos /*allow_new_token =*/0, 1158 1.1.1.2 christos /*allow_force_ack_eliciting =*/0, 1159 1.1.1.2 christos /*allow_padding =*/0, 1160 1.1.1.2 christos /*require_ack_eliciting =*/0, 1161 1.1.1.2 christos /*bypass_cc =*/1, 1162 1.1 christos }, 1163 1.1 christos }, 1164 1.1 christos /* EL (HANDSHAKE) */ 1165 1.1 christos { 1166 1.1 christos /* EL 2(HANDSHAKE) - Archetype 0(NORMAL) */ 1167 1.1 christos { 1168 1.1.1.2 christos /*allow_ack =*/1, 1169 1.1.1.2 christos /*allow_ping =*/1, 1170 1.1.1.2 christos /*allow_crypto =*/1, 1171 1.1.1.2 christos /*allow_handshake_done =*/0, 1172 1.1.1.2 christos /*allow_path_challenge =*/0, 1173 1.1.1.2 christos /*allow_path_response =*/0, 1174 1.1.1.2 christos /*allow_new_conn_id =*/0, 1175 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1176 1.1.1.2 christos /*allow_stream_rel =*/0, 1177 1.1.1.2 christos /*allow_conn_fc =*/0, 1178 1.1.1.2 christos /*allow_conn_close =*/1, 1179 1.1.1.2 christos /*allow_cfq_other =*/0, 1180 1.1.1.2 christos /*allow_new_token =*/0, 1181 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1182 1.1.1.2 christos /*allow_padding =*/1, 1183 1.1.1.2 christos /*require_ack_eliciting =*/0, 1184 1.1.1.2 christos /*bypass_cc =*/0, 1185 1.1 christos }, 1186 1.1 christos /* EL 2(HANDSHAKE) - Archetype 1(PROBE) */ 1187 1.1 christos { 1188 1.1.1.2 christos /*allow_ack =*/1, 1189 1.1.1.2 christos /*allow_ping =*/1, 1190 1.1.1.2 christos /*allow_crypto =*/1, 1191 1.1.1.2 christos /*allow_handshake_done =*/0, 1192 1.1.1.2 christos /*allow_path_challenge =*/0, 1193 1.1.1.2 christos /*allow_path_response =*/0, 1194 1.1.1.2 christos /*allow_new_conn_id =*/0, 1195 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1196 1.1.1.2 christos /*allow_stream_rel =*/0, 1197 1.1.1.2 christos /*allow_conn_fc =*/0, 1198 1.1.1.2 christos /*allow_conn_close =*/1, 1199 1.1.1.2 christos /*allow_cfq_other =*/0, 1200 1.1.1.2 christos /*allow_new_token =*/0, 1201 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1202 1.1.1.2 christos /*allow_padding =*/1, 1203 1.1.1.2 christos /*require_ack_eliciting =*/1, 1204 1.1.1.2 christos /*bypass_cc =*/1, 1205 1.1 christos }, 1206 1.1 christos /* EL 2(HANDSHAKE) - Archetype 2(ACK_ONLY) */ 1207 1.1 christos { 1208 1.1.1.2 christos /*allow_ack =*/1, 1209 1.1.1.2 christos /*allow_ping =*/0, 1210 1.1.1.2 christos /*allow_crypto =*/0, 1211 1.1.1.2 christos /*allow_handshake_done =*/0, 1212 1.1.1.2 christos /*allow_path_challenge =*/0, 1213 1.1.1.2 christos /*allow_path_response =*/0, 1214 1.1.1.2 christos /*allow_new_conn_id =*/0, 1215 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1216 1.1.1.2 christos /*allow_stream_rel =*/0, 1217 1.1.1.2 christos /*allow_conn_fc =*/0, 1218 1.1.1.2 christos /*allow_conn_close =*/0, 1219 1.1.1.2 christos /*allow_cfq_other =*/0, 1220 1.1.1.2 christos /*allow_new_token =*/0, 1221 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1222 1.1.1.2 christos /*allow_padding =*/0, 1223 1.1.1.2 christos /*require_ack_eliciting =*/0, 1224 1.1.1.2 christos /*bypass_cc =*/1, 1225 1.1 christos }, 1226 1.1 christos }, 1227 1.1 christos /* EL 3(1RTT) */ 1228 1.1 christos { 1229 1.1 christos /* EL 3(1RTT) - Archetype 0(NORMAL) */ 1230 1.1 christos { 1231 1.1.1.2 christos /*allow_ack =*/1, 1232 1.1.1.2 christos /*allow_ping =*/1, 1233 1.1.1.2 christos /*allow_crypto =*/1, 1234 1.1.1.2 christos /*allow_handshake_done =*/1, 1235 1.1.1.2 christos /*allow_path_challenge =*/0, 1236 1.1.1.2 christos /*allow_path_response =*/1, 1237 1.1.1.2 christos /*allow_new_conn_id =*/1, 1238 1.1.1.2 christos /*allow_retire_conn_id =*/1, 1239 1.1.1.2 christos /*allow_stream_rel =*/1, 1240 1.1.1.2 christos /*allow_conn_fc =*/1, 1241 1.1.1.2 christos /*allow_conn_close =*/1, 1242 1.1.1.2 christos /*allow_cfq_other =*/1, 1243 1.1.1.2 christos /*allow_new_token =*/1, 1244 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1245 1.1.1.2 christos /*allow_padding =*/1, 1246 1.1.1.2 christos /*require_ack_eliciting =*/0, 1247 1.1.1.2 christos /*bypass_cc =*/0, 1248 1.1 christos }, 1249 1.1 christos /* EL 3(1RTT) - Archetype 1(PROBE) */ 1250 1.1 christos { 1251 1.1.1.2 christos /*allow_ack =*/1, 1252 1.1.1.2 christos /*allow_ping =*/1, 1253 1.1.1.2 christos /*allow_crypto =*/1, 1254 1.1.1.2 christos /*allow_handshake_done =*/1, 1255 1.1.1.2 christos /*allow_path_challenge =*/0, 1256 1.1.1.2 christos /*allow_path_response =*/1, 1257 1.1.1.2 christos /*allow_new_conn_id =*/1, 1258 1.1.1.2 christos /*allow_retire_conn_id =*/1, 1259 1.1.1.2 christos /*allow_stream_rel =*/1, 1260 1.1.1.2 christos /*allow_conn_fc =*/1, 1261 1.1.1.2 christos /*allow_conn_close =*/1, 1262 1.1.1.2 christos /*allow_cfq_other =*/1, 1263 1.1.1.2 christos /*allow_new_token =*/1, 1264 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1265 1.1.1.2 christos /*allow_padding =*/1, 1266 1.1.1.2 christos /*require_ack_eliciting =*/1, 1267 1.1.1.2 christos /*bypass_cc =*/1, 1268 1.1 christos }, 1269 1.1 christos /* EL 3(1RTT) - Archetype 2(ACK_ONLY) */ 1270 1.1 christos { 1271 1.1.1.2 christos /*allow_ack =*/1, 1272 1.1.1.2 christos /*allow_ping =*/0, 1273 1.1.1.2 christos /*allow_crypto =*/0, 1274 1.1.1.2 christos /*allow_handshake_done =*/0, 1275 1.1.1.2 christos /*allow_path_challenge =*/0, 1276 1.1.1.2 christos /*allow_path_response =*/0, 1277 1.1.1.2 christos /*allow_new_conn_id =*/0, 1278 1.1.1.2 christos /*allow_retire_conn_id =*/0, 1279 1.1.1.2 christos /*allow_stream_rel =*/0, 1280 1.1.1.2 christos /*allow_conn_fc =*/0, 1281 1.1.1.2 christos /*allow_conn_close =*/0, 1282 1.1.1.2 christos /*allow_cfq_other =*/0, 1283 1.1.1.2 christos /*allow_new_token =*/0, 1284 1.1.1.2 christos /*allow_force_ack_eliciting =*/1, 1285 1.1.1.2 christos /*allow_padding =*/0, 1286 1.1.1.2 christos /*require_ack_eliciting =*/0, 1287 1.1.1.2 christos /*bypass_cc =*/1, 1288 1.1.1.2 christos } } 1289 1.1 christos }; 1290 1.1 christos 1291 1.1 christos static int txp_get_archetype_data(uint32_t enc_level, 1292 1.1.1.2 christos uint32_t archetype, 1293 1.1.1.2 christos struct archetype_data *a) 1294 1.1 christos { 1295 1.1 christos if (enc_level >= QUIC_ENC_LEVEL_NUM 1296 1.1 christos || archetype >= TX_PACKETISER_ARCHETYPE_NUM) 1297 1.1 christos return 0; 1298 1.1 christos 1299 1.1 christos /* No need to avoid copying this as it should not exceed one int in size. */ 1300 1.1 christos *a = archetypes[enc_level][archetype]; 1301 1.1 christos return 1; 1302 1.1 christos } 1303 1.1 christos 1304 1.1 christos static int txp_determine_geometry(OSSL_QUIC_TX_PACKETISER *txp, 1305 1.1.1.2 christos uint32_t archetype, 1306 1.1.1.2 christos uint32_t enc_level, 1307 1.1.1.2 christos size_t running_total, 1308 1.1.1.2 christos QUIC_PKT_HDR *phdr, 1309 1.1.1.2 christos struct txp_pkt_geom *geom) 1310 1.1 christos { 1311 1.1 christos size_t mdpl, cmpl, hdr_len; 1312 1.1 christos 1313 1.1 christos /* Get information about packet archetype. */ 1314 1.1 christos if (!txp_get_archetype_data(enc_level, archetype, &geom->adata)) 1315 1.1.1.2 christos return 0; 1316 1.1 christos 1317 1.1 christos /* Assemble packet header. */ 1318 1.1.1.2 christos phdr->type = ossl_quic_enc_level_to_pkt_type(enc_level); 1319 1.1.1.2 christos phdr->spin_bit = 0; 1320 1.1.1.2 christos phdr->pn_len = txp_determine_pn_len(txp); 1321 1.1.1.2 christos phdr->partial = 0; 1322 1.1.1.2 christos phdr->fixed = 1; 1323 1.1.1.2 christos phdr->reserved = 0; 1324 1.1.1.2 christos phdr->version = txp->args.protocol_version; 1325 1.1.1.2 christos phdr->dst_conn_id = txp->args.cur_dcid; 1326 1.1.1.2 christos phdr->src_conn_id = txp->args.cur_scid; 1327 1.1 christos 1328 1.1 christos /* 1329 1.1 christos * We need to know the length of the payload to get an accurate header 1330 1.1 christos * length for non-1RTT packets, because the Length field found in 1331 1.1 christos * Initial/Handshake/0-RTT packets uses a variable-length encoding. However, 1332 1.1 christos * we don't have a good idea of the length of our payload, because the 1333 1.1 christos * length of the payload depends on the room in the datagram after fitting 1334 1.1 christos * the header, which depends on the size of the header. 1335 1.1 christos * 1336 1.1 christos * In general, it does not matter if a packet is slightly shorter (because 1337 1.1 christos * e.g. we predicted use of a 2-byte length field, but ended up only needing 1338 1.1 christos * a 1-byte length field). However this does matter for Initial packets 1339 1.1 christos * which must be at least 1200 bytes, which is also the assumed default MTU; 1340 1.1 christos * therefore in many cases Initial packets will be padded to 1200 bytes, 1341 1.1 christos * which means if we overestimated the header size, we will be short by a 1342 1.1 christos * few bytes and the server will ignore the packet for being too short. In 1343 1.1 christos * this case, however, such packets always *will* be padded to meet 1200 1344 1.1 christos * bytes, which requires a 2-byte length field, so we don't actually need to 1345 1.1 christos * worry about this. Thus we estimate the header length assuming a 2-byte 1346 1.1 christos * length field here, which should in practice work well in all cases. 1347 1.1 christos */ 1348 1.1.1.2 christos phdr->len = OSSL_QUIC_VLINT_2B_MAX - phdr->pn_len; 1349 1.1 christos 1350 1.1 christos if (enc_level == QUIC_ENC_LEVEL_INITIAL) { 1351 1.1.1.2 christos phdr->token = txp->initial_token; 1352 1.1 christos phdr->token_len = txp->initial_token_len; 1353 1.1 christos } else { 1354 1.1.1.2 christos phdr->token = NULL; 1355 1.1 christos phdr->token_len = 0; 1356 1.1 christos } 1357 1.1 christos 1358 1.1 christos hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(phdr->dst_conn_id.id_len, 1359 1.1.1.2 christos phdr); 1360 1.1 christos if (hdr_len == 0) 1361 1.1 christos return 0; 1362 1.1 christos 1363 1.1 christos /* MDPL: Maximum datagram payload length. */ 1364 1.1 christos mdpl = txp_get_mdpl(txp); 1365 1.1 christos 1366 1.1 christos /* 1367 1.1 christos * CMPL: Maximum encoded packet size we can put into this datagram given any 1368 1.1 christos * previous packets coalesced into it. 1369 1.1 christos */ 1370 1.1 christos if (running_total > mdpl) 1371 1.1 christos /* Should not be possible, but if it happens: */ 1372 1.1 christos cmpl = 0; 1373 1.1 christos else 1374 1.1 christos cmpl = mdpl - running_total; 1375 1.1 christos 1376 1.1 christos /* CMPPL: Maximum amount we can put into the current packet payload */ 1377 1.1 christos if (!txp_determine_ppl_from_pl(txp, cmpl, enc_level, hdr_len, &geom->cmppl)) 1378 1.1 christos return 0; 1379 1.1 christos 1380 1.1.1.2 christos geom->cmpl = cmpl; 1381 1.1.1.2 christos geom->pkt_overhead = cmpl - geom->cmppl; 1382 1.1.1.2 christos geom->archetype = archetype; 1383 1.1 christos return 1; 1384 1.1 christos } 1385 1.1 christos 1386 1.1 christos static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp, 1387 1.1.1.2 christos uint64_t cc_limit) 1388 1.1 christos { 1389 1.1 christos OSSL_ACKM_PROBE_INFO *probe_info 1390 1.1 christos = ossl_ackm_get0_probe_request(txp->args.ackm); 1391 1.1 christos uint32_t pn_space; 1392 1.1 christos 1393 1.1 christos /* 1394 1.1 christos * If ACKM has requested probe generation (e.g. due to PTO), we generate a 1395 1.1 christos * Probe-archetype packet. Actually, we determine archetype on a 1396 1.1 christos * per-datagram basis, so if any EL wants a probe, do a pass in which 1397 1.1 christos * we try and generate a probe (if needed) for all ELs. 1398 1.1 christos */ 1399 1.1 christos if (probe_info->anti_deadlock_initial > 0 1400 1.1 christos || probe_info->anti_deadlock_handshake > 0) 1401 1.1 christos return TX_PACKETISER_ARCHETYPE_PROBE; 1402 1.1 christos 1403 1.1 christos for (pn_space = QUIC_PN_SPACE_INITIAL; 1404 1.1.1.2 christos pn_space < QUIC_PN_SPACE_NUM; 1405 1.1.1.2 christos ++pn_space) 1406 1.1 christos if (probe_info->pto[pn_space] > 0) 1407 1.1 christos return TX_PACKETISER_ARCHETYPE_PROBE; 1408 1.1 christos 1409 1.1 christos /* 1410 1.1 christos * If we are out of CC budget, we cannot send a normal packet, 1411 1.1 christos * but we can do an ACK-only packet (potentially, if we 1412 1.1 christos * want to send an ACK). 1413 1.1 christos */ 1414 1.1 christos if (cc_limit == 0) 1415 1.1 christos return TX_PACKETISER_ARCHETYPE_ACK_ONLY; 1416 1.1 christos 1417 1.1 christos /* All other packets. */ 1418 1.1 christos return TX_PACKETISER_ARCHETYPE_NORMAL; 1419 1.1 christos } 1420 1.1 christos 1421 1.1 christos static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp, 1422 1.1.1.2 christos uint32_t enc_level, 1423 1.1.1.2 christos uint32_t archetype, 1424 1.1.1.2 christos uint64_t cc_limit, 1425 1.1.1.2 christos uint32_t *conn_close_enc_level) 1426 1.1 christos { 1427 1.1 christos struct archetype_data a; 1428 1.1 christos uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 1429 1.1 christos QUIC_CFQ_ITEM *cfq_item; 1430 1.1 christos 1431 1.1 christos if (!ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level)) 1432 1.1 christos return 0; 1433 1.1 christos 1434 1.1 christos if (!txp_get_archetype_data(enc_level, archetype, &a)) 1435 1.1 christos return 0; 1436 1.1 christos 1437 1.1 christos if (!a.bypass_cc && cc_limit == 0) 1438 1.1 christos /* CC not allowing us to send. */ 1439 1.1 christos return 0; 1440 1.1 christos 1441 1.1 christos /* 1442 1.1 christos * We can produce CONNECTION_CLOSE frames on any EL in principle, which 1443 1.1 christos * means we need to choose which EL we would prefer to use. After a 1444 1.1 christos * connection is fully established we have only one provisioned EL and this 1445 1.1 christos * is a non-issue. Where multiple ELs are provisioned, it is possible the 1446 1.1 christos * peer does not have the keys for the EL yet, which suggests in general it 1447 1.1 christos * is preferable to use the lowest EL which is still provisioned. 1448 1.1 christos * 1449 1.1 christos * However (RFC 9000 s. 10.2.3 & 12.5) we are also required to not send 1450 1.1 christos * application CONNECTION_CLOSE frames in non-1-RTT ELs, so as to not 1451 1.1 christos * potentially leak application data on a connection which has yet to be 1452 1.1 christos * authenticated. Thus when we have an application CONNECTION_CLOSE frame 1453 1.1 christos * queued and need to send it on a non-1-RTT EL, we have to convert it 1454 1.1 christos * into a transport CONNECTION_CLOSE frame which contains no application 1455 1.1 christos * data. Since this loses information, it suggests we should use the 1-RTT 1456 1.1 christos * EL to avoid this if possible, even if a lower EL is also available. 1457 1.1 christos * 1458 1.1 christos * At the same time, just because we have the 1-RTT EL provisioned locally 1459 1.1 christos * does not necessarily mean the peer does, for example if a handshake 1460 1.1 christos * CRYPTO frame has been lost. It is fairly important that CONNECTION_CLOSE 1461 1.1 christos * is signalled in a way we know our peer can decrypt, as we stop processing 1462 1.1 christos * connection retransmission logic for real after connection close and 1463 1.1 christos * simply 'blindly' retransmit the same CONNECTION_CLOSE frame. 1464 1.1 christos * 1465 1.1 christos * This is not a major concern for clients, since if a client has a 1-RTT EL 1466 1.1 christos * provisioned the server is guaranteed to also have a 1-RTT EL provisioned. 1467 1.1 christos * 1468 1.1 christos * TODO(QUIC FUTURE): Revisit this when when have reached a decision on how 1469 1.1 christos * best to implement this 1470 1.1 christos */ 1471 1.1 christos if (*conn_close_enc_level > enc_level 1472 1.1 christos && *conn_close_enc_level != QUIC_ENC_LEVEL_1RTT) 1473 1.1 christos *conn_close_enc_level = enc_level; 1474 1.1 christos 1475 1.1 christos /* Do we need to send a PTO probe? */ 1476 1.1 christos if (a.allow_force_ack_eliciting) { 1477 1.1 christos OSSL_ACKM_PROBE_INFO *probe_info 1478 1.1 christos = ossl_ackm_get0_probe_request(txp->args.ackm); 1479 1.1 christos 1480 1.1 christos if ((enc_level == QUIC_ENC_LEVEL_INITIAL 1481 1.1.1.2 christos && probe_info->anti_deadlock_initial > 0) 1482 1.1 christos || (enc_level == QUIC_ENC_LEVEL_HANDSHAKE 1483 1.1 christos && probe_info->anti_deadlock_handshake > 0) 1484 1.1 christos || probe_info->pto[pn_space] > 0) 1485 1.1 christos return 1; 1486 1.1 christos } 1487 1.1 christos 1488 1.1 christos /* Does the crypto stream for this EL want to produce anything? */ 1489 1.1 christos if (a.allow_crypto && sstream_is_pending(txp->args.crypto[pn_space])) 1490 1.1 christos return 1; 1491 1.1 christos 1492 1.1 christos /* Does the ACKM for this PN space want to produce anything? */ 1493 1.1.1.2 christos if (a.allow_ack && (ossl_ackm_is_ack_desired(txp->args.ackm, pn_space) || (txp->want_ack & (1UL << pn_space)) != 0)) 1494 1.1 christos return 1; 1495 1.1 christos 1496 1.1 christos /* Do we need to force emission of an ACK-eliciting packet? */ 1497 1.1 christos if (a.allow_force_ack_eliciting 1498 1.1 christos && (txp->force_ack_eliciting & (1UL << pn_space)) != 0) 1499 1.1 christos return 1; 1500 1.1 christos 1501 1.1 christos /* Does the connection-level RXFC want to produce a frame? */ 1502 1.1.1.2 christos if (a.allow_conn_fc && (txp->want_max_data || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0))) 1503 1.1 christos return 1; 1504 1.1 christos 1505 1.1 christos /* Do we want to produce a MAX_STREAMS frame? */ 1506 1.1 christos if (a.allow_conn_fc 1507 1.1 christos && (txp->want_max_streams_bidi 1508 1.1 christos || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 1509 1.1.1.2 christos 0) 1510 1.1 christos || txp->want_max_streams_uni 1511 1.1 christos || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 1512 1.1.1.2 christos 0))) 1513 1.1 christos return 1; 1514 1.1 christos 1515 1.1 christos /* Do we want to produce a HANDSHAKE_DONE frame? */ 1516 1.1 christos if (a.allow_handshake_done && txp->want_handshake_done) 1517 1.1 christos return 1; 1518 1.1 christos 1519 1.1 christos /* Do we want to produce a CONNECTION_CLOSE frame? */ 1520 1.1.1.2 christos if (a.allow_conn_close && txp->want_conn_close && *conn_close_enc_level == enc_level) 1521 1.1 christos /* 1522 1.1 christos * This is a bit of a special case since CONNECTION_CLOSE can appear in 1523 1.1 christos * most packet types, and when we decide we want to send it this status 1524 1.1 christos * isn't tied to a specific EL. So if we want to send it, we send it 1525 1.1 christos * only on the lowest non-dropped EL. 1526 1.1 christos */ 1527 1.1 christos return 1; 1528 1.1 christos 1529 1.1 christos /* Does the CFQ have any frames queued for this PN space? */ 1530 1.1 christos if (enc_level != QUIC_ENC_LEVEL_0RTT) 1531 1.1 christos for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space); 1532 1.1.1.2 christos cfq_item != NULL; 1533 1.1.1.2 christos cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) { 1534 1.1 christos uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item); 1535 1.1 christos 1536 1.1 christos switch (frame_type) { 1537 1.1 christos case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID: 1538 1.1 christos if (a.allow_new_conn_id) 1539 1.1 christos return 1; 1540 1.1 christos break; 1541 1.1 christos case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID: 1542 1.1 christos if (a.allow_retire_conn_id) 1543 1.1 christos return 1; 1544 1.1 christos break; 1545 1.1 christos case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN: 1546 1.1 christos if (a.allow_new_token) 1547 1.1 christos return 1; 1548 1.1 christos break; 1549 1.1 christos case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE: 1550 1.1 christos if (a.allow_path_response) 1551 1.1 christos return 1; 1552 1.1 christos break; 1553 1.1 christos default: 1554 1.1 christos if (a.allow_cfq_other) 1555 1.1 christos return 1; 1556 1.1 christos break; 1557 1.1 christos } 1558 1.1.1.2 christos } 1559 1.1 christos 1560 1.1 christos if (a.allow_stream_rel && txp->handshake_complete) { 1561 1.1 christos QUIC_STREAM_ITER it; 1562 1.1 christos 1563 1.1 christos /* If there are any active streams, 0/1-RTT wants to produce a packet. 1564 1.1 christos * Whether a stream is on the active list is required to be precise 1565 1.1 christos * (i.e., a stream is never on the active list if we cannot produce a 1566 1.1 christos * frame for it), and all stream-related frames are governed by 1567 1.1 christos * a.allow_stream_rel (i.e., if we can send one type of stream-related 1568 1.1 christos * frame, we can send any of them), so we don't need to inspect 1569 1.1 christos * individual streams on the active list, just confirm that the active 1570 1.1 christos * list is non-empty. 1571 1.1 christos */ 1572 1.1 christos ossl_quic_stream_iter_init(&it, txp->args.qsm, 0); 1573 1.1 christos if (it.stream != NULL) 1574 1.1 christos return 1; 1575 1.1 christos } 1576 1.1 christos 1577 1.1 christos return 0; 1578 1.1 christos } 1579 1.1 christos 1580 1.1 christos static int sstream_is_pending(QUIC_SSTREAM *sstream) 1581 1.1 christos { 1582 1.1 christos OSSL_QUIC_FRAME_STREAM hdr; 1583 1.1 christos OSSL_QTX_IOVEC iov[2]; 1584 1.1 christos size_t num_iov = OSSL_NELEM(iov); 1585 1.1 christos 1586 1.1 christos return ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, &num_iov); 1587 1.1 christos } 1588 1.1 christos 1589 1.1 christos /* Determine how many bytes we should use for the encoded PN. */ 1590 1.1 christos static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp) 1591 1.1 christos { 1592 1.1 christos return 4; /* TODO(QUIC FUTURE) */ 1593 1.1 christos } 1594 1.1 christos 1595 1.1 christos /* Determine plaintext packet payload length from payload length. */ 1596 1.1 christos static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp, 1597 1.1.1.2 christos size_t pl, 1598 1.1.1.2 christos uint32_t enc_level, 1599 1.1.1.2 christos size_t hdr_len, 1600 1.1.1.2 christos size_t *r) 1601 1.1 christos { 1602 1.1 christos if (pl < hdr_len) 1603 1.1 christos return 0; 1604 1.1 christos 1605 1.1 christos pl -= hdr_len; 1606 1.1 christos 1607 1.1 christos if (!ossl_qtx_calculate_plaintext_payload_len(txp->args.qtx, enc_level, 1608 1.1.1.2 christos pl, &pl)) 1609 1.1 christos return 0; 1610 1.1 christos 1611 1.1 christos *r = pl; 1612 1.1 christos return 1; 1613 1.1 christos } 1614 1.1 christos 1615 1.1 christos static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp) 1616 1.1 christos { 1617 1.1 christos return ossl_qtx_get_mdpl(txp->args.qtx); 1618 1.1 christos } 1619 1.1 christos 1620 1.1 christos static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space, 1621 1.1.1.2 christos void *arg) 1622 1.1 christos { 1623 1.1 christos OSSL_QUIC_TX_PACKETISER *txp = arg; 1624 1.1 christos QUIC_STREAM *s; 1625 1.1 christos 1626 1.1 christos if (stream_id == UINT64_MAX) 1627 1.1 christos return txp->args.crypto[pn_space]; 1628 1.1 christos 1629 1.1 christos s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1630 1.1 christos if (s == NULL) 1631 1.1 christos return NULL; 1632 1.1 christos 1633 1.1 christos return s->sstream; 1634 1.1 christos } 1635 1.1 christos 1636 1.1 christos static void on_regen_notify(uint64_t frame_type, uint64_t stream_id, 1637 1.1.1.2 christos QUIC_TXPIM_PKT *pkt, void *arg) 1638 1.1 christos { 1639 1.1 christos OSSL_QUIC_TX_PACKETISER *txp = arg; 1640 1.1 christos 1641 1.1 christos switch (frame_type) { 1642 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE: 1643 1.1.1.2 christos txp->want_handshake_done = 1; 1644 1.1.1.2 christos break; 1645 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_MAX_DATA: 1646 1.1.1.2 christos txp->want_max_data = 1; 1647 1.1.1.2 christos break; 1648 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI: 1649 1.1.1.2 christos txp->want_max_streams_bidi = 1; 1650 1.1.1.2 christos break; 1651 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI: 1652 1.1.1.2 christos txp->want_max_streams_uni = 1; 1653 1.1.1.2 christos break; 1654 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN: 1655 1.1.1.2 christos txp->want_ack |= (1UL << pkt->ackm_pkt.pkt_space); 1656 1.1.1.2 christos break; 1657 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA: { 1658 1.1.1.2 christos QUIC_STREAM *s 1659 1.1.1.2 christos = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1660 1.1.1.2 christos 1661 1.1.1.2 christos if (s == NULL) 1662 1.1.1.2 christos return; 1663 1.1.1.2 christos 1664 1.1.1.2 christos s->want_max_stream_data = 1; 1665 1.1.1.2 christos ossl_quic_stream_map_update_state(txp->args.qsm, s); 1666 1.1.1.2 christos } break; 1667 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: { 1668 1.1.1.2 christos QUIC_STREAM *s 1669 1.1.1.2 christos = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1670 1.1.1.2 christos 1671 1.1.1.2 christos if (s == NULL) 1672 1.1.1.2 christos return; 1673 1.1.1.2 christos 1674 1.1.1.2 christos ossl_quic_stream_map_schedule_stop_sending(txp->args.qsm, s); 1675 1.1.1.2 christos } break; 1676 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: { 1677 1.1.1.2 christos QUIC_STREAM *s 1678 1.1.1.2 christos = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1679 1.1.1.2 christos 1680 1.1.1.2 christos if (s == NULL) 1681 1.1.1.2 christos return; 1682 1.1.1.2 christos 1683 1.1.1.2 christos s->want_reset_stream = 1; 1684 1.1.1.2 christos ossl_quic_stream_map_update_state(txp->args.qsm, s); 1685 1.1.1.2 christos } break; 1686 1.1.1.2 christos default: 1687 1.1.1.2 christos assert(0); 1688 1.1.1.2 christos break; 1689 1.1 christos } 1690 1.1 christos } 1691 1.1 christos 1692 1.1 christos static int txp_need_ping(OSSL_QUIC_TX_PACKETISER *txp, 1693 1.1.1.2 christos uint32_t pn_space, 1694 1.1.1.2 christos const struct archetype_data *adata) 1695 1.1 christos { 1696 1.1 christos return adata->allow_ping 1697 1.1 christos && (adata->require_ack_eliciting 1698 1.1 christos || (txp->force_ack_eliciting & (1UL << pn_space)) != 0); 1699 1.1 christos } 1700 1.1 christos 1701 1.1 christos static int txp_pkt_init(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp, 1702 1.1.1.2 christos uint32_t enc_level, uint32_t archetype, 1703 1.1.1.2 christos size_t running_total) 1704 1.1 christos { 1705 1.1 christos uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 1706 1.1 christos 1707 1.1 christos if (!txp_determine_geometry(txp, archetype, enc_level, 1708 1.1.1.2 christos running_total, &pkt->phdr, &pkt->geom)) 1709 1.1 christos return 0; 1710 1.1 christos 1711 1.1 christos /* 1712 1.1 christos * Initialise TX helper. If we must be ACK eliciting, reserve 1 byte for 1713 1.1 christos * PING. 1714 1.1 christos */ 1715 1.1 christos if (!tx_helper_init(&pkt->h, txp, enc_level, 1716 1.1.1.2 christos pkt->geom.cmppl, 1717 1.1.1.2 christos txp_need_ping(txp, pn_space, &pkt->geom.adata) ? 1 : 0)) 1718 1.1 christos return 0; 1719 1.1 christos 1720 1.1.1.2 christos pkt->h_valid = 1; 1721 1.1.1.2 christos pkt->tpkt = NULL; 1722 1.1.1.2 christos pkt->stream_head = NULL; 1723 1.1.1.2 christos pkt->force_pad = 0; 1724 1.1 christos return 1; 1725 1.1 christos } 1726 1.1 christos 1727 1.1 christos static void txp_pkt_cleanup(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp) 1728 1.1 christos { 1729 1.1 christos if (!pkt->h_valid) 1730 1.1 christos return; 1731 1.1 christos 1732 1.1 christos tx_helper_cleanup(&pkt->h); 1733 1.1 christos pkt->h_valid = 0; 1734 1.1 christos 1735 1.1 christos if (pkt->tpkt != NULL) { 1736 1.1 christos ossl_quic_txpim_pkt_release(txp->args.txpim, pkt->tpkt); 1737 1.1 christos pkt->tpkt = NULL; 1738 1.1 christos } 1739 1.1 christos } 1740 1.1 christos 1741 1.1 christos static int txp_pkt_postgen_update_pkt_overhead(struct txp_pkt *pkt, 1742 1.1.1.2 christos OSSL_QUIC_TX_PACKETISER *txp) 1743 1.1 christos { 1744 1.1 christos /* 1745 1.1 christos * After we have staged and generated our packets, but before we commit 1746 1.1 christos * them, it is possible for the estimated packet overhead (packet header + 1747 1.1 christos * AEAD tag size) to shrink slightly because we generated a short packet 1748 1.1 christos * whose which can be represented in fewer bytes as a variable-length 1749 1.1 christos * integer than we were (pessimistically) budgeting for. We need to account 1750 1.1 christos * for this to ensure that we get our padding calculation exactly right. 1751 1.1 christos * 1752 1.1 christos * Update pkt_overhead to be accurate now that we know how much data is 1753 1.1 christos * going in a packet. 1754 1.1 christos */ 1755 1.1 christos size_t hdr_len, ciphertext_len; 1756 1.1 christos 1757 1.1 christos if (pkt->h.enc_level == QUIC_ENC_LEVEL_INITIAL) 1758 1.1 christos /* 1759 1.1 christos * Don't update overheads for the INITIAL EL - we have not finished 1760 1.1 christos * appending padding to it and would potentially miscalculate the 1761 1.1 christos * correct padding if we now update the pkt_overhead field to switch to 1762 1.1 christos * e.g. a 1-byte length field in the packet header. Since we are padding 1763 1.1 christos * to QUIC_MIN_INITIAL_DGRAM_LEN which requires a 2-byte length field, 1764 1.1 christos * this is guaranteed to be moot anyway. See comment in 1765 1.1 christos * txp_determine_geometry for more information. 1766 1.1 christos */ 1767 1.1 christos return 1; 1768 1.1 christos 1769 1.1 christos if (!ossl_qtx_calculate_ciphertext_payload_len(txp->args.qtx, pkt->h.enc_level, 1770 1.1.1.2 christos pkt->h.bytes_appended, 1771 1.1.1.2 christos &ciphertext_len)) 1772 1.1 christos return 0; 1773 1.1 christos 1774 1.1 christos pkt->phdr.len = ciphertext_len; 1775 1.1 christos 1776 1.1 christos hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(pkt->phdr.dst_conn_id.id_len, 1777 1.1.1.2 christos &pkt->phdr); 1778 1.1 christos 1779 1.1 christos pkt->geom.pkt_overhead = hdr_len + ciphertext_len - pkt->h.bytes_appended; 1780 1.1 christos return 1; 1781 1.1 christos } 1782 1.1 christos 1783 1.1 christos static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id, 1784 1.1.1.2 christos QUIC_TXPIM_PKT *pkt, void *arg) 1785 1.1 christos { 1786 1.1 christos OSSL_QUIC_TX_PACKETISER *txp = arg; 1787 1.1 christos 1788 1.1 christos switch (frame_type) { 1789 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: { 1790 1.1.1.2 christos QUIC_STREAM *s 1791 1.1.1.2 christos = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1792 1.1.1.2 christos 1793 1.1.1.2 christos if (s == NULL) 1794 1.1.1.2 christos return; 1795 1.1.1.2 christos 1796 1.1.1.2 christos s->acked_stop_sending = 1; 1797 1.1.1.2 christos ossl_quic_stream_map_update_state(txp->args.qsm, s); 1798 1.1.1.2 christos } break; 1799 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: { 1800 1.1.1.2 christos QUIC_STREAM *s 1801 1.1.1.2 christos = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1802 1.1 christos 1803 1.1.1.2 christos if (s == NULL) 1804 1.1.1.2 christos return; 1805 1.1 christos 1806 1.1.1.2 christos /* 1807 1.1.1.2 christos * We must already be in RESET_SENT or RESET_RECVD if we are 1808 1.1.1.2 christos * here, so we don't need to check state here. 1809 1.1.1.2 christos */ 1810 1.1.1.2 christos ossl_quic_stream_map_notify_reset_stream_acked(txp->args.qsm, s); 1811 1.1.1.2 christos ossl_quic_stream_map_update_state(txp->args.qsm, s); 1812 1.1.1.2 christos } break; 1813 1.1.1.2 christos default: 1814 1.1.1.2 christos assert(0); 1815 1.1.1.2 christos break; 1816 1.1 christos } 1817 1.1 christos } 1818 1.1 christos 1819 1.1 christos static int txp_pkt_append_padding(struct txp_pkt *pkt, 1820 1.1.1.2 christos OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes) 1821 1.1 christos { 1822 1.1 christos WPACKET *wpkt; 1823 1.1 christos 1824 1.1 christos if (num_bytes == 0) 1825 1.1 christos return 1; 1826 1.1 christos 1827 1.1 christos if (!ossl_assert(pkt->h_valid)) 1828 1.1 christos return 0; 1829 1.1 christos 1830 1.1 christos if (!ossl_assert(pkt->tpkt != NULL)) 1831 1.1 christos return 0; 1832 1.1 christos 1833 1.1 christos wpkt = tx_helper_begin(&pkt->h); 1834 1.1 christos if (wpkt == NULL) 1835 1.1 christos return 0; 1836 1.1 christos 1837 1.1 christos if (!ossl_quic_wire_encode_padding(wpkt, num_bytes)) { 1838 1.1 christos tx_helper_rollback(&pkt->h); 1839 1.1 christos return 0; 1840 1.1 christos } 1841 1.1 christos 1842 1.1 christos if (!tx_helper_commit(&pkt->h)) 1843 1.1 christos return 0; 1844 1.1 christos 1845 1.1.1.2 christos pkt->tpkt->ackm_pkt.num_bytes += num_bytes; 1846 1.1 christos /* Cannot be non-inflight if we have a PADDING frame */ 1847 1.1.1.2 christos pkt->tpkt->ackm_pkt.is_inflight = 1; 1848 1.1 christos return 1; 1849 1.1 christos } 1850 1.1 christos 1851 1.1 christos static void on_sstream_updated(uint64_t stream_id, void *arg) 1852 1.1 christos { 1853 1.1 christos OSSL_QUIC_TX_PACKETISER *txp = arg; 1854 1.1 christos QUIC_STREAM *s; 1855 1.1 christos 1856 1.1 christos s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); 1857 1.1 christos if (s == NULL) 1858 1.1 christos return; 1859 1.1 christos 1860 1.1 christos ossl_quic_stream_map_update_state(txp->args.qsm, s); 1861 1.1 christos } 1862 1.1 christos 1863 1.1 christos /* 1864 1.1 christos * Returns 1 if we can send that many bytes in closing state, 0 otherwise. 1865 1.1 christos * Also maintains the bytes sent state if it returns a success. 1866 1.1 christos */ 1867 1.1 christos static int try_commit_conn_close(OSSL_QUIC_TX_PACKETISER *txp, size_t n) 1868 1.1 christos { 1869 1.1 christos int res; 1870 1.1 christos 1871 1.1 christos /* We can always send the first connection close frame */ 1872 1.1 christos if (txp->closing_bytes_recv == 0) 1873 1.1 christos return 1; 1874 1.1 christos 1875 1.1 christos /* 1876 1.1 christos * RFC 9000 s. 10.2.1 Closing Connection State: 1877 1.1 christos * To avoid being used for an amplification attack, such 1878 1.1 christos * endpoints MUST limit the cumulative size of packets it sends 1879 1.1 christos * to three times the cumulative size of the packets that are 1880 1.1 christos * received and attributed to the connection. 1881 1.1 christos * and: 1882 1.1 christos * An endpoint in the closing state MUST either discard packets 1883 1.1 christos * received from an unvalidated address or limit the cumulative 1884 1.1 christos * size of packets it sends to an unvalidated address to three 1885 1.1 christos * times the size of packets it receives from that address. 1886 1.1 christos */ 1887 1.1 christos res = txp->closing_bytes_xmit + n <= txp->closing_bytes_recv * 3; 1888 1.1 christos 1889 1.1 christos /* 1890 1.1 christos * Attribute the bytes to the connection, if we are allowed to send them 1891 1.1 christos * and this isn't the first closing frame. 1892 1.1 christos */ 1893 1.1 christos if (res && txp->closing_bytes_recv != 0) 1894 1.1 christos txp->closing_bytes_xmit += n; 1895 1.1 christos return res; 1896 1.1 christos } 1897 1.1 christos 1898 1.1 christos void ossl_quic_tx_packetiser_record_received_closing_bytes( 1899 1.1.1.2 christos OSSL_QUIC_TX_PACKETISER *txp, size_t n) 1900 1.1 christos { 1901 1.1 christos txp->closing_bytes_recv += n; 1902 1.1 christos } 1903 1.1 christos 1904 1.1 christos static int txp_generate_pre_token(OSSL_QUIC_TX_PACKETISER *txp, 1905 1.1.1.2 christos struct txp_pkt *pkt, 1906 1.1.1.2 christos int chosen_for_conn_close, 1907 1.1.1.2 christos int *can_be_non_inflight) 1908 1.1 christos { 1909 1.1 christos const uint32_t enc_level = pkt->h.enc_level; 1910 1.1 christos const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 1911 1.1 christos const struct archetype_data *a = &pkt->geom.adata; 1912 1.1 christos QUIC_TXPIM_PKT *tpkt = pkt->tpkt; 1913 1.1 christos struct tx_helper *h = &pkt->h; 1914 1.1 christos const OSSL_QUIC_FRAME_ACK *ack; 1915 1.1 christos OSSL_QUIC_FRAME_ACK ack2; 1916 1.1 christos 1917 1.1 christos tpkt->ackm_pkt.largest_acked = QUIC_PN_INVALID; 1918 1.1 christos 1919 1.1 christos /* ACK Frames (Regenerate) */ 1920 1.1 christos if (a->allow_ack 1921 1.1 christos && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_ACK 1922 1.1 christos && (((txp->want_ack & (1UL << pn_space)) != 0) 1923 1.1 christos || ossl_ackm_is_ack_desired(txp->args.ackm, pn_space)) 1924 1.1 christos && (ack = ossl_ackm_get_ack_frame(txp->args.ackm, pn_space)) != NULL) { 1925 1.1 christos WPACKET *wpkt = tx_helper_begin(h); 1926 1.1 christos 1927 1.1 christos if (wpkt == NULL) 1928 1.1 christos return 0; 1929 1.1 christos 1930 1.1 christos /* We do not currently support ECN */ 1931 1.1 christos ack2 = *ack; 1932 1.1 christos ack2.ecn_present = 0; 1933 1.1 christos 1934 1.1 christos if (ossl_quic_wire_encode_frame_ack(wpkt, 1935 1.1.1.2 christos txp->args.ack_delay_exponent, 1936 1.1.1.2 christos &ack2)) { 1937 1.1 christos if (!tx_helper_commit(h)) 1938 1.1 christos return 0; 1939 1.1 christos 1940 1.1 christos tpkt->had_ack_frame = 1; 1941 1.1 christos 1942 1.1 christos if (ack->num_ack_ranges > 0) 1943 1.1 christos tpkt->ackm_pkt.largest_acked = ack->ack_ranges[0].end; 1944 1.1 christos 1945 1.1 christos if (txp->ack_tx_cb != NULL) 1946 1.1 christos txp->ack_tx_cb(&ack2, pn_space, txp->ack_tx_cb_arg); 1947 1.1 christos } else { 1948 1.1 christos tx_helper_rollback(h); 1949 1.1 christos } 1950 1.1 christos } 1951 1.1 christos 1952 1.1 christos /* CONNECTION_CLOSE Frames (Regenerate) */ 1953 1.1 christos if (a->allow_conn_close && txp->want_conn_close && chosen_for_conn_close) { 1954 1.1 christos WPACKET *wpkt = tx_helper_begin(h); 1955 1.1 christos OSSL_QUIC_FRAME_CONN_CLOSE f, *pf = &txp->conn_close_frame; 1956 1.1 christos size_t l; 1957 1.1 christos 1958 1.1 christos if (wpkt == NULL) 1959 1.1 christos return 0; 1960 1.1 christos 1961 1.1 christos /* 1962 1.1 christos * Application CONNECTION_CLOSE frames may only be sent in the 1963 1.1 christos * Application PN space, as otherwise they may be sent before a 1964 1.1 christos * connection is authenticated and leak application data. Therefore, if 1965 1.1 christos * we need to send a CONNECTION_CLOSE frame in another PN space and were 1966 1.1 christos * given an application CONNECTION_CLOSE frame, convert it into a 1967 1.1 christos * transport CONNECTION_CLOSE frame, removing any sensitive application 1968 1.1 christos * data. 1969 1.1 christos * 1970 1.1 christos * RFC 9000 s. 10.2.3: "A CONNECTION_CLOSE of type 0x1d MUST be replaced 1971 1.1 christos * by a CONNECTION_CLOSE of type 0x1c when sending the frame in Initial 1972 1.1 christos * or Handshake packets. Otherwise, information about the application 1973 1.1 christos * state might be revealed. Endpoints MUST clear the value of the Reason 1974 1.1 christos * Phrase field and SHOULD use the APPLICATION_ERROR code when 1975 1.1 christos * converting to a CONNECTION_CLOSE of type 0x1c." 1976 1.1 christos */ 1977 1.1 christos if (pn_space != QUIC_PN_SPACE_APP && pf->is_app) { 1978 1.1 christos pf = &f; 1979 1.1.1.2 christos pf->is_app = 0; 1980 1.1.1.2 christos pf->frame_type = 0; 1981 1.1.1.2 christos pf->error_code = OSSL_QUIC_ERR_APPLICATION_ERROR; 1982 1.1.1.2 christos pf->reason = NULL; 1983 1.1.1.2 christos pf->reason_len = 0; 1984 1.1 christos } 1985 1.1 christos 1986 1.1 christos if (ossl_quic_wire_encode_frame_conn_close(wpkt, pf) 1987 1.1.1.2 christos && WPACKET_get_total_written(wpkt, &l) 1988 1.1.1.2 christos && try_commit_conn_close(txp, l)) { 1989 1.1 christos if (!tx_helper_commit(h)) 1990 1.1 christos return 0; 1991 1.1 christos 1992 1.1 christos tpkt->had_conn_close = 1; 1993 1.1 christos *can_be_non_inflight = 0; 1994 1.1 christos } else { 1995 1.1 christos tx_helper_rollback(h); 1996 1.1 christos } 1997 1.1 christos } 1998 1.1 christos 1999 1.1 christos return 1; 2000 1.1 christos } 2001 1.1 christos 2002 1.1 christos static int try_len(size_t space_left, size_t orig_len, 2003 1.1.1.2 christos size_t base_hdr_len, size_t lenbytes, 2004 1.1.1.2 christos uint64_t maxn, size_t *hdr_len, size_t *payload_len) 2005 1.1 christos { 2006 1.1 christos size_t n; 2007 1.1 christos size_t maxn_ = maxn > SIZE_MAX ? SIZE_MAX : (size_t)maxn; 2008 1.1 christos 2009 1.1 christos *hdr_len = base_hdr_len + lenbytes; 2010 1.1 christos 2011 1.1 christos if (orig_len == 0 && space_left >= *hdr_len) { 2012 1.1 christos *payload_len = 0; 2013 1.1 christos return 1; 2014 1.1 christos } 2015 1.1 christos 2016 1.1 christos n = orig_len; 2017 1.1 christos if (n > maxn_) 2018 1.1 christos n = maxn_; 2019 1.1 christos if (n + *hdr_len > space_left) 2020 1.1 christos n = (space_left >= *hdr_len) ? space_left - *hdr_len : 0; 2021 1.1 christos 2022 1.1 christos *payload_len = n; 2023 1.1 christos return n > 0; 2024 1.1 christos } 2025 1.1 christos 2026 1.1 christos static int determine_len(size_t space_left, size_t orig_len, 2027 1.1.1.2 christos size_t base_hdr_len, 2028 1.1.1.2 christos uint64_t *hlen, uint64_t *len) 2029 1.1 christos { 2030 1.1 christos int ok = 0; 2031 1.1 christos size_t chosen_payload_len = 0; 2032 1.1.1.2 christos size_t chosen_hdr_len = 0; 2033 1.1 christos size_t payload_len[4], hdr_len[4]; 2034 1.1.1.2 christos int i, valid[4] = { 0 }; 2035 1.1 christos 2036 1.1 christos valid[0] = try_len(space_left, orig_len, base_hdr_len, 2037 1.1.1.2 christos 1, OSSL_QUIC_VLINT_1B_MAX, 2038 1.1.1.2 christos &hdr_len[0], &payload_len[0]); 2039 1.1 christos valid[1] = try_len(space_left, orig_len, base_hdr_len, 2040 1.1.1.2 christos 2, OSSL_QUIC_VLINT_2B_MAX, 2041 1.1.1.2 christos &hdr_len[1], &payload_len[1]); 2042 1.1 christos valid[2] = try_len(space_left, orig_len, base_hdr_len, 2043 1.1.1.2 christos 4, OSSL_QUIC_VLINT_4B_MAX, 2044 1.1.1.2 christos &hdr_len[2], &payload_len[2]); 2045 1.1 christos valid[3] = try_len(space_left, orig_len, base_hdr_len, 2046 1.1.1.2 christos 8, OSSL_QUIC_VLINT_8B_MAX, 2047 1.1.1.2 christos &hdr_len[3], &payload_len[3]); 2048 1.1 christos 2049 1.1.1.2 christos for (i = OSSL_NELEM(valid) - 1; i >= 0; --i) 2050 1.1 christos if (valid[i] && payload_len[i] >= chosen_payload_len) { 2051 1.1 christos chosen_payload_len = payload_len[i]; 2052 1.1.1.2 christos chosen_hdr_len = hdr_len[i]; 2053 1.1.1.2 christos ok = 1; 2054 1.1 christos } 2055 1.1 christos 2056 1.1 christos *hlen = chosen_hdr_len; 2057 1.1.1.2 christos *len = chosen_payload_len; 2058 1.1 christos return ok; 2059 1.1 christos } 2060 1.1 christos 2061 1.1 christos /* 2062 1.1 christos * Given a CRYPTO frame header with accurate chdr->len and a budget 2063 1.1 christos * (space_left), try to find the optimal value of chdr->len to fill as much of 2064 1.1 christos * the budget as possible. This is slightly hairy because larger values of 2065 1.1 christos * chdr->len cause larger encoded sizes of the length field of the frame, which 2066 1.1 christos * in turn mean less space available for payload data. We check all possible 2067 1.1 christos * encodings and choose the optimal encoding. 2068 1.1 christos */ 2069 1.1 christos static int determine_crypto_len(struct tx_helper *h, 2070 1.1.1.2 christos OSSL_QUIC_FRAME_CRYPTO *chdr, 2071 1.1.1.2 christos size_t space_left, 2072 1.1.1.2 christos uint64_t *hlen, 2073 1.1.1.2 christos uint64_t *len) 2074 1.1 christos { 2075 1.1 christos size_t orig_len; 2076 1.1 christos size_t base_hdr_len; /* CRYPTO header length without length field */ 2077 1.1 christos 2078 1.1 christos if (chdr->len > SIZE_MAX) 2079 1.1 christos return 0; 2080 1.1 christos 2081 1.1 christos orig_len = (size_t)chdr->len; 2082 1.1 christos 2083 1.1 christos chdr->len = 0; 2084 1.1 christos base_hdr_len = ossl_quic_wire_get_encoded_frame_len_crypto_hdr(chdr); 2085 1.1 christos chdr->len = orig_len; 2086 1.1 christos if (base_hdr_len == 0) 2087 1.1 christos return 0; 2088 1.1 christos 2089 1.1 christos --base_hdr_len; 2090 1.1 christos 2091 1.1 christos return determine_len(space_left, orig_len, base_hdr_len, hlen, len); 2092 1.1 christos } 2093 1.1 christos 2094 1.1 christos static int determine_stream_len(struct tx_helper *h, 2095 1.1.1.2 christos OSSL_QUIC_FRAME_STREAM *shdr, 2096 1.1.1.2 christos size_t space_left, 2097 1.1.1.2 christos uint64_t *hlen, 2098 1.1.1.2 christos uint64_t *len) 2099 1.1 christos { 2100 1.1 christos size_t orig_len; 2101 1.1 christos size_t base_hdr_len; /* STREAM header length without length field */ 2102 1.1 christos 2103 1.1 christos if (shdr->len > SIZE_MAX) 2104 1.1 christos return 0; 2105 1.1 christos 2106 1.1 christos orig_len = (size_t)shdr->len; 2107 1.1 christos 2108 1.1 christos shdr->len = 0; 2109 1.1 christos base_hdr_len = ossl_quic_wire_get_encoded_frame_len_stream_hdr(shdr); 2110 1.1 christos shdr->len = orig_len; 2111 1.1 christos if (base_hdr_len == 0) 2112 1.1 christos return 0; 2113 1.1 christos 2114 1.1 christos if (shdr->has_explicit_len) 2115 1.1 christos --base_hdr_len; 2116 1.1 christos 2117 1.1 christos return determine_len(space_left, orig_len, base_hdr_len, hlen, len); 2118 1.1 christos } 2119 1.1 christos 2120 1.1 christos static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp, 2121 1.1.1.2 christos struct txp_pkt *pkt, 2122 1.1.1.2 christos int *have_ack_eliciting) 2123 1.1 christos { 2124 1.1 christos const uint32_t enc_level = pkt->h.enc_level; 2125 1.1 christos const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 2126 1.1 christos QUIC_TXPIM_PKT *tpkt = pkt->tpkt; 2127 1.1 christos struct tx_helper *h = &pkt->h; 2128 1.1 christos size_t num_stream_iovec; 2129 1.1.1.2 christos OSSL_QUIC_FRAME_STREAM shdr = { 0 }; 2130 1.1.1.2 christos OSSL_QUIC_FRAME_CRYPTO chdr = { 0 }; 2131 1.1 christos OSSL_QTX_IOVEC iov[2]; 2132 1.1 christos uint64_t hdr_bytes; 2133 1.1 christos WPACKET *wpkt; 2134 1.1.1.2 christos QUIC_TXPIM_CHUNK chunk = { 0 }; 2135 1.1 christos size_t i, space_left; 2136 1.1 christos 2137 1.1 christos for (i = 0;; ++i) { 2138 1.1 christos space_left = tx_helper_get_space_left(h); 2139 1.1 christos 2140 1.1 christos if (space_left < MIN_FRAME_SIZE_CRYPTO) 2141 1.1 christos return 1; /* no point trying */ 2142 1.1 christos 2143 1.1 christos /* Do we have any CRYPTO data waiting? */ 2144 1.1 christos num_stream_iovec = OSSL_NELEM(iov); 2145 1.1 christos if (!ossl_quic_sstream_get_stream_frame(txp->args.crypto[pn_space], 2146 1.1.1.2 christos i, &shdr, iov, 2147 1.1.1.2 christos &num_stream_iovec)) 2148 1.1 christos return 1; /* nothing to do */ 2149 1.1 christos 2150 1.1 christos /* Convert STREAM frame header to CRYPTO frame header */ 2151 1.1 christos chdr.offset = shdr.offset; 2152 1.1.1.2 christos chdr.len = shdr.len; 2153 1.1 christos 2154 1.1 christos if (chdr.len == 0) 2155 1.1 christos return 1; /* nothing to do */ 2156 1.1 christos 2157 1.1 christos /* Find best fit (header length, payload length) combination. */ 2158 1.1 christos if (!determine_crypto_len(h, &chdr, space_left, &hdr_bytes, 2159 1.1.1.2 christos &chdr.len)) 2160 1.1 christos return 1; /* can't fit anything */ 2161 1.1 christos 2162 1.1 christos /* 2163 1.1 christos * Truncate IOVs to match our chosen length. 2164 1.1 christos * 2165 1.1 christos * The length cannot be more than SIZE_MAX because this length comes 2166 1.1 christos * from our send stream buffer. 2167 1.1 christos */ 2168 1.1 christos ossl_quic_sstream_adjust_iov((size_t)chdr.len, iov, num_stream_iovec); 2169 1.1 christos 2170 1.1 christos /* 2171 1.1 christos * Ensure we have enough iovecs allocated (1 for the header, up to 2 for 2172 1.1 christos * the stream data.) 2173 1.1 christos */ 2174 1.1 christos if (!txp_el_ensure_iovec(&txp->el[enc_level], h->num_iovec + 3)) 2175 1.1 christos return 0; /* alloc error */ 2176 1.1 christos 2177 1.1 christos /* Encode the header. */ 2178 1.1 christos wpkt = tx_helper_begin(h); 2179 1.1 christos if (wpkt == NULL) 2180 1.1 christos return 0; /* alloc error */ 2181 1.1 christos 2182 1.1 christos if (!ossl_quic_wire_encode_frame_crypto_hdr(wpkt, &chdr)) { 2183 1.1 christos tx_helper_rollback(h); 2184 1.1 christos return 1; /* can't fit */ 2185 1.1 christos } 2186 1.1 christos 2187 1.1 christos if (!tx_helper_commit(h)) 2188 1.1 christos return 0; /* alloc error */ 2189 1.1 christos 2190 1.1 christos /* Add payload iovecs to the helper (infallible). */ 2191 1.1 christos for (i = 0; i < num_stream_iovec; ++i) 2192 1.1 christos tx_helper_append_iovec(h, iov[i].buf, iov[i].buf_len); 2193 1.1 christos 2194 1.1 christos *have_ack_eliciting = 1; 2195 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2196 1.1 christos 2197 1.1 christos /* Log chunk to TXPIM. */ 2198 1.1 christos chunk.stream_id = UINT64_MAX; /* crypto stream */ 2199 1.1.1.2 christos chunk.start = chdr.offset; 2200 1.1.1.2 christos chunk.end = chdr.offset + chdr.len - 1; 2201 1.1.1.2 christos chunk.has_fin = 0; /* Crypto stream never ends */ 2202 1.1 christos if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk)) 2203 1.1 christos return 0; /* alloc error */ 2204 1.1 christos } 2205 1.1 christos } 2206 1.1 christos 2207 1.1 christos struct chunk_info { 2208 1.1 christos OSSL_QUIC_FRAME_STREAM shdr; 2209 1.1 christos uint64_t orig_len; 2210 1.1 christos OSSL_QTX_IOVEC iov[2]; 2211 1.1 christos size_t num_stream_iovec; 2212 1.1 christos int valid; 2213 1.1 christos }; 2214 1.1 christos 2215 1.1 christos static int txp_plan_stream_chunk(OSSL_QUIC_TX_PACKETISER *txp, 2216 1.1.1.2 christos struct tx_helper *h, 2217 1.1.1.2 christos QUIC_SSTREAM *sstream, 2218 1.1.1.2 christos QUIC_TXFC *stream_txfc, 2219 1.1.1.2 christos size_t skip, 2220 1.1.1.2 christos struct chunk_info *chunk, 2221 1.1.1.2 christos uint64_t consumed) 2222 1.1 christos { 2223 1.1 christos uint64_t fc_credit, fc_swm, fc_limit; 2224 1.1 christos 2225 1.1 christos chunk->num_stream_iovec = OSSL_NELEM(chunk->iov); 2226 1.1 christos chunk->valid = ossl_quic_sstream_get_stream_frame(sstream, skip, 2227 1.1.1.2 christos &chunk->shdr, 2228 1.1.1.2 christos chunk->iov, 2229 1.1.1.2 christos &chunk->num_stream_iovec); 2230 1.1 christos if (!chunk->valid) 2231 1.1 christos return 1; 2232 1.1 christos 2233 1.1 christos if (!ossl_assert(chunk->shdr.len > 0 || chunk->shdr.is_fin)) 2234 1.1 christos /* Should only have 0-length chunk if FIN */ 2235 1.1 christos return 0; 2236 1.1 christos 2237 1.1 christos chunk->orig_len = chunk->shdr.len; 2238 1.1 christos 2239 1.1 christos /* Clamp according to connection and stream-level TXFC. */ 2240 1.1.1.2 christos fc_credit = ossl_quic_txfc_get_credit(stream_txfc, consumed); 2241 1.1.1.2 christos fc_swm = ossl_quic_txfc_get_swm(stream_txfc); 2242 1.1.1.2 christos fc_limit = fc_swm + fc_credit; 2243 1.1 christos 2244 1.1 christos if (chunk->shdr.len > 0 && chunk->shdr.offset + chunk->shdr.len > fc_limit) { 2245 1.1 christos chunk->shdr.len = (fc_limit <= chunk->shdr.offset) 2246 1.1.1.2 christos ? 0 2247 1.1.1.2 christos : fc_limit - chunk->shdr.offset; 2248 1.1 christos chunk->shdr.is_fin = 0; 2249 1.1 christos } 2250 1.1 christos 2251 1.1 christos if (chunk->shdr.len == 0 && !chunk->shdr.is_fin) { 2252 1.1 christos /* 2253 1.1 christos * Nothing to do due to TXFC. Since SSTREAM returns chunks in ascending 2254 1.1 christos * order of offset we don't need to check any later chunks, so stop 2255 1.1 christos * iterating here. 2256 1.1 christos */ 2257 1.1 christos chunk->valid = 0; 2258 1.1 christos return 1; 2259 1.1 christos } 2260 1.1 christos 2261 1.1 christos return 1; 2262 1.1 christos } 2263 1.1 christos 2264 1.1 christos /* 2265 1.1 christos * Returns 0 on fatal error (e.g. allocation failure), 1 on success. 2266 1.1 christos * *packet_full is set to 1 if there is no longer enough room for another STREAM 2267 1.1 christos * frame. 2268 1.1 christos */ 2269 1.1 christos static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp, 2270 1.1.1.2 christos struct txp_pkt *pkt, 2271 1.1.1.2 christos uint64_t id, 2272 1.1.1.2 christos QUIC_SSTREAM *sstream, 2273 1.1.1.2 christos QUIC_TXFC *stream_txfc, 2274 1.1.1.2 christos QUIC_STREAM *next_stream, 2275 1.1.1.2 christos int *have_ack_eliciting, 2276 1.1.1.2 christos int *packet_full, 2277 1.1.1.2 christos uint64_t *new_credit_consumed, 2278 1.1.1.2 christos uint64_t conn_consumed) 2279 1.1 christos { 2280 1.1 christos int rc = 0; 2281 1.1.1.2 christos struct chunk_info chunks[2] = { 0 }; 2282 1.1 christos const uint32_t enc_level = pkt->h.enc_level; 2283 1.1 christos QUIC_TXPIM_PKT *tpkt = pkt->tpkt; 2284 1.1 christos struct tx_helper *h = &pkt->h; 2285 1.1 christos OSSL_QUIC_FRAME_STREAM *shdr; 2286 1.1 christos WPACKET *wpkt; 2287 1.1 christos QUIC_TXPIM_CHUNK chunk; 2288 1.1 christos size_t i, j, space_left; 2289 1.1 christos int can_fill_payload, use_explicit_len; 2290 1.1 christos int could_have_following_chunk; 2291 1.1 christos uint64_t orig_len; 2292 1.1 christos uint64_t hdr_len_implicit, payload_len_implicit; 2293 1.1 christos uint64_t hdr_len_explicit, payload_len_explicit; 2294 1.1 christos uint64_t fc_swm, fc_new_hwm; 2295 1.1 christos 2296 1.1.1.2 christos fc_swm = ossl_quic_txfc_get_swm(stream_txfc); 2297 1.1.1.2 christos fc_new_hwm = fc_swm; 2298 1.1 christos 2299 1.1 christos /* 2300 1.1 christos * Load the first two chunks if any offered by the send stream. We retrieve 2301 1.1 christos * the next chunk in advance so we can determine if we need to send any more 2302 1.1 christos * chunks from the same stream after this one, which is needed when 2303 1.1 christos * determining when we can use an implicit length in a STREAM frame. 2304 1.1 christos */ 2305 1.1 christos for (i = 0; i < 2; ++i) { 2306 1.1 christos if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i, &chunks[i], 2307 1.1.1.2 christos conn_consumed)) 2308 1.1 christos goto err; 2309 1.1 christos 2310 1.1 christos if (i == 0 && !chunks[i].valid) { 2311 1.1 christos /* No chunks, nothing to do. */ 2312 1.1 christos rc = 1; 2313 1.1 christos goto err; 2314 1.1 christos } 2315 1.1 christos chunks[i].shdr.stream_id = id; 2316 1.1 christos } 2317 1.1 christos 2318 1.1 christos for (i = 0;; ++i) { 2319 1.1 christos space_left = tx_helper_get_space_left(h); 2320 1.1 christos 2321 1.1 christos if (!chunks[i % 2].valid) { 2322 1.1 christos /* Out of chunks; we're done. */ 2323 1.1 christos rc = 1; 2324 1.1 christos goto err; 2325 1.1 christos } 2326 1.1 christos 2327 1.1 christos if (space_left < MIN_FRAME_SIZE_STREAM) { 2328 1.1 christos *packet_full = 1; 2329 1.1 christos rc = 1; 2330 1.1 christos goto err; 2331 1.1 christos } 2332 1.1 christos 2333 1.1 christos if (!ossl_assert(!h->done_implicit)) 2334 1.1 christos /* 2335 1.1 christos * Logic below should have ensured we didn't append an 2336 1.1 christos * implicit-length unless we filled the packet or didn't have 2337 1.1 christos * another stream to handle, so this should not be possible. 2338 1.1 christos */ 2339 1.1 christos goto err; 2340 1.1 christos 2341 1.1 christos shdr = &chunks[i % 2].shdr; 2342 1.1 christos orig_len = chunks[i % 2].orig_len; 2343 1.1 christos if (i > 0) 2344 1.1 christos /* Load next chunk for lookahead. */ 2345 1.1 christos if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i + 1, 2346 1.1.1.2 christos &chunks[(i + 1) % 2], conn_consumed)) 2347 1.1 christos goto err; 2348 1.1 christos 2349 1.1 christos /* 2350 1.1 christos * Find best fit (header length, payload length) combination for if we 2351 1.1 christos * use an implicit length. 2352 1.1 christos */ 2353 1.1 christos shdr->has_explicit_len = 0; 2354 1.1 christos hdr_len_implicit = payload_len_implicit = 0; 2355 1.1 christos if (!determine_stream_len(h, shdr, space_left, 2356 1.1.1.2 christos &hdr_len_implicit, &payload_len_implicit)) { 2357 1.1 christos *packet_full = 1; 2358 1.1 christos rc = 1; 2359 1.1 christos goto err; /* can't fit anything */ 2360 1.1 christos } 2361 1.1 christos 2362 1.1 christos /* 2363 1.1 christos * If there is a next stream, we don't use the implicit length so we can 2364 1.1 christos * add more STREAM frames after this one, unless there is enough data 2365 1.1 christos * for this STREAM frame to fill the packet. 2366 1.1 christos */ 2367 1.1 christos can_fill_payload = (hdr_len_implicit + payload_len_implicit 2368 1.1.1.2 christos >= space_left); 2369 1.1 christos 2370 1.1 christos /* 2371 1.1 christos * Is there is a stream after this one, or another chunk pending 2372 1.1 christos * transmission in this stream? 2373 1.1 christos */ 2374 1.1 christos could_have_following_chunk 2375 1.1 christos = (next_stream != NULL || chunks[(i + 1) % 2].valid); 2376 1.1 christos 2377 1.1 christos /* Choose between explicit or implicit length representations. */ 2378 1.1 christos use_explicit_len = !((can_fill_payload || !could_have_following_chunk) 2379 1.1.1.2 christos && !pkt->force_pad); 2380 1.1 christos 2381 1.1 christos if (use_explicit_len) { 2382 1.1 christos /* 2383 1.1 christos * Find best fit (header length, payload length) combination for if 2384 1.1 christos * we use an explicit length. 2385 1.1 christos */ 2386 1.1 christos shdr->has_explicit_len = 1; 2387 1.1 christos hdr_len_explicit = payload_len_explicit = 0; 2388 1.1 christos if (!determine_stream_len(h, shdr, space_left, 2389 1.1.1.2 christos &hdr_len_explicit, &payload_len_explicit)) { 2390 1.1 christos *packet_full = 1; 2391 1.1 christos rc = 1; 2392 1.1 christos goto err; /* can't fit anything */ 2393 1.1 christos } 2394 1.1 christos 2395 1.1 christos shdr->len = payload_len_explicit; 2396 1.1 christos } else { 2397 1.1 christos *packet_full = 1; 2398 1.1 christos shdr->has_explicit_len = 0; 2399 1.1 christos shdr->len = payload_len_implicit; 2400 1.1 christos } 2401 1.1 christos 2402 1.1 christos /* If this is a FIN, don't keep filling the packet with more FINs. */ 2403 1.1 christos if (shdr->is_fin) 2404 1.1 christos chunks[(i + 1) % 2].valid = 0; 2405 1.1 christos 2406 1.1 christos /* 2407 1.1 christos * We are now committed to our length (shdr->len can't change). 2408 1.1 christos * If we truncated the chunk, clear the FIN bit. 2409 1.1 christos */ 2410 1.1 christos if (shdr->len < orig_len) 2411 1.1 christos shdr->is_fin = 0; 2412 1.1 christos 2413 1.1 christos /* Truncate IOVs to match our chosen length. */ 2414 1.1 christos ossl_quic_sstream_adjust_iov((size_t)shdr->len, chunks[i % 2].iov, 2415 1.1.1.2 christos chunks[i % 2].num_stream_iovec); 2416 1.1 christos 2417 1.1 christos /* 2418 1.1 christos * Ensure we have enough iovecs allocated (1 for the header, up to 2 for 2419 1.1 christos * the stream data.) 2420 1.1 christos */ 2421 1.1 christos if (!txp_el_ensure_iovec(&txp->el[enc_level], h->num_iovec + 3)) 2422 1.1 christos goto err; /* alloc error */ 2423 1.1 christos 2424 1.1 christos /* Encode the header. */ 2425 1.1 christos wpkt = tx_helper_begin(h); 2426 1.1 christos if (wpkt == NULL) 2427 1.1 christos goto err; /* alloc error */ 2428 1.1 christos 2429 1.1 christos if (!ossl_assert(ossl_quic_wire_encode_frame_stream_hdr(wpkt, shdr))) { 2430 1.1 christos /* (Should not be possible.) */ 2431 1.1 christos tx_helper_rollback(h); 2432 1.1 christos *packet_full = 1; 2433 1.1 christos rc = 1; 2434 1.1 christos goto err; /* can't fit */ 2435 1.1 christos } 2436 1.1 christos 2437 1.1 christos if (!tx_helper_commit(h)) 2438 1.1 christos goto err; /* alloc error */ 2439 1.1 christos 2440 1.1 christos /* Add payload iovecs to the helper (infallible). */ 2441 1.1 christos for (j = 0; j < chunks[i % 2].num_stream_iovec; ++j) 2442 1.1 christos tx_helper_append_iovec(h, chunks[i % 2].iov[j].buf, 2443 1.1.1.2 christos chunks[i % 2].iov[j].buf_len); 2444 1.1 christos 2445 1.1 christos *have_ack_eliciting = 1; 2446 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2447 1.1 christos if (!shdr->has_explicit_len) 2448 1.1 christos h->done_implicit = 1; 2449 1.1 christos 2450 1.1 christos /* Log new TXFC credit which was consumed. */ 2451 1.1 christos if (shdr->len > 0 && shdr->offset + shdr->len > fc_new_hwm) 2452 1.1 christos fc_new_hwm = shdr->offset + shdr->len; 2453 1.1 christos 2454 1.1 christos /* Log chunk to TXPIM. */ 2455 1.1.1.2 christos chunk.stream_id = shdr->stream_id; 2456 1.1.1.2 christos chunk.start = shdr->offset; 2457 1.1.1.2 christos chunk.end = shdr->offset + shdr->len - 1; 2458 1.1.1.2 christos chunk.has_fin = shdr->is_fin; 2459 1.1.1.2 christos chunk.has_stop_sending = 0; 2460 1.1.1.2 christos chunk.has_reset_stream = 0; 2461 1.1 christos if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk)) 2462 1.1 christos goto err; /* alloc error */ 2463 1.1 christos 2464 1.1 christos if (shdr->len < orig_len) { 2465 1.1 christos /* 2466 1.1 christos * If we did not serialize all of this chunk we definitely do not 2467 1.1 christos * want to try the next chunk 2468 1.1 christos */ 2469 1.1 christos rc = 1; 2470 1.1 christos goto err; 2471 1.1 christos } 2472 1.1 christos } 2473 1.1 christos 2474 1.1 christos err: 2475 1.1 christos *new_credit_consumed = fc_new_hwm - fc_swm; 2476 1.1 christos return rc; 2477 1.1 christos } 2478 1.1 christos 2479 1.1 christos static void txp_enlink_tmp(QUIC_STREAM **tmp_head, QUIC_STREAM *stream) 2480 1.1 christos { 2481 1.1 christos stream->txp_next = *tmp_head; 2482 1.1 christos *tmp_head = stream; 2483 1.1 christos } 2484 1.1 christos 2485 1.1 christos static int txp_generate_stream_related(OSSL_QUIC_TX_PACKETISER *txp, 2486 1.1.1.2 christos struct txp_pkt *pkt, 2487 1.1.1.2 christos int *have_ack_eliciting, 2488 1.1.1.2 christos QUIC_STREAM **tmp_head) 2489 1.1 christos { 2490 1.1 christos QUIC_STREAM_ITER it; 2491 1.1 christos WPACKET *wpkt; 2492 1.1 christos uint64_t cwm; 2493 1.1 christos QUIC_STREAM *stream, *snext; 2494 1.1 christos struct tx_helper *h = &pkt->h; 2495 1.1 christos uint64_t conn_consumed = 0; 2496 1.1 christos 2497 1.1 christos for (ossl_quic_stream_iter_init(&it, txp->args.qsm, 1); 2498 1.1.1.2 christos it.stream != NULL;) { 2499 1.1 christos 2500 1.1 christos stream = it.stream; 2501 1.1 christos ossl_quic_stream_iter_next(&it); 2502 1.1 christos snext = it.stream; 2503 1.1 christos 2504 1.1.1.2 christos stream->txp_sent_fc = 0; 2505 1.1.1.2 christos stream->txp_sent_stop_sending = 0; 2506 1.1.1.2 christos stream->txp_sent_reset_stream = 0; 2507 1.1.1.2 christos stream->txp_blocked = 0; 2508 1.1 christos stream->txp_txfc_new_credit_consumed = 0; 2509 1.1 christos 2510 1.1 christos /* Stream Abort Frames (STOP_SENDING, RESET_STREAM) */ 2511 1.1 christos if (stream->want_stop_sending) { 2512 1.1 christos OSSL_QUIC_FRAME_STOP_SENDING f; 2513 1.1 christos 2514 1.1 christos wpkt = tx_helper_begin(h); 2515 1.1 christos if (wpkt == NULL) 2516 1.1 christos return 0; /* alloc error */ 2517 1.1 christos 2518 1.1.1.2 christos f.stream_id = stream->id; 2519 1.1.1.2 christos f.app_error_code = stream->stop_sending_aec; 2520 1.1 christos if (!ossl_quic_wire_encode_frame_stop_sending(wpkt, &f)) { 2521 1.1 christos tx_helper_rollback(h); /* can't fit */ 2522 1.1 christos txp_enlink_tmp(tmp_head, stream); 2523 1.1 christos break; 2524 1.1 christos } 2525 1.1 christos 2526 1.1 christos if (!tx_helper_commit(h)) 2527 1.1 christos return 0; /* alloc error */ 2528 1.1 christos 2529 1.1 christos *have_ack_eliciting = 1; 2530 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2531 1.1 christos stream->txp_sent_stop_sending = 1; 2532 1.1 christos } 2533 1.1 christos 2534 1.1 christos if (stream->want_reset_stream) { 2535 1.1 christos OSSL_QUIC_FRAME_RESET_STREAM f; 2536 1.1 christos 2537 1.1 christos if (!ossl_assert(stream->send_state == QUIC_SSTREAM_STATE_RESET_SENT)) 2538 1.1 christos return 0; 2539 1.1 christos 2540 1.1 christos wpkt = tx_helper_begin(h); 2541 1.1 christos if (wpkt == NULL) 2542 1.1 christos return 0; /* alloc error */ 2543 1.1 christos 2544 1.1.1.2 christos f.stream_id = stream->id; 2545 1.1.1.2 christos f.app_error_code = stream->reset_stream_aec; 2546 1.1 christos if (!ossl_quic_stream_send_get_final_size(stream, &f.final_size)) 2547 1.1 christos return 0; /* should not be possible */ 2548 1.1 christos 2549 1.1 christos if (!ossl_quic_wire_encode_frame_reset_stream(wpkt, &f)) { 2550 1.1 christos tx_helper_rollback(h); /* can't fit */ 2551 1.1 christos txp_enlink_tmp(tmp_head, stream); 2552 1.1 christos break; 2553 1.1 christos } 2554 1.1 christos 2555 1.1 christos if (!tx_helper_commit(h)) 2556 1.1 christos return 0; /* alloc error */ 2557 1.1 christos 2558 1.1 christos *have_ack_eliciting = 1; 2559 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2560 1.1 christos stream->txp_sent_reset_stream = 1; 2561 1.1 christos 2562 1.1 christos /* 2563 1.1 christos * The final size of the stream as indicated by RESET_STREAM is used 2564 1.1 christos * to ensure a consistent view of flow control state by both 2565 1.1 christos * parties; if we happen to send a RESET_STREAM that consumes more 2566 1.1 christos * flow control credit, make sure we account for that. 2567 1.1 christos */ 2568 1.1 christos if (!ossl_assert(f.final_size <= ossl_quic_txfc_get_swm(&stream->txfc))) 2569 1.1 christos return 0; 2570 1.1 christos 2571 1.1 christos stream->txp_txfc_new_credit_consumed 2572 1.1 christos = f.final_size - ossl_quic_txfc_get_swm(&stream->txfc); 2573 1.1 christos } 2574 1.1 christos 2575 1.1 christos /* 2576 1.1 christos * Stream Flow Control Frames (MAX_STREAM_DATA) 2577 1.1 christos * 2578 1.1 christos * RFC 9000 s. 13.3: "An endpoint SHOULD stop sending MAX_STREAM_DATA 2579 1.1 christos * frames when the receiving part of the stream enters a "Size Known" or 2580 1.1 christos * "Reset Recvd" state." -- In practice, RECV is the only state 2581 1.1 christos * in which it makes sense to generate more MAX_STREAM_DATA frames. 2582 1.1 christos */ 2583 1.1 christos if (stream->recv_state == QUIC_RSTREAM_STATE_RECV 2584 1.1 christos && (stream->want_max_stream_data 2585 1.1 christos || ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 0))) { 2586 1.1 christos 2587 1.1 christos wpkt = tx_helper_begin(h); 2588 1.1 christos if (wpkt == NULL) 2589 1.1 christos return 0; /* alloc error */ 2590 1.1 christos 2591 1.1 christos cwm = ossl_quic_rxfc_get_cwm(&stream->rxfc); 2592 1.1 christos 2593 1.1 christos if (!ossl_quic_wire_encode_frame_max_stream_data(wpkt, stream->id, 2594 1.1.1.2 christos cwm)) { 2595 1.1 christos tx_helper_rollback(h); /* can't fit */ 2596 1.1 christos txp_enlink_tmp(tmp_head, stream); 2597 1.1 christos break; 2598 1.1 christos } 2599 1.1 christos 2600 1.1 christos if (!tx_helper_commit(h)) 2601 1.1 christos return 0; /* alloc error */ 2602 1.1 christos 2603 1.1 christos *have_ack_eliciting = 1; 2604 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2605 1.1 christos stream->txp_sent_fc = 1; 2606 1.1 christos } 2607 1.1 christos 2608 1.1 christos /* 2609 1.1 christos * Stream Data Frames (STREAM) 2610 1.1 christos * 2611 1.1 christos * RFC 9000 s. 3.3: A sender MUST NOT send a STREAM [...] frame for a 2612 1.1 christos * stream in the "Reset Sent" state [or any terminal state]. We don't 2613 1.1 christos * send any more STREAM frames if we are sending, have sent, or are 2614 1.1 christos * planning to send, RESET_STREAM. The other terminal state is Data 2615 1.1 christos * Recvd, but txp_generate_stream_frames() is guaranteed to generate 2616 1.1 christos * nothing in this case. 2617 1.1 christos */ 2618 1.1 christos if (ossl_quic_stream_has_send_buffer(stream) 2619 1.1 christos && !ossl_quic_stream_send_is_reset(stream)) { 2620 1.1 christos int packet_full = 0; 2621 1.1 christos 2622 1.1 christos if (!ossl_assert(!stream->want_reset_stream)) 2623 1.1 christos return 0; 2624 1.1 christos 2625 1.1 christos if (!txp_generate_stream_frames(txp, pkt, 2626 1.1.1.2 christos stream->id, stream->sstream, 2627 1.1.1.2 christos &stream->txfc, 2628 1.1.1.2 christos snext, 2629 1.1.1.2 christos have_ack_eliciting, 2630 1.1.1.2 christos &packet_full, 2631 1.1.1.2 christos &stream->txp_txfc_new_credit_consumed, 2632 1.1.1.2 christos conn_consumed)) { 2633 1.1 christos /* Fatal error (allocation, etc.) */ 2634 1.1 christos txp_enlink_tmp(tmp_head, stream); 2635 1.1 christos return 0; 2636 1.1 christos } 2637 1.1 christos conn_consumed += stream->txp_txfc_new_credit_consumed; 2638 1.1 christos 2639 1.1 christos if (packet_full) { 2640 1.1 christos txp_enlink_tmp(tmp_head, stream); 2641 1.1 christos break; 2642 1.1 christos } 2643 1.1 christos } 2644 1.1 christos 2645 1.1 christos txp_enlink_tmp(tmp_head, stream); 2646 1.1 christos } 2647 1.1 christos 2648 1.1 christos return 1; 2649 1.1 christos } 2650 1.1 christos 2651 1.1 christos static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp, 2652 1.1.1.2 christos struct txp_pkt *pkt, 2653 1.1.1.2 christos int chosen_for_conn_close) 2654 1.1 christos { 2655 1.1 christos int rc = TXP_ERR_SUCCESS; 2656 1.1 christos const uint32_t enc_level = pkt->h.enc_level; 2657 1.1 christos const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 2658 1.1 christos int have_ack_eliciting = 0, done_pre_token = 0; 2659 1.1 christos const struct archetype_data a = pkt->geom.adata; 2660 1.1 christos /* 2661 1.1 christos * Cleared if we encode any non-ACK-eliciting frame type which rules out the 2662 1.1 christos * packet being a non-inflight frame. This means any non-ACK ACK-eliciting 2663 1.1 christos * frame, even PADDING frames. ACK eliciting frames always cause a packet to 2664 1.1 christos * become ineligible for non-inflight treatment so it is not necessary to 2665 1.1 christos * clear this in cases where have_ack_eliciting is set, as it is ignored in 2666 1.1 christos * that case. 2667 1.1 christos */ 2668 1.1 christos int can_be_non_inflight = 1; 2669 1.1 christos QUIC_CFQ_ITEM *cfq_item; 2670 1.1 christos QUIC_TXPIM_PKT *tpkt = NULL; 2671 1.1 christos struct tx_helper *h = &pkt->h; 2672 1.1 christos 2673 1.1 christos /* Maximum PN reached? */ 2674 1.1 christos if (!ossl_quic_pn_valid(txp->next_pn[pn_space])) 2675 1.1 christos goto fatal_err; 2676 1.1 christos 2677 1.1 christos if (!ossl_assert(pkt->tpkt == NULL)) 2678 1.1 christos goto fatal_err; 2679 1.1 christos 2680 1.1 christos if ((pkt->tpkt = tpkt = ossl_quic_txpim_pkt_alloc(txp->args.txpim)) == NULL) 2681 1.1 christos goto fatal_err; 2682 1.1 christos 2683 1.1 christos /* 2684 1.1 christos * Frame Serialization 2685 1.1 christos * =================== 2686 1.1 christos * 2687 1.1 christos * We now serialize frames into the packet in descending order of priority. 2688 1.1 christos */ 2689 1.1 christos 2690 1.1 christos /* HANDSHAKE_DONE (Regenerate) */ 2691 1.1 christos if (a.allow_handshake_done && txp->want_handshake_done 2692 1.1 christos && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_HANDSHAKE_DONE) { 2693 1.1 christos WPACKET *wpkt = tx_helper_begin(h); 2694 1.1 christos 2695 1.1 christos if (wpkt == NULL) 2696 1.1 christos goto fatal_err; 2697 1.1 christos 2698 1.1 christos if (ossl_quic_wire_encode_frame_handshake_done(wpkt)) { 2699 1.1 christos tpkt->had_handshake_done_frame = 1; 2700 1.1.1.2 christos have_ack_eliciting = 1; 2701 1.1 christos 2702 1.1 christos if (!tx_helper_commit(h)) 2703 1.1 christos goto fatal_err; 2704 1.1 christos 2705 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2706 1.1 christos } else { 2707 1.1 christos tx_helper_rollback(h); 2708 1.1 christos } 2709 1.1 christos } 2710 1.1 christos 2711 1.1 christos /* MAX_DATA (Regenerate) */ 2712 1.1 christos if (a.allow_conn_fc 2713 1.1 christos && (txp->want_max_data 2714 1.1 christos || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0)) 2715 1.1 christos && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_DATA) { 2716 1.1 christos WPACKET *wpkt = tx_helper_begin(h); 2717 1.1 christos uint64_t cwm = ossl_quic_rxfc_get_cwm(txp->args.conn_rxfc); 2718 1.1 christos 2719 1.1 christos if (wpkt == NULL) 2720 1.1 christos goto fatal_err; 2721 1.1 christos 2722 1.1 christos if (ossl_quic_wire_encode_frame_max_data(wpkt, cwm)) { 2723 1.1 christos tpkt->had_max_data_frame = 1; 2724 1.1.1.2 christos have_ack_eliciting = 1; 2725 1.1 christos 2726 1.1 christos if (!tx_helper_commit(h)) 2727 1.1 christos goto fatal_err; 2728 1.1 christos 2729 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2730 1.1 christos } else { 2731 1.1 christos tx_helper_rollback(h); 2732 1.1 christos } 2733 1.1 christos } 2734 1.1 christos 2735 1.1 christos /* MAX_STREAMS_BIDI (Regenerate) */ 2736 1.1 christos if (a.allow_conn_fc 2737 1.1 christos && (txp->want_max_streams_bidi 2738 1.1 christos || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 0)) 2739 1.1 christos && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_STREAMS_BIDI) { 2740 1.1 christos WPACKET *wpkt = tx_helper_begin(h); 2741 1.1 christos uint64_t max_streams 2742 1.1 christos = ossl_quic_rxfc_get_cwm(txp->args.max_streams_bidi_rxfc); 2743 1.1 christos 2744 1.1 christos if (wpkt == NULL) 2745 1.1 christos goto fatal_err; 2746 1.1 christos 2747 1.1 christos if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/0, 2748 1.1.1.2 christos max_streams)) { 2749 1.1 christos tpkt->had_max_streams_bidi_frame = 1; 2750 1.1.1.2 christos have_ack_eliciting = 1; 2751 1.1 christos 2752 1.1 christos if (!tx_helper_commit(h)) 2753 1.1 christos goto fatal_err; 2754 1.1 christos 2755 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2756 1.1 christos } else { 2757 1.1 christos tx_helper_rollback(h); 2758 1.1 christos } 2759 1.1 christos } 2760 1.1 christos 2761 1.1 christos /* MAX_STREAMS_UNI (Regenerate) */ 2762 1.1 christos if (a.allow_conn_fc 2763 1.1 christos && (txp->want_max_streams_uni 2764 1.1 christos || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 0)) 2765 1.1 christos && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_STREAMS_UNI) { 2766 1.1 christos WPACKET *wpkt = tx_helper_begin(h); 2767 1.1 christos uint64_t max_streams 2768 1.1 christos = ossl_quic_rxfc_get_cwm(txp->args.max_streams_uni_rxfc); 2769 1.1 christos 2770 1.1 christos if (wpkt == NULL) 2771 1.1 christos goto fatal_err; 2772 1.1 christos 2773 1.1 christos if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/1, 2774 1.1.1.2 christos max_streams)) { 2775 1.1 christos tpkt->had_max_streams_uni_frame = 1; 2776 1.1.1.2 christos have_ack_eliciting = 1; 2777 1.1 christos 2778 1.1 christos if (!tx_helper_commit(h)) 2779 1.1 christos goto fatal_err; 2780 1.1 christos 2781 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2782 1.1 christos } else { 2783 1.1 christos tx_helper_rollback(h); 2784 1.1 christos } 2785 1.1 christos } 2786 1.1 christos 2787 1.1 christos /* GCR Frames */ 2788 1.1 christos for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space); 2789 1.1.1.2 christos cfq_item != NULL; 2790 1.1.1.2 christos cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) { 2791 1.1 christos uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item); 2792 1.1 christos const unsigned char *encoded = ossl_quic_cfq_item_get_encoded(cfq_item); 2793 1.1 christos size_t encoded_len = ossl_quic_cfq_item_get_encoded_len(cfq_item); 2794 1.1 christos 2795 1.1 christos switch (frame_type) { 2796 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID: 2797 1.1.1.2 christos if (!a.allow_new_conn_id) 2798 1.1.1.2 christos continue; 2799 1.1.1.2 christos break; 2800 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID: 2801 1.1.1.2 christos if (!a.allow_retire_conn_id) 2802 1.1.1.2 christos continue; 2803 1.1.1.2 christos break; 2804 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN: 2805 1.1.1.2 christos if (!a.allow_new_token) 2806 1.1.1.2 christos continue; 2807 1.1 christos 2808 1.1.1.2 christos /* 2809 1.1.1.2 christos * NEW_TOKEN frames are handled via GCR, but some 2810 1.1.1.2 christos * Regenerate-strategy frames should come before them (namely 2811 1.1.1.2 christos * ACK, CONNECTION_CLOSE, PATH_CHALLENGE and PATH_RESPONSE). If 2812 1.1.1.2 christos * we find a NEW_TOKEN frame, do these now. If there are no 2813 1.1.1.2 christos * NEW_TOKEN frames in the GCR queue we will handle these below. 2814 1.1.1.2 christos */ 2815 1.1.1.2 christos if (!done_pre_token) 2816 1.1.1.2 christos if (txp_generate_pre_token(txp, pkt, 2817 1.1.1.2 christos chosen_for_conn_close, 2818 1.1.1.2 christos &can_be_non_inflight)) 2819 1.1.1.2 christos done_pre_token = 1; 2820 1.1 christos 2821 1.1.1.2 christos break; 2822 1.1.1.2 christos case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE: 2823 1.1.1.2 christos if (!a.allow_path_response) 2824 1.1.1.2 christos continue; 2825 1.1 christos 2826 1.1.1.2 christos /* 2827 1.1.1.2 christos * RFC 9000 s. 8.2.2: An endpoint MUST expand datagrams that 2828 1.1.1.2 christos * contain a PATH_RESPONSE frame to at least the smallest 2829 1.1.1.2 christos * allowed maximum datagram size of 1200 bytes. 2830 1.1.1.2 christos */ 2831 1.1.1.2 christos pkt->force_pad = 1; 2832 1.1.1.2 christos break; 2833 1.1.1.2 christos default: 2834 1.1.1.2 christos if (!a.allow_cfq_other) 2835 1.1.1.2 christos continue; 2836 1.1.1.2 christos break; 2837 1.1 christos } 2838 1.1 christos 2839 1.1 christos /* 2840 1.1 christos * If the frame is too big, don't try to schedule any more GCR frames in 2841 1.1 christos * this packet rather than sending subsequent ones out of order. 2842 1.1 christos */ 2843 1.1 christos if (encoded_len > tx_helper_get_space_left(h)) 2844 1.1 christos break; 2845 1.1 christos 2846 1.1 christos if (!tx_helper_append_iovec(h, encoded, encoded_len)) 2847 1.1 christos goto fatal_err; 2848 1.1 christos 2849 1.1 christos ossl_quic_txpim_pkt_add_cfq_item(tpkt, cfq_item); 2850 1.1 christos 2851 1.1 christos if (ossl_quic_frame_type_is_ack_eliciting(frame_type)) { 2852 1.1 christos have_ack_eliciting = 1; 2853 1.1 christos tx_helper_unrestrict(h); /* no longer need PING */ 2854 1.1 christos } 2855 1.1 christos } 2856 1.1 christos 2857 1.1 christos /* 2858 1.1 christos * If we didn't generate ACK, CONNECTION_CLOSE, PATH_CHALLENGE or 2859 1.1 christos * PATH_RESPONSE (as desired) before, do so now. 2860 1.1 christos */ 2861 1.1 christos if (!done_pre_token) 2862 1.1 christos if (txp_generate_pre_token(txp, pkt, 2863 1.1.1.2 christos chosen_for_conn_close, 2864 1.1.1.2 christos &can_be_non_inflight)) 2865 1.1 christos done_pre_token = 1; 2866 1.1 christos 2867 1.1 christos /* CRYPTO Frames */ 2868 1.1 christos if (a.allow_crypto) 2869 1.1 christos if (!txp_generate_crypto_frames(txp, pkt, &have_ack_eliciting)) 2870 1.1 christos goto fatal_err; 2871 1.1 christos 2872 1.1 christos /* Stream-specific frames */ 2873 1.1 christos if (a.allow_stream_rel && txp->handshake_complete) 2874 1.1 christos if (!txp_generate_stream_related(txp, pkt, 2875 1.1.1.2 christos &have_ack_eliciting, 2876 1.1.1.2 christos &pkt->stream_head)) 2877 1.1 christos goto fatal_err; 2878 1.1 christos 2879 1.1 christos /* PING */ 2880 1.1 christos tx_helper_unrestrict(h); 2881 1.1 christos 2882 1.1 christos if (!have_ack_eliciting && txp_need_ping(txp, pn_space, &a)) { 2883 1.1 christos WPACKET *wpkt; 2884 1.1 christos 2885 1.1 christos assert(h->reserve > 0); 2886 1.1 christos wpkt = tx_helper_begin(h); 2887 1.1 christos if (wpkt == NULL) 2888 1.1 christos goto fatal_err; 2889 1.1 christos 2890 1.1 christos if (!ossl_quic_wire_encode_frame_ping(wpkt) 2891 1.1 christos || !tx_helper_commit(h)) 2892 1.1 christos /* 2893 1.1 christos * We treat a request to be ACK-eliciting as a requirement, so this 2894 1.1 christos * is an error. 2895 1.1 christos */ 2896 1.1 christos goto fatal_err; 2897 1.1 christos 2898 1.1 christos have_ack_eliciting = 1; 2899 1.1 christos } 2900 1.1 christos 2901 1.1 christos /* PADDING is added by ossl_quic_tx_packetiser_generate(). */ 2902 1.1 christos 2903 1.1 christos /* 2904 1.1 christos * ACKM Data 2905 1.1 christos * ========= 2906 1.1 christos */ 2907 1.1 christos if (have_ack_eliciting) 2908 1.1 christos can_be_non_inflight = 0; 2909 1.1 christos 2910 1.1 christos /* ACKM Data */ 2911 1.1.1.2 christos tpkt->ackm_pkt.num_bytes = h->bytes_appended + pkt->geom.pkt_overhead; 2912 1.1.1.2 christos tpkt->ackm_pkt.pkt_num = txp->next_pn[pn_space]; 2913 1.1 christos /* largest_acked is set in txp_generate_pre_token */ 2914 1.1.1.2 christos tpkt->ackm_pkt.pkt_space = pn_space; 2915 1.1.1.2 christos tpkt->ackm_pkt.is_inflight = !can_be_non_inflight; 2916 1.1 christos tpkt->ackm_pkt.is_ack_eliciting = have_ack_eliciting; 2917 1.1.1.2 christos tpkt->ackm_pkt.is_pto_probe = 0; 2918 1.1.1.2 christos tpkt->ackm_pkt.is_mtu_probe = 0; 2919 1.1.1.2 christos tpkt->ackm_pkt.time = txp->args.now(txp->args.now_arg); 2920 1.1.1.2 christos tpkt->pkt_type = pkt->phdr.type; 2921 1.1 christos 2922 1.1 christos /* Done. */ 2923 1.1 christos return rc; 2924 1.1 christos 2925 1.1 christos fatal_err: 2926 1.1 christos /* 2927 1.1 christos * Handler for fatal errors, i.e. errors causing us to abort the entire 2928 1.1 christos * packet rather than just one frame. Examples of such errors include 2929 1.1 christos * allocation errors. 2930 1.1 christos */ 2931 1.1 christos if (tpkt != NULL) { 2932 1.1 christos ossl_quic_txpim_pkt_release(txp->args.txpim, tpkt); 2933 1.1 christos pkt->tpkt = NULL; 2934 1.1 christos } 2935 1.1 christos return TXP_ERR_INTERNAL; 2936 1.1 christos } 2937 1.1 christos 2938 1.1 christos /* 2939 1.1 christos * Commits and queues a packet for transmission. There is no backing out after 2940 1.1 christos * this. 2941 1.1 christos * 2942 1.1 christos * This: 2943 1.1 christos * 2944 1.1 christos * - Sends the packet to the QTX for encryption and transmission; 2945 1.1 christos * 2946 1.1 christos * - Records the packet as having been transmitted in FIFM. ACKM is informed, 2947 1.1 christos * etc. and the TXPIM record is filed. 2948 1.1 christos * 2949 1.1 christos * - Informs various subsystems of frames that were sent and clears frame 2950 1.1 christos * wanted flags so that we do not generate the same frames again. 2951 1.1 christos * 2952 1.1 christos * Assumptions: 2953 1.1 christos * 2954 1.1 christos * - pkt is a txp_pkt for the correct EL; 2955 1.1 christos * 2956 1.1 christos * - pkt->tpkt is valid; 2957 1.1 christos * 2958 1.1 christos * - pkt->tpkt->ackm_pkt has been fully filled in; 2959 1.1 christos * 2960 1.1 christos * - Stream chunk records have been appended to pkt->tpkt for STREAM and 2961 1.1 christos * CRYPTO frames, but not for RESET_STREAM or STOP_SENDING frames; 2962 1.1 christos * 2963 1.1 christos * - The chosen stream list for the packet can be fully walked from 2964 1.1 christos * pkt->stream_head using stream->txp_next; 2965 1.1 christos * 2966 1.1 christos * - pkt->has_ack_eliciting is set correctly. 2967 1.1 christos * 2968 1.1 christos */ 2969 1.1 christos static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, 2970 1.1.1.2 christos struct txp_pkt *pkt, 2971 1.1.1.2 christos uint32_t archetype, 2972 1.1.1.2 christos int *txpim_pkt_reffed) 2973 1.1 christos { 2974 1.1 christos int rc = 1; 2975 1.1 christos uint32_t enc_level = pkt->h.enc_level; 2976 1.1 christos uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 2977 1.1 christos QUIC_TXPIM_PKT *tpkt = pkt->tpkt; 2978 1.1 christos QUIC_STREAM *stream; 2979 1.1 christos OSSL_QTX_PKT txpkt; 2980 1.1 christos struct archetype_data a; 2981 1.1 christos 2982 1.1 christos *txpim_pkt_reffed = 0; 2983 1.1 christos 2984 1.1 christos /* Cannot send a packet with an empty payload. */ 2985 1.1 christos if (pkt->h.bytes_appended == 0) 2986 1.1 christos return 0; 2987 1.1 christos 2988 1.1 christos if (!txp_get_archetype_data(enc_level, archetype, &a)) 2989 1.1 christos return 0; 2990 1.1 christos 2991 1.1 christos /* Packet Information for QTX */ 2992 1.1.1.2 christos txpkt.hdr = &pkt->phdr; 2993 1.1.1.2 christos txpkt.iovec = txp->el[enc_level].iovec; 2994 1.1 christos txpkt.num_iovec = pkt->h.num_iovec; 2995 1.1.1.2 christos txpkt.local = NULL; 2996 1.1.1.2 christos txpkt.peer = BIO_ADDR_family(&txp->args.peer) == AF_UNSPEC 2997 1.1.1.2 christos ? NULL 2998 1.1.1.2 christos : &txp->args.peer; 2999 1.1.1.2 christos txpkt.pn = txp->next_pn[pn_space]; 3000 1.1.1.2 christos txpkt.flags = OSSL_QTX_PKT_FLAG_COALESCE; /* always try to coalesce */ 3001 1.1 christos 3002 1.1 christos /* Generate TXPIM chunks representing STOP_SENDING and RESET_STREAM frames. */ 3003 1.1 christos for (stream = pkt->stream_head; stream != NULL; stream = stream->txp_next) 3004 1.1 christos if (stream->txp_sent_stop_sending || stream->txp_sent_reset_stream) { 3005 1.1 christos /* Log STOP_SENDING/RESET_STREAM chunk to TXPIM. */ 3006 1.1 christos QUIC_TXPIM_CHUNK chunk; 3007 1.1 christos 3008 1.1.1.2 christos chunk.stream_id = stream->id; 3009 1.1.1.2 christos chunk.start = UINT64_MAX; 3010 1.1.1.2 christos chunk.end = 0; 3011 1.1.1.2 christos chunk.has_fin = 0; 3012 1.1.1.2 christos chunk.has_stop_sending = stream->txp_sent_stop_sending; 3013 1.1.1.2 christos chunk.has_reset_stream = stream->txp_sent_reset_stream; 3014 1.1 christos if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk)) 3015 1.1 christos return 0; /* alloc error */ 3016 1.1 christos } 3017 1.1 christos 3018 1.1 christos /* Dispatch to FIFD. */ 3019 1.1 christos if (!ossl_quic_fifd_pkt_commit(&txp->fifd, tpkt)) 3020 1.1 christos return 0; 3021 1.1 christos 3022 1.1 christos /* 3023 1.1 christos * Transmission and Post-Packet Generation Bookkeeping 3024 1.1 christos * =================================================== 3025 1.1 christos * 3026 1.1 christos * No backing out anymore - at this point the ACKM has recorded the packet 3027 1.1 christos * as having been sent, so we need to increment our next PN counter, or 3028 1.1 christos * the ACKM will complain when we try to record a duplicate packet with 3029 1.1 christos * the same PN later. At this point actually sending the packet may still 3030 1.1 christos * fail. In this unlikely event it will simply be handled as though it 3031 1.1 christos * were a lost packet. 3032 1.1 christos */ 3033 1.1 christos ++txp->next_pn[pn_space]; 3034 1.1 christos *txpim_pkt_reffed = 1; 3035 1.1 christos 3036 1.1 christos /* Send the packet. */ 3037 1.1 christos if (!ossl_qtx_write_pkt(txp->args.qtx, &txpkt)) 3038 1.1 christos return 0; 3039 1.1 christos 3040 1.1 christos /* 3041 1.1 christos * Record FC and stream abort frames as sent; deactivate streams which no 3042 1.1 christos * longer have anything to do. 3043 1.1 christos */ 3044 1.1 christos for (stream = pkt->stream_head; stream != NULL; stream = stream->txp_next) { 3045 1.1 christos if (stream->txp_sent_fc) { 3046 1.1 christos stream->want_max_stream_data = 0; 3047 1.1 christos ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 1); 3048 1.1 christos } 3049 1.1 christos 3050 1.1 christos if (stream->txp_sent_stop_sending) 3051 1.1 christos stream->want_stop_sending = 0; 3052 1.1 christos 3053 1.1 christos if (stream->txp_sent_reset_stream) 3054 1.1 christos stream->want_reset_stream = 0; 3055 1.1 christos 3056 1.1 christos if (stream->txp_txfc_new_credit_consumed > 0) { 3057 1.1 christos if (!ossl_assert(ossl_quic_txfc_consume_credit(&stream->txfc, 3058 1.1.1.2 christos stream->txp_txfc_new_credit_consumed))) 3059 1.1 christos /* 3060 1.1 christos * Should not be possible, but we should continue with our 3061 1.1 christos * bookkeeping as we have already committed the packet to the 3062 1.1 christos * FIFD. Just change the value we return. 3063 1.1 christos */ 3064 1.1 christos rc = 0; 3065 1.1 christos 3066 1.1 christos stream->txp_txfc_new_credit_consumed = 0; 3067 1.1 christos } 3068 1.1 christos 3069 1.1 christos /* 3070 1.1 christos * If we no longer need to generate any flow control (MAX_STREAM_DATA), 3071 1.1 christos * STOP_SENDING or RESET_STREAM frames, nor any STREAM frames (because 3072 1.1 christos * the stream is drained of data or TXFC-blocked), we can mark the 3073 1.1 christos * stream as inactive. 3074 1.1 christos */ 3075 1.1 christos ossl_quic_stream_map_update_state(txp->args.qsm, stream); 3076 1.1 christos 3077 1.1 christos if (ossl_quic_stream_has_send_buffer(stream) 3078 1.1 christos && !ossl_quic_sstream_has_pending(stream->sstream) 3079 1.1 christos && ossl_quic_sstream_get_final_size(stream->sstream, NULL)) 3080 1.1 christos /* 3081 1.1 christos * Transition to DATA_SENT if stream has a final size and we have 3082 1.1 christos * sent all data. 3083 1.1 christos */ 3084 1.1 christos ossl_quic_stream_map_notify_all_data_sent(txp->args.qsm, stream); 3085 1.1 christos } 3086 1.1 christos 3087 1.1 christos /* We have now sent the packet, so update state accordingly. */ 3088 1.1 christos if (tpkt->ackm_pkt.is_ack_eliciting) 3089 1.1 christos txp->force_ack_eliciting &= ~(1UL << pn_space); 3090 1.1 christos 3091 1.1 christos if (tpkt->had_handshake_done_frame) 3092 1.1 christos txp->want_handshake_done = 0; 3093 1.1 christos 3094 1.1 christos if (tpkt->had_max_data_frame) { 3095 1.1 christos txp->want_max_data = 0; 3096 1.1 christos ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 1); 3097 1.1 christos } 3098 1.1 christos 3099 1.1 christos if (tpkt->had_max_streams_bidi_frame) { 3100 1.1 christos txp->want_max_streams_bidi = 0; 3101 1.1 christos ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 1); 3102 1.1 christos } 3103 1.1 christos 3104 1.1 christos if (tpkt->had_max_streams_uni_frame) { 3105 1.1 christos txp->want_max_streams_uni = 0; 3106 1.1 christos ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 1); 3107 1.1 christos } 3108 1.1 christos 3109 1.1 christos if (tpkt->had_ack_frame) 3110 1.1 christos txp->want_ack &= ~(1UL << pn_space); 3111 1.1 christos 3112 1.1 christos if (tpkt->had_conn_close) 3113 1.1 christos txp->want_conn_close = 0; 3114 1.1 christos 3115 1.1 christos /* 3116 1.1 christos * Decrement probe request counts if we have sent a packet that meets 3117 1.1 christos * the requirement of a probe, namely being ACK-eliciting. 3118 1.1 christos */ 3119 1.1 christos if (tpkt->ackm_pkt.is_ack_eliciting) { 3120 1.1 christos OSSL_ACKM_PROBE_INFO *probe_info 3121 1.1 christos = ossl_ackm_get0_probe_request(txp->args.ackm); 3122 1.1 christos 3123 1.1 christos if (enc_level == QUIC_ENC_LEVEL_INITIAL 3124 1.1 christos && probe_info->anti_deadlock_initial > 0) 3125 1.1 christos --probe_info->anti_deadlock_initial; 3126 1.1 christos 3127 1.1 christos if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE 3128 1.1 christos && probe_info->anti_deadlock_handshake > 0) 3129 1.1 christos --probe_info->anti_deadlock_handshake; 3130 1.1 christos 3131 1.1 christos if (a.allow_force_ack_eliciting /* (i.e., not for 0-RTT) */ 3132 1.1 christos && probe_info->pto[pn_space] > 0) 3133 1.1 christos --probe_info->pto[pn_space]; 3134 1.1 christos } 3135 1.1 christos 3136 1.1 christos return rc; 3137 1.1 christos } 3138 1.1 christos 3139 1.1 christos /* Ensure the iovec array is at least num elements long. */ 3140 1.1 christos static int txp_el_ensure_iovec(struct txp_el *el, size_t num) 3141 1.1 christos { 3142 1.1 christos OSSL_QTX_IOVEC *iovec; 3143 1.1 christos 3144 1.1 christos if (el->alloc_iovec >= num) 3145 1.1 christos return 1; 3146 1.1 christos 3147 1.1 christos num = el->alloc_iovec != 0 ? el->alloc_iovec * 2 : 8; 3148 1.1 christos 3149 1.1 christos iovec = OPENSSL_realloc(el->iovec, sizeof(OSSL_QTX_IOVEC) * num); 3150 1.1 christos if (iovec == NULL) 3151 1.1 christos return 0; 3152 1.1 christos 3153 1.1.1.2 christos el->iovec = iovec; 3154 1.1.1.2 christos el->alloc_iovec = num; 3155 1.1 christos return 1; 3156 1.1 christos } 3157 1.1 christos 3158 1.1 christos int ossl_quic_tx_packetiser_schedule_conn_close(OSSL_QUIC_TX_PACKETISER *txp, 3159 1.1.1.2 christos const OSSL_QUIC_FRAME_CONN_CLOSE *f) 3160 1.1 christos { 3161 1.1 christos char *reason = NULL; 3162 1.1 christos size_t reason_len = f->reason_len; 3163 1.1 christos size_t max_reason_len = txp_get_mdpl(txp) / 2; 3164 1.1 christos 3165 1.1 christos if (txp->want_conn_close) 3166 1.1 christos return 0; 3167 1.1 christos 3168 1.1 christos /* 3169 1.1 christos * Arbitrarily limit the length of the reason length string to half of the 3170 1.1 christos * MDPL. 3171 1.1 christos */ 3172 1.1 christos if (reason_len > max_reason_len) 3173 1.1 christos reason_len = max_reason_len; 3174 1.1 christos 3175 1.1 christos if (reason_len > 0) { 3176 1.1 christos reason = OPENSSL_memdup(f->reason, reason_len); 3177 1.1 christos if (reason == NULL) 3178 1.1 christos return 0; 3179 1.1 christos } 3180 1.1 christos 3181 1.1.1.2 christos txp->conn_close_frame = *f; 3182 1.1.1.2 christos txp->conn_close_frame.reason = reason; 3183 1.1.1.2 christos txp->conn_close_frame.reason_len = reason_len; 3184 1.1.1.2 christos txp->want_conn_close = 1; 3185 1.1 christos return 1; 3186 1.1 christos } 3187 1.1 christos 3188 1.1 christos void ossl_quic_tx_packetiser_set_msg_callback(OSSL_QUIC_TX_PACKETISER *txp, 3189 1.1.1.2 christos ossl_msg_cb msg_callback, 3190 1.1.1.2 christos SSL *msg_callback_ssl) 3191 1.1 christos { 3192 1.1 christos txp->msg_callback = msg_callback; 3193 1.1 christos txp->msg_callback_ssl = msg_callback_ssl; 3194 1.1 christos } 3195 1.1 christos 3196 1.1 christos void ossl_quic_tx_packetiser_set_msg_callback_arg(OSSL_QUIC_TX_PACKETISER *txp, 3197 1.1.1.2 christos void *msg_callback_arg) 3198 1.1 christos { 3199 1.1 christos txp->msg_callback_arg = msg_callback_arg; 3200 1.1 christos } 3201 1.1 christos 3202 1.1 christos QUIC_PN ossl_quic_tx_packetiser_get_next_pn(OSSL_QUIC_TX_PACKETISER *txp, 3203 1.1.1.2 christos uint32_t pn_space) 3204 1.1 christos { 3205 1.1 christos if (pn_space >= QUIC_PN_SPACE_NUM) 3206 1.1 christos return UINT64_MAX; 3207 1.1 christos 3208 1.1 christos return txp->next_pn[pn_space]; 3209 1.1 christos } 3210 1.1 christos 3211 1.1 christos OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp) 3212 1.1 christos { 3213 1.1 christos /* 3214 1.1 christos * TXP-specific deadline computations which rely on TXP innards. This is in 3215 1.1 christos * turn relied on by the QUIC_CHANNEL code to determine the channel event 3216 1.1 christos * handling deadline. 3217 1.1 christos */ 3218 1.1 christos OSSL_TIME deadline = ossl_time_infinite(); 3219 1.1 christos uint32_t enc_level, pn_space; 3220 1.1 christos 3221 1.1 christos /* 3222 1.1 christos * ACK generation is not CC-gated - packets containing only ACKs are allowed 3223 1.1 christos * to bypass CC. We want to generate ACK frames even if we are currently 3224 1.1 christos * restricted by CC so the peer knows we have received data. The generate 3225 1.1 christos * call will take care of selecting the correct packet archetype. 3226 1.1 christos */ 3227 1.1 christos for (enc_level = QUIC_ENC_LEVEL_INITIAL; 3228 1.1.1.2 christos enc_level < QUIC_ENC_LEVEL_NUM; 3229 1.1.1.2 christos ++enc_level) 3230 1.1 christos if (ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level)) { 3231 1.1 christos pn_space = ossl_quic_enc_level_to_pn_space(enc_level); 3232 1.1 christos deadline = ossl_time_min(deadline, 3233 1.1.1.2 christos ossl_ackm_get_ack_deadline(txp->args.ackm, pn_space)); 3234 1.1 christos } 3235 1.1 christos 3236 1.1 christos /* When will CC let us send more? */ 3237 1.1 christos if (txp->args.cc_method->get_tx_allowance(txp->args.cc_data) == 0) 3238 1.1 christos deadline = ossl_time_min(deadline, 3239 1.1.1.2 christos txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data)); 3240 1.1 christos 3241 1.1 christos return deadline; 3242 1.1 christos } 3243