/*******************************************************************************
 * Copyright 2014 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 net.onrc.onos.core.packet;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import net.onrc.onos.core.util.SwitchPort;

import org.apache.commons.lang3.ArrayUtils;

import com.google.common.base.Charsets;

/**
 * LLDP packets ONOS uses for discovery of physical network topology.
 * Refer to IEEE Std 802.1ABTM-2009 for more information.
 *
 */
public class OnosLldp extends LLDP {

    // ON.Lab OUI and ONOS name for organizationally specific TLVs
    static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05};
    public static final String ONOS_NAME = "ONOSVirteX";
    static final byte[] LLDP_NICIRA = {0x01, 0x23, 0x20, 0x00, 0x00,
            0x01};
    static final byte[] LLDP_MULTICAST = {0x01, (byte) 0x80,
            (byte) 0xc2, 0x00, 0x00, 0x0e};
    static final byte[] BDDP_MULTICAST = {(byte) 0xff, (byte) 0xff,
            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
    public static final short ETHERTYPE_VLAN = (short) 0x8100;

    // TLV constants: type, size and subtype
    // Organizationally specific TLV also have packet offset and contents of TLV
    // header
    private static final byte CHASSIS_TLV_TYPE = 1;
    private static final byte CHASSIS_TLV_SIZE = 7;
    private static final byte CHASSIS_TLV_SUBTYPE = 4;

    private static final byte PORT_TLV_TYPE = 2;
    private static final byte PORT_TLV_SIZE = 3;
    private static final byte PORT_TLV_SUBTYPE = 2;

    private static final byte TTL_TLV_TYPE = 3;
    private static final byte TTL_TLV_SIZE = 2;

    private static final byte NAME_TLV_TYPE = 127;
    // 4 = OUI (3) + subtype (1)
    private static final byte NAME_TLV_SIZE = (byte) (4 + OnosLldp.ONOS_NAME.length());
    private static final byte NAME_TLV_SUBTYPE = 1;
    private static final short NAME_TLV_OFFSET = 32;
    private static final short NAME_TLV_HEADER = (short) ((NAME_TLV_TYPE << 9) | (NAME_TLV_SIZE & 0xff));
    // Contents of full name TLV
    private static final byte[] NAME_TLV = ByteBuffer.allocate(NAME_TLV_SIZE + 2)
            .putShort(NAME_TLV_HEADER).put(ONLAB_OUI).put(NAME_TLV_SUBTYPE)
            .put(ONOS_NAME.getBytes(Charsets.UTF_8)).array();

    private static final byte DPID_TLV_TYPE = 127;
    private static final byte DPID_TLV_SIZE = (byte) (12); // 12 = OUI (3) + subtype
                                                     // (1) + dpid (8)
    private static final byte DPID_TLV_SUBTYPE = 2;
    private static final short DPID_TLV_HEADER = (short) ((DPID_TLV_TYPE << 9) | DPID_TLV_SIZE);
    // Contents of dpid TLV
    // Note that this does *not* contain the actual dpid since we cannot match
    // on it
    private static final byte[] DPID_TLV = ByteBuffer.allocate(DPID_TLV_SIZE + 2 - 8)
            .putShort(DPID_TLV_HEADER).put(ONLAB_OUI).put(DPID_TLV_SUBTYPE)
            .array();

    // Pre-built contents of both organizationally specific TLVs
    private static final byte[] OUI_TLV = ArrayUtils.addAll(NAME_TLV, DPID_TLV);

    // Default switch, port number and TTL
    private static final byte[] DEFAULT_DPID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00 };
    private static final short DEFAULT_PORT = 0;
    private static final short DEFAULT_TTL = 120; // in seconds

    // Minimum and ONOS-generated LLDP packet sizes
    private static final short MINIMUM_LLDP_SIZE = 61;
    // Add 12 for 2-byte header of each TLV and a single EndOfLLDPTLV
    private static final short ONOS_LLDP_SIZE = (short) (CHASSIS_TLV_SIZE
            + PORT_TLV_SIZE + TTL_TLV_SIZE + NAME_TLV_SIZE + DPID_TLV_SIZE + 12);

    // Direction TLVs are used to indicate if the LLDPs were sent
    // periodically or in response to a received LLDP
    private static final byte TLV_DIRECTION_TYPE = 0x73;
    private static final short TLV_DIRECTION_LENGTH = 1;  // 1 byte
    private static final byte[] TLV_DIRECTION_VALUE_FORWARD = {0x01};
    private static final byte[] TLV_DIRECTION_VALUE_REVERSE = {0x02};
    private static final LLDPTLV FORWARD_TLV
            = new LLDPTLV().
            setType(TLV_DIRECTION_TYPE).
            setLength(TLV_DIRECTION_LENGTH).
            setValue(TLV_DIRECTION_VALUE_FORWARD);

    private static final LLDPTLV REVERSE_TLV
            = new LLDPTLV().
            setType(TLV_DIRECTION_TYPE).
            setLength(TLV_DIRECTION_LENGTH).
            setValue(TLV_DIRECTION_VALUE_REVERSE);

    // Field offsets in ONOS-generated LLDP
    private static final short ETHERTYPE_OFFSET = 12;
    private static final short PORT_OFFSET = 26;
    private static final short DPID_OFFSET = 54;

    // Private member fields
    // Byte arrays for TLV information string
    private byte[] chassisId = new byte[CHASSIS_TLV_SIZE];
    private byte[] portId = new byte[PORT_TLV_SIZE];
    private byte[] ttl = new byte[TTL_TLV_SIZE];
    private byte[] ouiName = new byte[NAME_TLV_SIZE];
    private byte[] ouiDpid = new byte[DPID_TLV_SIZE];

    // TLVs
    private LLDPTLV chassisTLV;
    private LLDPTLV portTLV;
    private LLDPTLV ttlTLV;
    private LLDPTLV ouiNameTLV;
    private LLDPTLV ouiDpidTLV;
    private List<LLDPTLV> optionalTLVList;

    /**
     * Instantiates a new ONOS LDDP message.
     */
    public OnosLldp() {
        // Create TLVs
        this.chassisTLV = new LLDPTLV();
        this.portTLV = new LLDPTLV();
        this.ttlTLV = new LLDPTLV();
        this.ouiNameTLV = new LLDPTLV();
        this.ouiDpidTLV = new LLDPTLV();
        this.optionalTLVList = new LinkedList<LLDPTLV>();
        this.optionalTLVList.add(this.ouiNameTLV);
        this.optionalTLVList.add(this.ouiDpidTLV);

        // Add TLVs to LLDP packet
        this.setChassisId(this.chassisTLV);
        this.setPortId(this.portTLV);
        this.setTtl(this.ttlTLV);
        this.setOptionalTLVList(this.optionalTLVList);

        // Set TLVs to default values
        this.setChassisTLV(DEFAULT_DPID);
        this.setPortTLV(DEFAULT_PORT);
        this.setTTLTLV(DEFAULT_TTL);
        this.setOUIName(OnosLldp.ONOS_NAME);
        this.setOUIDpid(DEFAULT_DPID);
    }

    /**
     * Sets chassis TLV. Note that we can only put 6 bytes in the chassis ID, so
     * we use another organizationally specific TLV to put the full dpid (see
     * setOUIDpid()).
     *
     * @param dpid the switch DPID
     */
    private void setChassisTLV(final byte[] dpid) {
        ByteBuffer bb = ByteBuffer.wrap(this.chassisId);
        bb.put(CHASSIS_TLV_SUBTYPE);
        for (int i = 2; i < 8; i++) {
            bb.put(dpid[i]);
        }

        this.chassisTLV.setLength(CHASSIS_TLV_SIZE);
        this.chassisTLV.setType(CHASSIS_TLV_TYPE);
        this.chassisTLV.setValue(this.chassisId);
    }

    /**
     * Sets port TLV.
     *
     * @param portNumber the port number
     */
    private void setPortTLV(final short portNumber) {
        ByteBuffer bb = ByteBuffer.wrap(this.portId);
        bb.put(PORT_TLV_SUBTYPE);
        bb.putShort(portNumber);

        this.portTLV.setLength(PORT_TLV_SIZE);
        this.portTLV.setType(PORT_TLV_TYPE);
        this.portTLV.setValue(this.portId);
    }

    /**
     * Sets Time To Live TLV.
     *
     * @param time the time to live
     */
    private void setTTLTLV(final short time) {
        ByteBuffer bb = ByteBuffer.wrap(this.ttl);
        bb.putShort(time);

        this.ttlTLV.setLength(TTL_TLV_SIZE);
        this.ttlTLV.setType(TTL_TLV_TYPE);
        this.ttlTLV.setValue(this.ttl);
    }

    /**
     * Sets organizationally specific TLV for ONOS name (subtype 1).
     *
     * @param name the name
     */
    private void setOUIName(final String name) {
        ByteBuffer bb = ByteBuffer.wrap(ouiName);
        bb.put(OnosLldp.ONLAB_OUI);
        bb.put(NAME_TLV_SUBTYPE);
        bb.put(name.getBytes(Charsets.UTF_8));

        this.ouiNameTLV.setLength(NAME_TLV_SIZE);
        this.ouiNameTLV.setType(NAME_TLV_TYPE);
        this.ouiNameTLV.setValue(ouiName);
    }

    /**
     * Sets organizationally specific TLV for ONOS full dpid (subtype 2).
     *
     * @param dpid the switch DPID
     */
    private void setOUIDpid(final byte[] dpid) {
        ByteBuffer bb = ByteBuffer.wrap(ouiDpid);
        bb.put(OnosLldp.ONLAB_OUI);
        bb.put(DPID_TLV_SUBTYPE);
        bb.put(dpid);

        this.ouiDpidTLV.setLength(DPID_TLV_SIZE);
        this.ouiDpidTLV.setType(DPID_TLV_TYPE);
        this.ouiDpidTLV.setValue(ouiDpid);
    }

    /**
     * Sets switch DPID in LLDP packet.
     *
     * @param dpid the switch dpid
     */
    public void setSwitch(Long dpid) {
        final byte[] byteDpid = ByteBuffer.allocate(8).putLong(dpid)
                .array();
        this.setChassisTLV(byteDpid);
        this.setOUIDpid(byteDpid);
    }


    /**
     * Sets the port number in LLDP packet.
     *
     * @param portNumber the port number
     */
    public void setPort(short portNumber) {
        this.setPortTLV(portNumber);
    }

    /**
     * Sets whether this is a forward or reverse LLDP.
     *
     * @param isReverse true if reverse, false if forward
     */
    public void setReverse(boolean isReverse) {
        optionalTLVList.add((isReverse) ? REVERSE_TLV : FORWARD_TLV);
    }

    /**
     * Serializes full LLDP packet to byte array.
     *
     * @return the serialized packet
     */
    @Override
    public byte[] serialize() {
        return super.serialize();
    }

    /**
     * Checks if LLDP packet has correct size, LLDP multicast address, and
     * ethertype. Packet assumed to have Ethernet header.
     *
     * @param packet full packet starting from the Ethernet header
     * @return true if packet is LLDP, false otherwise
     */
    public static boolean isLLDP(final byte[] packet) {
        // Does packet exist and does it have the mininum size?
        if (packet == null || packet.length < MINIMUM_LLDP_SIZE) {
            return false;
        }

        // Packet has LLDP multicast destination address?
        final ByteBuffer bb = ByteBuffer.wrap(packet);
        final byte[] dst = new byte[6];
        bb.get(dst);

        if (!(Arrays.equals(dst, OnosLldp.LLDP_NICIRA)
                || Arrays.equals(dst, OnosLldp.LLDP_MULTICAST) || Arrays.equals(
                dst, OnosLldp.BDDP_MULTICAST))) {

            return false;
        }

        // Fetch ethertype, skip VLAN tag if it's there
        short etherType = bb.getShort(ETHERTYPE_OFFSET);
        if (etherType == ETHERTYPE_VLAN) {
            etherType = bb.getShort(ETHERTYPE_OFFSET + 4);
        }

        // Check ethertype
        if (etherType == Ethernet.TYPE_LLDP) {
            return true;
        }
        if (etherType == Ethernet.TYPE_BSN) {
            return true;
        }

        return false;

    }

    /**
     * Checks if packet has size of ONOS-generated LLDP, and correctness of two
     * organizationally specific TLVs that use ON.Lab's OUI. Assumes packet is
     * valid LLDP packet
     *
     * @param packet full packet starting from the Ethernet header
     * @return true if this is an ONOS-generated LLDP, otherwise false
     */
    public static boolean isOnosLldp(byte[] packet) {
        if (packet.length < ONOS_LLDP_SIZE) {
            return false;
        }

        // Extra offset due to VLAN tag
        final ByteBuffer bb = ByteBuffer.wrap(packet);
        int offset = 0;
        if (bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_LLDP
                && bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_BSN) {
            offset = 4;
        }

        // Compare packet's organizationally specific TLVs to the expected
        // values
        for (int i = 0; i < OUI_TLV.length; i++) {
            if (packet[NAME_TLV_OFFSET + offset + i] != OUI_TLV[i]) {
                return false;
            }
        }

        return true;
    }

    /**
     * Extracts dpid and port from ONOS-generated LLDP packet.
     *
     * @param packet full packet started at the Ethernet header
     * @return switchport switch and port info from the DPID and Port TLVs
     */
    public static SwitchPort extractSwitchPort(final byte[] packet) {
        final ByteBuffer bb = ByteBuffer.wrap(packet);

        // Extra offset due to VLAN tag
        int offset = 0;
        if (bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_LLDP
                && bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_BSN) {
            offset = 4;
        }

        final short port = bb.getShort(PORT_OFFSET + offset);
        final long dpid = bb.getLong(DPID_OFFSET + offset);

        return new SwitchPort(dpid, port);
    }

    /**
     * Checks if the LLDP is a reverse LLDP (i.e. sent in response to receiving
     * an LLDP on the link). This information is stored in the Direction TLV.
     *
     * @param lldp parsed LLDP packet
     * @return true if the LLDP is a reverse LLDP, otherwise false
     */
    public static boolean isReverse(final LLDP lldp) {
        for (LLDPTLV lldpTlv : lldp.getOptionalTLVList()) {
            if ((lldpTlv.getType() == TLV_DIRECTION_TYPE) &&
                    Arrays.equals(lldpTlv.getValue(), TLV_DIRECTION_VALUE_REVERSE)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if (!super.equals(other)) {
            return false;
        }
        //
        // NOTE: Subclasses are are considered as change of identity, hence
        // equals() will return false if the class type doesn't match.
        //
        if (getClass() != other.getClass()) {
            return false;
        }

        OnosLldp otherLldp = (OnosLldp) other;

        if (!this.chassisTLV.equals(otherLldp.chassisTLV)) {
            return false;
        }

        if (!this.portTLV.equals(otherLldp.portTLV)) {
            return false;
        }

        if (!this.ttlTLV.equals(otherLldp.ttlTLV)) {
            return false;
        }

        if (!this.ouiNameTLV.equals(otherLldp.ouiNameTLV)) {
            return false;
        }

        if (!this.ouiDpidTLV.equals(otherLldp.ouiDpidTLV)) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + chassisTLV.hashCode();
        result = prime * result + portTLV.hashCode();
        result = prime * result + ttlTLV.hashCode();
        result = prime * result + ouiNameTLV.hashCode();
        result = prime * result + ouiDpidTLV.hashCode();

        return result;
    }
}
