QUIC: reworked congestion control mechanism.

朱宇 pl080516 at gmail.com
Tue Dec 6 14:35:37 UTC 2022


Hi,

# HG changeset patch
# User Yu Zhu <lishu.zy at alibaba-inc.com>
# Date 1670326031 -28800
#      Tue Dec 06 19:27:11 2022 +0800
# Branch quic
# Node ID 9a47ff1223bb32c8ddb146d731b395af89769a97
# Parent  1a320805265db14904ca9deaae8330f4979619ce
QUIC: reworked congestion control mechanism.

1. move rtt measurement and congestion control to struct ngx_quic_path_t
because RTT and congestion control are properities of the path.

2. introduced struct "ngx_quic_congestion_ops_t" to wrap callback functions
of congestion control and extract the reno algorithm from ngx_event_quic_ack.c.

No functional changes.

diff -r 1a320805265d -r 9a47ff1223bb auto/make
--- a/auto/make Sat Nov 19 00:31:55 2022 +0800
+++ b/auto/make Tue Dec 06 19:27:11 2022 +0800
@@ -6,7 +6,7 @@
echo "creating $NGX_MAKEFILE"

mkdir -p $NGX_OBJS/src/core $NGX_OBJS/src/event $NGX_OBJS/src/event/modules \
-         $NGX_OBJS/src/event/quic \
+         $NGX_OBJS/src/event/quic $NGX_OBJS/src/event/quic/congestion \
          $NGX_OBJS/src/os/unix $NGX_OBJS/src/os/win32 \
          $NGX_OBJS/src/http $NGX_OBJS/src/http/v2 $NGX_OBJS/src/http/v3 \
          $NGX_OBJS/src/http/modules $NGX_OBJS/src/http/modules/perl \
diff -r 1a320805265d -r 9a47ff1223bb auto/modules
--- a/auto/modules    Sat Nov 19 00:31:55 2022 +0800
+++ b/auto/modules    Tue Dec 06 19:27:11 2022 +0800
@@ -1355,7 +1355,8 @@
                      src/event/quic/ngx_event_quic_tokens.c \
                      src/event/quic/ngx_event_quic_ack.c \
                      src/event/quic/ngx_event_quic_output.c \
-                     src/event/quic/ngx_event_quic_socket.c"
+                     src/event/quic/ngx_event_quic_socket.c \
+                     src/event/quic/congestion/ngx_quic_reno.c"

     ngx_module_libs=
     ngx_module_link=YES
