[ONOS-4170] PCEP provider changes for LSPDB sync

Change-Id: I9229fec9d97dd46343cc809e33c92b9722ab7ed3
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java
index 5e3996a..afeeae8 100644
--- a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java
@@ -95,18 +95,32 @@
     String channelId();
 
     /**
-     * To set the status of state synchronization.
+     * Sets the status of LSP state synchronization.
      *
-     * @param value to set the synchronization status
+     * @param syncStatus LSP synchronization status to be set
      */
-    void setIsSyncComplete(boolean value);
+    void setLspDbSyncStatus(PcepSyncStatus syncStatus);
 
     /**
-     * Indicates the state synchronization status of this pcc.
+     * Indicates the LSP state synchronization status of this pcc.
      *
-     * @return true/false if the synchronization is completed/not completed
+     * @return LSP state synchronization status.
      */
-    boolean isSyncComplete();
+    PcepSyncStatus lspDbSyncStatus();
+
+    /**
+     * Sets the status of label DB synchronization.
+     *
+     * @param syncStatus label DB synchronization status to be set
+     */
+    void setLabelDbSyncStatus(PcepSyncStatus syncStatus);
+
+    /**
+     * Indicates the label DB synchronization status of this pcc.
+     *
+     * @return label DB synchronization status.
+     */
+    PcepSyncStatus labelDbSyncStatus();
 
     /**
      * Sets capability negotiated during open message exchange.
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepSyncStatus.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepSyncStatus.java
new file mode 100644
index 0000000..3c8ace5
--- /dev/null
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepSyncStatus.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+/**
+ * Representation of PCEP database sync status on session establishment.
+ */
+public enum PcepSyncStatus {
+
+    /**
+     * Specifies that the DB state is not synchronized.
+     */
+    NOT_SYNCED(0),
+
+    /**
+     * Specifies that the DB state is currently undergoing synchronization.
+     */
+    IN_SYNC(1),
+
+    /**
+     * Specifies that the DB state synchronization is completed.
+     */
+    SYNCED(2);
+
+    int value;
+
+    /**
+     * Assign val with the value as the sync status.
+     *
+     * @param val sync status
+     */
+    PcepSyncStatus(int val) {
+        value = val;
+    }
+}
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 9f61b2a..744731f 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
@@ -169,6 +169,12 @@
                             }
                         }
 
+                        /*
+                         * If MPLS LSR id and PCEP session socket IP addresses are not same,
+                         * the MPLS LSR id will be encoded in separate TLV.
+                         * We always maintain session information based on LSR ids.
+                         * The socket IP is stored in channel.
+                         */
                         LinkedList<PcepValueType> optionalTlvs = pOpenmsg.getPcepOpenObject().getOptionalTlv();
                         for (PcepValueType optionalTlv : optionalTlvs) {
                             if (optionalTlv instanceof NodeAttributesTlv) {
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 23b6ba6..8328f2b 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
@@ -27,6 +27,7 @@
 import org.onosproject.pcep.controller.ClientCapability;
 import org.onosproject.pcep.controller.PccId;
 import org.onosproject.pcep.controller.PcepPacketStats;
+import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcep.controller.driver.PcepAgent;
 import org.onosproject.pcep.controller.driver.PcepClientDriver;
 import org.onosproject.pcepio.protocol.PcepFactories;
@@ -52,9 +53,10 @@
     protected String channelId;
 
     private boolean connected;
-    protected boolean startDriverHandshakeCalled = false;
-    protected boolean isHandShakeComplete = false;
-    protected boolean isSyncComplete = false;
+    protected boolean startDriverHandshakeCalled;
+    protected boolean isHandShakeComplete;
+    private PcepSyncStatus lspDbSyncStatus;
+    private PcepSyncStatus labelDbSyncStatus;
     private PccId pccId;
     private PcepAgent agent;
 
@@ -175,13 +177,23 @@
     }
 
     @Override
-    public void setIsSyncComplete(boolean value) {
-        this.isSyncComplete = value;
+    public void setLspDbSyncStatus(PcepSyncStatus syncStatus) {
+        this.lspDbSyncStatus = syncStatus;
     }
 
     @Override
-    public boolean isSyncComplete() {
-        return isSyncComplete;
+    public PcepSyncStatus lspDbSyncStatus() {
+        return lspDbSyncStatus;
+    }
+
+    @Override
+    public void setLabelDbSyncStatus(PcepSyncStatus syncStatus) {
+        this.labelDbSyncStatus = syncStatus;
+    }
+
+    @Override
+    public PcepSyncStatus labelDbSyncStatus() {
+        return labelDbSyncStatus;
     }
 
     @Override
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java
index b7d9666..13469e9 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLspObjectVer1.java
@@ -48,7 +48,7 @@
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-     |                PLSP-ID                |  Flag  C|    O|A|R|S|D|
+     |                PLSP-ID                |  Flag |C|    O|A|R|S|D|
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      //                        TLVs                                 //
      |                                                               |
@@ -116,6 +116,7 @@
      * @param bRFlag R flag
      * @param bSFlag S flag
      * @param bDFlag D flag
+     * @param bCFlag C flag
      * @param llOptionalTlv list of optional tlv
      */
     public PcepLspObjectVer1(PcepObjectHeader lspObjHeader, int iPlspId, byte yOFlag, boolean bAFlag, boolean bRFlag,
@@ -294,6 +295,9 @@
         }
 
         int iTemp = iPlspId << PLSPID_SHIFT_VALUE;
+
+        iTemp = iTemp | (((bCFlag) ? BIT_SET : BIT_RESET) << CFLAG_SHIFT_VALUE);
+
         iTemp = iTemp | (yOFlag << OFLAG_SHIFT_VALUE);
         byte bFlag;
         iTemp = bAFlag ? (iTemp | AFLAG_TEMP_SHIFT_VALUE) : iTemp;
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java
index 5b9ef66..63ad05d 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java
@@ -51,4 +51,9 @@
      * Annotation key for the LSP id assigned per tunnel.
      */
     public static final String LOCAL_LSP_ID = "localLspId";
+
+    /**
+     * Annotation key for the identification of initiated LSP.
+     */
+    public static final String PCE_INIT = "pceInit";
 }
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java
index 027a9a2..97cdce6 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java
@@ -18,7 +18,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.commons.collections.map.MultiKeyMap;
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.tunnel.TunnelProviderService;
 import org.slf4j.Logger;
@@ -40,8 +39,6 @@
     private Map<Integer, PcepTunnelData> tunnelDB;
     // Map to store the tunnel ids, given by core and given by pcc.
     private Map<TunnelId, Integer> tunnelIdMap;
-    //Map to store all the learnt tunnels.
-    private MultiKeyMap pccTunnelDB = new MultiKeyMap();
 
     TunnelProviderService tunnelApiMapperservice;
 
@@ -193,14 +190,4 @@
         boolean retValue = tunnelDB.containsKey((new Integer(value)));
         return retValue;
     }
-
-    /**
-     * Add Learnt tunnels to pcc tunnel DB.
-     *
-     * @param pcepTunnelData pcep tunnel data
-     */
-    public void addPccTunnelDB(PcepTunnelData pcepTunnelData) {
-        pccTunnelDB.put(pcepTunnelData.statefulIpv4IndentifierTlv().getTunnelId() & 0xFFFFL,
-                        pcepTunnelData.statefulIpv4IndentifierTlv().getIpv4IngressAddress(), pcepTunnelData);
-    }
 }
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
index 0ac46a9..cb1922a 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
@@ -73,6 +73,7 @@
 import org.onosproject.pcep.controller.PcepClientController;
 import org.onosproject.pcep.controller.PcepClientListener;
 import org.onosproject.pcep.controller.PcepEventListener;
