/*
 * Copyright 2015-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.manager.impl;

import static org.slf4j.LoggerFactory.getLogger;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.UUID;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TCP;
import org.onlab.packet.UDP;
import org.onlab.util.ItemNotFoundException;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.NshServicePathId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.sfc.installer.impl.SfcFlowRuleInstallerImpl;
import org.onosproject.sfc.manager.SfcService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
import org.onosproject.vtnrsc.DefaultFiveTuple;
import org.onosproject.vtnrsc.FiveTuple;
import org.onosproject.vtnrsc.FixedIp;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
import org.onosproject.vtnrsc.LoadBalanceId;
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortChainId;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairGroup;
import org.onosproject.vtnrsc.PortPairGroupId;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.VirtualPort;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.event.VtnRscEvent;
import org.onosproject.vtnrsc.event.VtnRscListener;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
import org.onosproject.vtnrsc.portchain.PortChainService;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
import org.onosproject.vtnrsc.service.VtnRscService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;

import com.google.common.collect.Lists;

/**
 * Provides implementation of SFC Service.
 */
@Component(immediate = true)
@Service
public class SfcManager implements SfcService {

    private final Logger log = getLogger(getClass());

    private String nshSpiIdTopic = "nsh-spi-id";
    private static final String APP_ID = "org.onosproject.app.vtn";
    private static final int SFC_PRIORITY = 1000;
    private static final int MAX_NSH_SPI_ID = 0x7FFFF;
    private static final int MAX_LOAD_BALANCE_ID = 0x20;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VtnRscService vtnRscService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PacketService packetService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PortChainService portChainService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PortPairGroupService portPairGroupService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowClassifierService flowClassifierService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VirtualPortService virtualPortService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    protected SfcPacketProcessor processor = new SfcPacketProcessor();

    protected ApplicationId appId;
    protected IdGenerator nshSpiIdGenerator;
    protected EventuallyConsistentMap<PortChainId, Integer> nshSpiPortChainMap;
    protected EventuallyConsistentMap<PortChainId, List<FiveTuple>> portChainFiveTupleMap;
    protected DistributedSet<Integer> nshSpiIdFreeList;

    private final VtnRscListener vtnRscListener = new InnerVtnRscListener();

    @Activate
    public void activate() {
        appId = coreService.registerApplication(APP_ID);
        nshSpiIdGenerator = coreService.getIdGenerator(nshSpiIdTopic);

        vtnRscService.addListener(vtnRscListener);

        KryoNamespace.Builder serializer = KryoNamespace
                .newBuilder()
                .register(PortChainId.class, UUID.class, FiveTuple.class, IpAddress.class, PortNumber.class,
                          DefaultFiveTuple.class, IpAddress.Version.class, TenantId.class);

        nshSpiPortChainMap = storageService.<PortChainId, Integer>eventuallyConsistentMapBuilder()
                .withName("nshSpiPortChainMap").withSerializer(serializer)
                .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();

        portChainFiveTupleMap = storageService.<PortChainId, List<FiveTuple>>eventuallyConsistentMapBuilder()
                .withName("portChainFiveTupleMap").withSerializer(serializer)
                .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();

        nshSpiIdFreeList = storageService.<Integer>setBuilder()
                .withName("nshSpiIdDeletedList")
                .withSerializer(Serializer.using(KryoNamespaces.API))
                .build()
                .asDistributedSet();

        packetService.addProcessor(processor, PacketProcessor.director(SFC_PRIORITY));
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        vtnRscService.removeListener(vtnRscListener);
        packetService.removeProcessor(processor);
        log.info("Stopped");
    }

