// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Parsing and serialization of Ethernet frames.

use net_types::ethernet::Mac;
use net_types::ip::{Ip, IpVersion, Ipv4, Ipv6};
use packet::{
    BufferView, BufferViewMut, FragmentedBytesMut, PacketBuilder, PacketConstraints,
    ParsablePacket, ParseMetadata, SerializeTarget,
};
use zerocopy::byteorder::network_endian::{U16, U32};
use zerocopy::{AsBytes, ByteSlice, FromBytes, FromZeros, NoCell, Ref, Unaligned};

use crate::error::{ParseError, ParseResult};

const ETHERNET_MIN_ILLEGAL_ETHERTYPE: u16 = 1501;
const ETHERNET_MAX_ILLEGAL_ETHERTYPE: u16 = 1535;

create_protocol_enum!(
    /// An EtherType number.
    #[allow(missing_docs)]
    #[derive(Copy, Clone, Hash, Eq, PartialEq)]
    pub enum EtherType: u16 {
        Ipv4, 0x0800, "IPv4";
        Arp, 0x0806, "ARP";
        Ipv6, 0x86DD, "IPv6";
        _, "EtherType {}";
    }
);

impl EtherType {
    /// Constructs the relevant [`EtherType`] from the given [`IpVersion`].
    pub fn from_ip_version(ip_version: IpVersion) -> Self {
        match ip_version {
            IpVersion::V4 => EtherType::Ipv4,
            IpVersion::V6 => EtherType::Ipv6,
        }
    }
}

/// An extension trait adding IP-related functionality to `Ipv4` and `Ipv6`.
pub trait EthernetIpExt: Ip {
    /// The `EtherType` value for an associated IP version.
    const ETHER_TYPE: EtherType;
}

impl EthernetIpExt for Ipv4 {
    const ETHER_TYPE: EtherType = EtherType::Ipv4;
}

impl EthernetIpExt for Ipv6 {
    const ETHER_TYPE: EtherType = EtherType::Ipv6;
}

#[derive(FromZeros, FromBytes, AsBytes, NoCell, Unaligned)]
#[repr(C)]
struct HeaderPrefix {
    dst_mac: Mac,
    src_mac: Mac,
}

const TPID_8021Q: u16 = 0x8100;
const TPID_8021AD: u16 = 0x88a8;

/// An Ethernet frame.
///
/// An `EthernetFrame` shares its underlying memory with the byte slice it was
/// parsed from or serialized to, meaning that no copying or extra allocation is
/// necessary.
pub struct EthernetFrame<B> {
    hdr_prefix: Ref<B, HeaderPrefix>,
    tag: Option<Ref<B, U32>>,
    ethertype: Ref<B, U16>,
    body: B,
}

/// Whether or not an Ethernet frame's length should be checked during parsing.
///
/// When the `Check` variant is used, the Ethernet frame will be rejected if its
/// total length (including header, but excluding the Frame Check Sequence (FCS)
/// footer) is less than the required minimum of 60 bytes.
#[derive(PartialEq)]
pub enum EthernetFrameLengthCheck {
    /// Check that the Ethernet frame's total length (including header, but
    /// excluding the Frame Check Sequence (FCS) footer) satisfies the required
    /// minimum of 60 bytes.
    Check,
    /// Do not check the Ethernet frame's total length. The frame will still be
    /// rejected if a complete, valid header is not present, but the body may be
    /// 0 bytes long.
    NoCheck,
}

impl<B: ByteSlice> ParsablePacket<B, EthernetFrameLengthCheck> for EthernetFrame<B> {
    type Error = ParseError;

    fn parse_metadata(&self) -> ParseMetadata {
        let header_len = self.hdr_prefix.bytes().len()
            + self.tag.as_ref().map(|tag| tag.bytes().len()).unwrap_or(0)
            + self.ethertype.bytes().len();
        ParseMetadata::from_packet(header_len, self.body.len(), 0)
    }

