BUG-139: PCE-triggered Initial State Synchronization Procedure 33/27033/10
authorClaudio D. Gasparini <cgaspari@cisco.com>
Mon, 14 Sep 2015 09:02:58 +0000 (11:02 +0200)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Fri, 9 Oct 2015 07:06:22 +0000 (07:06 +0000)
- Support of PCE-triggered state synchronization
- create Rpc to trigger Initial Sync
- Test PCE Trigger initial Sync w/o Incremental sync
- PcepRpcServicesRoutingTest updated

Change-Id: I2c9bae691b695c49ec7866bf888364703345a5eb
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
12 files changed:
integration-tests/src/test/java/org/opendaylight/protocol/integration/pcep/PcepRpcServicesRoutingTest.java
pcep/topology-api/src/main/yang/network-topology-pcep-programming.yang
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/ServerSessionManager.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/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyProgramming.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyRPCs.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologySessionRPCs.java
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/PCETriggeredInitialSyncProcedureTest.java [new file with mode: 0644]
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyProgrammingTest.java

index 2898fda8e101cd3bab4319aff256b244f81121f6..b6422af330e14e7dc2388fb1e00439125caa1c72 100644 (file)
@@ -31,6 +31,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitAddLspInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitEnsureLspOperationalInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitTriggerInitialSyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitTriggerInitialSyncInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
@@ -40,6 +42,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelInputBuilder;
@@ -113,6 +117,7 @@ public class PcepRpcServicesRoutingTest extends AbstractPcepOsgiTest {
 
                 testAddLspRpce(consumerPcepService);
                 testEnsureLspRpce(consumerPcepService);
+                testTriggerInitialSyncRpce(consumerPcepService);
             }
 
             private void testAddLspRpce(final NetworkTopologyPcepService consumerPcepService) {
@@ -130,6 +135,22 @@ public class PcepRpcServicesRoutingTest extends AbstractPcepOsgiTest {
                 verify(pcepService2).addLsp(addLspInput);
             }
 
+            private void testTriggerInitialSyncRpce(final NetworkTopologyPcepService consumerPcepService) {
+                TriggerInitialSyncInput triggerInput = getInputForRpc(topology, TriggerInitialSyncInputBuilder.class,
+                    TriggerInitialSyncInput.class);
+                consumerPcepService.triggerInitialSync(triggerInput);
+
+                verify(pcepService1).triggerInitialSync(triggerInput);
+                verifyZeroInteractions(pcepService2);
+
+                triggerInput = getInputForRpc(topology2, TriggerInitialSyncInputBuilder.class, TriggerInitialSyncInput.class);
+
+                consumerPcepService.triggerInitialSync(triggerInput);
+
+                verifyZeroInteractions(pcepService1);
+                verify(pcepService2).triggerInitialSync(triggerInput);
+            }
+
             private void testEnsureLspRpce(final NetworkTopologyPcepService consumerPcepService) {
                 EnsureLspOperationalInput ensureInput = getInputForRpc(topology, EnsureLspOperationalInputBuilder.class,
                         EnsureLspOperationalInput.class);
@@ -157,6 +178,7 @@ public class PcepRpcServicesRoutingTest extends AbstractPcepOsgiTest {
         final ListenableFuture future = Futures.immediateFuture(RpcResultBuilder.<AddLspOutput>success().build());
         when(pcepService.addLsp(Mockito.<AddLspInput>any())).thenReturn(future);
         when(pcepService.removeLsp(Mockito.<RemoveLspInput>any())).thenReturn(future);
+        when(pcepService.triggerInitialSync(Mockito.<TriggerInitialSyncInput>any())).thenReturn(future);
         when(pcepService.ensureLspOperational(Mockito.<EnsureLspOperationalInput>any())).thenReturn(future);
         when(pcepService.updateLsp(Mockito.<UpdateLspInput>any())).thenReturn(future);
 
@@ -229,6 +251,7 @@ public class PcepRpcServicesRoutingTest extends AbstractPcepOsgiTest {
 
                 testSubmitAddLspRpc(consumerPcepService);
                 testSubmitUpdateLspRpc(consumerPcepService);
+                testTriggerInitialSyncRpc(consumerPcepService);
             }
 
             private void testSubmitAddLspRpc(final NetworkTopologyPcepProgrammingService consumerPcepService) {
@@ -261,6 +284,24 @@ public class PcepRpcServicesRoutingTest extends AbstractPcepOsgiTest {
                 verifyZeroInteractions(pcepService1);
                 verify(pcepService2).submitUpdateLsp(submitLspInput);
             }
+
+            private void testTriggerInitialSyncRpc(final NetworkTopologyPcepProgrammingService consumerPcepService) {
+                SubmitTriggerInitialSyncInput submitTriggerInput = getInputForRpc(topology,
+                    SubmitTriggerInitialSyncInputBuilder.class,
+                    SubmitTriggerInitialSyncInput.class);
+                consumerPcepService.submitTriggerInitialSync(submitTriggerInput);
+
+                verify(pcepService1).submitTriggerInitialSync(submitTriggerInput);
+                verifyZeroInteractions(pcepService2);
+
+                submitTriggerInput = getInputForRpc(topology2, SubmitTriggerInitialSyncInputBuilder.class,
+                    SubmitTriggerInitialSyncInput.class);
+
+                consumerPcepService.submitTriggerInitialSync(submitTriggerInput);
+
+                verifyZeroInteractions(pcepService1);
+                verify(pcepService2).submitTriggerInitialSync(submitTriggerInput);
+            }
         };
         broker.registerConsumer(consumer, getBundleContext());
     }
@@ -271,6 +312,7 @@ public class PcepRpcServicesRoutingTest extends AbstractPcepOsgiTest {
         final ListenableFuture future = Futures.immediateFuture(RpcResultBuilder.<AddLspOutput>success().build());
         when(pcepService.submitAddLsp(Mockito.<SubmitAddLspInput>any())).thenReturn(future);
         when(pcepService.submitRemoveLsp(Mockito.<SubmitRemoveLspInput>any())).thenReturn(future);
+        when(pcepService.submitTriggerInitialSync(Mockito.<SubmitTriggerInitialSyncInput>any())).thenReturn(future);
         when(pcepService.submitEnsureLspOperational(Mockito.<SubmitEnsureLspOperationalInput>any())).thenReturn(future);
         when(pcepService.submitUpdateLsp(Mockito.<SubmitUpdateLspInput>any())).thenReturn(future);
     }
index 2af49509b73391998b978f575d5912a77efbbb89..b351c8390ac359e3378d561ddafbf2828f7d8e72 100644 (file)
@@ -76,5 +76,15 @@ module network-topology-pcep-programming {
             uses ntp:topology-instruction-output;
         }
     }
+
+    rpc submit-trigger-initial-sync {
+        input {
+            uses ntp:topology-instruction-input;
+            uses pcep:trigger-initial-sync-args;
+        }
+        output {
+            uses ntp:topology-instruction-output;
+        }
+    }
 }
 
