Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/neqo-common/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  tos.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::Debug;

use enum_map::Enum;

/// ECN (Explicit Congestion Notification) codepoints mapped to the
/// lower 2 bits of the TOS field.
/// <https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml>
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
#[repr(u8)]
pub enum IpTosEcn {
    #[default]
    /// Not-ECT, Not ECN-Capable Transport, RFC3168
    NotEct = 0b00,

    /// ECT(1), ECN-Capable Transport(1), RFC8311 and RFC9331
    Ect1 = 0b01,

    /// ECT(0), ECN-Capable Transport(0), RFC3168
    Ect0 = 0b10,

    /// CE, Congestion Experienced, RFC3168
    Ce = 0b11,
}

impl From<IpTosEcn> for u8 {
    fn from(v: IpTosEcn) -> Self {
        v as Self
    }
}

impl From<u8> for IpTosEcn {
    fn from(v: u8) -> Self {
        match v & 0b0000_0011 {
            0b00 => Self::NotEct,
            0b01 => Self::Ect1,
            0b10 => Self::Ect0,
            0b11 => Self::Ce,
            _ => unreachable!(),
        }
    }
}

impl From<IpTos> for IpTosEcn {
    fn from(v: IpTos) -> Self {
        Self::from(u8::from(v))
    }
}

impl IpTosEcn {
    #[must_use]
    pub const fn is_ecn_marked(&self) -> bool {
        match self {
            Self::Ect0 | Self::Ect1 | Self::Ce => true,
            Self::NotEct => false,
        }
    }
}

/// Diffserv Codepoints, mapped to the upper six bits of the TOS field.
/// <https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml>
#[derive(Copy, Clone, PartialEq, Eq, Enum, Default, Debug)]
#[repr(u8)]
pub enum IpTosDscp {
    #[default]
    /// Class Selector 0, RFC2474
    Cs0 = 0b0000_0000,

    /// Class Selector 1, RFC2474
    Cs1 = 0b0010_0000,

    /// Class Selector 2, RFC2474
    Cs2 = 0b0100_0000,

    /// Class Selector 3, RFC2474
    Cs3 = 0b0110_0000,

    /// Class Selector 4, RFC2474
    Cs4 = 0b1000_0000,

    /// Class Selector 5, RFC2474
    Cs5 = 0b1010_0000,

    /// Class Selector 6, RFC2474
    Cs6 = 0b1100_0000,

    /// Class Selector 7, RFC2474
    Cs7 = 0b1110_0000,

    /// Assured Forwarding 11, RFC2597
    Af11 = 0b0010_1000,

    /// Assured Forwarding 12, RFC2597
    Af12 = 0b0011_0000,

    /// Assured Forwarding 13, RFC2597
    Af13 = 0b0011_1000,

    /// Assured Forwarding 21, RFC2597
    Af21 = 0b0100_1000,

    /// Assured Forwarding 22, RFC2597
    Af22 = 0b0101_0000,

    /// Assured Forwarding 23, RFC2597
    Af23 = 0b0101_1000,

    /// Assured Forwarding 31, RFC2597
    Af31 = 0b0110_1000,

    /// Assured Forwarding 32, RFC2597
    Af32 = 0b0111_0000,

    /// Assured Forwarding 33, RFC2597
    Af33 = 0b0111_1000,

    /// Assured Forwarding 41, RFC2597
    Af41 = 0b1000_1000,

    /// Assured Forwarding 42, RFC2597
    Af42 = 0b1001_0000,

    /// Assured Forwarding 43, RFC2597
    Af43 = 0b1001_1000,

    /// Expedited Forwarding, RFC3246
    Ef = 0b1011_1000,

    /// Capacity-Admitted Traffic, RFC5865
    VoiceAdmit = 0b1011_0000,

    /// Lower-Effort, RFC8622
    Le = 0b0000_0100,
}

impl From<IpTosDscp> for u8 {
    fn from(v: IpTosDscp) -> Self {
        v as Self
    }
}

impl From<u8> for IpTosDscp {
    fn from(v: u8) -> Self {
        match v & 0b1111_1100 {
            0b0000_0000 => Self::Cs0,
            0b0010_0000 => Self::Cs1,
            0b0100_0000 => Self::Cs2,
            0b0110_0000 => Self::Cs3,
            0b1000_0000 => Self::Cs4,
            0b1010_0000 => Self::Cs5,
            0b1100_0000 => Self::Cs6,
            0b1110_0000 => Self::Cs7,
            0b0010_1000 => Self::Af11,
            0b0011_0000 => Self::Af12,
            0b0011_1000 => Self::Af13,
            0b0100_1000 => Self::Af21,
            0b0101_0000 => Self::Af22,
            0b0101_1000 => Self::Af23,
            0b0110_1000 => Self::Af31,
            0b0111_0000 => Self::Af32,
            0b0111_1000 => Self::Af33,
            0b1000_1000 => Self::Af41,
            0b1001_0000 => Self::Af42,
            0b1001_1000 => Self::Af43,
            0b1011_1000 => Self::Ef,
            0b1011_0000 => Self::VoiceAdmit,
            0b0000_0100 => Self::Le,
            _ => unreachable!(),
        }
    }
}

