1QUIC ACK Manager 2================ 3 4![(Overview block diagram.)](images/ackm.png "QUIC ACK Manager Block Diagram") 5 6The QUIC ACK manager is responsible for, on the TX side: 7 8 - Handling received ACK frames 9 - Generating notifications that a packet we sent was delivered successfully 10 - Generating notifications that a packet we sent was lost 11 - Generating requests for probe transmission 12 - Providing information on the largest unacked packet number so that packet 13 numbers in packet headers can be encoded and decoded correctly 14 15On the RX side, it is responsible for: 16 17 - Generating ACK frames for later transmission in response to packets we 18 received 19 - Providing information on whether a given RX packet number is potentially 20 duplicate and should not be processed 21 22In order to allow it to perform these tasks, the ACK manager must: 23 24 - be notified of all transmitted packets 25 - be notified of all received datagrams 26 - be notified of all received packets 27 - be notified of all received ACK frames 28 - be notified when a packet number space is discarded 29 - be notified when its loss detection deadline arrives 30 31The ACK manager consumes: 32 33 - an arbitrary function which returns the current time; 34 - a RTT statistics tracker; 35 - a congestion controller. 36 37The ACK manager provides the following outputs: 38 39 - It indicates the current deadline by which the loss detection 40 event should be invoked. 41 42 - It indicates when probes should be generated. 43 44 - It indicates what ACK frames should be generated. 45 46 - It indicates the current deadline by which new ACK frames 47 will be generated, if any. 48 49 - It indicates the largest unacknowledged packet number 50 for a given packet number space. 51 52 - It calls a callback for each transmitted packet it is notified 53 of, specifying whether the packet was successfully acknowledged by the peer, 54 lost or discarded. 55 56 - It may communicate with a congestion controller, causing the 57 congestion controller to update its state. 58 59 - It may communicate with a RTT statistics tracker, causing it 60 to update its state. 61 62In this document, “the caller” refers to the system which makes use of the ACK 63manager. 64 65Utility Definitions 66------------------- 67 68There are three QUIC packet number spaces: Initial, Handshake and Application 69Data. 70 71```c 72/* QUIC packet number spaces. */ 73#define QUIC_PN_SPACE_INITIAL 0 74#define QUIC_PN_SPACE_HANDSHAKE 1 75#define QUIC_PN_SPACE_APP 2 76#define QUIC_PN_SPACE_NUM 3 77``` 78 79Packet numbers are 62-bit values represented herein by `QUIC_PN`. 80`QUIC_PN_INFINITE` evaluates to an invalid QUIC packet number value. 81 82```c 83/* QUIC packet number representation. */ 84typedef uint64_t QUIC_PN; 85#define QUIC_PN_INFINITE UINT64_MAX 86``` 87 88Instantiation 89------------- 90 91The QUIC ACK manager is instantiated as follows: 92 93```c 94typedef struct ossl_ackm_st OSSL_ACKM; 95 96OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg), 97 void *now_arg, 98 QUIC_STATM *statm, 99 OSSL_CC_METHOD *cc_method, 100 OSSL_CC_DATA *cc_data); 101 102void ossl_ackm_free(OSSL_ACKM *ackm); 103``` 104 105The function pointer `now` is invoked by the ACK manager to obtain the current 106time. `now_arg` is passed as the argument. The congestion controller method and 107instance passed are used by the ACK manager instance. `statm` points to a 108[Statistics Manager tracker instance](quic-statm.md). 109 110Events 111------ 112 113The ACK manager state is evolved in response to events provided to the ACK 114manager by the caller. 115 116### On TX Packet 117 118This must be called when a packet is transmitted. It does not provide the 119payload of the packet, but provides metadata about the packet which is relevant 120to the loss detection and acknowledgement process. 121 122The caller is responsible for the allocation of the structure and the structure 123must remain allocated until one of the callbacks is called or the ACK manager is 124freed. It is expected this structure will usually be freed (or returned to a 125pool) in the implementation of either callback passed by the caller. 126 127Only exactly one of the callbacks in the structure will be called over the 128lifetime of a `OSSL_ACKM_TX_PKT`, and only once. 129 130Returns 1 on success. 131 132```c 133typedef struct ossl_ackm_tx_pkt_st { 134 /* The packet number of the transmitted packet. */ 135 QUIC_PN pkt_num; 136 137 /* The number of bytes in the packet which was sent. */ 138 size_t num_bytes; 139 140 /* The time at which the packet was sent. */ 141 OSSL_TIME time; 142 143 /* 144 * If the packet being described by this structure contains an ACK frame, 145 * this must be set to the largest PN ACK'd by that frame. 146 * 147 * Otherwise, it should be set to QUIC_PN_INVALID. 148 * 149 * This is necessary to bound the number of PNs we have to keep track of on 150 * the RX side (RFC 9000 s. 13.2.4). It allows older PN tracking information 151 * on the RX side to be discarded. 152 */ 153 QUIC_PN largest_acked; 154 155 /* 156 * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field 157 * into a packet number space. 158 */ 159 unsigned int pkt_space :2; 160 161 /* 1 if the packet is in flight. */ 162 unsigned int is_inflight :1; 163 164 /* 1 if the packet has one or more ACK-eliciting frames. */ 165 unsigned int is_ack_eliciting :1; 166 167 /* 1 if the packet is a PTO probe. */ 168 unsigned int is_pto_probe :1; 169 170 /* 1 if the packet is an MTU probe. */ 171 unsigned int is_mtu_probe :1; 172 173 /* Callback called if frames in this packet are lost. arg is cb_arg. */ 174 void (*on_lost)(void *arg); 175 176 /* Callback called if frames in this packet are acked. arg is cb_arg. */ 177 void (*on_acked)(void *arg); 178 179 /* 180 * Callback called if frames in this packet are neither acked nor lost. arg 181 * is cb_arg. 182 */ 183 void (*on_discarded)(void *arg); 184 void *cb_arg; 185 186 /* (Internal use fields are appended here and must be zero-initialized.) */ 187} OSSL_ACKM_TX_PKT; 188 189int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_TX_PKT *pkt); 190``` 191 192### On RX Datagram 193 194This must be called whenever a datagram is received. A datagram may contain 195multiple packets, and this function should be called before the calls to 196`ossl_ackm_on_rx_packet`. 197 198The primary use of this function is to inform the ACK manager of new credit to 199the anti-amplification budget. Packet and ACK-frame related logic are handled 200separately in the subsequent calls to `ossl_ackm_on_rx_packet` and 201`ossl_ackm_on_rx_ack_frame`, respectively. 202 203Returns 1 on success. 204 205```c 206int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes); 207``` 208 209### On RX Packet 210 211This must be called whenever a packet is received. It should be called after 212`ossl_ackm_on_rx_datagram` was called for the datagram containing the packet. 213 214Returns 1 on success. 215 216```c 217#define OSSL_ACKM_ECN_NONE 0 218#define OSSL_ACKM_ECN_ECT1 1 219#define OSSL_ACKM_ECN_ECT0 2 220#define OSSL_ACKM_ECN_ECNCE 3 221 222typedef struct ossl_ackm_rx_pkt_st { 223 /* The packet number of the received packet. */ 224 QUIC_PN pkt_num; 225 226 /* The time at which the packet was received. */ 227 OSSL_TIME time; 228 229 /* 230 * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field 231 * into a packet number space. 232 */ 233 unsigned int pkt_space :2; 234 235 /* 1 if the packet has one or more ACK-eliciting frames. */ 236 unsigned int is_ack_eliciting :1; 237 238 /* 239 * One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied 240 * to the received packet. If unknown, use OSSL_ACKM_ECN_NONE. 241 */ 242 unsigned int ecn :2; 243} OSSL_ACKM_RX_PKT; 244 245int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt); 246``` 247 248### On RX ACK Frame 249 250This must be called whenever an ACK frame is received. It should be called 251after any call to `ossl_ackm_on_rx_packet`. 252 253The ranges of packet numbers being acknowledged are passed as an argument. 254`pkt_space` is one of the `QUIC_PN_SPACE_*` values, specifying the packet number 255space of the containing packet. `rx_time` is the time the frame was 256received. 257 258This function causes `on_acked` callbacks to be invoked on applicable packets. 259 260Returns 1 on success. 261 262```c 263typedef struct ossl_ackm_ack_range_st { 264 /* 265 * Represents an inclusive range of packet numbers [start, end]. 266 * start must be <= end. 267 */ 268 QUIC_PN start, end; 269} OSSL_ACKM_ACK_RANGE; 270 271typedef struct ossl_ackm_ack { 272 /* 273 * A sequence of packet number ranges [[start, end]...]. 274 * 275 * The ranges must be sorted in descending order, for example: 276 * [ 95, 100] 277 * [ 90, 92] 278 * etc. 279 * 280 * As such, ack_ranges[0].end is always the highest packet number 281 * being acknowledged and ack_ranges[num_ack_ranges-1].start is 282 * always the lowest packet number being acknowledged. 283 * 284 * num_ack_ranges must be greater than zero, as an ACK frame must 285 * acknowledge at least one packet number. 286 */ 287 const OSSL_ACKM_ACK_RANGE *ack_ranges; 288 size_t num_ack_ranges; 289 290 OSSL_TIME delay_time; 291 uint64_t ect0, ect1, ecnce; 292 /* 1 if the ect0, ect1 and ecnce fields are valid */ 293 char ecn_present; 294} OSSL_ACKM_ACK; 295 296int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_ACKM_ACK *ack, 297 int pkt_space, OSSL_TIME rx_time); 298``` 299 300### On Packet Space Discarded 301 302This must be called whenever a packet number space is discarded. ACK-tracking 303information for the number space is thrown away. Any previously provided 304`OSSL_ACKM_TX_PKT` structures have their `on_discarded` callback invoked, 305providing an opportunity for them to be freed. 306 307Returns 1 on success. 308 309```c 310int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space); 311``` 312 313### On Handshake Confirmed 314 315This should be called by the caller when the QUIC handshake is confirmed. The 316Probe Timeout (PTO) algorithm behaves differently depending on whether the QUIC 317handshake is confirmed yet. 318 319Returns 1 on success. 320 321```c 322int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm); 323``` 324 325### On Timeout 326 327This must be called whenever the loss detection deadline expires. 328 329```c 330int ossl_ackm_on_timeout(OSSL_ACKM *ackm); 331``` 332 333Queries 334------- 335 336These functions allow information about the status of the ACK manager to be 337obtained. 338 339### Get Loss Detection Deadline 340 341This returns a deadline after which `ossl_ackm_on_timeout` should be called. 342 343If it is `OSSL_TIME_INFINITY`, no timeout is currently active. 344 345The value returned by this function may change after any call to any of the 346event functions above is made. 347 348```c 349OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm); 350``` 351 352### Get ACK Frame 353 354This returns a pointer to a `OSSL_ACKM_ACK` structure representing the 355information which should be packed into an ACK frame and transmitted. 356 357This generates an ACK frame regardless of whether the ACK manager thinks one 358should currently be sent. To determine if the ACK manager thinks an ACK frame 359should be sent, use `ossl_ackm_is_ack_desired`, discussed below. 360 361If no new ACK frame is currently needed, returns NULL. After calling this 362function, calling the function immediately again will return NULL. 363 364The structure pointed to by the returned pointer, and the referenced ACK range 365structures, are guaranteed to remain valid until the next call to any 366`OSSL_ACKM` function. After such a call is made, all fields become undefined. 367 368This function is used to provide ACK frames for acknowledging packets which have 369been received and notified to the ACK manager via `ossl_ackm_on_rx_packet`. 370 371Calling this function clears the flag returned by `ossl_ackm_is_ack_desired` and 372the deadline returned by `ossl_ackm_get_ack_deadline`. 373 374```c 375const OSSL_ACKM_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm, int pkt_space); 376``` 377 378### Is ACK Desired 379 380This returns 1 if the ACK manager thinks an ACK frame ought to be generated and 381sent at this time. `ossl_ackm_get_ack_frame` will always provide an ACK frame 382whether or not this returns 1, so it is suggested that you call this function 383first to determine whether you need to generate an ACK frame. 384 385The return value of this function can change based on calls to 386`ossl_ackm_on_rx_packet` and based on the passage of time (see 387`ossl_ackm_get_ack_deadline`). 388 389```c 390int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space); 391``` 392 393### Get ACK Deadline 394 395The ACK manager may defer generation of ACK frames to optimize performance. For 396example, after a packet requiring acknowledgement is received, it may decide to 397wait until a few more packets are received before generating an ACK frame, so 398that a single ACK frame can acknowledge all of them. However, if further 399packets do not arrive, an ACK frame must be generated anyway within a certain 400amount of time. 401 402This function returns the deadline at which the return value of 403`ossl_ackm_is_ack_desired` will change to 1, or `OSSL_TIME_INFINITY`, which 404means that no deadline is currently applicable. If the deadline has already 405passed, it may either return that deadline or `OSSL_TIME_ZERO`. 406 407```c 408OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space); 409``` 410 411### Is RX PN Processable 412 413Returns 1 if the given RX packet number is “processable”. A processable PN is 414one that is not either 415 416 - duplicate, meaning that we have already been passed such a PN in a call 417 to `ossl_ackm_on_rx_packet`; or 418 419 - written off, meaning that the PN is so old that we have stopped tracking 420 state for it (meaning we cannot tell whether it is a duplicate and cannot 421 process it safely). 422 423This should be called for a packet before attempting to process its contents. 424Failure to do so may may result in processing a duplicated packet in violation 425of the RFC. 426 427The returrn value of this function transitions from 1 to 0 for a given PN once 428that PN is passed to ossl_ackm_on_rx_packet, thus this function must be used 429before calling `ossl_ackm_on_rx_packet`. 430 431```c 432int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space); 433``` 434 435### Get Probe Packet 436 437This determines if the ACK manager is requesting any probe packets to be 438transmitted. 439 440The user calls `ossl_ackm_get_probe_request`. The structure pointed 441to by `info` is filled and the function returns 1 on success. 442 443The fields of `OSSL_ACKM_PROBE_INFO` record the number of probe requests 444of each type which are outstanding. In short: 445 446 - `handshake` designates the number of ACK-eliciting Handshake 447 packets being requested. This is equivalent to 448 `SendOneAckElicitingHandshakePacket()` in RFC 9002. 449 450 - `padded_initial` designates the number of ACK-eliciting 451 padded Initial packets being requested. This is equivalent to 452 `SendOneAckElicitingPaddedInitialPacket()` in RFC 9002. 453 454 - `pto` designates the number of ACK-eliciting outstanding probe events 455 corresponding to each packet number space. This is equivalent to 456 `SendOneOrTwoAckElicitingPackets(pn_space)` in RFC 9002. 457 458Once the caller has processed these requests, the caller must clear these 459outstanding requests by calling `ossl_ackm_get_probe_request` with `clear` set 460to 1. If `clear` is non-zero, the current values are returned and then zeroed, 461so that the next call to `ossl_ackm_get_probe_request` (if made immediately) 462will return zero values for all fields. 463 464```c 465typedef struct ossl_ackm_probe_info_st { 466 uint32_t handshake; 467 uint32_t padded_initial; 468 uint32_t pto[QUIC_PN_SPACE_NUM]; 469} OSSL_ACKM_PROBE_INFO; 470 471int ossl_ackm_get_probe_request(OSSL_ACKM *ackm, int clear, 472 OSSL_ACKM_PROBE_INFO *info); 473``` 474 475### Get Largest Unacked Packet Number 476 477This gets the largest unacknowledged packet number in the given packet number 478space. The packet number is written to `*pn`. Returns 1 on success. 479 480This is needed so that packet encoders can determine with what length to encode 481the abridged packet number in the packet header. 482 483```c 484int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn); 485``` 486 487Callback Functionality 488---------------------- 489 490The ACK manager supports optional callback functionality when its deadlines 491are updated. By default, the callback functionality is not enabled. To use 492the callback functionality, call either or both of the following functions 493with a non-NULL function pointer: 494 495```c 496void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm, 497 void (*fn)(OSSL_TIME deadline, 498 void *arg), 499 void *arg); 500 501void ossl_ackm_set_ack_deadline_callback(OSSL_ACKM *ackm, 502 void (*fn)(OSSL_TIME deadline, 503 int pkt_space, 504 void *arg), 505 void *arg); 506``` 507 508Callbacks can be subsequently disabled by calling these functions with a NULL 509function pointer. The callbacks are not called at the time that they are set, 510therefore it is recommended to call them immediately after the call to 511`ossl_ackm_new`. 512 513The loss detection deadline callback is called whenever the value returned 514by `ossl_ackm_get_loss_detection_deadline` changes. 515 516The ACK deadline callback is called whenever the value returned by 517`ossl_ackm_get_ack_deadline` changes for a given packet space. 518 519The `deadline` argument reflects the value which will be newly returned by the 520corresponding function. If the configured callback calls either of these 521functions, the returned value will reflect the new deadline. 522