diff -r 1a320805265d -r 9a47ff1223bb src/event/quic/congestion/ngx_quic_reno.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/src/event/quic/congestion/ngx_quic_reno.c  Tue Dec 06 19:27:11 2022 +0800
@@ -0,0 +1,133 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_event_quic_connection.h>
+
+
+static void ngx_quic_reno_on_init(ngx_connection_t *c, ngx_quic_congestion_t *cg);
+static ngx_int_t ngx_quic_reno_on_ack(ngx_connection_t *c, ngx_quic_frame_t *f);
+static ngx_int_t ngx_quic_reno_on_lost(ngx_connection_t *c, ngx_quic_frame_t *f);
+
+
+ngx_quic_congestion_ops_t  ngx_quic_reno = {
+    ngx_string("reno"),
+    ngx_quic_reno_on_init,
+    ngx_quic_reno_on_ack,
+    ngx_quic_reno_on_lost
+};
+
+
+static void
+ngx_quic_reno_on_init(ngx_connection_t *c, ngx_quic_congestion_t *cg)
+{
+    ngx_quic_connection_t  *qc;
+
+    qc = ngx_quic_get_connection(c);
+
+    cg->window = ngx_min(10 * qc->tp.max_udp_payload_size,
+                            ngx_max(2 * qc->tp.max_udp_payload_size,
+                                    14720));
+    cg->ssthresh = (size_t) -1;
+    cg->recovery_start = ngx_current_msec;
+}
+
+
+static ngx_int_t
+ngx_quic_reno_on_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
+{
+    ngx_msec_t              timer;
+    ngx_quic_path_t        *path;
+    ngx_quic_connection_t  *qc;
+    ngx_quic_congestion_t  *cg;
+
+    qc = ngx_quic_get_connection(c);
+    path = qc->path;
+
+    cg = &path->congestion;
+
+    cg->in_flight -= f->plen;
+
+    timer = f->last - cg->recovery_start;
+
+    if ((ngx_msec_int_t) timer <= 0) {
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "quic congestion ack recovery win:%uz ss:%z if:%uz",
+                       cg->window, cg->ssthresh, cg->in_flight);
+
+        return NGX_DONE;
+    }
+
+    if (cg->window < cg->ssthresh) {
+        cg->window += f->plen;
+
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "quic congestion slow start win:%uz ss:%z if:%uz",
+                       cg->window, cg->ssthresh, cg->in_flight);
+
+    } else {
+        cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window;
+
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "quic congestion avoidance win:%uz ss:%z if:%uz",
+                       cg->window, cg->ssthresh, cg->in_flight);
+    }
+
+    /* prevent recovery_start from wrapping */
+
+    timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2;
+
+    if ((ngx_msec_int_t) timer < 0) {
+        cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_quic_reno_on_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
+{
+    ngx_msec_t              timer;
+    ngx_quic_path_t        *path;
+    ngx_quic_connection_t  *qc;
+    ngx_quic_congestion_t  *cg;
+
+    qc = ngx_quic_get_connection(c);
+    path = qc->path;
+
+    cg = &path->congestion;
+
+    cg->in_flight -= f->plen;
+    f->plen = 0;
+
+    timer = f->last - cg->recovery_start;
+
+    if ((ngx_msec_int_t) timer <= 0) {
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "quic congestion lost recovery win:%uz ss:%z if:%uz",
+                       cg->window, cg->ssthresh, cg->in_flight);
+
+        return NGX_DONE;
+    }
+
+    cg->recovery_start = ngx_current_msec;
+    cg->window /= 2;
+
+    if (cg->window < qc->tp.max_udp_payload_size * 2) {
+        cg->window = qc->tp.max_udp_payload_size * 2;
+    }
+
+    cg->ssthresh = cg->window;
+
+    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "quic congestion lost win:%uz ss:%z if:%uz",
+                   cg->window, cg->ssthresh, cg->in_flight);
+
+    return NGX_OK;
+}
diff -r 1a320805265d -r 9a47ff1223bb src/event/quic/ngx_event_quic.c
--- a/src/event/quic/ngx_event_quic.c Sat Nov 19 00:31:55 2022 +0800
+++ b/src/event/quic/ngx_event_quic.c Tue Dec 06 19:27:11 2022 +0800
@@ -264,15 +264,6 @@

     ngx_queue_init(&qc->free_frames);

-    qc->avg_rtt = NGX_QUIC_INITIAL_RTT;
-    qc->rttvar = NGX_QUIC_INITIAL_RTT / 2;
-    qc->min_rtt = NGX_TIMER_INFINITE;
-    qc->first_rtt = NGX_TIMER_INFINITE;
-
-    /*
-     * qc->latest_rtt = 0
-     */
-
     qc->pto.log = c->log;
     qc->pto.data = c;
     qc->pto.handler = ngx_quic_pto_handler;
@@ -311,12 +302,6 @@
     qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
     qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;

-    qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size,
-                                    ngx_max(2 * qc->tp.max_udp_payload_size,
-                                            14720));
-    qc->congestion.ssthresh = (size_t) -1;
-    qc->congestion.recovery_start = ngx_current_msec;
-
     if (pkt->validated && pkt->retried) {
         qc->tp.retry_scid.len = pkt->dcid.len;
         qc->tp.retry_scid.data = ngx_pstrdup(c->pool, &pkt->dcid);
diff -r 1a320805265d -r 9a47ff1223bb src/event/quic/ngx_event_quic_ack.c
--- a/src/event/quic/ngx_event_quic_ack.c   Sat Nov 19 00:31:55 2022 +0800
+++ b/src/event/quic/ngx_event_quic_ack.c   Tue Dec 06 19:27:11 2022 +0800
@@ -29,7 +29,7 @@
} ngx_quic_ack_stat_t;


