/*******************************************************************************
 * 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.lang.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 sw 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 port 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
     */
    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;
    }
}
