1 /* 2 * Copyright 2022-2024 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); 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 int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes); 133 134 # define OSSL_ACKM_ECN_NONE 0 135 # define OSSL_ACKM_ECN_ECT1 1 136 # define OSSL_ACKM_ECN_ECT0 2 137 # define OSSL_ACKM_ECN_ECNCE 3 138 139 typedef struct ossl_ackm_rx_pkt_st { 140 /* The packet number of the received packet. */ 141 QUIC_PN pkt_num; 142 143 /* The time at which the packet was received. */ 144 OSSL_TIME time; 145 146 /* 147 * One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field 148 * into a packet number space. 149 */ 150 unsigned int pkt_space :2; 151 152 /* 1 if the packet has one or more ACK-eliciting frames. */ 153 unsigned int is_ack_eliciting :1; 154 155 /* 156 * One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied to 157 * the received packet. If unknown, use OSSL_ACKM_ECN_NONE. 158 */ 159 unsigned int ecn :2; 160 } OSSL_ACKM_RX_PKT; 161 162 int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt); 163 164 int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack, 165 int pkt_space, OSSL_TIME rx_time); 166 167 /* 168 * Discards a PN space. This must be called for a PN space before freeing the 169 * ACKM if you want in-flight packets to have their discarded callbacks called. 170 * This should never be called in ordinary QUIC usage for the Application Data 171 * PN space, but it may be called for the Application Data PN space prior to 172 * freeing the ACKM to simplify teardown implementations. 173 */ 174 int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space); 175 176 int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm); 177 int ossl_ackm_on_timeout(OSSL_ACKM *ackm); 178 179 OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm); 180 181 /* 182 * Generates an ACK frame, regardless of whether the ACK manager thinks 183 * one should currently be sent. 184 * 185 * This clears the flag returned by ossl_ackm_is_ack_desired and the deadline 186 * returned by ossl_ackm_get_ack_deadline. 187 */ 188 const OSSL_QUIC_FRAME_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm, 189 int pkt_space); 190 191 /* 192 * Returns the deadline after which an ACK frame should be generated by calling 193 * ossl_ackm_get_ack_frame, or OSSL_TIME_INFINITY if no deadline is currently 194 * applicable. If the deadline has already passed, this function may return that 195 * deadline, or may return OSSL_TIME_ZERO. 196 */ 197 OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space); 198 199 /* 200 * Returns 1 if the ACK manager thinks an ACK frame ought to be generated and 201 * sent at this time. ossl_ackm_get_ack_frame will always provide an ACK frame 202 * whether or not this returns 1, so it is suggested that you call this function 203 * first to determine whether you need to generate an ACK frame. 204 * 205 * The return value of this function can change based on calls to 206 * ossl_ackm_on_rx_packet and based on the passage of time (see 207 * ossl_ackm_get_ack_deadline). 208 */ 209 int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space); 210 211 /* 212 * Returns 1 if the given RX PN is 'processable'. A processable PN is one that 213 * is not either 214 * 215 * - duplicate, meaning that we have already been passed such a PN in a call 216 * to ossl_ackm_on_rx_packet; or 217 * 218 * - written off, meaning that the PN is so old we have stopped tracking state 219 * for it (meaning that we cannot tell whether it is a duplicate and cannot 220 * process it safely). 221 * 222 * This should be called for a packet before attempting to process its contents. 223 * Failure to do so may result in processing a duplicated packet in violation of 224 * the RFC. 225 * 226 * The return value of this function transitions from 1 to 0 for a given PN once 227 * that PN is passed to ossl_ackm_on_rx_packet, thus this function must be used 228 * before calling ossl_ackm_on_rx_packet. 229 */ 230 int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space); 231 232 typedef struct ossl_ackm_probe_info_st { 233 /* 234 * The following two probe request types are used only for anti-deadlock 235 * purposes in relation to the anti-amplification logic, by generating 236 * packets to buy ourselves more anti-amplification credit with the server 237 * until a client address is verified. Note that like all Initial packets, 238 * any Initial probes are padded. 239 * 240 * Note: The ACKM will only ever increase these by one at a time, 241 * as only one probe packet should be generated for these cases. 242 */ 243 uint32_t anti_deadlock_initial, anti_deadlock_handshake; 244 245 /* 246 * Send an ACK-eliciting packet for each count here. 247 * 248 * Note: The ACKM may increase this by either one or two for each probe 249 * request, depending on how many probe packets it thinks should be 250 * generated. 251 */ 252 uint32_t pto[QUIC_PN_SPACE_NUM]; 253 } OSSL_ACKM_PROBE_INFO; 254 255 /* 256 * Returns a pointer to a structure counting any pending probe requests which 257 * have been generated by the ACKM. The fields in the structure are incremented 258 * by one every time the ACKM wants another probe of the given type to be sent. 259 * If the ACKM thinks two packets should be generated for a probe, it will 260 * increment the field twice. 261 * 262 * It is permissible for the caller to decrement or zero these fields to keep 263 * track of when it has generated a probe as asked. The returned structure 264 * has the same lifetime as the ACKM. 265 * 266 * This function should be called after calling e.g. ossl_ackm_on_timeout 267 * to determine if any probe requests have been generated. 268 */ 269 OSSL_ACKM_PROBE_INFO *ossl_ackm_get0_probe_request(OSSL_ACKM *ackm); 270 271 int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn); 272 273 /* 274 * Forces the ACKM to consider a packet with the given PN in the given PN space 275 * as having been pseudo-lost. The main reason to use this is during a Retry, to 276 * force any resources sent in the first Initial packet to be resent. 277 * 278 * The lost callback is called for the packet, but the packet is NOT considered 279 * lost for congestion control purposes. Thus this is not exactly the same as a 280 * true loss situation. 281 */ 282 int ossl_ackm_mark_packet_pseudo_lost(OSSL_ACKM *ackm, 283 int pkt_space, QUIC_PN pn); 284 285 /* 286 * Returns the PTO duration as currently calculated. This is a quantity of time. 287 * This duration is used in various parts of QUIC besides the ACKM. 288 */ 289 OSSL_TIME ossl_ackm_get_pto_duration(OSSL_ACKM *ackm); 290 291 /* Returns the largest acked PN in the given PN space. */ 292 QUIC_PN ossl_ackm_get_largest_acked(OSSL_ACKM *ackm, int pkt_space); 293 294 # endif 295 296 #endif 297