wlan_common/mac/
eth.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::big_endian::BigEndianU16;
6use crate::mac::MacAddr;
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, Unaligned};
8
9// RFC 704, Appendix B.2
10// https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
11pub const ETHER_TYPE_EAPOL: u16 = 0x888E;
12pub const ETHER_TYPE_IPV4: u16 = 0x0800;
13pub const ETHER_TYPE_IPV6: u16 = 0x86DD;
14
15pub const MAX_ETH_FRAME_LEN: usize = 2048;
16
17// IEEE Std 802.3-2015, 3.1.1
18#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, Clone, Copy, Debug)]
19#[repr(C, packed)]
20pub struct EthernetIIHdr {
21    pub da: MacAddr,
22    pub sa: MacAddr,
23    pub ether_type: BigEndianU16,
24}
25
26pub struct EthernetFrame<B: SplitByteSlice> {
27    pub hdr: Ref<B, EthernetIIHdr>,
28    pub body: B,
29}
30
31impl<B: SplitByteSlice> EthernetFrame<B> {
32    pub fn parse(bytes: B) -> Option<Self> {
33        let (hdr, body) = Ref::from_prefix(bytes).ok()?;
34        Some(Self { hdr, body })
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn eth_hdr_big_endian() {
44        let mut bytes: Vec<u8> = vec![
45            1, 2, 3, 4, 5, 6, // dst_addr
46            7, 8, 9, 10, 11, 12, // src_addr
47            13, 14, // ether_type
48            99, 99, // trailing bytes
49        ];
50        let (mut hdr, body) = Ref::<_, EthernetIIHdr>::from_prefix(&mut bytes[..])
51            .expect("cannot create ethernet header.");
52        assert_eq!(hdr.da, MacAddr::from([1u8, 2, 3, 4, 5, 6]));
53        assert_eq!(hdr.sa, MacAddr::from([7u8, 8, 9, 10, 11, 12]));
54        assert_eq!(hdr.ether_type.to_native(), 13 << 8 | 14);
55        assert_eq!(hdr.ether_type.0, [13u8, 14]);
56        assert_eq!(body, [99, 99]);
57
58        hdr.ether_type.set_from_native(0x888e);
59        assert_eq!(hdr.ether_type.0, [0x88, 0x8e]);
60        #[rustfmt::skip]
61        assert_eq!(
62            &[1u8, 2, 3, 4, 5, 6,
63            7, 8, 9, 10, 11, 12,
64            0x88, 0x8e,
65            99, 99],
66            &bytes[..]);
67    }
68}