/*
 * Copyright 2014-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



package org.onlab.packet;

import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.packet.ndp.Redirect;
import org.onlab.packet.ndp.RouterAdvertisement;
import org.onlab.packet.ndp.RouterSolicitation;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.packet.PacketUtils.checkHeaderLength;
import static org.onlab.packet.PacketUtils.checkInput;

/**
 * Ethernet Packet.
 */
public class Ethernet extends BasePacket {
    private static final String HEXES = "0123456789ABCDEF";
    private static final String HEX_PROTO = "0x%s";

    public static final short TYPE_ARP = EthType.EtherType.ARP.ethType().toShort();
    public static final short TYPE_RARP = EthType.EtherType.RARP.ethType().toShort();
    public static final short TYPE_IPV4 = EthType.EtherType.IPV4.ethType().toShort();
    public static final short TYPE_IPV6 = EthType.EtherType.IPV6.ethType().toShort();
    public static final short TYPE_LLDP = EthType.EtherType.LLDP.ethType().toShort();
    public static final short TYPE_VLAN = EthType.EtherType.VLAN.ethType().toShort();
    public static final short TYPE_QINQ = EthType.EtherType.QINQ.ethType().toShort();
    public static final short TYPE_BSN = EthType.EtherType.BDDP.ethType().toShort();

    public static final short MPLS_UNICAST = EthType.EtherType.MPLS_UNICAST.ethType().toShort();
    public static final short MPLS_MULTICAST = EthType.EtherType.MPLS_MULTICAST.ethType().toShort();


    public static final short VLAN_UNTAGGED = (short) 0xffff;

    public static final short ETHERNET_HEADER_LENGTH = 14; // bytes
    public static final short VLAN_HEADER_LENGTH = 4; // bytes

    public static final short DATALAYER_ADDRESS_LENGTH = 6; // bytes

    private static final Map<Short, Deserializer<? extends IPacket>> ETHERTYPE_DESERIALIZER_MAP =
            new HashMap<>();

    static {
       for (EthType.EtherType ethType : EthType.EtherType.values()) {
           if (ethType.deserializer() != null) {
               ETHERTYPE_DESERIALIZER_MAP.put(ethType.ethType().toShort(), ethType.deserializer());
           }
       }
    }

    protected MacAddress destinationMACAddress;
    protected MacAddress sourceMACAddress;
    protected byte priorityCode;
    protected byte qInQPriorityCode;
    protected short vlanID;
    protected short qinqVID;
    protected short qinqTPID;
    protected short etherType;
    protected boolean pad = false;

    /**
     * By default, set Ethernet to untagged.
     */
    public Ethernet() {
        super();
        this.vlanID = Ethernet.VLAN_UNTAGGED;
        this.qinqVID = Ethernet.VLAN_UNTAGGED;
        this.qinqTPID = TYPE_QINQ;
    }

    /**
     * Gets the destination MAC address.
     *
     * @return the destination MAC as a byte array
     */
    public byte[] getDestinationMACAddress() {
        return this.destinationMACAddress.toBytes();
    }

    /**
     * Gets the destination MAC address.
     *
     * @return the destination MAC
     */
    public MacAddress getDestinationMAC() {
        return this.destinationMACAddress;
    }

    /**
     * Sets the destination MAC address.
     *
     * @param destMac the destination MAC to set
     * @return the Ethernet frame
     */
    public Ethernet setDestinationMACAddress(final MacAddress destMac) {
        this.destinationMACAddress = checkNotNull(destMac);
        return this;
    }

    /**
     * Sets the destination MAC address.
     *
     * @param destMac the destination MAC to set
     * @return the Ethernet frame
     */
    public Ethernet setDestinationMACAddress(final byte[] destMac) {
        this.destinationMACAddress = MacAddress.valueOf(destMac);
        return this;
    }

    /**
     * Sets the destination MAC address.
     *
     * @param destMac the destination MAC to set
     * @return the Ethernet frame
     */
    public Ethernet setDestinationMACAddress(final String destMac) {
        this.destinationMACAddress = MacAddress.valueOf(destMac);
        return this;
    }

    /**
     * Gets the source MAC address.
     *
     * @return the source MACAddress as a byte array
     */
    public byte[] getSourceMACAddress() {
        return this.sourceMACAddress.toBytes();
    }

    /**
     * Gets the source MAC address.
     *
     * @return the source MACAddress
     */
    public MacAddress getSourceMAC() {
        return this.sourceMACAddress;
    }

