]> git.kaiwu.me - nginx.git/commitdiff
QUIC: fixed unsent MTU probe acknowledgement.
authorRoman Arutyunyan <arut@nginx.com>
Wed, 14 Feb 2024 12:56:28 +0000 (16:56 +0400)
committerRoman Arutyunyan <arut@nginx.com>
Wed, 14 Feb 2024 12:56:28 +0000 (16:56 +0400)
Previously if an MTU probe send failed early in ngx_quic_frame_sendto()
due to allocation error or congestion control, the application level packet
number was not increased, but was still saved as MTU probe packet number.
Later when a packet with this number was acknowledged, the unsent MTU probe
was acknowledged as well.  This could result in discovering a bigger MTU than
supported by the path, which could lead to EMSGSIZE (Message too long) errors
while sending further packets.

The problem existed since PMTUD was introduced in 58afcd72446f (1.25.2).
Back then only the unlikely memory allocation error could trigger it.  However
in efcdaa66df2e congestion control was added to ngx_quic_frame_sendto() which
can now trigger the issue with a higher probability.

src/event/quic/ngx_event_quic_migration.c

index 3c1bbaf43f02528bc33e6bf23ea625b21ea6191d..2d1467e1493f97d5950ab92a26e6f1e6334238da 100644 (file)
@@ -909,6 +909,7 @@ static ngx_int_t
 ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
 {
     size_t                  mtu;
+    uint64_t                pnum;
     ngx_int_t               rc;
     ngx_uint_t              log_error;
     ngx_quic_frame_t       *frame;
@@ -925,7 +926,7 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
 
     qc = ngx_quic_get_connection(c);
     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
-    path->mtu_pnum[path->tries] = ctx->pnum;
+    pnum = ctx->pnum;
 
     ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "quic path seq:%uL send probe "
@@ -943,14 +944,18 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
     path->mtu = mtu;
     c->log_error = log_error;
 
+    if (rc == NGX_OK) {
+        path->mtu_pnum[path->tries] = pnum;
+        return NGX_OK;
+    }
+
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "quic path seq:%uL rejected mtu:%uz",
+                   path->seqnum, path->mtud);
+
     if (rc == NGX_ERROR) {
         if (c->write->error) {
             c->write->error = 0;
-
-            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                           "quic path seq:%uL rejected mtu:%uz",
-                           path->seqnum, path->mtud);
-
             return NGX_DECLINED;
         }
 
@@ -976,7 +981,7 @@ ngx_quic_handle_path_mtu(ngx_connection_t *c, ngx_quic_path_t *path,
         pnum = path->mtu_pnum[i];
 
         if (pnum == NGX_QUIC_UNSET_PN) {
-            break;
+            continue;
         }
 
         if (pnum < min || pnum > max) {