diff --git a/quinn-proto/src/connection/mod.rs b/quinn-proto/src/connection/mod.rs index 2cd4b00dc..54ef6b736 100644 --- a/quinn-proto/src/connection/mod.rs +++ b/quinn-proto/src/connection/mod.rs @@ -1314,6 +1314,20 @@ impl Connection { self.path.congestion.as_ref() } + /// Resets path-specific settings. + /// + /// This will force-reset several subsystems related to a specific network path. + /// Currently this is the congestion controller, round-trip estimator, and the MTU + /// discovery. + /// + /// This is useful when it is known the underlying network path has changed and the old + /// state of these subsystems is no longer valid or optimal. In this case it might be + /// faster or reduce loss to settle on optimal values by restarting from the initial + /// configuration in the [`TransportConfig`]. + pub fn path_changed(&mut self, now: Instant) { + self.path.reset(now, &self.config); + } + /// Modify the number of remotely initiated streams that may be concurrently open /// /// No streams may be opened by the peer unless fewer than `count` are already open. Large diff --git a/quinn-proto/src/connection/mtud.rs b/quinn-proto/src/connection/mtud.rs index 3fe8dc0b7..88743d57c 100644 --- a/quinn-proto/src/connection/mtud.rs +++ b/quinn-proto/src/connection/mtud.rs @@ -56,6 +56,15 @@ impl MtuDiscovery { } } + pub(super) fn reset(&mut self, current_mtu: u16, min_mtu: u16) { + self.current_mtu = current_mtu; + if let Some(state) = self.state.take() { + self.state = Some(EnabledMtuDiscovery::new(state.config)); + self.on_peer_max_udp_payload_size_received(state.peer_max_udp_payload_size); + } + self.black_hole_detector = BlackHoleDetector::new(min_mtu); + } + /// Returns the current MTU pub(crate) fn current_mtu(&self) -> u16 { self.current_mtu diff --git a/quinn-proto/src/connection/paths.rs b/quinn-proto/src/connection/paths.rs index 5b2bc9b5d..c99875a2e 100644 --- a/quinn-proto/src/connection/paths.rs +++ b/quinn-proto/src/connection/paths.rs @@ -115,6 +115,18 @@ impl PathData { } } + /// Resets RTT, congestion control and MTU states. + /// + /// This is useful when it is known the underlying path has changed. + pub(super) fn reset(&mut self, now: Instant, config: &TransportConfig) { + self.rtt = RttEstimator::new(config.initial_rtt); + self.congestion = config + .congestion_controller_factory + .clone() + .build(now, config.get_initial_mtu()); + self.mtud.reset(config.get_initial_mtu(), config.min_mtu); + } + /// Indicates whether we're a server that hasn't validated the peer's address and hasn't /// received enough data from the peer to permit sending `bytes_to_send` additional bytes pub(super) fn anti_amplification_blocked(&self, bytes_to_send: u64) -> bool {