1 /* 2 * Copyright 2022-2026 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 #ifndef OSSL_QUIC_ACKM_H 10 #define OSSL_QUIC_ACKM_H 11 12 #include "internal/quic_statm.h" 13 #include "internal/quic_cc.h" 14 #include "internal/quic_types.h" 15 #include "internal/quic_wire.h" 16 #include "internal/quic_predef.h" 17 #include "internal/time.h" 18 #include "internal/list.h" 19 20 #ifndef OPENSSL_NO_QUIC 21 22 OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg), 23 void *now_arg, 24 OSSL_STATM *statm, 25 const OSSL_CC_METHOD *cc_method, 26 OSSL_CC_DATA *cc_data, int is_server); 27 void ossl_ackm_free(OSSL_ACKM *ackm); 28 29 void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm, 30 void (*fn)(OSSL_TIME deadline, 31 void *arg), 32 void *arg); 33 34 void ossl_ackm_set_ack_deadline_callback(OSSL_ACKM *ackm, 35 void (*fn)(OSSL_TIME deadline, 36 int pkt_space, 37 void *arg), 38 void *arg); 39 40 /* 41 * Configures the RX-side maximum ACK delay. This is the maximum amount of time 42 * the peer is allowed to delay sending an ACK frame after receiving an 43 * ACK-eliciting packet. The peer communicates this value via a transport 44 * parameter and it must be provided to the ACKM. 45 */ 46 void ossl_ackm_set_rx_max_ack_delay(OSSL_ACKM *ackm, OSSL_TIME rx_max_ack_delay); 47 48 /* 49 * Configures the TX-side maximum ACK delay. This is the maximum amount of time 50 * we are allowed to delay sending an ACK frame after receiving an ACK-eliciting 51 * packet. Note that this cannot be changed after a connection is established as 52 * it must be accurately reported in the transport parameters we send to our 53 * peer. 54 */ 55 void ossl_ackm_set_tx_max_ack_delay(OSSL_ACKM *ackm, OSSL_TIME tx_max_ack_delay); 56 57 typedef struct ossl_ackm_tx_pkt_st OSSL_ACKM_TX_PKT; 58 struct ossl_ackm_tx_pkt_st { 59 /* The packet number of the transmitted packet. */ 60 QUIC_PN pkt_num; 61 62 /* The number of bytes in the packet which was sent. */ 63 size_t num_bytes; 64 65 /* The time at which the packet was sent. */ 66 OSSL_TIME time; 67 68 /* 69 * If the packet being described by this structure contains an ACK frame, 70 * this must be set to the largest PN ACK'd by that frame. 71 * 72 * Otherwise, it should be set to QUIC_PN_INVALID. 73 * 74 * This is necessary to bound the number of PNs we have to keep track of on 75 * the RX side (RFC 9000 s. 13.2.4). It allows older PN tracking information 76 * on the RX side to be discarded. 77 */ 78 QUIC_PN largest_acked; 79 80 /* 81 * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field 82 * into a packet number space. 83 */ 84 unsigned int pkt_space : 2; 85 86 /* 87 * 1 if the packet is in flight. A packet is considered 'in flight' if it is 88 * counted for purposes of congestion control and 'bytes in flight' counts. 89 * Most packets are considered in flight. The only circumstance where a 90 * numbered packet is not considered in flight is if it contains only ACK 91 * frames (not even PADDING frames), as these frames can bypass CC. 92 */ 93 unsigned int is_inflight : 1; 94 95 /* 96 * 1 if the packet has one or more ACK-eliciting frames. 97 * Note that if this is set, is_inflight must be set. 98 */ 99 unsigned int is_ack_eliciting : 1; 100 101 /* 1 if the packet is a PTO probe. */ 102 unsigned int is_pto_probe : 1; 103 104 /* 1 if the packet is an MTU probe. */ 105 unsigned int is_mtu_probe : 1; 106 107 /* Callback called if frames in this packet are lost. arg is cb_arg. */ 108 void (*on_lost)(void *arg); 109 /* Callback called if frames in this packet are acked. arg is cb_arg. */ 110 void (*on_acked)(void *arg); 111 /* 112 * Callback called if frames in this packet are neither acked nor lost. arg 113 * is cb_arg. 114 */ 115 void (*on_discarded)(void *arg); 116 void *cb_arg; 117 118 /* 119 * (Internal use fields; must be zero-initialized.) 120 * 121 * Keep a TX history list, anext is used to manifest 122 * a singly-linked list of newly-acknowledged packets, and lnext is used to 123 * manifest a singly-linked list of newly lost packets. 124 */ 125 OSSL_LIST_MEMBER(tx_history, OSSL_ACKM_TX_PKT); 126 127 struct ossl_ackm_tx_pkt_st *anext; 128 struct ossl_ackm_tx_pkt_st *lnext; 129 }; 130 131 int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt); 132 133 /* 134 * Records transmission of a packet containing only ACK frames. 135 */ 136 int ossl_ackm_on_tx_ack_only_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt); 137 int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes); 138 139 #define OSSL_ACKM_ECN_NONE 0 140 #define OSSL_ACKM_ECN_ECT1 1 141 #define OSSL_ACKM_ECN_ECT0 2 142 #define OSSL_ACKM_ECN_ECNCE 3 143 144 typedef struct ossl_ackm_rx_pkt_st { 145 /* The packet number of the received packet. */ 146 QUIC_PN pkt_num; 147 148 /* The time at which the packet was received. */ 149 OSSL_TIME time; 150 151 /* 152 * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field 153 * into a packet number space. 154 */ 155 unsigned int pkt_space : 2; 156 157 /* 1 if the packet has one or more ACK-eliciting frames. */ 158 unsigned int is_ack_eliciting : 1; 159 160 /* 161 * One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied to 162 * the received packet. If unknown, use OSSL_ACKM_ECN_NONE. 163 */ 164 unsigned int ecn : 2; 165 } OSSL_ACKM_RX_PKT; 166 167 int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt); 168 169 int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack, 170 int pkt_space, OSSL_TIME rx_time); 171 172 /* 173 * Discards a PN space. This must be called for a PN space before freeing the 174 * ACKM if you want in-flight packets to have their discarded callbacks called. 175 * This should never be called in ordinary QUIC usage for the Application Data 176 * PN space, but it may be called for the Application Data PN space prior to 177 * freeing the ACKM to simplify teardown implementations. 178 */ 179 int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space); 180 181 int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm); 182 int ossl_ackm_on_timeout(OSSL_ACKM *ackm); 183 184 OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm); 185 186 /* 187 * Generates an ACK frame, regardless of whether the ACK manager thinks 188 * one should currently be sent. 189 * 190 * This clears the flag returned by ossl_ackm_is_ack_desired and the deadline 191 * returned by ossl_ackm_get_ack_deadline. 192 */ 193 const OSSL_QUIC_FRAME_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm, 194 int pkt_space); 195 196 /* 197 * Returns the deadline after which an ACK frame should be generated by calling 198 * ossl_ackm_get_ack_frame, or OSSL_TIME_INFINITY if no deadline is currently 199 * applicable. If the deadline has already passed, this function may return that 200 * deadline, or may return OSSL_TIME_ZERO. 201 */ 202 OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space); 203 204 /* 205 * Returns 1 if the ACK manager thinks an ACK frame ought to be generated and 206 * sent at this time. ossl_ackm_get_ack_frame will always provide an ACK frame 207 * whether or not this returns 1, so it is suggested that you call this function 208 * first to determine whether you need to generate an ACK frame. 209 * 210 * The return value of this function can change based on calls to 211 * ossl_ackm_on_rx_packet and based on the passage of time (see 212 * ossl_ackm_get_ack_deadline). 213 */ 214 int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space); 215 216 /* 217 * Returns 1 if the given RX PN is 'processable'. A processable PN is one that 218 * is not either 219 * 220 * - duplicate, meaning that we have already been passed such a PN in a call 221 * to ossl_ackm_on_rx_packet; or 222 * 223 * - written off, meaning that the PN is so old we have stopped tracking state 224 * for it (meaning that we cannot tell whether it is a duplicate and cannot 225 * process it safely). 226 * 227 * This should be called for a packet before attempting to process its contents. 228 * Failure to do so may result in processing a duplicated packet in violation of 229 * the RFC. 230 * 231 * The return value of this function transitions from 1 to 0 for a given PN once 232 * that PN is passed to ossl_ackm_on_rx_packet, thus this function must be used 233 * before calling ossl_ackm_on_rx_packet. 234 */ 235 int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space); 236 237 typedef struct ossl_ackm_probe_info_st { 238 /* 239 * The following two probe request types are used only for anti-deadlock 240 * purposes in relation to the anti-amplification logic, by generating 241 * packets to buy ourselves more anti-amplification credit with the server 242 * until a client address is verified. Note that like all Initial packets, 243 * any Initial probes are padded. 244 * 245 * Note: The ACKM will only ever increase these by one at a time, 246 * as only one probe packet should be generated for these cases. 247 */ 248 uint32_t anti_deadlock_initial, anti_deadlock_handshake; 249 250 /* 251 * Send an ACK-eliciting packet for each count here. 252 * 253 * Note: The ACKM may increase this by either one or two for each probe 254 * request, depending on how many probe packets it thinks should be 255 * generated. 256 */ 257 uint32_t pto[QUIC_PN_SPACE_NUM]; 258 } OSSL_ACKM_PROBE_INFO; 259 260 /* 261 * Returns a pointer to a structure counting any pending probe requests which 262 * have been generated by the ACKM. The fields in the structure are incremented 263 * by one every time the ACKM wants another probe of the given type to be sent. 264 * If the ACKM thinks two packets should be generated for a probe, it will 265 * increment the field twice. 266 * 267 * It is permissible for the caller to decrement or zero these fields to keep 268 * track of when it has generated a probe as asked. The returned structure 269 * has the same lifetime as the ACKM. 270 * 271 * This function should be called after calling e.g. ossl_ackm_on_timeout 272 * to determine if any probe requests have been generated. 273 */ 274 OSSL_ACKM_PROBE_INFO *ossl_ackm_get0_probe_request(OSSL_ACKM *ackm); 275 276 int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn); 277 278 /* 279 * Forces the ACKM to consider a packet with the given PN in the given PN space 280 * as having been pseudo-lost. The main reason to use this is during a Retry, to 281 * force any resources sent in the first Initial packet to be resent. 282 * 283 * The lost callback is called for the packet, but the packet is NOT considered 284 * lost for congestion control purposes. Thus this is not exactly the same as a 285 * true loss situation. 286 */ 287 int ossl_ackm_mark_packet_pseudo_lost(OSSL_ACKM *ackm, 288 int pkt_space, QUIC_PN pn); 289 290 /* 291 * Returns the PTO duration as currently calculated. This is a quantity of time. 292 * This duration is used in various parts of QUIC besides the ACKM. 293 */ 294 OSSL_TIME ossl_ackm_get_pto_duration(OSSL_ACKM *ackm); 295 296 /* Returns the largest acked PN in the given PN space. */ 297 QUIC_PN ossl_ackm_get_largest_acked(OSSL_ACKM *ackm, int pkt_space); 298 299 #endif 300 301 #endif 302