Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_output.c @ 8823:f3331deed357 quic
QUIC: limit in-flight bytes by congestion window.
Previously, in-flight byte counter and congestion window were properly
maintained, but the limit was not properly implemented.
Now a new datagram is sent only if in-flight byte counter is less than window.
The limit is datagram-based, which means that a single datagram may lead to
exceeding the limit, but the next one will not be sent.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 29 Jul 2021 12:49:16 +0300 |
parents | ad046179eb91 |
children | c5155a0cb12f |
comparison
equal
deleted
inserted
replaced
8822:ad046179eb91 | 8823:f3331deed357 |
---|---|
145 u_char *p; | 145 u_char *p; |
146 uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; | 146 uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; |
147 ngx_uint_t i, pad; | 147 ngx_uint_t i, pad; |
148 ngx_quic_path_t *path; | 148 ngx_quic_path_t *path; |
149 ngx_quic_send_ctx_t *ctx; | 149 ngx_quic_send_ctx_t *ctx; |
150 ngx_quic_congestion_t *cg; | |
150 ngx_quic_connection_t *qc; | 151 ngx_quic_connection_t *qc; |
151 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 152 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
152 | 153 |
153 qc = ngx_quic_get_connection(c); | 154 qc = ngx_quic_get_connection(c); |
155 cg = &qc->congestion; | |
154 path = qsock->path; | 156 path = qsock->path; |
155 | 157 |
156 for ( ;; ) { | 158 while (cg->in_flight < cg->window) { |
159 | |
157 p = dst; | 160 p = dst; |
158 | 161 |
159 len = ngx_min(qc->ctp.max_udp_payload_size, | 162 len = ngx_min(qc->ctp.max_udp_payload_size, |
160 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE); | 163 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE); |
161 | 164 |
337 u_char *p, *end; | 340 u_char *p, *end; |
338 uint64_t preserved_pnum; | 341 uint64_t preserved_pnum; |
339 ngx_uint_t nseg; | 342 ngx_uint_t nseg; |
340 ngx_quic_path_t *path; | 343 ngx_quic_path_t *path; |
341 ngx_quic_send_ctx_t *ctx; | 344 ngx_quic_send_ctx_t *ctx; |
345 ngx_quic_congestion_t *cg; | |
342 ngx_quic_connection_t *qc; | 346 ngx_quic_connection_t *qc; |
343 static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; | 347 static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; |
344 | 348 |
345 qc = ngx_quic_get_connection(c); | 349 qc = ngx_quic_get_connection(c); |
350 cg = &qc->congestion; | |
346 path = qsock->path; | 351 path = qsock->path; |
347 | 352 |
348 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); | 353 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); |
349 | 354 |
350 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) { | 355 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) { |
362 | 367 |
363 for ( ;; ) { | 368 for ( ;; ) { |
364 | 369 |
365 len = ngx_min(segsize, (size_t) (end - p)); | 370 len = ngx_min(segsize, (size_t) (end - p)); |
366 | 371 |
367 if (len) { | 372 if (len && cg->in_flight < cg->window) { |
368 | 373 |
369 n = ngx_quic_output_packet(c, ctx, p, len, len, qsock); | 374 n = ngx_quic_output_packet(c, ctx, p, len, len, qsock); |
370 if (n == NGX_ERROR) { | 375 if (n == NGX_ERROR) { |
371 return NGX_ERROR; | 376 return NGX_ERROR; |
372 } | 377 } |
529 ngx_uint_t nframes, has_pr; | 534 ngx_uint_t nframes, has_pr; |
530 ngx_msec_t now; | 535 ngx_msec_t now; |
531 ngx_queue_t *q; | 536 ngx_queue_t *q; |
532 ngx_quic_frame_t *f; | 537 ngx_quic_frame_t *f; |
533 ngx_quic_header_t pkt; | 538 ngx_quic_header_t pkt; |
534 ngx_quic_congestion_t *cg; | |
535 ngx_quic_connection_t *qc; | 539 ngx_quic_connection_t *qc; |
536 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 540 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
537 | 541 |
538 if (ngx_queue_empty(&ctx->frames)) { | 542 if (ngx_queue_empty(&ctx->frames)) { |
539 return 0; | 543 return 0; |
543 "quic output sock #%uL %s packet max:%uz min:%uz", | 547 "quic output sock #%uL %s packet max:%uz min:%uz", |
544 qsock->sid.seqnum, ngx_quic_level_name(ctx->level), | 548 qsock->sid.seqnum, ngx_quic_level_name(ctx->level), |
545 max, min); | 549 max, min); |
546 | 550 |
547 qc = ngx_quic_get_connection(c); | 551 qc = ngx_quic_get_connection(c); |
548 cg = &qc->congestion; | |
549 | 552 |
550 hlen = (ctx->level == ssl_encryption_application) | 553 hlen = (ctx->level == ssl_encryption_application) |
551 ? NGX_QUIC_MAX_SHORT_HEADER | 554 ? NGX_QUIC_MAX_SHORT_HEADER |
552 : NGX_QUIC_MAX_LONG_HEADER; | 555 : NGX_QUIC_MAX_LONG_HEADER; |
553 | 556 |
565 for (q = ngx_queue_head(&ctx->frames); | 568 for (q = ngx_queue_head(&ctx->frames); |
566 q != ngx_queue_sentinel(&ctx->frames); | 569 q != ngx_queue_sentinel(&ctx->frames); |
567 q = ngx_queue_next(q)) | 570 q = ngx_queue_next(q)) |
568 { | 571 { |
569 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | 572 f = ngx_queue_data(q, ngx_quic_frame_t, queue); |
570 | |
571 if (!pkt.need_ack && f->need_ack && max > cg->window) { | |
572 max = cg->window; | |
573 } | |
574 | 573 |
575 if (f->type == NGX_QUIC_FT_PATH_RESPONSE | 574 if (f->type == NGX_QUIC_FT_PATH_RESPONSE |
576 || f->type == NGX_QUIC_FT_PATH_CHALLENGE) | 575 || f->type == NGX_QUIC_FT_PATH_CHALLENGE) |
577 { | 576 { |
578 has_pr = 1; | 577 has_pr = 1; |