/*
 * 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.onosproject.drivers.hp;

import org.onlab.packet.Ethernet;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.slf4j.Logger;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Driver for HP3500 hybrid switches employing V1 hardware module.
 *
 * Refer to the device manual to check unsupported features and features supported in hardware
 *
 */

public class HPPipelineV3500 extends AbstractHPPipeline {

    private Logger log = getLogger(getClass());

    @Override
    protected FlowRule.Builder setDefaultTableIdForFlowObjective(FlowRule.Builder ruleBuilder) {
        log.debug("HP V3500 Driver - Setting default table id to software table {}", HP_SOFTWARE_TABLE);

        return ruleBuilder.forTable(HP_SOFTWARE_TABLE);
    }

    @Override
    protected void initUnSupportedFeatures() {
        //Initialize unsupported criteria
        unsupportedCriteria.add(Criterion.Type.METADATA);
        unsupportedCriteria.add(Criterion.Type.IP_ECN);
        unsupportedCriteria.add(Criterion.Type.SCTP_SRC);
        unsupportedCriteria.add(Criterion.Type.SCTP_SRC_MASKED);
        unsupportedCriteria.add(Criterion.Type.SCTP_DST);
        unsupportedCriteria.add(Criterion.Type.SCTP_DST_MASKED);
        unsupportedCriteria.add(Criterion.Type.IPV6_ND_SLL);
        unsupportedCriteria.add(Criterion.Type.IPV6_ND_TLL);
        unsupportedCriteria.add(Criterion.Type.MPLS_LABEL);
        unsupportedCriteria.add(Criterion.Type.MPLS_TC);
        unsupportedCriteria.add(Criterion.Type.MPLS_BOS);
        unsupportedCriteria.add(Criterion.Type.PBB_ISID);
        unsupportedCriteria.add(Criterion.Type.TUNNEL_ID);
        unsupportedCriteria.add(Criterion.Type.IPV6_EXTHDR);

        //Initialize unsupported instructions
        unsupportedInstructions.add(Instruction.Type.QUEUE);
        unsupportedInstructions.add(Instruction.Type.METADATA);
        unsupportedInstructions.add(Instruction.Type.L0MODIFICATION);
        unsupportedInstructions.add(Instruction.Type.L1MODIFICATION);
        unsupportedInstructions.add(Instruction.Type.PROTOCOL_INDEPENDENT);
        unsupportedInstructions.add(Instruction.Type.EXTENSION);
        unsupportedInstructions.add(Instruction.Type.STAT_TRIGGER);

        //Initialize unsupported L2MODIFICATION actions
        unsupportedL2mod.add(L2ModificationInstruction.L2SubType.MPLS_PUSH);
        unsupportedL2mod.add(L2ModificationInstruction.L2SubType.MPLS_POP);
        unsupportedL2mod.add(L2ModificationInstruction.L2SubType.MPLS_LABEL);
        unsupportedL2mod.add(L2ModificationInstruction.L2SubType.MPLS_BOS);
        unsupportedL2mod.add(L2ModificationInstruction.L2SubType.DEC_MPLS_TTL);

        //Initialize unsupported L3MODIFICATION actions
        unsupportedL3mod.add(L3ModificationInstruction.L3SubType.TTL_IN);
        unsupportedL3mod.add(L3ModificationInstruction.L3SubType.TTL_OUT);
        unsupportedL3mod.add(L3ModificationInstruction.L3SubType.DEC_TTL);

        //All L4MODIFICATION actions are supported
    }

    @Override
    protected void initHardwareCriteria() {
        log.debug("HP V3500 Driver - Initializing hardware supported criteria");

        hardwareCriteria.add(Criterion.Type.IN_PORT);
        hardwareCriteria.add(Criterion.Type.VLAN_VID);

        //Match in hardware is supported only for ETH_TYPE == IPv4 (0x0800)
        hardwareCriteria.add(Criterion.Type.ETH_TYPE);

        hardwareCriteria.add(Criterion.Type.IPV4_SRC);
        hardwareCriteria.add(Criterion.Type.IPV4_DST);
        hardwareCriteria.add(Criterion.Type.IP_PROTO);
        hardwareCriteria.add(Criterion.Type.IP_DSCP);
        hardwareCriteria.add(Criterion.Type.TCP_SRC);
        hardwareCriteria.add(Criterion.Type.TCP_DST);
    }

    @Override
    protected void initHardwareInstructions() {
        log.debug("HP V3500 Driver - Initializing hardware supported instructions");

        //If the output is on CONTROLLER PORT the rule is processed in software
        hardwareInstructions.add(Instruction.Type.OUTPUT);

        //Only modification of VLAN priority (VLAN_PCP) is supported in hardware
        hardwareInstructions.add(Instruction.Type.L2MODIFICATION);
        hardwareInstructionsL2mod.add(L2ModificationInstruction.L2SubType.VLAN_PCP);

        //TODO also L3MODIFICATION of IP_DSCP is supported in hardware
    }

