aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2021-02-12 14:51:53 +0300
committerRoman Arutyunyan <arut@nginx.com>2021-02-12 14:51:53 +0300
commit5d4e864e0d83c4eae10d26cfca3be1bba415982a (patch)
treec7c26e09c946d91b850bf78d8d07ac9af0548e47
parent8084a829d022ddb5ebc16393a82e5374edb1a8f5 (diff)
downloadnginx-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.c82
-rw-r--r--src/event/quic/ngx_event_quic_transport.c21
-rw-r--r--src/event/quic/ngx_event_quic_transport.h4
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 {