    /*
     * Handle events.
     */
    private class InnerVtnRscListener implements VtnRscListener {
        @Override
        public void event(VtnRscEvent event) {

            if (VtnRscEvent.Type.PORT_PAIR_PUT == event.type()) {
                PortPair portPair = event.subject().portPair();
                onPortPairCreated(portPair);
            } else if (VtnRscEvent.Type.PORT_PAIR_DELETE == event.type()) {
                PortPair portPair = event.subject().portPair();
                onPortPairDeleted(portPair);
            } else if (VtnRscEvent.Type.PORT_PAIR_UPDATE == event.type()) {
                PortPair portPair = event.subject().portPair();
                onPortPairDeleted(portPair);
                onPortPairCreated(portPair);
            } else if (VtnRscEvent.Type.PORT_PAIR_GROUP_PUT == event.type()) {
                PortPairGroup portPairGroup = event.subject().portPairGroup();
                onPortPairGroupCreated(portPairGroup);
            } else if (VtnRscEvent.Type.PORT_PAIR_GROUP_DELETE == event.type()) {
                PortPairGroup portPairGroup = event.subject().portPairGroup();
                onPortPairGroupDeleted(portPairGroup);
            } else if (VtnRscEvent.Type.PORT_PAIR_GROUP_UPDATE == event.type()) {
                PortPairGroup portPairGroup = event.subject().portPairGroup();
                onPortPairGroupDeleted(portPairGroup);
                onPortPairGroupCreated(portPairGroup);
            } else if (VtnRscEvent.Type.FLOW_CLASSIFIER_PUT == event.type()) {
                FlowClassifier flowClassifier = event.subject().flowClassifier();
                onFlowClassifierCreated(flowClassifier);
            } else if (VtnRscEvent.Type.FLOW_CLASSIFIER_DELETE == event.type()) {
                FlowClassifier flowClassifier = event.subject().flowClassifier();
                onFlowClassifierDeleted(flowClassifier);
            } else if (VtnRscEvent.Type.FLOW_CLASSIFIER_UPDATE == event.type()) {
                FlowClassifier flowClassifier = event.subject().flowClassifier();
                onFlowClassifierDeleted(flowClassifier);
                onFlowClassifierCreated(flowClassifier);
            } else if (VtnRscEvent.Type.PORT_CHAIN_PUT == event.type()) {
                PortChain portChain = event.subject().portChain();
                if (portChain.oldPortChain() != null) {
                    onPortChainDeleted(portChain.oldPortChain());
                }
                onPortChainCreated(portChain);
            } else if (VtnRscEvent.Type.PORT_CHAIN_DELETE == event.type()) {
                PortChain portChain = event.subject().portChain();
                onPortChainDeleted(portChain);
                portChainFiveTupleMap.remove(portChain.portChainId());
            } else if (VtnRscEvent.Type.PORT_CHAIN_UPDATE == event.type()) {
                PortChain portChain = event.subject().portChain();
                onPortChainDeleted(portChain);
                onPortChainCreated(portChain);
            }
        }
    }

    @Override
    public void onPortPairCreated(PortPair portPair) {
        log.debug("onPortPairCreated");
        // Do nothing
    }

    @Override
    public void onPortPairDeleted(PortPair portPair) {
        log.debug("onPortPairDeleted");
        // Do nothing
    }

    @Override
    public void onPortPairGroupCreated(PortPairGroup portPairGroup) {
        log.debug("onPortPairGroupCreated");
        // Do nothing
    }

    @Override
    public void onPortPairGroupDeleted(PortPairGroup portPairGroup) {
        log.debug("onPortPairGroupDeleted");
        // Do nothing
    }

    @Override
    public void onFlowClassifierCreated(FlowClassifier flowClassifier) {
        log.debug("onFlowClassifierCreated");
        // Do nothing
    }

    @Override
    public void onFlowClassifierDeleted(FlowClassifier flowClassifier) {
        log.debug("onFlowClassifierDeleted");
        // Do nothing
    }

    @Override
    public void onPortChainCreated(PortChain portChain) {
        NshServicePathId nshSpi;
        log.info("On port chain created");

        int spi = getNextNshSpi();
        if (spi > MAX_NSH_SPI_ID) {
            log.error("Reached max limit of service path index." + "Failed to install SFC for port chain {}",
                      portChain.portChainId().toString());
            return;
        }
        nshSpi = NshServicePathId.of(spi);
        nshSpiPortChainMap.put(portChain.portChainId(), new Integer(spi));
        if (!portChainFiveTupleMap.containsKey(portChain.portChainId())) {
            portChainFiveTupleMap.put(portChain.portChainId(), Lists.newArrayList());
        }
        // Install classifier rule to send the packet to controller
        SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl(appId);
        flowRuleInstaller.installFlowClassifier(portChain, nshSpi);

        // Install rules for already identified five tuples.
        List<FiveTuple> list = portChainFiveTupleMap.get(portChain.portChainId());
        for (FiveTuple fiveTuple : list) {
            LoadBalanceId id = loadBalanceSfc(portChain.portChainId(), fiveTuple);
            // Get nsh service path index
            nshSpi = NshServicePathId.of(getNshServicePathId(id, spi));
            // download the required flow rules for classifier and
            // forwarding
            flowRuleInstaller.installLoadBalancedFlowRules(portChain, fiveTuple, nshSpi);
        }
    }