-static ngx_inline ngx_msec_t ngx_quic_lost_threshold(ngx_quic_connection_t *qc);
+static ngx_inline ngx_msec_t ngx_quic_lost_threshold(ngx_quic_path_t *path);
static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
     enum ssl_encryption_level_t level, ngx_msec_t send_time);
static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
@@ -48,11 +48,11 @@

/* RFC 9002, 6.1.2. Time Threshold: kTimeThreshold, kGranularity */
static ngx_inline ngx_msec_t
-ngx_quic_lost_threshold(ngx_quic_connection_t *qc)
+ngx_quic_lost_threshold(ngx_quic_path_t *path)
{
     ngx_msec_t  thr;

-    thr = ngx_max(qc->latest_rtt, qc->avg_rtt);
+    thr = ngx_max(path->latest_rtt, path->avg_rtt);
     thr += thr >> 3;

     return ngx_max(thr, NGX_QUIC_TIME_GRANULARITY);
@@ -179,21 +179,23 @@
     enum ssl_encryption_level_t level, ngx_msec_t send_time)
{
     ngx_msec_t              latest_rtt, ack_delay, adjusted_rtt, rttvar_sample;
+    ngx_quic_path_t        *path;
     ngx_quic_connection_t  *qc;

     qc = ngx_quic_get_connection(c);
+    path = qc->path;

     latest_rtt = ngx_current_msec - send_time;
-    qc->latest_rtt = latest_rtt;
+    path->latest_rtt = latest_rtt;

-    if (qc->min_rtt == NGX_TIMER_INFINITE) {
-        qc->min_rtt = latest_rtt;
-        qc->avg_rtt = latest_rtt;
-        qc->rttvar = latest_rtt / 2;
-        qc->first_rtt = ngx_current_msec;
+    if (path->min_rtt == NGX_TIMER_INFINITE) {
+        path->min_rtt = latest_rtt;
+        path->avg_rtt = latest_rtt;
+        path->rttvar = latest_rtt / 2;
+        path->first_rtt = ngx_current_msec;

     } else {
-        qc->min_rtt = ngx_min(qc->min_rtt, latest_rtt);
+        path->min_rtt = ngx_min(path->min_rtt, latest_rtt);

         ack_delay = ack->delay * (1 << qc->ctp.ack_delay_exponent) / 1000;

@@ -203,18 +205,18 @@

         adjusted_rtt = latest_rtt;

-        if (qc->min_rtt + ack_delay < latest_rtt) {
+        if (path->min_rtt + ack_delay < latest_rtt) {
             adjusted_rtt -= ack_delay;
         }

-        qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3);
-        rttvar_sample = ngx_abs((ngx_msec_int_t) (qc->avg_rtt - adjusted_rtt));
-        qc->rttvar += (rttvar_sample >> 2) - (qc->rttvar >> 2);
+        path->avg_rtt += (adjusted_rtt >> 3) - (path->avg_rtt >> 3);
+        rttvar_sample = ngx_abs((ngx_msec_int_t) (path->avg_rtt - adjusted_rtt));
+        path->rttvar += (rttvar_sample >> 2) - (path->rttvar >> 2);
     }

     ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "quic rtt sample latest:%M min:%M avg:%M var:%M",
-                   latest_rtt, qc->min_rtt, qc->avg_rtt, qc->rttvar);
+                   latest_rtt, path->min_rtt, path->avg_rtt, path->rttvar);
}


@@ -307,7 +309,6 @@
ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
{
     ngx_uint_t              blocked;
-    ngx_msec_t              timer;
     ngx_quic_congestion_t  *cg;
     ngx_quic_connection_t  *qc;

@@ -316,46 +317,11 @@
     }

     qc = ngx_quic_get_connection(c);
-    cg = &qc->congestion;
+    cg = &qc->path->congestion;

     blocked = (cg->in_flight >= cg->window) ? 1 : 0;

