[PATCH 1 of 3] QUIC: changed path validation timeout

Roman Arutyunyan arut at nginx.com
Tue Mar 28 14:51:38 UTC 2023


# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1679925333 -14400
#      Mon Mar 27 17:55:33 2023 +0400
# Branch quic
# Node ID f76e83412133085a6c82fce2c3e15b2c34a6e959
# Parent  5fd628b89bb7fb5c95afa1dc914385f7ab79f6a3
QUIC: changed path validation timeout.

Path validation packets containing PATH_CHALLENGE frames are sent separately
from regular frame queue, because of the need to use a decicated path and
pad the packets.  The packets are also resent separately from the regular
probe/lost detection mechanism.  A path validation packet is resent 3 times,
each time after PTO expiration.  Assuming constant PTO, the overall maximum
waiting time is 3 * PTO.  According to RFC 9000, 8.2.4. Failed Path Validation,
the following value is recommended as a validation timeout:

  A value of three times the larger of the current PTO
  or the PTO for the new path (using kInitialRtt, as
  defined in [QUIC-RECOVERY]) is RECOMMENDED.

The change adds PTO of the new path to the equation as the lower bound.
Also, max_ack_delay is now always accounted for, unlike previously, when
it was only used when there are packets in flight.  As mentioned before,
PACH_CHALLENGE is not considered in-flight by nginx since it's processed
separately, but technically it is.

diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c
--- a/src/event/quic/ngx_event_quic_migration.c
+++ b/src/event/quic/ngx_event_quic_migration.c
@@ -14,6 +14,7 @@ static void ngx_quic_set_connection_path
     ngx_quic_path_t *path);
 static ngx_int_t ngx_quic_validate_path(ngx_connection_t *c,
     ngx_quic_path_t *path);
+static ngx_msec_t ngx_quic_path_pto(ngx_connection_t *c);
 static ngx_int_t ngx_quic_send_path_challenge(ngx_connection_t *c,
     ngx_quic_path_t *path);
 static ngx_quic_path_t *ngx_quic_get_path(ngx_connection_t *c, ngx_uint_t tag);
@@ -487,7 +488,6 @@ static ngx_int_t
 ngx_quic_validate_path(ngx_connection_t *c, ngx_quic_path_t *path)
 {
     ngx_msec_t              pto;
-    ngx_quic_send_ctx_t    *ctx;
     ngx_quic_connection_t  *qc;
 
     qc = ngx_quic_get_connection(c);
@@ -509,8 +509,7 @@ ngx_quic_validate_path(ngx_connection_t 
         return NGX_ERROR;
     }
 
-    ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
-    pto = ngx_quic_pto(c, ctx);
+    pto = ngx_quic_path_pto(c);
 
     path->expires = ngx_current_msec + pto;
     path->tries = NGX_QUIC_PATH_RETRIES;
@@ -523,6 +522,33 @@ ngx_quic_validate_path(ngx_connection_t 
 }
 
 
+static ngx_msec_t
+ngx_quic_path_pto(ngx_connection_t *c)
+{
+
+    ngx_msec_t              duration;
+    ngx_quic_connection_t  *qc;
+
+    /*
+     * RFC 9000, 8.2.4. Failed Path Validation
+     *
+     * A value of three times the larger of the current PTO
+     * or the PTO for the new path (using kInitialRtt, as defined
+     * in [QUIC-RECOVERY]) is RECOMMENDED.
+     */
+
+    qc = ngx_quic_get_connection(c);
+
+    duration = qc->avg_rtt + 4 * qc->rttvar;
+
+    if (duration < 1000) {
+        duration = 1000;
+    }
+
+    return duration + qc->ctp.max_ack_delay;
+}
+
+
 static ngx_int_t
 ngx_quic_send_path_challenge(ngx_connection_t *c, ngx_quic_path_t *path)
 {
@@ -571,14 +597,12 @@ ngx_quic_path_validation_handler(ngx_eve
     ngx_msec_int_t          left, next, pto;
     ngx_quic_path_t        *path, *bkp;
     ngx_connection_t       *c;
-    ngx_quic_send_ctx_t    *ctx;
     ngx_quic_connection_t  *qc;
 
     c = ev->data;
     qc = ngx_quic_get_connection(c);
 
-    ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
-    pto = ngx_quic_pto(c, ctx);
+    pto = ngx_quic_path_pto(c);
 
     next = -1;
     now = ngx_current_msec;


More information about the nginx-devel mailing list