+import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcepio.exceptions.PcepParseException;
 import org.onosproject.pcepio.protocol.PcInitiatedLspRequest;
 import org.onosproject.pcepio.protocol.PcepAttribute;
@@ -98,6 +99,7 @@
 import org.slf4j.Logger;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
@@ -105,6 +107,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Map;
 import java.util.Optional;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -116,15 +119,20 @@
 import static org.onosproject.net.PortNumber.portNumber;
 import static org.onosproject.pcep.api.PcepDpid.uri;
 import static org.onosproject.provider.pcep.tunnel.impl.LspType.WITH_SIGNALLING;
+import static org.onosproject.provider.pcep.tunnel.impl.LspType.SR_WITHOUT_SIGNALLING;
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.BANDWIDTH;
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.LOCAL_LSP_ID;
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.LSP_SIG_TYPE;
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PCC_TUNNEL_ID;
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PLSP_ID;
+import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PCE_INIT;
 import static org.onosproject.provider.pcep.tunnel.impl.RequestType.CREATE;
 import static org.onosproject.provider.pcep.tunnel.impl.RequestType.DELETE;
 import static org.onosproject.provider.pcep.tunnel.impl.RequestType.LSP_STATE_RPT;
 import static org.onosproject.provider.pcep.tunnel.impl.RequestType.UPDATE;
+import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -174,6 +182,10 @@
     protected PcepTunnelApiMapper pcepTunnelApiMapper = new PcepTunnelApiMapper();
     private static final int DEFAULT_BANDWIDTH_VALUE = 10;
 
+    private Map<IpAddress, Map<TunnelId, Tunnel>> preSyncLspDbMap = new HashMap<>();
+    private Map<IpAddress, List<Tunnel>> syncCompleteDeleteList = new HashMap<>();
+    private Map<IpAddress, List<Tunnel>> syncCompleteUpdateList = new HashMap<>();
+
     /**
      * Creates a Tunnel provider.
      */
@@ -1089,13 +1101,39 @@
 
                             // Check the sync status
                             if (lspObj.getSFlag()) {
-                                handleSyncReport(stateRpt);
+                                if (pcepClientController.getClient(pccId).lspDbSyncStatus() != IN_SYNC) {
+                                    pcepClientController.getClient(pccId).setLspDbSyncStatus(IN_SYNC);
+
+                                    // On starting LSP-DB sync, store LSP DB locally for this PCC.
+                                    Map<TunnelId, Tunnel> preSyncLspDb = new HashMap<>();
+                                    Collection<Tunnel> queriedTunnels = tunnelService.queryTunnel(MPLS);
+
+                                    for (Tunnel tunnel : queriedTunnels) {
+                                        if (((IpTunnelEndPoint) tunnel.src()).ip().equals(pccId.ipAddress())) {
+                                            preSyncLspDb.put(tunnel.tunnelId(), tunnel);
+                                        }
+                                    }
+
+                                    preSyncLspDbMap.put(pccId.ipAddress(), preSyncLspDb);
+                                    syncCompleteDeleteList.put(pccId.ipAddress(), new LinkedList<>());
+                                    syncCompleteUpdateList.put(pccId.ipAddress(), new LinkedList<>());
+                                }
+                                handleRptWithoutSrpId(stateRpt, pccId, IN_SYNC);
                                 continue;
-                            } else if (!pcepClientController.getClient(pccId).isSyncComplete()) {
-                                // sync is done
-                                pcepClientController.getClient(pccId).setIsSyncComplete(true);
+
+                            } else if (pcepClientController.getClient(pccId).lspDbSyncStatus() == IN_SYNC) {
+                                // If sync flag is not set in the msg, and the
+                                // previous state was "in sync" means this is
+                                // end of sync message. PCRpt for end of sync
+                                // does not carry any LSP report.
+                                pcepClientController.getClient(pccId).setLspDbSyncStatus(SYNCED);
+                                handleEndOfSyncAction(pccId);
                                 continue;
                             }
