[ONOS-4170] Label Db sync

Change-Id: I7322d962551e3c5a046b64884ebc7a2f15ee0cd3
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/PcepSrpObject.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/PcepSrpObject.java
index 9fc2277..bd44c36 100755
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/PcepSrpObject.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/PcepSrpObject.java
@@ -57,6 +57,20 @@
     void setRFlag(boolean bRFlag);
 
     /**
+     * Returns S flag of SRP Object.
+     *
+     * @return S flag of SRP Object
+     */
+    boolean getSFlag();
+
+    /**
+     * Sets S(sync) flag with specified value.
+     *
+     * @param bSFlag S Flag of SRP Object
+     */
+    void setSFlag(boolean bSFlag);
+
+    /**
      * sets the optional TLvs.
      *
      * @param llOptionalTlv list of optional tlvs
@@ -130,6 +144,13 @@
         boolean getRFlag();
 
         /**
+         * Returns S(sync) flag of SRP Object.
+         *
+         * @return S flag of SRP Object
+         */
+        boolean getSFlag();
+
+        /**
          * Sets R flag and returns its builder.
          *
          * @param bRFlag R flag
@@ -138,6 +159,14 @@
         Builder setRFlag(boolean bRFlag);
 
         /**
+         * Sets S flag and returns its builder.
+         *
+         * @param bSFlag S flag
+         * @return Builder by setting S flag
+         */
+        Builder setSFlag(boolean bSFlag);
+
+        /**
          * Returns list of optional tlvs.
          *
          * @return llOptionalTlv list of optional tlvs
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepSrpObjectVer1.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepSrpObjectVer1.java
index 889c354..b88a1a4 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepSrpObjectVer1.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepSrpObjectVer1.java
@@ -43,7 +43,7 @@
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    |                          Flags                              |R|
+    |                          Flags                            |S|R|
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        SRP-ID-number                          |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -60,7 +60,7 @@
     public static final byte SRP_OBJECT_VERSION = 1;
     public static final short SRP_OBJ_MINIMUM_LENGTH = 12;
     public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
-    public static final boolean DEFAULT_RFLAG = false;
+    public static final boolean FLAG_DEFAULT_VALUE = false;
 
     static final PcepObjectHeader DEFAULT_SRP_OBJECT_HEADER = new PcepObjectHeader(SRP_OBJ_CLASS, SRP_OBJ_TYPE,
             PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, SRP_OBJ_MINIMUM_LENGTH);
@@ -68,6 +68,7 @@
     private PcepObjectHeader srpObjHeader;
     private static int flags;
     private boolean bRFlag;
+    private boolean bSFlag;
     private int srpId;
 
     //Optional TLV
@@ -80,14 +81,16 @@
      *
      * @param srpObjHeader srp object header
      * @param bRFlag R flag
+     * @param bSFlag S (sync) flag
      * @param srpID srp Id
      * @param llOptionalTlv list of optional tlv
      */
-    public PcepSrpObjectVer1(PcepObjectHeader srpObjHeader, boolean bRFlag, int srpID,
+    public PcepSrpObjectVer1(PcepObjectHeader srpObjHeader, boolean bRFlag, boolean bSFlag, int srpID,
             LinkedList<PcepValueType> llOptionalTlv) {
 
         this.srpObjHeader = srpObjHeader;
         this.bRFlag = bRFlag;
+        this.bSFlag = bSFlag;
         this.srpId = srpID;
         this.llOptionalTlv = llOptionalTlv;
     }
@@ -111,6 +114,11 @@
         this.bRFlag = bRFlag;
     }
 
