/*
 * Copyright 2016-present 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 org.onosproject.sfc.installer.impl;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE;
import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI;
import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_DST;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_SRC;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_MDTYPE;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_NP;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_POP_NSH;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_PUSH_NSH;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_TUN_GPE_NP;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.NshContextHeader;
import org.onosproject.net.NshServiceIndex;
import org.onosproject.net.NshServicePathId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.ExtensionSelectorResolver;
import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.host.HostService;
import org.onosproject.sfc.installer.SfcFlowRuleInstallerService;
import org.onosproject.vtnrsc.FiveTuple;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairGroup;
import org.onosproject.vtnrsc.PortPairGroupId;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.SegmentationId;
import org.onosproject.vtnrsc.VirtualPort;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
import org.onosproject.vtnrsc.portpair.PortPairService;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
import org.onosproject.vtnrsc.service.VtnRscService;
import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * Provides flow classifier installer implementation.
 */
public class SfcFlowRuleInstallerImpl implements SfcFlowRuleInstallerService {
    private final Logger log = getLogger(getClass());

    protected VirtualPortService virtualPortService;
    protected VtnRscService vtnRscService;
    protected PortPairService portPairService;
    protected PortPairGroupService portPairGroupService;
    protected FlowClassifierService flowClassifierService;
    protected DriverService driverService;
    protected DeviceService deviceService;
    protected HostService hostService;
    protected TenantNetworkService tenantNetworkService;
    protected FlowObjectiveService flowObjectiveService;
    protected ApplicationId appId;

    private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
    private static final int FLOW_CLASSIFIER_PRIORITY = 0xC738;
    private static final int DEFAULT_FORWARDER_PRIORITY = 0xD6D8;
    private static final int ENCAP_OUTPUT_PRIORITY = 0x64;
    private static final int TUNNEL_SEND_PRIORITY = 0xC8;
    private static final String SWITCH_CHANNEL_ID = "channelId";
    private static final int ENCAP_OUTPUT_TABLE = 4;
    private static final int TUNNEL_SEND_TABLE = 7;
    private static final short ENCAP_ETH_TYPE = (short) 0x894f;
    private static final String DEFAULT_IP = "0.0.0.0";
    private static final String VXLANPORT_HEAD = "vxlan-0.0.0.0";

    /* Port chain params */
    private short nshSi;
    List<DeviceId> classifierList;
    List<DeviceId> forwarderList;

    /**
     * Default constructor.
     */
    public SfcFlowRuleInstallerImpl() {
    }

    /**
     * Explicit constructor.
     *
     * @param appId application id.
     */
    public SfcFlowRuleInstallerImpl(ApplicationId appId) {
        this.appId = checkNotNull(appId, "ApplicationId can not be null");
        ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
        this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
        this.driverService = serviceDirectory.get(DriverService.class);
        this.deviceService = serviceDirectory.get(DeviceService.class);
        this.hostService = serviceDirectory.get(HostService.class);
        this.virtualPortService = serviceDirectory.get(VirtualPortService.class);
        this.vtnRscService = serviceDirectory.get(VtnRscService.class);
        this.portPairService = serviceDirectory.get(PortPairService.class);
        this.portPairGroupService = serviceDirectory.get(PortPairGroupService.class);
        this.flowClassifierService = serviceDirectory.get(FlowClassifierService.class);
        this.tenantNetworkService = serviceDirectory.get(TenantNetworkService.class);
        nshSi = 0xff;
    }

    @Override
    public ConnectPoint installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
        // Get the portPairGroup
        List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
        ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
        PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
        PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
        List<PortPairId> llPortPairIdList = portPairGroup.portPairs();