    fn parse<BV: BufferView<B>>(
        mut buffer: BV,
        length_check: EthernetFrameLengthCheck,
    ) -> ParseResult<Self> {
        // See for details: https://en.wikipedia.org/wiki/Ethernet_frame#Frame_%E2%80%93_data_link_layer

        let hdr_prefix = buffer
            .take_obj_front::<HeaderPrefix>()
            .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
        if length_check == EthernetFrameLengthCheck::Check && buffer.len() < 48 {
            // The minimum frame size (not including the Frame Check Sequence
            // (FCS) footer, which we do not handle in this code) is 60 bytes.
            // We've already consumed 12 bytes for the header prefix, so we must
            // have at least 48 bytes left.
            return debug_err!(Err(ParseError::Format), "too few bytes for frame");
        }

        // The tag (either IEEE 802.1Q or 802.1ad) is an optional four-byte
        // field. If present, it precedes the ethertype, and its first two bytes
        // (where the ethertype bytes are normally) are called the Tag Protocol
        // Identifier (TPID). A TPID of TPID_8021Q implies an 802.1Q tag, a TPID
        // of TPID_8021AD implies an 802.1ad tag, and anything else implies that
        // there is no tag - it's a normal ethertype field.
        let ethertype_or_tpid = buffer
            .peek_obj_front::<U16>()
            .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?
            .get();
        let (tag, ethertype, body) = match ethertype_or_tpid {
            self::TPID_8021Q | self::TPID_8021AD => (
                Some(
                    buffer.take_obj_front().ok_or_else(debug_err_fn!(
                        ParseError::Format,
                        "too few bytes for header"
                    ))?,
                ),
                buffer
                    .take_obj_front()
                    .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?,
                buffer.into_rest(),
            ),
            _ => (
                None,
                buffer
                    .take_obj_front()
                    .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?,
                buffer.into_rest(),
            ),
        };

        let frame = EthernetFrame { hdr_prefix, tag, ethertype, body };
        let et = frame.ethertype.get();
        if (ETHERNET_MIN_ILLEGAL_ETHERTYPE..=ETHERNET_MAX_ILLEGAL_ETHERTYPE).contains(&et)
            || (et < ETHERNET_MIN_ILLEGAL_ETHERTYPE && et as usize != frame.body.len())
        {
            // EtherType values between 1500 and 1536 are disallowed, and values
            // of 1500 and below are used to indicate the body length.
            return debug_err!(Err(ParseError::Format), "invalid ethertype number: {:x}", et);
        }
        Ok(frame)
    }
}

impl<B: ByteSlice> EthernetFrame<B> {
    /// The frame body.
    pub fn body(&self) -> &[u8] {
        &self.body
    }

    /// Consumes the frame and returns the body.
    pub fn into_body(self) -> B
    where
        B: Copy,
    {
        self.body
    }

    /// The source MAC address.
    pub fn src_mac(&self) -> Mac {
        self.hdr_prefix.src_mac
    }

    /// The destination MAC address.
    pub fn dst_mac(&self) -> Mac {
        self.hdr_prefix.dst_mac
    }

    /// The EtherType.
    ///
    /// `ethertype` returns the `EtherType` from the Ethernet header. However,
    /// some values of the EtherType header field are used to indicate the
    /// length of the frame's body. In this case, `ethertype` returns `None`.
    pub fn ethertype(&self) -> Option<EtherType> {
        let et = self.ethertype.get();
        if et < ETHERNET_MIN_ILLEGAL_ETHERTYPE {
            return None;
        }
        // values in (1500, 1536) are illegal, and shouldn't make it through
        // parse
        debug_assert!(et > ETHERNET_MAX_ILLEGAL_ETHERTYPE);
        Some(EtherType::from(et))
    }

    // The size of the frame header.
    fn header_len(&self) -> usize {
        self.hdr_prefix.bytes().len()
            + self.tag.as_ref().map(|t| t.bytes().len()).unwrap_or(0)
            + self.ethertype.bytes().len()
    }

