diff --git a/src/connection/connection.rs b/src/connection/connection.rs index cee0ed8c..08efa977 100644 --- a/src/connection/connection.rs +++ b/src/connection/connection.rs @@ -1786,6 +1786,7 @@ impl Connection { in_flight: write_status.in_flight, has_data: write_status.has_data, pmtu_probe: write_status.is_pmtu_probe, + pacing: write_status.pacing, frames: write_status.frames, rate_sample_state: Default::default(), buffer_flags: write_status.buffer_flags, @@ -1930,6 +1931,7 @@ impl Connection { if !st.is_probe && !r.can_send() { return Err(Error::Done); } + st.pacing = true; // Write PMTU probe frames // Note: To probe the path MTU, the write size will exceed `left` but @@ -4483,6 +4485,9 @@ struct FrameWriteStatus { /// Whether it is a PMTU probe packet is_pmtu_probe: bool, + /// Whether it consumes the pacer's tokens + pacing: bool, + /// Packet overhead (i.e. packet header and crypto overhead) in bytes overhead: usize, diff --git a/src/connection/recovery.rs b/src/connection/recovery.rs index 64ec2bcf..3d5699cd 100644 --- a/src/connection/recovery.rs +++ b/src/connection/recovery.rs @@ -167,6 +167,7 @@ impl Recovery { ) { let in_flight = pkt.in_flight; let ack_eliciting = pkt.ack_eliciting; + let pacing = pkt.pacing; let sent_size = pkt.sent_size; pkt.time_sent = now; @@ -218,7 +219,9 @@ impl Recovery { } // Update pacing tokens number. - self.pacer.on_sent(sent_size as u64); + if pacing { + self.pacer.on_sent(sent_size as u64); + } } /// Handle packet acknowledgment event. @@ -845,8 +848,29 @@ impl Recovery { /// Check whether this path can still send packets. pub(crate) fn can_send(&mut self) -> bool { - self.bytes_in_flight < self.congestion.congestion_window() as usize - && (!self.pacer.enabled() || self.can_pacing()) + // Check congestion controller + if self.bytes_in_flight >= self.congestion.congestion_window() as usize { + trace!( + "{} sending is limited by congestion controller, inflight {}, window {}", + self.trace_id, + self.bytes_in_flight, + self.congestion.congestion_window() + ); + return false; + } + + // Check pacer + if self.pacer.enabled() && !self.can_pacing() { + trace!( + "{} sending is limited by pacer, pacing timer {:?}", + self.trace_id, + self.pacer_timer + .map(|t| t.saturating_duration_since(Instant::now())) + ); + return false; + } + + true } fn can_pacing(&mut self) -> bool { @@ -865,12 +889,7 @@ impl Recovery { ); } - if self.pacer_timer.is_none() { - true - } else { - trace!("{} pacing timer is {:?}", self.trace_id, self.pacer_timer); - false - } + self.pacer_timer.is_none() } /// Update statistics for the packet sent event diff --git a/src/connection/space.rs b/src/connection/space.rs index 6ec9f577..154cc95c 100644 --- a/src/connection/space.rs +++ b/src/connection/space.rs @@ -369,6 +369,9 @@ pub struct SentPacket { /// Whether it is a PMUT probe packet pub pmtu_probe: bool, + /// Whether it consumes the pacer's tokens + pub pacing: bool, + /// The number of bytes sent in the packet, not including UDP or IP overhead, /// but including QUIC framing overhead. pub sent_size: usize, @@ -393,6 +396,7 @@ impl Default for SentPacket { in_flight: false, has_data: false, pmtu_probe: false, + pacing: false, sent_size: 0, rate_sample_state: RateSamplePacketState::default(), buffer_flags: BufferFlags::default(),