+    @Override
+    public void setSFlag(boolean bSFlag) {
+        this.bSFlag = bSFlag;
+    }
+
     /**
      * Returns SRP object header.
      *
@@ -131,6 +139,11 @@
     }
 
     @Override
+    public boolean getSFlag() {
+        return this.bSFlag;
+    }
+
+    @Override
     public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
         this.llOptionalTlv = llOptionalTlv;
 
@@ -153,6 +166,7 @@
         log.debug("SrpObject::read");
         PcepObjectHeader srpObjHeader;
         boolean bRFlag;
+        boolean bSFlag;
 
         int srpID;
         int flags;
@@ -167,12 +181,13 @@
         //take only SrpObject buffer.
         ChannelBuffer tempCb = cb.readBytes(srpObjHeader.getObjLen() - MINIMUM_COMMON_HEADER_LENGTH);
         flags = tempCb.readInt();
-        bRFlag = 0 < flags;
+        bRFlag = 0 < (flags & 0x1);
+        bSFlag = 0 < ((flags >> 1) & 0x1);
         srpID = tempCb.readInt();
 
         llOptionalTlv = parseOptionalTlv(tempCb);
 
-        return new PcepSrpObjectVer1(srpObjHeader, bRFlag, srpID, llOptionalTlv);
+        return new PcepSrpObjectVer1(srpObjHeader, bRFlag, bSFlag, srpID, llOptionalTlv);
     }
 
     @Override
@@ -187,6 +202,7 @@
         byte bFlag;
 
         bFlag = (bRFlag) ? BBIT_SET : BBIT_RESET;
+        bFlag |= (((bSFlag) ? BBIT_SET : BBIT_RESET) << 1);
 
         cb.writeInt(bFlag);
 
@@ -292,10 +308,12 @@
         private boolean bIsHeaderSet = false;
         private boolean bIsSrpIdset = false;
         private boolean bIsRFlagSet = false;
+        private boolean bIsSFlagSet = false;
 
         private PcepObjectHeader srpObjHeader;
         private int srpId;
         private boolean bRFlag;
+        private boolean bSFlag;
         LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
 
         private boolean bIsPFlagSet = false;
@@ -308,7 +326,8 @@
         public PcepSrpObject build() throws PcepParseException {
             PcepObjectHeader srpObjHeader = this.bIsHeaderSet ? this.srpObjHeader : DEFAULT_SRP_OBJECT_HEADER;
 
-            boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_RFLAG;
+            boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : FLAG_DEFAULT_VALUE;
+            boolean bSFlag = this.bIsSFlagSet ? this.bSFlag : FLAG_DEFAULT_VALUE;
 
             if (!this.bIsSrpIdset) {
                 throw new PcepParseException("SrpID not set while building SRP Object.");
@@ -322,7 +341,7 @@
                 srpObjHeader.setIFlag(bIFlag);
             }
 
-            return new PcepSrpObjectVer1(srpObjHeader, bRFlag, this.srpId, this.llOptionalTlv);
+            return new PcepSrpObjectVer1(srpObjHeader, bRFlag, bSFlag, this.srpId, this.llOptionalTlv);
         }
 
         @Override
@@ -362,6 +381,18 @@
         }
 
         @Override
+        public boolean getSFlag() {
+            return this.bSFlag;
+        }
+
+        @Override
+        public Builder setSFlag(boolean bSFlag) {
+            this.bSFlag = bSFlag;
+            this.bIsSFlagSet = true;
+            return this;
+        }
+
+        @Override
         public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
             this.llOptionalTlv = llOptionalTlv;
             return this;
@@ -392,6 +423,7 @@
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("RFlag", bRFlag)
+                .add("SFlag", bSFlag)
                 .add("SRPID", srpId)
                 .add("OptionalTlvList", llOptionalTlv)
                 .toString();
diff --git a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
index 6d0ad11..f8c3ec0 100644
--- a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
+++ b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
@@ -74,6 +74,9 @@
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
+import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -188,7 +191,13 @@
 
     //Pushes node labels to the specified device.
     private void pushGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId,
-            IpPrefix ipPrefix, Objective.Operation type) throws PcepParseException {
+            IpPrefix ipPrefix, Objective.Operation type, boolean isBos) throws PcepParseException {
+
+        checkNotNull(deviceId);
+        checkNotNull(labelId);
+        checkNotNull(ipPrefix);
+        checkNotNull(type);
+
         PcepClient pc = getPcepClient(deviceId);
         if (pc == null) {
             log.error("PCEP client not found");
@@ -201,7 +210,20 @@
                                       .setNodeID(ipPrefix.address().getIp4Address().toInt())
                                       .build();
 
-        PcepSrpObject srpObj = getSrpObject(pc, type);
+        boolean bSFlag = false;
+        if (pc.labelDbSyncStatus() == IN_SYNC) {
+            if (isBos) {
+                /*
+                 * Now the sync is completed.
+                 * Need to send label DB end-of-sync msg, i.e. S flag in SRP id is reset.
+                 */
+                pc.setLabelDbSyncStatus(SYNCED);
+            } else {
+                bSFlag = true;
+            }
+        }
+
+        PcepSrpObject srpObj = getSrpObject(pc, type, bSFlag);
 
         //Global NODE-SID as label object
         PcepLabelObject labelObject = pc.factory().buildLabelObject()