+
+                            // For PCRpt without matching SRP id not during LSPDB sync.
+                            handleRptWithoutSrpId(stateRpt, pccId, SYNCED);
+                            continue;
                         }
 
                         handleReportMessage(srpId, lspObj, stateRpt);
@@ -1121,11 +1159,6 @@
             ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
             PcepTunnelData pcepTunnelData = pcepTunnelApiMapper.getDataFromTunnelRequestQueue(srpId);
 
-            if (pcepTunnelData == null) {
-                handleRptWithoutSrpId(stateRpt);
-                return;
-            }
-
             // store the values required from report message
             pcepTunnelData.setPlspId(lspObj.getPlspId());
             pcepTunnelData.setLspAFlag(lspObj.getAFlag());
@@ -1176,117 +1209,43 @@
                 pcepTunnelApiMapper.handleUpdateTunnelRequestQueue(srpId, pcepTunnelData);
             }
 
+            PcepLspStatus pcepLspStatus = PcepLspStatus.values()[lspObj.getOFlag()];
+
             if (lspObj.getRFlag()) {
                 tunnelRemoved(td);
             } else {
-                State tunnelState = PcepLspStatus
-                        .getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
+                State tunnelState = PcepLspStatus.getTunnelStatusFromLspStatus(pcepLspStatus);
                 tunnelUpdated(td, tunnelState);
             }
+
+            // SR-TE also needs PCUpd msg after receiving PCRpt with status GOING-UP even
+            // though there are no labels to download for SR-TE.
+            if ((pcepLspStatus == PcepLspStatus.GOING_UP)
+                    && (LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)) == SR_WITHOUT_SIGNALLING)) {
+                updateTunnel(tunnel, tunnel.path());
+            }
         }
 
-        /**
-         * Handles asynchronous report messages from PCC when LSPDB sync is not in progress.
-         *
-         * @param stateRpt parsed PCEP report msg.
-         */
-        private void handleRptWithoutSrpId(PcepStateReport stateRpt) {
+        private void handleRptWithoutSrpId(PcepStateReport stateRpt, PccId pccId, PcepSyncStatus syncStatus) {
             ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
-            StatefulIPv4LspIdentifiersTlv ipv4LspTlv = null;
-
-            PcepLspObject lspObj = stateRpt.getLspObject();
-            ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
-
-            while (listTlvIterator.hasNext()) {
-                PcepValueType tlv = listTlvIterator.next();
-                if (tlv.getType() == StatefulIPv4LspIdentifiersTlv.TYPE) {
-                    ipv4LspTlv = (StatefulIPv4LspIdentifiersTlv) tlv;
-                    break;
-                }
-            }
-
-            checkNotNull(ipv4LspTlv);
-
-            IpTunnelEndPoint tunnelEndPointSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(ipv4LspTlv
-                    .getIpv4IngressAddress()));
-            IpTunnelEndPoint tunnelEndPointDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(ipv4LspTlv
-                    .getIpv4EgressAddress()));
-
-            Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnelEndPointSrc, tunnelEndPointDst);
-
-            Tunnel tunnel = null;
-            // Asynchronous status change message from PCC for LSP reported earlier.
-            for (Tunnel tunnelObj : tunnelQueryResult) {
-                if ((tunnelObj.annotations().value(PLSP_ID) == null)
-                        || (tunnelObj.annotations().value(LOCAL_LSP_ID) == null)) {
-                    /*
-                     *  Can skip this tunnel as this is one for which PCE has
-                     *  sent PCInit/PCUpd msg and waiting for a PCRpt.
-                     */
-                    continue;
-                }
-
-                if ((Integer.valueOf(tunnelObj.annotations().value(PLSP_ID)) == lspObj.getPlspId())
-                        && (Integer.valueOf(tunnelObj.annotations().value(LOCAL_LSP_ID))
-                                == ipv4LspTlv.getLspId())) {
-                    tunnel = tunnelObj;
-                    break;
-                }
-            }
-
-            // Status report for a new LSP when LSPDB sync was already completed sometime.
-            // No need to add the tunnel if msg is for remove but store doesn't have an entry.
-            if (tunnel == null) {
-                if (!lspObj.getRFlag()) {
-                    handleSyncReport(stateRpt);
-                }
-                return;
-            }
-
-            DefaultTunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(),
-                                                                       tunnel.dst(), tunnel.type(), tunnel.groupId(),
-                                                                       providerId, tunnel.tunnelName(), tunnel.path(),
-                                                                       (SparseAnnotations) tunnel.annotations());
-
-            if (lspObj.getRFlag()) {
-                tunnelRemoved(td); // This will happen only for PCC initiated tunnels.
-            } else {
-                State tunnelState = PcepLspStatus
-                        .getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
-                tunnelUpdated(td, tunnelState);
-            }
-        }
-
-        /**
-         * Handles sync report received from pcc.
-         *
-         * @param stateRpt pcep state report
-         */
-        private void handleSyncReport(PcepStateReport stateRpt) {
-            PcepLspObject lspObj = stateRpt.getLspObject();
             PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
             checkNotNull(msgPath);
             PcepEroObject eroObj = msgPath.getEroObject();
             if (eroObj == null) {
-                log.debug("ERO object is null in sate report");
+                log.error("ERO object is null in report message.");
                 return;
             }
+            Path path = buildPathFromEroObj(eroObj, providerId);
+
             int bandwidth = 0;
-
-            log.debug("Handle Sync report received from PCC.");
-
-            if (0 == lspObj.getOFlag()) {
-                log.warn("The PCC reported tunnel is in down state");
-            }
-            log.debug("Sync report received");
-
             if (msgPath.getBandwidthObject() != null) {
                 bandwidth = msgPath.getBandwidthObject().getBandwidth();
             }
 
-            // To carry PST TLV, SRP object can be present with value 0 even
-            // when PCRpt is
-            // not in response to any action from PCE.
+            /*
+             * To carry PST TLV, SRP object can be present with value 0 even when PCRpt is not in response to any action
+             * from PCE.
+             */
             PcepSrpObject srpObj = stateRpt.getSrpObject();
             LspType lspType = WITH_SIGNALLING;
 
@@ -1308,7 +1267,164 @@
                 }
             }
 
