1use crate::PrimitiveValues;
4
5use alloc::vec::Vec;
6use core::fmt;
7
8use xenet_core::mac::MacAddr;
9use xenet_macro::packet;
10
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14pub const ETHERNET_HEADER_LEN: usize = 14;
16
17pub const MAC_ADDR_LEN: usize = 6;
19
20#[derive(Clone, Debug, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct EthernetHeader {
24 pub destination: MacAddr,
26 pub source: MacAddr,
28 pub ethertype: EtherType,
30}
31
32impl EthernetHeader {
33 pub fn from_bytes(packet: &[u8]) -> Result<EthernetHeader, String> {
35 if packet.len() < ETHERNET_HEADER_LEN {
36 return Err("Packet is too small for Ethernet header".to_string());
37 }
38 match EthernetPacket::new(packet) {
39 Some(ethernet_packet) => Ok(EthernetHeader {
40 destination: ethernet_packet.get_destination(),
41 source: ethernet_packet.get_source(),
42 ethertype: ethernet_packet.get_ethertype(),
43 }),
44 None => Err("Failed to parse Ethernet packet".to_string()),
45 }
46 }
47 pub(crate) fn from_packet(ethernet_packet: &EthernetPacket) -> EthernetHeader {
49 EthernetHeader {
50 destination: ethernet_packet.get_destination(),
51 source: ethernet_packet.get_source(),
52 ethertype: ethernet_packet.get_ethertype(),
53 }
54 }
55}
56
57#[packet]
59pub struct Ethernet {
60 #[construct_with(u8, u8, u8, u8, u8, u8)]
61 pub destination: MacAddr,
62 #[construct_with(u8, u8, u8, u8, u8, u8)]
63 pub source: MacAddr,
64 #[construct_with(u16)]
65 pub ethertype: EtherType,
66 #[payload]
67 pub payload: Vec<u8>,
68}
69
70#[test]
71fn ethernet_header_test() {
72 let mut packet = [0u8; 14];
73 {
74 let mut ethernet_header = MutableEthernetPacket::new(&mut packet[..]).unwrap();
75
76 let source = MacAddr(0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc);
77 ethernet_header.set_source(source);
78 assert_eq!(ethernet_header.get_source(), source);
79
80 let dest = MacAddr(0xde, 0xf0, 0x12, 0x34, 0x45, 0x67);
81 ethernet_header.set_destination(dest);
82 assert_eq!(ethernet_header.get_destination(), dest);
83
84 ethernet_header.set_ethertype(EtherType::Ipv6);
85 assert_eq!(ethernet_header.get_ethertype(), EtherType::Ipv6);
86 }
87
88 let ref_packet = [
89 0xde, 0xf0, 0x12, 0x34, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x86, 0xdd, ];
93 assert_eq!(&ref_packet[..], &packet[..]);
94}
95
96#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
98#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
99pub enum EtherType {
100 Ipv4,
101 Arp,
102 WakeOnLan,
103 Trill,
104 DECnet,
105 Rarp,
106 AppleTalk,
107 Aarp,
108 Ipx,
109 Qnx,
110 Ipv6,
111 FlowControl,
112 CobraNet,
113 Mpls,
114 MplsMcast,
115 PppoeDiscovery,
116 PppoeSession,
117 Vlan,
118 PBridge,
119 Lldp,
120 Ptp,
121 Cfm,
122 QinQ,
123 Rldp,
124 Unknown(u16),
125}
126
127impl EtherType {
128 pub fn new(value: u16) -> EtherType {
130 match value {
131 0x0800 => EtherType::Ipv4,
132 0x0806 => EtherType::Arp,
133 0x0842 => EtherType::WakeOnLan,
134 0x22F3 => EtherType::Trill,
135 0x6003 => EtherType::DECnet,
136 0x8035 => EtherType::Rarp,
137 0x809B => EtherType::AppleTalk,
138 0x80F3 => EtherType::Aarp,
139 0x8137 => EtherType::Ipx,
140 0x8204 => EtherType::Qnx,
141 0x86DD => EtherType::Ipv6,
142 0x8808 => EtherType::FlowControl,
143 0x8819 => EtherType::CobraNet,
144 0x8847 => EtherType::Mpls,
145 0x8848 => EtherType::MplsMcast,
146 0x8863 => EtherType::PppoeDiscovery,
147 0x8864 => EtherType::PppoeSession,
148 0x8100 => EtherType::Vlan,
149 0x88a8 => EtherType::PBridge,
150 0x88cc => EtherType::Lldp,
151 0x88f7 => EtherType::Ptp,
152 0x8902 => EtherType::Cfm,
153 0x9100 => EtherType::QinQ,
154 0x8899 => EtherType::Rldp,
155 _ => EtherType::Unknown(value),
156 }
157 }
158 pub fn name(&self) -> &str {
160 match *self {
161 EtherType::Ipv4 => "IPv4",
162 EtherType::Arp => "ARP",
163 EtherType::WakeOnLan => "WakeOnLan",
164 EtherType::Trill => "Trill",
165 EtherType::DECnet => "DECnet",
166 EtherType::Rarp => "RARP",
167 EtherType::AppleTalk => "AppleTalk",
168 EtherType::Aarp => "AARP",
169 EtherType::Ipx => "IPX",
170 EtherType::Qnx => "QNX",
171 EtherType::Ipv6 => "IPv6",
172 EtherType::FlowControl => "FlowControl",
173 EtherType::CobraNet => "CobraNet",
174 EtherType::Mpls => "MPLS",
175 EtherType::MplsMcast => "MPLS Multicast",
176 EtherType::PppoeDiscovery => "PPPoE Discovery",
177 EtherType::PppoeSession => "PPPoE Session",
178 EtherType::Vlan => "VLAN",
179 EtherType::PBridge => "Provider Bridging",
180 EtherType::Lldp => "LLDP",
181 EtherType::Ptp => "PTP",
182 EtherType::Cfm => "CFM",
183 EtherType::QinQ => "QinQ",
184 EtherType::Rldp => "RLDP",
185 EtherType::Unknown(_) => "Unknown",
186 }
187 }
188}
189
190impl PrimitiveValues for EtherType {
191 type T = (u16,);
192 fn to_primitive_values(&self) -> (u16,) {
193 match *self {
194 EtherType::Ipv4 => (0x0800,),
195 EtherType::Arp => (0x0806,),
196 EtherType::WakeOnLan => (0x0842,),
197 EtherType::Trill => (0x22F3,),
198 EtherType::DECnet => (0x6003,),
199 EtherType::Rarp => (0x8035,),
200 EtherType::AppleTalk => (0x809B,),
201 EtherType::Aarp => (0x80F3,),
202 EtherType::Ipx => (0x8137,),
203 EtherType::Qnx => (0x8204,),
204 EtherType::Ipv6 => (0x86DD,),
205 EtherType::FlowControl => (0x8808,),
206 EtherType::CobraNet => (0x8819,),
207 EtherType::Mpls => (0x8847,),
208 EtherType::MplsMcast => (0x8848,),
209 EtherType::PppoeDiscovery => (0x8863,),
210 EtherType::PppoeSession => (0x8864,),
211 EtherType::Vlan => (0x8100,),
212 EtherType::PBridge => (0x88a8,),
213 EtherType::Lldp => (0x88cc,),
214 EtherType::Ptp => (0x88f7,),
215 EtherType::Cfm => (0x8902,),
216 EtherType::QinQ => (0x9100,),
217 EtherType::Rldp => (0x8899,),
218 EtherType::Unknown(n) => (n,),
219 }
220 }
221}
222
223impl fmt::Display for EtherType {
224 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
225 write!(
226 f,
227 "{}",
228 match self {
229 EtherType::Ipv4 => "Ipv4",
230 EtherType::Arp => "Arp",
231 EtherType::WakeOnLan => "WakeOnLan",
232 EtherType::Trill => "Trill",
233 EtherType::DECnet => "DECnet",
234 EtherType::Rarp => "Rarp",
235 EtherType::AppleTalk => "AppleTalk",
236 EtherType::Aarp => "Aarp",
237 EtherType::Ipx => "Ipx",
238 EtherType::Qnx => "Qnx",
239 EtherType::Ipv6 => "Ipv6",
240 EtherType::FlowControl => "FlowControl",
241 EtherType::CobraNet => "CobraNet",
242 EtherType::Mpls => "Mpls",
243 EtherType::MplsMcast => "MplsMcast",
244 EtherType::PppoeDiscovery => "PppoeDiscovery",
245 EtherType::PppoeSession => "PppoeSession",
246 EtherType::Vlan => "Vlan",
247 EtherType::PBridge => "PBridge",
248 EtherType::Lldp => "Lldp",
249 EtherType::Ptp => "Ptp",
250 EtherType::Cfm => "Cfm",
251 EtherType::QinQ => "QinQ",
252 EtherType::Rldp => "Rldp",
253 EtherType::Unknown(_) => "unknown",
254 }
255 )
256 }
257}
258
259#[test]
260fn ether_type_to_str() {
261 use std::format;
262 let ipv4 = EtherType::new(0x0800);
263 assert_eq!(format!("{}", ipv4), "Ipv4");
264 let arp = EtherType::new(0x0806);
265 assert_eq!(format!("{}", arp), "Arp");
266 let unknown = EtherType::new(0x0666);
267 assert_eq!(format!("{}", unknown), "unknown");
268}