index 5b0aa4ecbca3e68fcf9b96cf88481295b9860b3c..2ac5bdc08907ec0ad12cd27cce80c29bcdf2da7d 100644 (file)
@@ -50,6 +50,10 @@ module network-topology-pcep {
                 description
                     "Incremental state resynchronization is being performed.";
             }
+            enum triggered-initial-sync {
+                description
+                     "Triggered initial state resynchronization is being performed.";
+            }
             enum synchronized {
                 description
                     "State synchronization has been achieved.";
@@ -270,5 +274,22 @@ module network-topology-pcep {
             uses operation-result;
         }
     }
+
+    grouping trigger-initial-sync-args {
+        leaf node {
+            type nt:node-ref;
+            mandatory true;
+        }
+    }
+
+    rpc trigger-initial-sync {
+        input {
+            uses ont:network-topology-reference;
+            uses trigger-initial-sync-args;
+        }
+        output {
+            uses operation-result;
+        }
+    }
 }
 
index 4bd2117bf60af3cc39e96f732fabeb5e69fd1e84..1de5e1b2da853bf4377bd3e95032f5cbed65ee9b 100644 (file)
@@ -511,6 +511,13 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
         return false;
     }
 
+    protected final boolean isTriggeredInitialSynchro() {
+        if (syncOptimization != null) {
+            return syncOptimization.isTriggeredInitSyncEnabled();
+        }
+        return false;
+    }
+
     protected final boolean isSynchronized() {
         if (syncOptimization != null) {
             return syncOptimization.doesLspDbMatch();
index 3fbe5c8cfccffe5407aa61fcb6d1e856796b01ca..f59029c93b50ebfc156cf41fe300ff9765ce961b 100644 (file)
@@ -35,6 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcepBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
@@ -147,6 +148,12 @@ final class ServerSessionManager implements PCEPSessionListenerFactory, AutoClos
         return (l != null) ? l.ensureLspOperational(input) : OperationResults.UNSENT.future();
     }
 
+    @Override
+    public synchronized ListenableFuture<OperationResult> triggerInitialSync(final TriggerInitialSyncArgs input) {
+        final TopologySessionListener l = checkSessionPresence(input.getNode());
+        return (l != null) ? l.triggerInitialSync(input) : OperationResults.UNSENT.future();
+    }
+
     @Override
     public void close() throws TransactionCommitFailedException {
         if (this.runtimeRootRegistration.isPresent()) {
index 00fbee7511832160037253c883dc64aca42096f8..446f6b27f716bf36d5d4875c66d7e6a14f9b6b39 100644 (file)
@@ -64,6 +64,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.iet
 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.Message;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PcerrMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.Tlvs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.path.setup.type.tlv.PathSetupType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
@@ -73,6 +74,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
 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.RemoveLspArgs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClientBuilder;
@@ -114,6 +116,8 @@ class Stateful07TopologySessionListener extends AbstractTopologySessionListener<
                 pccBuilder.setReportedLsp(Collections.<ReportedLsp> emptyList());
                 if (isSynchronized()) {
                     pccBuilder.setStateSync(PccSyncState.Synchronized);
+                } else if (isTriggeredInitialSynchro()) {
+                    pccBuilder.setStateSync(PccSyncState.TriggeredInitialSync);
                 } else if (isIncrementalSynchro()) {
                     pccBuilder.setStateSync(PccSyncState.IncrementalSync);
                 } else {
@@ -129,6 +133,45 @@ class Stateful07TopologySessionListener extends AbstractTopologySessionListener<
         }
     }
 
+    /**
+     * when PCE-triggered Initial State Synchronization Procedure is set during the session establishment, PCC will
+     * wait arrival of PCUpd message with PLSP-ID = 0 and SYNC = 1 in order to trigger the LSP-DB synchronization
+     * process.
+     * @param input
+     * @return
+     */
+    @Override
+    public synchronized ListenableFuture<OperationResult> triggerInitialSync(final TriggerInitialSyncArgs input) {
+        if(isTriggeredInitialSynchro() && !isSynchronized()) {
+            final PcupdMessageBuilder pcupdMessageBuilder = new PcupdMessageBuilder(MESSAGE_HEADER);
+            final SrpIdNumber srpIdNumber = createUpdateMessageSync(pcupdMessageBuilder);
+            final Message msg = new PcupdBuilder().setPcupdMessage(pcupdMessageBuilder.build()).build();
+            // Send the message
+            return sendMessage(msg, srpIdNumber, null);
+        }
+        return OperationResults.UNSENT.future();
+    }
+
+    private SrpIdNumber createUpdateMessageSync(final PcupdMessageBuilder pcupdMessageBuilder) {
+        final UpdatesBuilder updBuilder = new UpdatesBuilder();
+        // LSP mandatory in Upd
+        final Lsp lsp = new LspBuilder().setPlspId(new PlspId(0L)).setSync(Boolean.TRUE).build();
+        // SRP Mandatory in Upd
+        final SrpBuilder srpBuilder = new SrpBuilder();
+        // not sue wheter use 0 instead of nextRequest() or dont  insert srp == SRP-ID-number = 0
+        srpBuilder.setOperationId(nextRequest());
+        final Srp srp = srpBuilder.build();
+        //ERO Mandatory in Upd
+        final PathBuilder pb = new PathBuilder();
+        pb.setEro(new EroBuilder().build());
+
+        updBuilder.setPath(pb.build());
+        updBuilder.setLsp(lsp).setSrp(srp).setPath(pb.build());
+
+        pcupdMessageBuilder.setUpdates(Collections.singletonList(updBuilder.build()));
+        return srp.getOperationId();
+    }
+
     private boolean handleErrorMessage(final PcerrMessage message) {
         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessage errMsg = message.getPcerrMessage();
         if (errMsg.getErrorType() instanceof StatefulCase) {
index 05449beeeb5414fc1c22d83b87a98170cef8e3a7..9e0333c88a018dc1aa1f766df1f19ae9d43c756d 100644 (file)
@@ -22,6 +22,8 @@ final class SyncOptimization {
     private final boolean isSyncAvoidanceEnabled;
     private final boolean isDeltaSyncEnabled;
     private final boolean isDbVersionPresent;
+    private final boolean isTriggeredInitialSynEnable;
+    private final boolean isTriggeredReSynEnable;
 
     public SyncOptimization(final PCEPSession session) {
         Preconditions.checkNotNull(session);
@@ -33,6 +35,8 @@ final class SyncOptimization {
         this.isSyncAvoidanceEnabled = isSyncAvoidance(local) && isSyncAvoidance(remote);
         this.isDeltaSyncEnabled = isDeltaSync(local) && isDeltaSync(remote);
         this.isDbVersionPresent = localLspDbVersion != null || remoteLspDbVersion != null;
+        this.isTriggeredInitialSynEnable = isTriggeredInitialSync(local) && isTriggeredInitialSync(remote);
+        this.isTriggeredReSynEnable = isTriggeredReSync(local) && isTriggeredReSync(remote);
     }
 
     public boolean doesLspDbMatch() {
@@ -46,6 +50,13 @@ final class SyncOptimization {
     public boolean isDeltaSyncEnabled() {
         return isDeltaSyncEnabled;
     }
+    /**
+     * Returns
+     * @return isTriggeredInitialSynEnable
+     */
+    public boolean isTriggeredInitSyncEnabled() {
+        return isTriggeredInitialSynEnable;
+    }
 
     public boolean isDbVersionPresent() {
         return isDbVersionPresent;
@@ -95,4 +106,19 @@ final class SyncOptimization {
         return false;
     }
 
+    private static boolean isTriggeredInitialSync(final Tlvs openTlvs) {
+        final Stateful1 stateful1 = getStateful1(openTlvs);
+        if (stateful1 != null && stateful1.isTriggeredInitialSync() != null) {
+            return stateful1.isTriggeredInitialSync();
+        }
+        return false;
+    }
+
+    private static boolean isTriggeredReSync(final Tlvs openTlvs) {
+        final Stateful1 stateful1 = getStateful1(openTlvs);
+        if (stateful1 != null && stateful1.isTriggeredResync() != null) {
+            return stateful1.isTriggeredResync();
+        }
+        return false;
+    }
 }
index 3e1c7108051307db66bc9a9ca7d70b7c2ef83e74..c6c6239e96c17ac811379876210c2a673f970b62 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.bgpcep.pcep.topology.provider;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-
 import org.opendaylight.bgpcep.pcep.topology.spi.AbstractInstructionExecutor;
 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
 import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
@@ -24,6 +23,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitTriggerInitialSyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitTriggerInitialSyncOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitTriggerInitialSyncOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspOutputBuilder;
@@ -117,4 +119,21 @@ final class TopologyProgramming implements NetworkTopologyPcepProgrammingService
         final RpcResult<SubmitEnsureLspOperationalOutput> res = SuccessfulRpcResult.create(b.build());
         return Futures.immediateFuture(res);
     }
+
+
+    @Override
+    public ListenableFuture<RpcResult<SubmitTriggerInitialSyncOutput>> submitTriggerInitialSync(final SubmitTriggerInitialSyncInput input) {
+        Preconditions.checkArgument(input.getNode() != null);
+
+        final SubmitTriggerInitialSyncOutputBuilder b = new SubmitTriggerInitialSyncOutputBuilder();
+        b.setResult(AbstractInstructionExecutor.schedule(scheduler, new AbstractInstructionExecutor(input) {
+            @Override
+            protected ListenableFuture<OperationResult> invokeOperation() {
+                return TopologyProgramming.this.manager.triggerInitialSync(input);
+            }
+        }));
+
+        final RpcResult<SubmitTriggerInitialSyncOutput> res = SuccessfulRpcResult.create(b.build());
+        return Futures.immediateFuture(res);
+    }
 }
index 24ecaa974ad62877dbec37ea5ea7dd4f1c592058..38429fc73464a6b9416c0df8e74c0577e769c891 100644 (file)
@@ -10,9 +10,7 @@ package org.opendaylight.bgpcep.pcep.topology.provider;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.Futures;
-
 import java.util.concurrent.Future;
-
 import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutput;
@@ -25,6 +23,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutputBuilder;
@@ -57,6 +58,16 @@ final class TopologyRPCs implements NetworkTopologyPcepService {
         });
     }
 
+    @Override
+    public Future<RpcResult<TriggerInitialSyncOutput>> triggerInitialSync(final TriggerInitialSyncInput input) {
+        return Futures.transform(manager.triggerInitialSync(input), new Function<OperationResult, RpcResult<TriggerInitialSyncOutput>>() {
+            @Override
+            public RpcResult<TriggerInitialSyncOutput> apply(final OperationResult input) {
+                return SuccessfulRpcResult.create(new TriggerInitialSyncOutputBuilder(input).build());
+            }
+        });
+    }
+
     @Override
     public Future<RpcResult<UpdateLspOutput>> updateLsp(final UpdateLspInput input) {
         return Futures.transform(manager.updateLsp(input), new Function<OperationResult, RpcResult<UpdateLspOutput>>() {
index b28067e879d0e8b8c730da934636066fe3eb0c38..4ad8eb03ca0f30a76423c1a49a4a9f1ed9429ad0 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
 
 interface TopologySessionRPCs {
@@ -23,4 +24,6 @@ interface TopologySessionRPCs {
     ListenableFuture<OperationResult> updateLsp(UpdateLspArgs input);
 
     ListenableFuture<OperationResult> ensureLspOperational(EnsureLspOperationalInput input);
+
+    ListenableFuture<OperationResult> triggerInitialSync(TriggerInitialSyncArgs input);
 }
\ No newline at end of file
diff --git a/pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/PCETriggeredInitialSyncProcedureTest.java b/pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/PCETriggeredInitialSyncProcedureTest.java
new file mode 100644 (file)
index 0000000..fbc31d0
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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 PCETriggeredInitialSyncProcedureTest extends AbstractPCEPSessionTest<Stateful07TopologySessionListenerFactory> {
+    private Stateful07TopologySessionListener listener;
+
+    private PCEPSession session;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        this.listener = (Stateful07TopologySessionListener) getSessionListener();
+    }
+
+    /**
+     * Test Triggered Initial Sync procedure
+     **/
+    @Test
+    public void testPcepTriggeredInitialSyncPerformed() throws InterruptedException, ExecutionException {
+        this.listener = (Stateful07TopologySessionListener) getSessionListener();
+
+        //session up - expect triggered sync (LSP-DBs do not match)
+        final LspDbVersion localDbVersion = new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(1l)).build();
+        final LspDbVersion localDbVersion2 = new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(2l)).build();
+        this.session = getPCEPSession(getOpen(localDbVersion, Boolean.FALSE), getOpen(localDbVersion2, Boolean.FALSE));
+        this.listener.onSessionUp(session);
+
+        final PathComputationClient pcc2 = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+        //check node - not synchronized and TriggeredInitialSync state
+        Assert.assertEquals(PccSyncState.TriggeredInitialSync, pcc2.getStateSync());
+        //sync rpt + LSP-DB
+        final Pcrpt syncMsg = getsyncMsg();
+        this.listener.onMessage(session, syncMsg);
+        final PathComputationClient pcc3 = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+        //check node - synchronized
+        Assert.assertEquals(PccSyncState.Synchronized, pcc3.getStateSync());
+        //check reported LSP is empty, LSP state from previous session was purged
+        Assert.assertTrue(pcc3.getReportedLsp().isEmpty());
+
+        //report LSP + LSP-DB version number
+        final Pcrpt pcRpt = getPcrpt();
+        this.listener.onMessage(session, pcRpt);
+        final PathComputationClient pcc = getTopology().get().getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+        Assert.assertFalse(pcc.getReportedLsp().isEmpty());
+    }
+
+    private Open getOpen(final LspDbVersion dbVersion, final boolean incremental) {
+        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).setTriggeredInitialSync(Boolean.TRUE).setDeltaLspSyncCapability(incremental).build())
+            .build()).build()).addAugmentation(Tlvs3.class, new Tlvs3Builder().setLspDbVersion(dbVersion).build()).build()).build();
+    }
+
+    private Pcrpt getsyncMsg() {
+        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(2l)).build()).build()).build()), true, false), Optional.<Srp>absent(),
+                        createPath(Collections.<Subobject>emptyList()));
+    }
+
+    private Pcrpt getPcrpt() {
+        return MsgBuilderUtil.createPcRtpMessage(new LspBuilder().setPlspId(new PlspId(1l)).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(1l)).build
+                ()).setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(new SymbolicPathName("test"
+                .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(3l)).build())
+                .build()).build()).setPlspId(new PlspId(1L)).setSync(true).setRemove(false).setOperational
+            (OperationalStatus.Active).build(), Optional.<Srp>absent(), createPath(Collections.<Subobject>emptyList()));
+    }
+}
index 94b1e9cfdf3a3c82f88c93d84180dd1ad4605deb..2e94da5a897b71ab288a5d9397171aefa3df68a4 100644 (file)
@@ -33,6 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programm
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitAddLspInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitEnsureLspOperationalInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitTriggerInitialSyncInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
@@ -42,6 +43,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncArgs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TriggerInitialSyncOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutput;
@@ -63,6 +67,7 @@ public class TopologyProgrammingTest extends AbstractPCEPSessionTest<MockedTopol
     private AddLspArgs addLspArgs;
     private UpdateLspArgs updateLspArgs;
     private RemoveLspArgs removeLspArgs;