impl From<IpTos> for IpTosDscp {
    fn from(v: IpTos) -> Self {
        Self::from(u8::from(v))
    }
}

/// The type-of-service field in an IP packet.
#[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct IpTos(u8);

impl From<IpTosEcn> for IpTos {
    fn from(v: IpTosEcn) -> Self {
        Self(u8::from(v))
    }
}

impl From<IpTosDscp> for IpTos {
    fn from(v: IpTosDscp) -> Self {
        Self(u8::from(v))
    }
}

impl From<(IpTosDscp, IpTosEcn)> for IpTos {
    fn from(v: (IpTosDscp, IpTosEcn)) -> Self {
        Self(u8::from(v.0) | u8::from(v.1))
    }
}

impl From<(IpTosEcn, IpTosDscp)> for IpTos {
    fn from(v: (IpTosEcn, IpTosDscp)) -> Self {
        Self(u8::from(v.0) | u8::from(v.1))
    }
}

impl From<IpTos> for u8 {
    fn from(v: IpTos) -> Self {
        v.0
    }
}

impl From<u8> for IpTos {
    fn from(v: u8) -> Self {
        Self(v)
    }
}

impl Debug for IpTos {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("IpTos")
            .field(&IpTosDscp::from(*self))
            .field(&IpTosEcn::from(*self))
            .finish()
    }
}

impl IpTos {
    pub fn set_ecn(&mut self, ecn: IpTosEcn) {
        self.0 = u8::from(IpTosDscp::from(*self)) | u8::from(ecn);
    }

    pub fn set_dscp(&mut self, dscp: IpTosDscp) {
        self.0 = u8::from(IpTosEcn::from(*self)) | u8::from(dscp);
    }

    #[must_use]
    pub fn is_ecn_marked(&self) -> bool {
        IpTosEcn::from(*self).is_ecn_marked()
    }
}

#[cfg(test)]
mod tests {
    use crate::{IpTos, IpTosDscp, IpTosEcn};

    #[test]
    fn iptosecn_into_u8() {
        assert_eq!(u8::from(IpTosEcn::NotEct), 0b00);
        assert_eq!(u8::from(IpTosEcn::Ect1), 0b01);
        assert_eq!(u8::from(IpTosEcn::Ect0), 0b10);
        assert_eq!(u8::from(IpTosEcn::Ce), 0b11);
    }

    #[test]
    fn u8_into_iptosecn() {
        assert_eq!(IpTosEcn::from(0b00), IpTosEcn::NotEct);
        assert_eq!(IpTosEcn::from(0b01), IpTosEcn::Ect1);
        assert_eq!(IpTosEcn::from(0b10), IpTosEcn::Ect0);
        assert_eq!(IpTosEcn::from(0b11), IpTosEcn::Ce);
    }

    #[test]
    fn iptosdscp_into_u8() {
        assert_eq!(u8::from(IpTosDscp::Cs0), 0b0000_0000);
        assert_eq!(u8::from(IpTosDscp::Cs1), 0b0010_0000);
        assert_eq!(u8::from(IpTosDscp::Cs2), 0b0100_0000);
        assert_eq!(u8::from(IpTosDscp::Cs3), 0b0110_0000);
        assert_eq!(u8::from(IpTosDscp::Cs4), 0b1000_0000);
        assert_eq!(u8::from(IpTosDscp::Cs5), 0b1010_0000);
        assert_eq!(u8::from(IpTosDscp::Cs6), 0b1100_0000);
        assert_eq!(u8::from(IpTosDscp::Cs7), 0b1110_0000);
        assert_eq!(u8::from(IpTosDscp::Af11), 0b0010_1000);
        assert_eq!(u8::from(IpTosDscp::Af12), 0b0011_0000);
        assert_eq!(u8::from(IpTosDscp::Af13), 0b0011_1000);
        assert_eq!(u8::from(IpTosDscp::Af21), 0b0100_1000);
        assert_eq!(u8::from(IpTosDscp::Af22), 0b0101_0000);
        assert_eq!(u8::from(IpTosDscp::Af23), 0b0101_1000);
        assert_eq!(u8::from(IpTosDscp::Af31), 0b0110_1000);
        assert_eq!(u8::from(IpTosDscp::Af32), 0b0111_0000);
        assert_eq!(u8::from(IpTosDscp::Af33), 0b0111_1000);
        assert_eq!(u8::from(IpTosDscp::Af41), 0b1000_1000);
        assert_eq!(u8::from(IpTosDscp::Af42), 0b1001_0000);
        assert_eq!(u8::from(IpTosDscp::Af43), 0b1001_1000);
        assert_eq!(u8::from(IpTosDscp::Ef), 0b1011_1000);
        assert_eq!(u8::from(IpTosDscp::VoiceAdmit), 0b1011_0000);
        assert_eq!(u8::from(IpTosDscp::Le), 0b0000_0100);
    }

