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_rtb.h"
26
27 #include <assert.h>
28 #include <string.h>
29
30 #include "ngtcp2_macro.h"
31 #include "ngtcp2_conn.h"
32 #include "ngtcp2_log.h"
33 #include "ngtcp2_vec.h"
34 #include "ngtcp2_cc.h"
35 #include "ngtcp2_rcvry.h"
36 #include "ngtcp2_rst.h"
37
ngtcp2_frame_chain_new(ngtcp2_frame_chain ** pfrc,const ngtcp2_mem * mem)38 int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) {
39 *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain));
40 if (*pfrc == NULL) {
41 return NGTCP2_ERR_NOMEM;
42 }
43
44 ngtcp2_frame_chain_init(*pfrc);
45
46 return 0;
47 }
48
ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain ** pfrc,size_t extralen,const ngtcp2_mem * mem)49 int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen,
50 const ngtcp2_mem *mem) {
51 *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain) + extralen);
52 if (*pfrc == NULL) {
53 return NGTCP2_ERR_NOMEM;
54 }
55
56 ngtcp2_frame_chain_init(*pfrc);
57
58 return 0;
59 }
60
ngtcp2_frame_chain_stream_datacnt_new(ngtcp2_frame_chain ** pfrc,size_t datacnt,const ngtcp2_mem * mem)61 int ngtcp2_frame_chain_stream_datacnt_new(ngtcp2_frame_chain **pfrc,
62 size_t datacnt,
63 const ngtcp2_mem *mem) {
64 size_t need, avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream);
65
66 if (datacnt > 1) {
67 need = sizeof(ngtcp2_vec) * (datacnt - 1);
68
69 if (need > avail) {
70 return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem);
71 }
72 }
73
74 return ngtcp2_frame_chain_new(pfrc, mem);
75 }
76
ngtcp2_frame_chain_crypto_datacnt_new(ngtcp2_frame_chain ** pfrc,size_t datacnt,const ngtcp2_mem * mem)77 int ngtcp2_frame_chain_crypto_datacnt_new(ngtcp2_frame_chain **pfrc,
78 size_t datacnt,
79 const ngtcp2_mem *mem) {
80 size_t need, avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_crypto);
81
82 if (datacnt > 1) {
83 need = sizeof(ngtcp2_vec) * (datacnt - 1);
84
85 if (need > avail) {
86 return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem);
87 }
88 }
89
90 return ngtcp2_frame_chain_new(pfrc, mem);
91 }
92
ngtcp2_frame_chain_new_token_new(ngtcp2_frame_chain ** pfrc,const ngtcp2_vec * token,const ngtcp2_mem * mem)93 int ngtcp2_frame_chain_new_token_new(ngtcp2_frame_chain **pfrc,
94 const ngtcp2_vec *token,
95 const ngtcp2_mem *mem) {
96 size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token);
97 int rv;
98 uint8_t *p;
99 ngtcp2_frame *fr;
100
101 if (token->len > avail) {
102 rv = ngtcp2_frame_chain_extralen_new(pfrc, token->len - avail, mem);
103 } else {
104 rv = ngtcp2_frame_chain_new(pfrc, mem);
105 }
106 if (rv != 0) {
107 return rv;
108 }
109
110 fr = &(*pfrc)->fr;
111 fr->type = NGTCP2_FRAME_NEW_TOKEN;
112
113 p = (uint8_t *)fr + sizeof(ngtcp2_new_token);
114 memcpy(p, token->base, token->len);
115
116 ngtcp2_vec_init(&fr->new_token.token, p, token->len);
117
118 return 0;
119 }
120
ngtcp2_frame_chain_del(ngtcp2_frame_chain * frc,const ngtcp2_mem * mem)121 void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem) {
122 ngtcp2_frame_chain_binder *binder;
123
124 if (frc == NULL) {
125 return;
126 }
127
128 binder = frc->binder;
129 if (binder && --binder->refcount == 0) {
130 ngtcp2_mem_free(mem, binder);
131 }
132
133 ngtcp2_mem_free(mem, frc);
134 }
135
ngtcp2_frame_chain_init(ngtcp2_frame_chain * frc)136 void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc) {
137 frc->next = NULL;
138 frc->binder = NULL;
139 }
140
ngtcp2_frame_chain_list_del(ngtcp2_frame_chain * frc,const ngtcp2_mem * mem)141 void ngtcp2_frame_chain_list_del(ngtcp2_frame_chain *frc,
142 const ngtcp2_mem *mem) {
143 ngtcp2_frame_chain *next;
144
145 for (; frc;) {
146 next = frc->next;
147 ngtcp2_frame_chain_del(frc, mem);
148 frc = next;
149 }
150 }
151
ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder ** pbinder,const ngtcp2_mem * mem)152 int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder,
153 const ngtcp2_mem *mem) {
154 *pbinder = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_frame_chain_binder));
155 if (*pbinder == NULL) {
156 return NGTCP2_ERR_NOMEM;
157 }
158
159 return 0;
160 }
161
ngtcp2_bind_frame_chains(ngtcp2_frame_chain * a,ngtcp2_frame_chain * b,const ngtcp2_mem * mem)162 int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b,
163 const ngtcp2_mem *mem) {
164 ngtcp2_frame_chain_binder *binder;
165 int rv;
166
167 assert(b->binder == NULL);
168
169 if (a->binder == NULL) {
170 rv = ngtcp2_frame_chain_binder_new(&binder, mem);
171 if (rv != 0) {
172 return rv;
173 }
174
175 a->binder = binder;
176 ++a->binder->refcount;
177 }
178
179 b->binder = a->binder;
180 ++b->binder->refcount;
181
182 return 0;
183 }
184
ngtcp2_rtb_entry_new(ngtcp2_rtb_entry ** pent,const ngtcp2_pkt_hd * hd,ngtcp2_frame_chain * frc,ngtcp2_tstamp ts,size_t pktlen,uint8_t flags,const ngtcp2_mem * mem)185 int ngtcp2_rtb_entry_new(ngtcp2_rtb_entry **pent, const ngtcp2_pkt_hd *hd,
186 ngtcp2_frame_chain *frc, ngtcp2_tstamp ts,
187 size_t pktlen, uint8_t flags, const ngtcp2_mem *mem) {
188 (*pent) = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_rtb_entry));
189 if (*pent == NULL) {
190 return NGTCP2_ERR_NOMEM;
191 }
192
193 (*pent)->hd.pkt_num = hd->pkt_num;
194 (*pent)->hd.type = hd->type;
195 (*pent)->hd.flags = hd->flags;
196 (*pent)->frc = frc;
197 (*pent)->ts = ts;
198 (*pent)->lost_ts = UINT64_MAX;
199 (*pent)->pktlen = pktlen;
200 (*pent)->flags = flags;
201 (*pent)->next = NULL;
202
203 return 0;
204 }
205
ngtcp2_rtb_entry_del(ngtcp2_rtb_entry * ent,const ngtcp2_mem * mem)206 void ngtcp2_rtb_entry_del(ngtcp2_rtb_entry *ent, const ngtcp2_mem *mem) {
207 if (ent == NULL) {
208 return;
209 }
210
211 ngtcp2_frame_chain_list_del(ent->frc, mem);
212
213 ngtcp2_mem_free(mem, ent);
214 }
215
greater(const ngtcp2_ksl_key * lhs,const ngtcp2_ksl_key * rhs)216 static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
217 return *(int64_t *)lhs > *(int64_t *)rhs;
218 }
219
ngtcp2_rtb_init(ngtcp2_rtb * rtb,ngtcp2_pktns_id pktns_id,ngtcp2_strm * crypto,ngtcp2_rst * rst,ngtcp2_cc * cc,ngtcp2_log * log,ngtcp2_qlog * qlog,const ngtcp2_mem * mem)220 void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id,
221 ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc,
222 ngtcp2_log *log, ngtcp2_qlog *qlog,
223 const ngtcp2_mem *mem) {
224 ngtcp2_ksl_init(&rtb->ents, greater, sizeof(int64_t), mem);
225 rtb->crypto = crypto;
226 rtb->rst = rst;
227 rtb->cc = cc;
228 rtb->log = log;
229 rtb->qlog = qlog;
230 rtb->mem = mem;
231 rtb->largest_acked_tx_pkt_num = -1;
232 rtb->num_ack_eliciting = 0;
233 rtb->num_retransmittable = 0;
234 rtb->probe_pkt_left = 0;
235 rtb->pktns_id = pktns_id;
236 rtb->cc_pkt_num = 0;
237 rtb->cc_bytes_in_flight = 0;
238 rtb->persistent_congestion_start_ts = UINT64_MAX;
239 rtb->num_lost_pkts = 0;
240 }
241
ngtcp2_rtb_free(ngtcp2_rtb * rtb)242 void ngtcp2_rtb_free(ngtcp2_rtb *rtb) {
243 ngtcp2_ksl_it it;
244
245 if (rtb == NULL) {
246 return;
247 }
248
249 it = ngtcp2_ksl_begin(&rtb->ents);
250
251 for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) {
252 ngtcp2_rtb_entry_del(ngtcp2_ksl_it_get(&it), rtb->mem);
253 }
254
255 ngtcp2_ksl_free(&rtb->ents);
256 }
257
rtb_on_add(ngtcp2_rtb * rtb,ngtcp2_rtb_entry * ent,ngtcp2_conn_stat * cstat)258 static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
259 ngtcp2_conn_stat *cstat) {
260 ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat);
261
262 assert(rtb->cc_pkt_num <= ent->hd.pkt_num);
263
264 cstat->bytes_in_flight += ent->pktlen;
265 rtb->cc_bytes_in_flight += ent->pktlen;
266
267 ngtcp2_rst_update_app_limited(rtb->rst, cstat);
268
269 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
270 ++rtb->num_ack_eliciting;
271 }
272 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) {
273 ++rtb->num_retransmittable;
274 }
275 }
276
rtb_on_remove(ngtcp2_rtb * rtb,ngtcp2_rtb_entry * ent,ngtcp2_conn_stat * cstat)277 static void rtb_on_remove(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
278 ngtcp2_conn_stat *cstat) {
279 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) {
280 assert(rtb->num_lost_pkts);
281 --rtb->num_lost_pkts;
282 return;
283 }
284
285 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
286 assert(rtb->num_ack_eliciting);
287 --rtb->num_ack_eliciting;
288 }
289
290 if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) &&
291 !(ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED)) {
292 assert(rtb->num_retransmittable);
293 --rtb->num_retransmittable;
294 }
295
296 if (rtb->cc_pkt_num <= ent->hd.pkt_num) {
297 assert(cstat->bytes_in_flight >= ent->pktlen);
298 cstat->bytes_in_flight -= ent->pktlen;
299
300 assert(rtb->cc_bytes_in_flight >= ent->pktlen);
301 rtb->cc_bytes_in_flight -= ent->pktlen;
302 }
303 }
304
305 /*
306 * rtb_reclaim_frame queues unacknowledged frames included in |ent|
307 * for retransmission. The re-queued frames are not deleted from
308 * |ent|. It returns the number of frames queued.
309 */
rtb_reclaim_frame(ngtcp2_rtb * rtb,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_rtb_entry * ent)310 static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
311 ngtcp2_pktns *pktns,
312 ngtcp2_rtb_entry *ent) {
313 ngtcp2_frame_chain *frc, *nfrc, **pfrc = &pktns->tx.frq;
314 ngtcp2_frame *fr;
315 ngtcp2_strm *strm;
316 ngtcp2_range gap, range;
317 size_t num_reclaimed = 0;
318 int rv;
319
320 assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE);
321
322 /* TODO Reconsider the order of pfrc */
323 for (frc = ent->frc; frc; frc = frc->next) {
324 fr = &frc->fr;
325 /* Check that a late ACK acknowledged this frame. */
326 if (frc->binder &&
327 (frc->binder->flags & NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK)) {
328 continue;
329 }
330 switch (frc->fr.type) {
331 case NGTCP2_FRAME_STREAM:
332 strm = ngtcp2_conn_find_stream(conn, fr->stream.stream_id);
333 if (strm == NULL) {
334 continue;
335 }
336
337 gap = ngtcp2_strm_get_unacked_range_after(strm, fr->stream.offset);
338
339 range.begin = fr->stream.offset;
340 range.end = fr->stream.offset +
341 ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt);
342 range = ngtcp2_range_intersect(&range, &gap);
343 if (ngtcp2_range_len(&range) == 0) {
344 if (!fr->stream.fin) {
345 /* 0 length STREAM frame with offset == 0 must be
346 retransmitted if no non-empty data is sent to this stream
347 and no data in this stream is acknowledged. */
348 if (fr->stream.offset != 0 || fr->stream.datacnt != 0 ||
349 strm->tx.offset || (strm->flags & NGTCP2_STRM_FLAG_ANY_ACKED)) {
350 continue;
351 }
352 } else if (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) {
353 continue;
354 }
355 }
356
357 rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, fr->stream.datacnt,
358 rtb->mem);
359 if (rv != 0) {
360 return rv;
361 }
362
363 nfrc->fr = *fr;
364 ngtcp2_vec_copy(nfrc->fr.stream.data, fr->stream.data,
365 fr->stream.datacnt);
366
367 rv = ngtcp2_strm_streamfrq_push(strm, nfrc);
368 if (rv != 0) {
369 ngtcp2_frame_chain_del(nfrc, conn->mem);
370 return rv;
371 }
372 if (!ngtcp2_strm_is_tx_queued(strm)) {
373 strm->cycle = ngtcp2_conn_tx_strmq_first_cycle(conn);
374 rv = ngtcp2_conn_tx_strmq_push(conn, strm);
375 if (rv != 0) {
376 return rv;
377 }
378 }
379
380 ++num_reclaimed;
381
382 continue;
383 case NGTCP2_FRAME_CRYPTO:
384 /* Don't resend CRYPTO frame if the whole region it contains has
385 been acknowledged */
386 gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->crypto.offset);
387
388 range.begin = fr->crypto.offset;
389 range.end = fr->crypto.offset +
390 ngtcp2_vec_len(fr->crypto.data, fr->crypto.datacnt);
391 range = ngtcp2_range_intersect(&range, &gap);
392 if (ngtcp2_range_len(&range) == 0) {
393 continue;
394 }
395
396 rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, fr->crypto.datacnt,
397 rtb->mem);
398 if (rv != 0) {
399 return rv;
400 }
401
402 nfrc->fr = *fr;
403 ngtcp2_vec_copy(nfrc->fr.crypto.data, fr->crypto.data,
404 fr->crypto.datacnt);
405
406 rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
407 &nfrc->fr.crypto.offset, nfrc);
408 if (rv != 0) {
409 assert(ngtcp2_err_is_fatal(rv));
410 ngtcp2_frame_chain_del(nfrc, conn->mem);
411 return rv;
412 }
413
414 ++num_reclaimed;
415
416 continue;
417 case NGTCP2_FRAME_NEW_TOKEN:
418 rv = ngtcp2_frame_chain_new_token_new(&nfrc, &fr->new_token.token,
419 rtb->mem);
420 if (rv != 0) {
421 return rv;
422 }
423
424 rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem);
425 if (rv != 0) {
426 return rv;
427 }
428
429 break;
430 case NGTCP2_FRAME_DATAGRAM:
431 case NGTCP2_FRAME_DATAGRAM_LEN:
432 continue;
433 default:
434 rv = ngtcp2_frame_chain_new(&nfrc, rtb->mem);
435 if (rv != 0) {
436 return rv;
437 }
438
439 nfrc->fr = *fr;
440
441 rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem);
442 if (rv != 0) {
443 return rv;
444 }
445
446 break;
447 }
448
449 ++num_reclaimed;
450
451 nfrc->next = *pfrc;
452 *pfrc = nfrc;
453 pfrc = &nfrc->next;
454 }
455
456 return (ngtcp2_ssize)num_reclaimed;
457 }
458
459 /*
460 * conn_process_lost_datagram calls ngtcp2_lost_datagram callback for
461 * lost DATAGRAM frames.
462 */
conn_process_lost_datagram(ngtcp2_conn * conn,ngtcp2_rtb_entry * ent)463 static int conn_process_lost_datagram(ngtcp2_conn *conn,
464 ngtcp2_rtb_entry *ent) {
465 ngtcp2_frame_chain *frc;
466 int rv;
467
468 for (frc = ent->frc; frc; frc = frc->next) {
469 switch (frc->fr.type) {
470 case NGTCP2_FRAME_DATAGRAM:
471 case NGTCP2_FRAME_DATAGRAM_LEN:
472 assert(conn->callbacks.lost_datagram);
473
474 rv = conn->callbacks.lost_datagram(conn, frc->fr.datagram.dgram_id,
475 conn->user_data);
476 if (rv != 0) {
477 return NGTCP2_ERR_CALLBACK_FAILURE;
478 }
479 break;
480 }
481 }
482
483 return 0;
484 }
485
rtb_on_pkt_lost(ngtcp2_rtb * rtb,ngtcp2_ksl_it * it,ngtcp2_rtb_entry * ent,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_tstamp ts)486 static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it,
487 ngtcp2_rtb_entry *ent, ngtcp2_conn *conn,
488 ngtcp2_pktns *pktns, ngtcp2_tstamp ts) {
489 int rv;
490 ngtcp2_ssize reclaimed;
491
492 ngtcp2_log_pkt_lost(rtb->log, ent->hd.pkt_num, ent->hd.type, ent->hd.flags,
493 ent->ts);
494
495 if (rtb->qlog) {
496 ngtcp2_qlog_pkt_lost(rtb->qlog, ent);
497 }
498
499 if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_PROBE)) {
500 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED) {
501 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
502 "pkn=%" PRId64 " has already been reclaimed on PTO",
503 ent->hd.pkt_num);
504 assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED));
505 assert(UINT64_MAX == ent->lost_ts);
506
507 ent->flags |= NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED;
508 ent->lost_ts = ts;
509
510 ++rtb->num_lost_pkts;
511
512 ngtcp2_ksl_it_next(it);
513
514 return 0;
515 }
516
517 if (conn->callbacks.lost_datagram &&
518 (ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM)) {
519 rv = conn_process_lost_datagram(conn, ent);
520 if (rv != 0) {
521 return rv;
522 }
523 }
524
525 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) {
526 assert(ent->frc);
527 assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED));
528 assert(UINT64_MAX == ent->lost_ts);
529
530 reclaimed = rtb_reclaim_frame(rtb, conn, pktns, ent);
531 if (reclaimed < 0) {
532 return (int)reclaimed;
533 }
534 }
535
536 ent->flags |= NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED;
537 ent->lost_ts = ts;
538
539 ++rtb->num_lost_pkts;
540
541 ngtcp2_ksl_it_next(it);
542
543 return 0;
544 }
545
546 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
547 "pkn=%" PRId64
548 " is a probe packet, no retransmission is necessary",
549 ent->hd.pkt_num);
550
551 rv = ngtcp2_ksl_remove_hint(&rtb->ents, it, it, &ent->hd.pkt_num);
552 assert(0 == rv);
553
554 ngtcp2_rtb_entry_del(ent, rtb->mem);
555
556 return 0;
557 }
558
ngtcp2_rtb_add(ngtcp2_rtb * rtb,ngtcp2_rtb_entry * ent,ngtcp2_conn_stat * cstat)559 int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
560 ngtcp2_conn_stat *cstat) {
561 int rv;
562
563 rv = ngtcp2_ksl_insert(&rtb->ents, NULL, &ent->hd.pkt_num, ent);
564 if (rv != 0) {
565 return rv;
566 }
567
568 rtb_on_add(rtb, ent, cstat);
569
570 return 0;
571 }
572
ngtcp2_rtb_head(ngtcp2_rtb * rtb)573 ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb) {
574 return ngtcp2_ksl_begin(&rtb->ents);
575 }
576
rtb_remove(ngtcp2_rtb * rtb,ngtcp2_ksl_it * it,ngtcp2_rtb_entry ** pent,ngtcp2_rtb_entry * ent,ngtcp2_conn_stat * cstat)577 static void rtb_remove(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it,
578 ngtcp2_rtb_entry **pent, ngtcp2_rtb_entry *ent,
579 ngtcp2_conn_stat *cstat) {
580 int rv;
581 (void)rv;
582
583 rv = ngtcp2_ksl_remove_hint(&rtb->ents, it, it, &ent->hd.pkt_num);
584 assert(0 == rv);
585 rtb_on_remove(rtb, ent, cstat);
586
587 assert(ent->next == NULL);
588
589 ngtcp2_list_insert(ent, pent);
590 }
591
conn_ack_crypto_data(ngtcp2_conn * conn,ngtcp2_pktns * pktns,uint64_t datalen)592 static void conn_ack_crypto_data(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
593 uint64_t datalen) {
594 ngtcp2_buf_chain **pbufchain, *bufchain;
595 size_t left;
596
597 for (pbufchain = &pktns->crypto.tx.data; *pbufchain;) {
598 left = ngtcp2_buf_len(&(*pbufchain)->buf);
599 if (left > datalen) {
600 (*pbufchain)->buf.pos += datalen;
601 return;
602 }
603
604 bufchain = *pbufchain;
605 *pbufchain = bufchain->next;
606
607 ngtcp2_mem_free(conn->mem, bufchain);
608
609 datalen -= left;
610
611 if (datalen == 0) {
612 return;
613 }
614 }
615
616 assert(datalen == 0);
617
618 return;
619 }
620
rtb_process_acked_pkt(ngtcp2_rtb * rtb,ngtcp2_rtb_entry * ent,ngtcp2_conn * conn)621 static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
622 ngtcp2_conn *conn) {
623 ngtcp2_frame_chain *frc;
624 uint64_t prev_stream_offset, stream_offset;
625 ngtcp2_strm *strm;
626 int rv;
627 uint64_t datalen;
628 ngtcp2_strm *crypto = rtb->crypto;
629 ngtcp2_pktns *pktns;
630
631 for (frc = ent->frc; frc; frc = frc->next) {
632 if (frc->binder) {
633 frc->binder->flags |= NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK;
634 }
635
636 switch (frc->fr.type) {
637 case NGTCP2_FRAME_STREAM:
638 strm = ngtcp2_conn_find_stream(conn, frc->fr.stream.stream_id);
639 if (strm == NULL) {
640 break;
641 }
642
643 strm->flags |= NGTCP2_STRM_FLAG_ANY_ACKED;
644
645 if (frc->fr.stream.fin) {
646 strm->flags |= NGTCP2_STRM_FLAG_FIN_ACKED;
647 }
648
649 prev_stream_offset = ngtcp2_strm_get_acked_offset(strm);
650 rv = ngtcp2_strm_ack_data(
651 strm, frc->fr.stream.offset,
652 ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt));
653 if (rv != 0) {
654 return rv;
655 }
656
657 if (conn->callbacks.acked_stream_data_offset) {
658 stream_offset = ngtcp2_strm_get_acked_offset(strm);
659 datalen = stream_offset - prev_stream_offset;
660 if (datalen == 0 && !frc->fr.stream.fin) {
661 break;
662 }
663
664 rv = conn->callbacks.acked_stream_data_offset(
665 conn, strm->stream_id, prev_stream_offset, datalen, conn->user_data,
666 strm->stream_user_data);
667 if (rv != 0) {
668 return NGTCP2_ERR_CALLBACK_FAILURE;
669 }
670 }
671
672 rv = ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm);
673 if (rv != 0) {
674 return rv;
675 }
676 break;
677 case NGTCP2_FRAME_CRYPTO:
678 prev_stream_offset = ngtcp2_strm_get_acked_offset(crypto);
679 rv = ngtcp2_strm_ack_data(
680 crypto, frc->fr.crypto.offset,
681 ngtcp2_vec_len(frc->fr.crypto.data, frc->fr.crypto.datacnt));
682 if (rv != 0) {
683 return rv;
684 }
685
686 stream_offset = ngtcp2_strm_get_acked_offset(crypto);
687 datalen = stream_offset - prev_stream_offset;
688 if (datalen == 0) {
689 break;
690 }
691
692 switch (rtb->pktns_id) {
693 case NGTCP2_PKTNS_ID_INITIAL:
694 pktns = conn->in_pktns;
695 break;
696 case NGTCP2_PKTNS_ID_HANDSHAKE:
697 pktns = conn->hs_pktns;
698 break;
699 case NGTCP2_PKTNS_ID_APPLICATION:
700 pktns = &conn->pktns;
701 break;
702 default:
703 assert(0);
704 }
705
706 conn_ack_crypto_data(conn, pktns, datalen);
707
708 break;
709 case NGTCP2_FRAME_RESET_STREAM:
710 strm = ngtcp2_conn_find_stream(conn, frc->fr.reset_stream.stream_id);
711 if (strm == NULL) {
712 break;
713 }
714 strm->flags |= NGTCP2_STRM_FLAG_RST_ACKED;
715 rv = ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm);
716 if (rv != 0) {
717 return rv;
718 }
719 break;
720 case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
721 assert(conn->dcid.num_retire_queued);
722 --conn->dcid.num_retire_queued;
723 break;
724 case NGTCP2_FRAME_DATAGRAM:
725 case NGTCP2_FRAME_DATAGRAM_LEN:
726 if (!conn->callbacks.ack_datagram) {
727 break;
728 }
729
730 rv = conn->callbacks.ack_datagram(conn, frc->fr.datagram.dgram_id,
731 conn->user_data);
732 if (rv != 0) {
733 return NGTCP2_ERR_CALLBACK_FAILURE;
734 }
735 break;
736 }
737 }
738 return 0;
739 }
740
rtb_on_pkt_acked(ngtcp2_rtb * rtb,ngtcp2_rtb_entry * ent,ngtcp2_conn_stat * cstat,ngtcp2_tstamp ts)741 static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
742 ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) {
743 ngtcp2_cc *cc = rtb->cc;
744 ngtcp2_cc_pkt pkt;
745
746 ngtcp2_rst_update_rate_sample(rtb->rst, ent, ts);
747
748 cc->on_pkt_acked(cc, cstat,
749 ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen,
750 rtb->pktns_id, ent->ts),
751 ts);
752
753 if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_PROBE) &&
754 (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) {
755 cstat->pto_count = 0;
756 }
757 }
758
conn_verify_ecn(ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_cc * cc,ngtcp2_conn_stat * cstat,const ngtcp2_ack * fr,size_t ecn_acked,ngtcp2_tstamp largest_acked_sent_ts,ngtcp2_tstamp ts)759 static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
760 ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
761 const ngtcp2_ack *fr, size_t ecn_acked,
762 ngtcp2_tstamp largest_acked_sent_ts,
763 ngtcp2_tstamp ts) {
764 if (conn->tx.ecn.state == NGTCP2_ECN_STATE_FAILED) {
765 return;
766 }
767
768 if ((ecn_acked && fr->type == NGTCP2_FRAME_ACK) ||
769 (fr->type == NGTCP2_FRAME_ACK_ECN &&
770 (pktns->rx.ecn.ack.ect0 > fr->ecn.ect0 ||
771 pktns->rx.ecn.ack.ect1 > fr->ecn.ect1 ||
772 pktns->rx.ecn.ack.ce > fr->ecn.ce ||
773 (fr->ecn.ect0 - pktns->rx.ecn.ack.ect0) +
774 (fr->ecn.ce - pktns->rx.ecn.ack.ce) <
775 ecn_acked ||
776 fr->ecn.ect0 > pktns->tx.ecn.ect0 || fr->ecn.ect1))) {
777 ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
778 "path is not ECN capable");
779 conn->tx.ecn.state = NGTCP2_ECN_STATE_FAILED;
780 return;
781 }
782
783 if (conn->tx.ecn.state != NGTCP2_ECN_STATE_CAPABLE && ecn_acked) {
784 ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "path is ECN capable");
785 conn->tx.ecn.state = NGTCP2_ECN_STATE_CAPABLE;
786 }
787
788 if (fr->type == NGTCP2_FRAME_ACK_ECN) {
789 if (largest_acked_sent_ts != UINT64_MAX &&
790 fr->ecn.ce > pktns->rx.ecn.ack.ce) {
791 cc->congestion_event(cc, cstat, largest_acked_sent_ts, ts);
792 }
793
794 pktns->rx.ecn.ack.ect0 = fr->ecn.ect0;
795 pktns->rx.ecn.ack.ect1 = fr->ecn.ect1;
796 pktns->rx.ecn.ack.ce = fr->ecn.ce;
797 }
798 }
799
800 static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost,
801 ngtcp2_conn *conn, ngtcp2_pktns *pktns,
802 ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts);
803
ngtcp2_rtb_recv_ack(ngtcp2_rtb * rtb,const ngtcp2_ack * fr,ngtcp2_conn_stat * cstat,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_tstamp pkt_ts,ngtcp2_tstamp ts)804 ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
805 ngtcp2_conn_stat *cstat, ngtcp2_conn *conn,
806 ngtcp2_pktns *pktns, ngtcp2_tstamp pkt_ts,
807 ngtcp2_tstamp ts) {
808 ngtcp2_rtb_entry *ent;
809 int64_t largest_ack = fr->largest_ack, min_ack;
810 size_t i;
811 int rv;
812 ngtcp2_ksl_it it;
813 ngtcp2_ssize num_acked = 0;
814 ngtcp2_tstamp largest_pkt_sent_ts = UINT64_MAX;
815 ngtcp2_tstamp largest_acked_sent_ts = UINT64_MAX;
816 int64_t pkt_num;
817 ngtcp2_cc *cc = rtb->cc;
818 ngtcp2_rtb_entry *acked_ent = NULL;
819 int ack_eliciting_pkt_acked = 0;
820 size_t ecn_acked = 0;
821 int verify_ecn = 0;
822 ngtcp2_cc_ack cc_ack = {0};
823 size_t num_lost_pkts = rtb->num_lost_pkts;
824
825 cc_ack.prior_bytes_in_flight = cstat->bytes_in_flight;
826
827 if (conn && (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) &&
828 largest_ack >= conn->pktns.crypto.tx.ckm->pkt_num) {
829 conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED;
830 conn->crypto.key_update.confirmed_ts = ts;
831
832 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_CRY, "key update confirmed");
833 }
834
835 if (rtb->largest_acked_tx_pkt_num < largest_ack) {
836 rtb->largest_acked_tx_pkt_num = largest_ack;
837 verify_ecn = 1;
838 }
839
840 /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
841 it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack);
842 if (ngtcp2_ksl_it_end(&it)) {
843 if (conn && verify_ecn) {
844 conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked,
845 largest_acked_sent_ts, ts);
846 }
847 return 0;
848 }
849
850 min_ack = largest_ack - (int64_t)fr->first_ack_blklen;
851
852 for (; !ngtcp2_ksl_it_end(&it);) {
853 pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it);
854
855 assert(pkt_num <= largest_ack);
856
857 if (pkt_num < min_ack) {
858 break;
859 }
860
861 ent = ngtcp2_ksl_it_get(&it);
862
863 if (largest_ack == pkt_num) {
864 largest_pkt_sent_ts = ent->ts;
865 }
866
867 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
868 ack_eliciting_pkt_acked = 1;
869 }
870
871 rtb_remove(rtb, &it, &acked_ent, ent, cstat);
872 ++num_acked;
873 }
874
875 for (i = 0; i < fr->num_blks;) {
876 largest_ack = min_ack - (int64_t)fr->blks[i].gap - 2;
877 min_ack = largest_ack - (int64_t)fr->blks[i].blklen;
878
879 it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack);
880 if (ngtcp2_ksl_it_end(&it)) {
881 break;
882 }
883
884 for (; !ngtcp2_ksl_it_end(&it);) {
885 pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it);
886 if (pkt_num < min_ack) {
887 break;
888 }
889 ent = ngtcp2_ksl_it_get(&it);
890
891 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) {
892 ack_eliciting_pkt_acked = 1;
893 }
894
895 rtb_remove(rtb, &it, &acked_ent, ent, cstat);
896 ++num_acked;
897 }
898
899 ++i;
900 }
901
902 if (largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) {
903 ngtcp2_conn_update_rtt(conn, pkt_ts - largest_pkt_sent_ts,
904 fr->ack_delay_unscaled, ts);
905 if (cc->new_rtt_sample) {
906 cc->new_rtt_sample(cc, cstat, ts);
907 }
908 }
909
910 if (conn) {
911 for (ent = acked_ent; ent; ent = acked_ent) {
912 if (ent->hd.pkt_num >= pktns->tx.ecn.start_pkt_num &&
913 (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ECN)) {
914 ++ecn_acked;
915 }
916
917 assert(largest_acked_sent_ts == UINT64_MAX ||
918 largest_acked_sent_ts <= ent->ts);
919
920 largest_acked_sent_ts = ent->ts;
921
922 rv = rtb_process_acked_pkt(rtb, ent, conn);
923 if (rv != 0) {
924 goto fail;
925 }
926
927 if (ent->hd.pkt_num >= rtb->cc_pkt_num) {
928 assert(cc_ack.pkt_delivered <= ent->rst.delivered);
929
930 cc_ack.bytes_delivered += ent->pktlen;
931 cc_ack.pkt_delivered = ent->rst.delivered;
932 }
933
934 rtb_on_pkt_acked(rtb, ent, cstat, ts);
935 acked_ent = ent->next;
936 ngtcp2_rtb_entry_del(ent, rtb->mem);
937 }
938
939 if (verify_ecn) {
940 conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked,
941 largest_acked_sent_ts, ts);
942 }
943 } else {
944 /* For unit tests */
945 for (ent = acked_ent; ent; ent = acked_ent) {
946 rtb_on_pkt_acked(rtb, ent, cstat, ts);
947 acked_ent = ent->next;
948 ngtcp2_rtb_entry_del(ent, rtb->mem);
949 }
950 }
951
952 if (rtb->cc->on_spurious_congestion && num_lost_pkts &&
953 rtb->num_lost_pkts == 0) {
954 rtb->cc->on_spurious_congestion(cc, cstat, ts);
955 }
956
957 ngtcp2_rst_on_ack_recv(rtb->rst, cstat, cc_ack.pkt_delivered);
958
959 if (conn && num_acked > 0) {
960 rv = rtb_detect_lost_pkt(rtb, &cc_ack.bytes_lost, conn, pktns, cstat, ts);
961 if (rv != 0) {
962 return rv;
963 }
964 }
965
966 cc_ack.largest_acked_sent_ts = largest_acked_sent_ts;
967 cc->on_ack_recv(cc, cstat, &cc_ack, ts);
968
969 return num_acked;
970
971 fail:
972 for (ent = acked_ent; ent; ent = acked_ent) {
973 acked_ent = ent->next;
974 ngtcp2_rtb_entry_del(ent, rtb->mem);
975 }
976
977 return rv;
978 }
979
rtb_pkt_lost(ngtcp2_rtb * rtb,ngtcp2_conn_stat * cstat,const ngtcp2_rtb_entry * ent,uint64_t loss_delay,ngtcp2_tstamp lost_send_time,size_t pkt_thres)980 static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat,
981 const ngtcp2_rtb_entry *ent, uint64_t loss_delay,
982 ngtcp2_tstamp lost_send_time, size_t pkt_thres) {
983 ngtcp2_tstamp loss_time;
984
985 if (ent->ts <= lost_send_time ||
986 rtb->largest_acked_tx_pkt_num >= ent->hd.pkt_num + (int64_t)pkt_thres) {
987 return 1;
988 }
989
990 loss_time = cstat->loss_time[rtb->pktns_id];
991
992 if (loss_time == UINT64_MAX) {
993 loss_time = ent->ts + loss_delay;
994 } else {
995 loss_time = ngtcp2_min(loss_time, ent->ts + loss_delay);
996 }
997
998 cstat->loss_time[rtb->pktns_id] = loss_time;
999
1000 return 0;
1001 }
1002
1003 /*
1004 * rtb_compute_pkt_loss_delay computes loss delay.
1005 */
compute_pkt_loss_delay(const ngtcp2_conn_stat * cstat)1006 static ngtcp2_duration compute_pkt_loss_delay(const ngtcp2_conn_stat *cstat) {
1007 /* 9/8 is kTimeThreshold */
1008 ngtcp2_duration loss_delay =
1009 ngtcp2_max(cstat->latest_rtt, cstat->smoothed_rtt) * 9 / 8;
1010 return ngtcp2_max(loss_delay, NGTCP2_GRANULARITY);
1011 }
1012
1013 /*
1014 * conn_all_ecn_pkt_lost returns nonzero if all ECN QUIC packets are
1015 * lost during validation period.
1016 */
conn_all_ecn_pkt_lost(ngtcp2_conn * conn)1017 static int conn_all_ecn_pkt_lost(ngtcp2_conn *conn) {
1018 ngtcp2_pktns *in_pktns = conn->in_pktns;
1019 ngtcp2_pktns *hs_pktns = conn->hs_pktns;
1020 ngtcp2_pktns *pktns = &conn->pktns;
1021
1022 return (!in_pktns || in_pktns->tx.ecn.validation_pkt_sent ==
1023 in_pktns->tx.ecn.validation_pkt_lost) &&
1024 (!hs_pktns || hs_pktns->tx.ecn.validation_pkt_sent ==
1025 hs_pktns->tx.ecn.validation_pkt_lost) &&
1026 pktns->tx.ecn.validation_pkt_sent == pktns->tx.ecn.validation_pkt_lost;
1027 }
1028
rtb_detect_lost_pkt(ngtcp2_rtb * rtb,uint64_t * ppkt_lost,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_conn_stat * cstat,ngtcp2_tstamp ts)1029 static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost,
1030 ngtcp2_conn *conn, ngtcp2_pktns *pktns,
1031 ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) {
1032 ngtcp2_rtb_entry *ent;
1033 ngtcp2_duration loss_delay;
1034 ngtcp2_tstamp lost_send_time;
1035 ngtcp2_ksl_it it;
1036 ngtcp2_tstamp latest_ts, oldest_ts;
1037 int64_t last_lost_pkt_num;
1038 ngtcp2_duration loss_window, congestion_period;
1039 ngtcp2_cc *cc = rtb->cc;
1040 int rv;
1041 uint64_t pkt_thres =
1042 rtb->cc_bytes_in_flight / cstat->max_udp_payload_size / 2;
1043 size_t ecn_pkt_lost = 0;
1044 ngtcp2_tstamp start_ts;
1045 ngtcp2_duration pto = ngtcp2_conn_compute_pto(conn, pktns);
1046 uint64_t prior_bytes_in_flight = cstat->bytes_in_flight;
1047
1048 pkt_thres = ngtcp2_max(pkt_thres, NGTCP2_PKT_THRESHOLD);
1049 pkt_thres = ngtcp2_min(pkt_thres, 256);
1050 cstat->loss_time[rtb->pktns_id] = UINT64_MAX;
1051 loss_delay = compute_pkt_loss_delay(cstat);
1052 lost_send_time = ts - loss_delay;
1053
1054 it = ngtcp2_ksl_lower_bound(&rtb->ents, &rtb->largest_acked_tx_pkt_num);
1055 for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) {
1056 ent = ngtcp2_ksl_it_get(&it);
1057
1058 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) {
1059 break;
1060 }
1061
1062 if (rtb_pkt_lost(rtb, cstat, ent, loss_delay, lost_send_time,
1063 (size_t)pkt_thres)) {
1064 /* All entries from ent are considered to be lost. */
1065 latest_ts = oldest_ts = ent->ts;
1066 last_lost_pkt_num = ent->hd.pkt_num;
1067
1068 congestion_period = (cstat->smoothed_rtt +
1069 ngtcp2_max(4 * cstat->rttvar, NGTCP2_GRANULARITY) +
1070 conn->remote.transport_params.max_ack_delay) *
1071 NGTCP2_PERSISTENT_CONGESTION_THRESHOLD;
1072
1073 start_ts = ngtcp2_max(rtb->persistent_congestion_start_ts,
1074 cstat->first_rtt_sample_ts);
1075
1076 for (; !ngtcp2_ksl_it_end(&it);) {
1077 ent = ngtcp2_ksl_it_get(&it);
1078
1079 if (last_lost_pkt_num == ent->hd.pkt_num + 1 && ent->ts >= start_ts) {
1080 last_lost_pkt_num = ent->hd.pkt_num;
1081 oldest_ts = ent->ts;
1082 } else {
1083 last_lost_pkt_num = -1;
1084 }
1085
1086 if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)) {
1087 if (rtb->pktns_id != NGTCP2_PKTNS_ID_APPLICATION ||
1088 last_lost_pkt_num == -1 ||
1089 latest_ts - oldest_ts >= congestion_period) {
1090 break;
1091 }
1092 ngtcp2_ksl_it_next(&it);
1093 continue;
1094 }
1095
1096 if (ent->hd.pkt_num >= pktns->tx.ecn.start_pkt_num &&
1097 (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ECN)) {
1098 ++ecn_pkt_lost;
1099 }
1100
1101 rtb_on_remove(rtb, ent, cstat);
1102 rv = rtb_on_pkt_lost(rtb, &it, ent, conn, pktns, ts);
1103 if (rv != 0) {
1104 return rv;
1105 }
1106 }
1107
1108 switch (conn->tx.ecn.state) {
1109 case NGTCP2_ECN_STATE_TESTING:
1110 if (conn->tx.ecn.validation_start_ts == UINT64_MAX) {
1111 break;
1112 }
1113 if (ts - conn->tx.ecn.validation_start_ts < 3 * pto) {
1114 pktns->tx.ecn.validation_pkt_lost += ecn_pkt_lost;
1115 assert(pktns->tx.ecn.validation_pkt_sent >=
1116 pktns->tx.ecn.validation_pkt_lost);
1117 break;
1118 }
1119 conn->tx.ecn.state = NGTCP2_ECN_STATE_UNKNOWN;
1120 /* fall through */
1121 case NGTCP2_ECN_STATE_UNKNOWN:
1122 pktns->tx.ecn.validation_pkt_lost += ecn_pkt_lost;
1123 assert(pktns->tx.ecn.validation_pkt_sent >=
1124 pktns->tx.ecn.validation_pkt_lost);
1125 if (conn_all_ecn_pkt_lost(conn)) {
1126 conn->tx.ecn.state = NGTCP2_ECN_STATE_FAILED;
1127 }
1128 break;
1129 default:
1130 break;
1131 }
1132
1133 cc->congestion_event(cc, cstat, latest_ts, ts);
1134
1135 loss_window = latest_ts - oldest_ts;
1136 /* Persistent congestion situation is only evaluated for app
1137 * packet number space and for the packets sent after handshake
1138 * is confirmed. During handshake, there is not much packets
1139 * sent and also people seem to do lots of effort not to trigger
1140 * persistent congestion there, then it is a lot easier to just
1141 * not enable it during handshake.
1142 */
1143 if (rtb->pktns_id == NGTCP2_PKTNS_ID_APPLICATION && loss_window > 0) {
1144 if (loss_window >= congestion_period) {
1145 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
1146 "persistent congestion loss_window=%" PRIu64
1147 " congestion_period=%" PRIu64,
1148 loss_window, congestion_period);
1149
1150 /* Reset min_rtt, srtt, and rttvar here. Next new RTT
1151 sample will be used to recalculate these values. */
1152 cstat->min_rtt = UINT64_MAX;
1153 cstat->smoothed_rtt = conn->local.settings.initial_rtt;
1154 cstat->rttvar = conn->local.settings.initial_rtt / 2;
1155 cstat->first_rtt_sample_ts = UINT64_MAX;
1156
1157 cc->on_persistent_congestion(cc, cstat, ts);
1158 }
1159 }
1160
1161 break;
1162 }
1163 }
1164
1165 ngtcp2_rtb_remove_excessive_lost_pkt(rtb, (size_t)pkt_thres);
1166
1167 if (ppkt_lost) {
1168 assert(prior_bytes_in_flight >= cstat->bytes_in_flight);
1169
1170 *ppkt_lost = prior_bytes_in_flight - cstat->bytes_in_flight;
1171 }
1172
1173 return 0;
1174 }
1175
ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb * rtb,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_conn_stat * cstat,ngtcp2_tstamp ts)1176 int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
1177 ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat,
1178 ngtcp2_tstamp ts) {
1179 return rtb_detect_lost_pkt(rtb, /* ppkt_lost = */ NULL, conn, pktns, cstat,
1180 ts);
1181 }
1182
ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb * rtb,size_t n)1183 void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) {
1184 ngtcp2_ksl_it it = ngtcp2_ksl_end(&rtb->ents);
1185 ngtcp2_rtb_entry *ent;
1186 int rv;
1187 (void)rv;
1188
1189 for (; rtb->num_lost_pkts > n;) {
1190 assert(ngtcp2_ksl_it_end(&it));
1191 ngtcp2_ksl_it_prev(&it);
1192 ent = ngtcp2_ksl_it_get(&it);
1193
1194 assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED);
1195
1196 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
1197 "removing stale lost pkn=%" PRId64, ent->hd.pkt_num);
1198
1199 --rtb->num_lost_pkts;
1200 rv = ngtcp2_ksl_remove_hint(&rtb->ents, &it, &it, &ent->hd.pkt_num);
1201 assert(0 == rv);
1202 ngtcp2_rtb_entry_del(ent, rtb->mem);
1203 }
1204 }
1205
ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb * rtb,ngtcp2_duration pto,ngtcp2_tstamp ts)1206 void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto,
1207 ngtcp2_tstamp ts) {
1208 ngtcp2_ksl_it it;
1209 ngtcp2_rtb_entry *ent;
1210 int rv;
1211 (void)rv;
1212
1213 if (ngtcp2_ksl_len(&rtb->ents) == 0) {
1214 return;
1215 }
1216
1217 it = ngtcp2_ksl_end(&rtb->ents);
1218
1219 for (;;) {
1220 assert(ngtcp2_ksl_it_end(&it));
1221
1222 ngtcp2_ksl_it_prev(&it);
1223 ent = ngtcp2_ksl_it_get(&it);
1224
1225 if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) ||
1226 ts - ent->lost_ts < pto) {
1227 return;
1228 }
1229
1230 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
1231 "removing stale lost pkn=%" PRId64, ent->hd.pkt_num);
1232
1233 --rtb->num_lost_pkts;
1234 rv = ngtcp2_ksl_remove_hint(&rtb->ents, &it, &it, &ent->hd.pkt_num);
1235 assert(0 == rv);
1236 ngtcp2_rtb_entry_del(ent, rtb->mem);
1237
1238 if (ngtcp2_ksl_len(&rtb->ents) == 0) {
1239 return;
1240 }
1241 }
1242 }
1243
ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb * rtb)1244 ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb) {
1245 ngtcp2_ksl_it it;
1246 ngtcp2_rtb_entry *ent;
1247
1248 if (ngtcp2_ksl_len(&rtb->ents) == 0) {
1249 return UINT64_MAX;
1250 }
1251
1252 it = ngtcp2_ksl_end(&rtb->ents);
1253 ngtcp2_ksl_it_prev(&it);
1254 ent = ngtcp2_ksl_it_get(&it);
1255
1256 if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)) {
1257 return UINT64_MAX;
1258 }
1259
1260 return ent->lost_ts;
1261 }
1262
rtb_on_pkt_lost_resched_move(ngtcp2_rtb * rtb,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_rtb_entry * ent)1263 static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
1264 ngtcp2_pktns *pktns,
1265 ngtcp2_rtb_entry *ent) {
1266 ngtcp2_frame_chain **pfrc, *frc;
1267 ngtcp2_stream *sfr;
1268 ngtcp2_strm *strm;
1269 int rv;
1270
1271 ngtcp2_log_pkt_lost(rtb->log, ent->hd.pkt_num, ent->hd.type, ent->hd.flags,
1272 ent->ts);
1273
1274 if (rtb->qlog) {
1275 ngtcp2_qlog_pkt_lost(rtb->qlog, ent);
1276 }
1277
1278 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PROBE) {
1279 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
1280 "pkn=%" PRId64
1281 " is a probe packet, no retransmission is necessary",
1282 ent->hd.pkt_num);
1283 return 0;
1284 }
1285
1286 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) {
1287 --rtb->num_lost_pkts;
1288
1289 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
1290 "pkn=%" PRId64
1291 " was declared lost and has already been retransmitted",
1292 ent->hd.pkt_num);
1293 return 0;
1294 }
1295
1296 if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED) {
1297 ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
1298 "pkn=%" PRId64 " has already been reclaimed on PTO",
1299 ent->hd.pkt_num);
1300 return 0;
1301 }
1302
1303 if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) &&
1304 (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM) ||
1305 !conn->callbacks.lost_datagram)) {
1306 /* PADDING only (or PADDING + ACK ) packets will have NULL
1307 ent->frc. */
1308 return 0;
1309 }
1310
1311 pfrc = &ent->frc;
1312
1313 for (; *pfrc;) {
1314 switch ((*pfrc)->fr.type) {
1315 case NGTCP2_FRAME_STREAM:
1316 frc = *pfrc;
1317
1318 *pfrc = frc->next;
1319 frc->next = NULL;
1320 sfr = &frc->fr.stream;
1321
1322 strm = ngtcp2_conn_find_stream(conn, sfr->stream_id);
1323 if (!strm) {
1324 ngtcp2_frame_chain_del(frc, conn->mem);
1325 break;
1326 }
1327 rv = ngtcp2_strm_streamfrq_push(strm, frc);
1328 if (rv != 0) {
1329 ngtcp2_frame_chain_del(frc, conn->mem);
1330 return rv;
1331 }
1332 if (!ngtcp2_strm_is_tx_queued(strm)) {
1333 strm->cycle = ngtcp2_conn_tx_strmq_first_cycle(conn);
1334 rv = ngtcp2_conn_tx_strmq_push(conn, strm);
1335 if (rv != 0) {
1336 return rv;
1337 }
1338 }
1339 break;
1340 case NGTCP2_FRAME_CRYPTO:
1341 frc = *pfrc;
1342
1343 *pfrc = frc->next;
1344 frc->next = NULL;
1345
1346 rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
1347 &frc->fr.crypto.offset, frc);
1348 if (rv != 0) {
1349 assert(ngtcp2_err_is_fatal(rv));
1350 ngtcp2_frame_chain_del(frc, conn->mem);
1351 return rv;
1352 }
1353 break;
1354 case NGTCP2_FRAME_DATAGRAM:
1355 case NGTCP2_FRAME_DATAGRAM_LEN:
1356 frc = *pfrc;
1357
1358 if (conn->callbacks.lost_datagram) {
1359 rv = conn->callbacks.lost_datagram(conn, frc->fr.datagram.dgram_id,
1360 conn->user_data);
1361 if (rv != 0) {
1362 return NGTCP2_ERR_CALLBACK_FAILURE;
1363 }
1364 }
1365
1366 *pfrc = (*pfrc)->next;
1367
1368 ngtcp2_frame_chain_del(frc, conn->mem);
1369 break;
1370 default:
1371 pfrc = &(*pfrc)->next;
1372 }
1373 }
1374
1375 *pfrc = pktns->tx.frq;
1376 pktns->tx.frq = ent->frc;
1377 ent->frc = NULL;
1378
1379 return 0;
1380 }
1381
ngtcp2_rtb_remove_all(ngtcp2_rtb * rtb,ngtcp2_conn * conn,ngtcp2_pktns * pktns,ngtcp2_conn_stat * cstat)1382 int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
1383 ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat) {
1384 ngtcp2_rtb_entry *ent;
1385 ngtcp2_ksl_it it;
1386 int rv;
1387
1388 it = ngtcp2_ksl_begin(&rtb->ents);
1389
1390 for (; !ngtcp2_ksl_it_end(&it);) {
1391 ent = ngtcp2_ksl_it_get(&it);
1392
1393 rtb_on_remove(rtb, ent, cstat);
1394 rv = ngtcp2_ksl_remove_hint(&rtb->ents, &it, &it, &ent->hd.pkt_num);
1395 assert(0 == rv);
1396
1397 rv = rtb_on_pkt_lost_resched_move(rtb, conn, pktns, ent);
1398 ngtcp2_rtb_entry_del(ent, rtb->mem);
1399 if (rv != 0) {
1400 return rv;
1401 }
1402 }
1403
1404 return 0;
1405 }
1406
ngtcp2_rtb_remove_early_data(ngtcp2_rtb * rtb,ngtcp2_conn_stat * cstat)1407 void ngtcp2_rtb_remove_early_data(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat) {
1408 ngtcp2_rtb_entry *ent;
1409 ngtcp2_ksl_it it;
1410 int rv;
1411 (void)rv;
1412
1413 it = ngtcp2_ksl_begin(&rtb->ents);
1414
1415 for (; !ngtcp2_ksl_it_end(&it);) {
1416 ent = ngtcp2_ksl_it_get(&it);
1417
1418 if (ent->hd.type != NGTCP2_PKT_0RTT) {
1419 ngtcp2_ksl_it_next(&it);
1420 continue;
1421 }
1422
1423 rtb_on_remove(rtb, ent, cstat);
1424 rv = ngtcp2_ksl_remove_hint(&rtb->ents, &it, &it, &ent->hd.pkt_num);
1425 assert(0 == rv);
1426
1427 ngtcp2_rtb_entry_del(ent, rtb->mem);
1428 }
1429 }
1430
ngtcp2_rtb_empty(ngtcp2_rtb * rtb)1431 int ngtcp2_rtb_empty(ngtcp2_rtb *rtb) {
1432 return ngtcp2_ksl_len(&rtb->ents) == 0;
1433 }
1434
ngtcp2_rtb_reset_cc_state(ngtcp2_rtb * rtb,int64_t cc_pkt_num)1435 void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num) {
1436 rtb->cc_pkt_num = cc_pkt_num;
1437 rtb->cc_bytes_in_flight = 0;
1438 }
1439
ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb * rtb,ngtcp2_conn * conn,ngtcp2_pktns * pktns,size_t num_pkts)1440 ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
1441 ngtcp2_pktns *pktns, size_t num_pkts) {
1442 ngtcp2_ksl_it it;
1443 ngtcp2_rtb_entry *ent;
1444 ngtcp2_ssize reclaimed;
1445 size_t atmost = num_pkts;
1446
1447 it = ngtcp2_ksl_end(&rtb->ents);
1448 for (; !ngtcp2_ksl_it_begin(&it) && num_pkts >= 1;) {
1449 ngtcp2_ksl_it_prev(&it);
1450 ent = ngtcp2_ksl_it_get(&it);
1451
1452 if ((ent->flags & (NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED |
1453 NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED)) ||
1454 !(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE)) {
1455 continue;
1456 }
1457
1458 assert(ent->frc);
1459
1460 reclaimed = rtb_reclaim_frame(rtb, conn, pktns, ent);
1461 if (reclaimed < 0) {
1462 return reclaimed;
1463 }
1464
1465 /* Mark reclaimed even if reclaimed == 0 so that we can skip it in
1466 the next run. */
1467 ent->flags |= NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED;
1468
1469 assert(rtb->num_retransmittable);
1470 --rtb->num_retransmittable;
1471
1472 if (reclaimed) {
1473 --num_pkts;
1474 }
1475 }
1476
1477 return (ngtcp2_ssize)(atmost - num_pkts);
1478 }
1479