ngtcp2_cc.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * ngtcp2
  3. *
  4. * Copyright (c) 2018 ngtcp2 contributors
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef NGTCP2_CC_H
  26. #define NGTCP2_CC_H
  27. #ifdef HAVE_CONFIG_H
  28. # include <config.h>
  29. #endif /* defined(HAVE_CONFIG_H) */
  30. #include <ngtcp2/ngtcp2.h>
  31. #include "ngtcp2_pktns_id.h"
  32. #define NGTCP2_LOSS_REDUCTION_FACTOR_BITS 1
  33. #define NGTCP2_PERSISTENT_CONGESTION_THRESHOLD 3
  34. typedef struct ngtcp2_log ngtcp2_log;
  35. typedef struct ngtcp2_conn_stat ngtcp2_conn_stat;
  36. typedef struct ngtcp2_rst ngtcp2_rst;
  37. /**
  38. * @struct
  39. *
  40. * :type:`ngtcp2_cc_pkt` is a convenient structure to include
  41. * acked/lost/sent packet.
  42. */
  43. typedef struct ngtcp2_cc_pkt {
  44. /**
  45. * :member:`pkt_num` is the packet number
  46. */
  47. int64_t pkt_num;
  48. /**
  49. * :member:`pktlen` is the length of packet.
  50. */
  51. size_t pktlen;
  52. /**
  53. * :member:`pktns_id` is the ID of packet number space which this
  54. * packet belongs to.
  55. */
  56. ngtcp2_pktns_id pktns_id;
  57. /**
  58. * :member:`sent_ts` is the timestamp when packet is sent.
  59. */
  60. ngtcp2_tstamp sent_ts;
  61. /**
  62. * :member:`lost` is the number of bytes lost when this packet was
  63. * sent.
  64. */
  65. uint64_t lost;
  66. /**
  67. * :member:`tx_in_flight` is the bytes in flight when this packet
  68. * was sent.
  69. */
  70. uint64_t tx_in_flight;
  71. /**
  72. * :member:`is_app_limited` is nonzero if the connection is
  73. * app-limited when this packet was sent.
  74. */
  75. int is_app_limited;
  76. } ngtcp2_cc_pkt;
  77. /**
  78. * @struct
  79. *
  80. * :type:`ngtcp2_cc_ack` is a convenient structure which stores
  81. * acknowledged and lost bytes.
  82. */
  83. typedef struct ngtcp2_cc_ack {
  84. /**
  85. * :member:`prior_bytes_in_flight` is the in-flight bytes before
  86. * processing this ACK.
  87. */
  88. uint64_t prior_bytes_in_flight;
  89. /**
  90. * :member:`bytes_delivered` is the number of bytes acknowledged.
  91. */
  92. uint64_t bytes_delivered;
  93. /**
  94. * :member:`bytes_lost` is the number of bytes declared lost.
  95. */
  96. uint64_t bytes_lost;
  97. /**
  98. * :member:`pkt_delivered` is the cumulative acknowledged bytes when
  99. * the last packet acknowledged by this ACK was sent.
  100. */
  101. uint64_t pkt_delivered;
  102. /**
  103. * :member:`largest_pkt_sent_ts` is the time when the largest
  104. * acknowledged packet was sent. It is UINT64_MAX if it is unknown.
  105. */
  106. ngtcp2_tstamp largest_pkt_sent_ts;
  107. /**
  108. * :member:`rtt` is the RTT sample. It is UINT64_MAX if no RTT
  109. * sample is available.
  110. */
  111. ngtcp2_duration rtt;
  112. } ngtcp2_cc_ack;
  113. typedef struct ngtcp2_cc ngtcp2_cc;
  114. /**
  115. * @functypedef
  116. *
  117. * :type:`ngtcp2_cc_on_pkt_acked` is a callback function which is
  118. * called with an acknowledged packet.
  119. */
  120. typedef void (*ngtcp2_cc_on_pkt_acked)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  121. const ngtcp2_cc_pkt *pkt,
  122. ngtcp2_tstamp ts);
  123. /**
  124. * @functypedef
  125. *
  126. * :type:`ngtcp2_cc_on_pkt_lost` is a callback function which is
  127. * called with a lost packet.
  128. */
  129. typedef void (*ngtcp2_cc_on_pkt_lost)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  130. const ngtcp2_cc_pkt *pkt,
  131. ngtcp2_tstamp ts);
  132. /**
  133. * @functypedef
  134. *
  135. * :type:`ngtcp2_cc_congestion_event` is a callback function which is
  136. * called when congestion event happens (e.g., when packet is lost).
  137. * |bytes_lost| is the number of bytes lost in this congestion event.
  138. */
  139. typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc,
  140. ngtcp2_conn_stat *cstat,
  141. ngtcp2_tstamp sent_ts,
  142. uint64_t bytes_lost,
  143. ngtcp2_tstamp ts);
  144. /**
  145. * @functypedef
  146. *
  147. * :type:`ngtcp2_cc_on_spurious_congestion` is a callback function
  148. * which is called when a spurious congestion is detected.
  149. */
  150. typedef void (*ngtcp2_cc_on_spurious_congestion)(ngtcp2_cc *cc,
  151. ngtcp2_conn_stat *cstat,
  152. ngtcp2_tstamp ts);
  153. /**
  154. * @functypedef
  155. *
  156. * :type:`ngtcp2_cc_on_persistent_congestion` is a callback function
  157. * which is called when persistent congestion is established.
  158. */
  159. typedef void (*ngtcp2_cc_on_persistent_congestion)(ngtcp2_cc *cc,
  160. ngtcp2_conn_stat *cstat,
  161. ngtcp2_tstamp ts);
  162. /**
  163. * @functypedef
  164. *
  165. * :type:`ngtcp2_cc_on_ack_recv` is a callback function which is
  166. * called when an acknowledgement is received.
  167. */
  168. typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  169. const ngtcp2_cc_ack *ack,
  170. ngtcp2_tstamp ts);
  171. /**
  172. * @functypedef
  173. *
  174. * :type:`ngtcp2_cc_on_pkt_sent` is a callback function which is
  175. * called when an ack-eliciting packet is sent.
  176. */
  177. typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  178. const ngtcp2_cc_pkt *pkt);
  179. /**
  180. * @functypedef
  181. *
  182. * :type:`ngtcp2_cc_new_rtt_sample` is a callback function which is
  183. * called when new RTT sample is obtained.
  184. */
  185. typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  186. ngtcp2_tstamp ts);
  187. /**
  188. * @functypedef
  189. *
  190. * :type:`ngtcp2_cc_reset` is a callback function which is called when
  191. * congestion state must be reset.
  192. */
  193. typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  194. ngtcp2_tstamp ts);
  195. /**
  196. * @enum
  197. *
  198. * :type:`ngtcp2_cc_event_type` defines congestion control events.
  199. */
  200. typedef enum ngtcp2_cc_event_type {
  201. /**
  202. * :enum:`NGTCP2_CC_EVENT_TX_START` occurs when ack-eliciting packet
  203. * is sent and no other ack-eliciting packet is present.
  204. */
  205. NGTCP2_CC_EVENT_TYPE_TX_START
  206. } ngtcp2_cc_event_type;
  207. /**
  208. * @functypedef
  209. *
  210. * :type:`ngtcp2_cc_event` is a callback function which is called when
  211. * a specific event happens.
  212. */
  213. typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  214. ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
  215. /**
  216. * @struct
  217. *
  218. * :type:`ngtcp2_cc` is congestion control algorithm interface shared
  219. * by implementations. All callback functions are optional.
  220. */
  221. typedef struct ngtcp2_cc {
  222. /**
  223. * :member:`log` is ngtcp2 library internal logger.
  224. */
  225. ngtcp2_log *log;
  226. /**
  227. * :member:`on_pkt_acked` is a callback function which is called
  228. * when a packet is acknowledged.
  229. */
  230. ngtcp2_cc_on_pkt_acked on_pkt_acked;
  231. /**
  232. * :member:`on_pkt_lost` is a callback function which is called when
  233. * a packet is lost.
  234. */
  235. ngtcp2_cc_on_pkt_lost on_pkt_lost;
  236. /**
  237. * :member:`congestion_event` is a callback function which is called
  238. * when congestion event happens (.e.g, packet is lost).
  239. */
  240. ngtcp2_cc_congestion_event congestion_event;
  241. /**
  242. * :member:`on_spurious_congestion` is a callback function which is
  243. * called when a spurious congestion is detected.
  244. */
  245. ngtcp2_cc_on_spurious_congestion on_spurious_congestion;
  246. /**
  247. * :member:`on_persistent_congestion` is a callback function which
  248. * is called when persistent congestion is established.
  249. */
  250. ngtcp2_cc_on_persistent_congestion on_persistent_congestion;
  251. /**
  252. * :member:`on_ack_recv` is a callback function which is called when
  253. * an acknowledgement is received.
  254. */
  255. ngtcp2_cc_on_ack_recv on_ack_recv;
  256. /**
  257. * :member:`on_pkt_sent` is a callback function which is called when
  258. * ack-eliciting packet is sent.
  259. */
  260. ngtcp2_cc_on_pkt_sent on_pkt_sent;
  261. /**
  262. * :member:`new_rtt_sample` is a callback function which is called
  263. * when new RTT sample is obtained.
  264. */
  265. ngtcp2_cc_new_rtt_sample new_rtt_sample;
  266. /**
  267. * :member:`reset` is a callback function which is called when
  268. * congestion control state must be reset.
  269. */
  270. ngtcp2_cc_reset reset;
  271. /**
  272. * :member:`event` is a callback function which is called when a
  273. * specific event happens.
  274. */
  275. ngtcp2_cc_event event;
  276. } ngtcp2_cc;
  277. /*
  278. * ngtcp2_cc_compute_initcwnd computes initial cwnd.
  279. */
  280. uint64_t ngtcp2_cc_compute_initcwnd(size_t max_packet_size);
  281. ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
  282. size_t pktlen, ngtcp2_pktns_id pktns_id,
  283. ngtcp2_tstamp sent_ts, uint64_t lost,
  284. uint64_t tx_in_flight, int is_app_limited);
  285. /* ngtcp2_cc_reno is the RENO congestion controller. */
  286. typedef struct ngtcp2_cc_reno {
  287. ngtcp2_cc cc;
  288. uint64_t pending_add;
  289. } ngtcp2_cc_reno;
  290. void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log);
  291. void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  292. const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts);
  293. void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  294. ngtcp2_tstamp sent_ts,
  295. uint64_t bytes_lost, ngtcp2_tstamp ts);
  296. void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc,
  297. ngtcp2_conn_stat *cstat,
  298. ngtcp2_tstamp ts);
  299. void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  300. ngtcp2_tstamp ts);
  301. typedef enum ngtcp2_cubic_state {
  302. /* NGTCP2_CUBIC_STATE_INITIAL is the state where CUBIC is in slow
  303. start phase, or congestion avoidance phase before congestion
  304. events occur. */
  305. NGTCP2_CUBIC_STATE_INITIAL,
  306. /* NGTCP2_CUBIC_STATE_RECOVERY is the state that a connection is in
  307. recovery period. */
  308. NGTCP2_CUBIC_STATE_RECOVERY,
  309. /* NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE is the state where CUBIC
  310. is in congestion avoidance phase after recovery period ends. */
  311. NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE,
  312. } ngtcp2_cubic_state;
  313. typedef struct ngtcp2_cubic_vars {
  314. uint64_t cwnd_prior;
  315. uint64_t w_max;
  316. ngtcp2_duration k;
  317. ngtcp2_tstamp epoch_start;
  318. uint64_t w_est;
  319. ngtcp2_cubic_state state;
  320. /* app_limited_start_ts is the timestamp where app limited period
  321. started. */
  322. ngtcp2_tstamp app_limited_start_ts;
  323. /* app_limited_duration is the cumulative duration where a
  324. connection is under app limited when ACK is received. */
  325. ngtcp2_duration app_limited_duration;
  326. uint64_t pending_bytes_delivered;
  327. uint64_t pending_est_bytes_delivered;
  328. } ngtcp2_cubic_vars;
  329. /* ngtcp2_cc_cubic is CUBIC congestion controller. */
  330. typedef struct ngtcp2_cc_cubic {
  331. ngtcp2_cc cc;
  332. ngtcp2_rst *rst;
  333. /* current is a set of variables that are currently in effect. */
  334. ngtcp2_cubic_vars current;
  335. /* undo stores the congestion state when a congestion event occurs
  336. in order to restore the state when it turns out that the event is
  337. spurious. */
  338. struct {
  339. ngtcp2_cubic_vars v;
  340. uint64_t cwnd;
  341. uint64_t ssthresh;
  342. } undo;
  343. /* HyStart++ variables */
  344. struct {
  345. ngtcp2_duration current_round_min_rtt;
  346. ngtcp2_duration last_round_min_rtt;
  347. ngtcp2_duration curr_rtt;
  348. size_t rtt_sample_count;
  349. ngtcp2_duration css_baseline_min_rtt;
  350. size_t css_round;
  351. } hs;
  352. uint64_t next_round_delivered;
  353. } ngtcp2_cc_cubic;
  354. void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log,
  355. ngtcp2_rst *rst);
  356. void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  357. const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts);
  358. void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  359. ngtcp2_tstamp sent_ts,
  360. uint64_t bytes_lost, ngtcp2_tstamp ts);
  361. void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *ccx,
  362. ngtcp2_conn_stat *cstat,
  363. ngtcp2_tstamp ts);
  364. void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc,
  365. ngtcp2_conn_stat *cstat,
  366. ngtcp2_tstamp ts);
  367. void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
  368. ngtcp2_tstamp ts);
  369. uint64_t ngtcp2_cbrt(uint64_t n);
  370. #endif /* !defined(NGTCP2_CC_H) */