]> git.kaiwu.me - nginx.git/commitdiff
QUIC: added limit of queued data.
authorVladimir Homutov <vl@nginx.com>
Thu, 16 Jul 2020 12:02:38 +0000 (15:02 +0300)
committerVladimir Homutov <vl@nginx.com>
Thu, 16 Jul 2020 12:02:38 +0000 (15:02 +0300)
The ngx_quic_queue_frame() functions puts a frame into send queue and
schedules a push timer to actually send data.

The patch adds tracking for data amount in the queue and sends data
immediately if amount of data exceeds limit.

src/event/ngx_event_quic.c
src/event/ngx_event_quic.h
src/event/ngx_event_quic_transport.h

index e0c197b6ec1c4879ecdc7a9d5d4b3b6366007d57..8c13c6a047e0cb04f2dba4b8ecba511ebdefd493 100644 (file)
@@ -73,6 +73,8 @@ typedef struct {
 
     ngx_queue_t                       frames;
     ngx_queue_t                       sent;
+
+    size_t                            frames_len;
 } ngx_quic_send_ctx_t;
 
 
@@ -3273,10 +3275,24 @@ ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame)
 
     ngx_queue_insert_tail(&ctx->frames, &frame->queue);
 
-    /* TODO: check PUSH flag on stream and call output */
+    frame->len = ngx_quic_create_frame(NULL, frame);
+    /* always succeeds */
+
+    ctx->frames_len += frame->len;
 
-    if (!qc->push.timer_set && !qc->closing) {
-        ngx_add_timer(&qc->push, qc->tp.max_ack_delay);
+    if (qc->closing) {
+        return;
+    }
+
+    /* TODO: TCP_NODELAY analogue ? TCP_CORK and others... */
+
+    if (ctx->frames_len < NGX_QUIC_MIN_DATA_NODELAY) {
+        if (!qc->push.timer_set) {
+            ngx_add_timer(&qc->push, qc->tp.max_ack_delay);
+        }
+
+    } else {
+        ngx_post_event(&qc->push, &ngx_posted_events);
     }
 }
 
@@ -3309,7 +3325,7 @@ ngx_quic_output(ngx_connection_t *c)
 static ngx_int_t
 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
 {
-    size_t                  len, hlen, n;
+    size_t                  len, hlen;
     ngx_uint_t              need_ack;
     ngx_queue_t            *q, range;
     ngx_quic_frame_t       *f;
@@ -3340,9 +3356,7 @@ ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
             /* process group of frames that fits into packet */
             f = ngx_queue_data(q, ngx_quic_frame_t, queue);
 
-            n = ngx_quic_create_frame(NULL, f);
-
-            if (len && hlen + len + n > qc->ctp.max_udp_payload_size) {
+            if (len && hlen + len + f->len > qc->ctp.max_udp_payload_size) {
                 break;
             }
 
@@ -3350,7 +3364,7 @@ ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
                 need_ack = 1;
             }
 
-            if (need_ack && cg->in_flight + len + n > cg->window) {
+            if (need_ack && cg->in_flight + len + f->len > cg->window) {
                 break;
             }
 
@@ -3360,8 +3374,9 @@ ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
 
             ngx_queue_remove(&f->queue);
             ngx_queue_insert_tail(&range, &f->queue);
+            ctx->frames_len -= f->len;
 
-            len += n;
+            len += f->len;
 
         } while (q != ngx_queue_sentinel(&ctx->frames));
 
@@ -4271,7 +4286,6 @@ ngx_quic_alloc_frame(ngx_connection_t *c, size_t size)
 static void
 ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
 {
-    ssize_t                 n;
     ngx_msec_t              timer;
     ngx_quic_congestion_t  *cg;
     ngx_quic_connection_t  *qc;
@@ -4279,9 +4293,7 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
     qc = c->quic;
     cg = &qc->congestion;
 
-    n = ngx_quic_create_frame(NULL, f);
-
-    cg->in_flight -= n;
+    cg->in_flight -= f->len;
 
     timer = f->last - cg->recovery_start;
 
@@ -4290,14 +4302,14 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
     }
 
     if (cg->window < cg->ssthresh) {
-        cg->window += n;
+        cg->window += f->len;
 
         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "quic congestion slow start win:%uz, ss:%uz, if:%uz",
                        cg->window, cg->ssthresh, cg->in_flight);
 
     } else {
-        cg->window += qc->tp.max_udp_payload_size * n / cg->window;
+        cg->window += qc->tp.max_udp_payload_size * f->len / cg->window;
 
         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "quic congestion avoidance win:%uz, ss:%uz, if:%uz",
index 7d4281d552f8c7300142e0fe75c5fb5980e8f517..783820a2f88d273890d4adc42d586f437cc3d7b9 100644 (file)
 
 #define NGX_QUIC_MIN_INITIAL_SIZE            1200
 
+/* if we have so much data, send immediately */
+/* TODO: configurable ? */
+#define NGX_QUIC_MIN_DATA_NODELAY             512 /* bytes */
+
 #define NGX_QUIC_STREAM_SERVER_INITIATED     0x01
 #define NGX_QUIC_STREAM_UNIDIRECTIONAL       0x02
 
index 661ffede11044e75a74324eb27f7db9487e6aad0..f1a2787698a79b288f7ffa09bf4c3b1f6c4e3c62 100644 (file)
@@ -250,6 +250,7 @@ struct ngx_quic_frame_s {
     uint64_t                                    pnum;
     ngx_msec_t                                  first;
     ngx_msec_t                                  last;
+    ssize_t                                     len;
     ngx_uint_t                                  need_ack;
                                                     /* unsigned need_ack:1; */