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