@@ -1492,8 +1492,16 @@ impl Connection {
14921492 // we need them in `path_congestion_check`.
14931493 self . path_data_mut ( path_id) . update_pacer ( now) ;
14941494 let congestion_blocked =
1495- self . path_congestion_check ( space_id, path_id, transmit, & can_send, now ) ;
1495+ self . path_congestion_check ( space_id, path_id, transmit, & can_send) ;
14961496 if congestion_blocked != PathBlocked :: No {
1497+ if let PathBlocked :: Pacing ( delay) = congestion_blocked {
1498+ let resume_time = now + delay;
1499+ self . timers . set_if_earlier (
1500+ Timer :: PerPath ( path_id, PathTimer :: Pacing ) ,
1501+ resume_time,
1502+ self . qlog . with_time ( now) ,
1503+ ) ;
1504+ }
14971505 // Previous iterations of this loop may have built packets already.
14981506 return match last_packet_number {
14991507 Some ( pn) => PollPathSpaceStatus :: WrotePacket {
@@ -1882,14 +1890,22 @@ impl Connection {
18821890 false
18831891 }
18841892
1885- /// Checks if creating a new datagram would be blocked by congestion control
1893+ /// Checks if creating a new datagram would be blocked by congestion control or pacing.
1894+ ///
1895+ /// This is a pure function - it doesn't modify state, so neither does it update the pacer
1896+ /// nor does it set the pacing timer. Callers need to handle that:
1897+ ///
1898+ /// - To make new pacing tokens available, the pacer needs to be update before a call to
1899+ /// this function using [`PathData::update_pacer`].
1900+ /// - When this function returns [`PathBlocked::Pacing`], and you decide to actually send
1901+ /// the given packet, call [`TimerTable::set_if_earlier`] with [`PathTimer::Pacing`]
1902+ /// and given delay relative to the time used for `update_pacer`.
18861903 fn path_congestion_check (
18871904 & mut self ,
18881905 space_id : SpaceId ,
18891906 path_id : PathId ,
18901907 transmit : & TransmitBuf < ' _ > ,
18911908 can_send : & SendableFrames ,
1892- now : Instant ,
18931909 ) -> PathBlocked {
18941910 // Anti-amplification is only based on `total_sent`, which gets updated after
18951911 // the transmit is sent. Therefore we pass the amount of bytes for datagrams
@@ -1926,16 +1942,10 @@ impl Connection {
19261942
19271943 // Pacing check.
19281944 if let Some ( delay) = self . path_data ( path_id) . pacing_delay ( bytes_to_send) {
1929- let resume_time = now + delay;
1930- self . timers . set (
1931- Timer :: PerPath ( path_id, PathTimer :: Pacing ) ,
1932- resume_time,
1933- self . qlog . with_time ( now) ,
1934- ) ;
19351945 // Loss probes and CONNECTION_CLOSE should be subject to pacing, even though
19361946 // they are not congestion controlled.
19371947 trace ! ( ?space_id, %path_id, ?delay, "blocked by pacing" ) ;
1938- return PathBlocked :: Pacing ;
1948+ return PathBlocked :: Pacing ( delay ) ;
19391949 }
19401950
19411951 PathBlocked :: No
@@ -7243,7 +7253,7 @@ enum PathBlocked {
72437253 No ,
72447254 AntiAmplification ,
72457255 Congestion ,
7246- Pacing ,
7256+ Pacing ( Duration ) ,
72477257}
72487258
72497259/// Fields of `Connection` specific to it being client-side or server-side
0 commit comments