noq_proto/connection/
ack_frequency.rs

1use crate::Duration;
2use crate::frame::AckFrequency;
3use crate::transport_parameters::TransportParameters;
4use crate::{AckFrequencyConfig, TIMER_GRANULARITY, TransportError, VarInt};
5
6use super::PathId;
7
8/// State associated to ACK frequency
9pub(super) struct AckFrequencyState {
10    //
11    // Sending ACK_FREQUENCY frames
12    //
13    /// The path ID, packet number and value of the in-flight ACK_FREQUENCY frame
14    in_flight_ack_frequency_frame: Option<(PathId, u64, Duration)>,
15    next_outgoing_sequence_number: VarInt,
16    pub(super) peer_max_ack_delay: Duration,
17
18    //
19    // Receiving ACK_FREQUENCY frames
20    //
21    /// The sequence number of the most recently received ACK_FREQUENCY frame
22    last_ack_frequency_frame: Option<u64>,
23    pub(super) max_ack_delay: Duration,
24}
25
26impl AckFrequencyState {
27    pub(super) fn new(default_max_ack_delay: Duration) -> Self {
28        Self {
29            in_flight_ack_frequency_frame: None,
30            next_outgoing_sequence_number: VarInt(0),
31            peer_max_ack_delay: default_max_ack_delay,
32
33            last_ack_frequency_frame: None,
34            max_ack_delay: default_max_ack_delay,
35        }
36    }
37
38    /// Returns the `max_ack_delay` that should be requested of the peer when sending an
39    /// ACK_FREQUENCY frame
40    pub(super) fn candidate_max_ack_delay(
41        &self,
42        rtt: Duration,
43        config: &AckFrequencyConfig,
44        peer_params: &TransportParameters,
45    ) -> Duration {
46        // Use the peer's max_ack_delay if no custom max_ack_delay was provided in the config
47        let min_ack_delay =
48            Duration::from_micros(peer_params.min_ack_delay.map_or(0, |x| x.into()));
49        config
50            .max_ack_delay
51            .unwrap_or(self.peer_max_ack_delay)
52            .clamp(min_ack_delay, rtt.max(MIN_AUTOMATIC_ACK_DELAY))
53    }
54
55    /// Returns the `max_ack_delay` for the purposes of calculating the PTO
56    ///
57    /// This `max_ack_delay` is defined as the maximum of the peer's current `max_ack_delay` and all
58    /// in-flight `max_ack_delay`s (i.e. proposed values that haven't been acknowledged yet, but
59    /// might be already in use by the peer).
60    pub(super) fn max_ack_delay_for_pto(&self) -> Duration {
61        // Note: we have at most one in-flight ACK_FREQUENCY frame
62        if let Some((_, _, max_ack_delay)) = self.in_flight_ack_frequency_frame {
63            self.peer_max_ack_delay.max(max_ack_delay)
64        } else {
65            self.peer_max_ack_delay
66        }
67    }
68
69    /// Returns the next sequence number for an ACK_FREQUENCY frame
70    pub(super) fn next_sequence_number(&mut self) -> VarInt {
71        assert!(self.next_outgoing_sequence_number <= VarInt::MAX);
72
73        let seq = self.next_outgoing_sequence_number;
74        self.next_outgoing_sequence_number.0 += 1;
75        seq
76    }
77
78    /// Returns true if we should send an ACK_FREQUENCY frame
79    pub(super) fn should_send_ack_frequency(
80        &self,
81        rtt: Duration,
82        config: &AckFrequencyConfig,
83        peer_params: &TransportParameters,
84    ) -> bool {
85        if self.next_outgoing_sequence_number.0 == 0 {
86            // Always send at startup
87            return true;
88        }
89        let current = self
90            .in_flight_ack_frequency_frame
91            .map_or(self.peer_max_ack_delay, |(_, _, pending)| pending);
92        let desired = self.candidate_max_ack_delay(rtt, config, peer_params);
93        let error = (desired.as_secs_f32() / current.as_secs_f32()) - 1.0;
94        error.abs() > MAX_RTT_ERROR
95    }
96
97    /// Notifies the [`AckFrequencyState`] that a packet containing an ACK_FREQUENCY frame was sent
98    pub(super) fn ack_frequency_sent(
99        &mut self,
100        path_id: PathId,
101        pn: u64,
102        requested_max_ack_delay: Duration,
103    ) {
104        self.in_flight_ack_frequency_frame = Some((path_id, pn, requested_max_ack_delay));
105    }
106
107    /// Notifies the [`AckFrequencyState`] that a packet has been ACKed
108    pub(super) fn on_acked(&mut self, path_id: PathId, pn: u64) {
109        match self.in_flight_ack_frequency_frame {
110            Some((path, number, requested_max_ack_delay)) if path == path_id && number == pn => {
111                self.in_flight_ack_frequency_frame = None;
112                self.peer_max_ack_delay = requested_max_ack_delay;
113            }
114            _ => {}
115        }
116    }
117
118    /// Notifies the [`AckFrequencyState`] that an ACK_FREQUENCY frame was received
119    ///
120    /// Updates the endpoint's params according to the payload of the ACK_FREQUENCY frame, or
121    /// returns an error in case the requested `max_ack_delay` is invalid.
122    ///
123    /// Returns `true` if the frame was processed and `false` if it was ignored because of being
124    /// stale.
125    pub(super) fn ack_frequency_received(
126        &mut self,
127        frame: &AckFrequency,
128    ) -> Result<bool, TransportError> {
129        if self
130            .last_ack_frequency_frame
131            .is_some_and(|highest_sequence_nr| frame.sequence.into_inner() <= highest_sequence_nr)
132        {
133            return Ok(false);
134        }
135
136        self.last_ack_frequency_frame = Some(frame.sequence.into_inner());
137
138        // Update max_ack_delay
139        let max_ack_delay = Duration::from_micros(frame.request_max_ack_delay.into_inner());
140        if max_ack_delay < TIMER_GRANULARITY {
141            return Err(TransportError::PROTOCOL_VIOLATION(
142                "Requested Max Ack Delay in ACK_FREQUENCY frame is less than min_ack_delay",
143            ));
144        }
145        self.max_ack_delay = max_ack_delay;
146
147        Ok(true)
148    }
149}
150
151/// Maximum proportion difference between the most recently requested max ACK delay and the
152/// currently desired one before a new request is sent, when the peer supports the ACK frequency
153/// extension and an explicit max ACK delay is not configured.
154const MAX_RTT_ERROR: f32 = 0.2;
155
156/// Minimum value to request the peer set max ACK delay to when the peer supports the ACK frequency
157/// extension and an explicit max ACK delay is not configured.
158// Keep in sync with `AckFrequencyConfig::max_ack_delay` documentation
159const MIN_AUTOMATIC_ACK_DELAY: Duration = Duration::from_millis(25);