    #[test]
    fn u8_into_iptosdscp() {
        assert_eq!(IpTosDscp::from(0b0000_0000), IpTosDscp::Cs0);
        assert_eq!(IpTosDscp::from(0b0010_0000), IpTosDscp::Cs1);
        assert_eq!(IpTosDscp::from(0b0100_0000), IpTosDscp::Cs2);
        assert_eq!(IpTosDscp::from(0b0110_0000), IpTosDscp::Cs3);
        assert_eq!(IpTosDscp::from(0b1000_0000), IpTosDscp::Cs4);
        assert_eq!(IpTosDscp::from(0b1010_0000), IpTosDscp::Cs5);
        assert_eq!(IpTosDscp::from(0b1100_0000), IpTosDscp::Cs6);
        assert_eq!(IpTosDscp::from(0b1110_0000), IpTosDscp::Cs7);
        assert_eq!(IpTosDscp::from(0b0010_1000), IpTosDscp::Af11);
        assert_eq!(IpTosDscp::from(0b0011_0000), IpTosDscp::Af12);
        assert_eq!(IpTosDscp::from(0b0011_1000), IpTosDscp::Af13);
        assert_eq!(IpTosDscp::from(0b0100_1000), IpTosDscp::Af21);
        assert_eq!(IpTosDscp::from(0b0101_0000), IpTosDscp::Af22);
        assert_eq!(IpTosDscp::from(0b0101_1000), IpTosDscp::Af23);
        assert_eq!(IpTosDscp::from(0b0110_1000), IpTosDscp::Af31);
        assert_eq!(IpTosDscp::from(0b0111_0000), IpTosDscp::Af32);
        assert_eq!(IpTosDscp::from(0b0111_1000), IpTosDscp::Af33);
        assert_eq!(IpTosDscp::from(0b1000_1000), IpTosDscp::Af41);
        assert_eq!(IpTosDscp::from(0b1001_0000), IpTosDscp::Af42);
        assert_eq!(IpTosDscp::from(0b1001_1000), IpTosDscp::Af43);
        assert_eq!(IpTosDscp::from(0b1011_1000), IpTosDscp::Ef);
        assert_eq!(IpTosDscp::from(0b1011_0000), IpTosDscp::VoiceAdmit);
        assert_eq!(IpTosDscp::from(0b0000_0100), IpTosDscp::Le);
    }

    #[test]
    fn iptosecn_into_iptos() {
        let ecn = IpTosEcn::default();
        let iptos_ecn: IpTos = ecn.into();
        assert_eq!(u8::from(iptos_ecn), ecn as u8);
    }

    #[test]
    fn iptosdscp_into_iptos() {
        let dscp = IpTosDscp::default();
        let iptos_dscp: IpTos = dscp.into();
        assert_eq!(u8::from(iptos_dscp), dscp as u8);
    }

    #[test]
    fn u8_to_iptos() {
        let tos = 0x8b;
        let iptos: IpTos = (IpTosEcn::Ce, IpTosDscp::Af41).into();
        assert_eq!(tos, u8::from(iptos));
        assert_eq!(IpTos::from(tos), iptos);
    }

    #[test]
    fn iptos_to_iptosdscp() {
        let tos = IpTos::from((IpTosDscp::Af41, IpTosEcn::NotEct));
        let dscp = IpTosDscp::from(tos);
        assert_eq!(dscp, IpTosDscp::Af41);
    }

    #[test]
    fn tos_modify_ecn() {
        let mut iptos: IpTos = (IpTosDscp::Af41, IpTosEcn::NotEct).into();
        iptos.set_ecn(IpTosEcn::Ce);
        assert_eq!(u8::from(iptos), 0b1000_1011);
    }

    #[test]
    fn tos_modify_dscp() {
        let mut iptos: IpTos = (IpTosDscp::Af41, IpTosEcn::Ect1).into();
        iptos.set_dscp(IpTosDscp::Le);
        assert_eq!(u8::from(iptos), 0b0000_0101);
    }

    #[test]
    fn iptos_is_ecn_marked() {
        let iptos: IpTos = (IpTosDscp::Af41, IpTosEcn::Ce).into();
        assert!(iptos.is_ecn_marked());
    }

    #[test]
    fn iptosecn_is_ecn_marked() {
        assert!(IpTosEcn::Ce.is_ecn_marked());
        assert!(!IpTosEcn::NotEct.is_ecn_marked());
    }
}

[ Dauer der Verarbeitung: 0.36 Sekunden  ]