Mercurial > hg > nginx
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 } |