    // Total frame length including header prefix, tag, EtherType, and body.
    // This is not the same as the length as optionally encoded in the
    // EtherType.
    // TODO(rheacock): remove `allow(dead_code)` when this is used.
    #[allow(dead_code)]
    fn total_frame_len(&self) -> usize {
        self.header_len() + self.body.len()
    }

    /// Construct a builder with the same contents as this frame.
    pub fn builder(&self) -> EthernetFrameBuilder {
        EthernetFrameBuilder {
            src_mac: self.src_mac(),
            dst_mac: self.dst_mac(),
            ethertype: self.ethertype.get(),
            min_body_len: ETHERNET_MIN_BODY_LEN_NO_TAG,
        }
    }
}

/// A builder for Ethernet frames.
///
/// A [`PacketBuilder`] that serializes into an Ethernet frame. The padding
/// parameter `P` can be used to choose how the body of the frame is padded.
#[derive(Debug)]
pub struct EthernetFrameBuilder {
    src_mac: Mac,
    dst_mac: Mac,
    ethertype: u16,
    min_body_len: usize,
}

impl EthernetFrameBuilder {
    /// Construct a new `EthernetFrameBuilder`.
    ///
    /// The provided source and destination [`Mac`] addresses and [`EtherType`]
    /// will be placed in the Ethernet frame header. The `min_body_len`
    /// parameter sets the minimum length of the frame's body in bytes. If,
    /// during serialization, the inner packet builder produces a smaller body
    /// than `min_body_len`, it will be padded with trailing zero bytes up to
    /// `min_body_len`.
    pub fn new(
        src_mac: Mac,
        dst_mac: Mac,
        ethertype: EtherType,
        min_body_len: usize,
    ) -> EthernetFrameBuilder {
        EthernetFrameBuilder { src_mac, dst_mac, ethertype: ethertype.into(), min_body_len }
    }
}

// NOTE(joshlf): header_len and min_body_len assume no 802.1Q or 802.1ad tag. We
// don't support creating packets with these tags at the moment, so this is a
// sound assumption. If we support them in the future, we will need to update
// these to compute dynamically.

impl PacketBuilder for EthernetFrameBuilder {
    fn constraints(&self) -> PacketConstraints {
        PacketConstraints::new(ETHERNET_HDR_LEN_NO_TAG, 0, self.min_body_len, core::usize::MAX)
    }

    fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
        // NOTE: EtherType values of 1500 and below are used to indicate the
        // length of the body in bytes. We don't need to validate this because
        // the EtherType enum has no variants with values in that range.

        let total_len = target.header.len() + body.len();
        // implements BufferViewMut, giving us take_obj_xxx_zero methods
        let mut header = &mut target.header;

        header
            .write_obj_front(&HeaderPrefix { src_mac: self.src_mac, dst_mac: self.dst_mac })
            .expect("too few bytes for Ethernet header");
        header
            .write_obj_front(&U16::new(self.ethertype))
            .expect("too few bytes for Ethernet header");

        // NOTE(joshlf): This doesn't include the tag. If we ever add support
        // for serializing tags, we will need to update this.
        let min_frame_size = self.min_body_len + ETHERNET_HDR_LEN_NO_TAG;

        // Assert this here so that if there isn't enough space for even an
        // Ethernet header, we report that more specific error.
        assert!(
            total_len >= min_frame_size,
            "total frame size of {} bytes is below minimum frame size of {}",
            total_len,
            min_frame_size,
        );
    }
}

/// The length of an Ethernet header when it has no tags.
pub const ETHERNET_HDR_LEN_NO_TAG: usize = 14;

/// The minimum length of an Ethernet frame's body when the header contains no tags.
pub const ETHERNET_MIN_BODY_LEN_NO_TAG: usize = 46;

/// Constants useful for testing.
pub mod testutil {
    pub use super::{ETHERNET_HDR_LEN_NO_TAG, ETHERNET_MIN_BODY_LEN_NO_TAG};

