@@ -2016,8 +2016,10 @@ impl Connection {
2016
2016
. expect ( "update not acknowledged yet" )
2017
2017
. 1
2018
2018
} ;
2019
+
2020
+ // QUIC-MULTIPATH § 2.5 Key Phase Update Process: use largest PTO off all paths.
2019
2021
self . timers
2020
- . set ( Timer :: KeyDiscard , start + self . pto ( space) * 3 ) ;
2022
+ . set ( Timer :: KeyDiscard , start + self . pto_max_path ( space) * 3 ) ;
2021
2023
}
2022
2024
2023
2025
/// Handle a [`Timer::LossDetection`] timeout.
@@ -2103,7 +2105,7 @@ impl Connection {
2103
2105
// lost packet, including the edges, are marked lost. PTO computation must always
2104
2106
// include max ACK delay, i.e. operate as if in Data space (see RFC9001 §7.6.1).
2105
2107
let congestion_period =
2106
- self . pto ( SpaceId :: Data ) * self . config . persistent_congestion_threshold ;
2108
+ self . pto ( SpaceId :: Data , path_id ) * self . config . persistent_congestion_threshold ;
2107
2109
let mut persistent_congestion_start: Option < Instant > = None ;
2108
2110
let mut prev_packet = None ;
2109
2111
let mut in_persistent_congestion = false ;
@@ -2368,15 +2370,31 @@ impl Connection {
2368
2370
}
2369
2371
}
2370
2372
2373
+ /// The maximum probe timeout across all paths
2374
+ ///
2375
+ /// See [`Connection::pto`]
2376
+ fn pto_max_path ( & self , space : SpaceId ) -> Duration {
2377
+ match space {
2378
+ SpaceId :: Initial | SpaceId :: Handshake => self . pto ( space, PathId :: ZERO ) ,
2379
+ SpaceId :: Data => self
2380
+ . paths
2381
+ . keys ( )
2382
+ . map ( |path_id| self . pto ( space, * path_id) )
2383
+ . max ( )
2384
+ . expect ( "there should be one at least path" ) ,
2385
+ }
2386
+ }
2387
+
2371
2388
/// Probe Timeout
2372
- // TODO(flub): This needs a PathId parameter
2373
- fn pto ( & self , space : SpaceId ) -> Duration {
2389
+ ///
2390
+ /// The PTO is logically the time in which you'd expect to receive an acknowledgement
2391
+ /// for a packet. So approximately RTT + max_ack_delay.
2392
+ fn pto ( & self , space : SpaceId , path_id : PathId ) -> Duration {
2374
2393
let max_ack_delay = match space {
2375
2394
SpaceId :: Initial | SpaceId :: Handshake => Duration :: ZERO ,
2376
2395
SpaceId :: Data => self . ack_frequency . max_ack_delay_for_pto ( ) ,
2377
2396
} ;
2378
- // TODO(@divma): fix
2379
- self . path_data ( PathId ( 0 ) ) . rtt . pto_base ( ) + max_ack_delay
2397
+ self . path_data ( path_id) . rtt . pto_base ( ) + max_ack_delay
2380
2398
}
2381
2399
2382
2400
fn on_packet_authenticated (
@@ -2429,6 +2447,8 @@ impl Connection {
2429
2447
}
2430
2448
}
2431
2449
2450
+ // TODO(flub): figure out if this should take a PathId. We could use an idle timeout on
2451
+ // each path. We will need to figure out.
2432
2452
fn reset_idle_timeout ( & mut self , now : Instant , space : SpaceId ) {
2433
2453
let timeout = match self . idle_timeout {
2434
2454
None => return ,
@@ -2438,7 +2458,8 @@ impl Connection {
2438
2458
self . timers . stop ( Timer :: Idle ) ;
2439
2459
return ;
2440
2460
}
2441
- let dt = cmp:: max ( timeout, 3 * self . pto ( space) ) ;
2461
+ // TODO(flub): Wrong PathId, see comment above.
2462
+ let dt = cmp:: max ( timeout, 3 * self . pto ( space, PathId :: ZERO ) ) ;
2442
2463
self . timers . set ( Timer :: Idle , now + dt) ;
2443
2464
}
2444
2465
@@ -3755,7 +3776,7 @@ impl Connection {
3755
3776
// Reset rtt/congestion state for new path unless it looks like a NAT rebinding.
3756
3777
// Note that the congestion window will not grow until validation terminates. Helps mitigate
3757
3778
// amplification attacks performed by spoofing source addresses.
3758
- let prev_pto = self . pto ( SpaceId :: Data ) ;
3779
+ let prev_pto = self . pto ( SpaceId :: Data , path_id ) ;
3759
3780
let known_path = self . paths . get_mut ( & path_id) . expect ( "known path" ) ;
3760
3781
let path = & mut known_path. data ;
3761
3782
let mut new_path = if remote. is_ipv4 ( ) && remote. ip ( ) == path. remote . ip ( ) {
@@ -3794,7 +3815,7 @@ impl Connection {
3794
3815
3795
3816
self . timers . set (
3796
3817
Timer :: PathValidation ( path_id) ,
3797
- now + 3 * cmp:: max ( self . pto ( SpaceId :: Data ) , prev_pto) ,
3818
+ now + 3 * cmp:: max ( self . pto ( SpaceId :: Data , path_id ) , prev_pto) ,
3798
3819
) ;
3799
3820
}
3800
3821
@@ -4388,8 +4409,12 @@ impl Connection {
4388
4409
}
4389
4410
4390
4411
fn set_close_timer ( & mut self , now : Instant ) {
4391
- self . timers
4392
- . set ( Timer :: Close , now + 3 * self . pto ( self . highest_space ) ) ;
4412
+ // QUIC-MULTIPATH § 2.6 Connection Closure: draining for 3*PTO with PTO the max of
4413
+ // the PTO for all paths.
4414
+ self . timers . set (
4415
+ Timer :: Close ,
4416
+ now + 3 * self . pto_max_path ( self . highest_space ) ,
4417
+ ) ;
4393
4418
}
4394
4419
4395
4420
/// Handle transport parameters received from the peer
0 commit comments