1 /* 2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 #ifndef OSSL_QUIC_CC_H 10 # define OSSL_QUIC_CC_H 11 12 #include "openssl/params.h" 13 #include "internal/time.h" 14 #include "internal/quic_predef.h" 15 16 # ifndef OPENSSL_NO_QUIC 17 18 typedef struct ossl_cc_ack_info_st { 19 /* The time the packet being acknowledged was originally sent. */ 20 OSSL_TIME tx_time; 21 22 /* The size in bytes of the packet being acknowledged. */ 23 size_t tx_size; 24 } OSSL_CC_ACK_INFO; 25 26 typedef struct ossl_cc_loss_info_st { 27 /* The time the packet being lost was originally sent. */ 28 OSSL_TIME tx_time; 29 30 /* The size in bytes of the packet which has been determined lost. */ 31 size_t tx_size; 32 } OSSL_CC_LOSS_INFO; 33 34 typedef struct ossl_cc_ecn_info_st { 35 /* 36 * The time at which the largest acked PN (in the incoming ACK frame) was 37 * sent. 38 */ 39 OSSL_TIME largest_acked_time; 40 } OSSL_CC_ECN_INFO; 41 42 /* Parameter (read-write): Maximum datagram payload length in bytes. */ 43 #define OSSL_CC_OPTION_MAX_DGRAM_PAYLOAD_LEN "max_dgram_payload_len" 44 45 /* Diagnostic (read-only): current congestion window size in bytes. */ 46 #define OSSL_CC_OPTION_CUR_CWND_SIZE "cur_cwnd_size" 47 48 /* Diagnostic (read-only): minimum congestion window size in bytes. */ 49 #define OSSL_CC_OPTION_MIN_CWND_SIZE "min_cwnd_size" 50 51 /* Diagnostic (read-only): current net bytes in flight. */ 52 #define OSSL_CC_OPTION_CUR_BYTES_IN_FLIGHT "bytes_in_flight" 53 54 /* Diagnostic (read-only): method-specific state value. */ 55 #define OSSL_CC_OPTION_CUR_STATE "cur_state" 56 57 /* 58 * Congestion control abstract interface. 59 * 60 * This interface is broadly based on the design described in RFC 9002. However, 61 * the demarcation between the ACKM and the congestion controller does not 62 * exactly match that delineated in the RFC 9002 pseudocode. Where aspects of 63 * the demarcation involve the congestion controller accessing internal state of 64 * the ACKM, the interface has been revised where possible to provide the 65 * information needed by the congestion controller and avoid needing to give the 66 * congestion controller access to the ACKM's internal data structures. 67 * 68 * Particular changes include: 69 * 70 * - In our implementation, it is the responsibility of the ACKM to determine 71 * if a loss event constitutes persistent congestion. 72 * 73 * - In our implementation, it is the responsibility of the ACKM to determine 74 * if the ECN-CE counter has increased. The congestion controller is simply 75 * informed when an ECN-CE event occurs. 76 * 77 * All of these changes are intended to avoid having a congestion controller 78 * have to access ACKM internal state. 79 */ 80 #define OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION (1U << 0) 81 82 struct ossl_cc_method_st { 83 /* 84 * Instantiation. 85 */ 86 OSSL_CC_DATA *(*new)(OSSL_TIME (*now_cb)(void *arg), 87 void *now_cb_arg); 88 89 void (*free)(OSSL_CC_DATA *ccdata); 90 91 /* 92 * Reset of state. 93 */ 94 void (*reset)(OSSL_CC_DATA *ccdata); 95 96 /* 97 * Escape hatch for option configuration. 98 * 99 * params is an array of OSSL_PARAM structures. 100 * 101 * Returns 1 on success and 0 on failure. 102 */ 103 int (*set_input_params)(OSSL_CC_DATA *ccdata, 104 const OSSL_PARAM *params); 105 106 /* 107 * (Re)bind output (diagnostic) information. 108 * 109 * params is an array of OSSL_PARAM structures used to output values. The 110 * storage locations associated with each parameter are stored internally 111 * and updated whenever the state of the congestion controller is updated; 112 * thus, the storage locations associated with the OSSL_PARAMs passed in the 113 * call to this function must remain valid until the congestion controller 114 * is freed or those parameters are unbound. A given parameter name may be 115 * bound to only one location at a time. The params structures themselves 116 * do not need to remain allocated after this call returns. 117 * 118 * Returns 1 on success and 0 on failure. 119 */ 120 int (*bind_diagnostics)(OSSL_CC_DATA *ccdata, 121 OSSL_PARAM *params); 122 123 /* 124 * Unbind diagnostic information. The parameters with the given names are 125 * unbound, cancelling the effects of a previous call to bind_diagnostic(). 126 * params is an array of OSSL_PARAMs. The values of the parameters are 127 * ignored. If a parameter is already unbound, there is no effect for that 128 * parameter but other parameters are still unbound. 129 * 130 * Returns 1 on success or 0 on failure. 131 */ 132 int (*unbind_diagnostics)(OSSL_CC_DATA *ccdata, 133 OSSL_PARAM *params); 134 135 /* 136 * Returns the amount of additional data (above and beyond the data 137 * currently in flight) which can be sent in bytes. Returns 0 if no more 138 * data can be sent at this time. The return value of this method 139 * can vary as time passes. 140 */ 141 uint64_t (*get_tx_allowance)(OSSL_CC_DATA *ccdata); 142 143 /* 144 * Returns the time at which the return value of get_tx_allowance might be 145 * higher than its current value. This is not a guarantee and spurious 146 * wakeups are allowed. Returns ossl_time_infinite() if there is no current 147 * wakeup deadline. 148 */ 149 OSSL_TIME (*get_wakeup_deadline)(OSSL_CC_DATA *ccdata); 150 151 /* 152 * The On Data Sent event. num_bytes should be the size of the packet in 153 * bytes (or the aggregate size of multiple packets which have just been 154 * sent). 155 */ 156 int (*on_data_sent)(OSSL_CC_DATA *ccdata, 157 uint64_t num_bytes); 158 159 /* 160 * The On Data Acked event. See OSSL_CC_ACK_INFO structure for details 161 * of the information to be passed. 162 */ 163 int (*on_data_acked)(OSSL_CC_DATA *ccdata, 164 const OSSL_CC_ACK_INFO *info); 165 166 /* 167 * The On Data Lost event. See OSSL_CC_LOSS_INFO structure for details 168 * of the information to be passed. 169 * 170 * Note: When the ACKM determines that a set of multiple packets has been 171 * lost, it is useful for a congestion control algorithm to be able to 172 * process this as a single loss event rather than multiple loss events. 173 * Thus, calling this function may cause the congestion controller to defer 174 * state updates under the assumption that subsequent calls to 175 * on_data_lost() representing further lost packets in the same loss event 176 * may be forthcoming. Always call on_data_lost_finished() after one or more 177 * calls to on_data_lost(). 178 */ 179 int (*on_data_lost)(OSSL_CC_DATA *ccdata, 180 const OSSL_CC_LOSS_INFO *info); 181 182 /* 183 * To be called after a sequence of one or more on_data_lost() calls 184 * representing multiple packets in a single loss detection incident. 185 * 186 * Flags may be 0 or OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION. 187 */ 188 int (*on_data_lost_finished)(OSSL_CC_DATA *ccdata, uint32_t flags); 189 190 /* 191 * For use when a PN space is invalidated or a packet must otherwise be 192 * 'undone' for congestion control purposes without acting as a loss signal. 193 * Only the size of the packet is needed. 194 */ 195 int (*on_data_invalidated)(OSSL_CC_DATA *ccdata, 196 uint64_t num_bytes); 197 198 /* 199 * Called from the ACKM when detecting an increased ECN-CE value in an ACK 200 * frame. This indicates congestion. 201 * 202 * Note that this differs from the RFC's conceptual segregation of the loss 203 * detection and congestion controller functions, as in our implementation 204 * the ACKM is responsible for detecting increases to ECN-CE and simply 205 * tells the congestion controller when ECN-triggered congestion has 206 * occurred. This allows a slightly more efficient implementation and 207 * narrower interface between the ACKM and CC. 208 */ 209 int (*on_ecn)(OSSL_CC_DATA *ccdata, 210 const OSSL_CC_ECN_INFO *info); 211 }; 212 213 extern const OSSL_CC_METHOD ossl_cc_dummy_method; 214 extern const OSSL_CC_METHOD ossl_cc_newreno_method; 215 216 # endif 217 218 #endif 219