ngtcp2_acktr.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * ngtcp2
  3. *
  4. * Copyright (c) 2017 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. #include "ngtcp2_acktr.h"
  26. #include <assert.h>
  27. #include "ngtcp2_macro.h"
  28. #include "ngtcp2_tstamp.h"
  29. ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent)
  30. static void acktr_entry_init(ngtcp2_acktr_entry *ent, int64_t pkt_num,
  31. ngtcp2_tstamp tstamp) {
  32. ent->pkt_num = pkt_num;
  33. ent->len = 1;
  34. ent->tstamp = tstamp;
  35. }
  36. int ngtcp2_acktr_entry_objalloc_new(ngtcp2_acktr_entry **ent, int64_t pkt_num,
  37. ngtcp2_tstamp tstamp,
  38. ngtcp2_objalloc *objalloc) {
  39. *ent = ngtcp2_objalloc_acktr_entry_get(objalloc);
  40. if (*ent == NULL) {
  41. return NGTCP2_ERR_NOMEM;
  42. }
  43. acktr_entry_init(*ent, pkt_num, tstamp);
  44. return 0;
  45. }
  46. void ngtcp2_acktr_entry_objalloc_del(ngtcp2_acktr_entry *ent,
  47. ngtcp2_objalloc *objalloc) {
  48. ngtcp2_objalloc_acktr_entry_release(objalloc, ent);
  49. }
  50. void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
  51. const ngtcp2_mem *mem) {
  52. ngtcp2_objalloc_acktr_entry_init(&acktr->objalloc, NGTCP2_ACKTR_MAX_ENT + 1,
  53. mem);
  54. ngtcp2_static_ringbuf_acks_init(&acktr->acks);
  55. ngtcp2_ksl_init(&acktr->ents, ngtcp2_ksl_int64_greater,
  56. ngtcp2_ksl_int64_greater_search, sizeof(int64_t), mem);
  57. acktr->log = log;
  58. acktr->flags = NGTCP2_ACKTR_FLAG_NONE;
  59. acktr->first_unacked_ts = UINT64_MAX;
  60. acktr->rx_npkt = 0;
  61. }
  62. void ngtcp2_acktr_free(ngtcp2_acktr *acktr) {
  63. #ifdef NOMEMPOOL
  64. ngtcp2_ksl_it it;
  65. #endif /* defined(NOMEMPOOL) */
  66. if (acktr == NULL) {
  67. return;
  68. }
  69. #ifdef NOMEMPOOL
  70. for (it = ngtcp2_ksl_begin(&acktr->ents); !ngtcp2_ksl_it_end(&it);
  71. ngtcp2_ksl_it_next(&it)) {
  72. ngtcp2_acktr_entry_objalloc_del(ngtcp2_ksl_it_get(&it), &acktr->objalloc);
  73. }
  74. #endif /* defined(NOMEMPOOL) */
  75. ngtcp2_ksl_free(&acktr->ents);
  76. ngtcp2_objalloc_free(&acktr->objalloc);
  77. }
  78. int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
  79. ngtcp2_tstamp ts) {
  80. ngtcp2_ksl_it it, prev_it;
  81. ngtcp2_acktr_entry *ent, *prev_ent, *delent;
  82. int rv;
  83. int added = 0;
  84. if (ngtcp2_ksl_len(&acktr->ents)) {
  85. it = ngtcp2_ksl_lower_bound(&acktr->ents, &pkt_num);
  86. if (ngtcp2_ksl_it_end(&it)) {
  87. ngtcp2_ksl_it_prev(&it);
  88. ent = ngtcp2_ksl_it_get(&it);
  89. assert(ent->pkt_num >= pkt_num + (int64_t)ent->len);
  90. if (ent->pkt_num == pkt_num + (int64_t)ent->len) {
  91. ++ent->len;
  92. added = 1;
  93. }
  94. } else {
  95. ent = ngtcp2_ksl_it_get(&it);
  96. assert(ent->pkt_num != pkt_num);
  97. if (ngtcp2_ksl_it_begin(&it)) {
  98. if (ent->pkt_num + 1 == pkt_num) {
  99. ngtcp2_ksl_update_key(&acktr->ents, &ent->pkt_num, &pkt_num);
  100. ent->pkt_num = pkt_num;
  101. ent->tstamp = ts;
  102. ++ent->len;
  103. added = 1;
  104. }
  105. } else {
  106. prev_it = it;
  107. ngtcp2_ksl_it_prev(&prev_it);
  108. prev_ent = ngtcp2_ksl_it_get(&prev_it);
  109. assert(prev_ent->pkt_num >= pkt_num + (int64_t)prev_ent->len);
  110. if (ent->pkt_num + 1 == pkt_num) {
  111. if (prev_ent->pkt_num == pkt_num + (int64_t)prev_ent->len) {
  112. prev_ent->len += ent->len + 1;
  113. ngtcp2_ksl_remove_hint(&acktr->ents, NULL, &it, &ent->pkt_num);
  114. ngtcp2_acktr_entry_objalloc_del(ent, &acktr->objalloc);
  115. added = 1;
  116. } else {
  117. ngtcp2_ksl_update_key(&acktr->ents, &ent->pkt_num, &pkt_num);
  118. ent->pkt_num = pkt_num;
  119. ent->tstamp = ts;
  120. ++ent->len;
  121. added = 1;
  122. }
  123. } else if (prev_ent->pkt_num == pkt_num + (int64_t)prev_ent->len) {
  124. ++prev_ent->len;
  125. added = 1;
  126. }
  127. }
  128. }
  129. }
  130. if (!added) {
  131. rv = ngtcp2_acktr_entry_objalloc_new(&ent, pkt_num, ts, &acktr->objalloc);
  132. if (rv != 0) {
  133. return rv;
  134. }
  135. rv = ngtcp2_ksl_insert(&acktr->ents, NULL, &ent->pkt_num, ent);
  136. if (rv != 0) {
  137. ngtcp2_acktr_entry_objalloc_del(ent, &acktr->objalloc);
  138. return rv;
  139. }
  140. }
  141. if (active_ack) {
  142. acktr->flags |= NGTCP2_ACKTR_FLAG_ACTIVE_ACK;
  143. if (acktr->first_unacked_ts == UINT64_MAX) {
  144. acktr->first_unacked_ts = ts;
  145. }
  146. }
  147. if (ngtcp2_ksl_len(&acktr->ents) > NGTCP2_ACKTR_MAX_ENT) {
  148. it = ngtcp2_ksl_end(&acktr->ents);
  149. ngtcp2_ksl_it_prev(&it);
  150. delent = ngtcp2_ksl_it_get(&it);
  151. ngtcp2_ksl_remove_hint(&acktr->ents, NULL, &it, &delent->pkt_num);
  152. ngtcp2_acktr_entry_objalloc_del(delent, &acktr->objalloc);
  153. }
  154. return 0;
  155. }
  156. void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent) {
  157. ngtcp2_ksl_it it;
  158. it = ngtcp2_ksl_lower_bound(&acktr->ents, &ent->pkt_num);
  159. assert(*(int64_t *)ngtcp2_ksl_it_key(&it) == (int64_t)ent->pkt_num);
  160. for (; !ngtcp2_ksl_it_end(&it);) {
  161. ent = ngtcp2_ksl_it_get(&it);
  162. ngtcp2_ksl_remove_hint(&acktr->ents, &it, &it, &ent->pkt_num);
  163. ngtcp2_acktr_entry_objalloc_del(ent, &acktr->objalloc);
  164. }
  165. }
  166. ngtcp2_ksl_it ngtcp2_acktr_get(const ngtcp2_acktr *acktr) {
  167. return ngtcp2_ksl_begin(&acktr->ents);
  168. }
  169. int ngtcp2_acktr_empty(const ngtcp2_acktr *acktr) {
  170. ngtcp2_ksl_it it = ngtcp2_ksl_begin(&acktr->ents);
  171. return ngtcp2_ksl_it_end(&it);
  172. }
  173. ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr,
  174. int64_t pkt_num,
  175. int64_t largest_ack) {
  176. ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb);
  177. ent->largest_ack = largest_ack;
  178. ent->pkt_num = pkt_num;
  179. return ent;
  180. }
  181. /*
  182. * acktr_remove removes |ent| from |acktr|. |it| must point to the
  183. * node whose key identifies |ent|. The iterator which points to the
  184. * entry next to |ent| is assigned to |it|.
  185. */
  186. static void acktr_remove(ngtcp2_acktr *acktr, ngtcp2_ksl_it *it,
  187. ngtcp2_acktr_entry *ent) {
  188. ngtcp2_ksl_remove_hint(&acktr->ents, it, it, &ent->pkt_num);
  189. ngtcp2_acktr_entry_objalloc_del(ent, &acktr->objalloc);
  190. }
  191. static void acktr_on_ack(ngtcp2_acktr *acktr, ngtcp2_ringbuf *rb,
  192. size_t ack_ent_offset) {
  193. ngtcp2_acktr_ack_entry *ack_ent;
  194. ngtcp2_acktr_entry *ent;
  195. ngtcp2_ksl_it it;
  196. assert(ngtcp2_ringbuf_len(rb));
  197. ack_ent = ngtcp2_ringbuf_get(rb, ack_ent_offset);
  198. /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
  199. it = ngtcp2_ksl_lower_bound(&acktr->ents, &ack_ent->largest_ack);
  200. for (; !ngtcp2_ksl_it_end(&it);) {
  201. ent = ngtcp2_ksl_it_get(&it);
  202. acktr_remove(acktr, &it, ent);
  203. }
  204. if (ngtcp2_ksl_len(&acktr->ents)) {
  205. assert(ngtcp2_ksl_it_end(&it));
  206. ngtcp2_ksl_it_prev(&it);
  207. ent = ngtcp2_ksl_it_get(&it);
  208. assert(ent->pkt_num > ack_ent->largest_ack);
  209. if (ack_ent->largest_ack + (int64_t)ent->len > ent->pkt_num) {
  210. ent->len = (size_t)(ent->pkt_num - ack_ent->largest_ack);
  211. }
  212. }
  213. ngtcp2_ringbuf_resize(rb, ack_ent_offset);
  214. }
  215. void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) {
  216. ngtcp2_acktr_ack_entry *ent;
  217. int64_t largest_ack = fr->largest_ack, min_ack;
  218. size_t i, j;
  219. ngtcp2_ringbuf *rb = &acktr->acks.rb;
  220. size_t nacks = ngtcp2_ringbuf_len(rb);
  221. /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
  222. for (j = 0; j < nacks; ++j) {
  223. ent = ngtcp2_ringbuf_get(rb, j);
  224. if (largest_ack >= ent->pkt_num) {
  225. break;
  226. }
  227. }
  228. if (j == nacks) {
  229. return;
  230. }
  231. min_ack = largest_ack - (int64_t)fr->first_ack_range;
  232. if (min_ack <= ent->pkt_num) {
  233. acktr_on_ack(acktr, rb, j);
  234. return;
  235. }
  236. for (i = 0; i < fr->rangecnt && j < nacks; ++i) {
  237. largest_ack = min_ack - (int64_t)fr->ranges[i].gap - 2;
  238. min_ack = largest_ack - (int64_t)fr->ranges[i].len;
  239. for (;;) {
  240. if (ent->pkt_num > largest_ack) {
  241. if (++j == nacks) {
  242. return;
  243. }
  244. ent = ngtcp2_ringbuf_get(rb, j);
  245. continue;
  246. }
  247. if (ent->pkt_num < min_ack) {
  248. break;
  249. }
  250. acktr_on_ack(acktr, rb, j);
  251. return;
  252. }
  253. }
  254. }
  255. void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr) {
  256. acktr->flags &= (uint16_t) ~(NGTCP2_ACKTR_FLAG_ACTIVE_ACK |
  257. NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK |
  258. NGTCP2_ACKTR_FLAG_CANCEL_TIMER);
  259. acktr->first_unacked_ts = UINT64_MAX;
  260. acktr->rx_npkt = 0;
  261. }
  262. int ngtcp2_acktr_require_active_ack(const ngtcp2_acktr *acktr,
  263. ngtcp2_duration max_ack_delay,
  264. ngtcp2_tstamp ts) {
  265. return ngtcp2_tstamp_elapsed(acktr->first_unacked_ts, max_ack_delay, ts);
  266. }
  267. void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr) {
  268. acktr->flags |= NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK;
  269. }