-    cg->in_flight -= f->plen;
-
-    timer = f->last - cg->recovery_start;
-
-    if ((ngx_msec_int_t) timer <= 0) {
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                       "quic congestion ack recovery win:%uz ss:%z if:%uz",
-                       cg->window, cg->ssthresh, cg->in_flight);
-
-        goto done;
-    }
-
-    if (cg->window < cg->ssthresh) {
-        cg->window += f->plen;
-
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                       "quic congestion slow start win:%uz ss:%z if:%uz",
-                       cg->window, cg->ssthresh, cg->in_flight);
-
-    } else {
-        cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window;
-
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                       "quic congestion avoidance win:%uz ss:%z if:%uz",
-                       cg->window, cg->ssthresh, cg->in_flight);
-    }
-
-    /* prevent recovery_start from wrapping */
-
-    timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2;
-
-    if ((ngx_msec_int_t) timer < 0) {
-        cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
-    }
-
-done:
+    cg->cc_ops->ack(c, f);

     if (blocked && cg->in_flight < cg->window) {
         ngx_post_event(&qc->push, &ngx_posted_events);
@@ -433,7 +399,7 @@

     qc = ngx_quic_get_connection(c);
     now = ngx_current_msec;
-    thr = ngx_quic_lost_threshold(qc);
+    thr = ngx_quic_lost_threshold(qc->path);

     /* send time of lost packets across all send contexts */
     oldest = NGX_TIMER_INFINITE;
@@ -470,7 +436,7 @@
                 break;
             }

