BUG-139: Incremental Synchronization Procedure 32/27032/9
authorClaudio D. Gasparini <cgaspari@cisco.com>
Fri, 11 Sep 2015 12:43:38 +0000 (14:43 +0200)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Fri, 9 Oct 2015 07:02:42 +0000 (09:02 +0200)
- In case incremental syncronization is available, PCC will only
  synchronize the delta ( Changes on LSP Database that occured
  since session went down and  during session reestablishment).
  Therefore is not required PCE Purge LSP.

-ref: https://tools.ietf.org/html/draft-ietf-pce-stateful-sync-optimizations-02#section-4.2

Change-Id: I085906ea9c9a5cd0d8850834fea060342be4213e
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
pcep/topology-api/src/main/yang/network-topology-pcep.yang
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/AbstractTopologySessionListener.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful07TopologySessionListener.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/SyncOptimization.java
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/IncrementalSynchronizationProcedureTest.java [new file with mode: 0644]
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/SyncOptimizationTest.java

index c542078c21aced12bf035879150dca5164e49965..5b0aa4ecbca3e68fcf9b96cf88481295b9860b3c 100644 (file)
@@ -46,6 +46,10 @@ module network-topology-pcep {
                 description
                     "Initial state resynchronization is being performed.";
             }
+            enum incremental-sync {
+                description
+                    "Incremental state resynchronization is being performed.";
+            }
             enum synchronized {
                 description
                     "State synchronization has been achieved.";
index bf9452804c8bf804d97cbf737a9cde0026fed119..4bd2117bf60af3cc39e96f732fabeb5e69fd1e84 100644 (file)
@@ -159,7 +159,7 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
         final Node initialNodeState = state.getInitialNodeState();
         final boolean isNodePresent = isLspDbRetreived() && initialNodeState != null;
         if (isNodePresent) {
-            loadLspData(initialNodeState, lspData, lsps);
+            loadLspData(initialNodeState, lspData, lsps, isIncrementalSynchro());
             pccBuilder.setReportedLsp(initialNodeState.getAugmentation(Node1.class).getPathComputationClient().getReportedLsp());
         }
         writeNode(pccBuilder, state, topologyAugment);
@@ -483,7 +483,7 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
 
     protected abstract Object validateReportedLsp(final Optional<ReportedLsp> rep, final LspId input);
 
-    protected abstract void loadLspData(final Node node, final Map<String, ReportedLsp> lspData, final Map<L, String> lsps);
+    protected abstract void loadLspData(final Node node, final Map<String, ReportedLsp> lspData, final Map<L, String> lsps, final boolean incrementalSynchro);
 
     protected final boolean isLspDbPersisted() {
         if (syncOptimization != null) {
@@ -499,6 +499,18 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
         return false;
     }
 
+    /**
+     * Is Incremental synchronization if LSP-DB-VERSION are included,
+     * LSP-DB-VERSION TLV values doesnt match, and  LSP-SYNC-CAPABILITY is enabled
+     * @return
+     */
+    protected final boolean isIncrementalSynchro() {
+        if (syncOptimization != null) {
+            return syncOptimization.isSyncAvoidanceEnabled() && syncOptimization.isDeltaSyncEnabled();
+        }
+        return false;
+    }
+
     protected final boolean isSynchronized() {
         if (syncOptimization != null) {
             return syncOptimization.doesLspDbMatch();
index b85367fbefcd3bebf29f6326d4b4ac7ea9843191..00fbee7511832160037253c883dc64aca42096f8 100644 (file)
@@ -114,6 +114,8 @@ class Stateful07TopologySessionListener extends AbstractTopologySessionListener<
                 pccBuilder.setReportedLsp(Collections.<ReportedLsp> emptyList());
                 if (isSynchronized()) {
                     pccBuilder.setStateSync(PccSyncState.Synchronized);
+                } else if (isIncrementalSynchro()) {
+                    pccBuilder.setStateSync(PccSyncState.IncrementalSync);
                 } else {
                     pccBuilder.setStateSync(PccSyncState.InitialResync);
                 }
@@ -184,7 +186,7 @@ class Stateful07TopologySessionListener extends AbstractTopologySessionListener<
     private boolean manageNextReport(final Reports report, final MessageContext ctx) {
         final Lsp lsp = report.getLsp();
         final PlspId plspid = lsp.getPlspId();
-        if (!lsp.isSync() && (lsp.getPlspId() == null || plspid.getValue() == 0)) {
+        if (!lsp.isSync() && (plspid == null || plspid.getValue() == 0)) {
             purgeStaleLsps(ctx);
             stateSynchronizationAchieved(ctx);
             return true;
@@ -566,8 +568,14 @@ class Stateful07TopologySessionListener extends AbstractTopologySessionListener<
         return capa;
     }
 
+    /**
+     * Recover lspData and mark any LSPs in the LSP database that were previously reported by the PCC as stale
+     * @param lspData
+     * @param lsps
+     * @param incrementalSynchro
+     */
     @Override
-    protected synchronized void loadLspData(final Node node, final Map<String, ReportedLsp> lspData, final Map<PlspId, String> lsps) {
+    protected synchronized void loadLspData(final Node node, final Map<String, ReportedLsp> lspData, final Map<PlspId, String> lsps, final boolean incrementalSynchro) {
         //load node's lsps from DS
         final PathComputationClient pcc = node.getAugmentation(Node1.class).getPathComputationClient();
         final List<ReportedLsp> reportedLsps = pcc.getReportedLsp();
@@ -578,19 +586,32 @@ class Stateful07TopologySessionListener extends AbstractTopologySessionListener<
                 final Path1 path1 = reportedLsp.getPath().get(0).getAugmentation(Path1.class);
                 if (path1 != null) {
                     final PlspId plspId = path1.getLsp().getPlspId();
-                    staleLsps.add(plspId);
+                    if (!incrementalSynchro) {
+                        staleLsps.add(plspId);
+                    }
                     lsps.put(plspId, lspName);
                 }
             }
         }
     }
 
+    /**
+     * When the PCC reports an LSP during state synchronization, if the LSP already
+     * exists in the LSP database, the PCE MUST update the LSP database and
+     * clear the stale marker from the LSP
+     * @param plspId
+     * @param sync
+     */
     private synchronized void unmarkStaleLsp(final PlspId plspId, final boolean sync) {
         if (!sync) {
             staleLsps.remove(plspId);
         }
     }
 
+    /**
+     *  Purge any LSPs from the LSP database that are still marked as stale
+     * @param ctx
+     */
     private synchronized void purgeStaleLsps(final MessageContext ctx) {
         for (final PlspId plspId : staleLsps) {
             removeLsp(ctx, plspId);
index 44299792f2bc0cbf3fb0e9c7c8b33be1cbd8e808..05449beeeb5414fc1c22d83b87a98170cef8e3a7 100644 (file)
@@ -20,6 +20,7 @@ final class SyncOptimization {
 
     private final boolean dbVersionMatch;
     private final boolean isSyncAvoidanceEnabled;
+    private final boolean isDeltaSyncEnabled;
     private final boolean isDbVersionPresent;
 
     public SyncOptimization(final PCEPSession session) {
@@ -30,6 +31,7 @@ final class SyncOptimization {
         final LspDbVersion remoteLspDbVersion = getLspDbVersion(remote);
         this.dbVersionMatch = compareLspDbVersion(localLspDbVersion, remoteLspDbVersion);
         this.isSyncAvoidanceEnabled = isSyncAvoidance(local) && isSyncAvoidance(remote);
+        this.isDeltaSyncEnabled = isDeltaSync(local) && isDeltaSync(remote);
         this.isDbVersionPresent = localLspDbVersion != null || remoteLspDbVersion != null;
     }
 
@@ -41,6 +43,10 @@ final class SyncOptimization {
         return isSyncAvoidanceEnabled;
     }
 
+    public boolean isDeltaSyncEnabled() {
+        return isDeltaSyncEnabled;
+    }
+
     public boolean isDbVersionPresent() {
         return isDbVersionPresent;
     }
@@ -63,16 +69,29 @@ final class SyncOptimization {
         return false;
     }
 
-    private static boolean isSyncAvoidance(final Tlvs openTlvs) {
+    private static Stateful1 getStateful1(final Tlvs openTlvs) {
         if (openTlvs != null) {
             final Tlvs1 tlvs1 = openTlvs.getAugmentation(Tlvs1.class);
             if (tlvs1 != null && tlvs1.getStateful() != null) {
-                final Stateful1 stateful1 = tlvs1.getStateful().getAugmentation(Stateful1.class);
-                if (stateful1 != null && stateful1.isIncludeDbVersion() != null) {
-                    return stateful1.isIncludeDbVersion();
-                }
+                return tlvs1.getStateful().getAugmentation(Stateful1.class);
             }
         }
+        return null;
+    }
+
+    private static boolean isSyncAvoidance(final Tlvs openTlvs) {
+        final Stateful1 stateful1 = getStateful1(openTlvs);
+        if (stateful1 != null && stateful1.isIncludeDbVersion() != null) {
+            return stateful1.isIncludeDbVersion();
+        }
+        return false;
+    }
+
+    private static boolean isDeltaSync(final Tlvs openTlvs) {
+        final Stateful1 stateful1 = getStateful1(openTlvs);
+        if (stateful1 != null && stateful1.isDeltaLspSyncCapability() != null) {
+            return stateful1.isDeltaLspSyncCapability();
+        }
         return false;
     }
 
diff --git a/pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/IncrementalSynchronizationProcedureTest.java b/pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/IncrementalSynchronizationProcedureTest.java
new file mode 100644 (file)
index 0000000..34589b2
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLsp;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPath;
+
+import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SymbolicPathName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.LspIdentifiersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.stateful.capability.tlv.StatefulBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.LspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.PccSyncState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
+
+public class IncrementalSynchronizationProcedureTest extends AbstractPCEPSessionTest<Stateful07TopologySessionListenerFactory> {
+
+    private Stateful07TopologySessionListener listener;
+
+    private PCEPSession session;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        this.listener = (Stateful07TopologySessionListener) getSessionListener();
+    }
+
+    @Test
+    public void testStateSynchronizationPerformed() throws InterruptedException, ExecutionException {
+        this.session = getPCEPSession(getOpen(null), getOpen(null));
+        this.listener.onSessionUp(session);
+        //report LSP + LSP-DB version number
+        final Pcrpt pcRpt = getPcrpt(1L, "test");
+        this.listener.onMessage(session, pcRpt);
+
+        final PathComputationClient pcc = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+        Assert.assertFalse(pcc.getReportedLsp().isEmpty());
+        this.listener.onSessionDown(session, new IllegalArgumentException());
+        this.listener = (Stateful07TopologySessionListener) getSessionListener();
+
+        //session up - expect sync (LSP-DBs do not match)
+        final LspDbVersion localDbVersion = new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(2l)).build();
+        this.session = getPCEPSession(getOpen(localDbVersion), getOpen(null));
+        this.listener.onSessionUp(session);
+
+        final PathComputationClient pcc2 = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+        //check node - IncrementalSync state
+        Assert.assertEquals(PccSyncState.IncrementalSync, pcc2.getStateSync());
+        //check reported LSP - persisted from previous session
+        Assert.assertFalse(pcc2.getReportedLsp().isEmpty());
+
+        //report LSP2 + LSP-DB version number 2
+        final Pcrpt pcRpt2 = getPcrpt(2L,"testsecond");
+        this.listener.onMessage(session, pcRpt2);
+
+        final PathComputationClient pcc3 = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+
+        //check node - synchronized
+        Assert.assertEquals(PccSyncState.IncrementalSync, pcc3.getStateSync());
+        //check reported LSP is not empty
+        Assert.assertEquals(2, pcc3.getReportedLsp().size());
+
+        //sync rpt + LSP-DB
+        final Pcrpt syncMsg = getSyncPcrt();
+        this.listener.onMessage(session, syncMsg);
+        final PathComputationClient pcc4 = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+        //check node - synchronized
+        Assert.assertEquals(PccSyncState.Synchronized, pcc4.getStateSync());
+        //check reported LSP is empty, LSP state from previous session was purged
+        Assert.assertEquals(2, pcc4.getReportedLsp().size());
+
+
+        //report LSP3 + LSP-DB version number 4
+        final Pcrpt pcRpt3 = getPcrpt(3L,"testthird");
+        this.listener.onMessage(session, pcRpt3);
+
+        final PathComputationClient pcc5 = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+
+        //check node - synchronized
+        Assert.assertEquals(PccSyncState.Synchronized, pcc5.getStateSync());
+        Assert.assertEquals(3,pcc5.getReportedLsp().size());
+    }
+
+    private Open getOpen(final LspDbVersion dbVersion) {
+        return new OpenBuilder(super.getLocalPref()).setTlvs(new TlvsBuilder().addAugmentation(Tlvs1.class, new Tlvs1Builder().setStateful(new StatefulBuilder()
+            .addAugmentation(Stateful1.class, new Stateful1Builder().setInitiation(Boolean.TRUE).build())
+            .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1Builder()
+                .setIncludeDbVersion(Boolean.TRUE).setDeltaLspSyncCapability(Boolean.TRUE).build())
+            .build()).build()).addAugmentation(Tlvs3.class, new Tlvs3Builder().setLspDbVersion(dbVersion).build()).build()).build();
+    }
+
+    private Pcrpt getPcrpt(Long val, String pathname) {
+        return MsgBuilderUtil.createPcRtpMessage(new LspBuilder().setPlspId(new PlspId(val)).setTlvs(
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.
+                TlvsBuilder().setLspIdentifiers(new LspIdentifiersBuilder().setLspId(new LspId(val)).build())
+                .setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(pathname.getBytes())).build())
+                .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync
+                    .optimizations.rev150714.Tlvs1Builder().setLspDbVersion(new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(val)).build()).build()).build()).setPlspId(new PlspId(val)
+        ).setSync(true).setRemove(false).setOperational(OperationalStatus.Active).build(), Optional.<Srp>absent(), createPath(Collections.<Subobject>emptyList()));
+    }
+
+    private Pcrpt getSyncPcrt() {
+        return MsgBuilderUtil.createPcRtpMessage(createLsp(0, false, Optional.of(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder().addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class,
+                    new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync
+                        .optimizations.rev150714.Tlvs1Builder().setLspDbVersion(new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(3l)).build()).build()).build()), true, false), Optional.<Srp>absent(),
+            createPath(Collections.<Subobject>emptyList()));
+    }
+}
index 7f7020ecfdb5d746081c3a484c76edbf30f4a0f3..105e1dab871f573d00a6beab72653069b81780ae 100644 (file)
@@ -41,7 +41,7 @@ public class SyncOptimizationTest {
 
     @Test
     public void testDoesLspDbMatchPositive() {
-        final Tlvs tlvs = createTlvs(1l, false);
+        final Tlvs tlvs = createTlvs(1l, false, false);
         Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
         Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
         final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
@@ -50,8 +50,8 @@ public class SyncOptimizationTest {
 
     @Test
     public void testDoesLspDbMatchNegative() {
-        final Tlvs localTlvs = createTlvs(1l, false);
-        final Tlvs remoteTlvs = createTlvs(2l, false);
+        final Tlvs localTlvs = createTlvs(1l, false, false);
+        final Tlvs remoteTlvs = createTlvs(2l, false, false);
         Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
         Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
         final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
@@ -60,7 +60,7 @@ public class SyncOptimizationTest {
 
     @Test
     public void testIsSyncAvoidanceEnabledPositive() {
-        final Tlvs tlvs = createTlvs(1l, true);
+        final Tlvs tlvs = createTlvs(1l, true, false);
         Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
         Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
         final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
@@ -69,18 +69,37 @@ public class SyncOptimizationTest {
 
     @Test
     public void testIsSyncAvoidanceEnabledNegative() {
-        final Tlvs localTlvs = createTlvs(1l, true);
-        final Tlvs remoteTlvs = createTlvs(2l, false);
+        final Tlvs localTlvs = createTlvs(1l, true, false);
+        final Tlvs remoteTlvs = createTlvs(2l, false, false);
         Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
         Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
         final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
         assertFalse(syncOpt.isSyncAvoidanceEnabled());
     }
 
+    @Test
+    public void testIsDeltaSyncEnabledPositive() {
+        final Tlvs tlvs = createTlvs(1l, true, true);
+        Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
+        Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
+        final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+        assertTrue(syncOpt.isDeltaSyncEnabled());
+    }
+
+    @Test
+    public void testIsDeltaSyncEnabledNegative() {
+        final Tlvs localTlvs = createTlvs(1l, true, true);
+        final Tlvs remoteTlvs = createTlvs(2l, false, false);
+        Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
+        Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
+        final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+        assertFalse(syncOpt.isDeltaSyncEnabled());
+    }
+
     @Test
     public void testIsDbVersionPresentPositive() {
-        final Tlvs localTlvs = createTlvs(null, false);
-        final Tlvs remoteTlvs = createTlvs(2l, false);
+        final Tlvs localTlvs = createTlvs(null, false, false);
+        final Tlvs remoteTlvs = createTlvs(2l, false, false);
         Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
         Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
         final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
@@ -89,21 +108,21 @@ public class SyncOptimizationTest {
 
     @Test
     public void testIsDbVersionPresentNegative() {
-        final Tlvs tlvs = createTlvs(null, true);
+        final Tlvs tlvs = createTlvs(null, true, false);
         Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
         Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
         final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
         assertFalse(syncOpt.isDbVersionPresent());
     }
 
-    private static Tlvs createTlvs(final Long lspDbVersion, final boolean includeDbVresion) {
+    private static Tlvs createTlvs(final Long lspDbVersion, final boolean includeDbVresion, final boolean includeDeltaSync) {
         return new TlvsBuilder()
             .addAugmentation(Tlvs1.class, new Tlvs1Builder().setStateful(
                 new StatefulBuilder().addAugmentation(Stateful1.class,
                         new Stateful1Builder()
-                            .setIncludeDbVersion(includeDbVresion).build()).build()).build())
+                            .setIncludeDbVersion(includeDbVresion).setDeltaLspSyncCapability(includeDeltaSync).build()).build()).build())
             .addAugmentation(Tlvs3.class, new Tlvs3Builder().setLspDbVersion(
-                    new LspDbVersionBuilder().setLspDbVersionValue(lspDbVersion != null ? BigInteger.valueOf(lspDbVersion) : null).build()).build()).build();
+                new LspDbVersionBuilder().setLspDbVersionValue(lspDbVersion != null ? BigInteger.valueOf(lspDbVersion) : null).build()).build()).build();
     }
 
 }