comparison src/event/ngx_event_quic.c @ 8603:c5ea341f705a quic

QUIC: optimized acknowledgement generation. For application level packets, only every second packet is now acknowledged, respecting max ack delay. 13.2.1 Sending ACK Frames In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack- eliciting packet either: * when the received packet has a packet number less than another ack-eliciting packet that has been received, or * when the packet has a packet number larger than the highest- numbered ack-eliciting packet that has been received and there are missing packets between that packet and this packet. 13.2.2. Acknowledgement Frequency A receiver SHOULD send an ACK frame after receiving at least two ack-eliciting packets.
author Vladimir Homutov <vl@nginx.com>
date Fri, 23 Oct 2020 17:08:50 +0300
parents 454aa886c5f3
children b3d9e57d0f62
comparison
equal deleted inserted replaced
8602:454aa886c5f3 8603:c5ea341f705a
46 #define NGX_QUIC_MIN_PKT_LEN 21 46 #define NGX_QUIC_MIN_PKT_LEN 21
47 47
48 #define NGX_QUIC_MIN_SR_PACKET 43 /* 5 random + 16 srt + 22 padding */ 48 #define NGX_QUIC_MIN_SR_PACKET 43 /* 5 random + 16 srt + 22 padding */
49 #define NGX_QUIC_MAX_SR_PACKET 1200 49 #define NGX_QUIC_MAX_SR_PACKET 1200
50 50
51 #define NGX_QUIC_MAX_ACK_GAP 2
52
51 #define ngx_quic_level_name(lvl) \ 53 #define ngx_quic_level_name(lvl) \
52 (lvl == ssl_encryption_application) ? "application" \ 54 (lvl == ssl_encryption_application) ? "application" \
53 : (lvl == ssl_encryption_initial) ? "initial" \ 55 : (lvl == ssl_encryption_initial) ? "initial" \
54 : (lvl == ssl_encryption_handshake) ? "handshake" : "early_data" 56 : (lvl == ssl_encryption_handshake) ? "handshake" : "early_data"
55 57
105 ngx_queue_t sent; 107 ngx_queue_t sent;
106 108
107 uint64_t pending_ack; /* non sent ack-eliciting */ 109 uint64_t pending_ack; /* non sent ack-eliciting */
108 uint64_t largest_range; 110 uint64_t largest_range;
109 uint64_t first_range; 111 uint64_t first_range;
112 ngx_msec_t largest_received;
113 ngx_msec_t ack_delay_start;
110 ngx_uint_t nranges; 114 ngx_uint_t nranges;
111 ngx_quic_ack_range_t ranges[NGX_QUIC_MAX_RANGES]; 115 ngx_quic_ack_range_t ranges[NGX_QUIC_MAX_RANGES];
112 struct timeval ack_received; 116 ngx_uint_t send_ack;
113 ngx_uint_t send_ack; /* unsigned send_ack:1 */
114 } ngx_quic_send_ctx_t; 117 } ngx_quic_send_ctx_t;
115 118
116 119
117 struct ngx_quic_connection_s { 120 struct ngx_quic_connection_s {
118 ngx_str_t scid; /* initial client ID */ 121 ngx_str_t scid; /* initial client ID */
248 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest); 251 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest);
249 static void ngx_quic_drop_ack_ranges(ngx_connection_t *c, 252 static void ngx_quic_drop_ack_ranges(ngx_connection_t *c,
250 ngx_quic_send_ctx_t *ctx, uint64_t pn); 253 ngx_quic_send_ctx_t *ctx, uint64_t pn);
251 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c, 254 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c,
252 ngx_quic_send_ctx_t *ctx); 255 ngx_quic_send_ctx_t *ctx);
253 static ngx_int_t ngx_quic_ack_delay(ngx_connection_t *c,
254 struct timeval *received, enum ssl_encryption_level_t level);
255 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c); 256 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
256 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c); 257 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
257 258
258 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, 259 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
259 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f); 260 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f);
1909 */ 1910 */
1910 ngx_quic_discard_ctx(c, ssl_encryption_initial); 1911 ngx_quic_discard_ctx(c, ssl_encryption_initial);
1911 qc->validated = 1; 1912 qc->validated = 1;
1912 } 1913 }
1913 1914
1914 if (pkt->level == ssl_encryption_early_data 1915 pkt->received = ngx_current_msec;
1915 || pkt->level == ssl_encryption_application)
1916 {
1917 ngx_gettimeofday(&pkt->received);
1918 }
1919 1916
1920 c->log->action = "handling payload"; 1917 c->log->action = "handling payload";
1921 1918
1922 if (pkt->level != ssl_encryption_application) { 1919 if (pkt->level != ssl_encryption_application) {
1923 return ngx_quic_payload_handler(c, pkt); 1920 return ngx_quic_payload_handler(c, pkt);
2318 2315
2319 if (pkt->need_ack) { 2316 if (pkt->need_ack) {
2320 2317
2321 ngx_post_event(&c->quic->push, &ngx_posted_events); 2318 ngx_post_event(&c->quic->push, &ngx_posted_events);
2322 2319
2323 ctx->send_ack = 1; 2320 if (ctx->send_ack == 0) {
2321 ctx->ack_delay_start = ngx_current_msec;
2322 }
2323
2324 ctx->send_ack++;
2324 2325
2325 if (ctx->pending_ack == NGX_QUIC_UNSET_PN 2326 if (ctx->pending_ack == NGX_QUIC_UNSET_PN
2326 || ctx->pending_ack < pkt->pn) 2327 || ctx->pending_ack < pkt->pn)
2327 { 2328 {
2328 ctx->pending_ack = pkt->pn; 2329 ctx->pending_ack = pkt->pn;
2332 base = ctx->largest_range; 2333 base = ctx->largest_range;
2333 pn = pkt->pn; 2334 pn = pkt->pn;
2334 2335
2335 if (base == NGX_QUIC_UNSET_PN) { 2336 if (base == NGX_QUIC_UNSET_PN) {
2336 ctx->largest_range = pn; 2337 ctx->largest_range = pn;
2337 ctx->ack_received = pkt->received; 2338 ctx->largest_received = pkt->received;
2338 return NGX_OK; 2339 return NGX_OK;
2339 } 2340 }
2340 2341
2341 if (base == pn) { 2342 if (base == pn) {
2342 return NGX_OK; 2343 return NGX_OK;
2348 if (pn > base) { 2349 if (pn > base) {
2349 2350
2350 if (pn - base == 1) { 2351 if (pn - base == 1) {
2351 ctx->first_range++; 2352 ctx->first_range++;
2352 ctx->largest_range = pn; 2353 ctx->largest_range = pn;
2353 ctx->ack_received = pkt->received; 2354 ctx->largest_received = pkt->received;
2354 2355
2355 return NGX_OK; 2356 return NGX_OK;
2356 2357
2357 } else { 2358 } else {
2358 /* new gap in front of current largest */ 2359 /* new gap in front of current largest */
2374 gap = pn - base - 2; 2375 gap = pn - base - 2;
2375 range = ctx->first_range; 2376 range = ctx->first_range;
2376 2377
2377 ctx->first_range = 0; 2378 ctx->first_range = 0;
2378 ctx->largest_range = pn; 2379 ctx->largest_range = pn;
2379 ctx->ack_received = pkt->received; 2380 ctx->largest_received = pkt->received;
2381
2382 /* packet is out of order, force send */
2383 if (pkt->need_ack) {
2384 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
2385 }
2380 2386
2381 i = 0; 2387 i = 0;
2382 2388
2383 goto insert; 2389 goto insert;
2384 } 2390 }
2385 } 2391 }
2386 2392
2387 /* pn < base, perform lookup in existing ranges */ 2393 /* pn < base, perform lookup in existing ranges */
2394
2395 /* packet is out of order */
2396 if (pkt->need_ack) {
2397 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
2398 }
2388 2399
2389 if (pn >= smallest && pn <= largest) { 2400 if (pn >= smallest && pn <= largest) {
2390 return NGX_OK; 2401 return NGX_OK;
2391 } 2402 }
2392 2403
2602 2613
2603 static ngx_int_t 2614 static ngx_int_t
2604 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) 2615 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
2605 { 2616 {
2606 size_t ranges_len; 2617 size_t ranges_len;
2618 uint64_t ack_delay;
2607 ngx_quic_frame_t *frame; 2619 ngx_quic_frame_t *frame;
2620
2621 if (ctx->level == ssl_encryption_application) {
2622 ack_delay = ngx_current_msec - ctx->largest_received;
2623 ack_delay *= 1000;
2624 ack_delay >>= c->quic->ctp.ack_delay_exponent;
2625
2626 } else {
2627 ack_delay = 0;
2628 }
2608 2629
2609 ranges_len = sizeof(ngx_quic_ack_range_t) * ctx->nranges; 2630 ranges_len = sizeof(ngx_quic_ack_range_t) * ctx->nranges;
2610 2631
2611 frame = ngx_quic_alloc_frame(c, ranges_len); 2632 frame = ngx_quic_alloc_frame(c, ranges_len);
2612 if (frame == NULL) { 2633 if (frame == NULL) {
2616 ngx_memcpy(frame->data, ctx->ranges, ranges_len); 2637 ngx_memcpy(frame->data, ctx->ranges, ranges_len);
2617 2638
2618 frame->level = ctx->level; 2639 frame->level = ctx->level;
2619 frame->type = NGX_QUIC_FT_ACK; 2640 frame->type = NGX_QUIC_FT_ACK;
2620 frame->u.ack.largest = ctx->largest_range; 2641 frame->u.ack.largest = ctx->largest_range;
2621 frame->u.ack.delay = ngx_quic_ack_delay(c, &ctx->ack_received, ctx->level); 2642 frame->u.ack.delay = ack_delay;
2622 frame->u.ack.range_count = ctx->nranges; 2643 frame->u.ack.range_count = ctx->nranges;
2623 frame->u.ack.first_range = ctx->first_range; 2644 frame->u.ack.first_range = ctx->first_range;
2624 frame->u.ack.ranges_start = frame->data; 2645 frame->u.ack.ranges_start = frame->data;
2625 frame->u.ack.ranges_end = frame->data + ranges_len; 2646 frame->u.ack.ranges_end = frame->data + ranges_len;
2626 2647
2628 ctx->largest_range, ctx->nranges, frame->level); 2649 ctx->largest_range, ctx->nranges, frame->level);
2629 2650
2630 ngx_quic_queue_frame(c->quic, frame); 2651 ngx_quic_queue_frame(c->quic, frame);
2631 2652
2632 return NGX_OK; 2653 return NGX_OK;
2633 }
2634
2635
2636 static ngx_int_t
2637 ngx_quic_ack_delay(ngx_connection_t *c, struct timeval *received,
2638 enum ssl_encryption_level_t level)
2639 {
2640 ngx_int_t ack_delay;
2641 struct timeval tv;
2642
2643 ack_delay = 0;
2644
2645 if (level == ssl_encryption_application) {
2646 ngx_gettimeofday(&tv);
2647 ack_delay = (tv.tv_sec - received->tv_sec) * 1000000
2648 + tv.tv_usec - received->tv_usec;
2649 ack_delay = ngx_max(ack_delay, 0);
2650 ack_delay >>= c->quic->ctp.ack_delay_exponent;
2651 }
2652
2653 return ack_delay;
2654 } 2654 }
2655 2655
2656 2656
2657 static ngx_int_t 2657 static ngx_int_t
2658 ngx_quic_send_cc(ngx_connection_t *c) 2658 ngx_quic_send_cc(ngx_connection_t *c)
4052 4052
4053 static ngx_int_t 4053 static ngx_int_t
4054 ngx_quic_output(ngx_connection_t *c) 4054 ngx_quic_output(ngx_connection_t *c)
4055 { 4055 {
4056 ngx_uint_t i; 4056 ngx_uint_t i;
4057 ngx_msec_t delay;
4057 ngx_quic_send_ctx_t *ctx; 4058 ngx_quic_send_ctx_t *ctx;
4058 ngx_quic_connection_t *qc; 4059 ngx_quic_connection_t *qc;
4059 4060
4060 c->log->action = "sending frames"; 4061 c->log->action = "sending frames";
4061 4062
4064 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { 4065 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
4065 4066
4066 ctx = &qc->send_ctx[i]; 4067 ctx = &qc->send_ctx[i];
4067 4068
4068 if (ctx->send_ack) { 4069 if (ctx->send_ack) {
4070
4071 if (ctx->level == ssl_encryption_application) {
4072
4073 delay = ngx_current_msec - ctx->ack_delay_start;
4074
4075 if (ctx->send_ack < NGX_QUIC_MAX_ACK_GAP
4076 && delay < qc->tp.max_ack_delay)
4077 {
4078 if (!qc->push.timer_set && !qc->closing) {
4079 ngx_add_timer(&qc->push, qc->tp.max_ack_delay - delay);
4080 }
4081
4082 goto output;
4083 }
4084 }
4085
4069 if (ngx_quic_send_ack(c, ctx) != NGX_OK) { 4086 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
4070 return NGX_ERROR; 4087 return NGX_ERROR;
4071 } 4088 }
4072 ctx->send_ack = 0; 4089 ctx->send_ack = 0;
4073 } 4090 }
4091
4092 output:
4074 4093
4075 if (ngx_quic_output_frames(c, ctx) != NGX_OK) { 4094 if (ngx_quic_output_frames(c, ctx) != NGX_OK) {
4076 return NGX_ERROR; 4095 return NGX_ERROR;
4077 } 4096 }
4078 } 4097 }