-            if (start->last > qc->first_rtt) {
+            if (start->last > qc->path->first_rtt) {

                 if (oldest == NGX_TIMER_INFINITE || start->last < oldest) {
                     oldest = start->last;
@@ -518,8 +484,8 @@

     qc = ngx_quic_get_connection(c);

-    duration = qc->avg_rtt;
-    duration += ngx_max(4 * qc->rttvar, NGX_QUIC_TIME_GRANULARITY);
+    duration = qc->path->avg_rtt;
+    duration += ngx_max(4 * qc->path->rttvar, NGX_QUIC_TIME_GRANULARITY);
     duration += qc->ctp.max_ack_delay;
     duration *= NGX_QUIC_PERSISTENT_CONGESTION_THR;

@@ -534,7 +500,7 @@
     ngx_quic_connection_t  *qc;

     qc = ngx_quic_get_connection(c);
-    cg = &qc->congestion;
+    cg = &qc->path->congestion;

     cg->recovery_start = ngx_current_msec;
     cg->window = qc->tp.max_udp_payload_size * 2;
@@ -646,7 +612,6 @@
ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
{
     ngx_uint_t              blocked;
-    ngx_msec_t              timer;
     ngx_quic_congestion_t  *cg;
     ngx_quic_connection_t  *qc;

@@ -655,37 +620,11 @@
     }

     qc = ngx_quic_get_connection(c);
-    cg = &qc->congestion;
+    cg = &qc->path->congestion;

     blocked = (cg->in_flight >= cg->window) ? 1 : 0;

-    cg->in_flight -= f->plen;
-    f->plen = 0;
-
-    timer = f->last - cg->recovery_start;
-
-    if ((ngx_msec_int_t) timer <= 0) {
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                       "quic congestion lost recovery win:%uz ss:%z if:%uz",
-                       cg->window, cg->ssthresh, cg->in_flight);
-
-        goto done;
-    }
-
-    cg->recovery_start = ngx_current_msec;
-    cg->window /= 2;
-
-    if (cg->window < qc->tp.max_udp_payload_size * 2) {
-        cg->window = qc->tp.max_udp_payload_size * 2;
-    }
-
-    cg->ssthresh = cg->window;
-
-    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "quic congestion lost win:%uz ss:%z if:%uz",
-                   cg->window, cg->ssthresh, cg->in_flight);
-
-done:
+    cg->cc_ops->lost(c, f);

     if (blocked && cg->in_flight < cg->window) {
         ngx_post_event(&qc->push, &ngx_posted_events);
@@ -720,7 +659,7 @@
         if (ctx->largest_ack != NGX_QUIC_UNSET_PN) {
             q = ngx_queue_head(&ctx->sent);
             f = ngx_queue_data(q, ngx_quic_frame_t, queue);
-            w = (ngx_msec_int_t) (f->last + ngx_quic_lost_threshold(qc) - now);
+            w = (ngx_msec_int_t) (f->last + ngx_quic_lost_threshold(qc->path) - now);

             if (f->pnum <= ctx->largest_ack) {
                 if (w < 0 || ctx->largest_ack - f->pnum >= NGX_QUIC_PKT_THR) {
@@ -781,12 +720,12 @@
     qc = ngx_quic_get_connection(c);

     /* RFC 9002, Appendix A.8.  Setting the Loss Detection Timer */
-    duration = qc->avg_rtt;
+    duration = qc->path->avg_rtt;

-    duration += ngx_max(4 * qc->rttvar, NGX_QUIC_TIME_GRANULARITY);
+    duration += ngx_max(4 * qc->path->rttvar, NGX_QUIC_TIME_GRANULARITY);
    duration <<= qc->pto_count;

-    if (qc->congestion.in_flight == 0) { /* no in-flight packets */
+    if (qc->path->congestion.in_flight == 0) { /* no in-flight packets */
         return duration;
     }

diff -r 1a320805265d -r 9a47ff1223bb src/event/quic/ngx_event_quic_connection.h
--- a/src/event/quic/ngx_event_quic_connection.h Sat Nov 19 00:31:55 2022 +0800
+++ b/src/event/quic/ngx_event_quic_connection.h Tue Dec 06 19:27:11 2022 +0800
@@ -18,6 +18,7 @@
/* #define NGX_QUIC_DEBUG_CRYPTO */

typedef struct ngx_quic_connection_s  ngx_quic_connection_t;
+typedef struct ngx_quic_congestion_s  ngx_quic_congestion_t;
typedef struct ngx_quic_server_id_s   ngx_quic_server_id_t;
typedef struct ngx_quic_client_id_s   ngx_quic_client_id_t;
typedef struct ngx_quic_send_ctx_s    ngx_quic_send_ctx_t;
@@ -63,6 +64,12 @@
#define ngx_quic_get_socket(c)               ((ngx_quic_socket_t *)((c)->udp))


+typedef void (*ngx_quic_congestion_init_pt)(ngx_connection_t *c,
+    ngx_quic_congestion_t *cg);
+typedef ngx_int_t (*ngx_quic_congestion_event_pt)(ngx_connection_t *c,
+    ngx_quic_frame_t *f);
+
+
struct ngx_quic_client_id_s {
     ngx_queue_t                       queue;
     uint64_t                          seqnum;
@@ -80,6 +87,23 @@
};


+typedef struct {
+    ngx_str_t                         name;
+    ngx_quic_congestion_init_pt       init;
+    ngx_quic_congestion_event_pt      ack;
+    ngx_quic_congestion_event_pt      lost;
+} ngx_quic_congestion_ops_t;
+
+
+struct ngx_quic_congestion_s {
+    size_t                            in_flight;
+    size_t                            window;
+    size_t                            ssthresh;
+    ngx_msec_t                        recovery_start;
+    ngx_quic_congestion_ops_t        *cc_ops;
+};
+
+
struct ngx_quic_path_s {
     ngx_queue_t                       queue;
     struct sockaddr                  *sockaddr;
@@ -96,6 +120,15 @@
     uint64_t                          seqnum;
     ngx_str_t                         addr_text;
     u_char                            text[NGX_SOCKADDR_STRLEN];
+
+    ngx_msec_t                        first_rtt;
+    ngx_msec_t                        latest_rtt;
+    ngx_msec_t                        avg_rtt;
+    ngx_msec_t                        min_rtt;
+    ngx_msec_t                        rttvar;
+
+    ngx_quic_congestion_t             congestion;
+
     unsigned                          validated:1;
     unsigned                          validating:1;
     unsigned                          limited:1;
@@ -143,14 +176,6 @@
} ngx_quic_streams_t;


-typedef struct {
-    size_t                            in_flight;
-    size_t                            window;
-    size_t                            ssthresh;
-    ngx_msec_t                        recovery_start;
-} ngx_quic_congestion_t;
-
-
/*
  * RFC 9000, 12.3.  Packet Numbers
  *
@@ -218,12 +243,6 @@
     ngx_event_t                       path_validation;
     ngx_msec_t                        last_cc;

-    ngx_msec_t                        first_rtt;
-    ngx_msec_t                        latest_rtt;
-    ngx_msec_t                        avg_rtt;
-    ngx_msec_t                        min_rtt;
-    ngx_msec_t                        rttvar;
-
     ngx_uint_t                        pto_count;

     ngx_queue_t                       free_frames;
@@ -237,7 +256,6 @@
#endif

     ngx_quic_streams_t                streams;
-    ngx_quic_congestion_t             congestion;

     off_t                             received;

@@ -273,4 +291,8 @@
#define ngx_quic_connstate_dbg(c)
#endif

+
+extern ngx_quic_congestion_ops_t  ngx_quic_reno;
+
+
#endif /* _NGX_EVENT_QUIC_CONNECTION_H_INCLUDED_ */
diff -r 1a320805265d -r 9a47ff1223bb src/event/quic/ngx_event_quic_migration.c
--- a/src/event/quic/ngx_event_quic_migration.c  Sat Nov 19 00:31:55 2022 +0800
+++ b/src/event/quic/ngx_event_quic_migration.c  Tue Dec 06 19:27:11 2022 +0800
@@ -135,17 +135,17 @@
         {
             /* address did not change */
             rst = 0;
+
+            ngx_memcpy(&path->congestion, &prev->congestion,
+                       sizeof(ngx_quic_congestion_t));
         }
     }

     if (rst) {
-        ngx_memzero(&qc->congestion, sizeof(ngx_quic_congestion_t));
+        ngx_memzero(&path->congestion, sizeof(ngx_quic_congestion_t));

-        qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size,
-                                   ngx_max(2 * qc->tp.max_udp_payload_size,
-                                           14720));
-        qc->congestion.ssthresh = (size_t) -1;
-        qc->congestion.recovery_start = ngx_current_msec;
+        path->congestion.cc_ops = &ngx_quic_reno;
+        path->congestion.cc_ops->init(c, &path->congestion);
     }

     /*
@@ -217,6 +217,18 @@
     path->addr_text.len = ngx_sock_ntop(sockaddr, socklen, path->text,
                                         NGX_SOCKADDR_STRLEN, 1);

+    path->avg_rtt = NGX_QUIC_INITIAL_RTT;
+    path->rttvar = NGX_QUIC_INITIAL_RTT / 2;
+    path->min_rtt = NGX_TIMER_INFINITE;
+    path->first_rtt = NGX_TIMER_INFINITE;
+
+    /*
+     * path->latest_rtt = 0
+     */
+
+    path->congestion.cc_ops = &ngx_quic_reno;
+    path->congestion.cc_ops->init(c, &path->congestion);
+
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "quic path seq:%uL created addr:%V",
                    path->seqnum, &path->addr_text);
diff -r 1a320805265d -r 9a47ff1223bb src/event/quic/ngx_event_quic_output.c
--- a/src/event/quic/ngx_event_quic_output.c     Sat Nov 19 00:31:55 2022 +0800
+++ b/src/event/quic/ngx_event_quic_output.c     Tue Dec 06 19:27:11 2022 +0800
@@ -87,7 +87,7 @@
     c->log->action = "sending frames";

     qc = ngx_quic_get_connection(c);
-    cg = &qc->congestion;
+    cg = &qc->path->congestion;

     in_flight = cg->in_flight;

@@ -135,7 +135,7 @@
     static u_char           dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];

     qc = ngx_quic_get_connection(c);
-    cg = &qc->congestion;
+    cg = &qc->path->congestion;
     path = qc->path;

     while (cg->in_flight < cg->window) {
@@ -223,7 +223,7 @@

     qc = ngx_quic_get_connection(c);

-    cg = &qc->congestion;
+    cg = &qc->path->congestion;

     while (!ngx_queue_empty(&ctx->sending)) {

@@ -336,7 +336,7 @@
     static u_char           dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF];

     qc = ngx_quic_get_connection(c);
-    cg = &qc->congestion;
+    cg = &qc->path->congestion;
     path = qc->path;

     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);



/* ----------------------------QUIC-TEST---------------------------------*/
/* h3_absolute_redirect.t */
$ TEST_NGINX_LEAVE=1 TEST_NGINX_BINARY=/data/nginx-quic/objs/nginx prove h3_absolute_redirect.t  -v
h3_absolute_redirect.t ..
1..25
ok 1 - directory
ok 2 - directory alias
ok 3 - directory escaped
ok 4 - directory escaped args
ok 5 - auto
ok 6 - auto args
ok 7 - auto escaped
ok 8 - auto escaped args
ok 9 - return
ok 10 - server_name_in_redirect on
ok 11 - server_name_in_redirect off - using host
ok 12 - invalid host - using local sockaddr
ok 13 - port_in_redirect off
ok 14 - off directory
ok 15 - off directory alias
ok 16 - off directory escaped
ok 17 - off directory escaped args
ok 18 - off auto
ok 19 - off auto args
ok 20 - auto escaped
ok 21 - auto escaped args
ok 22 - off return
ok 23 - auto escaped strict
ok 24 - no alerts
ok 25 - no sanitizer errors
ok
All tests successful.
Files=1, Tests=25,  1 wallclock secs ( 0.01 usr  0.00 sys +  0.37 cusr  0.03 csys =  0.41 CPU)
Result: PASS

/* h3_headers.t */
$ TEST_NGINX_LEAVE=1 TEST_NGINX_BINARY=/data/nginx-quic/objs/nginx prove h3_headers.t  -v
h3_headers.t ..
1..68
ok 1 - indexed
ok 2 - indexed dynamic
ok 3 - indexed dynamic huffman
ok 4 - indexed dynamic previous
ok 5 - indexed reference
ok 6 - indexed reference dynamic
ok 7 - indexed reference huffman
ok 8 - post-base index
ok 9 - reference
ok 10 - reference huffman
ok 11 - reference never indexed
ok 12 - reference dynamic
ok 13 - base-base ref
ok 14 - post-base ref huffman
ok 15 - post-base ref never indexed
ok 16 - literal
ok 17 - literal huffman
ok 18 - literal never indexed
ok 19 - rare chars
ok 20 - rare chars - no huffman encoding
ok 21 - well known chars
ok 22 - well known chars - huffman encoding
ok 23 - all chars
ok 24 - all chars - huffman encoding
ok 25 - capacity insert
ok 26 - capacity replace
ok 27 - capacity eviction
ok 28 - capacity invalid
ok 29 - multiple request header fields - cookie
ok 30 - multiple request header fields - cookie 2
ok 31 - multiple request header fields - semi-colon
ok 32 - multiple request header fields proxied - semi-colon
ok 33 - multiple request header fields proxied - dublicate cookie
ok 34 - multiple request header fields proxied - cookie 1
ok 35 - multiple request header fields proxied - cookie 2
ok 36 - multiple response header fields - cookie
ok 37 - multiple response header fields - cookie 2
ok 38 - multiple response header proxied - cookie
ok 39 - multiple response header proxied - cookie 2
ok 40 - multiple response header proxied - upstream cookie
ok 41 - multiple response header proxied - upstream cookie 2
ok 42 - field name size less
ok 43 - field name size equal
ok 44 - field name size greater
ok 45 - field value size less
ok 46 - field value size equal
ok 47 - field value size greater
ok 48 - header size less
ok 49 - header size equal
ok 50 - header size greater
ok 51 - header size indexed
ok 52 - header size indexed greater
not ok 53 # TODO & SKIP not yet
not ok 54 # TODO & SKIP not yet
not ok 55 # TODO & SKIP not yet
ok 56 - after invalid header name
not ok 57 # TODO & SKIP not yet
not ok 58 # TODO & SKIP not yet
not ok 59 # TODO & SKIP not yet
not ok 60 # TODO & SKIP not yet
ok 61 - underscore in header name - underscores_in_headers
ok 62 - underscore in header name - ignore_invalid_headers
ok 63 - incomplete headers
ok 64 - empty authority
ok 65 - invalid path
ok 66 - invalid path control
ok 67 - no alerts
ok 68 - no sanitizer errors
ok
All tests successful.
Files=1, Tests=68,  1 wallclock secs ( 0.03 usr  0.00 sys +  0.48 cusr  0.04 csys =  0.55 CPU)
Result: PASS

--
Yu Zhu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20221206/9839f93a/attachment.htm>


More information about the nginx-devel mailing list