-            buildAndStorePcepTunnelData(lspObj, eroObj, bandwidth, lspType);
+            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;
+                }
+            }
+
+            /*
+             * Draft says: The LSP-IDENTIFIERS TLV MUST be included in the LSP object in PCRpt messages for
+             * RSVP-signaled LSPs. For ONOS PCECC implementation, it is mandatory.
+             */
+            if (ipv4LspIdenTlv == null) {
+                log.error("Stateful IPv4 identifier TLV is null in PCRpt msg.");
+                return;
+            }
+
+            IpTunnelEndPoint tunnelEndPointSrc = IpTunnelEndPoint
+                    .ipTunnelPoint(IpAddress.valueOf(ipv4LspIdenTlv.getIpv4IngressAddress()));
+            IpTunnelEndPoint tunnelEndPointDst = IpTunnelEndPoint
+                    .ipTunnelPoint(IpAddress.valueOf(ipv4LspIdenTlv.getIpv4EgressAddress()));
+            Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnelEndPointSrc, tunnelEndPointDst);
+
+            Tunnel tunnel = null;
+            // Asynchronous status change message from PCC for LSP reported earlier.
+            for (Tunnel tunnelObj : tunnelQueryResult) {
+                if (tunnelObj.annotations().value(PLSP_ID) == null) {
+                    /*
+                     * 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.
+                     */
+                    if ((pathNameTlv != null)
+                            && Arrays.equals(tunnelObj.tunnelName().value().getBytes(), pathNameTlv.getValue())) {
+                        tunnel = tunnelObj;
+                        break;
+                    }
+                    continue;
+                }
+
+                if ((Integer.valueOf(tunnelObj.annotations().value(PLSP_ID)) == lspObj.getPlspId()) && (Integer
+                        .valueOf(tunnelObj.annotations().value(LOCAL_LSP_ID)) == ipv4LspIdenTlv.getLspId())) {
+                    tunnel = tunnelObj;
+                    break;
+                }
+            }
+
+            DefaultTunnelDescription td;
+            State tunnelState = PcepLspStatus.getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
+            if (tunnel == null) {
+                if (lspObj.getRFlag()) {
+                    /*
+                     * If PCC sends remove message and for any reason PCE does not have that entry, simply discard the
+                     * message. Or if PCRpt for initiated LSP received and PCE doesn't know, then too discard.
+                     */
+                    return;
+                }
+
+                if (lspObj.getCFlag()) {
+                    /*
+                     * While in sync, if PCRpt is received for PCE init LSP and PCE doesn't have entry, mark to send
+                     * delete message on end of sync.
+                     */
+                    SparseAnnotations annotations = DefaultAnnotations.builder()
+                            .set(BANDWIDTH, (new Integer(bandwidth)).toString())
+                            .set(LSP_SIG_TYPE, lspType.name())
+                            .set(PCC_TUNNEL_ID, String.valueOf(ipv4LspIdenTlv.getTunnelId()))
+                            .set(PLSP_ID, String.valueOf(lspObj.getPlspId()))
+                            .set(LOCAL_LSP_ID, String.valueOf(ipv4LspIdenTlv.getLspId())).build();
+
+                    // Gnenerate tunnel id for the temporary tunnel.
+                    String onosTunnelId = "PCC" + String.valueOf(ipv4LspIdenTlv.getTunnelId());
+                    Tunnel tunnelToBeDeleted = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
+                                                                 new DefaultGroupId(0), TunnelId.valueOf(onosTunnelId),
+                                                                 TunnelName.tunnelName(String
+                                                                         .valueOf(pathNameTlv.getValue())),
+                                                                 path, annotations);
+
+                    /*
+                     * Need to send PCInitiate delete msg for a tunnel which does not exist at PCE. For that some dummy
+                     * data-structures need to be populated.
+                     */
+                    PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnelToBeDeleted, path, RequestType.DELETE);
+                    pcepTunnelData.setPlspId(lspObj.getPlspId());
+                    pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspIdenTlv);
+                    pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
+                    pcepTunnelApiMapper.handleCreateTunnelRequestQueue(0, pcepTunnelData);
+
+                    /*
+                     * Add to the list of tunnels for which PCInit delete will be sent at the end of sync.
+                     */
+                    List<Tunnel> tunnelToBeDeletedList = syncCompleteDeleteList.get(pccId.ipAddress());
+                    tunnelToBeDeletedList.add(tunnelToBeDeleted);
+                    syncCompleteDeleteList.put(pccId.ipAddress(), tunnelToBeDeletedList);
+                    return;
+                }
+
+                SparseAnnotations annotations = DefaultAnnotations.builder()
+                        .set(BANDWIDTH, (new Integer(bandwidth)).toString())
+                        .set(LSP_SIG_TYPE, lspType.name())
+                        .set(PCC_TUNNEL_ID, String.valueOf(ipv4LspIdenTlv.getTunnelId()))
+                        .set(PLSP_ID, String.valueOf(lspObj.getPlspId()))
+                        .set(LOCAL_LSP_ID, String.valueOf(ipv4LspIdenTlv.getLspId())).build();
+
+                td = new DefaultTunnelDescription(null, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
+                                                  new DefaultGroupId(0), providerId,
+                                                  TunnelName.tunnelName(String.valueOf(pathNameTlv.getValue())), path,
+                                                  annotations);
+
+                TunnelId tId = tunnelAdded(td, tunnelState);
+                Tunnel tunnelInserted = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
+                                                          tunnelState, new DefaultGroupId(0), tId,
+                                                          TunnelName.tunnelName(String.valueOf(pathNameTlv.getValue())),
+                                                          path, annotations);
+
+                PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnelInserted, path, LSP_STATE_RPT);
+                pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspIdenTlv);
+                pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
+                return;
+            }
+
+            if ((syncStatus == IN_SYNC) && (lspObj.getCFlag()) && (tunnelState != tunnel.state())) {
+                // Mark to send PCUpd msg with state known at PCE.
+                List<Tunnel> tunnelToBeUpdateList = syncCompleteUpdateList.get(pccId.ipAddress());
+                tunnelToBeUpdateList.add(tunnel);
+                syncCompleteUpdateList.put(pccId.ipAddress(), tunnelToBeUpdateList);
+                return;
+            }
+
+            td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(), tunnel.dst(),
+                                                                       tunnel.type(), tunnel.groupId(), providerId,
+                                                                       tunnel.tunnelName(), tunnel.path(),
+                                                                       (SparseAnnotations) tunnel.annotations());
+
+            if (lspObj.getRFlag()) {
+                tunnelRemoved(td);
+            } else {
+                if (syncStatus == IN_SYNC) {
+                    markLspDbEntryAsLatest(pccId, tunnel.tunnelId());
+                }
+                tunnelUpdated(td, tunnelState);
+            }
+            return;
         }
 
         /**
@@ -1323,7 +1439,7 @@
             List<Link> links = new ArrayList<Link>();
             LinkedList<PcepValueType> llSubObj = eroObj.getSubObjects();
             if (0 == llSubObj.size()) {
-                log.error("RRO in report message does not have hop information");
+                log.error("ERO in report message does not have hop information");
             }
             ListIterator<PcepValueType> tlvIterator = llSubObj.listIterator();
 
@@ -1361,71 +1477,6 @@
             return new DefaultPath(providerId, links, 0, EMPTY);
         }
 
-        /**
-         * To build pcepTunnelData and informs core about the PCC reported
-         * tunnel.
-         *
-         * @param lspObj PCEP LSP object
-         * @param eroObj PCEP ERO object
-         * @param bandwidth bandwidth of tunnel
-         * @param lspType path setup type/signaling type of the LSP.
-         */
-        private void buildAndStorePcepTunnelData(PcepLspObject lspObj, PcepEroObject eroObj, int bandwidth,
-                                                 LspType lspType) {
-
-            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
-
-            // StatefulIPv4LspIdentidiersTlv in LSP object will have the source and destination address.
-            StatefulIPv4LspIdentifiersTlv lspIdenTlv = null;
-            SymbolicPathNameTlv pathNameTlv = null;
-            LinkedList<PcepValueType> llOptionalTlv = lspObj.getOptionalTlv();
-            ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
-            while (listIterator.hasNext()) {
-                PcepValueType tlv = listIterator.next();
-                switch (tlv.getType()) {
-                case StatefulIPv4LspIdentifiersTlv.TYPE:
-                    lspIdenTlv = (StatefulIPv4LspIdentifiersTlv) tlv;
-                    break;
-                case SymbolicPathNameTlv.TYPE:
-                    pathNameTlv = (SymbolicPathNameTlv) tlv;
-                    break;
-                default:
-                    // currently this tlv is not required
-                }
-            }
-
-            IpTunnelEndPoint tunnelEndPointSrc;
-            tunnelEndPointSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(lspIdenTlv.getIpv4IngressAddress()));
-            IpTunnelEndPoint tunnelEndPointDst;
-            tunnelEndPointDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(lspIdenTlv.getIpv4EgressAddress()));
-
-            Path path = buildPathFromEroObj(eroObj, providerId);
-
-            SparseAnnotations annotations = DefaultAnnotations.builder()
-                    .set(BANDWIDTH, (new Integer(bandwidth)).toString())
-                    .set(LSP_SIG_TYPE, lspType.name())
-                    .set(PCC_TUNNEL_ID, String.valueOf(lspIdenTlv.getTunnelId()))
-                    .set(PLSP_ID, String.valueOf(lspObj.getPlspId()))
-                    .set(LOCAL_LSP_ID, String.valueOf(lspIdenTlv.getLspId())).build();
-
-            DefaultTunnelDescription td = new DefaultTunnelDescription(null, tunnelEndPointSrc,
-                                                                       tunnelEndPointDst, MPLS,
-                                                                       new DefaultGroupId(0), providerId,
-                                                                       TunnelName.tunnelName(pathNameTlv.toString()),
-                                                                       path, annotations);
-            State tunnelState = PcepLspStatus.getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
-            TunnelId tId = tunnelAdded(td, tunnelState);
-
-            Tunnel tunnel = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
-                                              new DefaultGroupId(0), tId,
-                                              TunnelName.tunnelName(pathNameTlv.toString()), path, annotations);
-
-            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, LSP_STATE_RPT);
-            pcepTunnelData.setStatefulIpv4IndentifierTlv(lspIdenTlv);
-            pcepTunnelApiMapper.addPccTunnelDB(pcepTunnelData);
-            pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
-        }
-
         @Override
         public void clientConnected(PccId pccId) {
             // TODO
@@ -1448,4 +1499,83 @@
     public Tunnel tunnelQueryById(TunnelId tunnelId) {
         return service.tunnelQueryById(tunnelId);
     }
+
+    /**
+     * Removes the entry from temporary copy of LSPDB, signifying its status as upto date.
+     *
+     * @param pccId the key for temporary LSPDB
+     * @param tunnelId the tunnel id for which information is updated.
+     */
+    private void markLspDbEntryAsLatest(PccId pccId, TunnelId tunnelId) {
+        checkNotNull(pccId);
+        checkNotNull(tunnelId);
+
+        Map<TunnelId, Tunnel> preSyncLspDb = preSyncLspDbMap.get(pccId.ipAddress());
+        checkNotNull(preSyncLspDb);
+
+        preSyncLspDb.remove(tunnelId);
+        preSyncLspDbMap.put(pccId.ipAddress(), preSyncLspDb);
+    }
+
+    /**
+     * Sends PCInit, PCInit(R) or PCUpd messages for initiated LSPs at the end
+     * of LSP DB sync based on actions decided while sync was in progress. Also
+     * triggers label DB sync.
+     *
+     * @param pccId the key for temporary DBs storing required end of sync
+     *            actions.
+     */
+    private void handleEndOfSyncAction(PccId pccId) {
+
+        Map<TunnelId, Tunnel> preSyncLspDb = preSyncLspDbMap.get(pccId.ipAddress());
+        checkNotNull(preSyncLspDb);
+
+        for (Tunnel tunnel : preSyncLspDb.values()) {
+
+            TunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(),
+                                                                tunnel.src(), tunnel.dst(),
+                                                                tunnel.type(),
+                                                                tunnel.groupId(),
+                                                                tunnel.providerId(),
+                                                                tunnel.tunnelName(),
+                                                                tunnel.path(),
+                                                                (SparseAnnotations) tunnel.annotations());
+
+            if ((tunnel.annotations().value(PCE_INIT) == null)
+                    || (tunnel.annotations().value(PCE_INIT).equals("false"))) {
+
+                tunnelRemoved(td);
+            } else {
+                // Send PCInit msg again after global reoptimization.
+                tunnelUpdated(td, UNSTABLE);
+
+                // To remove the old tunnel from store whose PLSPID is not
+                // recognized by ingress PCC.
+                tunnelRemoved(td);
+            }
+        }
+
+        List<Tunnel> tunnelsToBeDeletedList = syncCompleteDeleteList.get(pccId.ipAddress());
+        checkNotNull(tunnelsToBeDeletedList);
+        for (Tunnel tunnel: tunnelsToBeDeletedList) {
+            releaseTunnel(tunnel);
+        }
+
+        List<Tunnel> tunnelsToBeUpdatedList = syncCompleteUpdateList.get(pccId.ipAddress());
+        checkNotNull(tunnelsToBeUpdatedList);
+        for (Tunnel tunnel: tunnelsToBeUpdatedList) {
+            updateTunnel(tunnel, tunnel.path());
+        }
+
+        /* On end of sync, empty all temporary data structures. */
+        preSyncLspDbMap.remove(pccId.ipAddress());
+        syncCompleteDeleteList.remove(pccId.ipAddress());
+        syncCompleteUpdateList.remove(pccId.ipAddress());
+
+        // TODO: If SR capable, send a notification to
+        // PCE APP to start label DB sync.
+        if (true) {
+            pcepClientController.getClient(pccId).setLabelDbSyncStatus(IN_SYNC);
+        }
+    }
 }
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java
index 2f519ec..daf315a 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java
@@ -24,6 +24,7 @@
 import org.onosproject.pcep.controller.ClientCapability;
 import org.onosproject.pcep.controller.PccId;
 import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcepio.protocol.PcepFactories;
 import org.onosproject.pcepio.protocol.PcepFactory;
 import org.onosproject.pcepio.protocol.PcepMessage;
