#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RetransmissionTimeOutData
{
smoothed_round_trip_time: MillisecondDuration,
round_trip_time_variance: MillisecondDuration,
retransmission_time_out: MillisecondDuration,
number_of_retransmissions: u8,
back_off_scalars: &'static [u64; RetransmissionTimeOutData::MaximumNumberOfRetransmissions],
}
static NonSynchronizedStateBackOffScalars: [u64; RetransmissionTimeOutData::MaximumNumberOfRetransmissions] =
[
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0
];
static AllOtherStatesBackOffScalars: [u64; RetransmissionTimeOutData::MaximumNumberOfRetransmissions] =
[
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0
];
impl RetransmissionTimeOutData
{
const MaximumNumberOfRetransmissions: usize = 12;
const ExclusiveMaximumNumberOfTransmissionsBeforeResetingMeasurementOfRoundTripTime: usize = Self::MaximumNumberOfRetransmissions / 4;
const ClockGranularity: MillisecondDuration = MillisecondDuration::from_milliseconds(Tick::MillisecondsPerTick);
const MinimumRetransmissionTimeOut: MillisecondDuration = MillisecondDuration::from_milliseconds(256);
const MaximumRetransmissionTimeOut: MillisecondDuration = MillisecondDuration::OneMinute;
pub const InitialSmoothedRoundTripTime: MillisecondDuration = MillisecondDuration(Self::MinimumRetransmissionTimeOut.0 / 3);
pub const InitialRoundTripTimeVariance: MillisecondDuration = MillisecondDuration(Self::InitialSmoothedRoundTripTime.0 / 2);
const ReInitializeRetransmissionTimeOut: MillisecondDuration = MillisecondDuration((Self::MinimumRetransmissionTimeOut.0) * 3);
#[inline(always)]
pub fn new(smoothed_round_trip_time: MillisecondDuration, round_trip_time_variance: MillisecondDuration, is_for_non_synchronized_state: bool) -> Self
{
Self
{
smoothed_round_trip_time,
round_trip_time_variance,
retransmission_time_out: Self::compute_retransmission_time_out(smoothed_round_trip_time, round_trip_time_variance),
number_of_retransmissions: 0,
back_off_scalars: if is_for_non_synchronized_state
{
&NonSynchronizedStateBackOffScalars
}
else
{
&AllOtherStatesBackOffScalars
}
}
}
#[inline(always)]
pub fn retransmission_time_out(&self) -> MillisecondDuration
{
self.retransmission_time_out
}
#[inline(always)]
pub fn increment_retransmissions(&mut self) -> Option<u8>
{
let number_of_retransmissions = self.number_of_retransmissions;
if number_of_retransmissions >= Self::MaximumNumberOfRetransmissions as u8
{
return None
}
let back_off_scalar = unsafe { * self.back_off_scalars.get_unchecked(number_of_retransmissions as usize) };
let unclamped_retransmission_time_out = self.retransmission_time_out << back_off_scalar;
self.retransmission_time_out = if unclamped_retransmission_time_out < Self::MinimumRetransmissionTimeOut
{
Self::MinimumRetransmissionTimeOut
}
else if unclamped_retransmission_time_out > Self::MaximumRetransmissionTimeOut
{
Self::MaximumRetransmissionTimeOut
}
else
{
unclamped_retransmission_time_out
};
self.number_of_retransmissions += 1;
Some(number_of_retransmissions)
}
#[inline(always)]
pub fn reset_retransmissions(&mut self)
{
self.number_of_retransmissions = 0
}
#[inline(always)]
pub fn reset_after_establishment_of_state_if_we_sent_the_first_synchronize_segment_and_the_timer_expired(&mut self)
{
if self.number_of_retransmissions != 0
{
self.retransmission_time_out = Self::ReInitializeRetransmissionTimeOut;
self.number_of_retransmissions = 0
}
}
#[inline(always)]
pub fn entering_established_state(&mut self)
{
if self.retransmission_time_out() < Self::ReInitializeRetransmissionTimeOut
{
self.retransmission_time_out = Self::ReInitializeRetransmissionTimeOut;
}
self.back_off_scalars = &AllOtherStatesBackOffScalars;
self.number_of_retransmissions = 0;
}
#[inline(always)]
pub fn process_measurement_of_round_trip_time(&mut self, measurement_of_round_trip_time: MillisecondDuration)
{
self.number_of_retransmissions = 0;
if unlikely!(measurement_of_round_trip_time.is_zero())
{
return
}
if self.round_trip_time_measurements_are_bogus()
{
self.first_measurement_of_round_trip_time_made(measurement_of_round_trip_time);
}
else
{
self.subsequent_measurement_of_round_trip_time(measurement_of_round_trip_time);
}
}
#[inline(always)]
pub fn smoothed_round_trip_time_and_round_trip_time_variance(&self) -> (MillisecondDuration, MillisecondDuration)
{
if self.round_trip_time_measurements_are_bogus()
{
(Self::InitialSmoothedRoundTripTime, Self::InitialRoundTripTimeVariance)
}
else
{
(self.smoothed_round_trip_time, self.round_trip_time_variance)
}
}
#[inline(always)]
fn round_trip_time_measurements_are_bogus(&self) -> bool
{
self.number_of_retransmissions > (Self::ExclusiveMaximumNumberOfTransmissionsBeforeResetingMeasurementOfRoundTripTime as u8) || (self.smoothed_round_trip_time == Self::InitialSmoothedRoundTripTime && self.round_trip_time_variance == Self::InitialRoundTripTimeVariance)
}
#[inline(always)]
#[allow(non_snake_case)]
fn first_measurement_of_round_trip_time_made(&mut self, measurement_of_round_trip_time: MillisecondDuration)
{
let R = measurement_of_round_trip_time;
self.smoothed_round_trip_time = R;
self.round_trip_time_variance = R / 2;
self.recompute_retransmission_time_out();
}
#[inline(always)]
#[allow(non_snake_case)]
fn subsequent_measurement_of_round_trip_time(&mut self, measurement_of_round_trip_time: MillisecondDuration)
{
let Rdash = measurement_of_round_trip_time;
self.round_trip_time_variance = (self.round_trip_time_variance * 3 + self.smoothed_round_trip_time.absolute_difference(Rdash)) / 4;
self.smoothed_round_trip_time = (self.smoothed_round_trip_time * 7 + Rdash) / 8;
self.recompute_retransmission_time_out();
}
#[inline(always)]
fn recompute_retransmission_time_out(&mut self)
{
self.retransmission_time_out = Self::compute_retransmission_time_out(self.smoothed_round_trip_time, self.round_trip_time_variance);
}
#[inline(always)]
fn compute_retransmission_time_out(smoothed_round_trip_time: MillisecondDuration, round_trip_time_variance: MillisecondDuration) -> MillisecondDuration
{
const G: MillisecondDuration = RetransmissionTimeOutData::ClockGranularity;
const K: u64 = 4;
smoothed_round_trip_time + max(G, round_trip_time_variance * K)
}
}