Skip to main content

tokio_fast_udp/
ecn.rs

1/// Explicit Congestion Notification codepoint.
2///
3/// Represents the 2-bit ECN field in the IP header (ToS for IPv4, Traffic
4/// Class for IPv6).
5///
6/// See [RFC 9331](https://datatracker.ietf.org/doc/rfc9331/) for the use of
7/// ECN with QUIC and [RFC 3168](https://datatracker.ietf.org/doc/rfc3168/)
8/// for the original specification.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum Ecn {
11    /// Not ECN-Capable Transport — routers may drop the packet on congestion.
12    NotEct,
13    /// ECN-Capable Transport, codepoint 1.
14    Ect1,
15    /// ECN-Capable Transport, codepoint 0.
16    Ect0,
17    /// Congestion Experienced — set by a router on an ECT-marked packet.
18    Ce,
19}
20
21impl Ecn {
22    /// Encode the ECN codepoint as the low 2 bits of a TOS/Traffic Class byte.
23    pub fn to_tos_bits(self) -> u8 {
24        match self {
25            Ecn::NotEct => 0b00,
26            Ecn::Ect1 => 0b01,
27            Ecn::Ect0 => 0b10,
28            Ecn::Ce => 0b11,
29        }
30    }
31
32    /// Decode the ECN codepoint from the low 2 bits of a TOS/Traffic Class byte.
33    pub fn from_tos_bits(tos: u8) -> Self {
34        match tos & 0b11 {
35            0b00 => Ecn::NotEct,
36            0b01 => Ecn::Ect1,
37            0b10 => Ecn::Ect0,
38            _ => Ecn::Ce,
39        }
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_round_trip() {
49        for ecn in [Ecn::NotEct, Ecn::Ect1, Ecn::Ect0, Ecn::Ce] {
50            assert_eq!(Ecn::from_tos_bits(ecn.to_tos_bits()), ecn);
51        }
52    }
53
54    #[test]
55    fn test_masks_high_bits() {
56        assert_eq!(Ecn::from_tos_bits(0b1010), Ecn::Ect0);
57        assert_eq!(Ecn::from_tos_bits(0b1111), Ecn::Ce);
58    }
59}