Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic.c @ 8697:faa3201ff351 quic
QUIC: improved setting the lost timer.
Setting the timer is brought into compliance with quic-recovery-34. Now it's
set from a single function ngx_quic_set_lost_timer() that takes into account
both loss detection and PTO. The following issues are fixed with this change:
- when in loss detection mode, discarding a context could turn off the
timer forever after switching to the PTO mode
- when in loss detection mode, sending a packet resulted in rescheduling the
timer as if it's always in the PTO mode
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 12 Feb 2021 14:40:33 +0300 |
parents | 88c9c868a7c9 |
children | 9ed95726b99b |
comparison
equal
deleted
inserted
replaced
8696:88c9c868a7c9 | 8697:faa3201ff351 |
---|---|
21 */ | 21 */ |
22 #define ngx_quic_get_send_ctx(qc, level) \ | 22 #define ngx_quic_get_send_ctx(qc, level) \ |
23 ((level) == ssl_encryption_initial) ? &((qc)->send_ctx[0]) \ | 23 ((level) == ssl_encryption_initial) ? &((qc)->send_ctx[0]) \ |
24 : (((level) == ssl_encryption_handshake) ? &((qc)->send_ctx[1]) \ | 24 : (((level) == ssl_encryption_handshake) ? &((qc)->send_ctx[1]) \ |
25 : &((qc)->send_ctx[2])) | 25 : &((qc)->send_ctx[2])) |
26 | |
27 #define ngx_quic_lost_threshold(qc) \ | |
28 ngx_max(NGX_QUIC_TIME_THR * ngx_max((qc)->latest_rtt, (qc)->avg_rtt), \ | |
29 NGX_QUIC_TIME_GRANULARITY) | |
26 | 30 |
27 #define NGX_QUIC_SEND_CTX_LAST (NGX_QUIC_ENCRYPTION_LAST - 1) | 31 #define NGX_QUIC_SEND_CTX_LAST (NGX_QUIC_ENCRYPTION_LAST - 1) |
28 | 32 |
29 /* | 33 /* |
30 * 7.4. Cryptographic Message Buffering | 34 * 7.4. Cryptographic Message Buffering |
355 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, | 359 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, |
356 ngx_quic_send_ctx_t *ctx); | 360 ngx_quic_send_ctx_t *ctx); |
357 static void ngx_quic_pto_handler(ngx_event_t *ev); | 361 static void ngx_quic_pto_handler(ngx_event_t *ev); |
358 static void ngx_quic_lost_handler(ngx_event_t *ev); | 362 static void ngx_quic_lost_handler(ngx_event_t *ev); |
359 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c); | 363 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c); |
364 static void ngx_quic_set_lost_timer(ngx_connection_t *c); | |
360 static void ngx_quic_resend_frames(ngx_connection_t *c, | 365 static void ngx_quic_resend_frames(ngx_connection_t *c, |
361 ngx_quic_send_ctx_t *ctx); | 366 ngx_quic_send_ctx_t *ctx); |
362 static void ngx_quic_push_handler(ngx_event_t *ev); | 367 static void ngx_quic_push_handler(ngx_event_t *ev); |
363 | 368 |
364 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, | 369 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, |
2605 if (level == ssl_encryption_initial) { | 2610 if (level == ssl_encryption_initial) { |
2606 ngx_quic_clear_temp_server_ids(c); | 2611 ngx_quic_clear_temp_server_ids(c); |
2607 } | 2612 } |
2608 | 2613 |
2609 ctx->send_ack = 0; | 2614 ctx->send_ack = 0; |
2615 | |
2616 ngx_quic_set_lost_timer(c); | |
2610 } | 2617 } |
2611 | 2618 |
2612 | 2619 |
2613 static ngx_int_t | 2620 static ngx_int_t |
2614 ngx_quic_check_csid(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) | 2621 ngx_quic_check_csid(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) |
4917 if (!qc->send_timer_set && !qc->closing) { | 4924 if (!qc->send_timer_set && !qc->closing) { |
4918 qc->send_timer_set = 1; | 4925 qc->send_timer_set = 1; |
4919 ngx_add_timer(c->read, qc->tp.max_idle_timeout); | 4926 ngx_add_timer(c->read, qc->tp.max_idle_timeout); |
4920 } | 4927 } |
4921 } | 4928 } |
4929 | |
4930 ngx_quic_set_lost_timer(c); | |
4922 | 4931 |
4923 return NGX_OK; | 4932 return NGX_OK; |
4924 } | 4933 } |
4925 | 4934 |
4926 | 4935 |
5165 do { | 5174 do { |
5166 q = ngx_queue_head(&ctx->frames); | 5175 q = ngx_queue_head(&ctx->frames); |
5167 ngx_queue_remove(q); | 5176 ngx_queue_remove(q); |
5168 ngx_queue_insert_tail(&ctx->sent, q); | 5177 ngx_queue_insert_tail(&ctx->sent, q); |
5169 } while (--nframes); | 5178 } while (--nframes); |
5170 | |
5171 if (qc->pto.timer_set) { | |
5172 ngx_del_timer(&qc->pto); | |
5173 } | |
5174 | |
5175 ngx_add_timer(&qc->pto, ngx_quic_pto(c, ctx)); | |
5176 } | 5179 } |
5177 | 5180 |
5178 cg->in_flight += res.len; | 5181 cg->in_flight += res.len; |
5179 | 5182 |
5180 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 5183 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
5421 | 5424 |
5422 static ngx_int_t | 5425 static ngx_int_t |
5423 ngx_quic_detect_lost(ngx_connection_t *c) | 5426 ngx_quic_detect_lost(ngx_connection_t *c) |
5424 { | 5427 { |
5425 ngx_uint_t i; | 5428 ngx_uint_t i; |
5426 ngx_msec_t now, wait, min_wait, thr; | 5429 ngx_msec_t now, wait, thr; |
5427 ngx_queue_t *q; | 5430 ngx_queue_t *q; |
5428 ngx_quic_frame_t *start; | 5431 ngx_quic_frame_t *start; |
5429 ngx_quic_send_ctx_t *ctx; | 5432 ngx_quic_send_ctx_t *ctx; |
5430 ngx_quic_connection_t *qc; | 5433 ngx_quic_connection_t *qc; |
5431 | 5434 |
5432 qc = ngx_quic_get_connection(c); | 5435 qc = ngx_quic_get_connection(c); |
5433 now = ngx_current_msec; | 5436 now = ngx_current_msec; |
5434 | 5437 thr = ngx_quic_lost_threshold(qc); |
5435 min_wait = 0; | |
5436 | |
5437 thr = NGX_QUIC_TIME_THR * ngx_max(qc->latest_rtt, qc->avg_rtt); | |
5438 thr = ngx_max(thr, NGX_QUIC_TIME_GRANULARITY); | |
5439 | 5438 |
5440 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { | 5439 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { |
5441 | 5440 |
5442 ctx = &qc->send_ctx[i]; | 5441 ctx = &qc->send_ctx[i]; |
5443 | 5442 |
5461 start->pnum, thr, (ngx_int_t) wait, start->level); | 5460 start->pnum, thr, (ngx_int_t) wait, start->level); |
5462 | 5461 |
5463 if ((ngx_msec_int_t) wait > 0 | 5462 if ((ngx_msec_int_t) wait > 0 |
5464 && ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR) | 5463 && ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR) |
5465 { | 5464 { |
5466 | |
5467 if (min_wait == 0 || wait < min_wait) { | |
5468 min_wait = wait; | |
5469 } | |
5470 | |
5471 break; | 5465 break; |
5472 } | 5466 } |
5473 | 5467 |
5474 ngx_quic_resend_frames(c, ctx); | 5468 ngx_quic_resend_frames(c, ctx); |
5475 } | 5469 } |
5476 } | 5470 } |
5477 | 5471 |
5478 /* no more preceeding packets */ | 5472 ngx_quic_set_lost_timer(c); |
5479 | 5473 |
5480 if (min_wait == 0) { | 5474 return NGX_OK; |
5481 qc->pto.handler = ngx_quic_pto_handler; | 5475 } |
5482 return NGX_OK; | 5476 |
5483 } | 5477 |
5484 | 5478 static void |
5485 qc->pto.handler = ngx_quic_lost_handler; | 5479 ngx_quic_set_lost_timer(ngx_connection_t *c) |
5480 { | |
5481 ngx_uint_t i; | |
5482 ngx_msec_t now; | |
5483 ngx_queue_t *q; | |
5484 ngx_msec_int_t lost, pto, w; | |
5485 ngx_quic_frame_t *f; | |
5486 ngx_quic_send_ctx_t *ctx; | |
5487 ngx_quic_connection_t *qc; | |
5488 | |
5489 qc = ngx_quic_get_connection(c); | |
5490 now = ngx_current_msec; | |
5491 | |
5492 lost = -1; | |
5493 pto = -1; | |
5494 | |
5495 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { | |
5496 ctx = &qc->send_ctx[i]; | |
5497 | |
5498 if (ngx_queue_empty(&ctx->sent)) { | |
5499 continue; | |
5500 } | |
5501 | |
5502 if (ctx->largest_ack != NGX_QUIC_UNSET_PN) { | |
5503 q = ngx_queue_head(&ctx->sent); | |
5504 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
5505 w = (ngx_msec_int_t) (f->last + ngx_quic_lost_threshold(qc) - now); | |
5506 | |
5507 if (f->pnum <= ctx->largest_ack) { | |
5508 if (w < 0 || ctx->largest_ack - f->pnum >= NGX_QUIC_PKT_THR) { | |
5509 w = 0; | |
5510 } | |
5511 | |
5512 if (lost == -1 || w < lost) { | |
5513 lost = w; | |
5514 } | |
5515 } | |
5516 } | |
5517 | |
5518 q = ngx_queue_last(&ctx->sent); | |
5519 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
5520 w = (ngx_msec_int_t) (f->last + ngx_quic_pto(c, ctx) - now); | |
5521 | |
5522 if (w < 0) { | |
5523 w = 0; | |
5524 } | |
5525 | |
5526 if (pto == -1 || w < pto) { | |
5527 pto = w; | |
5528 } | |
5529 } | |
5486 | 5530 |
5487 if (qc->pto.timer_set) { | 5531 if (qc->pto.timer_set) { |
5488 ngx_del_timer(&qc->pto); | 5532 ngx_del_timer(&qc->pto); |
5489 } | 5533 } |
5490 | 5534 |
5491 ngx_add_timer(&qc->pto, min_wait); | 5535 if (lost != -1) { |
5492 | 5536 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
5493 return NGX_OK; | 5537 "quic lost timer lost:%M", lost); |
5538 | |
5539 qc->pto.handler = ngx_quic_lost_handler; | |
5540 ngx_add_timer(&qc->pto, lost); | |
5541 return; | |
5542 } | |
5543 | |
5544 if (pto != -1) { | |
5545 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5546 "quic lost timer pto:%M", pto); | |
5547 | |
5548 qc->pto.handler = ngx_quic_pto_handler; | |
5549 ngx_add_timer(&qc->pto, pto); | |
5550 return; | |
5551 } | |
5552 | |
5553 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic lost timer unset"); | |
5494 } | 5554 } |
5495 | 5555 |
5496 | 5556 |
5497 static void | 5557 static void |
5498 ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) | 5558 ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) |