[ONOS] Cherry picked from master 1.7

Change-Id: I74a0c1634f9c425af2bcb646edc3d9170b3c087c
diff --git a/protocols/pcep/ctl/BUCK b/protocols/pcep/ctl/BUCK
index dd7e29c..ae62881 100644
--- a/protocols/pcep/ctl/BUCK
+++ b/protocols/pcep/ctl/BUCK
@@ -2,6 +2,7 @@
     '//lib:CORE_DEPS',
     '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
     '//protocols/pcep/api:onos-protocols-pcep-api',
+    '//incubator/api:onos-incubator-api',
 ]
 
 osgi_jar_with_tests (
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
index 744731f..bbad497 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
@@ -55,6 +55,7 @@
 import org.onosproject.pcepio.types.IPv4RouterIdOfLocalNodeSubTlv;
 import org.onosproject.pcepio.types.NodeAttributesTlv;
 import org.onosproject.pcepio.types.PceccCapabilityTlv;
+import org.onosproject.pcepio.types.SrPceCapabilityTlv;
 import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
 import org.onosproject.pcepio.types.PcepErrorDetailInfo;
 import org.onosproject.pcepio.types.PcepValueType;
@@ -260,6 +261,8 @@
                         disconnectDuplicate(h);
                     } else {
                         h.setState(ESTABLISHED);
+                        //Session is established, add a PCEP device
+                        h.addNode();
                     }
                 }
             }
@@ -469,6 +472,20 @@
     }
 
     /**
+     * Adds PCEP device once session is established.
+     */
+    private void addNode() {
+        pc.addNode(pc);
+    }
+
+    /**
+     * Deletes PCEP device when session is disconnected.
+     */
+    private void deleteNode() {
+        pc.deleteNode(pc.getPccId());
+    }
+
+    /**
      * Return a string describing this client based on the already available
      * information (ip address and/or remote socket).
      *
@@ -523,6 +540,8 @@
         boolean pceccCapability = false;
         boolean statefulPceCapability = false;
         boolean pcInstantiationCapability = false;
+        boolean labelStackCapability = false;
+        boolean srCapability = false;
 
         ListIterator<PcepValueType> listIterator = tlvList.listIterator();
         while (listIterator.hasNext()) {
@@ -531,6 +550,9 @@
             switch (tlv.getType()) {
             case PceccCapabilityTlv.TYPE:
                 pceccCapability = true;
+                if (((PceccCapabilityTlv) tlv).sBit()) {
+                    labelStackCapability = true;
+                }
                 break;
             case StatefulPceCapabilityTlv.TYPE:
                 statefulPceCapability = true;
@@ -539,11 +561,15 @@
                     pcInstantiationCapability = true;
                 }
                 break;
+            case SrPceCapabilityTlv.TYPE:
+                srCapability = true;
+                break;
             default:
                 continue;
             }
         }
-        this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability);
+        this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability,
+                labelStackCapability, srCapability);
     }
 
     /**
@@ -563,6 +589,8 @@
      */
     private void sendErrMsgAndCloseChannel() {
         // TODO send error message
+        //Remove PCEP device from topology
+        deleteNode();
         channel.close();
     }
 
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
index 1f58bed..20c2856 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
@@ -15,34 +15,66 @@
  */
 package org.onosproject.pcep.controller.impl;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 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.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.incubator.net.tunnel.Tunnel.State;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.pcep.controller.LspKey;
 import org.onosproject.pcep.controller.PccId;
 import org.onosproject.pcep.controller.PcepClient;
 import org.onosproject.pcep.controller.PcepClientController;
 import org.onosproject.pcep.controller.PcepClientListener;
 import org.onosproject.pcep.controller.PcepEventListener;
+import org.onosproject.pcep.controller.PcepNodeListener;
+import org.onosproject.pcep.controller.PcepPacketListener;
+import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcep.controller.driver.PcepAgent;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcInitiatedLspRequest;
 import org.onosproject.pcepio.protocol.PcepError;
 import org.onosproject.pcepio.protocol.PcepErrorInfo;
 import org.onosproject.pcepio.protocol.PcepErrorMsg;
 import org.onosproject.pcepio.protocol.PcepErrorObject;
 import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepInitiateMsg;
+import org.onosproject.pcepio.protocol.PcepLspObject;
 import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepReportMsg;
+import org.onosproject.pcepio.protocol.PcepStateReport;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
+import org.onosproject.pcepio.types.SymbolicPathNameTlv;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.checkNotNull;
 