+    private TriggerInitialSyncArgs triggerInitialSyncArgs;
     private EnsureLspOperationalInput ensureLspInput;
 
     @Mock
@@ -72,6 +77,8 @@ public class TopologyProgrammingTest extends AbstractPCEPSessionTest<MockedTopol
     @Mock
     private ListenableFuture<RpcResult<RemoveLspOutput>> futureRemoveLspOutput;
     @Mock
+    private ListenableFuture<RpcResult<TriggerInitialSyncOutput>> futureTriggerInitialSyncOutput;
+    @Mock
     private ListenableFuture<RpcResult<EnsureLspOperationalOutput>> futureEnsureLspOutput;
 
     private TopologyProgramming topologyProgramming;
@@ -116,6 +123,14 @@ public class TopologyProgrammingTest extends AbstractPCEPSessionTest<MockedTopol
                 return null;
             }
         }).when(this.futureRemoveLspOutput).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class));
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(final InvocationOnMock invocation) throws Throwable {
+                final Runnable callback = (Runnable) invocation.getArguments()[0];
+                callback.run();
+                return null;
+            }
+        }).when(this.futureTriggerInitialSyncOutput).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class));
         Mockito.doAnswer(new Answer<Void>() {
             @Override
             public Void answer(final InvocationOnMock invocation) throws Throwable {
@@ -145,6 +160,13 @@ public class TopologyProgrammingTest extends AbstractPCEPSessionTest<MockedTopol
                 return TopologyProgrammingTest.this.futureRemoveLspOutput;
             }
         }).when(listener).removeLsp(Mockito.any(RemoveLspInput.class));
