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