+import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.REMOVE;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.SEND_UPDATE;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.SEND_DELETE;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.UNSTABLE;
 import static org.onosproject.pcepio.types.PcepErrorDetailInfo.ERROR_TYPE_19;
 import static org.onosproject.pcepio.types.PcepErrorDetailInfo.ERROR_VALUE_5;
 
@@ -55,6 +87,9 @@
 
     private static final Logger log = LoggerFactory.getLogger(PcepClientControllerImpl.class);
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
     protected ConcurrentHashMap<PccId, PcepClient> connectedClients =
             new ConcurrentHashMap<>();
 
@@ -62,9 +97,23 @@
     protected Set<PcepClientListener> pcepClientListener = new HashSet<>();
 
     protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
+    protected Set<PcepNodeListener> pcepNodeListener = Sets.newHashSet();
+    protected Set<PcepPacketListener> pcepPacketListener = Sets.newHashSet();
 
     private final Controller ctrl = new Controller();
 
+    public static final String BANDWIDTH = "bandwidth";
+    public static final String LSP_SIG_TYPE = "lspSigType";
+    public static final String PCC_TUNNEL_ID = "PccTunnelId";
+    public static final String PLSP_ID = "PLspId";
+    public static final String LOCAL_LSP_ID = "localLspId";
+    public static final String PCE_INIT = "pceInit";
+    public static final String COST_TYPE = "costType";
+    public static final String DELEGATE = "delegation";
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TunnelService tunnelService;
+
     @Activate
     public void activate() {
         ctrl.start(agent);
@@ -112,11 +161,31 @@
     }
 
     @Override
+    public void addPacketListener(PcepPacketListener listener) {
+        pcepPacketListener.add(listener);
+    }
+
+    @Override
+    public void removePacketListener(PcepPacketListener listener) {
+        pcepPacketListener.remove(listener);
+    }
+
+    @Override
     public void writeMessage(PccId pccId, PcepMessage msg) {
         this.getClient(pccId).sendMessage(msg);
     }
 
     @Override
