mirror of
https://github.com/nginx/nginx.git
synced 2025-01-20 10:32:59 +08:00
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.
This commit is contained in:
parent
cc3752ce8e
commit
7a8fa11828
@ -293,6 +293,7 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
|
|||||||
void
|
void
|
||||||
ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
|
ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
|
||||||
{
|
{
|
||||||
|
ngx_uint_t blocked;
|
||||||
ngx_msec_t timer;
|
ngx_msec_t timer;
|
||||||
ngx_quic_congestion_t *cg;
|
ngx_quic_congestion_t *cg;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
@ -304,6 +305,8 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
|
|||||||
qc = ngx_quic_get_connection(c);
|
qc = ngx_quic_get_connection(c);
|
||||||
cg = &qc->congestion;
|
cg = &qc->congestion;
|
||||||
|
|
||||||
|
blocked = (cg->in_flight >= cg->window) ? 1 : 0;
|
||||||
|
|
||||||
cg->in_flight -= f->plen;
|
cg->in_flight -= f->plen;
|
||||||
|
|
||||||
timer = f->last - cg->recovery_start;
|
timer = f->last - cg->recovery_start;
|
||||||
@ -313,7 +316,7 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
|
|||||||
"quic congestion ack recovery win:%uz ss:%z if:%uz",
|
"quic congestion ack recovery win:%uz ss:%z if:%uz",
|
||||||
cg->window, cg->ssthresh, cg->in_flight);
|
cg->window, cg->ssthresh, cg->in_flight);
|
||||||
|
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cg->window < cg->ssthresh) {
|
if (cg->window < cg->ssthresh) {
|
||||||
@ -338,6 +341,12 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
|
|||||||
if ((ngx_msec_int_t) timer < 0) {
|
if ((ngx_msec_int_t) timer < 0) {
|
||||||
cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
|
cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (blocked && cg->in_flight < cg->window) {
|
||||||
|
ngx_post_event(&qc->push, &ngx_posted_events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -620,6 +629,7 @@ ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
|
|||||||
static void
|
static void
|
||||||
ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
|
ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
|
||||||
{
|
{
|
||||||
|
ngx_uint_t blocked;
|
||||||
ngx_msec_t timer;
|
ngx_msec_t timer;
|
||||||
ngx_quic_congestion_t *cg;
|
ngx_quic_congestion_t *cg;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
@ -631,6 +641,8 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
|
|||||||
qc = ngx_quic_get_connection(c);
|
qc = ngx_quic_get_connection(c);
|
||||||
cg = &qc->congestion;
|
cg = &qc->congestion;
|
||||||
|
|
||||||
|
blocked = (cg->in_flight >= cg->window) ? 1 : 0;
|
||||||
|
|
||||||
cg->in_flight -= f->plen;
|
cg->in_flight -= f->plen;
|
||||||
f->plen = 0;
|
f->plen = 0;
|
||||||
|
|
||||||
@ -641,7 +653,7 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
|
|||||||
"quic congestion lost recovery win:%uz ss:%z if:%uz",
|
"quic congestion lost recovery win:%uz ss:%z if:%uz",
|
||||||
cg->window, cg->ssthresh, cg->in_flight);
|
cg->window, cg->ssthresh, cg->in_flight);
|
||||||
|
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
cg->recovery_start = ngx_current_msec;
|
cg->recovery_start = ngx_current_msec;
|
||||||
@ -656,6 +668,12 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
|
|||||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"quic congestion lost win:%uz ss:%z if:%uz",
|
"quic congestion lost win:%uz ss:%z if:%uz",
|
||||||
cg->window, cg->ssthresh, cg->in_flight);
|
cg->window, cg->ssthresh, cg->in_flight);
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (blocked && cg->in_flight < cg->window) {
|
||||||
|
ngx_post_event(&qc->push, &ngx_posted_events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,13 +147,16 @@ ngx_quic_create_datagrams(ngx_connection_t *c, ngx_quic_socket_t *qsock)
|
|||||||
ngx_uint_t i, pad;
|
ngx_uint_t i, pad;
|
||||||
ngx_quic_path_t *path;
|
ngx_quic_path_t *path;
|
||||||
ngx_quic_send_ctx_t *ctx;
|
ngx_quic_send_ctx_t *ctx;
|
||||||
|
ngx_quic_congestion_t *cg;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
|
static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
|
||||||
|
|
||||||
qc = ngx_quic_get_connection(c);
|
qc = ngx_quic_get_connection(c);
|
||||||
|
cg = &qc->congestion;
|
||||||
path = qsock->path;
|
path = qsock->path;
|
||||||
|
|
||||||
for ( ;; ) {
|
while (cg->in_flight < cg->window) {
|
||||||
|
|
||||||
p = dst;
|
p = dst;
|
||||||
|
|
||||||
len = ngx_min(qc->ctp.max_udp_payload_size,
|
len = ngx_min(qc->ctp.max_udp_payload_size,
|
||||||
@ -339,10 +342,12 @@ ngx_quic_create_segments(ngx_connection_t *c, ngx_quic_socket_t *qsock)
|
|||||||
ngx_uint_t nseg;
|
ngx_uint_t nseg;
|
||||||
ngx_quic_path_t *path;
|
ngx_quic_path_t *path;
|
||||||
ngx_quic_send_ctx_t *ctx;
|
ngx_quic_send_ctx_t *ctx;
|
||||||
|
ngx_quic_congestion_t *cg;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF];
|
static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF];
|
||||||
|
|
||||||
qc = ngx_quic_get_connection(c);
|
qc = ngx_quic_get_connection(c);
|
||||||
|
cg = &qc->congestion;
|
||||||
path = qsock->path;
|
path = qsock->path;
|
||||||
|
|
||||||
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
|
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
|
||||||
@ -364,7 +369,7 @@ ngx_quic_create_segments(ngx_connection_t *c, ngx_quic_socket_t *qsock)
|
|||||||
|
|
||||||
len = ngx_min(segsize, (size_t) (end - p));
|
len = ngx_min(segsize, (size_t) (end - p));
|
||||||
|
|
||||||
if (len) {
|
if (len && cg->in_flight < cg->window) {
|
||||||
|
|
||||||
n = ngx_quic_output_packet(c, ctx, p, len, len, qsock);
|
n = ngx_quic_output_packet(c, ctx, p, len, len, qsock);
|
||||||
if (n == NGX_ERROR) {
|
if (n == NGX_ERROR) {
|
||||||
@ -531,7 +536,6 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
|
|||||||
ngx_queue_t *q;
|
ngx_queue_t *q;
|
||||||
ngx_quic_frame_t *f;
|
ngx_quic_frame_t *f;
|
||||||
ngx_quic_header_t pkt;
|
ngx_quic_header_t pkt;
|
||||||
ngx_quic_congestion_t *cg;
|
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
|
static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
|
||||||
|
|
||||||
@ -545,7 +549,6 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
|
|||||||
max, min);
|
max, min);
|
||||||
|
|
||||||
qc = ngx_quic_get_connection(c);
|
qc = ngx_quic_get_connection(c);
|
||||||
cg = &qc->congestion;
|
|
||||||
|
|
||||||
hlen = (ctx->level == ssl_encryption_application)
|
hlen = (ctx->level == ssl_encryption_application)
|
||||||
? NGX_QUIC_MAX_SHORT_HEADER
|
? NGX_QUIC_MAX_SHORT_HEADER
|
||||||
@ -568,10 +571,6 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
|
|||||||
{
|
{
|
||||||
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
|
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
|
||||||
|
|
||||||
if (!pkt.need_ack && f->need_ack && max > cg->window) {
|
|
||||||
max = cg->window;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f->type == NGX_QUIC_FT_PATH_RESPONSE
|
if (f->type == NGX_QUIC_FT_PATH_RESPONSE
|
||||||
|| f->type == NGX_QUIC_FT_PATH_CHALLENGE)
|
|| f->type == NGX_QUIC_FT_PATH_CHALLENGE)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user