        // Get port pair
        ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return installSfcClassifierRules(portChain, portPair, nshSpiId, null, Objective.Operation.ADD);
    }

    @Override
    public ConnectPoint unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
        // Get the portPairGroup
        List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
        ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
        PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
        PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
        List<PortPairId> llPortPairIdList = portPairGroup.portPairs();

        // Get port pair
        ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return installSfcClassifierRules(portChain, portPair, nshSpiId, null, Objective.Operation.REMOVE);
    }

    @Override
    public ConnectPoint installLoadBalancedFlowRules(PortChain portChain, FiveTuple fiveTuple,
            NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);

        return installSfcFlowRules(portChain, fiveTuple, nshSpiId, Objective.Operation.ADD);
    }

    @Override
    public ConnectPoint unInstallLoadBalancedFlowRules(PortChain portChain, FiveTuple fiveTuple,
            NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
        return installSfcFlowRules(portChain, fiveTuple, nshSpiId, Objective.Operation.REMOVE);
    }

    @Override
    public ConnectPoint unInstallLoadBalancedClassifierRules(PortChain portChain, FiveTuple fiveTuple,
            NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);

        List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);
        // Get the first port pair
        ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return installSfcClassifierRules(portChain, portPair, nshSpiId, fiveTuple, Objective.Operation.REMOVE);
    }

    public ConnectPoint installSfcFlowRules(PortChain portChain, FiveTuple fiveTuple, NshServicePathId nshSpiId,
            Objective.Operation type) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);

        classifierList = Lists.newArrayList();
        forwarderList = Lists.newArrayList();

        // Get the load balanced path
        List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);

        // Get the first port pair
        ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair currentPortPair = portPairService.getPortPair(portPairId);

        ConnectPoint connectPoint = installSfcClassifierRules(portChain, currentPortPair, nshSpiId, fiveTuple, type);

        log.info("Installing encap and output for first port pair");

        installSfcEncapOutputRule(currentPortPair, nshSpiId, type);

        PortPair nextPortPair;
        while (portPairListIterator.hasNext()) {
            portPairId = portPairListIterator.next();
            nextPortPair = portPairService.getPortPair(portPairId);
            installSfcForwardRule(currentPortPair, nextPortPair, nshSpiId, type);
            installSfcEncapOutputRule(nextPortPair, nshSpiId, type);
            currentPortPair = nextPortPair;
        }
        installSfcEndRule(currentPortPair, nshSpiId, type);

        if (type.equals(Objective.Operation.ADD)) {
            portChain.addSfcClassifiers(portChain.getLoadBalanceId(fiveTuple), classifierList);
            portChain.addSfcForwarders(portChain.getLoadBalanceId(fiveTuple), forwarderList);
        } else {
            portChain.removeSfcClassifiers(portChain.getLoadBalanceId(fiveTuple), classifierList);
            portChain.removeSfcForwarders(portChain.getLoadBalanceId(fiveTuple), forwarderList);
        }
        return connectPoint;
    }

    public void installSfcTunnelReceiveRule(DeviceId deviceId, NshServicePathId nshSpiId, Objective.Operation type) {

        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionSelectorResolver selectorResolver = handler.behaviour(ExtensionSelectorResolver.class);
        ExtensionSelector nshSpiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
        ExtensionSelector nshSiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());

        try {
            nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Spi Id for end rule {}", e.getMessage());
        }
        try {
            nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Si Id for end rule {}", e.getMessage());
        }

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.extension(nshSpiSelector, deviceId);
        selector.extension(nshSiSelector, deviceId);

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.transition(ENCAP_OUTPUT_TABLE);

        sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
    }

    public void installSfcTunnelSendRule(DeviceId deviceId, NshServicePathId nshSpiId, Objective.Operation type) {

        // Prepare selector with nsp, nsi and inport from egress of port pair
        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionSelectorResolver selectorResolver = handler.behaviour(ExtensionSelectorResolver.class);
        ExtensionSelector nshSpiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
        ExtensionSelector nshSiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
        ExtensionSelector encapEthTypeSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_ENCAP_ETH_TYPE
                                                                                       .type());
        try {
            nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Spi Id for end rule {}", e.getMessage());
        }
        try {
            nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Si Id for end rule {}", e.getMessage());
        }
        try {
            encapEthTypeSelector.setPropertyValue("encapEthType", ENCAP_ETH_TYPE);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match encapEthType {}", deviceId);
        }

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.extension(nshSpiSelector, deviceId);
        selector.extension(nshSiSelector, deviceId);

        ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment tunGpeNpTreatment = treatmentResolver.getExtensionInstruction(NICIRA_TUN_GPE_NP.type());
        try {
            tunGpeNpTreatment.setPropertyValue("tunGpeNp", ((byte) 4));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set tunGpeNp {}", deviceId);
        }

        ExtensionTreatment moveC1ToC1 = treatmentResolver
                .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                         .NICIRA_MOV_NSH_C1_TO_C1.type());

        ExtensionTreatment moveC2ToC2 = treatmentResolver
                .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                         .NICIRA_MOV_NSH_C2_TO_C2.type());

        ExtensionTreatment moveC3ToC3 = treatmentResolver
                .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                         .NICIRA_MOV_NSH_C3_TO_C3.type());

        ExtensionTreatment moveC4ToC4 = treatmentResolver
                .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                         .NICIRA_MOV_NSH_C4_TO_C4.type());

        ExtensionTreatment moveTunIpv4DstToTunIpv4Dst = treatmentResolver
                .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                         .NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST.type());

        ExtensionTreatment moveTunIdToTunId = treatmentResolver
                .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                         .NICIRA_MOV_TUN_ID_TO_TUN_ID.type());

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.extension(tunGpeNpTreatment, deviceId);
        treatment.extension(moveC1ToC1, deviceId);
        treatment.extension(moveC2ToC2, deviceId);
        treatment.extension(moveC3ToC3, deviceId);
        treatment.extension(moveC4ToC4, deviceId);
        treatment.extension(moveTunIpv4DstToTunIpv4Dst, deviceId);
        treatment.extension(moveTunIdToTunId, deviceId);

        Iterable<Device> devices = deviceService.getAvailableDevices();
        DeviceId localControllerId = getControllerId(deviceService.getDevice(deviceId), devices);
        DriverHandler controllerHandler = driverService.createHandler(localControllerId);

        BridgeConfig bridgeConfig = controllerHandler.behaviour(BridgeConfig.class);
        Set<PortNumber> ports = bridgeConfig.getPortNumbers();
        String tunnelName = "vxlan-" + DEFAULT_IP;
        ports.stream()
        .filter(p ->p.name().equalsIgnoreCase(tunnelName))
        .forEach(p -> {
            treatment.setOutput(p);
            sendSfcRule(selector, treatment, deviceId, type, TUNNEL_SEND_PRIORITY);
        });
    }

    public void installSfcEndRule(PortPair portPair, NshServicePathId nshSpiId, Objective.Operation type) {
        DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.egress()));
        MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
        Host host = hostService.getHost(HostId.hostId(srcMacAddress));
        PortNumber port = host.location().port();

        // Prepare selector with nsp, nsi and inport from egress of port pair
        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionSelectorResolver selectorResolver = handler.behaviour(ExtensionSelectorResolver.class);
        ExtensionSelector nshSpiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
        ExtensionSelector nshSiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
        ExtensionSelector encapEthTypeSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_ENCAP_ETH_TYPE
                .type());
        try {
            nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Spi Id for end rule {}", e.getMessage());
        }
        // Decrement the SI
        nshSi = (short) (nshSi - 1);
        try {
            nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Si Id for end rule {}", e.getMessage());
        }
        try {
            encapEthTypeSelector.setPropertyValue("encapEthType", ENCAP_ETH_TYPE);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match encapEthType {}", deviceId);
        }
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.extension(encapEthTypeSelector, deviceId);
        selector.extension(nshSpiSelector, deviceId);
        selector.extension(nshSiSelector, deviceId);
        selector.matchInPort(port);

        // Set treatment to pop nsh header, set tunnel id and resubmit to table
        // 0.
        ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment popNshTreatment = treatmentResolver.getExtensionInstruction(NICIRA_POP_NSH.type());

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.extension(popNshTreatment, deviceId);

        VirtualPort virtualPort = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress()));
        SegmentationId segmentationId = tenantNetworkService.getNetwork(virtualPort.networkId()).segmentationId();
        treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId.toString())));

        ExtensionTreatment resubmitTableTreatment = treatmentResolver.getExtensionInstruction(NICIRA_RESUBMIT_TABLE
                .type());

        PortNumber vxlanPortNumber = getVxlanPortNumber(deviceId);

        try {
            resubmitTableTreatment.setPropertyValue("inPort", vxlanPortNumber);
        } catch (Exception e) {
            log.error("Failed to set extension treatment for resubmit table in port {}", deviceId);
        }
        try {
            resubmitTableTreatment.setPropertyValue("table", ((short) 0));
        } catch (Exception e) {
            log.error("Failed to set extension treatment for resubmit table {}", deviceId);
        }
        treatment.extension(resubmitTableTreatment, deviceId);

        sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
    }

    public void installSfcForwardRule(PortPair portPair, PortPair nextPortPair, NshServicePathId nshSpiId,
            Objective.Operation type) {
        DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.egress()));
        MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
        Host host = hostService.getHost(HostId.hostId(srcMacAddress));
        PortNumber port = host.location().port();

        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);

        // Prepare selector with nsp, nsi and inport from egress of port pair
        ExtensionSelector nshSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
        ExtensionSelector nshSiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
        try {
            nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Spi Id for forward rule {}", e.getMessage());
        }
        // Decrement the SI
        nshSi = (short) (nshSi - 1);
        try {
            nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Si Id for forward rule {}", e.getMessage());
        }
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.extension(nshSpiSelector, deviceId);
        selector.extension(nshSiSelector, deviceId);
        selector.matchInPort(port);

        DeviceId nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(nextPortPair.ingress()));
        if (deviceId.equals(nextDeviceId)) {

            // Treatment with transition
            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
            treatment.transition(ENCAP_OUTPUT_TABLE);

            sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
        } else {
            // Treatment with with transition to send on tunnel
            ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
            ExtensionTreatment moveC2ToTunId = treatmentResolver
                    .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
                                             .NICIRA_MOV_NSH_C2_TO_TUN_ID.type());

            Device remoteDevice = deviceService.getDevice(nextDeviceId);
            String url = remoteDevice.annotations().value(SWITCH_CHANNEL_ID);
            String remoteControllerIp = url.substring(0, url.lastIndexOf(":"));
            if (remoteControllerIp == null) {
                log.error("Can't find remote controller of device: {}", nextDeviceId.toString());
                return;
            }

            ExtensionTreatment tunnelDsttreatment = treatmentResolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST
                                                                                              .type());
            try {
                tunnelDsttreatment.setPropertyValue("tunnelDst", Ip4Address.valueOf(remoteControllerIp));
            } catch (Exception e) {
                log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
            }

            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
            treatment.extension(moveC2ToTunId, deviceId);
            treatment.extension(tunnelDsttreatment, deviceId);
            treatment.transition(TUNNEL_SEND_TABLE);

            sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);

            installSfcTunnelSendRule(deviceId, nshSpiId, type);
            installSfcTunnelReceiveRule(nextDeviceId, nshSpiId, type);
        }
    }

    public void installSfcEncapOutputRule(PortPair portPair, NshServicePathId nshSpiId, Objective.Operation type) {

        DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
        MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
        Host host = hostService.getHost(HostId.hostId(srcMacAddress));
        PortNumber port = host.location().port();

        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);

        // Prepare selector with nsp, nsi and encap eth type
        ExtensionSelector nshSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
        ExtensionSelector nshSiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
        ExtensionSelector nshEncapEthTypeSelector = resolver.getExtensionSelector(NICIRA_MATCH_ENCAP_ETH_TYPE.type());

        try {
            nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Spi Id for encap rule {}", e.getMessage());
        }
        try {
            nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Si Id for encap rule {}", e.getMessage());
        }
        try {
            nshEncapEthTypeSelector.setPropertyValue("encapEthType", ENCAP_ETH_TYPE);
        } catch (Exception e) {
            log.error("Failed to set extension selector to match Nsh Si Id {}", deviceId);
        }
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.extension(nshSpiSelector, deviceId);
        selector.extension(nshSiSelector, deviceId);

        ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment encapEthSrcTreatment = treatmentResolver
                .getExtensionInstruction(NICIRA_ENCAP_ETH_SRC.type());
        ExtensionTreatment encapEthDstTreatment = treatmentResolver
                .getExtensionInstruction(NICIRA_ENCAP_ETH_DST.type());

        try {
            encapEthDstTreatment.setPropertyValue("encapEthDst", srcMacAddress);
        } catch (Exception e) {
            log.error("Failed to set extension treatment to set encap eth dst {}", deviceId);
        }
        // TODO: move from packet source mac address
        try {
            encapEthSrcTreatment.setPropertyValue("encapEthSrc", srcMacAddress);
        } catch (Exception e) {
            log.error("Failed to set extension treatment to set encap eth src {}", deviceId);
        }

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.extension(encapEthSrcTreatment, deviceId);
        treatment.extension(encapEthDstTreatment, deviceId);
        treatment.setOutput(port);

        sendSfcRule(selector, treatment, deviceId, type, ENCAP_OUTPUT_PRIORITY);
        forwarderList.add(deviceId);
    }

    public ConnectPoint installSfcClassifierRules(PortChain portChain, PortPair portPair, NshServicePathId nshSpiId,
            FiveTuple fiveTuple, Objective.Operation type) {

        DeviceId deviceIdfromPortPair = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
        MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
        VirtualPort virtualPort = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress()));
        Host host = hostService.getHost(HostId.hostId(srcMacAddress));
        PortNumber port = host.location().port();

        DeviceId deviceId = deviceIdfromPortPair;

        // get flow classifiers
        List<FlowClassifierId> llFlowClassifierList = portChain.flowClassifiers();
        ListIterator<FlowClassifierId> flowClassifierListIterator = llFlowClassifierList.listIterator();

        while (flowClassifierListIterator.hasNext()) {
            FlowClassifierId flowclassifierId = flowClassifierListIterator.next();
            FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowclassifierId);

            if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
                deviceId = vtnRscService.getSfToSffMaping(flowClassifier.srcPort());
            }

            // Build Traffic selector.
            TrafficSelector.Builder selector = packClassifierSelector(flowClassifier, fiveTuple);

            if (fiveTuple == null) {
                // Send the packet to controller
                log.info("Downloading rule to send packet to controller");
                TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
                treatment.setOutput(PortNumber.CONTROLLER);
                sendSfcRule(selector, treatment, deviceId, type, FLOW_CLASSIFIER_PRIORITY);
                continue;
            }

            if (deviceId != null && !deviceId.equals(deviceIdfromPortPair)) {
                // First SF is in another device. Set tunnel ipv4 destination to
                // treatment
                Device remoteDevice = deviceService.getDevice(deviceIdfromPortPair);
                String url = remoteDevice.annotations().value(SWITCH_CHANNEL_ID);
                String remoteControllerIp = url.substring(0, url.lastIndexOf(":"));
                if (remoteControllerIp == null) {
                    log.error("Can't find remote controller of device: {}", deviceIdfromPortPair.toString());
                    return null;
                }

                DriverHandler handler = driverService.createHandler(deviceId);
                ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
                ExtensionTreatment tunnelDsttreatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
                try {
                    tunnelDsttreatment.setPropertyValue("tunnelDst", Ip4Address.valueOf(remoteControllerIp));
                } catch (Exception e) {
                    log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
                }

                TrafficTreatment.Builder treatment = packClassifierTreatment(deviceId, virtualPort, port,
                                                                             nshSpiId, flowClassifier);
                treatment.extension(tunnelDsttreatment, deviceId);
                treatment.transition(TUNNEL_SEND_TABLE);
                sendSfcRule(selector, treatment, deviceId, type, flowClassifier.priority());

                selector.matchInPort(PortNumber.CONTROLLER);
                sendSfcRule(selector, treatment, deviceId, type, flowClassifier.priority());
                classifierList.add(deviceId);

                installSfcTunnelSendRule(deviceId, nshSpiId, type);
                installSfcTunnelReceiveRule(deviceIdfromPortPair, nshSpiId, type);

            } else {
                // classifier and port pair are in the same OVS. So directly
                // send packet to first port pair
                TrafficTreatment.Builder treatment = packClassifierTreatment(deviceIdfromPortPair, virtualPort, port,
                                                                             nshSpiId, flowClassifier);
                treatment.transition(ENCAP_OUTPUT_TABLE);
                sendSfcRule(selector, treatment, deviceIdfromPortPair, type, flowClassifier.priority());

                selector.matchInPort(PortNumber.CONTROLLER);
                sendSfcRule(selector, treatment, deviceId, type, flowClassifier.priority());
                classifierList.add(deviceIdfromPortPair);
            }
        }

        return host.location();
    }

    /**
     * Pack Traffic selector.
     *
     * @param flowClassifier flow-classifier
     * @param fiveTuple five tuple info for the packet
     * @return traffic selector
     */
    public TrafficSelector.Builder packClassifierSelector(FlowClassifier flowClassifier, FiveTuple fiveTuple) {

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();

        if ((flowClassifier.srcIpPrefix() != null) && (flowClassifier.srcIpPrefix().prefixLength() != 0)) {
            selector.matchIPSrc(flowClassifier.srcIpPrefix());
        } else if (fiveTuple != null && fiveTuple.ipSrc() != null) {
            selector.matchIPSrc(IpPrefix.valueOf(fiveTuple.ipSrc(), 24));
        }

        if ((flowClassifier.dstIpPrefix() != null) && (flowClassifier.dstIpPrefix().prefixLength() != 0)) {
            selector.matchIPDst(flowClassifier.dstIpPrefix());
        } else if (fiveTuple != null && fiveTuple.ipDst() != null) {
            selector.matchIPDst(IpPrefix.valueOf(fiveTuple.ipDst(), 24));
        }

        if ((flowClassifier.protocol() != null) && (!flowClassifier.protocol().isEmpty())) {
            if (flowClassifier.protocol().equalsIgnoreCase("TCP")) {
                selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_TCP));
            } else if (flowClassifier.protocol().equalsIgnoreCase("UDP")) {
                selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP));
            } else if (flowClassifier.protocol().equalsIgnoreCase("ICMP")) {
                selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_ICMP));
            }
        } else if (fiveTuple != null && fiveTuple.protocol() != 0) {
            selector.add(Criteria.matchIPProtocol(fiveTuple.protocol()));
        }

        if (((flowClassifier.etherType() != null) && (!flowClassifier.etherType().isEmpty()))
                && (flowClassifier.etherType().equals("IPv4") || flowClassifier.etherType().equals("IPv6"))) {
            if (flowClassifier.etherType().equals("IPv4")) {
                selector.matchEthType(Ethernet.TYPE_IPV4);
            } else {
                selector.matchEthType(Ethernet.TYPE_IPV6);
            }
        }

        if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
            VirtualPortId vPortId = VirtualPortId.portId(flowClassifier.srcPort().portId());
            MacAddress macAddress = virtualPortService.getPort(vPortId).macAddress();
            Host host = hostService.getHost(HostId.hostId(macAddress));
            selector.matchInPort(host.location().port());
        }

        // Take the port information from five tuple only when the protocol is
        // TCP.
        if (fiveTuple != null && fiveTuple.protocol() == IPv4.PROTOCOL_TCP) {
            selector.matchTcpSrc(TpPort.tpPort((int) fiveTuple.portSrc().toLong()));
            selector.matchTcpDst(TpPort.tpPort((int) fiveTuple.portDst().toLong()));
        } else {
            // For udp packets take the port information from flow classifier
            List<TpPort> srcPortRange = new LinkedList<>();
            List<TpPort> dstPortRange = new LinkedList<>();
            if ((flowClassifier.minSrcPortRange() != 0) && flowClassifier.maxSrcPortRange() != 0
                    && flowClassifier.minDstPortRange() != 0 && flowClassifier.maxDstPortRange() != 0) {

                for (int port = flowClassifier.minSrcPortRange(); port <= flowClassifier.maxSrcPortRange(); port++) {
                    srcPortRange.add(TpPort.tpPort(port));
                }
                for (int port = flowClassifier.minDstPortRange(); port <= flowClassifier.maxDstPortRange(); port++) {
                    dstPortRange.add(TpPort.tpPort(port));
                }
            }

            for (TpPort inPort : srcPortRange) {
                selector.matchUdpSrc(inPort);
            }
            for (TpPort outPort : dstPortRange) {
                selector.matchUdpDst(outPort);
            }
        }
        return selector;
    }

    /**
     * Pack traffic treatment.
     *
     * @param deviceId device id
     * @param virtualPort virtual port
     * @param port port number
     * @param nshSpi nsh spi
     * @param flowClassifier flow-classifier
     * @return traffic treatment
     */
    public TrafficTreatment.Builder packClassifierTreatment(DeviceId deviceId, VirtualPort virtualPort,
            PortNumber port, NshServicePathId nshSpi, FlowClassifier flowClassifier) {

        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();

        // set tunnel id
        SegmentationId segmentationId = tenantNetworkService.getNetwork(virtualPort.networkId()).segmentationId();
        treatmentBuilder.add(Instructions.modTunnelId(Long.parseLong(segmentationId.toString())));

        // Set all NSH header fields
        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment nspIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SPI.type());
        ExtensionTreatment nsiIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SI.type());
        ExtensionTreatment pushNshTreatment = resolver.getExtensionInstruction(NICIRA_PUSH_NSH.type());

        ExtensionTreatment nshCh1Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH1.type());
        ExtensionTreatment nshCh2Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH2.type());
        ExtensionTreatment nshCh3Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH3.type());
        ExtensionTreatment nshCh4Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH4.type());
        ExtensionTreatment nshMdTypeTreatment = resolver.getExtensionInstruction(NICIRA_NSH_MDTYPE.type());
        ExtensionTreatment nshNpTreatment = resolver.getExtensionInstruction(NICIRA_NSH_NP.type());

        try {
            nshMdTypeTreatment.setPropertyValue("nshMdType", ((byte) 1));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set nshMdType {}", deviceId);
        }
        try {
            nshNpTreatment.setPropertyValue("nshNp", ((byte) 3));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set nshNp {}", deviceId);
        }
        try {
            nspIdTreatment.setPropertyValue("nshSpi", nshSpi);
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
        }
        try {
            nsiIdTreatment.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set Nsh Si Id {}", deviceId);
        }
        try {
            nshCh1Treatment.setPropertyValue("nshCh", NshContextHeader.of(1));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set NshCh1 {}", deviceId);
        }
        try {
            nshCh2Treatment.setPropertyValue("nshCh", NshContextHeader.of(Integer.parseInt(segmentationId.toString())));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set NshCh2 {}", deviceId);
        }
        try {
            nshCh3Treatment.setPropertyValue("nshCh", NshContextHeader.of(3));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set NshCh3 {}", deviceId);
        }
        try {
            nshCh4Treatment.setPropertyValue("nshCh", NshContextHeader.of(4));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set NshCh4 {}", deviceId);
        }
        treatmentBuilder.extension(pushNshTreatment, deviceId);
        treatmentBuilder.extension(nshMdTypeTreatment, deviceId);
        treatmentBuilder.extension(nshNpTreatment, deviceId);
        treatmentBuilder.extension(nspIdTreatment, deviceId);
        treatmentBuilder.extension(nsiIdTreatment, deviceId);
        treatmentBuilder.extension(nshCh1Treatment, deviceId);
        treatmentBuilder.extension(nshCh2Treatment, deviceId);
        treatmentBuilder.extension(nshCh3Treatment, deviceId);
        treatmentBuilder.extension(nshCh4Treatment, deviceId);

        return treatmentBuilder;
    }

    /**
     * Get the ControllerId from the device .
     *
     * @param device Device
     * @param devices Devices
     * @return Controller Id
     */
    public DeviceId getControllerId(Device device, Iterable<Device> devices) {
        for (Device d : devices) {
            if (d.type() == Device.Type.CONTROLLER && d.id().toString()
                    .contains(getControllerIpOfSwitch(device))) {
                return d.id();
            }
        }
        log.info("Can not find controller for device : {}", device.id());
        return null;
    }

    /**
     * Get the ControllerIp from the device .
     *
     * @param device Device
     * @return Controller Ip
     */
    public String getControllerIpOfSwitch(Device device) {
        String url = device.annotations().value(SWITCH_CHANNEL_ID);
        return url.substring(0, url.lastIndexOf(":"));
    }

    /**
     * Send service-function-forwarder to OVS.
     *
     * @param selector traffic selector
     * @param treatment traffic treatment
     * @param deviceId device id
     * @param type operation type
     * @param priority priority of classifier
     */
    public void sendSfcRule(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment, DeviceId deviceId,
            Objective.Operation type, int priority) {

        log.info("Sending sfc flow rule. Selector {}, Treatment {}", selector.toString(),
                 treatment.toString());
        ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
                .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE)
                .withPriority(priority);

        if (type.equals(Objective.Operation.ADD)) {
            log.debug("flowClassifierRules-->ADD");
            flowObjectiveService.forward(deviceId, objective.add());
        } else {
            log.debug("flowClassifierRules-->REMOVE");
            flowObjectiveService.forward(deviceId, objective.remove());
        }
    }

    private PortNumber getVxlanPortNumber(DeviceId deviceId) {
        Iterable<Port> ports = deviceService.getPorts(deviceId);
        Port vxlanPort = Sets.newHashSet(ports).stream()
                .filter(p ->!p.number().equals(PortNumber.LOCAL))
                .filter(p ->p.annotations().value(AnnotationKeys.PORT_NAME)
                        .startsWith(VXLANPORT_HEAD))
                .findFirst().get();
        return vxlanPort.number();
    }
}
