comparison src/event/ngx_event_quic.c @ 8587:61f1c6ac8967 quic

QUIC: added ACK frame range support. The history of acknowledged packet is kept in send context as ranges. Up to NGX_QUIC_MAX_RANGES ranges is stored. As a result, instead of separate ack frames, single frame with ranges is sent.
author Vladimir Homutov <vl@nginx.com>
date Wed, 14 Oct 2020 23:21:36 +0300
parents 02ee77f8d53d
children 018baa412c0d
comparison
equal deleted inserted replaced
8586:7621ffaa79b3 8587:61f1c6ac8967
91 */ 91 */
92 typedef struct { 92 typedef struct {
93 ngx_quic_secret_t client_secret; 93 ngx_quic_secret_t client_secret;
94 ngx_quic_secret_t server_secret; 94 ngx_quic_secret_t server_secret;
95 95
96 enum ssl_encryption_level_t level;
97
96 uint64_t pnum; /* to be sent */ 98 uint64_t pnum; /* to be sent */
97 uint64_t largest_ack; /* received from peer */ 99 uint64_t largest_ack; /* received from peer */
98 uint64_t largest_pn; /* received from peer */ 100 uint64_t largest_pn; /* received from peer */
99 101
100 ngx_queue_t frames; 102 ngx_queue_t frames;
101 ngx_queue_t sent; 103 ngx_queue_t sent;
104
105 uint64_t largest_range;
106 uint64_t first_range;
107 ngx_uint_t nranges;
108 ngx_quic_ack_range_t ranges[NGX_QUIC_MAX_RANGES];
109 struct timeval ack_received;
110 ngx_uint_t send_ack; /* unsigned send_ack:1 */
102 } ngx_quic_send_ctx_t; 111 } ngx_quic_send_ctx_t;
103 112
104 113
105 struct ngx_quic_connection_s { 114 struct ngx_quic_connection_s {
106 ngx_str_t scid; /* initial client ID */ 115 ngx_str_t scid; /* initial client ID */
228 enum ssl_encryption_level_t level); 237 enum ssl_encryption_level_t level);
229 static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc, 238 static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc,
230 ngx_quic_header_t *pkt); 239 ngx_quic_header_t *pkt);
231 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, 240 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
232 ngx_quic_header_t *pkt); 241 ngx_quic_header_t *pkt);
233 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt); 242 static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c,
243 ngx_quic_header_t *pkt);
244 static ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c,
245 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest);
246 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c,
247 ngx_quic_send_ctx_t *ctx);
234 static ngx_int_t ngx_quic_ack_delay(ngx_connection_t *c, 248 static ngx_int_t ngx_quic_ack_delay(ngx_connection_t *c,
235 struct timeval *received, enum ssl_encryption_level_t level); 249 struct timeval *received, enum ssl_encryption_level_t level);
236 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c); 250 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
237 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c); 251 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
238 252
683 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { 697 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
684 ngx_queue_init(&qc->send_ctx[i].frames); 698 ngx_queue_init(&qc->send_ctx[i].frames);
685 ngx_queue_init(&qc->send_ctx[i].sent); 699 ngx_queue_init(&qc->send_ctx[i].sent);
686 qc->send_ctx[i].largest_pn = (uint64_t) -1; 700 qc->send_ctx[i].largest_pn = (uint64_t) -1;
687 qc->send_ctx[i].largest_ack = (uint64_t) -1; 701 qc->send_ctx[i].largest_ack = (uint64_t) -1;
688 } 702 qc->send_ctx[i].largest_range = (uint64_t) -1;
703 }
704
705 qc->send_ctx[0].level = ssl_encryption_initial;
706 qc->send_ctx[1].level = ssl_encryption_handshake;
707 qc->send_ctx[2].level = ssl_encryption_application;
689 708
690 for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) { 709 for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
691 ngx_queue_init(&qc->crypto[i].frames); 710 ngx_queue_init(&qc->crypto[i].frames);
692 } 711 }
693 712
1972 1991
1973 f = ngx_queue_data(q, ngx_quic_frame_t, queue); 1992 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
1974 ngx_quic_congestion_ack(c, f); 1993 ngx_quic_congestion_ack(c, f);
1975 ngx_quic_free_frame(c, f); 1994 ngx_quic_free_frame(c, f);
1976 } 1995 }
1996
1997 ctx->send_ack = 0;
1977 } 1998 }
1978 1999
1979 2000
1980 static ngx_int_t 2001 static ngx_int_t
1981 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) 2002 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt)
2107 } 2128 }
2108 2129
2109 /* got there with ack-eliciting packet */ 2130 /* got there with ack-eliciting packet */
2110 2131
2111 if (!ack_sent) { 2132 if (!ack_sent) {
2112 if (ngx_quic_send_ack(c, pkt) != NGX_OK) { 2133 if (ngx_quic_ack_packet(c, pkt) != NGX_OK) {
2113 return NGX_ERROR; 2134 return NGX_ERROR;
2114 } 2135 }
2115 2136
2116 ack_sent = 1; 2137 ack_sent = 1;
2117 } 2138 }
2272 return NGX_OK; 2293 return NGX_OK;
2273 } 2294 }
2274 2295
2275 2296
2276 static ngx_int_t 2297 static ngx_int_t
2277 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt) 2298 ngx_quic_ack_packet(ngx_connection_t *c, ngx_quic_header_t *pkt)
2299 {
2300 uint64_t base, largest, smallest, gs, ge, gap, range, pn;
2301 ngx_uint_t i, j, nr;
2302 ngx_quic_send_ctx_t *ctx;
2303 ngx_quic_ack_range_t *r;
2304
2305 c->log->action = "preparing ack";
2306
2307 ctx = ngx_quic_get_send_ctx(c->quic, pkt->level);
2308
2309 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
2310 "ngx_quic_ack_packet pn %uL largest %uL nranges %ui",
2311 pkt->pn, ctx->largest_range, ctx->nranges);
2312
2313 if (!ctx->send_ack) {
2314 ngx_post_event(&c->quic->push, &ngx_posted_events);
2315 }
2316
2317 ctx->send_ack = 1;
2318
2319 base = ctx->largest_range;
2320 pn = pkt->pn;
2321
2322 if (base == (uint64_t) -1) {
2323 ctx->largest_range = pn;
2324 ctx->ack_received = pkt->received;
2325 return NGX_OK;
2326 }
2327
2328 if (base == pn) {
2329 return NGX_OK;
2330 }
2331
2332 largest = base;
2333 smallest = largest - ctx->first_range;
2334
2335 if (pn > base) {
2336 ctx->largest_range = pn;
2337 ctx->ack_received = pkt->received;
2338
2339 if (pn - base == 1) {
2340 ctx->first_range++;
2341 return NGX_OK;
2342
2343 } else {
2344 /* new gap in front of current largest */
2345 gap = pn - base - 2;
2346 range = ctx->first_range;
2347
2348 ctx->first_range = 0;
2349 i = 0;
2350
2351 goto insert;
2352 }
2353 }
2354
2355 /* pn < base, perform lookup in existing ranges */
2356
2357 if (pn >= smallest && pn <= largest) {
2358 return NGX_OK;
2359 }
2360
2361 #if (NGX_SUPPRESS_WARN)
2362 r = NULL;
2363 #endif
2364
2365 for (i = 0; i < ctx->nranges; i++) {
2366 r = &ctx->ranges[i];
2367
2368 ge = smallest - 1;
2369 gs = ge - r->gap;
2370
2371 if (pn >= gs && pn <= ge) {
2372
2373 if (gs == ge) {
2374 /* gap size is exactly one packet, now filled */
2375
2376 /* data moves to previous range, current is removed */
2377
2378 if (i == 0) {
2379 ctx->first_range += r->range + 2;
2380
2381 } else {
2382 ctx->ranges[i - 1].range += r->range + 2;
2383 }
2384
2385 nr = ctx->nranges - i - 1;
2386 if (nr) {
2387 ngx_memmove(&ctx->ranges[i], &ctx->ranges[i + 1],
2388 sizeof(ngx_quic_ack_range_t) * nr);
2389 }
2390
2391 ctx->nranges--;
2392
2393 } else if (pn == gs) {
2394 /* current gap shrinks from tail (current range grows) */
2395 r->gap--;
2396 r->range++;
2397
2398 } else if (pn == ge) {
2399 /* current gap shrinks from head (previous range grows) */
2400 r->gap--;
2401
2402 if (i == 0) {
2403 ctx->first_range++;
2404
2405 } else {
2406 ctx->ranges[i - 1].range++;
2407 }
2408
2409 } else {
2410 /* current gap is split into two parts */
2411
2412 r->gap = pn - gs - 1;
2413 gap = ge - pn - 1;
2414 range = 0;
2415
2416 goto insert;
2417 }
2418
2419 return NGX_OK;
2420 }
2421
2422 largest = smallest - r->gap - 2;
2423 smallest = largest - r->range;
2424
2425 if (pn >= smallest && pn <= largest) {
2426 /* this packet number is already known */
2427 return NGX_OK;
2428 }
2429
2430 }
2431
2432 if (pn == smallest - 1) {
2433 /* extend first or last range */
2434
2435 if (i == 0) {
2436 ctx->first_range++;
2437
2438 } else {
2439 r->range++;
2440 }
2441
2442 return NGX_OK;
2443 }
2444
2445 /* nothing found, add new range at the tail */
2446
2447 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2448 /* packet is too old to keep it */
2449 return ngx_quic_send_ack_range(c, ctx, pn, pn);
2450 }
2451
2452 gap = smallest - 2 - pn;
2453 range = 0;
2454
2455 insert:
2456
2457 nr = ctx->nranges - i;
2458
2459 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2460 /* last range is dropped and reused for newer data */
2461
2462 for (j = i; j < ctx->nranges; j++) {
2463 largest = smallest - ctx->ranges[j].gap - 2;
2464 smallest = largest - ctx->ranges[j].range;
2465 }
2466
2467 if (ngx_quic_send_ack_range(c, ctx, smallest, largest) != NGX_OK) {
2468 return NGX_ERROR;
2469 }
2470
2471 nr--;
2472
2473 } else {
2474 ctx->nranges++;
2475 }
2476
2477 ngx_memmove(&ctx->ranges[i + 1], &ctx->ranges[i],
2478 sizeof(ngx_quic_ack_range_t) * nr);
2479
2480 ctx->ranges[i].gap = gap;
2481 ctx->ranges[i].range = range;
2482
2483 return NGX_OK;
2484 }
2485
2486
2487 static ngx_int_t
2488 ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2489 uint64_t smallest, uint64_t largest)
2278 { 2490 {
2279 ngx_quic_frame_t *frame; 2491 ngx_quic_frame_t *frame;
2280
2281 c->log->action = "generating acknowledgment";
2282
2283 /* every ACK-eliciting packet is acknowledged, TODO ACK Ranges */
2284 2492
2285 frame = ngx_quic_alloc_frame(c, 0); 2493 frame = ngx_quic_alloc_frame(c, 0);
2286 if (frame == NULL) { 2494 if (frame == NULL) {
2287 return NGX_ERROR; 2495 return NGX_ERROR;
2288 } 2496 }
2289 2497
2290 frame->level = (pkt->level == ssl_encryption_early_data) 2498 frame->level = ctx->level;
2291 ? ssl_encryption_application
2292 : pkt->level;
2293
2294 frame->type = NGX_QUIC_FT_ACK; 2499 frame->type = NGX_QUIC_FT_ACK;
2295 frame->u.ack.largest = pkt->pn; 2500 frame->u.ack.largest = largest;
2296 frame->u.ack.delay = ngx_quic_ack_delay(c, &pkt->received, frame->level); 2501 frame->u.ack.delay = 0;
2297 2502 frame->u.ack.range_count = 0;
2298 ngx_sprintf(frame->info, "ACK for PN=%uL from frame handler level=%d", 2503 frame->u.ack.first_range = largest - smallest;
2299 pkt->pn, frame->level); 2504
2505 ngx_sprintf(frame->info, "ACK for PN=%uL..%uL 0 ranges level=%d",
2506 largest, smallest, frame->level);
2507
2508 return NGX_OK;
2509 }
2510
2511
2512 static ngx_int_t
2513 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
2514 {
2515 size_t ranges_len;
2516 ngx_quic_frame_t *frame;
2517
2518 ranges_len = sizeof(ngx_quic_ack_range_t) * ctx->nranges;
2519
2520 frame = ngx_quic_alloc_frame(c, ranges_len);
2521 if (frame == NULL) {
2522 return NGX_ERROR;
2523 }
2524
2525 ngx_memcpy(frame->data, ctx->ranges, ranges_len);
2526
2527 frame->level = ctx->level;
2528 frame->type = NGX_QUIC_FT_ACK;
2529 frame->u.ack.largest = ctx->largest_range;
2530 frame->u.ack.delay = ngx_quic_ack_delay(c, &ctx->ack_received, ctx->level);
2531 frame->u.ack.range_count = ctx->nranges;
2532 frame->u.ack.first_range = ctx->first_range;
2533 frame->u.ack.ranges_start = frame->data;
2534 frame->u.ack.ranges_end = frame->data + ranges_len;
2535
2536 ngx_sprintf(frame->info, "ACK for PN=%uL %ui ranges level=%d",
2537 ctx->largest_range, ctx->nranges, frame->level);
2538
2300 ngx_quic_queue_frame(c->quic, frame); 2539 ngx_quic_queue_frame(c->quic, frame);
2540
2541 ctx->send_ack = 0;
2301 2542
2302 return NGX_OK; 2543 return NGX_OK;
2303 } 2544 }
2304 2545
2305 2546
3710 3951
3711 static ngx_int_t 3952 static ngx_int_t
3712 ngx_quic_output(ngx_connection_t *c) 3953 ngx_quic_output(ngx_connection_t *c)
3713 { 3954 {
3714 ngx_uint_t i; 3955 ngx_uint_t i;
3956 ngx_quic_send_ctx_t *ctx;
3715 ngx_quic_connection_t *qc; 3957 ngx_quic_connection_t *qc;
3716 3958
3717 c->log->action = "sending frames"; 3959 c->log->action = "sending frames";
3718 3960
3719 qc = c->quic; 3961 qc = c->quic;
3720 3962
3721 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { 3963 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
3722 if (ngx_quic_output_frames(c, &qc->send_ctx[i]) != NGX_OK) { 3964
3965 ctx = &qc->send_ctx[i];
3966
3967 if (ctx->send_ack) {
3968 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
3969 return NGX_ERROR;
3970 }
3971 }
3972
3973 if (ngx_quic_output_frames(c, ctx) != NGX_OK) {
3723 return NGX_ERROR; 3974 return NGX_ERROR;
3724 } 3975 }
3725 } 3976 }
3726 3977
3727 if (!qc->send_timer_set && !qc->closing) { 3978 if (!qc->send_timer_set && !qc->closing) {