@@ -42,7 +43,8 @@
     private ClientCapability capability;
 
     private PcepVersion pcepVersion;
-    private boolean syncCompleted;
+    private PcepSyncStatus lspDbSyncStatus;
+    private PcepSyncStatus labelDbSyncStatus;
 
     /**
      * Initialize instance with specified parameters.
@@ -109,13 +111,23 @@
     }
 
     @Override
-    public final boolean isSyncComplete() {
-        return syncCompleted;
+    public void setLspDbSyncStatus(PcepSyncStatus syncStatus) {
+        this.lspDbSyncStatus = syncStatus;
     }
 
     @Override
-    public final void setIsSyncComplete(boolean value) {
-        syncCompleted = value;
+    public PcepSyncStatus lspDbSyncStatus() {
+        return lspDbSyncStatus;
+    }
+
+    @Override
+    public void setLabelDbSyncStatus(PcepSyncStatus syncStatus) {
+        this.labelDbSyncStatus = syncStatus;
+    }
+
+    @Override
+    public PcepSyncStatus labelDbSyncStatus() {
+        return labelDbSyncStatus;
     }
 
     @Override
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java
index 76f2bb0..2abab75 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java
@@ -25,6 +25,8 @@
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PCC_TUNNEL_ID;
 import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PLSP_ID;
 import static org.onosproject.provider.pcep.tunnel.impl.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
+import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
+import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
 
 import java.io.IOException;
 import java.util.Collection;
@@ -260,7 +262,7 @@
 
         PccId pccId = PccId.pccId(IpAddress.valueOf(0x4e1f0400));
         controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
-        controller.getClient(pccId).setIsSyncComplete(true);
+        controller.getClient(pccId).setLspDbSyncStatus(SYNCED);
 
         // Process update message.
         controller.processClientMessage(pccId, message);
@@ -307,13 +309,291 @@
         PcepMessage message = reader.readFrom(buffer);
 
         PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
-        controller.getClient(pccId).setIsSyncComplete(true);
+        controller.getClient(pccId).setLspDbSyncStatus(SYNCED);
         controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
         controller.processClientMessage(pccId, message);
 
         assertThat(registry.tunnelIdCounter, is((long) 1));
     }
 
+    /**
+     * Tests LSPDB sync where PCC reports less LSPs than known by PCE and PCE deletes at the end of DB sync.
+     */
+    @Test
+    public void testCaseLspDbSync1() throws PcepParseException, PcepOutOfBoundMessageException {
+        /* Step 1 create 2 LSPs */
+        byte[] reportMsg1 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x84,
+                                       0x21, 0x10, 0x00, 0x14, //SRP object
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x20, 0x10, 0x00, 0x24, 0x00, 0x00, 0x10, 0x19, // LSP object
+                                       0x00, 0x11, 0x00, 0x04, 0x54, 0x31, 0x00, 0x00, // symbolic path TLV
+                                       0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x00, 0x01, 0x00, 0x01,
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x05, 0x05, 0x05, 0x05,
+
+                                       0x07, 0x10, 0x00, 0x14, //ERO object
+                                       0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                       0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00,
+
+                                       0x08, 0x10, 0x00, 0x34, //RRO object
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x01, 0x04, 0x00, // RRO IPv4 sub objects
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x06, 0x06, 0x06, 0x06, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x01, 0x04, 0x00,
+                                       0x01, 0x08, 0x05, 0x05, 0x05, 0x05, 0x04, 0x00
+                                       };
+
+        ChannelBuffer buffer1 = ChannelBuffers.dynamicBuffer();
+        buffer1.writeBytes(reportMsg1);
+
+        PcepMessageReader<PcepMessage> reader1 = PcepFactories.getGenericReader();
+        PcepMessage message1 = reader1.readFrom(buffer1);
+
+        PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
+        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
+        controller.processClientMessage(pccId, message1);
+
+        /* create 2nd LSP */
+        byte[] reportMsg2 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x84,
+                                       0x21, 0x10, 0x00, 0x14, //SRP object
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x20, 0x10, 0x00, 0x24, 0x00, 0x00, 0x20, 0x19, // LSP object
+                                       0x00, 0x11, 0x00, 0x04, 0x54, 0x31, 0x00, 0x00, // symbolic path TLV
+                                       0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x00, 0x02, 0x00, 0x02,
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x05, 0x05, 0x05, 0x05,
+
+                                       0x07, 0x10, 0x00, 0x14, //ERO object
+                                       0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                       0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00,
+
+                                       0x08, 0x10, 0x00, 0x34, //RRO object
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x01, 0x04, 0x00, // RRO IPv4 sub objects
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x06, 0x06, 0x06, 0x06, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x01, 0x04, 0x00,
+                                       0x01, 0x08, 0x05, 0x05, 0x05, 0x05, 0x04, 0x00
+                                       };
+
+        ChannelBuffer buffer2 = ChannelBuffers.dynamicBuffer();
+        buffer2.writeBytes(reportMsg2);
+
+        PcepMessageReader<PcepMessage> reader2 = PcepFactories.getGenericReader();
+        PcepMessage message2 = reader2.readFrom(buffer2);
+
+        controller.processClientMessage(pccId, message2);
+
+        /* Assert number of LSPs in DB to be 2. */
+        assertThat(registry.tunnelIdCounter, is((long) 2));
+
+        /* Step 2 send sync begin message and LSP 1. */
+        byte[] reportMsg3 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x84,
+                                        0x21, 0x10, 0x00, 0x14, //SRP object
+                                        0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                        0x00, 0x00, 0x00, 0x00,
+                                        0x20, 0x10, 0x00, 0x24, 0x00, 0x00, 0x10, 0x1B, // LSP object
+                                        0x00, 0x11, 0x00, 0x04, 0x54, 0x31, 0x00, 0x00, // symbolic path TLV
+                                        0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                        0x01, 0x01, 0x01, 0x01,
+                                        0x00, 0x01, 0x00, 0x01,
+                                        0x01, 0x01, 0x01, 0x01,
+                                        0x05, 0x05, 0x05, 0x05,
+
+                                        0x07, 0x10, 0x00, 0x14, //ERO object
+                                        0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                        0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00,
+
+                                        0x08, 0x10, 0x00, 0x34, //RRO object
+                                        0x01, 0x08, 0x11, 0x01, 0x01, 0x01, 0x04, 0x00, // RRO IPv4 sub objects
+                                        0x01, 0x08, 0x11, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                        0x01, 0x08, 0x06, 0x06, 0x06, 0x06, 0x04, 0x00,
+                                        0x01, 0x08, 0x12, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                        0x01, 0x08, 0x12, 0x01, 0x01, 0x01, 0x04, 0x00,
+                                        0x01, 0x08, 0x05, 0x05, 0x05, 0x05, 0x04, 0x00
+                                        };
+
+         ChannelBuffer buffer3 = ChannelBuffers.dynamicBuffer();
+         buffer3.writeBytes(reportMsg3);
+         PcepMessageReader<PcepMessage> reader3 = PcepFactories.getGenericReader();
+         PcepMessage message3 = reader3.readFrom(buffer3);
+         controller.processClientMessage(pccId, message3);
+
+         assertThat(controller.getClient(pccId).lspDbSyncStatus(), is(IN_SYNC));
+
+        /* Step 3 send end of sync marker */
+         byte[] reportMsg4 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x24,
+                                         0x20, 0x10, 0x00, 0x1C, // LSP object
+                                         0x00, 0x00, 0x10, 0x19,
+                                         0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                         0x00, 0x00, 0x00, 0x00,
+                                         0x00, 0x00, 0x00, 0x00,
+                                         0x00, 0x00, 0x00, 0x00,
+                                         0x00, 0x00, 0x00, 0x00,
+                                         0x07, 0x10, 0x00, 0x04, //ERO object
+                                         };
+
+          ChannelBuffer buffer4 = ChannelBuffers.dynamicBuffer();
+          buffer4.writeBytes(reportMsg4);
+          PcepMessageReader<PcepMessage> reader4 = PcepFactories.getGenericReader();
+          PcepMessage message4 = reader4.readFrom(buffer4);
+          controller.processClientMessage(pccId, message4);
+
+        assertThat(controller.getClient(pccId).lspDbSyncStatus(), is(SYNCED));
+    }
+
+    /**
+     * Tests PCC PCRpt PCE initiated LSP which PCE doesn't know and hence should send PCInit delete msg.
+     */
+    @Test
+    public void testCaseLspDbSync2() throws PcepParseException, PcepOutOfBoundMessageException {
+        /* Step 1 create 2 LSPs */
+        byte[] reportMsg1 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x84,
+                                       0x21, 0x10, 0x00, 0x14, //SRP object
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x20, 0x10, 0x00, 0x24, 0x00, 0x00, 0x10, 0x19, // LSP object
+                                       0x00, 0x11, 0x00, 0x04, 0x54, 0x31, 0x00, 0x00, // symbolic path TLV
+                                       0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x00, 0x01, 0x00, 0x01,
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x05, 0x05, 0x05, 0x05,
+
+                                       0x07, 0x10, 0x00, 0x14, //ERO object
+                                       0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                       0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00,
+
+                                       0x08, 0x10, 0x00, 0x34, //RRO object
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x01, 0x04, 0x00, // RRO IPv4 sub objects
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x06, 0x06, 0x06, 0x06, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x01, 0x04, 0x00,
+                                       0x01, 0x08, 0x05, 0x05, 0x05, 0x05, 0x04, 0x00
+                                       };
+
+        ChannelBuffer buffer1 = ChannelBuffers.dynamicBuffer();
+        buffer1.writeBytes(reportMsg1);
+
+        PcepMessageReader<PcepMessage> reader1 = PcepFactories.getGenericReader();
+        PcepMessage message1 = reader1.readFrom(buffer1);
+
+        PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
+        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
+        controller.processClientMessage(pccId, message1);
+
+        /* create 2nd LSP */
+        byte[] reportMsg2 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x84,
+                                       0x21, 0x10, 0x00, 0x14, //SRP object
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x20, 0x10, 0x00, 0x24, 0x00, 0x00, 0x20, 0x19, // LSP object
+                                       0x00, 0x11, 0x00, 0x04, 0x54, 0x31, 0x00, 0x00, // symbolic path TLV
+                                       0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x00, 0x02, 0x00, 0x02,
+                                       0x01, 0x01, 0x01, 0x01,
+                                       0x05, 0x05, 0x05, 0x05,
+
+                                       0x07, 0x10, 0x00, 0x14, //ERO object
+                                       0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                       0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00,
+
+                                       0x08, 0x10, 0x00, 0x34, //RRO object
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x01, 0x04, 0x00, // RRO IPv4 sub objects
+                                       0x01, 0x08, 0x11, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x06, 0x06, 0x06, 0x06, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                       0x01, 0x08, 0x12, 0x01, 0x01, 0x01, 0x04, 0x00,
+                                       0x01, 0x08, 0x05, 0x05, 0x05, 0x05, 0x04, 0x00
+                                       };
+
+        ChannelBuffer buffer2 = ChannelBuffers.dynamicBuffer();
+        buffer2.writeBytes(reportMsg2);
+
+        PcepMessageReader<PcepMessage> reader2 = PcepFactories.getGenericReader();
+        PcepMessage message2 = reader2.readFrom(buffer2);
+
+        controller.processClientMessage(pccId, message2);
+
+        /* Assert number of LSPs in DB to be 2. */
+        assertThat(registry.tunnelIdCounter, is((long) 2));
+
+        /* Step 2 send sync begin message and LSP 1. */
+        byte[] reportMsg3 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x84,
+                                        0x21, 0x10, 0x00, 0x14, //SRP object
+                                        0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                        0x00, 0x00, 0x00, 0x00,
+                                        0x20, 0x10, 0x00, 0x24, 0x00, 0x00, 0x10, (byte) 0x9B, // LSP object
+                                        0x00, 0x11, 0x00, 0x04, 0x54, 0x31, 0x00, 0x00, // symbolic path TLV
+                                        0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                        0x01, 0x01, 0x01, 0x01,
+                                        0x00, 0x01, 0x00, 0x03,
+                                        0x01, 0x01, 0x01, 0x01,
+                                        0x05, 0x05, 0x05, 0x05,
+
+                                        0x07, 0x10, 0x00, 0x14, //ERO object
+                                        0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                        0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00,
+
+                                        0x08, 0x10, 0x00, 0x34, //RRO object
+                                        0x01, 0x08, 0x11, 0x01, 0x01, 0x01, 0x04, 0x00, // RRO IPv4 sub objects
+                                        0x01, 0x08, 0x11, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                        0x01, 0x08, 0x06, 0x06, 0x06, 0x06, 0x04, 0x00,
+                                        0x01, 0x08, 0x12, 0x01, 0x01, 0x02, 0x04, 0x00,
+                                        0x01, 0x08, 0x12, 0x01, 0x01, 0x01, 0x04, 0x00,
+                                        0x01, 0x08, 0x05, 0x05, 0x05, 0x05, 0x04, 0x00
+                                        };
+
+        ChannelBuffer buffer3 = ChannelBuffers.dynamicBuffer();
+        buffer3.writeBytes(reportMsg3);
+        PcepMessageReader<PcepMessage> reader3 = PcepFactories.getGenericReader();
+        PcepMessage message3 = reader3.readFrom(buffer3);
+        controller.processClientMessage(pccId, message3);
+
+        assertThat(controller.getClient(pccId).lspDbSyncStatus(), is(IN_SYNC));
+
+        /* Step 3 send end of sync marker */
+        byte[] reportMsg4 = new byte[] {0x20, 0x0a, 0x00, (byte) 0x24,
+                                       0x20, 0x10, 0x00, 0x1C, // LSP object
+                                       0x00, 0x00, 0x10, 0x19,
+                                       0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+                                       0x07, 0x10, 0x00, 0x04, //ERO object
+                                       };
+
+        ChannelBuffer buffer4 = ChannelBuffers.dynamicBuffer();
+        buffer4.writeBytes(reportMsg4);
+        PcepMessageReader<PcepMessage> reader4 = PcepFactories.getGenericReader();
+        PcepMessage message4 = reader4.readFrom(buffer4);
+        controller.processClientMessage(pccId, message4);
+
+        assertThat(controller.getClient(pccId).lspDbSyncStatus(), is(SYNCED));
+    }
+
     @After
     public void tearDown() throws IOException {
         tunnelProvider.deactivate();