quic_fc.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * Copyright 2022 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)
  41. {
  42. assert(txfc->swm <= txfc->cwm);
  43. return txfc->cwm - txfc->swm;
  44. }
  45. uint64_t ossl_quic_txfc_get_credit(QUIC_TXFC *txfc)
  46. {
  47. uint64_t r, conn_r;
  48. r = ossl_quic_txfc_get_credit_local(txfc);
  49. if (txfc->parent != NULL) {
  50. assert(txfc->parent->parent == NULL);
  51. conn_r = ossl_quic_txfc_get_credit_local(txfc->parent);
  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);
  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. return 1;
  122. }
  123. QUIC_RXFC *ossl_quic_rxfc_get_parent(QUIC_RXFC *rxfc)
  124. {
  125. return rxfc->parent;
  126. }
  127. void ossl_quic_rxfc_set_max_window_size(QUIC_RXFC *rxfc,
  128. size_t max_window_size)
  129. {
  130. rxfc->max_window_size = max_window_size;
  131. }
  132. static void rxfc_start_epoch(QUIC_RXFC *rxfc)
  133. {
  134. rxfc->epoch_start = rxfc->now(rxfc->now_arg);
  135. rxfc->esrwm = rxfc->rwm;
  136. }
  137. static int on_rx_controlled_bytes(QUIC_RXFC *rxfc, uint64_t num_bytes)
  138. {
  139. int ok = 1;
  140. uint64_t credit = rxfc->cwm - rxfc->swm;
  141. if (num_bytes > credit) {
  142. ok = 0;
  143. num_bytes = credit;
  144. rxfc->error_code = QUIC_ERR_FLOW_CONTROL_ERROR;
  145. }
  146. rxfc->swm += num_bytes;
  147. return ok;
  148. }
  149. int ossl_quic_rxfc_on_rx_stream_frame(QUIC_RXFC *rxfc, uint64_t end, int is_fin)
  150. {
  151. uint64_t delta;
  152. if (rxfc->parent == NULL)
  153. return 0;
  154. if (rxfc->is_fin && ((is_fin && rxfc->hwm != end) || end > rxfc->hwm)) {
  155. /* Stream size cannot change after the stream is finished */
  156. rxfc->error_code = QUIC_ERR_FINAL_SIZE_ERROR;
  157. return 1; /* not a caller error */
  158. }
  159. if (is_fin)
  160. rxfc->is_fin = 1;
  161. if (end > rxfc->hwm) {
  162. delta = end - rxfc->hwm;
  163. rxfc->hwm = end;
  164. on_rx_controlled_bytes(rxfc, delta); /* result ignored */
  165. on_rx_controlled_bytes(rxfc->parent, delta); /* result ignored */
  166. } else if (end < rxfc->hwm && is_fin) {
  167. rxfc->error_code = QUIC_ERR_FINAL_SIZE_ERROR;
  168. return 1; /* not a caller error */
  169. }
  170. return 1;
  171. }
  172. /* threshold = 3/4 */
  173. #define WINDOW_THRESHOLD_NUM 3
  174. #define WINDOW_THRESHOLD_DEN 4
  175. static int rxfc_cwm_bump_desired(QUIC_RXFC *rxfc)
  176. {
  177. int err = 0;
  178. uint64_t window_rem = rxfc->cwm - rxfc->rwm;
  179. uint64_t threshold
  180. = safe_mul_uint64_t(rxfc->cur_window_size,
  181. WINDOW_THRESHOLD_NUM, &err) / WINDOW_THRESHOLD_DEN;
  182. if (err)
  183. /*
  184. * Extremely large window should never occur, but if it does, just use
  185. * 1/2 as the threshold.
  186. */
  187. threshold = rxfc->cur_window_size / 2;
  188. return window_rem <= threshold;
  189. }
  190. static int rxfc_should_bump_window_size(QUIC_RXFC *rxfc, OSSL_TIME rtt)
  191. {
  192. /*
  193. * dt: time since start of epoch
  194. * b: bytes of window consumed since start of epoch
  195. * dw: proportion of window consumed since start of epoch
  196. * T_window: time it will take to use up the entire window, based on dt, dw
  197. * RTT: The current estimated RTT.
  198. *
  199. * b = rwm - esrwm
  200. * dw = b / window_size
  201. * T_window = dt / dw
  202. * T_window = dt / (b / window_size)
  203. * T_window = (dt * window_size) / b
  204. *
  205. * We bump the window size if T_window < 4 * RTT.
  206. *
  207. * We leave the division by b on the LHS to reduce the risk of overflowing
  208. * our 64-bit nanosecond representation, which will afford plenty of
  209. * precision left over after the division anyway.
  210. */
  211. uint64_t b = rxfc->rwm - rxfc->esrwm;
  212. OSSL_TIME now, dt, t_window;
  213. if (b == 0)
  214. return 0;
  215. now = rxfc->now(rxfc->now_arg);
  216. dt = ossl_time_subtract(now, rxfc->epoch_start);
  217. t_window = ossl_time_muldiv(dt, rxfc->cur_window_size, b);
  218. return ossl_time_compare(t_window, ossl_time_multiply(rtt, 4)) < 0;
  219. }
  220. static void rxfc_adjust_window_size(QUIC_RXFC *rxfc, uint64_t min_window_size,
  221. OSSL_TIME rtt)
  222. {
  223. /* Are we sending updates too often? */
  224. uint64_t new_window_size;
  225. new_window_size = rxfc->cur_window_size;
  226. if (rxfc_should_bump_window_size(rxfc, rtt))
  227. new_window_size *= 2;
  228. if (new_window_size < min_window_size)
  229. new_window_size = min_window_size;
  230. if (new_window_size > rxfc->max_window_size) /* takes precedence over min size */
  231. new_window_size = rxfc->max_window_size;
  232. rxfc->cur_window_size = new_window_size;
  233. rxfc_start_epoch(rxfc);
  234. }
  235. static void rxfc_update_cwm(QUIC_RXFC *rxfc, uint64_t min_window_size,
  236. OSSL_TIME rtt)
  237. {
  238. uint64_t new_cwm;
  239. if (!rxfc_cwm_bump_desired(rxfc))
  240. return;
  241. rxfc_adjust_window_size(rxfc, min_window_size, rtt);
  242. new_cwm = rxfc->rwm + rxfc->cur_window_size;
  243. if (new_cwm > rxfc->cwm) {
  244. rxfc->cwm = new_cwm;
  245. rxfc->has_cwm_changed = 1;
  246. }
  247. }
  248. static int rxfc_on_retire(QUIC_RXFC *rxfc, uint64_t num_bytes,
  249. uint64_t min_window_size,
  250. OSSL_TIME rtt)
  251. {
  252. if (ossl_time_is_zero(rxfc->epoch_start))
  253. /* This happens when we retire our first ever bytes. */
  254. rxfc_start_epoch(rxfc);
  255. rxfc->rwm += num_bytes;
  256. rxfc_update_cwm(rxfc, min_window_size, rtt);
  257. return 1;
  258. }
  259. int ossl_quic_rxfc_on_retire(QUIC_RXFC *rxfc,
  260. uint64_t num_bytes,
  261. OSSL_TIME rtt)
  262. {
  263. if (rxfc->parent == NULL)
  264. return 0;
  265. if (num_bytes == 0)
  266. return 1;
  267. if (rxfc->rwm + num_bytes > rxfc->swm)
  268. /* Impossible for us to retire more bytes than we have received. */
  269. return 0;
  270. rxfc_on_retire(rxfc, num_bytes, 0, rtt);
  271. rxfc_on_retire(rxfc->parent, num_bytes, rxfc->cur_window_size, rtt);
  272. return 1;
  273. }
  274. uint64_t ossl_quic_rxfc_get_cwm(QUIC_RXFC *rxfc)
  275. {
  276. return rxfc->cwm;
  277. }
  278. uint64_t ossl_quic_rxfc_get_swm(QUIC_RXFC *rxfc)
  279. {
  280. return rxfc->swm;
  281. }
  282. uint64_t ossl_quic_rxfc_get_rwm(QUIC_RXFC *rxfc)
  283. {
  284. return rxfc->rwm;
  285. }
  286. int ossl_quic_rxfc_has_cwm_changed(QUIC_RXFC *rxfc, int clear)
  287. {
  288. int r = rxfc->has_cwm_changed;
  289. if (clear)
  290. rxfc->has_cwm_changed = 0;
  291. return r;
  292. }
  293. int ossl_quic_rxfc_get_error(QUIC_RXFC *rxfc, int clear)
  294. {
  295. int r = rxfc->error_code;
  296. if (clear)
  297. rxfc->error_code = 0;
  298. return r;
  299. }