Bug-2081: PCEP statistics
[bgpcep.git] / pcep / topology-provider / src / main / java / org / opendaylight / bgpcep / pcep / topology / provider / Stateful07TopologySessionListener.java
index 4425f21a62d935f28988c21e272043ee12f16a49..64ada921bb1a631323b4b1701af42e07a6729b48 100644 (file)
@@ -8,31 +8,36 @@
 package org.opendaylight.bgpcep.pcep.topology.provider;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-
 import java.net.InetAddress;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Collections;
-
-import javax.annotation.concurrent.GuardedBy;
-
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
 import org.opendaylight.protocol.pcep.PCEPSession;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
+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.pcinitiate.message.PcinitiateMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.RequestsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Arguments3;
 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.Path1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Path1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcrptMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcupdBuilder;
 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.ReportedLsp1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.ReportedLsp1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.StatefulTlv1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.StatefulTlv1Builder;
@@ -56,6 +61,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.typ
 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.topology.pcep.rev131024.AddLspArgs;
 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.LspId;
 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;
@@ -71,6 +77,8 @@ import org.slf4j.LoggerFactory;
 final class Stateful07TopologySessionListener extends AbstractTopologySessionListener<SrpIdNumber, PlspId> {
     private static final Logger LOG = LoggerFactory.getLogger(Stateful07TopologySessionListener.class);
 
+    private final AtomicLong requestId = new AtomicLong(1L);
+
     /**
      * @param serverSessionManager
      */
@@ -78,9 +86,6 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
         super(serverSessionManager);
     }
 
-    @GuardedBy("this")
-    private long requestId = 1;
-
     @Override
     protected void onSessionUp(final PCEPSession session, final PathComputationClientBuilder pccBuilder) {
         final InetAddress peerAddress = session.getRemoteAddress();
@@ -89,10 +94,11 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
         if (tlvs != null && tlvs.getAugmentation(Tlvs1.class) != null) {
             final Stateful stateful = tlvs.getAugmentation(Tlvs1.class).getStateful();
             if (stateful != null) {
+                getSessionListenerState().setPeerCapabilities(getCapabilities(stateful));
                 pccBuilder.setReportedLsp(Collections.<ReportedLsp> emptyList());
                 pccBuilder.setStateSync(PccSyncState.InitialResync);
                 pccBuilder.setStatefulTlv(new StatefulTlvBuilder().addAugmentation(StatefulTlv1.class,
-                        new StatefulTlv1Builder(tlvs.getAugmentation(Tlvs1.class)).build()).build());
+                    new StatefulTlv1Builder(tlvs.getAugmentation(Tlvs1.class)).build()).build());
             } else {
                 LOG.debug("Peer {} does not advertise stateful TLV", peerAddress);
             }
@@ -101,52 +107,48 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
         }
     }
 