    @Override
    public void onPortChainDeleted(PortChain portChain) {
        log.info("onPortChainDeleted");
        if (!nshSpiPortChainMap.containsKey(portChain.portChainId())) {
            throw new ItemNotFoundException("Unable to find NSH SPI");
        }

        int nshSpiId = nshSpiPortChainMap.get(portChain.portChainId());
        // Uninstall classifier rules
        SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl(appId);
        flowRuleInstaller.unInstallFlowClassifier(portChain, NshServicePathId.of(nshSpiId));
        // remove from nshSpiPortChainMap and add to nshSpiIdFreeList
        nshSpiPortChainMap.remove(portChain.portChainId());
        nshSpiIdFreeList.add(nshSpiId);

        // Uninstall load balanced classifier and forwarding rules.
        NshServicePathId nshSpi;
        LoadBalanceId id;
        List<LoadBalanceId> processedIdList = Lists.newArrayList();
        Set<FiveTuple> fiveTupleSet = portChain.getLoadBalanceIdMapKeys();
        for (FiveTuple fiveTuple : fiveTupleSet) {
            id = portChain.getLoadBalanceId(fiveTuple);
            nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId));
            if (processedIdList.contains(id)) {
                // Multiple five tuple can have single path. In this case only
                // the classifier rule need to delete
                flowRuleInstaller.unInstallLoadBalancedClassifierRules(portChain, fiveTuple, nshSpi);
                continue;
            } else {
                processedIdList.add(id);
            }
            flowRuleInstaller.unInstallLoadBalancedFlowRules(portChain, fiveTuple, nshSpi);
        }

        // Reset load for all the port pairs
        List<PortPairGroupId> ppgIdlist = portChain.portPairGroups();
        ListIterator<PortPairGroupId> ppgIdListIterator = ppgIdlist.listIterator();
        while (ppgIdListIterator.hasNext()) {
            PortPairGroupId portPairGroupId = ppgIdListIterator.next();
            PortPairGroup ppg = portPairGroupService.getPortPairGroup(portPairGroupId);
            ppg.resetLoad();
        }
    }

    /**
     * Get next nsh service path identifier.
     *
     * @return value of service path identifier
     */
    int getNextNshSpi() {
        // If there is any free id use it. Otherwise generate new id.
        if (nshSpiIdFreeList.isEmpty()) {
            return (int) nshSpiIdGenerator.getNewId();
        }
        Iterator<Integer> it = nshSpiIdFreeList.iterator();
        Integer value = it.next();
        nshSpiIdFreeList.remove(value);
        return value;
    }

    private class SfcPacketProcessor implements PacketProcessor {

        /**
         * Check for given ip match with the fixed ips for the virtual port.
         *
         * @param vPortId virtual port id
         * @param ip ip address to match
         * @return true if the ip match with the fixed ips in virtual port false otherwise
         */
        private boolean checkIpInVirtualPort(VirtualPortId vPortId, IpAddress ip) {
            boolean found = false;
            Set<FixedIp> ips = virtualPortService.getPort(vPortId).fixedIps();
            for (FixedIp fixedIp : ips) {
                if (fixedIp.ip().equals(ip)) {
                    found = true;
                    break;
                }
            }
            return found;
        }

        /**
         * Find the port chain for the received packet.
         *
         * @param fiveTuple five tuple info from the packet
         * @return portChainId id of port chain, null if portChain is not found
         */
        private PortChainId findPortChainFromFiveTuple(FiveTuple fiveTuple) {

            PortChainId portChainId = null;

            Iterable<PortChain> portChains = portChainService.getPortChains();
            if (portChains == null) {
                log.error("Could not retrive port chain list");
                return null;
            }

            // Identify the port chain to which the packet belongs
            for (final PortChain portChain : portChains) {

                if (!portChain.tenantId().equals(fiveTuple.tenantId())) {
                    continue;
                }

                Iterable<FlowClassifierId> flowClassifiers = portChain.flowClassifiers();

                // One port chain can have multiple flow classifiers.
                for (final FlowClassifierId flowClassifierId : flowClassifiers) {

                    FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowClassifierId);
                    boolean match = false;
                    // Check whether protocol is set in flow classifier
                    if (flowClassifier.protocol() != null) {
                        if ((flowClassifier.protocol().equalsIgnoreCase("TCP")
                                && fiveTuple.protocol() == IPv4.PROTOCOL_TCP)
                                || (flowClassifier.protocol().equalsIgnoreCase("UDP")
                                        && fiveTuple.protocol() == IPv4.PROTOCOL_UDP)
                                        || (flowClassifier.protocol().equalsIgnoreCase("ICMP")
                                                && fiveTuple.protocol() == IPv4.PROTOCOL_ICMP)) {
                            match = true;
                        } else {
                            continue;
                        }
                    }

                    // Check whether source ip prefix is set in flow classifier
                    if (flowClassifier.srcIpPrefix() != null) {
                        if (flowClassifier.srcIpPrefix().contains(fiveTuple.ipSrc())) {
                            match = true;
                        } else {
                            continue;
                        }
                    }

                    // Check whether destination ip prefix is set in flow classifier
                    if (flowClassifier.dstIpPrefix() != null) {
                        if (flowClassifier.dstIpPrefix().contains(fiveTuple.ipDst())) {
                            match = true;
                        } else {
                            continue;
                        }
                    }

                    // Check whether source port is set in flow classifier
                    if (fiveTuple.portSrc().toLong() >= flowClassifier.minSrcPortRange() ||
                            fiveTuple.portSrc().toLong() <= flowClassifier.maxSrcPortRange()) {
                        match = true;
                    } else {
                        continue;
                    }

                    // Check whether destination port is set in flow classifier
                    if (fiveTuple.portDst().toLong() >= flowClassifier.minSrcPortRange() ||
                            fiveTuple.portDst().toLong() <= flowClassifier.maxSrcPortRange()) {
                        match = true;
                    } else {
                        continue;
                    }

                    // Check whether neutron source port is set in flow classfier
                    if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
                        match = checkIpInVirtualPort(VirtualPortId.portId(flowClassifier.srcPort().portId()),
                                                     fiveTuple.ipSrc());
                        if (!match) {
                            continue;
                        }
                    }

                    // Check whether destination neutron destination port is set in flow classifier
                    if ((flowClassifier.dstPort() != null) && (!flowClassifier.dstPort().portId().isEmpty())) {
                        match = checkIpInVirtualPort(VirtualPortId.portId(flowClassifier.dstPort().portId()),
                                                     fiveTuple.ipDst());
                        if (!match) {
                            continue;
                        }
                    }

                    if (match) {
                        portChainId = portChain.portChainId();
                        break;
                    }
                }
            }
            return portChainId;
        }

        /**
         * Get the tenant id for the given mac address.
         *
         * @param mac mac address
         * @return tenantId tenant id for the given mac address
         */
        private TenantId getTenantId(MacAddress mac) {
            Collection<VirtualPort> virtualPorts = virtualPortService.getPorts();
            for (VirtualPort virtualPort : virtualPorts) {
                if (virtualPort.macAddress().equals(mac)) {
                    return virtualPort.tenantId();
                }
            }
            return null;
        }

        @Override
        public void process(PacketContext context) {
            Ethernet packet = context.inPacket().parsed();
            if (packet == null || portChainService.getPortChainCount() == 0) {
                return;
            }
            // get the five tuple parameters for the packet
            short ethType = packet.getEtherType();
            IpAddress ipSrc = null;
            IpAddress ipDst = null;
            int portSrc = 0;
            int portDst = 0;
            byte protocol = 0;
            MacAddress macSrc = packet.getSourceMAC();
            MacAddress macDst = packet.getDestinationMAC();
            TenantId tenantId = getTenantId(macSrc);

            if (ethType == Ethernet.TYPE_IPV4) {
                IPv4 ipv4Packet = (IPv4) packet.getPayload();
                ipSrc = IpAddress.valueOf(ipv4Packet.getSourceAddress());
                ipDst = IpAddress.valueOf(ipv4Packet.getDestinationAddress());
                protocol = ipv4Packet.getProtocol();
                if (protocol == IPv4.PROTOCOL_TCP) {
                    TCP tcpPacket = (TCP) ipv4Packet.getPayload();
                    portSrc = tcpPacket.getSourcePort();
                    portDst = tcpPacket.getDestinationPort();
                } else if (protocol == IPv4.PROTOCOL_UDP) {
                    UDP udpPacket = (UDP) ipv4Packet.getPayload();
                    portSrc = udpPacket.getSourcePort();
                    portDst = udpPacket.getDestinationPort();
                } else if (protocol == IPv4.PROTOCOL_ICMP) {
                    // do nothing
                } else {
                    // No need to process other packets received by controller.
                    return;
                }
            } else {
                return;
            }

            FiveTuple fiveTuple = DefaultFiveTuple.builder()
                    .setIpSrc(ipSrc)
                    .setIpDst(ipDst)
                    .setPortSrc(PortNumber.portNumber(portSrc))
                    .setPortDst(PortNumber.portNumber(portDst))
                    .setProtocol(protocol)
                    .setTenantId(tenantId)
                    .setMacSrc(macSrc)
                    .setMacDst(macDst)
                    .build();

            PortChainId portChainId = findPortChainFromFiveTuple(fiveTuple);

            if (portChainId == null) {
                return;
            }

            // Once the 5 tuple and port chain are identified, give this input for load balancing
            addToPortChainIdFiveTupleMap(portChainId, fiveTuple);
            LoadBalanceId id = loadBalanceSfc(portChainId, fiveTuple);
            // Get nsh service path index
            NshServicePathId nshSpi;
            PortChain portChain = portChainService.getPortChain(portChainId);
            if (nshSpiPortChainMap.containsKey(portChain.portChainId())) {
                int nshSpiId = nshSpiPortChainMap.get(portChain.portChainId());
                nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId));
            } else {
                int nshSpiId = getNextNshSpi();
                if (nshSpiId > MAX_NSH_SPI_ID) {
                    log.error("Reached max limit of service path index."
                            + "Failed to install SFC for port chain {}", portChain.portChainId());
                    return;
                }
                nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId));
                nshSpiPortChainMap.put(portChain.portChainId(), new Integer(nshSpiId));
            }
            // download the required flow rules for classifier and forwarding
            // install in OVS.
            SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl(appId);
            flowRuleInstaller.installLoadBalancedFlowRules(portChain, fiveTuple, nshSpi);
            sendPacket(context);
        }

        /**
         * Send packet back to classifier.
         *
         * @param context packet context
         */
        private void sendPacket(PacketContext context) {

            ConnectPoint sourcePoint = context.inPacket().receivedFrom();

            TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(PortNumber.TABLE).build();
            OutboundPacket packet = new DefaultOutboundPacket(sourcePoint.deviceId(), treatment, context.inPacket()
                    .unparsed());
            packetService.emit(packet);
            log.trace("Sending packet: {}", packet);
        }
    }

    /**
     * Encapsulate 5 bit load balance id to nsh spi.
     *
     * @param id load balance identifier
     * @param nshSpiId nsh service path index
     * @return updated service path index
     */
    protected int getNshServicePathId(LoadBalanceId id, int nshSpiId) {
        int nshSpiNew = nshSpiId << 5;
        nshSpiNew = nshSpiNew | id.loadBalanceId();
        return nshSpiNew;
    }

    private void addToPortChainIdFiveTupleMap(PortChainId portChainId, FiveTuple fiveTuple) {
        List<FiveTuple> list = portChainFiveTupleMap.get(portChainId);
        list.add(fiveTuple);
        portChainFiveTupleMap.put(portChainId, list);
    }

    /**
     * Find the load balanced path set it to port chain for the given five
     * tuple.
     *
     * @param portChainId port chain id
     * @param fiveTuple five tuple info
     * @return load balance id
     */
    private LoadBalanceId loadBalanceSfc(PortChainId portChainId, FiveTuple fiveTuple) {

        // Get the port chain
        PortChain portChain = portChainService.getPortChain(portChainId);
        List<PortPairId> loadBalancePath = Lists.newArrayList();
        LoadBalanceId id;
        int paths = portChain.getLoadBalancePathSize();
        if (paths >= MAX_LOAD_BALANCE_ID) {
            log.info("Max limit reached for load balance paths. "
                    + "Reusing the created path for port chain {} with five tuple {}", portChainId, fiveTuple);
            id = LoadBalanceId.of((byte) ((paths + 1) % MAX_LOAD_BALANCE_ID));
            portChain.addLoadBalancePath(fiveTuple, id, portChain.getLoadBalancePath(id));
        }

        // Get the list of port pair groups from port chain
        Iterable<PortPairGroupId> portPairGroups = portChain.portPairGroups();
        for (final PortPairGroupId portPairGroupId : portPairGroups) {
            PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);

            // Get the list of port pair ids from port pair group.
            Iterable<PortPairId> portPairs = portPairGroup.portPairs();
            int minLoad = 0xFFF;
            PortPairId minLoadPortPairId = null;
            for (final PortPairId portPairId : portPairs) {
                int load = portPairGroup.getLoad(portPairId);
                if (load == 0) {
                    minLoadPortPairId = portPairId;
                    break;
                } else {
                    // Check the port pair which has min load.
                    if (load < minLoad) {
                        minLoad = load;
                        minLoadPortPairId = portPairId;
                    }
                }
            }
            if (minLoadPortPairId != null) {
                loadBalancePath.add(minLoadPortPairId);
                portPairGroup.addLoad(minLoadPortPairId);
            }
        }

        // Check if the path already exists, if not create a new id
        id = portChain.matchPath(loadBalancePath);
        if (id == null) {
            id = LoadBalanceId.of((byte) (paths + 1));
        }

        portChain.addLoadBalancePath(fiveTuple, id, loadBalancePath);
        return id;
    }

}
