1 /* 2 * Copyright (c) 2019 Fastly, Janardhan Iyengar 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 * IN THE SOFTWARE. 21 */ 22 23 /* Interface definition for quicly's congestion controller. 24 */ 25 26 #ifndef quicly_cc_h 27 #define quicly_cc_h 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #include <assert.h> 34 #include <stdint.h> 35 #include <string.h> 36 #include "quicly/constants.h" 37 #include "quicly/loss.h" 38 39 #define QUICLY_MIN_CWND 2 40 #define QUICLY_RENO_BETA 0.7 41 42 /** 43 * Holds pointers to concrete congestion control implementation functions. 44 */ 45 typedef const struct st_quicly_cc_type_t quicly_cc_type_t; 46 47 typedef struct st_quicly_cc_t { 48 /** 49 * Congestion controller type. 50 */ 51 quicly_cc_type_t *type; 52 /** 53 * Current congestion window. 54 */ 55 uint32_t cwnd; 56 /** 57 * Current slow start threshold. 58 */ 59 uint32_t ssthresh; 60 /** 61 * Packet number indicating end of recovery period, if in recovery. 62 */ 63 uint64_t recovery_end; 64 /** 65 * State information specific to the congestion controller implementation. 66 */ 67 union { 68 /** 69 * State information for Reno congestion control. 70 */ 71 struct { 72 /** 73 * Stash of acknowledged bytes, used during congestion avoidance. 74 */ 75 uint32_t stash; 76 } reno; 77 /** 78 * State information for Pico. 79 */ 80 struct { 81 /** 82 * Stash of acknowledged bytes, used during congestion avoidance. 83 */ 84 uint32_t stash; 85 /** 86 * Number of bytes required to be acked in order to increase CWND by 1 MTU. 87 */ 88 uint32_t bytes_per_mtu_increase; 89 } pico; 90 /** 91 * State information for CUBIC congestion control. 92 */ 93 struct { 94 /** 95 * Time offset from the latest congestion event until cwnd reaches W_max again. 96 */ 97 double k; 98 /** 99 * Last cwnd value before the latest congestion event. 100 */ 101 uint32_t w_max; 102 /** 103 * W_max value from the previous congestion event. 104 */ 105 uint32_t w_last_max; 106 /** 107 * Timestamp of the latest congestion event. 108 */ 109 int64_t avoidance_start; 110 /** 111 * Timestamp of the most recent send operation. 112 */ 113 int64_t last_sent_time; 114 } cubic; 115 } state; 116 /** 117 * Initial congestion window. 118 */ 119 uint32_t cwnd_initial; 120 /** 121 * Congestion window at the end of slow start. 122 */ 123 uint32_t cwnd_exiting_slow_start; 124 /** 125 * Minimum congestion window during the connection. 126 */ 127 uint32_t cwnd_minimum; 128 /** 129 * Maximum congestion window during the connection. 130 */ 131 uint32_t cwnd_maximum; 132 /** 133 * Total number of number of loss episodes (congestion window reductions). 134 */ 135 uint32_t num_loss_episodes; 136 } quicly_cc_t; 137 138 struct st_quicly_cc_type_t { 139 /** 140 * name (e.g., "reno") 141 */ 142 const char *name; 143 /** 144 * Corresponding default init_cc. 145 */ 146 struct st_quicly_init_cc_t *cc_init; 147 /** 148 * Called when a packet is newly acknowledged. 149 */ 150 void (*cc_on_acked)(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t largest_acked, uint32_t inflight, 151 uint64_t next_pn, int64_t now, uint32_t max_udp_payload_size); 152 /** 153 * Called when a packet is detected as lost. |next_pn| is the next unsent packet number, 154 * used for setting the recovery window. 155 */ 156 void (*cc_on_lost)(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t lost_pn, uint64_t next_pn, int64_t now, 157 uint32_t max_udp_payload_size); 158 /** 159 * Called when persistent congestion is observed. 160 */ 161 void (*cc_on_persistent_congestion)(quicly_cc_t *cc, const quicly_loss_t *loss, int64_t now); 162 /** 163 * Called after a packet is sent. 164 */ 165 void (*cc_on_sent)(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, int64_t now); 166 /** 167 * Switches the underlying algorithm of `cc` to that of `cc_switch`, returning a boolean if the operation was successful. 168 */ 169 int (*cc_switch)(quicly_cc_t *cc); 170 }; 171 172 /** 173 * The type objects for each CC. These can be used for testing the type of each `quicly_cc_t`. 174 */ 175 extern quicly_cc_type_t quicly_cc_type_reno, quicly_cc_type_cubic, quicly_cc_type_pico; 176 /** 177 * The factory methods for each CC. 178 */ 179 extern struct st_quicly_init_cc_t quicly_cc_reno_init, quicly_cc_cubic_init, quicly_cc_pico_init; 180 181 /** 182 * A null-terminated list of all CC types. 183 */ 184 extern quicly_cc_type_t *quicly_cc_all_types[]; 185 186 /** 187 * Calculates the initial congestion window size given the maximum UDP payload size. 188 */ 189 uint32_t quicly_cc_calc_initial_cwnd(uint32_t max_packets, uint16_t max_udp_payload_size); 190 191 void quicly_cc_reno_on_lost(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t lost_pn, uint64_t next_pn, 192 int64_t now, uint32_t max_udp_payload_size); 193 void quicly_cc_reno_on_persistent_congestion(quicly_cc_t *cc, const quicly_loss_t *loss, int64_t now); 194 void quicly_cc_reno_on_sent(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, int64_t now); 195 196 #ifdef __cplusplus 197 } 198 #endif 199 200 #endif 201