-    @Override
-    protected synchronized boolean onMessage(final DataModificationTransaction trans, final Message message) {
-        if (message instanceof PcerrMessage) {
-            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessage errMsg = ((PcerrMessage) message).getPcerrMessage();
-            if (errMsg.getErrorType() instanceof StatefulCase) {
-                StatefulCase stat = (StatefulCase)errMsg.getErrorType();
-                for (Srps srps : stat.getStateful().getSrps()) {
-                    SrpIdNumber id = srps.getSrp().getOperationId();
-                    if (id.getValue() != 0) {
-                        final PCEPRequest req = removeRequest(id);
-                        if (req != null) {
-                            req.setResult(OperationResults.SUCCESS);
-                        } else {
-                            LOG.warn("Request ID {} not found in outstanding DB", id);
-                        }
+    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) {
+            final StatefulCase stat = (StatefulCase)errMsg.getErrorType();
+            for (final Srps srps : stat.getStateful().getSrps()) {
+                final SrpIdNumber id = srps.getSrp().getOperationId();
+                if (id.getValue() != 0) {
+                    final PCEPRequest req = removeRequest(id);
+                    if (req != null) {
+                        req.done(OperationResults.createFailed(errMsg.getErrors()));
+                    } else {
+                        LOG.warn("Request ID {} not found in outstanding DB", id);
                     }
                 }
-            } else {
-                LOG.warn("Unhandled PCErr message {}.", errMsg);
-                return true;
             }
-            return false;
+        } else {
+            LOG.warn("Unhandled PCErr message {}.", errMsg);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean onMessage(final MessageContext ctx, final Message message) {
+        if (message instanceof PcerrMessage) {
+            return handleErrorMessage((PcerrMessage) message);
         }
         if (!(message instanceof PcrptMessage)) {
             return true;
         }
-
+        getSessionListenerState().updateLastReceivedRptMsg();
         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.PcrptMessage rpt = ((PcrptMessage) message).getPcrptMessage();
-        for (final Reports r : rpt.getReports()) {
-            final Lsp lsp = r.getLsp();
-
-            if (!lsp.isSync() && (lsp.getPlspId() == null || lsp.getPlspId().getValue() == 0)) {
-                stateSynchronizationAchieved(trans);
+        for (final Reports report : rpt.getReports()) {
+            final Lsp lsp = report.getLsp();
+            final PlspId plspid = lsp.getPlspId();
+            if (!lsp.isSync() && (lsp.getPlspId() == null || plspid.getValue() == 0)) {
+                stateSynchronizationAchieved(ctx);
                 continue;
             }
-
             final ReportedLspBuilder rlb = new ReportedLspBuilder();
-            rlb.addAugmentation(ReportedLsp1.class, new ReportedLsp1Builder(r).build());
-            if (r.getPath() != null) {
-                org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.PathBuilder pb = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.PathBuilder();
-                pb.fieldsFrom(r.getPath());
-                rlb.setPath(pb.build());
-            }
             boolean solicited = false;
-
-            final Srp srp = r.getSrp();
+            final Srp srp = report.getSrp();
             if (srp != null) {
                 final SrpIdNumber id = srp.getOperationId();
                 if (id.getValue() != 0) {
@@ -160,7 +162,7 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
                         if (req != null) {
                             LOG.debug("Request {} resulted in LSP operational state {}", id, lsp.getOperational());
                             rlb.setMetadata(req.getMetadata());
-                            req.setResult(OperationResults.SUCCESS);
+                            ctx.resolveRequest(req);
                         } else {
                             LOG.warn("Request ID {} not found in outstanding DB", id);
                         }
@@ -171,149 +173,236 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
                         // up...
                         break;
                     }
+                    // if remove flag is set in SRP object, remove the tunnel immediately
+                    if (srp.getAugmentation(Srp1.class) != null) {
+                        final Srp1 initiatedSrp = srp.getAugmentation(Srp1.class);
+                        if (initiatedSrp.isRemove()) {
+                            super.removeLsp(ctx, plspid);
+                            return false;
+                        }
+                    }
                 }
             }
-
-            final PlspId id = lsp.getPlspId();
-            if (!lsp.isRemove()) {
-                final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = r.getLsp().getTlvs();
-                final String name;
-                if (tlvs != null && tlvs.getSymbolicPathName() != null) {
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.PathBuilder pb = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.PathBuilder();
+            if (report.getPath() != null) {
+                pb.fieldsFrom(report.getPath());
+            }
+            // LSP is mandatory (if there is none, parser will throw an exception)
+            // this is to ensure a path will be created at any rate
+            pb.addAugmentation(Path1.class, new Path1Builder().setLsp(report.getLsp()).build());
+            String name = lookupLspName(plspid);
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = report.getLsp().getTlvs();
+            if (tlvs != null) {
+                if (tlvs.getLspIdentifiers() != null) {
+                    pb.setLspId(tlvs.getLspIdentifiers().getLspId());
+                }
+                if (tlvs.getSymbolicPathName() != null) {
                     name = Charsets.UTF_8.decode(ByteBuffer.wrap(tlvs.getSymbolicPathName().getPathName().getValue())).toString();
-                } else {
-                    name = null;
                 }
-
-                updateLsp(trans, id, name, rlb, solicited);
-                LOG.debug("LSP {} updated", lsp);
-            } else {
-                removeLsp(trans, id);
-                LOG.debug("LSP {} removed", lsp);
             }
+            rlb.setPath(Collections.singletonList(pb.build()));
+            updateLsp(ctx, plspid, name, rlb, solicited, lsp.isRemove());
+            LOG.debug("LSP {} updated", lsp);
         }
-
         return false;
     }
 
-    @GuardedBy("this")
     private SrpIdNumber nextRequest() {
-        return new SrpIdNumber(this.requestId++);
+        return new SrpIdNumber(this.requestId.getAndIncrement());
     }
 
     @Override
     public synchronized ListenableFuture<OperationResult> addLsp(final AddLspArgs input) {
-        Preconditions.checkArgument(input != null && input.getName() != null & input.getNode() != null && input.getArguments() != null, "Mandatory XML tags are missing.");
+        Preconditions.checkArgument(input != null && input.getName() != null && input.getNode() != null && input.getArguments() != null, MISSING_XML_TAG);
         LOG.trace("AddLspArgs {}", input);
         // Make sure there is no such LSP
-        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName()).build();
-        if (readOperationalData(lsp) != null) {
-            LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
-            return OperationResults.UNSENT.future();
-        }
-        // Build the request
-        final RequestsBuilder rb = new RequestsBuilder();
-        Arguments2 args = input.getArguments().getAugmentation(Arguments2.class);
-        Preconditions.checkState(args != null, "Input is missing operational tag.");
-        Lsp inputLsp = args.getLsp();
-        Preconditions.checkState(inputLsp != null, "Reported LSP does not contain LSP object.");
+        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
+        final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
+
+        return Futures.transform(f, new AsyncFunction<Optional<ReportedLsp>, OperationResult>() {
+            @Override
+            public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
+                if (rep.isPresent()) {
+                    LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
+                    return OperationResults.UNSENT.future();
+                }
 
-        rb.fieldsFrom(input.getArguments());
-        rb.setSrp(new SrpBuilder().setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build());
-        rb.setLsp(new LspBuilder().setAdministrative(inputLsp.isAdministrative()).setDelegate(inputLsp.isDelegate()).setPlspId(
-                new PlspId(0L)).setTlvs(
-                        new TlvsBuilder().setSymbolicPathName(
-                                new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(input.getName().getBytes(Charsets.UTF_8))).build()).build()).build());
+                // Build the request
+                final RequestsBuilder rb = new RequestsBuilder();
+                final Arguments2 args = input.getArguments().getAugmentation(Arguments2.class);
+                Preconditions.checkArgument(args != null, "Input is missing operational tag.");
+                final Lsp inputLsp = args.getLsp();
+                Preconditions.checkArgument(inputLsp != null, "Reported LSP does not contain LSP object.");
 
-        final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder(MESSAGE_HEADER);
-        ib.setRequests(ImmutableList.of(rb.build()));
+                rb.fieldsFrom(input.getArguments());
 
-        // Send the message
-        return sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId(),
-                input.getArguments().getMetadata());
+                final TlvsBuilder tlvsBuilder = new TlvsBuilder();
+                tlvsBuilder.setSymbolicPathName(
+                    new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(input.getName().getBytes(Charsets.UTF_8))).build());
+                if (inputLsp.getTlvs() != null) {
+                    tlvsBuilder.setVsTlv(inputLsp.getTlvs().getVsTlv());
+                }
+
+                rb.setSrp(new SrpBuilder().setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build());
+                rb.setLsp(new LspBuilder().setAdministrative(inputLsp.isAdministrative()).setDelegate(inputLsp.isDelegate()).setPlspId(
+                    new PlspId(0L)).setTlvs(tlvsBuilder.build()).build());
+
+                final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder(MESSAGE_HEADER);
+                ib.setRequests(Collections.singletonList(rb.build()));
+
+                // Send the message
+                return sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId(),
+                    input.getArguments().getMetadata());
+            }
+        });
     }
 
     @Override
     public synchronized ListenableFuture<OperationResult> removeLsp(final RemoveLspArgs input) {
-        Preconditions.checkArgument(input != null && input.getName() != null & input.getNode() != null, "Mandatory XML tags are missing.");
+        Preconditions.checkArgument(input != null && input.getName() != null && input.getNode() != null, MISSING_XML_TAG);
+        LOG.trace("RemoveLspArgs {}", input);
         // Make sure the LSP exists, we need it for PLSP-ID
-        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName()).build();
-        final ReportedLsp rep = readOperationalData(lsp);
-        if (rep == null) {
-            LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
-            return OperationResults.UNSENT.future();
-        }
-
-        final ReportedLsp1 ra = rep.getAugmentation(ReportedLsp1.class);
-        Preconditions.checkState(ra != null, "Reported LSP reported null from data-store.");
-        Lsp reportedLsp = ra.getLsp();
-        Preconditions.checkState(reportedLsp != null, "Reported LSP does not contain LSP object.");
-
-        // Build the request and send it
-        final RequestsBuilder rb = new RequestsBuilder();
-        rb.setSrp(new SrpBuilder().addAugmentation(Srp1.class, new Srp1Builder().setRemove(Boolean.TRUE).build()).setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build());
-        rb.setLsp(new LspBuilder().setRemove(Boolean.TRUE).setPlspId(reportedLsp.getPlspId()).setDelegate(reportedLsp.isDelegate()).build());
-
-        final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder(MESSAGE_HEADER);
-        ib.setRequests(ImmutableList.of(rb.build()));
-        return sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId(), null);
+        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
+        final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
+
+        return Futures.transform(f, new AsyncFunction<Optional<ReportedLsp>, OperationResult>() {
+            @Override
+            public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
+                final Lsp reportedLsp = validateReportedLsp(rep, input);
+                if (reportedLsp == null) {
+                    return OperationResults.UNSENT.future();
+                }
+                // Build the request and send it
+                final RequestsBuilder rb = new RequestsBuilder();
+                rb.setSrp(new SrpBuilder().addAugmentation(Srp1.class, new Srp1Builder().setRemove(Boolean.TRUE).build()).setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build());
+                rb.setLsp(new LspBuilder().setRemove(Boolean.FALSE).setPlspId(reportedLsp.getPlspId()).setDelegate(reportedLsp.isDelegate()).build());
+
+                final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder(MESSAGE_HEADER);
+                ib.setRequests(Collections.singletonList(rb.build()));
+                return sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId(), null);
+            }
+        });
     }
 
     @Override
     public synchronized ListenableFuture<OperationResult> updateLsp(final UpdateLspArgs input) {
-        Preconditions.checkArgument(input != null && input.getName() != null & input.getNode() != null && input.getArguments() != null, "Mandatory XML tags are missing.");
+        Preconditions.checkArgument(input != null && input.getName() != null && input.getNode() != null && input.getArguments() != null, MISSING_XML_TAG);
+        LOG.trace("UpdateLspArgs {}", input);
         // Make sure the LSP exists
-        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName()).build();
-        final ReportedLsp rep = readOperationalData(lsp);
-        if (rep == null) {
-            LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
-            return OperationResults.UNSENT.future();
-        }
-        final ReportedLsp1 ra = rep.getAugmentation(ReportedLsp1.class);
-        Preconditions.checkState(ra != null, "Reported LSP reported null from data-store.");
-        Lsp reportedLsp = ra.getLsp();
-        Preconditions.checkState(reportedLsp != null, "Reported LSP does not contain LSP object.");
-
-        // Build the PCUpd request and send it
-        final UpdatesBuilder rb = new UpdatesBuilder();
-        rb.setSrp(new SrpBuilder().setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build());
-        rb.setLsp(new LspBuilder().setPlspId(reportedLsp.getPlspId()).setDelegate(reportedLsp.isDelegate()).build());
-        final PathBuilder pb = new PathBuilder();
-        pb.fieldsFrom(input.getArguments());
-        rb.setPath(pb.build());
-        final PcupdMessageBuilder ub = new PcupdMessageBuilder(MESSAGE_HEADER);
-        ub.setUpdates(ImmutableList.of(rb.build()));
-        return sendMessage(new PcupdBuilder().setPcupdMessage(ub.build()).build(), rb.getSrp().getOperationId(),
-                input.getArguments().getMetadata());
+        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
+        final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
+
+        return Futures.transform(f, new AsyncFunction<Optional<ReportedLsp>, OperationResult>() {
+            @Override
+            public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
+                final Lsp reportedLsp = validateReportedLsp(rep, input);
+                if (reportedLsp == null) {
+                    return OperationResults.UNSENT.future();
+                }
+                // create mandatory objects
+                final Srp srp = new SrpBuilder().setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build();
+
+                final Lsp inputLsp = input.getArguments().getAugmentation(Arguments3.class).getLsp();
+                final Lsp lsp = (inputLsp != null) ?
+                    new LspBuilder().setPlspId(reportedLsp.getPlspId()).setDelegate((inputLsp.isDelegate() != null) ? inputLsp.isDelegate() : false).setTlvs(inputLsp.getTlvs()).setAdministrative((inputLsp.isAdministrative() != null) ? inputLsp.isAdministrative() : false).build()
+                    : new LspBuilder().setPlspId(reportedLsp.getPlspId()).build();
+                Message msg = null;
+                // the D bit that was reported decides the type of PCE message sent
+                Preconditions.checkNotNull(reportedLsp.isDelegate());
+                if (reportedLsp.isDelegate()) {
+                    // we already have delegation, send update
+                    final UpdatesBuilder rb = new UpdatesBuilder();
+                    rb.setSrp(srp);
+                    rb.setLsp(lsp);
+                    final PathBuilder pb = new PathBuilder();
+                    pb.fieldsFrom(input.getArguments());
+                    rb.setPath(pb.build());
+                    final PcupdMessageBuilder ub = new PcupdMessageBuilder(MESSAGE_HEADER);
+                    ub.setUpdates(Collections.singletonList(rb.build()));
+                    msg = new PcupdBuilder().setPcupdMessage(ub.build()).build();
+                } else {
+                    // we want to revoke delegation, different type of message
+                    // is sent because of specification by Siva
+                    // this message is also sent, when input delegate bit is set to 0
+                    // generating an error in PCC
+                    final List<Requests> reqs = new ArrayList<>();
+                    reqs.add(new RequestsBuilder().setSrp(srp).setLsp(lsp).build());
+                    final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder();
+                    ib.setRequests(reqs);
+                    msg = new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build();
+                }
+                return sendMessage(msg, srp.getOperationId(), input.getArguments().getMetadata());
+            }
+        });
     }
 
     @Override
     public synchronized ListenableFuture<OperationResult> ensureLspOperational(final EnsureLspOperationalInput input) {
-        Preconditions.checkArgument(input != null && input.getName() != null & input.getNode() != null && input.getArguments() != null, "Mandatory XML tags are missing.");
-        OperationalStatus op = null;
+        Preconditions.checkArgument(input != null && input.getName() != null && input.getNode() != null && input.getArguments() != null, MISSING_XML_TAG);
+        final OperationalStatus op;
         final Arguments1 aa = input.getArguments().getAugmentation(Arguments1.class);
         if (aa != null) {
             op = aa.getOperational();
+        } else {
+            op = null;
         }
 
         // Make sure the LSP exists
-        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName()).build();
+        final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
         LOG.debug("Checking if LSP {} has operational state {}", lsp, op);
