From 374d7373f9d630392c4980ef3b1213b0f457146f Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Thu, 25 Dec 2025 22:26:25 +0900 Subject: [PATCH 1/4] perf: avoid sending a redundant max-size probe when restarting PMTUD --- quiche/src/pmtud.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/quiche/src/pmtud.rs b/quiche/src/pmtud.rs index 6fa645028e..90acfc99c7 100644 --- a/quiche/src/pmtud.rs +++ b/quiche/src/pmtud.rs @@ -87,7 +87,14 @@ impl Pmtud { successful_probe_size: {successful_probe_size}", ); - return self.restart_pmtud(); + self.restart_pmtud(); + + // Record the failed probe again after restarting PMTUD + // to ensure the next probe size is reduced (binary search down) + // instead of resetting to the maximum MTU. + self.failed_probe(failed_probe_size); + + return; } // Found the PMTU @@ -367,6 +374,24 @@ mod tests { pmtud_test_runner(&mut pmtud, 1250); } + /// Test case for changing network conditions during PMTUD. + /// + /// This test simulates a scenario where network conditions change + /// during the PMTUD process, causing inconsistent probe results. + #[test] + fn test_pmtud_changing_network_conditions() { + let mut pmtud = Pmtud::new(1500); + + // Simulate a successful probe + pmtud.successful_probe(1400); + + // Simulate a failed probe that is less than the last successful probe + pmtud.failed_probe(1300); + + // Run the PMTUD test runner to verify handling of inconsistent results + pmtud_test_runner(&mut pmtud, 1250); + } + /// Runs a test for the PMTUD algorithm, given a target PMTU `target_mtu`. /// /// The test iteratively sends probes until the PMTU is found or the minimum From 9c2100a215abcc750293c7bae2f0dd6a5ace7ac2 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Thu, 25 Dec 2025 22:43:27 +0900 Subject: [PATCH 2/4] test: improve pmtud::tests::test_pmtud_changing_network_conditions --- quiche/src/pmtud.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/quiche/src/pmtud.rs b/quiche/src/pmtud.rs index 90acfc99c7..3a88abfd32 100644 --- a/quiche/src/pmtud.rs +++ b/quiche/src/pmtud.rs @@ -388,6 +388,12 @@ mod tests { // Simulate a failed probe that is less than the last successful probe pmtud.failed_probe(1300); + // The largest successful probe should be reset after restarting PMTUD + assert_eq!(pmtud.largest_successful_probe_size, None); + + // The smallest failed probe should be recorded again after restarting PMTUD + assert_eq!(pmtud.smallest_failed_probe_size, Some(1300)); + // Run the PMTUD test runner to verify handling of inconsistent results pmtud_test_runner(&mut pmtud, 1250); } From 980a2fe56939b9f823c1af848478aa06992d3b0d Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Thu, 25 Dec 2025 22:46:26 +0900 Subject: [PATCH 3/4] refactor: explain safety of the intentional recursive call --- quiche/src/pmtud.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/quiche/src/pmtud.rs b/quiche/src/pmtud.rs index 3a88abfd32..fdfac517e0 100644 --- a/quiche/src/pmtud.rs +++ b/quiche/src/pmtud.rs @@ -92,6 +92,13 @@ impl Pmtud { // Record the failed probe again after restarting PMTUD // to ensure the next probe size is reduced (binary search down) // instead of resetting to the maximum MTU. + // + // NOTE: `failed_probe()` internally calls `update_probe_size()`, + // so this is an intentional and bounded recursive call. After + // `restart_pmtud()` the state is reset, and re-recording the + // failed probe brings the PMTUD state back into a consistent + // configuration for the next probe without causing unbounded + // recursion. self.failed_probe(failed_probe_size); return; From b597908f10db0aaa4aaabc750c2095e84c97a076 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Wed, 21 Jan 2026 01:10:01 +0900 Subject: [PATCH 4/4] style: rustfmt --- quiche/src/pmtud.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/quiche/src/pmtud.rs b/quiche/src/pmtud.rs index fdfac517e0..f7beb2b08c 100644 --- a/quiche/src/pmtud.rs +++ b/quiche/src/pmtud.rs @@ -89,16 +89,16 @@ impl Pmtud { self.restart_pmtud(); - // Record the failed probe again after restarting PMTUD - // to ensure the next probe size is reduced (binary search down) + // Record the failed probe again after restarting PMTUD to + // ensure the next probe size is reduced (binary search down) // instead of resetting to the maximum MTU. // - // NOTE: `failed_probe()` internally calls `update_probe_size()`, - // so this is an intentional and bounded recursive call. After - // `restart_pmtud()` the state is reset, and re-recording the - // failed probe brings the PMTUD state back into a consistent - // configuration for the next probe without causing unbounded - // recursion. + // NOTE: `failed_probe()` internally calls + // `update_probe_size()`, so this is an intentional and + // bounded recursive call. After `restart_pmtud()` the state + // is reset, and re-recording the failed probe brings the + // PMTUD state back into a consistent configuration for the + // next probe without causing unbounded recursion. self.failed_probe(failed_probe_size); return; @@ -398,7 +398,7 @@ mod tests { // The largest successful probe should be reset after restarting PMTUD assert_eq!(pmtud.largest_successful_probe_size, None); - // The smallest failed probe should be recorded again after restarting PMTUD + // The smallest failed probe should be recorded again assert_eq!(pmtud.smallest_failed_probe_size, Some(1300)); // Run the PMTUD test runner to verify handling of inconsistent results