    /**
     * Sets the source MAC address.
     *
     * @param sourceMac the source MAC to set
     * @return the Ethernet frame
     */
    public Ethernet setSourceMACAddress(final MacAddress sourceMac) {
        this.sourceMACAddress = checkNotNull(sourceMac);
        return this;
    }

    /**
     * Sets the source MAC address.
     *
     * @param sourceMac the source MAC to set
     * @return the Ethernet frame
     */
    public Ethernet setSourceMACAddress(final byte[] sourceMac) {
        this.sourceMACAddress = MacAddress.valueOf(sourceMac);
        return this;
    }

    /**
     * Sets the source MAC address.
     *
     * @param sourceMac the source MAC to set
     * @return the Ethernet frame
     */
    public Ethernet setSourceMACAddress(final String sourceMac) {
        this.sourceMACAddress = MacAddress.valueOf(sourceMac);
        return this;
    }

    /**
     * Gets the priority code.
     *
     * @return the priorityCode
     */
    public byte getPriorityCode() {
        return this.priorityCode;
    }

    /**
     * Sets the priority code.
     *
     * @param priority the priorityCode to set
     * @return the Ethernet frame
     */
    public Ethernet setPriorityCode(final byte priority) {
        this.priorityCode = priority;
        return this;
    }

    /**
     * Gets the QinQ priority code.
     *
     * @return the qInQPriorityCode
     */
    public byte getQinQPriorityCode() {
        return this.qInQPriorityCode;
    }

    /**
     * Sets the QinQ priority code.
     *
     * @param priority the priorityCode to set
     * @return the Ethernet frame
     */
    public Ethernet setQinQPriorityCode(final byte priority) {
        this.qInQPriorityCode = priority;
        return this;
    }

    /**
     * Gets the VLAN ID.
     *
     * @return the vlanID
     */
    public short getVlanID() {
        return this.vlanID;
    }

    /**
     * Sets the VLAN ID.
     *
     * @param vlan the vlanID to set
     * @return the Ethernet frame
     */
    public Ethernet setVlanID(final short vlan) {
        this.vlanID = vlan;
        return this;
    }

    /**
     * Gets the QinQ VLAN ID.
     *
     * @return the QinQ vlanID
     */
    public short getQinQVID() {
        return this.qinqVID;
    }

    /**
     * Sets the QinQ VLAN ID.
     *
     * @param vlan the vlanID to set
     * @return the Ethernet frame
     */
    public Ethernet setQinQVID(final short vlan) {
        this.qinqVID = vlan;
        return this;
    }
    /**
     * Gets the QinQ TPID.
     *
     * @return the QinQ TPID
     */
    public short getQinQTPID() {
        return this.qinqTPID;
    }

    /**
     * Sets the QinQ TPID.
     *
     * @param tpId the TPID to set
     * @return the Ethernet frame
     */
    public Ethernet setQinQTPID(final short tpId) {
        if (tpId != TYPE_VLAN && tpId != TYPE_QINQ) {
           return null;
        }
        this.qinqTPID = tpId;
        return this;
    }
    /**
     * Gets the Ethernet type.
     *
     * @return the etherType
     */
    public short getEtherType() {
        return this.etherType;
    }

    /**
     * Sets the Ethernet type.
     *
     * @param ethType the etherType to set
     * @return the Ethernet frame
     */
    public Ethernet setEtherType(final short ethType) {
        this.etherType = ethType;
        return this;
    }

    /**
     * @return True if the Ethernet frame is broadcast, false otherwise
     */
    public boolean isBroadcast() {
        assert this.destinationMACAddress.length() == 6;
        return this.destinationMACAddress.isBroadcast();
    }

    /**
     * @return True is the Ethernet frame is multicast, False otherwise
     */
    public boolean isMulticast() {
        return this.destinationMACAddress.isMulticast();
    }

    /**
     * Pad this packet to 60 bytes minimum, filling with zeros?
     *
     * @return the pad
     */
    public boolean isPad() {
        return this.pad;
    }

    /**
     * Pad this packet to 60 bytes minimum, filling with zeros?
     *
     * @param pd
     *            the pad to set
     * @return this
     */
    public Ethernet setPad(final boolean pd) {
        this.pad = pd;
        return this;
    }

    @Override
    public byte[] serialize() {
        byte[] payloadData = null;
        if (this.payload != null) {
            this.payload.setParent(this);
            payloadData = this.payload.serialize();
        }
        int length = 14 + (this.vlanID == Ethernet.VLAN_UNTAGGED ? 0 : 4)
                + (this.qinqVID == Ethernet.VLAN_UNTAGGED ? 0 : 4)
                + (payloadData == null ? 0 : payloadData.length);
        if (this.pad && length < 60) {
            length = 60;
        }
        final byte[] data = new byte[length];
        final ByteBuffer bb = ByteBuffer.wrap(data);
        bb.put(this.destinationMACAddress.toBytes());
        bb.put(this.sourceMACAddress.toBytes());
        if (this.qinqVID != Ethernet.VLAN_UNTAGGED) {
            bb.putShort(this.qinqTPID);
            bb.putShort((short) (this.qInQPriorityCode << 13 | this.qinqVID & 0x0fff));
        }
        if (this.vlanID != Ethernet.VLAN_UNTAGGED) {
            bb.putShort(TYPE_VLAN);
            bb.putShort((short) (this.priorityCode << 13 | this.vlanID & 0x0fff));
        }
        bb.putShort(this.etherType);
        if (payloadData != null) {
            bb.put(payloadData);
        }
        if (this.pad) {
            Arrays.fill(data, bb.position(), data.length, (byte) 0x0);
        }
        return data;
    }

    @Override
    public IPacket deserialize(final byte[] data, final int offset,
                               final int length) {
        if (length <= 0) {
            return null;
        }
        final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
        if (this.destinationMACAddress == null) {
            this.destinationMACAddress = MacAddress.valueOf(new byte[6]);
        }
        final byte[] dstAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
        bb.get(dstAddr);
        this.destinationMACAddress = MacAddress.valueOf(dstAddr);

        if (this.sourceMACAddress == null) {
            this.sourceMACAddress = MacAddress.valueOf(new byte[6]);
        }
        final byte[] srcAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
        bb.get(srcAddr);
        this.sourceMACAddress = MacAddress.valueOf(srcAddr);

        short ethType = bb.getShort();
        if (ethType == TYPE_QINQ) {
            final short tci = bb.getShort();
            this.qInQPriorityCode = (byte) (tci >> 13 & 0x07);
            this.qinqVID = (short) (tci & 0x0fff);
            this.qinqTPID = TYPE_QINQ;
            ethType = bb.getShort();
        }

        if (ethType == TYPE_VLAN) {
            final short tci = bb.getShort();
            this.priorityCode = (byte) (tci >> 13 & 0x07);
            this.vlanID = (short) (tci & 0x0fff);
            ethType = bb.getShort();

            // there might be one more tag with 1q TPID
            if (ethType == TYPE_VLAN) {
                // packet is double tagged with 1q TPIDs
                // We handle only double tagged packets here and assume that in this case
                // TYPE_QINQ above was not hit
                // We put the values retrieved above with TYPE_VLAN in
                // qInQ fields
                this.qInQPriorityCode = this.priorityCode;
                this.qinqVID = this.vlanID;
                this.qinqTPID = TYPE_VLAN;

                final short innerTci = bb.getShort();
                this.priorityCode = (byte) (innerTci >> 13 & 0x07);
                this.vlanID = (short) (innerTci & 0x0fff);
                ethType = bb.getShort();
            }
        } else {
            this.vlanID = Ethernet.VLAN_UNTAGGED;
        }
        this.etherType = ethType;

        IPacket payload;
        Deserializer<? extends IPacket> deserializer;
        if (Ethernet.ETHERTYPE_DESERIALIZER_MAP.containsKey(ethType)) {
            deserializer = Ethernet.ETHERTYPE_DESERIALIZER_MAP.get(ethType);
        } else {
            deserializer = Data.deserializer();
        }
        try {
            this.payload = deserializer.deserialize(data, bb.position(),
                                                    bb.limit() - bb.position());
            this.payload.setParent(this);
        } catch (DeserializationException e) {
            return this;
        }
        return this;
    }

    /**
     * Checks to see if a string is a valid MAC address.
     *
     * @param macAddress string to test if it is a valid MAC
     * @return True if macAddress is a valid MAC, False otherwise
     */
    public static boolean isMACAddress(final String macAddress) {
        final String[] macBytes = macAddress.split(":");
        if (macBytes.length != 6) {
            return false;
        }
        for (int i = 0; i < 6; ++i) {
            if (Ethernet.HEXES.indexOf(macBytes[i].toUpperCase().charAt(0)) == -1
                    || Ethernet.HEXES.indexOf(macBytes[i].toUpperCase().charAt(
                            1)) == -1) {
                return false;
            }
        }
        return true;
    }

    /**
     * Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
     * matter, and returns a corresponding byte[].
     *
     * @param macAddress
     *            The MAC address to convert into a byte array
     * @return The macAddress as a byte array
     */
    public static byte[] toMACAddress(final String macAddress) {
        return MacAddress.valueOf(macAddress).toBytes();
    }

    /**
     * Accepts a MAC address and returns the corresponding long, where the MAC
     * bytes are set on the lower order bytes of the long.
     *
     * @param macAddress MAC address as a byte array
     * @return a long containing the mac address bytes
     */
    public static long toLong(final byte[] macAddress) {
        return MacAddress.valueOf(macAddress).toLong();
    }

    /**
     * Converts a long MAC address to a byte array.
     *
     * @param macAddress MAC address set on the lower order bytes of the long
     * @return the bytes of the mac address
     */
    public static byte[] toByteArray(final long macAddress) {
        return MacAddress.valueOf(macAddress).toBytes();
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 7867;
        int result = super.hashCode();
        result = prime * result + this.destinationMACAddress.hashCode();
        result = prime * result + this.etherType;
        result = prime * result + this.qinqVID;
        result = prime * result + this.qInQPriorityCode;
        result = prime * result + this.vlanID;
        result = prime * result + this.priorityCode;
        result = prime * result + (this.pad ? 1231 : 1237);
        result = prime * result + this.sourceMACAddress.hashCode();
        return result;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!super.equals(obj)) {
            return false;
        }
        if (!(obj instanceof Ethernet)) {
            return false;
        }
        final Ethernet other = (Ethernet) obj;
        if (!this.destinationMACAddress.equals(other.destinationMACAddress)) {
            return false;
        }
        if (this.qInQPriorityCode != other.qInQPriorityCode) {
            return false;
        }
        if (this.qinqVID != other.qinqVID) {
            return false;
        }
        if (this.priorityCode != other.priorityCode) {
            return false;
        }
        if (this.vlanID != other.vlanID) {
            return false;
        }
        if (this.etherType != other.etherType) {
            return false;
        }
        if (this.pad != other.pad) {
            return false;
        }
        if (!this.sourceMACAddress.equals(other.sourceMACAddress)) {
            return false;
        }
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#toString(java.lang.Object)
     */
    @Override
    public String toString() {

        final StringBuffer sb = new StringBuffer("\n");

        final IPacket pkt = this.getPayload();

        if (pkt instanceof ARP) {
            sb.append("arp");
        } else if (pkt instanceof LLDP) {
            sb.append("lldp");
        } else if (pkt instanceof ICMP) {
            sb.append("icmp");
        } else if (pkt instanceof IPv4) {
            sb.append("ip");
        } else if (pkt instanceof DHCP) {
            sb.append("dhcp");
        } else {
            /*
             * When we don't know the protocol, we print using
             * the well known hex format instead of a decimal
             * value.
             */
            sb.append(String.format(HEX_PROTO,
                                    Integer.toHexString(this.getEtherType() & 0xffff)));
        }

        if (this.getQinQVID() != Ethernet.VLAN_UNTAGGED) {
            sb.append("\ndl_qinqVlan: ");
            sb.append(this.getQinQVID());
            sb.append("\ndl_qinqVlan_pcp: ");
            sb.append(this.getQinQPriorityCode());
        }

        sb.append("\ndl_vlan: ");
        if (this.getVlanID() == Ethernet.VLAN_UNTAGGED) {
            sb.append("untagged");
        } else {
            sb.append(this.getVlanID());
        }
        sb.append("\ndl_vlan_pcp: ");
        sb.append(this.getPriorityCode());
        sb.append("\ndl_src: ");
        sb.append(bytesToHex(this.getSourceMACAddress()));
        sb.append("\ndl_dst: ");
        sb.append(bytesToHex(this.getDestinationMACAddress()));

        if (pkt instanceof ARP) {
            final ARP p = (ARP) pkt;
            sb.append("\nnw_src: ");
            sb.append(IPv4.fromIPv4Address(IPv4.toIPv4Address(p
                    .getSenderProtocolAddress())));
            sb.append("\nnw_dst: ");
            sb.append(IPv4.fromIPv4Address(IPv4.toIPv4Address(p
                    .getTargetProtocolAddress())));
        } else if (pkt instanceof LLDP) {
            sb.append("lldp packet");
        } else if (pkt instanceof ICMP) {
            final ICMP icmp = (ICMP) pkt;
            sb.append("\nicmp_type: ");
            sb.append(icmp.getIcmpType());
            sb.append("\nicmp_code: ");
            sb.append(icmp.getIcmpCode());
        } else if (pkt instanceof IPv4) {
            final IPv4 p = (IPv4) pkt;
            sb.append("\nnw_src: ");
            sb.append(IPv4.fromIPv4Address(p.getSourceAddress()));
            sb.append("\nnw_dst: ");
            sb.append(IPv4.fromIPv4Address(p.getDestinationAddress()));
            sb.append("\nnw_tos: ");
            sb.append(p.getDiffServ());
            sb.append("\nnw_proto: ");
            sb.append(p.getProtocol());

            IPacket payload = pkt.getPayload();
            if (payload != null) {
                if (payload instanceof TCP) {
                    sb.append("\ntp_src: ");
                    sb.append(((TCP) payload).getSourcePort());
                    sb.append("\ntp_dst: ");
                    sb.append(((TCP) payload).getDestinationPort());

                } else if (payload instanceof UDP) {
                    sb.append("\ntp_src: ");
                    sb.append(((UDP) payload).getSourcePort());
                    sb.append("\ntp_dst: ");
                    sb.append(((UDP) payload).getDestinationPort());
                } else if (payload instanceof ICMP) {
                    final ICMP icmp = (ICMP) payload;
                    sb.append("\nicmp_type: ");
                    sb.append(icmp.getIcmpType());
                    sb.append("\nicmp_code: ");
                    sb.append(icmp.getIcmpCode());
                }
            }
        } else if (pkt instanceof IPv6) {
            final IPv6 ipv6 = (IPv6) pkt;
            sb.append("\nipv6_src: ");
            sb.append(Ip6Address.valueOf(ipv6.getSourceAddress()).toString());
            sb.append("\nipv6_dst: ");
            sb.append(Ip6Address.valueOf(ipv6.getDestinationAddress()).toString());
            sb.append("\nipv6_proto: ");
            sb.append(ipv6.getNextHeader());

            IPacket payload = pkt.getPayload();
            if (payload != null && payload instanceof ICMP6) {
                final ICMP6 icmp6 = (ICMP6) payload;
                sb.append("\nicmp6_type: ");
                sb.append(icmp6.getIcmpType());
                sb.append("\nicmp6_code: ");
                sb.append(icmp6.getIcmpCode());

                payload = payload.getPayload();
                if (payload != null) {
                    if (payload instanceof NeighborSolicitation) {
                        final NeighborSolicitation ns = (NeighborSolicitation) payload;
                        sb.append("\nns_target_addr: ");
                        sb.append(Ip6Address.valueOf(ns.getTargetAddress()).toString());
                        ns.getOptions().forEach(option -> {
                            sb.append("\noption_type: ");
                            sb.append(option.type());
                            sb.append("\noption_data: ");
                            sb.append(bytesToHex(option.data()));
                        });
                    } else if (payload instanceof NeighborAdvertisement) {
                        final NeighborAdvertisement na = (NeighborAdvertisement) payload;
                        sb.append("\nna_target_addr: ");
                        sb.append(Ip6Address.valueOf(na.getTargetAddress()).toString());
                        sb.append("\nna_solicited_flag: ");
                        sb.append(na.getSolicitedFlag());
                        sb.append("\nna_router_flag: ");
                        sb.append(na.getRouterFlag());
                        sb.append("\nna_override_flag: ");
                        sb.append(na.getOverrideFlag());
                        na.getOptions().forEach(option -> {
                            sb.append("\noption_type: ");
                            sb.append(option.type());
                            sb.append("\noption_data: ");
                            sb.append(bytesToHex(option.data()));
                        });
                    } else if (payload instanceof RouterSolicitation) {
                        final RouterSolicitation rs = (RouterSolicitation) payload;
                        sb.append("\nrs");
                        rs.getOptions().forEach(option -> {
                            sb.append("\noption_type: ");
                            sb.append(option.type());
                            sb.append("\noption_data: ");
                            sb.append(bytesToHex(option.data()));
                        });
                    } else if (payload instanceof RouterAdvertisement) {
                        final RouterAdvertisement ra = (RouterAdvertisement) payload;
                        sb.append("\nra_hop_limit: ");
                        sb.append(ra.getCurrentHopLimit());
                        sb.append("\nra_mflag: ");
                        sb.append(ra.getMFlag());
                        sb.append("\nra_oflag: ");
                        sb.append(ra.getOFlag());
                        sb.append("\nra_reachable_time: ");
                        sb.append(ra.getReachableTime());
                        sb.append("\nra_retransmit_time: ");
                        sb.append(ra.getRetransmitTimer());
                        sb.append("\nra_router_lifetime: ");
                        sb.append(ra.getRouterLifetime());
                        ra.getOptions().forEach(option -> {
                            sb.append("\noption_type: ");
                            sb.append(option.type());
                            sb.append("\noption_data: ");
                            sb.append(bytesToHex(option.data()));
                        });
                    } else if (payload instanceof Redirect) {
                        final Redirect rd = (Redirect) payload;
                        sb.append("\nrd_target_addr: ");
                        sb.append(Ip6Address.valueOf(rd.getTargetAddress()).toString());
                        rd.getOptions().forEach(option -> {
                            sb.append("\noption_type: ");
                            sb.append(option.type());
                            sb.append("\noption_data: ");
                            sb.append(bytesToHex(option.data()));
                        });
                    }
                }
            }
        } else if (pkt instanceof DHCP) {
            sb.append("\ndhcp packet");
        } else if (pkt instanceof Data) {
            sb.append("\ndata packet");
        } else if (pkt instanceof LLC) {
            sb.append("\nllc packet");
        } else {
            sb.append("\nunknown packet");
        }

        return sb.toString();
    }

    public static String bytesToHex(byte[] in) {
        final StringBuilder builder = new StringBuilder();
        for (byte b : in) {
            builder.append(String.format("%02x", b));
        }
        return builder.toString();
    }

    /**
     * Deserializer function for Ethernet packets.
     *
     * @return deserializer function
     */
    public static Deserializer<Ethernet> deserializer() {
        return (data, offset, length) -> {
            checkInput(data, offset, length, ETHERNET_HEADER_LENGTH);

            byte[] addressBuffer = new byte[DATALAYER_ADDRESS_LENGTH];

            ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            Ethernet eth = new Ethernet();
            // Read destination MAC address into buffer
            bb.get(addressBuffer);
            eth.setDestinationMACAddress(addressBuffer);

            // Read source MAC address into buffer
            bb.get(addressBuffer);
            eth.setSourceMACAddress(addressBuffer);

            short ethType = bb.getShort();
            if (ethType == TYPE_QINQ) {
                // in this case we excpect 2 VLAN headers
                checkHeaderLength(length, ETHERNET_HEADER_LENGTH + VLAN_HEADER_LENGTH + VLAN_HEADER_LENGTH);
                final short tci = bb.getShort();
                eth.setQinQPriorityCode((byte) (tci >> 13 & 0x07));
                eth.setQinQVID((short) (tci & 0x0fff));
                eth.setQinQTPID(TYPE_QINQ);
                ethType = bb.getShort();
            }
            if (ethType == TYPE_VLAN) {
                checkHeaderLength(length, ETHERNET_HEADER_LENGTH + VLAN_HEADER_LENGTH);
                final short tci = bb.getShort();
                eth.setPriorityCode((byte) (tci >> 13 & 0x07));
                eth.setVlanID((short) (tci & 0x0fff));
                ethType = bb.getShort();

                if (ethType == TYPE_VLAN) {
                    // We handle only double tagged packets here and assume that in this case
                    // TYPE_QINQ above was not hit
                    // We put the values retrieved above with TYPE_VLAN in
                    // qInQ fields
                    checkHeaderLength(length, ETHERNET_HEADER_LENGTH + VLAN_HEADER_LENGTH);
                    eth.setQinQPriorityCode(eth.getPriorityCode());
                    eth.setQinQVID(eth.getVlanID());
                    eth.setQinQTPID(TYPE_VLAN);

                    final short innerTci = bb.getShort();
                    eth.setPriorityCode((byte) (innerTci >> 13 & 0x07));
                    eth.setVlanID((short) (innerTci & 0x0fff));
                    ethType = bb.getShort();
                }
            } else {
                eth.setVlanID(Ethernet.VLAN_UNTAGGED);
            }
            eth.setEtherType(ethType);

            IPacket payload;
            Deserializer<? extends IPacket> deserializer;
            if (Ethernet.ETHERTYPE_DESERIALIZER_MAP.containsKey(ethType)) {
                deserializer = Ethernet.ETHERTYPE_DESERIALIZER_MAP.get(ethType);
            } else {
                deserializer = Data.deserializer();
            }
            payload = deserializer.deserialize(data, bb.position(),
                                               bb.limit() - bb.position());
            payload.setParent(eth);
            eth.setPayload(payload);

            return eth;
        };
    }
}
