diff options
author | Roman Arutyunyan <arut@nginx.com> | 2021-02-12 14:51:53 +0300 |
---|---|---|
committer | Roman Arutyunyan <arut@nginx.com> | 2021-02-12 14:51:53 +0300 |
commit | 5d4e864e0d83c4eae10d26cfca3be1bba415982a (patch) | |
tree | c7c26e09c946d91b850bf78d8d07ac9af0548e47 | |
parent | 8084a829d022ddb5ebc16393a82e5374edb1a8f5 (diff) | |
download | nginx-5d4e864e0d83c4eae10d26cfca3be1bba415982a.tar.gz nginx-5d4e864e0d83c4eae10d26cfca3be1bba415982a.zip |
QUIC: send PING frames on PTO expiration.
Two PING frames are sent per level that generate two UDP datagrams.
-rw-r--r-- | src/event/quic/ngx_event_quic.c | 82 | ||||
-rw-r--r-- | src/event/quic/ngx_event_quic_transport.c | 21 | ||||
-rw-r--r-- | src/event/quic/ngx_event_quic_transport.h | 4 |
3 files changed, 95 insertions, 12 deletions
diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 58986da9a..2ffa1a810 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -5099,6 +5099,10 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, f->plen = 0; nframes++; + + if (f->flush) { + break; + } } if (nframes == 0) { @@ -5346,9 +5350,10 @@ static void ngx_quic_pto_handler(ngx_event_t *ev) { ngx_uint_t i; - ngx_queue_t *q; + ngx_msec_t now; + ngx_queue_t *q, *next; ngx_connection_t *c; - ngx_quic_frame_t *start; + ngx_quic_frame_t *f; ngx_quic_send_ctx_t *ctx; ngx_quic_connection_t *qc; @@ -5356,8 +5361,7 @@ ngx_quic_pto_handler(ngx_event_t *ev) c = ev->data; qc = ngx_quic_get_connection(c); - - qc->pto_count++; + now = ngx_current_msec; for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { @@ -5368,21 +5372,79 @@ ngx_quic_pto_handler(ngx_event_t *ev) } q = ngx_queue_head(&ctx->sent); - start = ngx_queue_data(q, ngx_quic_frame_t, queue); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); - if (start->pnum <= ctx->largest_ack + if (f->pnum <= ctx->largest_ack && ctx->largest_ack != NGX_QUIC_UNSET_PN) { continue; } - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic pto pnum:%uL pto_count:%ui level:%d", - start->pnum, qc->pto_count, start->level); + if ((ngx_msec_int_t) (f->last + ngx_quic_pto(c, ctx) - now) > 0) { + continue; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic pto %s pto_count:%ui", + ngx_quic_level_name(ctx->level), qc->pto_count); + + for (q = ngx_queue_head(&ctx->frames); + q != ngx_queue_sentinel(&ctx->frames); + /* void */) + { + next = ngx_queue_next(q); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); + + if (f->type == NGX_QUIC_FT_PING) { + ngx_queue_remove(q); + ngx_quic_free_frame(c, f); + } - ngx_quic_resend_frames(c, ctx); + q = next; + } + + for (q = ngx_queue_head(&ctx->sent); + q != ngx_queue_sentinel(&ctx->sent); + /* void */) + { + next = ngx_queue_next(q); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); + + if (f->type == NGX_QUIC_FT_PING) { + ngx_quic_congestion_lost(c, f); + ngx_queue_remove(q); + ngx_quic_free_frame(c, f); + } + + q = next; + } + + /* enforce 2 udp datagrams */ + + f = ngx_quic_alloc_frame(c); + if (f == NULL) { + break; + } + + f->level = ctx->level; + f->type = NGX_QUIC_FT_PING; + f->flush = 1; + + ngx_quic_queue_frame(qc, f); + + f = ngx_quic_alloc_frame(c); + if (f == NULL) { + break; + } + + f->level = ctx->level; + f->type = NGX_QUIC_FT_PING; + + ngx_quic_queue_frame(qc, f); } + qc->pto_count++; + ngx_quic_connstate_dbg(c); } diff --git a/src/event/quic/ngx_event_quic_transport.c b/src/event/quic/ngx_event_quic_transport.c index 73b146731..bba1a9b39 100644 --- a/src/event/quic/ngx_event_quic_transport.c +++ b/src/event/quic/ngx_event_quic_transport.c @@ -93,6 +93,7 @@ static size_t ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out, static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt, ngx_uint_t frame_type); +static size_t ngx_quic_create_ping(u_char *p); static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, ngx_chain_t *ranges); static size_t ngx_quic_create_stop_sending(u_char *p, @@ -1220,6 +1221,9 @@ ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f) f->need_ack = 1; switch (f->type) { + case NGX_QUIC_FT_PING: + return ngx_quic_create_ping(p); + case NGX_QUIC_FT_ACK: f->need_ack = 0; return ngx_quic_create_ack(p, &f->u.ack, f->data); @@ -1277,6 +1281,23 @@ ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f) static size_t +ngx_quic_create_ping(u_char *p) +{ + u_char *start; + + if (p == NULL) { + return ngx_quic_varint_len(NGX_QUIC_FT_PING); + } + + start = p; + + ngx_quic_build_int(&p, NGX_QUIC_FT_PING); + + return p - start; +} + + +static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, ngx_chain_t *ranges) { size_t len; diff --git a/src/event/quic/ngx_event_quic_transport.h b/src/event/quic/ngx_event_quic_transport.h index e747aaa2c..163ef3779 100644 --- a/src/event/quic/ngx_event_quic_transport.h +++ b/src/event/quic/ngx_event_quic_transport.h @@ -263,8 +263,8 @@ struct ngx_quic_frame_s { ngx_msec_t first; ngx_msec_t last; ssize_t len; - ngx_uint_t need_ack; - /* unsigned need_ack:1; */ + unsigned need_ack:1; + unsigned flush:1; ngx_chain_t *data; union { |