+    public void addNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.add(listener);
+    }
+
+    @Override
+    public void removeNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.remove(listener);
+    }
+
+    @Override
     public void processClientMessage(PccId pccId, PcepMessage msg) {
         PcepClient pc = getClient(pccId);
 
@@ -162,8 +231,48 @@
         case REPORT:
             //Only update the listener if respective capability is supported else send PCEP-ERR msg
             if (pc.capability().statefulPceCapability()) {
-                for (PcepEventListener l : pcepEventListener) {
-                    l.handleMessage(pccId, msg);
+
+                ListIterator<PcepStateReport> listIterator = ((PcepReportMsg) msg).getStateReportList().listIterator();
+                while (listIterator.hasNext()) {
+                    PcepStateReport stateRpt = listIterator.next();
+                    if (stateRpt.getLspObject().getSFlag()) {
+                        if (pc.lspDbSyncStatus() != PcepSyncStatus.IN_SYNC) {
+                            // Initialize LSP DB sync and temporary cache.
+                            pc.setLspDbSyncStatus(PcepSyncStatus.IN_SYNC);
+                            pc.initializeSyncMsgList(pccId);
+                        }
+                        // Store stateRpt in temporary cache.
+                        pc.addSyncMsgToList(pccId, stateRpt);
+
+                        // Don't send to provider as of now.
+                        continue;
+                    } else {
+                        if (pc.lspDbSyncStatus() == PcepSyncStatus.IN_SYNC) {
+                            // Set end of LSPDB sync.
+                            pc.setLspDbSyncStatus(PcepSyncStatus.SYNCED);
+
+                            // Call packet provider to initiate label DB sync (only if PCECC capable).
+                            if (pc.capability().pceccCapability()) {
+                                pc.setLabelDbSyncStatus(IN_SYNC);
+                                for (PcepPacketListener l : pcepPacketListener) {
+                                    l.sendPacketIn(pccId);
+                                }
+                            } else {
+                                // If label db sync is not to be done, handle end of LSPDB sync actions.
+                                agent.analyzeSyncMsgList(pccId);
+                            }
+                            continue;
+                        }
+                    }
+
+                    // It's a usual report message while sync is not undergoing. So process it immediately.
+                    LinkedList<PcepStateReport> llPcRptList = new LinkedList<>();
+                    llPcRptList.add(stateRpt);
+                    PcepMessage pcReportMsg = pc.factory().buildReportMsg().setStateReportList((llPcRptList))
+                            .build();
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleMessage(pccId, pcReportMsg);
+                    }
                 }
             } else {
                 // Send PCEP-ERROR message.
@@ -173,6 +282,8 @@
             break;
         case LABEL_RANGE_RESERV:
             break;
+        case LS_REPORT: //TODO: need to handle LS report to add or remove node
+            break;
         case MAX:
             break;
         case END:
@@ -270,5 +381,176 @@
         public void processPcepMessage(PccId pccId, PcepMessage m) {
             processClientMessage(pccId, m);
         }
+
+        @Override
+        public void addNode(PcepClient pc) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.addNode(pc);
+            }
+        }
+
+        @Override
+        public void deleteNode(PccId pccId) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.deleteNode(pccId);
+            }
+        }
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        @Override
+        public boolean analyzeSyncMsgList(PccId pccId) {
+            PcepClient pc = getClient(pccId);
+            /*
+             * PLSP_ID is null while tunnel is created at PCE and PCInit msg carries it as 0. It is allocated by PCC and
+             * in that case it becomes the first PCRpt msg from PCC for this LSP, and hence symbolic path name must be
+             * carried in the PCRpt msg. Draft says: The SYMBOLIC-PATH-NAME TLV "MUST" be included in the LSP object in
+             * the LSP State Report (PCRpt) message when during a given PCEP session an LSP is "first" reported to a
+             * PCE. So two separate lists with separate keys are maintained.
+             */
+            Map<LspKey, Tunnel> preSyncLspDbByKey = new HashMap<>();
+            Map<String, Tunnel> preSyncLspDbByName = new HashMap<>();
+
+            // Query tunnel service and fetch all the tunnels with this PCC as ingress.
+            // Organize into two maps, with LSP key if known otherwise with symbolic path name, for quick search.
+            Collection<Tunnel> queriedTunnels = tunnelService.queryTunnel(Tunnel.Type.MPLS);
+            for (Tunnel tunnel : queriedTunnels) {
+                if (((IpTunnelEndPoint) tunnel.src()).ip().equals(pccId.ipAddress())) {
+                    String pLspId = tunnel.annotations().value(PLSP_ID);
+                    if (pLspId != null) {
+                        String localLspId = tunnel.annotations().value(LOCAL_LSP_ID);
+                        checkNotNull(localLspId);
+                        LspKey lspKey = new LspKey(Integer.valueOf(pLspId), Short.valueOf(localLspId));
+                        preSyncLspDbByKey.put(lspKey, tunnel);
+                    } else {
+                        preSyncLspDbByName.put(tunnel.tunnelName().value(), tunnel);
+                    }
+                }
+            }
+
+            List<PcepStateReport> syncStateRptList = pc.getSyncMsgList(pccId);
+            Iterator<PcepStateReport> stateRptListIterator = syncStateRptList.iterator();
+
+            // For every report, fetch PLSP id, local LSP id and symbolic path name from the message.
+            while (syncStateRptList.iterator().hasNext()) {
+                PcepStateReport stateRpt = stateRptListIterator.next();
+                Tunnel tunnel = null;
+
+                PcepLspObject lspObj = stateRpt.getLspObject();
+                ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
+                StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv = null;
+                SymbolicPathNameTlv pathNameTlv = null;
+
+                while (listTlvIterator.hasNext()) {
+                    PcepValueType tlv = listTlvIterator.next();
+                    switch (tlv.getType()) {
+                    case StatefulIPv4LspIdentifiersTlv.TYPE:
+                        ipv4LspIdenTlv = (StatefulIPv4LspIdentifiersTlv) tlv;
+                        break;
+
+                    case SymbolicPathNameTlv.TYPE:
+                        pathNameTlv = (SymbolicPathNameTlv) tlv;
+                        break;
+
+                    default:
+                        break;
+                    }
+                }
+
+                LspKey lspKeyOfRpt = new LspKey(lspObj.getPlspId(), ipv4LspIdenTlv.getLspId());
+                tunnel = preSyncLspDbByKey.get(lspKeyOfRpt);
+                // PCE tunnel is matched with PCRpt LSP. Now delete it from the preSyncLspDb list as the residual
+                // non-matching list will be processed at the end.
+                if (tunnel != null) {
+                    preSyncLspDbByKey.remove(lspKeyOfRpt);
+                } else if (pathNameTlv != null) {
+                    tunnel = preSyncLspDbByName.get(Arrays.toString(pathNameTlv.getValue()));
+                    if (tunnel != null) {
+                        preSyncLspDbByName.remove(tunnel.tunnelName());
+                    }
+                }
+
+                if (tunnel == null) {
+                    // If remove flag is set, and tunnel is not known to PCE, ignore it.
+                    if (lspObj.getCFlag() && !lspObj.getRFlag()) {
+                        // For initiated LSP, need to send PCInit delete msg.
+                        try {
+                            PcInitiatedLspRequest releaseLspRequest = pc.factory().buildPcInitiatedLspRequest()
+                                    .setLspObject(lspObj).build();
+                            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList
+                                    = new LinkedList<PcInitiatedLspRequest>();
+                            llPcInitiatedLspRequestList.add(releaseLspRequest);
+
+                            PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
+                                    .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList).build();
+
+                            for (PcepEventListener l : pcepEventListener) {
+                                l.handleEndOfSyncAction(pccId, pcInitiateMsg, SEND_DELETE);
+                            }
+
+                        } catch (PcepParseException e) {
+                            log.error("Exception occured while sending initiate delete message {}", e.getMessage());
+                        }
+                    }
+                    continue;
+                }
+
+                if (!lspObj.getCFlag()) {
+                    // For learned LSP process both add/update PCRpt.
+                    LinkedList<PcepStateReport> llPcRptList = new LinkedList<>();
+                    llPcRptList.add(stateRpt);
+                    PcepMessage pcReportMsg = pc.factory().buildReportMsg().setStateReportList((llPcRptList))
+                            .build();
+
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleMessage(pccId, pcReportMsg);
+                    }
+                    continue;
+                }
+
+                // Implied that tunnel != null and lspObj.getCFlag() is set
+                // State different for PCC sent LSP and PCE known LSP, send PCUpd msg.
+                State tunnelState = PcepLspStatus
+                        .getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
+                if (tunnelState != tunnel.state()) {
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleEndOfSyncAction(tunnel, SEND_UPDATE);
+                    }
+                }
+            }
+
+            // Check which tunnels are extra at PCE that were not reported by PCC.
+            Map<Object, Tunnel> preSyncLspDb = (Map) preSyncLspDbByKey;
+            handleResidualTunnels(preSyncLspDb);
+            preSyncLspDbByKey = null;
+
+            preSyncLspDb = (Map) preSyncLspDbByName;
+            handleResidualTunnels(preSyncLspDb);
+            preSyncLspDbByName = null;
+            preSyncLspDb = null;
+
+            pc.removeSyncMsgList(pccId);
+            return true;
+        }
+
+        /*
+         * Go through the tunnels which are known by PCE but were not reported by PCC during LSP DB sync and take
+         * appropriate actions.
+         */
+        private void handleResidualTunnels(Map<Object, Tunnel> preSyncLspDb) {
+            for (Tunnel pceExtraTunnel : preSyncLspDb.values()) {
+                if (pceExtraTunnel.annotations().value(PCE_INIT) == null
+                        || "false".equalsIgnoreCase(pceExtraTunnel.annotations().value(PCE_INIT))) {
+                    // PCC initiated tunnels should be removed from tunnel store.
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleEndOfSyncAction(pceExtraTunnel, REMOVE);
+                    }
+                } else {
+                    // PCE initiated tunnels should be initiated again.
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleEndOfSyncAction(pceExtraTunnel, UNSTABLE);
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java
index 8328f2b..a62a611 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java
@@ -19,13 +19,18 @@
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.RejectedExecutionException;
 
 import org.jboss.netty.channel.Channel;
 import org.onlab.packet.IpAddress;
 import org.onosproject.pcep.controller.ClientCapability;
+import org.onosproject.pcep.controller.LspKey;
 import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
 import org.onosproject.pcep.controller.PcepPacketStats;
 import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcep.controller.driver.PcepAgent;
@@ -33,6 +38,7 @@
 import org.onosproject.pcepio.protocol.PcepFactories;
 import org.onosproject.pcepio.protocol.PcepFactory;
 import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepStateReport;
 import org.onosproject.pcepio.protocol.PcepVersion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,6 +72,8 @@
     private byte deadTime;
     private byte sessionId;
     private PcepPacketStatsImpl pktStats;
+    private Map<LspKey, Boolean> lspDelegationInfo;
+    private Map<PccId, List<PcepStateReport>> sycRptCache = new HashMap<>();
 
     @Override
     public void init(PccId pccId, PcepVersion pcepVersion, PcepPacketStats pktStats) {
@@ -188,7 +196,14 @@
 
     @Override
     public void setLabelDbSyncStatus(PcepSyncStatus syncStatus) {
+
+        PcepSyncStatus syncOldStatus = labelDbSyncStatus();
         this.labelDbSyncStatus = syncStatus;
+
+        if ((syncOldStatus == PcepSyncStatus.IN_SYNC) && (syncStatus == PcepSyncStatus.SYNCED)) {
+            // Perform end of LSP DB sync actions.
+            this.agent.analyzeSyncMsgList(pccId);
+        }
     }
 
     @Override
@@ -203,6 +218,16 @@
     }
 
     @Override
+    public void addNode(PcepClient pc) {
+        this.agent.addNode(pc);
+    }
+
+    @Override
+    public void deleteNode(PccId pccId) {
+        this.agent.deleteNode(pccId);
+    }
+
+    @Override
     public final boolean connectClient() {
         return this.agent.addConnectedClient(pccId, this);
     }
@@ -230,6 +255,39 @@
     }
 
     @Override
+    public void setLspAndDelegationInfo(LspKey lspKey, boolean dFlag) {
+        lspDelegationInfo.put(lspKey, dFlag);
+    }
+
+    @Override
+    public Boolean delegationInfo(LspKey lspKey) {
+        return lspDelegationInfo.get(lspKey);
+    }
+
+    @Override
+    public void initializeSyncMsgList(PccId pccId) {
+        List<PcepStateReport> rptMsgList = new LinkedList<>();
+        sycRptCache.put(pccId, rptMsgList);
+    }
+
+    @Override
+    public List<PcepStateReport> getSyncMsgList(PccId pccId) {
+        return sycRptCache.get(pccId);
+    }
+
+    @Override
+    public void removeSyncMsgList(PccId pccId) {
+        sycRptCache.remove(pccId);
+    }
+
+    @Override
+    public void addSyncMsgToList(PccId pccId, PcepStateReport rptMsg) {
+        List<PcepStateReport> rptMsgList = sycRptCache.get(pccId);
+        rptMsgList.add(rptMsg);
+        sycRptCache.put(pccId, rptMsgList);
+    }
+
+    @Override
     public boolean isOptical() {
         return false;
     }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepLspStatus.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepLspStatus.java
new file mode 100644
index 0000000..79ed9fe
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepLspStatus.java
@@ -0,0 +1,103 @@
+/*
+ * 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.pcep.controller.impl;
+
+import org.onosproject.incubator.net.tunnel.Tunnel.State;
+
+/**
+ * Representation of the PCEP LSP state.
+ */
+public enum PcepLspStatus {
+
+    /**
+     * Signifies that the LSP is not active.
+     */
+    DOWN,
+
+    /**
+     * Signifies that the LSP is signalled.
+     */
+    UP,
+
+    /**
+     * Signifies that the LSP is up and carrying traffic.
+     */
+    ACTIVE,
+
+    /**
+     * Signifies that the LSP is being torn down, resources are being released.
+     */
+    GOING_DOWN,
+
+    /**
+     * Signifies that the LSP is being signalled.
+     */
+    GOING_UP;
+
+    /**
+     * Returns the applicable PCEP LSP status corresponding to ONOS tunnel state.
+     *
+     * @param tunnelState ONOS tunnel state
+     * @return LSP status as per protocol
+     */
+    public static PcepLspStatus getLspStatusFromTunnelStatus(State tunnelState) {
+
+        switch (tunnelState) {
+
+        case INIT:
+            return PcepLspStatus.DOWN;
+
+        case ESTABLISHED:
+            return PcepLspStatus.GOING_UP;
+
+        case ACTIVE:
+            return PcepLspStatus.UP;
+
+        case FAILED: // fall through
+        case INACTIVE: // LSP is administratively down.
+        default:
+            return PcepLspStatus.DOWN;
+        }
+    }
+
+    /**
+     * Returns the applicable ONOS tunnel state corresponding to PCEP LSP status.
+     *
+     * @param lspState PCEP LSP status
+     * @return tunnel state
+     */
+    public static State getTunnelStatusFromLspStatus(PcepLspStatus lspState) {
+
+        switch (lspState) {
+
+        case DOWN:
+            return State.FAILED;
+
+        case UP: // fall through
+        case ACTIVE:
+            return State.ACTIVE;
+
+        case GOING_DOWN:
+            return State.FAILED;
+
+        case GOING_UP:
+            return State.ESTABLISHED;
+
+        default:
+            return State.FAILED;
+        }
+    }
+}