-        final ReportedLsp rep = readOperationalData(lsp);
-        if (rep == null) {
+        final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
+
+        return Futures.transform(f, new Function<Optional<ReportedLsp>, OperationResult>() {
+            @Override
+            public OperationResult apply(final Optional<ReportedLsp> rep) {
+                if (!rep.isPresent()) {
+                    LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
+                    return OperationResults.UNSENT;
+                }
+
+                // check if at least one of the paths has the same status as requested
+                boolean operational = false;
+                for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.Path p : rep.get().getPath()) {
+                    final Path1 p1 = p.getAugmentation(Path1.class);
+                    if (p1 == null) {
+                        LOG.warn("Node {} LSP {} does not contain data", input.getNode(), input.getName());
+                        return OperationResults.UNSENT;
+                    }
+                    final Lsp l = p1.getLsp();
+                    if (l.getOperational().equals(op)) {
+                        operational = true;
+                    }
+                }
+
+                return operational ? OperationResults.SUCCESS : OperationResults.UNSENT;
+            }
+        });
+    }
+
+    @Override
+    protected Lsp validateReportedLsp(final Optional<ReportedLsp> rep, final LspId input) {
+        if (!rep.isPresent()) {
             LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
-            return OperationResults.UNSENT.future();
+            return null;
         }
+        // it doesn't matter how many lsps there are in the path list, we only need data that is the same in each path
+        final Path1 ra = rep.get().getPath().get(0).getAugmentation(Path1.class);
+        Preconditions.checkState(ra != null, "Reported LSP reported null from data-store.");
+        final Lsp reportedLsp = ra.getLsp();
+        Preconditions.checkState(reportedLsp != null, "Reported LSP does not contain LSP object.");
+        return reportedLsp;
+    }
 
-        final ReportedLsp1 ra = rep.getAugmentation(ReportedLsp1.class);
-        if (ra == null) {
-            LOG.warn("Node {} LSP {} does not contain data", input.getNode(), input.getName());
-            return OperationResults.UNSENT.future();
+    private static PeerCapabilities getCapabilities(final Stateful stateful) {
+        final PeerCapabilities capa = new PeerCapabilities();
+        capa.setStateful(true);
+        if (stateful.isLspUpdateCapability() != null) {
+            capa.setActive(stateful.isLspUpdateCapability());
         }
-
-        if (ra.getLsp().getOperational().equals(op)) {
-            return OperationResults.SUCCESS.future();
-        } else {
-            return OperationResults.UNSENT.future();
+        final Stateful1 stateful1 = stateful.getAugmentation(Stateful1.class);
+        if (stateful1 != null && stateful1.isInitiation() != null) {
+            capa.setInstantiation(stateful1.isInitiation());
         }
+        return capa;
     }
 }