    /// Ethernet frame, in bytes.
    pub const ETHERNET_DST_MAC_BYTE_OFFSET: usize = 0;

    /// The offset to the start of the source MAC address from the start of the
    /// Ethernet frame, in bytes.
    pub const ETHERNET_SRC_MAC_BYTE_OFFSET: usize = 6;
}

#[cfg(test)]
mod tests {
    use byteorder::{ByteOrder, NetworkEndian};
    use packet::{
        AsFragmentedByteSlice, Buf, GrowBufferMut, InnerPacketBuilder, ParseBuffer, Serializer,
    };

    use super::*;

    const DEFAULT_DST_MAC: Mac = Mac::new([0, 1, 2, 3, 4, 5]);
    const DEFAULT_SRC_MAC: Mac = Mac::new([6, 7, 8, 9, 10, 11]);
    const ETHERNET_ETHERTYPE_BYTE_OFFSET: usize = 12;
    const ETHERNET_MIN_FRAME_LEN: usize = 60;

    // Return a buffer for testing parsing with values 0..60 except for the
    // EtherType field, which is EtherType::Arp. Also return the contents
    // of the body.
    fn new_parse_buf() -> ([u8; ETHERNET_MIN_FRAME_LEN], [u8; ETHERNET_MIN_BODY_LEN_NO_TAG]) {
        let mut buf = [0; ETHERNET_MIN_FRAME_LEN];
        for (i, elem) in buf.iter_mut().enumerate() {
            *elem = i as u8;
        }
        NetworkEndian::write_u16(&mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..], EtherType::Arp.into());
        let mut body = [0; ETHERNET_MIN_BODY_LEN_NO_TAG];
        (&mut body).copy_from_slice(&buf[ETHERNET_HDR_LEN_NO_TAG..]);
        (buf, body)
    }

    // Return a test buffer with values 0..46 to be used as a test payload for
    // serialization.
    fn new_serialize_buf() -> [u8; ETHERNET_MIN_BODY_LEN_NO_TAG] {
        let mut buf = [0; ETHERNET_MIN_BODY_LEN_NO_TAG];
        for (i, elem) in buf.iter_mut().enumerate() {
            *elem = i as u8;
        }
        buf
    }

    #[test]
    fn test_parse() {
        crate::testutil::set_logger_for_test();
        let (mut backing_buf, body) = new_parse_buf();
        let mut buf = &mut backing_buf[..];
        // Test parsing with a sufficiently long body.
        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
        assert_eq!(frame.hdr_prefix.dst_mac, DEFAULT_DST_MAC);
        assert_eq!(frame.hdr_prefix.src_mac, DEFAULT_SRC_MAC);
        assert!(frame.tag.is_none());
        assert_eq!(frame.ethertype(), Some(EtherType::Arp));
        assert_eq!(frame.body(), &body[..]);
        // Test parsing with a too-short body but length checking disabled.
        let mut buf = &mut backing_buf[..ETHERNET_HDR_LEN_NO_TAG];
        let frame =
            buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::NoCheck).unwrap();
        assert_eq!(frame.hdr_prefix.dst_mac, DEFAULT_DST_MAC);
        assert_eq!(frame.hdr_prefix.src_mac, DEFAULT_SRC_MAC);
        assert!(frame.tag.is_none());
        assert_eq!(frame.ethertype(), Some(EtherType::Arp));
        assert_eq!(frame.body(), &[]);

        // For both of the TPIDs that imply the existence of a tag, make sure
        // that the tag is present and correct (and that all of the normal
        // checks succeed).
        for tpid in [TPID_8021Q, TPID_8021AD].iter() {
            let (mut buf, body) = new_parse_buf();
            let mut buf = &mut buf[..];

            const TPID_OFFSET: usize = 12;
            NetworkEndian::write_u16(&mut buf[TPID_OFFSET..], *tpid);
            // write a valid EtherType
            NetworkEndian::write_u16(&mut buf[TPID_OFFSET + 4..], EtherType::Arp.into());

            let frame =
                buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
            assert_eq!(frame.hdr_prefix.dst_mac, DEFAULT_DST_MAC);
            assert_eq!(frame.hdr_prefix.src_mac, DEFAULT_SRC_MAC);
            assert_eq!(frame.ethertype(), Some(EtherType::Arp));

            // help out with type inference
            let tag: &U32 = frame.tag.as_ref().unwrap();
            let want_tag =
                u32::from(*tpid) << 16 | ((TPID_OFFSET as u32 + 2) << 8) | (TPID_OFFSET as u32 + 3);
            assert_eq!(tag.get(), want_tag);
            // Offset by 4 since new_parse_buf returns a body on the assumption
            // that there's no tag.
            assert_eq!(frame.body(), &body[4..]);
        }
    }

    #[test]
    fn test_ethertype() {
        // EtherTypes of 1500 and below must match the body length
        let mut buf = [0u8; 1014];
        // an incorrect length results in error
        NetworkEndian::write_u16(&mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..], 1001);
        assert!((&mut buf[..])
            .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
            .is_err());

        // a correct length results in success
        NetworkEndian::write_u16(&mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..], 1000);
        assert_eq!(
            (&mut buf[..])
                .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
                .unwrap()
                .ethertype(),
            None
        );

        // an unrecognized EtherType is returned numerically
        let mut buf = [0u8; 1014];
        NetworkEndian::write_u16(
            &mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..],
            ETHERNET_MAX_ILLEGAL_ETHERTYPE + 1,
        );
        assert_eq!(
            (&mut buf[..])
                .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
                .unwrap()
                .ethertype(),
            Some(EtherType::Other(ETHERNET_MAX_ILLEGAL_ETHERTYPE + 1))
        );
    }

    #[test]
    fn test_serialize() {
        let buf = (&new_serialize_buf()[..])
            .into_serializer()
            .encapsulate(EthernetFrameBuilder::new(
                DEFAULT_DST_MAC,
                DEFAULT_SRC_MAC,
                EtherType::Arp,
                ETHERNET_MIN_BODY_LEN_NO_TAG,
            ))
            .serialize_vec_outer()
            .unwrap();
        assert_eq!(
            &buf.as_ref()[..ETHERNET_HDR_LEN_NO_TAG],
            [6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 0x08, 0x06]
        );
    }

    #[test]
    fn test_serialize_zeroes() {
        // Test that EthernetFrame::serialize properly zeroes memory before
        // serializing the header.
        let mut buf_0 = [0; ETHERNET_MIN_FRAME_LEN];
        let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], ETHERNET_HDR_LEN_NO_TAG..)
            .encapsulate(EthernetFrameBuilder::new(
                DEFAULT_SRC_MAC,
                DEFAULT_DST_MAC,
                EtherType::Arp,
                ETHERNET_MIN_BODY_LEN_NO_TAG,
            ))
            .serialize_vec_outer()
            .unwrap()
            .unwrap_a();
        let mut buf_1 = [0; ETHERNET_MIN_FRAME_LEN];
        (&mut buf_1[..ETHERNET_HDR_LEN_NO_TAG]).copy_from_slice(&[0xFF; ETHERNET_HDR_LEN_NO_TAG]);
        let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], ETHERNET_HDR_LEN_NO_TAG..)
            .encapsulate(EthernetFrameBuilder::new(
                DEFAULT_SRC_MAC,
                DEFAULT_DST_MAC,
                EtherType::Arp,
                ETHERNET_MIN_BODY_LEN_NO_TAG,
            ))
            .serialize_vec_outer()
            .unwrap()
            .unwrap_a();
        assert_eq!(&buf_0[..], &buf_1[..]);
    }

    #[test]
    fn test_parse_error() {
        // 1 byte shorter than the minimum
        let mut buf = [0u8; ETHERNET_MIN_FRAME_LEN - 1];
        assert!((&mut buf[..])
            .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
            .is_err());

        // 1 byte shorter than the minimum header length still fails even if
        // length checking is disabled
        let mut buf = [0u8; ETHERNET_HDR_LEN_NO_TAG - 1];
        assert!((&mut buf[..])
            .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::NoCheck)
            .is_err());

        // an ethertype of 1500 should be validated as the length of the body
        let mut buf = [0u8; ETHERNET_MIN_FRAME_LEN];
        NetworkEndian::write_u16(
            &mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..],
            ETHERNET_MIN_ILLEGAL_ETHERTYPE - 1,
        );
        assert!((&mut buf[..])
            .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
            .is_err());

        // an ethertype of 1501 is illegal because it's in the range [1501, 1535]
        let mut buf = [0u8; ETHERNET_MIN_FRAME_LEN];
        NetworkEndian::write_u16(
            &mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..],
            ETHERNET_MIN_ILLEGAL_ETHERTYPE,
        );
        assert!((&mut buf[..])
            .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
            .is_err());

        // an ethertype of 1535 is illegal
        let mut buf = [0u8; ETHERNET_MIN_FRAME_LEN];
        NetworkEndian::write_u16(
            &mut buf[ETHERNET_ETHERTYPE_BYTE_OFFSET..],
            ETHERNET_MAX_ILLEGAL_ETHERTYPE,
        );
        assert!((&mut buf[..])
            .parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)
            .is_err());
    }

    #[test]
    #[should_panic(expected = "bytes is below minimum frame size of")]
    fn test_serialize_panic() {
        // create with a body which is below the minimum length
        let mut buf = [0u8; ETHERNET_MIN_FRAME_LEN - 1];
        let mut b = [&mut buf[..]];
        let buf = b.as_fragmented_byte_slice();
        let (header, body, footer) = buf.try_split_contiguous(ETHERNET_HDR_LEN_NO_TAG..).unwrap();
        EthernetFrameBuilder::new(
            Mac::new([0, 1, 2, 3, 4, 5]),
            Mac::new([6, 7, 8, 9, 10, 11]),
            EtherType::Arp,
            ETHERNET_MIN_BODY_LEN_NO_TAG,
        )
        .serialize(&mut SerializeTarget { header, footer }, body);
    }

    #[test]
    fn test_custom_min_body_len() {
        const MIN_BODY_LEN: usize = 4;
        const UNWRITTEN_BYTE: u8 = 0xAA;

        let builder = EthernetFrameBuilder::new(
            Mac::new([0, 1, 2, 3, 4, 5]),
            Mac::new([6, 7, 8, 9, 10, 11]),
            EtherType::Arp,
            MIN_BODY_LEN,
        );

        let mut buffer = [UNWRITTEN_BYTE; ETHERNET_MIN_FRAME_LEN];
        // TODO(https://fxbug.dev/42079821): Don't use this `#[doc(hidden)]`
        // method, and use the public API instead.
        GrowBufferMut::serialize(
            &mut Buf::new(&mut buffer[..], ETHERNET_HDR_LEN_NO_TAG..ETHERNET_HDR_LEN_NO_TAG),
            builder,
        );

        let (header, tail) = buffer.split_at(ETHERNET_HDR_LEN_NO_TAG);
        let (padding, unwritten) = tail.split_at(MIN_BODY_LEN);
        assert_eq!(
            header,
            &[
                6, 7, 8, 9, 10, 11, // dst_mac
                0, 1, 2, 3, 4, 5, // src_mac
                08, 06, // ethertype
            ]
        );
        assert_eq!(padding, &[0; MIN_BODY_LEN]);
        assert_eq!(
            unwritten,
            &[UNWRITTEN_BYTE; ETHERNET_MIN_FRAME_LEN - MIN_BODY_LEN - ETHERNET_HDR_LEN_NO_TAG]
        );
    }
}
