/*
 * 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.pipelines.fabric.impl.behaviour.pipeliner;

import com.google.common.collect.Lists;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.pipelines.fabric.impl.behaviour.FabricCapabilities;
import org.onosproject.pipelines.fabric.FabricConstants;
import org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils;

import java.util.Collection;
import java.util.List;

import static java.lang.String.format;
import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID;
import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP;
import static org.onosproject.net.pi.model.PiPipelineInterpreter.PiInterpreterException;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_VLAN;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_PW_TRANSPORT_VLAN;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ETH_TYPE_EXACT_MASK;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_MPLS;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV4_ROUTING;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV6_ROUTING;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ONE;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_EDGE;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_INFRA;
import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ZERO;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.l2InstructionOrFail;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.criterion;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.l2Instruction;


/**
 * ObjectiveTranslator implementation for FilteringObjective.
 */
class FilteringObjectiveTranslator
        extends AbstractObjectiveTranslator<FilteringObjective> {

    private static final PiAction DENY = PiAction.builder()
            .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY)
            .build();

    private static final int INTERFACE_CONFIG_UPDATE = 2;

    FilteringObjectiveTranslator(DeviceId deviceId, FabricCapabilities capabilities) {
        super(deviceId, capabilities);
    }

    @Override
    public ObjectiveTranslation doTranslate(FilteringObjective obj)
            throws FabricPipelinerException {

        final ObjectiveTranslation.Builder resultBuilder =
                ObjectiveTranslation.builder();

        if (obj.key() == null || obj.key().type() != Criterion.Type.IN_PORT) {
            throw new FabricPipelinerException(
                    format("Unsupported or missing filtering key: key=%s", obj.key()),
                    ObjectiveError.BADPARAMS);
        }

        final PortCriterion inPort = (PortCriterion) obj.key();

        final VlanIdCriterion outerVlan = (VlanIdCriterion) criterion(
                obj.conditions(), Criterion.Type.VLAN_VID);
        final VlanIdCriterion innerVlan = (VlanIdCriterion) criterion(
                obj.conditions(), Criterion.Type.INNER_VLAN_VID);
        final EthCriterion ethDst = (EthCriterion) criterion(
                obj.conditions(), Criterion.Type.ETH_DST);
        final EthCriterion ethDstMasked = (EthCriterion) criterion(
                obj.conditions(), Criterion.Type.ETH_DST_MASKED);

        ingressPortVlanRule(obj, inPort, outerVlan, innerVlan, resultBuilder);
        if (shouldModifyFwdClassifierTable(obj)) {
            fwdClassifierRules(obj, inPort, ethDst, ethDstMasked, resultBuilder);
        } else {
            log.debug("Skipping fwd classifier rules for device {}.", deviceId);
        }
        return resultBuilder.build();
    }

    private boolean shouldModifyFwdClassifierTable(FilteringObjective obj) {
        // NOTE: in fabric pipeline the forwarding classifier acts similarly
        // to the TMAC table of OFDPA that matches on input port.
        // NOTE: that SR signals when it is a port update event by not setting
        // the INTERFACE_CONFIG_UPDATE metadata. During the INTERFACE_CONFIG_UPDATE
        // there is no need to add/remove rules in the fwd_classifier table.
        // NOTE: that in scenarios like (T, N) -> T where we remove only the native
        // VLAN there is not an ADD following the remove.

        // Forwarding classifier rules should be added/removed to translation when:
        // - the operation is ADD
        //     AND it is a port update event (ADD or UPDATE) OR
        // - it doesn't refer to double tagged traffic
        //     AND it is a port REMOVE event OR
        // - it refers to double tagged traffic
        //     and SR is triggering the removal of forwarding classifier rules.
        return (obj.op() == Objective.Operation.ADD && !isInterfaceConfigUpdate(obj)) ||
                (!isDoubleTagged(obj) && !isInterfaceConfigUpdate(obj)) ||
                (isDoubleTagged(obj) && isLastDoubleTaggedForPort(obj));
    }

    /**
     * Check if the given filtering objective is triggered by a interface config change.
     *
     * @param obj Filtering objective to check.
     * @return True if SR is signaling to not remove the forwarding classifier rule,
     * false otherwise.
     */
    private boolean isInterfaceConfigUpdate(FilteringObjective obj) {
        if (obj.meta() == null) {
            return false;
        }
        Instructions.MetadataInstruction meta = obj.meta().writeMetadata();
        // SR is setting this metadata when an interface config update has
        // been performed and thus fwd classifier rules should not be removed
        return (meta != null && (meta.metadata() & meta.metadataMask()) == INTERFACE_CONFIG_UPDATE);
    }

    /**
     * Check if the given filtering objective is the last filtering objective
     * for a double-tagged host for a specific port.
     * <p>
     * {@see org.onosproject.segmentrouting.RoutingRulePopulator#buildDoubleTaggedFilteringObj()}
     * {@see org.onosproject.segmentrouting.RoutingRulePopulator#processDoubleTaggedFilter()}
     *
     * @param obj Filtering objective to check.
     * @return True if SR is signaling to remove the forwarding classifier rule,
     * false otherwise.
     */
    private boolean isLastDoubleTaggedForPort(FilteringObjective obj) {
        Instructions.MetadataInstruction meta = obj.meta().writeMetadata();
        // SR is setting this metadata when a double tagged filtering objective
        // is removed and no other hosts is sharing the same input port.
        return (meta != null && (meta.metadata() & meta.metadataMask()) == 1);
    }

    private boolean isDoubleTagged(FilteringObjective obj) {
        return obj.meta() != null &&
                FabricUtils.l2Instruction(obj.meta(), L2SubType.VLAN_POP) != null &&
                FabricUtils.criterion(obj.conditions(), VLAN_VID) != null &&
                FabricUtils.criterion(obj.conditions(), INNER_VLAN_VID) != null;
    }

    private void ingressPortVlanRule(
            FilteringObjective obj,
            Criterion inPortCriterion,
            VlanIdCriterion outerVlanCriterion,
            VlanIdCriterion innerVlanCriterion,
            ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final boolean outerVlanValid = outerVlanCriterion != null
                && !outerVlanCriterion.vlanId().equals(VlanId.NONE);
        final boolean innerVlanValid = innerVlanCriterion != null
                && !innerVlanCriterion.vlanId().equals(VlanId.NONE);

        if (innerVlanValid && !capabilities.supportDoubleVlanTerm()) {
            throw new FabricPipelinerException(
                    "Found 2 VLAN IDs, but the pipeline does not support double VLAN termination",
                    ObjectiveError.UNSUPPORTED);
        }

        final PiCriterion piCriterion = PiCriterion.builder()
                .matchExact(FabricConstants.HDR_VLAN_IS_VALID, outerVlanValid ? ONE : ZERO)
                .build();

        final TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
                .add(inPortCriterion)
                .add(piCriterion);
        if (outerVlanValid) {
            selector.add(outerVlanCriterion);
        }
        if (innerVlanValid) {
            selector.add(innerVlanCriterion);
        }

        final TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
        if (obj.type().equals(FilteringObjective.Type.DENY)) {
            treatmentBuilder.piTableAction(DENY);
        } else {
            byte portType = PORT_TYPE_EDGE;
            if (!innerVlanValid && outerVlanValid &&
                    outerVlanCriterion.vlanId().toShort() == DEFAULT_PW_TRANSPORT_VLAN) {
                portType = PORT_TYPE_INFRA;
            } else if (obj.meta() != null) {
                ModVlanIdInstruction modVlanIdInstruction = (ModVlanIdInstruction) l2Instruction(obj.meta(), VLAN_ID);
                if (modVlanIdInstruction != null && modVlanIdInstruction.vlanId().toShort() == DEFAULT_VLAN) {
                    portType = PORT_TYPE_INFRA;
                }
            }
            try {
                treatmentBuilder.piTableAction(mapFilteringTreatment(obj.meta(),
                        FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN, portType));
            } catch (PiInterpreterException ex) {
                throw new FabricPipelinerException(format("Unable to map treatment for table '%s': %s",
                        FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN,
                        ex.getMessage()), ObjectiveError.UNSUPPORTED);
            }
        }
        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN,
                selector.build(), treatmentBuilder.build()));
    }

    private PiAction mapFilteringTreatment(TrafficTreatment treatment, PiTableId tableId, byte portType)
            throws PiInterpreterException {
        if (treatment == null) {
            treatment = DefaultTrafficTreatment.emptyTreatment();
        }
        // VLAN_POP action is equivalent to the permit action (VLANs pop is done anyway)
        if (isFilteringNoAction(treatment) || isFilteringPopAction(treatment)) {
            // Permit action if table is ingress_port_vlan;
            return PiAction.builder()
                    .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
                    .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, portType))
                    .build();
        }

        final ModVlanIdInstruction setVlanInst = (ModVlanIdInstruction) l2InstructionOrFail(
                treatment, VLAN_ID, tableId);
        return PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
                .withParameter(new PiActionParam(FabricConstants.VLAN_ID, setVlanInst.vlanId().toShort()))
                .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, portType))
                .build();
    }

    // NOTE: we use clearDeferred to signal when there are no more ports associated to a given vlan
    private static boolean isFilteringNoAction(TrafficTreatment treatment) {
        return treatment.equals(DefaultTrafficTreatment.emptyTreatment()) ||
                (treatment.allInstructions().isEmpty()) ||
                (treatment.allInstructions().size() == 1 && treatment.writeMetadata() != null);
    }

    private boolean isFilteringPopAction(TrafficTreatment treatment) {
        return l2Instruction(treatment, VLAN_POP) != null;
    }

    private void fwdClassifierRules(
            FilteringObjective obj,
            PortCriterion inPortCriterion,
            EthCriterion ethDstCriterion,
            EthCriterion ethDstMaskedCriterion,
            ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final List<FlowRule> flowRules = Lists.newArrayList();

        final PortNumber inPort = inPortCriterion.port();
        if (ethDstCriterion == null) {
            if (ethDstMaskedCriterion == null) {
                // No match. Do bridging (default action).
                return;
            }
            // Masked fwd classifier rule
            final MacAddress dstMac = ethDstMaskedCriterion.mac();
            final MacAddress dstMacMask = ethDstMaskedCriterion.mask();
            flowRules.add(maskedFwdClassifierRule(inPort, dstMac, dstMacMask, obj));
        } else {
            final MacAddress dstMac = ethDstCriterion.mac();
            flowRules.addAll(ipFwdClassifierRules(inPort, dstMac, obj));
            flowRules.addAll(mplsFwdClassifierRules(inPort, dstMac, obj));
        }

        for (FlowRule f : flowRules) {
            resultBuilder.addFlowRule(f);
        }
    }

    private FlowRule maskedFwdClassifierRule(
            PortNumber inPort, MacAddress dstMac, MacAddress dstMacMask,
            FilteringObjective obj)
            throws FabricPipelinerException {
        final TrafficTreatment treatment;
        final short ethType;
        if (dstMac.equals(MacAddress.IPV4_MULTICAST)
                && dstMacMask.equals(MacAddress.IPV4_MULTICAST_MASK)) {
            treatment = fwdClassifierTreatment(FWD_IPV4_ROUTING);
            ethType = Ethernet.TYPE_IPV4;
        } else if (dstMac.equals(MacAddress.IPV6_MULTICAST)
                && dstMacMask.equals(MacAddress.IPV6_MULTICAST_MASK)) {
            treatment = fwdClassifierTreatment(FWD_IPV6_ROUTING);
            ethType = Ethernet.TYPE_IPV6;
        } else {
            throw new FabricPipelinerException(format(
                    "Unsupported masked Ethernet address for fwd " +
                            "classifier rule (mac=%s, mask=%s)",
                    dstMac, dstMacMask));
        }
        return fwdClassifierRule(inPort, ethType, dstMac, dstMacMask, treatment, obj);
    }

    private Collection<FlowRule> ipFwdClassifierRules(
            PortNumber inPort, MacAddress dstMac, FilteringObjective obj)
            throws FabricPipelinerException {
        final Collection<FlowRule> flowRules = Lists.newArrayList();
        flowRules.add(fwdClassifierRule(
                inPort, Ethernet.TYPE_IPV4, dstMac, null,
                fwdClassifierTreatment(FWD_IPV4_ROUTING), obj));
        flowRules.add(fwdClassifierRule(
                inPort, Ethernet.TYPE_IPV6, dstMac, null,
                fwdClassifierTreatment(FWD_IPV6_ROUTING), obj));
        return flowRules;
    }

    private Collection<FlowRule> mplsFwdClassifierRules(
            PortNumber inPort, MacAddress dstMac, FilteringObjective obj)
            throws FabricPipelinerException {
        // Forwarding classifier for MPLS is composed of 2 rules
        // with higher priority wrt standard forwarding classifier rules,
        // this is due to overlap on ternary matching.
        TrafficTreatment treatment = fwdClassifierTreatment(FWD_MPLS);
        final PiCriterion ethTypeMplsIpv4 = PiCriterion.builder()
                .matchTernary(FabricConstants.HDR_ETH_TYPE,
                              Ethernet.MPLS_UNICAST, ETH_TYPE_EXACT_MASK)
                .matchExact(FabricConstants.HDR_IP_ETH_TYPE,
                            Ethernet.TYPE_IPV4)
                .build();
        final TrafficSelector selectorMplsIpv4 = DefaultTrafficSelector.builder()
                .matchInPort(inPort)
                .matchPi(ethTypeMplsIpv4)
                .matchEthDstMasked(dstMac, MacAddress.EXACT_MASK)
                .build();

        final PiCriterion ethTypeMplsIpv6 = PiCriterion.builder()
                .matchTernary(FabricConstants.HDR_ETH_TYPE,
                              Ethernet.MPLS_UNICAST, ETH_TYPE_EXACT_MASK)
                .matchExact(FabricConstants.HDR_IP_ETH_TYPE,
                            Ethernet.TYPE_IPV6)
                .build();
        final TrafficSelector selectorMplsIpv6 = DefaultTrafficSelector.builder()
                .matchInPort(inPort)
                .matchPi(ethTypeMplsIpv6)
                .matchEthDstMasked(dstMac, MacAddress.EXACT_MASK)
                .build();

        return List.of(
                flowRule(obj, FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER,
                         selectorMplsIpv4, treatment, obj.priority() + 1),
                flowRule(obj, FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER,
                         selectorMplsIpv6, treatment, obj.priority() + 1)
        );
    }

    private FlowRule fwdClassifierRule(
            PortNumber inPort, short ethType, MacAddress dstMac, MacAddress dstMacMask,
            TrafficTreatment treatment, FilteringObjective obj)
            throws FabricPipelinerException {
        // Match on ip_eth_type that is the eth_type of the L3 protocol.
        // i.e., if the packet has an IP header, ip_eth_type should
        // contain the corresponding eth_type (for IPv4 or IPv6)
        final PiCriterion ethTypeCriterion = PiCriterion.builder()
                .matchExact(FabricConstants.HDR_IP_ETH_TYPE, ethType)
                .build();
        final TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchInPort(inPort)
                .matchPi(ethTypeCriterion)
                .matchEthDstMasked(dstMac, dstMacMask == null
                        ? MacAddress.EXACT_MASK : dstMacMask)
                .build();
        return flowRule(
                obj, FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER,
                selector, treatment);
    }

    private TrafficTreatment fwdClassifierTreatment(byte fwdType) {
        final PiActionParam param = new PiActionParam(FabricConstants.FWD_TYPE, fwdType);
        final PiAction action = PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
                .withParameter(param)
                .build();
        return DefaultTrafficTreatment.builder()
                .piTableAction(action)
                .build();

    }
}
