mutnet/typed_protocol_headers/
ether_type.rs

1//! Typed versions of Ethernet II protocol header fields.
2
3/// Sources:
4/// <https://en.wikipedia.org/wiki/EtherType>
5/// <https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml>
6/// <https://standards-oui.ieee.org/ethertype/eth.txt>
7#[repr(u16)]
8#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
9#[cfg_attr(kani, derive(kani::Arbitrary))]
10pub enum EtherType {
11    /// Internet Protocol v4
12    Ipv4 = 0x0800,
13    /// Address Resolution Protocol
14    Arp = 0x0806,
15    /// Wake on lan
16    WakeOnLan = 0x0842,
17    /// Audio Video Transport Protocol
18    Avtp = 0x22F0,
19    /// Stream Reservation Protocol
20    Srp = 0x22EA,
21    /// Reverse Address Resolution Protocol
22    Rarp = 0x8035,
23    /// Apple talk
24    AppleTalk = 0x809B,
25    /// AppleTalk Address Resolution Protocol
26    Aarp = 0x80F3,
27    /// Customer VLAN Tag Type (C-Tag, formerly called the Q-Tag)
28    CustomerTag = 0x8100,
29    ///Simple Loop Prevention Protocol
30    Slpp = 0x8102,
31    /// Virtual Link Aggregation Control Protocol
32    Vlacp = 0x8103,
33    /// Internetwork Packet Exchange
34    Ipx = 0x8137,
35    /// QNX Qnet
36    QnxQnet = 0x8204,
37    /// Internet Protocol v6
38    Ipv6 = 0x86DD,
39    /// Ethernet flow control
40    EthernetFlowControl = 0x8808,
41    /// Ethernet slow protocols
42    EthernetSlowProtocols = 0x8809,
43    /// CobraNet
44    CobraNet = 0x8819,
45    /// MPLS unicast
46    MplsUnicast = 0x8847,
47    /// MPLS multicast
48    MplsMulticast = 0x8848,
49    /// PPPOE discovery stage
50    PppoeDiscoveryStage = 0x8863,
51    /// PPPOE session stage
52    PppoeSessionStage = 0x8864,
53    /// HomePlug 1.0 MME
54    HomePlug1_0Mme = 0x887B,
55    /// EAP over LAN
56    EapOverLan = 0x888E,
57    /// PROFINET
58    Profinet = 0x8892,
59    ///HyperSCSI
60    HyperScsi = 0x889A,
61    /// ATA over ethernet
62    AtaOverEthernet = 0x88A2,
63    /// EtherCAT
64    EtherCat = 0x88A4,
65    /// IEEE Std 802.1Q - Service VLAN tag identifier (S-Tag)
66    ServiceTag = 0x88A8,
67    /// Ethernet powerlink
68    EthernetPowerlink = 0x88AB,
69    /// Generic Object Oriented Substation Event
70    Goose = 0x88B8,
71    /// Generic Substation Events Management Services
72    GseManagementServices = 0x88B9,
73    /// Sampled Value
74    Sv = 0x88BA,
75    /// Link Layer Discovery Protocol
76    Lldp = 0x88CC,
77    /// SERCOS III
78    Sercos3 = 0x88CD,
79    /// HomePlug green PHY
80    HomePlugGreenPhy = 0x88E1,
81    /// Media redundancy protocol
82    MediaRedundancyProtocol = 0x88E3,
83    /// MACsec
84    MacSec = 0x88E5,
85    /// Provider Backbone Bridges
86    Pbb = 0x88E7,
87    /// Precision Time Protocol
88    Ptp = 0x88F7,
89    /// Network Controller Sideband Interface
90    NcSi = 0x88F8,
91    /// Parallel Redundancy Protocol
92    Prp = 0x88FB,
93    /// Fibre Channel Over Ethernet
94    Fcoe = 0x8906,
95    /// Mediaxtream
96    Mediaxtream = 0x8912,
97    /// Fibre Channel Over Ethernet Initialization Protocol
98    FcoeInitializationProtocol = 0x8914,
99    /// RDMA over Converged Ethernet
100    Roce = 0x8915,
101    /// TTEthernet Protocol Control Frame
102    Tte = 0x891D,
103    /// High-Availability Seamless Redundancy
104    Hsr = 0x892F,
105    /// Ethernet configuration testing protocol
106    EthernetConfigurationTestingProtocol = 0x9000,
107    /// Redundancy Tag (IEEE 802.1CB)
108    RTag = 0xF1C1,
109}
110
111impl core::fmt::Display for EtherType {
112    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
113        write!(f, "{self:?}")
114    }
115}
116
117/// Error returned by [`EtherType::try_from()`].
118#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
119pub struct UnrecognizedEtherTypeError {
120    /// The unrecognized ether type.
121    pub ether_type: u16,
122}
123
124impl core::fmt::Display for UnrecognizedEtherTypeError {
125    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126        write!(f, "Unrecognized ether type, was: {:?}", self.ether_type)
127    }
128}
129
130impl core::error::Error for UnrecognizedEtherTypeError {}
131
132impl TryFrom<u16> for EtherType {
133    type Error = UnrecognizedEtherTypeError;
134    #[inline]
135    fn try_from(value: u16) -> Result<Self, Self::Error> {
136        match value {
137            0x0800 => Ok(EtherType::Ipv4),
138            0x0806 => Ok(EtherType::Arp),
139            0x0842 => Ok(EtherType::WakeOnLan),
140            0x22F0 => Ok(EtherType::Avtp),
141            0x22EA => Ok(EtherType::Srp),
142            0x8035 => Ok(EtherType::Rarp),
143            0x809B => Ok(EtherType::AppleTalk),
144            0x80F3 => Ok(EtherType::Aarp),
145            0x8100 => Ok(EtherType::CustomerTag),
146            0x8102 => Ok(EtherType::Slpp),
147            0x8103 => Ok(EtherType::Vlacp),
148            0x8137 => Ok(EtherType::Ipx),
149            0x8204 => Ok(EtherType::QnxQnet),
150            0x86DD => Ok(EtherType::Ipv6),
151            0x8808 => Ok(EtherType::EthernetFlowControl),
152            0x8809 => Ok(EtherType::EthernetSlowProtocols),
153            0x8819 => Ok(EtherType::CobraNet),
154            0x8847 => Ok(EtherType::MplsUnicast),
155            0x8848 => Ok(EtherType::MplsMulticast),
156            0x8863 => Ok(EtherType::PppoeDiscoveryStage),
157            0x8864 => Ok(EtherType::PppoeSessionStage),
158            0x887B => Ok(EtherType::HomePlug1_0Mme),
159            0x888E => Ok(EtherType::EapOverLan),
160            0x8892 => Ok(EtherType::Profinet),
161            0x889A => Ok(EtherType::HyperScsi),
162            0x88A2 => Ok(EtherType::AtaOverEthernet),
163            0x88A4 => Ok(EtherType::EtherCat),
164            0x88A8 => Ok(EtherType::ServiceTag),
165            0x88AB => Ok(EtherType::EthernetPowerlink),
166            0x88B8 => Ok(EtherType::Goose),
167            0x88B9 => Ok(EtherType::GseManagementServices),
168            0x88BA => Ok(EtherType::Sv),
169            0x88CC => Ok(EtherType::Lldp),
170            0x88CD => Ok(EtherType::Sercos3),
171            0x88E1 => Ok(EtherType::HomePlugGreenPhy),
172            0x88E3 => Ok(EtherType::MediaRedundancyProtocol),
173            0x88E5 => Ok(EtherType::MacSec),
174            0x88E7 => Ok(EtherType::Pbb),
175            0x88F7 => Ok(EtherType::Ptp),
176            0x88F8 => Ok(EtherType::NcSi),
177            0x88FB => Ok(EtherType::Prp),
178            0x8906 => Ok(EtherType::Fcoe),
179            0x8912 => Ok(EtherType::Mediaxtream),
180            0x8914 => Ok(EtherType::FcoeInitializationProtocol),
181            0x8915 => Ok(EtherType::Roce),
182            0x891D => Ok(EtherType::Tte),
183            0x892F => Ok(EtherType::Hsr),
184            0x9000 => Ok(EtherType::EthernetConfigurationTestingProtocol),
185            0xF1C1 => Ok(EtherType::RTag),
186
187            _ => Err(UnrecognizedEtherTypeError { ether_type: value }),
188        }
189    }
190}
191
192// Kani verification to ensure the code does not panic on any input.
193#[cfg(kani)]
194mod ether_type_verification {
195    use super::*;
196
197    #[kani::proof]
198    fn ether_type_proof() {
199        let try_value = kani::any::<u16>();
200        match EtherType::try_from(try_value) {
201            Ok(ether_type) => {
202                assert_eq!(ether_type as u16, try_value);
203            }
204            Err(err) => {
205                assert_eq!(
206                    UnrecognizedEtherTypeError {
207                        ether_type: try_value
208                    },
209                    err
210                );
211            }
212        }
213    }
214}