Skip to content

Instantly share code, notes, and snippets.

@WesleyRosenblum
Last active February 2, 2021 17:53
Show Gist options
  • Save WesleyRosenblum/6e74c9944e3e27405d047bdf669e62c2 to your computer and use it in GitHub Desktop.
Save WesleyRosenblum/6e74c9944e3e27405d047bdf669e62c2 to your computer and use it in GitHub Desktop.
Under utilized
impl CubicCongestionController {
pub fn new(max_datagram_size: u16) -> Self {
Self {
cubic: Cubic::new(max_datagram_size),
slow_start: HybridSlowStart::new(max_datagram_size),
max_datagram_size,
congestion_window: CubicCongestionController::initial_window(max_datagram_size) as f32,
state: SlowStart,
bytes_in_flight: Counter::new(0),
time_of_last_sent_packet: None,
is_under_utilized: true,
}
}
fn on_packet_sent(&mut self, time_sent: Timestamp, bytes_sent: usize) {
self.bytes_in_flight
.try_add(bytes_sent)
.expect("bytes sent should not exceed u32::MAX");
self.is_under_utilized = self.is_congestion_window_under_utilized();
if self.is_under_utilized {
if let CongestionAvoidance(ref mut avoidance_start_time) = self.state {
//= https://tools.ietf.org/rfc/rfc8312#5.8
//# CUBIC does not raise its congestion window size if the flow is
//# currently limited by the application instead of the congestion
//# window. In case of long periods when cwnd has not been updated due
//# to the application rate limit, such as idle periods, t in Eq. 1 MUST
//# NOT include these periods; otherwise, W_cubic(t) might be very high
//# after restarting from these periods.
// Since we are application limited, we shift the start time of CongestionAvoidance
// by the app limited duration, to avoid including that duration in W_cubic(t).
let last_time_sent = self.time_of_last_sent_packet.unwrap_or(time_sent);
// Use the later of the last time sent and the avoidance start time to not count
// the app limited time spent prior to entering congestion avoidance.
let app_limited_duration = time_sent - last_time_sent.max(*avoidance_start_time);
*avoidance_start_time += app_limited_duration;
}
}
if let Recovery(recovery_start_time, RequiresTransmission) = self.state {
// A packet has been sent since we entered recovery (fast retransmission)
// so flip the state back to idle.
self.state = Recovery(recovery_start_time, Idle);
}
self.time_of_last_sent_packet = Some(time_sent);
}
fn on_packet_ack(
&mut self,
largest_acked_time_sent: Timestamp,
sent_bytes: usize,
rtt_estimator: &RTTEstimator,
ack_receive_time: Timestamp,
) {
self.bytes_in_flight
.try_sub(sent_bytes)
.expect("sent bytes should not exceed u32::MAX");
if self.is_under_utilized {
//= https://tools.ietf.org/id/draft-ietf-quic-recovery-32.txt#7.8
//# When bytes in flight is smaller than the congestion window and
//# sending is not pacing limited, the congestion window is under-
//# utilized. When this occurs, the congestion window SHOULD NOT be
//# increased in either slow start or congestion avoidance. This can
//# happen due to insufficient application data or flow control limits.
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment