/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.opencord.dhcpl2relay.packet;

import org.onlab.packet.ARP;
import org.onlab.packet.BasePacket;
import org.onlab.packet.DHCP;
import org.onlab.packet.Data;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Deserializer;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPacket;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.LLC;
import org.onlab.packet.LLDP;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TCP;
import org.onlab.packet.UDP;
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 DhcpEthernet 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 DhcpEthernet() {
        super();
        this.vlanID = org.onlab.packet.Ethernet.VLAN_UNTAGGED;
        this.qinqVid = org.onlab.packet.Ethernet.VLAN_UNTAGGED;
        this.qinqTPid = TYPE_QINQ;
    }

    public DhcpEthernet(org.onlab.packet.Ethernet eth) {
        super();
        this.destinationMacAddress = eth.getDestinationMAC();
        this.sourceMacAddress = eth.getSourceMAC();
        this.priorityCode = eth.getPriorityCode();
        this.vlanID = eth.getVlanID();
        this.etherType = eth.getEtherType();
        this.pad = eth.isPad();
        this.payload = eth.getPayload();
        this.payload.setParent(this);
        this.qinqVid = Ethernet.VLAN_UNTAGGED;
        this.qinqTPid = TYPE_QINQ;
        //this.parent = eth.getParent();
    }


    /**
     * 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 DhcpEthernet 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 == org.onlab.packet.Ethernet.VLAN_UNTAGGED ? 0 : 4)
                + (this.qinqVid == org.onlab.packet.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 != org.onlab.packet.Ethernet.VLAN_UNTAGGED) {
            bb.putShort(this.qinqTPid);
            bb.putShort((short) (this.qInQPriorityCode << 13 | this.qinqVid & 0x0fff));
        }
        if (this.vlanID != org.onlab.packet.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 = org.onlab.packet.Ethernet.VLAN_UNTAGGED;
        }
        this.etherType = ethType;

        IPacket payload;
        Deserializer<? extends IPacket> deserializer;
        if (DhcpEthernet.ETHERTYPE_DESERIALIZER_MAP.containsKey(ethType)) {
            deserializer = 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 (DhcpEthernet.HEXES.indexOf(macBytes[i].toUpperCase().charAt(0)) == -1
                    || 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 DhcpEthernet)) {
            return false;
        }
        final DhcpEthernet other = (DhcpEthernet) 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() != org.onlab.packet.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() == org.onlab.packet.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<DhcpEthernet> 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);
            DhcpEthernet eth = new DhcpEthernet();
            // 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(org.onlab.packet.Ethernet.VLAN_UNTAGGED);
            }
            eth.setEtherType(ethType);

            IPacket payload;
            Deserializer<? extends IPacket> deserializer;
            if (DhcpEthernet.ETHERTYPE_DESERIALIZER_MAP.containsKey(ethType)) {
                deserializer = DhcpEthernet.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;
        };
    }
}