@@ -224,26 +246,35 @@
         pc.sendMessage(labelMsg);
     }
 
-    private PcepSrpObject getSrpObject(PcepClient pc, Objective.Operation type) throws PcepParseException {
+    private PcepSrpObject getSrpObject(PcepClient pc, Objective.Operation type, boolean bSFlag)
+            throws PcepParseException {
         PcepSrpObject srpObj;
-        if (type.equals(Objective.Operation.ADD)) {
-            srpObj = pc.factory().buildSrpObject()
-                    .setRFlag(false)
-                    .setSrpID(SrpIdGenerators.create())
-                    .build();
-        } else {
-            //To cleanup labels, R bit is set
-            srpObj = pc.factory().buildSrpObject()
-                    .setRFlag(true)
-                    .setSrpID(SrpIdGenerators.create())
-                    .build();
+        boolean bRFlag = false;
+
+        if (!type.equals(Objective.Operation.ADD)) {
+            // To cleanup labels, R bit is set
+            bRFlag = true;
         }
+
+        srpObj = pc.factory().buildSrpObject()
+                .setRFlag(bRFlag)
+                .setSFlag(bSFlag)
+                .setSrpID(SrpIdGenerators.create())
+                .build();
+
         return srpObj;
     }
 
     //Pushes adjacency labels to the specified device.
     private void pushAdjacencyLabel(DeviceId deviceId, LabelResourceId labelId,
             PortNumber srcPortNum, PortNumber dstPortNum, Objective.Operation type) throws PcepParseException {
+
+        checkNotNull(deviceId);
+        checkNotNull(labelId);
+        checkNotNull(srcPortNum);
+        checkNotNull(dstPortNum);
+        checkNotNull(type);
+
         PcepClient pc = getPcepClient(deviceId);
         if (pc == null) {
             log.error("PCEP client not found");
@@ -262,7 +293,7 @@
                                                   .seLocalIPv4Address((int) srcPortNo)
                                                   .build();
 
-        PcepSrpObject srpObj = getSrpObject(pc, type);
+        PcepSrpObject srpObj = getSrpObject(pc, type, false);
 
         //Adjacency label object
         PcepLabelObject labelObject = pc.factory().buildLabelObject()
@@ -290,6 +321,13 @@
             PortNumber portNum, TunnelId tunnelId,
             Boolean isBos, Long labelType, Objective.Operation type) throws PcepParseException {
 
+        checkNotNull(deviceId);
+        checkNotNull(labelId);
+        checkNotNull(portNum);
+        checkNotNull(tunnelId);
+        checkNotNull(labelType);
+        checkNotNull(type);
+
         PcepClient pc = getPcepClient(deviceId);
         if (pc == null) {
             log.error("PCEP client not found");
@@ -335,7 +373,7 @@
         //Add OUT label object in case of transit node
         labelObjects.add(labelObj);
 
-        srpObj = getSrpObject(pc, type);
+        srpObj = getSrpObject(pc, type, false);
 
         String lspId = tunnel.annotations().value(PcepAnnotationKeys.PLSP_ID);
         String plspId = tunnel.annotations().value(PcepAnnotationKeys.LOCAL_LSP_ID);