quic_fc.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. #include "internal/quic_fc.h"
  10. #include "internal/quic_error.h"
  11. #include "internal/common.h"
  12. #include "internal/safe_math.h"
  13. #include <assert.h>
  14. OSSL_SAFE_MATH_UNSIGNED(uint64_t, uint64_t)
  15. /*
  16. * TX Flow Controller (TXFC)
  17. * =========================
  18. */
  19. int ossl_quic_txfc_init(QUIC_TXFC *txfc, QUIC_TXFC *conn_txfc)
  20. {
  21. if (conn_txfc != NULL && conn_txfc->parent != NULL)
  22. return 0;
  23. txfc->swm = 0;
  24. txfc->cwm = 0;
  25. txfc->parent = conn_txfc;
  26. txfc->has_become_blocked = 0;
  27. return 1;
  28. }
  29. QUIC_TXFC *ossl_quic_txfc_get_parent(QUIC_TXFC *txfc)
  30. {
  31. return txfc->parent;
  32. }
  33. int ossl_quic_txfc_bump_cwm(QUIC_TXFC *txfc, uint64_t cwm)
  34. {
  35. if (cwm <= txfc->cwm)
  36. return 0;
  37. txfc->cwm = cwm;
  38. return 1;
  39. }
  40. uint64_t ossl_quic_txfc_get_credit_local(QUIC_TXFC *txfc, uint64_t consumed)
  41. {
  42. assert((txfc->swm + consumed) <= txfc->cwm);
  43. return txfc->cwm - (consumed + txfc->swm);
  44. }
  45. uint64_t ossl_quic_txfc_get_credit(QUIC_TXFC *txfc, uint64_t consumed)
  46. {
  47. uint64_t r, conn_r;
  48. r = ossl_quic_txfc_get_credit_local(txfc, 0);
  49. if (txfc->parent != NULL) {
  50. assert(txfc->parent->parent == NULL);
  51. conn_r = ossl_quic_txfc_get_credit_local(txfc->parent, consumed);
  52. if (conn_r < r)
  53. r = conn_r;
  54. }
  55. return r;
  56. }
  57. int ossl_quic_txfc_consume_credit_local(QUIC_TXFC *txfc, uint64_t num_bytes)
  58. {
  59. int ok = 1;
  60. uint64_t credit = ossl_quic_txfc_get_credit_local(txfc, 0);
  61. if (num_bytes > credit) {
  62. ok = 0;
  63. num_bytes = credit;
  64. }
  65. if (num_bytes > 0 && num_bytes == credit)
  66. txfc->has_become_blocked = 1;
  67. txfc->swm += num_bytes;
  68. return ok;
  69. }
  70. int ossl_quic_txfc_consume_credit(QUIC_TXFC *txfc, uint64_t num_bytes)
  71. {
  72. int ok = ossl_quic_txfc_consume_credit_local(txfc, num_bytes);
  73. if (txfc->parent != NULL) {
  74. assert(txfc->parent->parent == NULL);
  75. if (!ossl_quic_txfc_consume_credit_local(txfc->parent, num_bytes))
  76. return 0;
  77. }
  78. return ok;
  79. }
  80. int ossl_quic_txfc_has_become_blocked(QUIC_TXFC *txfc, int clear)
  81. {
  82. int r = txfc->has_become_blocked;
  83. if (clear)
  84. txfc->has_become_blocked = 0;
  85. return r;
  86. }
  87. uint64_t ossl_quic_txfc_get_cwm(QUIC_TXFC *txfc)
  88. {
  89. return txfc->cwm;
  90. }
  91. uint64_t ossl_quic_txfc_get_swm(QUIC_TXFC *txfc)
  92. {
  93. return txfc->swm;
  94. }
  95. /*
  96. * RX Flow Controller (RXFC)
  97. * =========================
  98. */
  99. int ossl_quic_rxfc_init(QUIC_RXFC *rxfc, QUIC_RXFC *conn_rxfc,
  100. uint64_t initial_window_size,
  101. uint64_t max_window_size,
  102. OSSL_TIME (*now)(void *now_arg),
  103. void *now_arg)
  104. {
  105. if (conn_rxfc != NULL && conn_rxfc->parent != NULL)
  106. return 0;
  107. rxfc->swm = 0;
  108. rxfc->cwm = initial_window_size;
  109. rxfc->rwm = 0;
  110. rxfc->esrwm = 0;
  111. rxfc->hwm = 0;
  112. rxfc->cur_window_size = initial_window_size;
  113. rxfc->max_window_size = max_window_size;
  114. rxfc->parent = conn_rxfc;
  115. rxfc->error_code = 0;
  116. rxfc->has_cwm_changed = 0;
  117. rxfc->epoch_start = ossl_time_zero();
  118. rxfc->now = now;
  119. rxfc->now_arg = now_arg;
  120. rxfc->is_fin = 0;
  121. rxfc->standalone = 0;
  122. return 1;
  123. }
  124. int ossl_quic_rxfc_init_standalone(QUIC_RXFC *rxfc,
  125. uint64_t initial_window_size,
  126. OSSL_TIME (*now)(void *arg),
  127. void *now_arg)
  128. {
  129. if (!ossl_quic_rxfc_init(rxfc, NULL,
  130. initial_window_size, initial_window_size,
  131. now, now_arg))
  132. return 0;
  133. rxfc->standalone = 1;
  134. return 1;
  135. }
  136. QUIC_RXFC *ossl_quic_rxfc_get_parent(QUIC_RXFC *rxfc)
  137. {
  138. return rxfc->parent;
  139. }
  140. void ossl_quic_rxfc_set_max_window_size(QUIC_RXFC *rxfc,
  141. size_t max_window_size)
  142. {
  143. rxfc->max_window_size = max_window_size;
  144. }
  145. static void rxfc_start_epoch(QUIC_RXFC *rxfc)
  146. {
  147. rxfc->epoch_start = rxfc->now(rxfc->now_arg);
  148. rxfc->esrwm = rxfc->rwm;
  149. }
  150. static int on_rx_controlled_bytes(QUIC_RXFC *rxfc, uint64_t num_bytes)
  151. {
  152. int ok = 1;
  153. uint64_t credit = rxfc->cwm - rxfc->swm;
  154. if (num_bytes > credit) {
  155. ok = 0;
  156. num_bytes = credit;
  157. rxfc->error_code = OSSL_QUIC_ERR_FLOW_CONTROL_ERROR;
  158. }
  159. rxfc->swm += num_bytes;
  160. return ok;
  161. }
  162. int ossl_quic_rxfc_on_rx_stream_frame(QUIC_RXFC *rxfc, uint64_t end, int is_fin)
  163. {
  164. uint64_t delta;
  165. if (!rxfc->standalone && rxfc->parent == NULL)
  166. return 0;
  167. if (rxfc->is_fin && ((is_fin && rxfc->hwm != end) || end > rxfc->hwm)) {
  168. /* Stream size cannot change after the stream is finished */
  169. rxfc->error_code = OSSL_QUIC_ERR_FINAL_SIZE_ERROR;
  170. return 1; /* not a caller error */
  171. }
  172. if (is_fin)
  173. rxfc->is_fin = 1;
  174. if (end > rxfc->hwm) {
  175. delta = end - rxfc->hwm;
  176. rxfc->hwm = end;
  177. on_rx_controlled_bytes(rxfc, delta); /* result ignored */
  178. if (rxfc->parent != NULL)
  179. on_rx_controlled_bytes(rxfc->parent, delta); /* result ignored */
  180. } else if (end < rxfc->hwm && is_fin) {
  181. rxfc->error_code = OSSL_QUIC_ERR_FINAL_SIZE_ERROR;
  182. return 1; /* not a caller error */
  183. }
  184. return 1;
  185. }
  186. /* threshold = 3/4 */
  187. #define WINDOW_THRESHOLD_NUM 3
  188. #define WINDOW_THRESHOLD_DEN 4
  189. static int rxfc_cwm_bump_desired(QUIC_RXFC *rxfc)
  190. {
  191. int err = 0;
  192. uint64_t window_rem = rxfc->cwm - rxfc->rwm;
  193. uint64_t threshold
  194. = safe_muldiv_uint64_t(rxfc->cur_window_size,
  195. WINDOW_THRESHOLD_NUM, WINDOW_THRESHOLD_DEN, &err);
  196. if (err)
  197. /*
  198. * Extremely large window should never occur, but if it does, just use
  199. * 1/2 as the threshold.
  200. */
  201. threshold = rxfc->cur_window_size / 2;
  202. /*
  203. * No point emitting a new MAX_STREAM_DATA frame if the stream has a final
  204. * size.
  205. */
  206. return !rxfc->is_fin && window_rem <= threshold;
  207. }
  208. static int rxfc_should_bump_window_size(QUIC_RXFC *rxfc, OSSL_TIME rtt)
  209. {
  210. /*
  211. * dt: time since start of epoch
  212. * b: bytes of window consumed since start of epoch
  213. * dw: proportion of window consumed since start of epoch
  214. * T_window: time it will take to use up the entire window, based on dt, dw
  215. * RTT: The current estimated RTT.
  216. *
  217. * b = rwm - esrwm
  218. * dw = b / window_size
  219. * T_window = dt / dw
  220. * T_window = dt / (b / window_size)
  221. * T_window = (dt * window_size) / b
  222. *
  223. * We bump the window size if T_window < 4 * RTT.
  224. *
  225. * We leave the division by b on the LHS to reduce the risk of overflowing
  226. * our 64-bit nanosecond representation, which will afford plenty of
  227. * precision left over after the division anyway.
  228. */
  229. uint64_t b = rxfc->rwm - rxfc->esrwm;
  230. OSSL_TIME now, dt, t_window;
  231. if (b == 0)
  232. return 0;
  233. now = rxfc->now(rxfc->now_arg);
  234. dt = ossl_time_subtract(now, rxfc->epoch_start);
  235. t_window = ossl_time_muldiv(dt, rxfc->cur_window_size, b);
  236. return ossl_time_compare(t_window, ossl_time_multiply(rtt, 4)) < 0;
  237. }
  238. static void rxfc_adjust_window_size(QUIC_RXFC *rxfc, uint64_t min_window_size,
  239. OSSL_TIME rtt)
  240. {
  241. /* Are we sending updates too often? */
  242. uint64_t new_window_size;
  243. new_window_size = rxfc->cur_window_size;
  244. if (rxfc_should_bump_window_size(rxfc, rtt))
  245. new_window_size *= 2;
  246. if (new_window_size < min_window_size)
  247. new_window_size = min_window_size;
  248. if (new_window_size > rxfc->max_window_size) /* takes precedence over min size */
  249. new_window_size = rxfc->max_window_size;
  250. rxfc->cur_window_size = new_window_size;
  251. rxfc_start_epoch(rxfc);
  252. }
  253. static void rxfc_update_cwm(QUIC_RXFC *rxfc, uint64_t min_window_size,
  254. OSSL_TIME rtt)
  255. {
  256. uint64_t new_cwm;
  257. if (!rxfc_cwm_bump_desired(rxfc))
  258. return;
  259. rxfc_adjust_window_size(rxfc, min_window_size, rtt);
  260. new_cwm = rxfc->rwm + rxfc->cur_window_size;
  261. if (new_cwm > rxfc->cwm) {
  262. rxfc->cwm = new_cwm;
  263. rxfc->has_cwm_changed = 1;
  264. }
  265. }
  266. static int rxfc_on_retire(QUIC_RXFC *rxfc, uint64_t num_bytes,
  267. uint64_t min_window_size,
  268. OSSL_TIME rtt)
  269. {
  270. if (ossl_time_is_zero(rxfc->epoch_start))
  271. /* This happens when we retire our first ever bytes. */
  272. rxfc_start_epoch(rxfc);
  273. rxfc->rwm += num_bytes;
  274. rxfc_update_cwm(rxfc, min_window_size, rtt);
  275. return 1;
  276. }
  277. int ossl_quic_rxfc_on_retire(QUIC_RXFC *rxfc,
  278. uint64_t num_bytes,
  279. OSSL_TIME rtt)
  280. {
  281. if (rxfc->parent == NULL && !rxfc->standalone)
  282. return 0;
  283. if (num_bytes == 0)
  284. return 1;
  285. if (rxfc->rwm + num_bytes > rxfc->swm)
  286. /* Impossible for us to retire more bytes than we have received. */
  287. return 0;
  288. rxfc_on_retire(rxfc, num_bytes, 0, rtt);
  289. if (!rxfc->standalone)
  290. rxfc_on_retire(rxfc->parent, num_bytes, rxfc->cur_window_size, rtt);
  291. return 1;
  292. }
  293. uint64_t ossl_quic_rxfc_get_cwm(const QUIC_RXFC *rxfc)
  294. {
  295. return rxfc->cwm;
  296. }
  297. uint64_t ossl_quic_rxfc_get_swm(const QUIC_RXFC *rxfc)
  298. {
  299. return rxfc->swm;
  300. }
  301. uint64_t ossl_quic_rxfc_get_rwm(const QUIC_RXFC *rxfc)
  302. {
  303. return rxfc->rwm;
  304. }
  305. uint64_t ossl_quic_rxfc_get_credit(const QUIC_RXFC *rxfc)
  306. {
  307. return ossl_quic_rxfc_get_cwm(rxfc) - ossl_quic_rxfc_get_swm(rxfc);
  308. }
  309. int ossl_quic_rxfc_has_cwm_changed(QUIC_RXFC *rxfc, int clear)
  310. {
  311. int r = rxfc->has_cwm_changed;
  312. if (clear)
  313. rxfc->has_cwm_changed = 0;
  314. return r;
  315. }
  316. int ossl_quic_rxfc_get_error(QUIC_RXFC *rxfc, int clear)
  317. {
  318. int r = rxfc->error_code;
  319. if (clear)
  320. rxfc->error_code = 0;
  321. return r;
  322. }
  323. int ossl_quic_rxfc_get_final_size(const QUIC_RXFC *rxfc, uint64_t *final_size)
  324. {
  325. if (!rxfc->is_fin)
  326. return 0;
  327. if (final_size != NULL)
  328. *final_size = rxfc->hwm;
  329. return 1;
  330. }