    //Return TRUE if ForwardingObjective fwd includes unsupported features
    @Override
    protected boolean checkUnSupportedFeatures(ForwardingObjective fwd) {
        boolean unsupportedFeatures = false;

        for (Criterion criterion : fwd.selector().criteria()) {
            if (this.unsupportedCriteria.contains(criterion.type())) {
                log.warn("HP V3500 Driver - unsupported criteria {}", criterion.type());

                unsupportedFeatures = true;
            }
        }

        for (Instruction instruction : fwd.treatment().allInstructions()) {
            if (this.unsupportedInstructions.contains(instruction.type())) {
                log.warn("HP V3500 Driver - unsupported instruction {}", instruction.type());

                unsupportedFeatures = true;
            }

            if (instruction.type() == Instruction.Type.L2MODIFICATION) {
                if (this.unsupportedL2mod.contains(((L2ModificationInstruction) instruction).subtype())) {
                    log.warn("HP V3500 Driver - unsupported L2MODIFICATION instruction {}",
                            ((L2ModificationInstruction) instruction).subtype());

                    unsupportedFeatures = true;
                }
            }

            if (instruction.type() == Instruction.Type.L3MODIFICATION) {
                if (this.unsupportedL3mod.contains(((L3ModificationInstruction) instruction).subtype())) {
                    log.warn("HP V3500 Driver - unsupported L3MODIFICATION instruction {}",
                            ((L3ModificationInstruction) instruction).subtype());

                    unsupportedFeatures = true;
                }
            }
        }

        return unsupportedFeatures;
    }

    @Override
    protected int tableIdForForwardingObjective(ForwardingObjective fwd) {
        boolean hardwareProcess = true;

        log.debug("HP V3500 Driver - Evaluating the ForwardingObjective for proper TableID");

        //Check criteria supported in hardware
        for (Criterion criterion : fwd.selector().criteria()) {

            if (!this.hardwareCriteria.contains(criterion.type())) {
                log.warn("HP V3500 Driver - criterion {} only supported in SOFTWARE", criterion.type());

                hardwareProcess = false;
                break;
            }

            //HP3500 supports hardware match on ETH_TYPE only with value TYPE_IPV4
            if (criterion.type() == Criterion.Type.ETH_TYPE) {

                if (((EthTypeCriterion) criterion).ethType().toShort() != Ethernet.TYPE_IPV4) {
                    log.warn("HP V3500 Driver - only ETH_TYPE == IPv4 (0x0800) is supported in hardware");

                    hardwareProcess = false;
                    break;
                }
            }

            //HP3500 supports IN_PORT criterion in hardware only if associated with ETH_TYPE criterion
            if (criterion.type() == Criterion.Type.IN_PORT) {
                hardwareProcess = false;

                for (Criterion requiredCriterion : fwd.selector().criteria()) {
                    if (requiredCriterion.type() == Criterion.Type.ETH_TYPE) {
                        hardwareProcess = true;
                    }
                }

                if (!hardwareProcess) {
                    log.warn("HP V3500 Driver - IN_PORT criterion without ETH_TYPE is not supported in hardware");

                    break;
                }
            }

        }

        //Check if a CLEAR action is included
        if (fwd.treatment().clearedDeferred()) {
            log.warn("HP V3500 Driver - CLEAR action only supported in SOFTWARE");

            hardwareProcess = false;
        }

        //If criteria can be processed in hardware, then check treatment
        if (hardwareProcess) {

            for (Instruction instruction : fwd.treatment().allInstructions()) {

                //Check if the instruction type is contained in the hardware instruction
                if (!this.hardwareInstructions.contains(instruction.type())) {
                    log.warn("HP V3500 Driver - instruction {} only supported in SOFTWARE", instruction.type());

                    hardwareProcess = false;
                    break;
                }

                /** If output is CONTROLLER_PORT the flow entry could be installed in hardware
                 * but is anyway processed in software because openflow header has to be added
                 */
                if (instruction.type() == Instruction.Type.OUTPUT) {
                    if (((Instructions.OutputInstruction) instruction).port() == PortNumber.CONTROLLER) {
                        log.warn("HP V3500 Driver - Forwarding to CONTROLLER only supported in software");

                        hardwareProcess = false;
                        break;
                    }
                }

                /** Only L2MODIFICATION supported in hardware is MODIFY VLAN_PRIORITY.
                 * Check if the specific L2MODIFICATION.subtype is supported in hardware
                 * */
                if (instruction.type() == Instruction.Type.L2MODIFICATION) {

                    if (!this.hardwareInstructionsL2mod.contains(((L2ModificationInstruction) instruction).subtype())) {
                        log.warn("HP V3500 Driver - L2MODIFICATION.subtype {} only supported in SOFTWARE",
                                ((L2ModificationInstruction) instruction).subtype());

                        hardwareProcess = false;
                        break;
                    }

                }
            }
        }

        if (hardwareProcess) {
            log.warn("HP V3500 Driver - This flow rule is supported in HARDWARE");
            return HP_HARDWARE_TABLE;
        } else {
            //TODO: create a specific flow in table 100 to redirect selected traffic on table 200

            log.warn("HP V3500 Driver - This flow rule is only supported in SOFTWARE");
            return HP_SOFTWARE_TABLE;
        }

    }

    @Override
    public void filter(FilteringObjective filter) {
        log.error("HP V3500 Driver - Unsupported FilteringObjective: filtering method send");
    }

    @Override
    protected FlowRule.Builder processEthFilter(FilteringObjective filt, EthCriterion eth, PortCriterion port) {
        log.error("HP V3500 Driver - Unsupported FilteringObjective: processEthFilter invoked");
        return null;
    }

    @Override
    protected FlowRule.Builder processVlanFilter(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) {
        log.error("HP V3500 Driver - Unsupported FilteringObjective: processVlanFilter invoked");
        return null;
    }

    @Override
    protected FlowRule.Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) {
        log.error("HP V3500 Driver - Unsupported FilteringObjective: processIpFilter invoked");
        return null;
    }
}