+        Mockito.doAnswer(new Answer<Future<RpcResult<TriggerInitialSyncOutput>>>() {
+            @Override
+            public Future<RpcResult<TriggerInitialSyncOutput>> answer(final InvocationOnMock invocation) throws Throwable {
+                TopologyProgrammingTest.this.triggerInitialSyncArgs = (TriggerInitialSyncArgs) invocation.getArguments()[0];
+                return TopologyProgrammingTest.this.futureTriggerInitialSyncOutput;
+            }
+        }).when(listener).triggerInitialSync(Mockito.any(TriggerInitialSyncInput.class));
         Mockito.doAnswer(new Answer<Future<RpcResult<EnsureLspOperationalOutput>>>() {
             @Override
             public Future<RpcResult<EnsureLspOperationalOutput>> answer(final InvocationOnMock invocation) throws Throwable {
@@ -207,6 +229,15 @@ public class TopologyProgrammingTest extends AbstractPCEPSessionTest<MockedTopol
         Assert.assertEquals(NODE_ID, this.removeLspArgs.getNode());
     }
 
+    @Test
+    public void testSubmitTriggerInitialSync() {
+        final SubmitTriggerInitialSyncInputBuilder inputBuilder = new SubmitTriggerInitialSyncInputBuilder();
+        inputBuilder.setNode(NODE_ID);
+        this.topologyProgramming.submitTriggerInitialSync(inputBuilder.build());
+        Assert.assertNotNull(this.triggerInitialSyncArgs);
+        Assert.assertEquals(NODE_ID, this.triggerInitialSyncArgs.getNode());
+    }
+
     protected static final class MockedTopologySessionListenerFactory implements TopologySessionListenerFactory {
         @Override
         public TopologySessionListener createTopologySessionListener(final ServerSessionManager manager) {