[ONOS-4170] [ONOS-4163] PCE APP side changes : PceManager (code + UT)

Change-Id: I43db98b2fa3c5930b989d4fa3e2c00f7fa65c5ca
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java
index 3ed670d..d7d18b1 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/BasicPceccHandler.java
@@ -23,13 +23,24 @@
 import java.util.ListIterator;
 import java.util.LinkedList;
 
+import org.onlab.packet.MplsLabel;
+import org.onosproject.core.ApplicationId;
 import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
 import org.onosproject.incubator.net.resource.label.LabelResource;
 import org.onosproject.incubator.net.resource.label.LabelResourceId;
 import org.onosproject.incubator.net.resource.label.LabelResourceService;
 import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
 import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.pce.pcestore.api.LspLocalLabelInfo;
 import org.onosproject.pce.pcestore.PceccTunnelInfo;
@@ -58,6 +69,8 @@
     private static BasicPceccHandler crHandlerInstance = null;
     private LabelResourceService labelRsrcService;
     private PceStore pceStore;
+    private FlowObjectiveService flowObjectiveService;
+    private ApplicationId appId;
 
     /**
      * Initializes default values.
@@ -83,8 +96,11 @@
      * @param labelRsrcService label resource service
      * @param pceStore pce label store
      */
-    public void initialize(LabelResourceService labelRsrcService, PceStore pceStore) {
+    public void initialize(LabelResourceService labelRsrcService, FlowObjectiveService flowObjectiveService,
+                           ApplicationId appId, PceStore pceStore) {
         this.labelRsrcService = labelRsrcService;
+        this.flowObjectiveService = flowObjectiveService;
+        this.appId = appId;
         this.pceStore = pceStore;
     }
 
@@ -106,8 +122,8 @@
         if ((linkList != null) && (linkList.size() > 0)) {
             // Sequence through reverse order to push local labels into devices
             // Generation of labels from egress to ingress
-            for (ListIterator iterator = linkList.listIterator(linkList.size()); iterator.hasPrevious();) {
-                Link link = (Link) iterator.previous();
+            for (ListIterator<Link> iterator = linkList.listIterator(linkList.size()); iterator.hasPrevious();) {
+                Link link = iterator.previous();
                 DeviceId dstDeviceId = link.dst().deviceId();
                 DeviceId srcDeviceId = link.src().deviceId();
                 labelRscList = labelRsrcService.applyFromDevicePool(dstDeviceId, applyNum);
@@ -131,16 +147,14 @@
                     }
 
                     // Push into destination device
-                    //TODO: uncomment below lines once installLocalLabelRule() method is ready
                     // Destination device IN port is link.dst().port()
-                    //installLocalLabelRule(dstDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
-                    //                      LabelType.IN, Objective.Operation.ADD);
+                    installLocalLabelRule(dstDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
+                                          Long.valueOf(LabelType.IN_LABEL.value), Objective.Operation.ADD);
 
                     // Push into source device
-                    //TODO: uncomment below lines once installLocalLabelRule() method is ready
                     // Source device OUT port will be link.dst().port(). Means its remote port used to send packet.
-                    //installLocalLabelRule(srcDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
-                    //                      LabelType.OUT, Objective.Operation.ADD);
+                    installLocalLabelRule(srcDeviceId, labelId, dstPort, tunnel.tunnelId(), isLastLabelToPush,
+                                          Long.valueOf(LabelType.OUT_LABEL.value), Objective.Operation.ADD);
 
                     // Add or update pcecc tunnel info in pce store.
                     updatePceccTunnelInfoInStore(srcDeviceId, dstDeviceId, labelId, dstPort,
@@ -183,7 +197,7 @@
            if ((lspLabelInfoList != null) && (lspLabelInfoList.size() > 0)) {
                for (int i = 0; i < lspLabelInfoList.size(); ++i) {
                    LspLocalLabelInfo lspLocalLabelInfo =
-                           (DefaultLspLocalLabelInfo) lspLabelInfoList.get(i);
+                           lspLabelInfoList.get(i);
                    LspLocalLabelInfo.Builder lspLocalLabelInfoBuilder = null;
                    if (dstDeviceId.equals(lspLocalLabelInfo.deviceId())) {
                        lspLocalLabelInfoBuilder = DefaultLspLocalLabelInfo.builder(lspLocalLabelInfo);
@@ -264,7 +278,7 @@
            List<LspLocalLabelInfo> lspLocalLabelInfoList = pceccTunnelInfo.lspLocalLabelInfoList();
            if ((lspLocalLabelInfoList != null) && (lspLocalLabelInfoList.size() > 0)) {
                for (Iterator<LspLocalLabelInfo> iterator = lspLocalLabelInfoList.iterator(); iterator.hasNext();) {
-                   LspLocalLabelInfo lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+                   LspLocalLabelInfo lspLocalLabelInfo = iterator.next();
                    DeviceId deviceId = lspLocalLabelInfo.deviceId();
                    LabelResourceId inLabelId = lspLocalLabelInfo.inLabelId();
                    LabelResourceId outLabelId = lspLocalLabelInfo.outLabelId();
@@ -278,15 +292,13 @@
 
                    // Push into device
                    if ((inLabelId != null) && (inPort != null)) {
-                       //TODO: uncomment below lines once installLocalLabelRule() method is ready
-                       //installLocalLabelRule(deviceId, inLabelId, inPort, tunnelId, isLastLabelToPush,
-                       //                      LabelType.IN, Objective.Operation.REMOVE);
+                       installLocalLabelRule(deviceId, inLabelId, inPort, tunnel.tunnelId(), isLastLabelToPush,
+                                             Long.valueOf(LabelType.IN_LABEL.value), Objective.Operation.REMOVE);
                    }
 
                    if ((outLabelId != null) && (outPort != null)) {
-                       //TODO: uncomment below lines once installLocalLabelRule() method is ready
-                       //installLocalLabelRule(deviceId, outLabelId, outPort, tunnelId, isLastLabelToPush,
-                       //                      LabelType.OUT, Objective.Operation.REMOVE);
+                       installLocalLabelRule(deviceId, outLabelId, outPort, tunnel.tunnelId(), isLastLabelToPush,
+                                             Long.valueOf(LabelType.OUT_LABEL.value), Objective.Operation.REMOVE);
                    }
 
                    // List is stored from egress to ingress. So, using IN label id to release.
@@ -315,4 +327,35 @@
            log.error("Unable to find PCECC tunnel info in store for a tunnel {}.", tunnel.toString());
        }
    }
+
+    // Install a rule for pushing local labels to the device which is specific to path.
+    private void installLocalLabelRule(DeviceId deviceId, LabelResourceId labelId,
+                                       PortNumber portNum, TunnelId tunnelId,
+                                       Boolean isBos, Long labelType,
+                                       Objective.Operation type) {
+        checkNotNull(flowObjectiveService);
+        checkNotNull(appId);
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+        selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+        selectorBuilder.matchInPort(portNum);
+        selectorBuilder.matchTunnelId(Long.parseLong(tunnelId.id()));
+        selectorBuilder.matchMplsBos(isBos);
+        selectorBuilder.matchMetadata(labelType);
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+        ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+                .withSelector(selectorBuilder.build())
+                .withTreatment(treatment)
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .fromApp(appId)
+                .makePermanent();
+
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(deviceId, forwardingObjective.add());
+        } else {
+            flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+        }
+    }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index 7ea9934..904371d 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -16,11 +16,15 @@
 package org.onosproject.pce.pceservice;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -29,22 +33,53 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.util.Bandwidth;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
 import org.onosproject.core.IdGenerator;
+import org.onosproject.incubator.net.tunnel.DefaultTunnel;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.LabelStack;
 import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelEvent;
 import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelListener;
+import org.onosproject.incubator.net.tunnel.TunnelName;
 import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultAnnotations.Builder;
+import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
 import org.onosproject.net.Path;
-import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint.CapabilityType;
+import org.onosproject.pce.pceservice.constraint.CostConstraint;
+import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceQueryService;
 import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.TopologyEdge;
 import org.onosproject.pce.pceservice.api.PceService;
-import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
+import org.onosproject.pce.pcestore.PcePathInfo;
+import org.onosproject.pce.pcestore.PceccTunnelInfo;
+import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.DistributedSet;
 import org.onosproject.store.service.Serializer;
@@ -53,6 +88,29 @@
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.ESTABLISHED;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
+import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
+import static org.onosproject.pce.pceservice.LspType.SR_WITHOUT_SIGNALLING;
+import static org.onosproject.pce.pceservice.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
+
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.BANDWIDTH;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LSP_SIG_TYPE;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCE_INIT;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCC_TUNNEL_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.DELEGATE;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.COST_TYPE;
+
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
 
 /**
  * Implementation of PCE service.
@@ -63,8 +121,17 @@
     private static final Logger log = LoggerFactory.getLogger(PceManager.class);
 
     public static final String PCE_SERVICE_APP = "org.onosproject.pce";
-
     private static final String LOCAL_LSP_ID_GEN_TOPIC = "pcep-local-lsp-id";
+    private static final int PREFIX_LENGTH = 32;
+
+    private static final String TUNNEL_CONSUMER_ID_GEN_TOPIC = "pcep-tunnel-consumer-id";
+    private IdGenerator tunnelConsumerIdGen;
+
+    private static final String LSRID = "lsrId";
+    private static final String TRUE = "true";
+    private static final String FALSE = "false";
+    private static final String END_OF_SYNC_IP_PREFIX = "0.0.0.0/32";
+
     private IdGenerator localLspIdIdGen;
     protected DistributedSet<Short> localLspIdFreeList;
 
@@ -72,22 +139,45 @@
     protected CoreService coreService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ResourceService resourceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ResourceQueryService resourceQueryService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PathService pathService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PceStore pceStore;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected TunnelService tunnelService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService storageService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected PathService pathService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ResourceService resourceService;
+    protected PacketService packetService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LabelResourceAdminService labelRsrcAdminService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LabelResourceService labelRsrcService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowObjectiveService flowObjectiveService;
+
+    private TunnelListener listener = new InnerTunnelListener();
+    private BasicPceccHandler crHandler;
+    private PceccSrTeBeHandler srTeHandler;
     private ApplicationId appId;
 
+    private final PcepPacketProcessor processor = new PcepPacketProcessor();
+
     /**
      * Creates new instance of PceManager.
      */
@@ -97,18 +187,30 @@
     @Activate
     protected void activate() {
         appId = coreService.registerApplication(PCE_SERVICE_APP);
-        log.info("Started");
+        crHandler = BasicPceccHandler.getInstance();
+        crHandler.initialize(labelRsrcService, flowObjectiveService, appId, pceStore);
 
+        srTeHandler = PceccSrTeBeHandler.getInstance();
+        srTeHandler.initialize(labelRsrcAdminService, labelRsrcService, flowObjectiveService, appId, pceStore);
+
+        tunnelService.addListener(listener);
+
+        tunnelConsumerIdGen = coreService.getIdGenerator(TUNNEL_CONSUMER_ID_GEN_TOPIC);
         localLspIdIdGen = coreService.getIdGenerator(LOCAL_LSP_ID_GEN_TOPIC);
         localLspIdFreeList = storageService.<Short>setBuilder()
                 .withName("pcepLocalLspIdDeletedList")
                 .withSerializer(Serializer.using(KryoNamespaces.API))
                 .build()
                 .asDistributedSet();
+
+        packetService.addProcessor(processor, PacketProcessor.director(4));
+        log.info("Started");
     }
 
     @Deactivate
     protected void deactivate() {
+        tunnelService.removeListener(listener);
+        packetService.removeProcessor(processor);
         log.info("Stopped");
     }
 
@@ -133,13 +235,13 @@
      */
     protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
         if (pathService == null) {
-            return null;
+            return ImmutableSet.of();
         }
         Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
         if (!paths.isEmpty()) {
             return paths;
         }
-        return null;
+        return ImmutableSet.of();
     }
 
     //[TODO:] handle requests in queue
@@ -149,22 +251,264 @@
         checkNotNull(src);
         checkNotNull(dst);
         checkNotNull(tunnelName);
-        checkNotNull(constraints);
         checkNotNull(lspType);
 
-        // TODO: compute and setup path.
-        //TODO: gets the path based on constraints and creates a tunnel in network via tunnel manager
-        return computePath(src, dst, constraints) != null ? true : false;
-    }
+        // Convert from DeviceId to TunnelEndPoint
+        Device srcDevice = deviceService.getDevice(src);
+        Device dstDevice = deviceService.getDevice(dst);
 
+        if (srcDevice == null || dstDevice == null) {
+            // Device is not known.
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            return false;
+        }
+
+        // In future projections instead of annotations will be used to fetch LSR ID.
+        String srcLsrId = srcDevice.annotations().value(LSRID);
+        String dstLsrId = dstDevice.annotations().value(LSRID);
+
+        if (srcLsrId == null || dstLsrId == null) {
+            // LSR id is not known.
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            return false;
+        }
+
+        TunnelEndPoint srcEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(srcLsrId));
+        TunnelEndPoint dstEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dstLsrId));
+
+        double bwConstraintValue = 0;
+        CostConstraint costConstraint = null;
+        if (constraints != null) {
+            constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
+            Iterator<Constraint> iterator = constraints.iterator();
+
+            while (iterator.hasNext()) {
+                Constraint constraint = iterator.next();
+                if (constraint instanceof BandwidthConstraint) {
+                    bwConstraintValue = ((BandwidthConstraint) constraint).bandwidth().bps();
+                } else if (constraint instanceof CostConstraint) {
+                    costConstraint = (CostConstraint) constraint;
+                }
+            }
+
+            /*
+             * Add cost at the end of the list of constraints. The path computation algorithm also computes cumulative
+             * cost. The function which checks the limiting/capability constraints also returns per link cost. This
+             * function can either return the result of limiting/capability constraint validation or the value of link
+             * cost, depending upon what is the last constraint in the loop.
+             */
+            if (costConstraint != null) {
+                constraints.remove(costConstraint);
+                constraints.add(costConstraint);
+            }
+        } else {
+            constraints = new LinkedList<>();
+            constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
+        }
+
+        Set<Path> computedPathSet = computePath(src, dst, constraints);
+
+        // NO-PATH
+        if (computedPathSet.isEmpty()) {
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            return false;
+        }
+
+        Builder annotationBuilder = DefaultAnnotations.builder();
+        if (bwConstraintValue != 0) {
+            annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
+        }
+        if (costConstraint != null) {
+            annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
+        }
+        annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
+        annotationBuilder.set(PCE_INIT, TRUE);
+        annotationBuilder.set(DELEGATE, TRUE);
+
+        Path computedPath = computedPathSet.iterator().next();
+        LabelStack labelStack = null;
+
+        if (lspType == SR_WITHOUT_SIGNALLING) {
+            labelStack = srTeHandler.computeLabelStack(computedPath);
+            // Failed to form a label stack.
+            if (labelStack == null) {
+                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+                return false;
+            }
+        }
+
+        if (lspType != WITH_SIGNALLING) {
+            /*
+             * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
+             * PCE for non-RSVP signalled LSPs.
+             */
+            annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
+        }
+
+        // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
+        Tunnel tunnel = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
+                                          TunnelName.tunnelName(tunnelName), computedPath,
+                                          labelStack, annotationBuilder.build());
+
+        // Allocate bandwidth.
+        TunnelConsumerId consumerId = null;
+        if (bwConstraintValue != 0) {
+            consumerId = reserveBandwidth(computedPath, bwConstraintValue, null);
+            if (consumerId == null) {
+                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+                return false;
+            }
+        }
+
+        TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
+        if (tunnelId == null) {
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            if (consumerId != null) {
+                resourceService.release(consumerId);
+            }
+            return false;
+        }
+
+        if (consumerId != null) {
+            // Store tunnel consumer id in LSP-Label store.
+            PceccTunnelInfo pceccTunnelInfo = new PceccTunnelInfo(null, consumerId);
+            pceStore.addTunnelInfo(tunnelId, pceccTunnelInfo);
+        }
+        return true;
+    }
 
     @Override
     public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
         checkNotNull(tunnelId);
-        checkNotNull(constraints);
+        Set<Path> computedPathSet = null;
+        Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
 
-        // TODO: compute and update path.
+        if (tunnel == null) {
+            return false;
+        }
 
+        if (tunnel.type() != MPLS || FALSE.equalsIgnoreCase(tunnel.annotations().value(DELEGATE))) {
+            // Only delegated LSPs can be updated.
+            return false;
+        }
+
+        List<Link> links = tunnel.path().links();
+        String lspSigType = tunnel.annotations().value(LSP_SIG_TYPE);
+        double bwConstraintValue = 0;
+        SharedBandwidthConstraint shBwConstraint = null;
+        BandwidthConstraint bwConstraint = null;
+        CostConstraint costConstraint = null;
+
+        if (constraints != null) {
+            // Call path computation in shared bandwidth mode.
+            Iterator<Constraint> iterator = constraints.iterator();
+            while (iterator.hasNext()) {
+                Constraint constraint = iterator.next();
+                if (constraint instanceof BandwidthConstraint) {
+                    bwConstraint = (BandwidthConstraint) constraint;
+                    bwConstraintValue = bwConstraint.bandwidth().bps();
+                } else if (constraint instanceof CostConstraint) {
+                    costConstraint = (CostConstraint) constraint;
+                }
+            }
+
+            // Remove and keep the cost constraint at the end of the list of constraints.
+            if (costConstraint != null) {
+                constraints.remove(costConstraint);
+            }
+
+            Bandwidth existingBwValue = null;
+            String existingBwAnnotation = tunnel.annotations().value(BANDWIDTH);
+            if (existingBwAnnotation != null) {
+                existingBwValue = Bandwidth.bps(Double.parseDouble(existingBwAnnotation));
+
+                /*
+                 * The computation is a shared bandwidth constraint based, so need to remove bandwidth constraint which
+                 * has been utilized to create shared bandwidth constraint.
+                 */
+                if (bwConstraint != null) {
+                    constraints.remove(bwConstraint);
+                }
+            }
+
+            if (existingBwValue != null) {
+                shBwConstraint = new SharedBandwidthConstraint(links, existingBwValue, bwConstraint.bandwidth());
+                constraints.add(shBwConstraint);
+            }
+        } else {
+            constraints = new LinkedList<>();
+        }
+
+        constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspSigType)));
+        if (costConstraint != null) {
+            constraints.add(costConstraint);
+        }
+
+        computedPathSet = computePath(links.get(0).src().deviceId(), links.get(links.size() - 1).dst().deviceId(),
+                                      constraints);
+
+        // NO-PATH
+        if (computedPathSet.isEmpty()) {
+            return false;
+        }
+
+        Builder annotationBuilder = DefaultAnnotations.builder();
+        annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
+        annotationBuilder.set(LSP_SIG_TYPE, lspSigType);
+        annotationBuilder.set(PCE_INIT, TRUE);
+        annotationBuilder.set(DELEGATE, TRUE);
+        annotationBuilder.set(PLSP_ID, tunnel.annotations().value(PLSP_ID));
+        annotationBuilder.set(PCC_TUNNEL_ID, tunnel.annotations().value(PCC_TUNNEL_ID));
+
+        Path computedPath = computedPathSet.iterator().next();
+        LabelStack labelStack = null;
+        TunnelConsumerId consumerId = null;
+        LspType lspType = LspType.valueOf(lspSigType);
+        long localLspId = 0;
+        if (lspType != WITH_SIGNALLING) {
+            /*
+             * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
+             * PCE for non-RSVP signalled LSPs.
+             */
+            localLspId = getNextLocalLspId();
+            annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(localLspId));
+
+            if (lspType == SR_WITHOUT_SIGNALLING) {
+                labelStack = srTeHandler.computeLabelStack(computedPath);
+                // Failed to form a label stack.
+                if (labelStack == null) {
+                    return false;
+                }
+            }
+        }
+
+        Tunnel updatedTunnel = new DefaultTunnel(null, tunnel.src(), tunnel.dst(), MPLS, INIT, null, null,
+                                                 tunnel.tunnelName(), computedPath,
+                                                 labelStack, annotationBuilder.build());
+
+        // Allocate shared bandwidth.
+        if (bwConstraintValue != 0) {
+            consumerId = reserveBandwidth(computedPath, bwConstraintValue, shBwConstraint);
+            if (consumerId == null) {
+                return false;
+            }
+        }
+
+        TunnelId updatedTunnelId = tunnelService.setupTunnel(appId, links.get(0).src().deviceId(), updatedTunnel,
+                                                             computedPath);
+
+        if (updatedTunnelId == null) {
+            if (consumerId != null) {
+                resourceService.release(consumerId);
+            }
+            return false;
+        }
+
+        if (consumerId != null) {
+            // Store tunnel consumer id in LSP-Label store.
+            PceccTunnelInfo pceccTunnelInfo = new PceccTunnelInfo(null, consumerId);
+            pceStore.addTunnelInfo(updatedTunnelId, pceccTunnelInfo);
+        }
         return true;
     }
 
@@ -249,4 +593,281 @@
             return cost;
         }
     }
+
+
+    // Allocates the bandwidth locally for PCECC tunnels.
+    private TunnelConsumerId reserveBandwidth(Path computedPath, double bandwidthConstraint,
+                                  SharedBandwidthConstraint shBwConstraint) {
+        checkNotNull(computedPath);
+        checkNotNull(bandwidthConstraint);
+        Resource resource = null;
+        double bwToAllocate = 0;
+
+        TunnelConsumerId consumer = TunnelConsumerId.valueOf(tunnelConsumerIdGen.getNewId());
+
+        /**
+         * Shared bandwidth sub-case : Lesser bandwidth required than original -
+         * No reservation required.
+         */
+        Double additionalBwValue = null;
+        if (shBwConstraint != null) {
+            additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
+                : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
+        }
+
+        Optional<ResourceAllocation> resAlloc = null;
+        for (Link link : computedPath.links()) {
+            bwToAllocate = 0;
+            if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
+                if (additionalBwValue != null) {
+                    bwToAllocate = bandwidthConstraint - additionalBwValue;
+                }
+            } else {
+                bwToAllocate = bandwidthConstraint;
+            }
+
+            /**
+             *  In shared bandwidth cases, where new BW is lesser than old BW, it
+             *  is not required to allocate anything.
+             */
+            if (bwToAllocate != 0) {
+                resource = Resources.continuous(link.src().deviceId(), link.src().port(), Bandwidth.class)
+                        .resource(bwToAllocate);
+                resAlloc = resourceService.allocate(consumer, resource);
+
+                // If allocation for any link fails, then release the partially allocated bandwidth.
+                if (!resAlloc.isPresent()) {
+                    resourceService.release(consumer);
+                    return null;
+                }
+            }
+        }
+
+        /*
+         * Note: Storing of tunnel consumer id is done by caller of bandwidth reservation function. So deleting tunnel
+         * consumer id should be done by caller of bandwidth releasing function. This will prevent ambiguities related
+         * to who is supposed to store/delete.
+         */
+        return consumer;
+    }
+
+    /*
+     * Deallocates the bandwidth which is reserved locally for PCECC tunnels.
+     */
+    private void releaseBandwidth(Tunnel tunnel) {
+        // Between same source and destination, search the tunnel with same symbolic path name.
+        Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
+        Tunnel newTunnel = null;
+        for (Tunnel tunnelObj : tunnelQueryResult) {
+            if (tunnel.tunnelName().value().equals(tunnelObj.tunnelName().value())) {
+                newTunnel = tunnelObj;
+                break;
+            }
+        }
+
+        // Even if one link is shared, the bandwidth release should happen based on shared mechanism.
+        boolean isLinkShared = false;
+        if (newTunnel != null) {
+            for (Link link : tunnel.path().links()) {
+                if (newTunnel.path().links().contains(link)) {
+                    isLinkShared = true;
+                    break;
+                }
+            }
+        }
+
+        if (isLinkShared) {
+            releaseSharedBandwidth(newTunnel, tunnel);
+            return;
+        }
+
+        resourceService.release(pceStore.getTunnelInfo(tunnel.tunnelId()).tunnelConsumerId());
+        return;
+
+        /*
+         * Note: Storing of tunnel consumer id is done by caller of bandwidth reservation function. So deleting tunnel
+         * consumer id should be done by caller of bandwidth releasing function. This will prevent ambiguities related
+         * to who is supposed to store/delete.
+         */
+    }
+
+    /**
+     *  Re-allocates the bandwidth for the tunnel for which the bandwidth was
+     *  allocated in shared mode initially.
+     */
+    private synchronized void releaseSharedBandwidth(Tunnel newTunnel, Tunnel oldTunnel) {
+        // 1. Release old tunnel's bandwidth.
+        resourceService.release(pceStore.getTunnelInfo(oldTunnel.tunnelId()).tunnelConsumerId());
+
+        // 2. Release new tunnel's bandwidth
+        ResourceConsumer consumer = pceStore.getTunnelInfo(newTunnel.tunnelId()).tunnelConsumerId();
+        resourceService.release(consumer);
+
+        // 3. Allocate new tunnel's complete bandwidth.
+        double bandwidth = Double.parseDouble(newTunnel.annotations().value(BANDWIDTH));
+        Resource resource;
+
+        for (Link link : newTunnel.path().links()) {
+            resource = Resources.continuous(link.src().deviceId(), link.src().port(), Bandwidth.class)
+                    .resource(bandwidth);
+            resourceService.allocate(consumer, resource); // Reusing new tunnel's TunnelConsumerId intentionally.
+        }
+    }
+
+    // Listens on tunnel events.
+    private class InnerTunnelListener implements TunnelListener {
+        @Override
+        public void event(TunnelEvent event) {
+            // Event gets generated with old tunnel object.
+            Tunnel tunnel = event.subject();
+            if (tunnel.type() != MPLS) {
+                return;
+            }
+
+            LspType lspType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
+            String tunnelBandwidth = tunnel.annotations().value(BANDWIDTH);
+            double bwConstraintValue = 0;
+            if (tunnelBandwidth != null) {
+                bwConstraintValue = Double.parseDouble(tunnelBandwidth);
+            }
+
+            switch (event.type()) {
+            case TUNNEL_ADDED:
+                // Allocate bandwidth for non-initiated, delegated LSPs with non-zero bandwidth (learned LSPs).
+                String pceInit = tunnel.annotations().value(PCE_INIT);
+                if (FALSE.equalsIgnoreCase(pceInit)
+                        && bwConstraintValue != 0) {
+                    reserveBandwidth(tunnel.path(), bwConstraintValue, null);
+                }
+                break;
+
+            case TUNNEL_UPDATED:
+                // Allocate/send labels for basic PCECC tunnels.
+                if ((tunnel.state() == ESTABLISHED) && (lspType == WITHOUT_SIGNALLING_AND_WITHOUT_SR)) {
+                    crHandler.allocateLabel(tunnel);
+                }
+
+                if (tunnel.state() == UNSTABLE) {
+                    /*
+                     * During LSP DB sync if PCC doesn't report LSP which was PCE initiated, it's state is turned into
+                     * unstable so that it can be setup again. Add into failed path store so that it can be recomputed
+                     * and setup while global reoptimization.
+                     */
+
+                    List<Constraint> constraints = new LinkedList<>();
+                    String bandwidth = tunnel.annotations().value(BANDWIDTH);
+                    if (bandwidth != null) {
+                        constraints.add(new BandwidthConstraint(Bandwidth
+                                .bps(Double.parseDouble(bandwidth))));
+                    }
+
+                    String costType = tunnel.annotations().value(COST_TYPE);
+                    if (costType != null) {
+                        CostConstraint costConstraint = new CostConstraint(CostConstraint.Type.valueOf(costType));
+                        constraints.add(costConstraint);
+                    }
+
+                    constraints.add(CapabilityConstraint
+                            .of(CapabilityType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
+
+                    List<Link> links = tunnel.path().links();
+                    pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
+                                                                  links.get(links.size() - 1).dst().deviceId(),
+                                                                  tunnel.tunnelName().value(), constraints, lspType));
+                }
+                break;
+
+            case TUNNEL_REMOVED:
+                if (lspType != WITH_SIGNALLING) {
+                    localLspIdFreeList.add(Short.valueOf(tunnel.annotations().value(LOCAL_LSP_ID)));
+                }
+
+                // If not zero bandwidth, and delegated (initiated LSPs will also be delegated).
+                if (bwConstraintValue != 0) {
+                    releaseBandwidth(event.subject());
+
+                    // Release basic PCECC labels.
+                    if (lspType == WITHOUT_SIGNALLING_AND_WITHOUT_SR) {
+                        // Delete stored tunnel consumer id from PCE store (while still retaining label list.)
+                        PceccTunnelInfo pceccTunnelInfo = pceStore.getTunnelInfo(tunnel.tunnelId());
+                        pceccTunnelInfo.tunnelConsumerId(null);
+                        crHandler.releaseLabel(tunnel);
+                    } else {
+                        pceStore.removeTunnelInfo(tunnel.tunnelId());
+                    }
+                }
+                break;
+
+            default:
+                break;
+
+            }
+            return;
+        }
+    }
+
+    private boolean syncLabelDb(DeviceId deviceId) {
+        checkNotNull(deviceId);
+        Map<DeviceId, LabelResourceId> globalNodeLabelMap = pceStore.getGlobalNodeLabels();
+
+        for (Entry<DeviceId, LabelResourceId> entry : globalNodeLabelMap.entrySet()) {
+
+            // Convert from DeviceId to TunnelEndPoint
+            Device srcDevice = deviceService.getDevice(entry.getKey());
+
+            /*
+             * If there is a slight difference in timing such that if device subsystem has removed the device but PCE
+             * store still has it, just ignore such devices.
+             */
+            if (srcDevice == null) {
+                continue;
+            }
+
+            String srcLsrId = srcDevice.annotations().value(LSRID);
+            if (srcLsrId == null) {
+                continue;
+            }
+
+            srTeHandler.advertiseNodeLabelRule(deviceId,
+                                               entry.getValue(),
+                                               IpPrefix.valueOf(IpAddress.valueOf(srcLsrId), PREFIX_LENGTH),
+                                               Objective.Operation.ADD, false);
+        }
+
+        Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
+        for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
+            if (entry.getKey().src().deviceId().equals(deviceId)) {
+                srTeHandler.installAdjLabelRule(deviceId,
+                                                entry.getValue(),
+                                                entry.getKey().src().port(),
+                                                entry.getKey().dst().port(),
+                                                Objective.Operation.ADD);
+            }
+        }
+
+        srTeHandler.advertiseNodeLabelRule(deviceId,
+                                           LabelResourceId.labelResourceId(0),
+                                           IpPrefix.valueOf(END_OF_SYNC_IP_PREFIX),
+                                           Objective.Operation.ADD, true);
+
+        return true;
+    }
+
+    // Process the packet received.
+    private class PcepPacketProcessor implements PacketProcessor {
+        // Process the packet received and in our case initiates the label DB sync.
+        @Override
+        public void process(PacketContext context) {
+            // Stop processing if the packet has been handled, since we
+            // can't do any more to it.
+
+            if (context.isHandled()) {
+                return;
+            }
+
+            InboundPacket pkt = context.inPacket();
+            syncLabelDb(pkt.receivedFrom().deviceId());
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
index 2a10dcf..51fd6dc 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceccSrTeBeHandler.java
@@ -25,6 +25,11 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
 import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
 import org.onosproject.incubator.net.resource.label.LabelResource;
 import org.onosproject.incubator.net.resource.label.LabelResourceId;
@@ -36,7 +41,15 @@
 import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.net.Link;
 import org.onosproject.net.Path;
-
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,7 +80,9 @@
     private static PceccSrTeBeHandler srTeHandlerInstance = null;
     private LabelResourceAdminService labelRsrcAdminService;
     private LabelResourceService labelRsrcService;
+    private FlowObjectiveService flowObjectiveService;
     private PceStore pceStore;
+    private ApplicationId appId;
 
     /**
      * Initializes default values.
@@ -95,10 +110,14 @@
      * @param pceStore PCE label store
      */
     public void initialize(LabelResourceAdminService labelRsrcAdminService,
-                           LabelResourceService labelRsrcService, PceStore pceStore) {
+                           LabelResourceService labelRsrcService,
+                           FlowObjectiveService flowObjectiveService,
+                           ApplicationId appId, PceStore pceStore) {
         this.labelRsrcAdminService = labelRsrcAdminService;
         this.labelRsrcService = labelRsrcService;
+        this.flowObjectiveService = flowObjectiveService;
         this.pceStore = pceStore;
+        this.appId = appId;
     }
 
     /**
@@ -152,15 +171,15 @@
         }
 
         pceStore.addGlobalNodeLabel(specificDeviceId, specificLabelId);
-        //TODO: uncomment below line once advertiseNodeLabelRule() is ready
         // Push its label information into specificDeviceId
-        //advertiseNodeLabelRule(specificDeviceId, specificLabelId,
-        //                       IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
+        advertiseNodeLabelRule(specificDeviceId, specificLabelId,
+                               IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
+                               Objective.Operation.ADD, false);
 
         // Configure (node-label, lsr-id) mapping of each devices in list to specific device and vice versa.
-        for (Map.Entry element:deviceIdLsrIdMap.entrySet()) {
-           DeviceId otherDevId = (DeviceId) element.getKey();
-           String otherLsrId = (String) element.getValue();
+        for (Map.Entry<DeviceId, String> element:deviceIdLsrIdMap.entrySet()) {
+           DeviceId otherDevId = element.getKey();
+           String otherLsrId = element.getValue();
            if (otherLsrId == null) {
                log.error("The lsr-id of device id {} is null.", otherDevId.toString());
                releaseNodeLabel(specificDeviceId, specificLsrId, deviceIdLsrIdMap);
@@ -176,12 +195,11 @@
            }
 
            // Push to device
-           // TODO: uncomment below line once advertiseNodeLabelRule() is ready
            // Push label information of specificDeviceId to otherDevId in list and vice versa.
-           //advertiseNodeLabelRule(otherDevId, specificLabelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
-           //                       PREFIX_LENGTH), Objective.Operation.ADD);
-           //advertiseNodeLabelRule(specificDeviceId, otherLabelId, IpPrefix.valueOf(IpAddress.valueOf(otherLsrId),
-           //                       PREFIX_LENGTH), Objective.Operation.ADD);
+           advertiseNodeLabelRule(otherDevId, specificLabelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
+                                  PREFIX_LENGTH), Objective.Operation.ADD, false);
+           advertiseNodeLabelRule(specificDeviceId, otherLabelId, IpPrefix.valueOf(IpAddress.valueOf(otherLsrId),
+                                  PREFIX_LENGTH), Objective.Operation.ADD, false);
         }
 
         return true;
@@ -214,15 +232,14 @@
         }
 
         // Go through all devices in the map and remove label entry
-        for (Map.Entry element:deviceIdLsrIdMap.entrySet()) {
-           DeviceId otherDevId = (DeviceId) element.getKey();
+        for (Map.Entry<DeviceId, String> element:deviceIdLsrIdMap.entrySet()) {
+           DeviceId otherDevId = element.getKey();
 
            // Remove this specific device label information from all other nodes except
            // this specific node where connection already lost.
            if (!specificDeviceId.equals(otherDevId)) {
-              //TODO: uncomment below lines once advertiseNodeLabelRule() is ready
-              //advertiseNodeLabelRule(otherDevId, labelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
-              //                       PREFIX_LENGTH), Objective.Operation.REMOVE);
+              advertiseNodeLabelRule(otherDevId, labelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
+                                     PREFIX_LENGTH), Objective.Operation.REMOVE, false);
            }
         }
 
@@ -278,8 +295,7 @@
                   link.toString());
 
         // Push adjacency label to device
-        //TODO: uncomment below line once installAdjLabelRule() method is ready
-        //installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.ADD);
+        installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.ADD);
 
         // Save in store
         pceStore.addAdjLabel(link, labelId);
@@ -309,8 +325,7 @@
        DeviceId srcDeviceId = link.src().deviceId();
 
        // Release adjacency label from device
-       //TODO: uncomment below line once installAdjLabelRule() method is ready
-       //installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.REMOVE);
+       installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.REMOVE);
 
        // Release link label from label manager
        Multimap<DeviceId, LabelResource> release = ArrayListMultimap.create();
@@ -350,7 +365,7 @@
             LabelResourceId adjLabelId = null;
             DeviceId deviceId = null;
             for (Iterator<Link> iterator = linkList.iterator(); iterator.hasNext();) {
-                link = (Link) iterator.next();
+                link = iterator.next();
                 // Add source device label now
                 deviceId = link.src().deviceId();
                 nodeLabelId = pceStore.getGlobalNodeLabel(deviceId);
@@ -386,4 +401,109 @@
         }
         return new DefaultLabelStack(labelStack);
     }
+
+    /**
+     * Install a rule for pushing unique global labels to the device.
+     * @param deviceId device to which flow should be pushed
+     * @param labelId label for the device
+     * @param type type of operation
+     */
+    private void installNodeLabelRule(DeviceId deviceId, LabelResourceId labelId, Objective.Operation type) {
+        checkNotNull(flowObjectiveService);
+        checkNotNull(appId);
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+        selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .build();
+
+        ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+                .withSelector(selectorBuilder.build())
+                .withTreatment(treatment)
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .fromApp(appId)
+                .makePermanent();
+
+        if (type.equals(Objective.Operation.ADD)) {
+
+            flowObjectiveService.forward(deviceId, forwardingObjective.add());
+        } else {
+            flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+        }
+    }
+
+    /**
+     * Install a rule for pushing node labels to the device of other nodes.
+     * @param deviceId device to which flow should be pushed
+     * @param labelId label for the device
+     * @param ipPrefix device for which label is pushed
+     * @param type type of operation
+     * @param bBos is this the end of sync push
+     */
+    public void advertiseNodeLabelRule(DeviceId deviceId, LabelResourceId labelId,
+                                        IpPrefix ipPrefix, Objective.Operation type, boolean bBos) {
+        checkNotNull(flowObjectiveService);
+        checkNotNull(appId);
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+        selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+        selectorBuilder.matchIPSrc(ipPrefix);
+
+        if (bBos) {
+            selectorBuilder.matchMplsBos(bBos);
+        }
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .build();
+
+        ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+                .withSelector(selectorBuilder.build())
+                .withTreatment(treatment)
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .fromApp(appId)
+                .makePermanent();
+
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(deviceId, forwardingObjective.add());
+        } else {
+            flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+        }
+    }
+
+    /**
+     *  Install a rule for pushing Adjacency labels to the device.
+     * @param deviceId device to which flow should be pushed
+     * @param labelId label for the adjacency
+     * @param srcPortNum local port of the adjacency
+     * @param dstPortNum remote port of the adjacency
+     * @param type type of operation
+     */
+    public void installAdjLabelRule(DeviceId deviceId, LabelResourceId labelId,
+                                     PortNumber srcPortNum, PortNumber dstPortNum,
+                                     Objective.Operation type) {
+        checkNotNull(flowObjectiveService);
+        checkNotNull(appId);
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+        selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(labelId.id().intValue()));
+        selectorBuilder.matchTcpSrc(TpPort.tpPort((int) srcPortNum.toLong()));
+        selectorBuilder.matchTcpDst(TpPort.tpPort((int) dstPortNum.toLong()));
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .build();
+
+        ForwardingObjective.Builder forwardingObjective = DefaultForwardingObjective.builder()
+                .withSelector(selectorBuilder.build())
+                .withTreatment(treatment)
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .fromApp(appId)
+                .makePermanent();
+
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(deviceId, forwardingObjective.add());
+        } else {
+            flowObjectiveService.forward(deviceId, forwardingObjective.remove());
+        }
+    }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcepAnnotationKeys.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcepAnnotationKeys.java
new file mode 100644
index 0000000..3eada9f
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcepAnnotationKeys.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice;
+
+/**
+ * Collection of keys for annotation for PCEP tunnels.
+ */
+public final class PcepAnnotationKeys {
+
+    /**
+     *  Prohibits instantiation.
+     */
+    private PcepAnnotationKeys() {
+    }
+
+    /**
+     * Annotation key for bandwidth.
+     * The value for this key is interpreted as Mbps.
+     */
+    public static final String BANDWIDTH = "bandwidth";
+
+    /**
+     * Annotation key for the LSP signaling type.
+     */
+    public static final String LSP_SIG_TYPE = "lspSigType";
+
+    /**
+     * Annotation key for the PCC tunnel id.
+     */
+    public static final String PCC_TUNNEL_ID = "PccTunnelId";
+
+    /**
+     * Annotation key for the LSP id assigned per tunnel per session.
+     */
+    public static final String PLSP_ID = "PLspId";
+
+    /**
+     * Annotation key for the LSP id assigned per tunnel.
+     */
+    public static final String LOCAL_LSP_ID = "localLspId";
+
+    /**
+     * Annotation key for the identification of initiated LSP.
+     */
+    public static final String PCE_INIT = "pceInit";
+
+    /**
+     * Annotation key for the cost type.
+     */
+    public static final String COST_TYPE = "costType";
+
+    /**
+     * Annotation key for the Delegation.
+     * Whether LSPs are delegated or not.
+     */
+    public static final String DELEGATE = "delegate";
+}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java
index ddb5fad..e1a65b4 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/TunnelConsumerId.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.pce.pceservice;
 
+import org.onlab.util.Identifier;
 import org.onosproject.net.resource.ResourceConsumer;
 
 import com.google.common.annotations.Beta;
@@ -25,9 +26,7 @@
  * resource allocations.
  */
 @Beta
-public final class TunnelConsumerId implements ResourceConsumer {
-
-    private final long value;
+public final class TunnelConsumerId extends Identifier<Long> implements ResourceConsumer {
 
     /**
      * Creates a tunnel resource consumer identifier from the specified long value.
@@ -43,7 +42,7 @@
      * Initializes object for serializer.
      */
     public TunnelConsumerId() {
-        this.value = 0;
+        super(0L);
     }
 
     /**
@@ -54,43 +53,25 @@
      *            resource consumer id
      */
     public TunnelConsumerId(long value) {
-        this.value = value;
+        super(value);
     }
 
     /**
-     * Returns the tunnel resource consumer id value in long format.
+     * Returns the backing identifier value.
      *
-     * @return value the tunnel resource consumer id's long value
+     * @return value backing identifier value
      */
     public long value() {
-        return value;
-    }
-
-    @Override
-    public int hashCode() {
-        return Long.hashCode(value);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-        if (!(obj instanceof TunnelConsumerId)) {
-            return false;
-        }
-        TunnelConsumerId that = (TunnelConsumerId) obj;
-        return this.value == that.value;
+        return identifier;
     }
 
     @Override
     public String toString() {
-        return "0x" + Long.toHexString(value);
+        return "0x" + Long.toHexString(identifier);
     }
 
     @Override
     public ResourceConsumerId consumerId() {
-        // TODO
-        return null;
+        return ResourceConsumerId.of(this);
     }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java
index 8eb75fa..ae5d9c7 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Open Networking Laboratory
+ * Copyright 2016-present Open Networking Laboratory
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/BasicPceccHandlerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/BasicPceccHandlerTest.java
index a5ea175..8c3de14 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/BasicPceccHandlerTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/BasicPceccHandlerTest.java
@@ -31,6 +31,8 @@
 import org.junit.Test;
 
 import org.onlab.packet.IpAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
@@ -45,11 +47,11 @@
 import org.onosproject.net.DefaultPath;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
 import org.onosproject.net.Path;
 import org.onosproject.pce.pcestore.api.LspLocalLabelInfo;
 import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.pce.pcestore.PceccTunnelInfo;
-import org.onosproject.pce.pcestore.DefaultLspLocalLabelInfo;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.pce.util.LabelResourceAdapter;
 import org.onosproject.pce.util.PceStoreAdapter;
@@ -67,6 +69,9 @@
     private BasicPceccHandler pceccHandler;
     protected LabelResourceService labelRsrcService;
     protected PceStore pceStore;
+    private FlowObjectiveService flowObjectiveService;
+    private CoreService coreService;
+    private ApplicationId appId;
     private TunnelEndPoint src = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(23423));
     private TunnelEndPoint dst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(32421));
     private DefaultGroupId groupId = new DefaultGroupId(92034);
@@ -92,7 +97,10 @@
        pceccHandler = BasicPceccHandler.getInstance();
        labelRsrcService = new LabelResourceAdapter();
        pceStore = new PceStoreAdapter();
-       pceccHandler.initialize(labelRsrcService, pceStore);
+       flowObjectiveService = new PceManagerTest.MockFlowObjService();
+       coreService = new PceManagerTest.MockCoreService();
+       appId = coreService.registerApplication("org.onosproject.pce");
+       pceccHandler.initialize(labelRsrcService, flowObjectiveService, appId, pceStore);
 
        // Cretae tunnel test
        // Link
@@ -190,7 +198,7 @@
        iterator = lspLocalLabelInfoList.iterator();
 
        // Retrieve values and check device5
-       lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+       lspLocalLabelInfo = iterator.next();
        deviceId = lspLocalLabelInfo.deviceId();
        inLabelId = lspLocalLabelInfo.inLabelId();
        outLabelId = lspLocalLabelInfo.outLabelId();
@@ -205,7 +213,7 @@
 
        // Next element check
        // Retrieve values and check device4
-       lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+       lspLocalLabelInfo = iterator.next();
        deviceId = lspLocalLabelInfo.deviceId();
        inLabelId = lspLocalLabelInfo.inLabelId();
        outLabelId = lspLocalLabelInfo.outLabelId();
@@ -220,7 +228,7 @@
 
        // Next element check
        // Retrieve values and check device3
-       lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+       lspLocalLabelInfo = iterator.next();
        deviceId = lspLocalLabelInfo.deviceId();
        inLabelId = lspLocalLabelInfo.inLabelId();
        outLabelId = lspLocalLabelInfo.outLabelId();
@@ -235,7 +243,7 @@
 
        // Next element check
        // Retrieve values and check device2
-       lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+       lspLocalLabelInfo = iterator.next();
        deviceId = lspLocalLabelInfo.deviceId();
        inLabelId = lspLocalLabelInfo.inLabelId();
        outLabelId = lspLocalLabelInfo.outLabelId();
@@ -250,7 +258,7 @@
 
        // Next element check
        // Retrieve values and check device1
-       lspLocalLabelInfo = (DefaultLspLocalLabelInfo) iterator.next();
+       lspLocalLabelInfo = iterator.next();
        deviceId = lspLocalLabelInfo.deviceId();
        inLabelId = lspLocalLabelInfo.inLabelId();
        outLabelId = lspLocalLabelInfo.outLabelId();
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
index 446aea2..c4040ed 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
@@ -96,20 +96,20 @@
     private final MockDeviceService deviceService = new MockDeviceService();
     private PceManager pceManager = new PceManager();
     public static ProviderId providerId = new ProviderId("pce", "foo");
-    private static final String DEVICE1 = "D001";
-    private static final String DEVICE2 = "D002";
-    private static final String DEVICE3 = "D003";
-    private static final String DEVICE4 = "D004";
-    private static final String DEVICE5 = "D005";
+    public static final String DEVICE1 = "D001";
+    public static final String DEVICE2 = "D002";
+    public static final String DEVICE3 = "D003";
+    public static final String DEVICE4 = "D004";
+    public static final String DEVICE5 = "D005";
     public static final String PCEPDEVICE1 = "PD001";
     public static final String PCEPDEVICE2 = "PD002";
     public static final String PCEPDEVICE3 = "PD003";
     public static final String PCEPDEVICE4 = "PD004";
-    private static final TopologyVertex D1 = new DefaultTopologyVertex(DeviceId.deviceId("D001"));
-    private static final TopologyVertex D2 = new DefaultTopologyVertex(DeviceId.deviceId("D002"));
-    private static final TopologyVertex D3 = new DefaultTopologyVertex(DeviceId.deviceId("D003"));
-    private static final TopologyVertex D4 = new DefaultTopologyVertex(DeviceId.deviceId("D004"));
-    private static final TopologyVertex D5 = new DefaultTopologyVertex(DeviceId.deviceId("D005"));
+    public static final TopologyVertex D1 = new DefaultTopologyVertex(DeviceId.deviceId("D001"));
+    public static final TopologyVertex D2 = new DefaultTopologyVertex(DeviceId.deviceId("D002"));
+    public static final TopologyVertex D3 = new DefaultTopologyVertex(DeviceId.deviceId("D003"));
+    public static final TopologyVertex D4 = new DefaultTopologyVertex(DeviceId.deviceId("D004"));
+    public static final TopologyVertex D5 = new DefaultTopologyVertex(DeviceId.deviceId("D005"));
     private static final String ANNOTATION_COST = "cost";
     private static final String ANNOTATION_TE_COST = "teCost";
     private static final String UNKNOWN = "unknown";
@@ -130,7 +130,7 @@
      *
      * @return graph path search algorithm
      */
-    private AbstractGraphPathSearch<TopologyVertex, TopologyEdge> graphSearch() {
+    public static AbstractGraphPathSearch<TopologyVertex, TopologyEdge> graphSearch() {
         return new DijkstraGraphSearch<>();
     }
 
@@ -143,7 +143,7 @@
      * @param port2 destination port
      * @return link
      */
-    private Link addLink(String device, long port, String device2, long port2, boolean setCost, int value) {
+    public static Link addLink(String device, long port, String device2, long port2, boolean setCost, int value) {
         ConnectPoint src = new ConnectPoint(DeviceId.deviceId(device), PortNumber.portNumber(port));
         ConnectPoint dst = new ConnectPoint(DeviceId.deviceId(device2), PortNumber.portNumber(port2));
         Link curLink;
@@ -256,19 +256,37 @@
         }
     }
 
-    private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
+    /**
+     * Returns the path in Path object format.
+     */
+    public static Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
         List<Link> links = path.edges().stream().map(TopologyEdge::link).collect(Collectors.toList());
         return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
     }
 
     /**
-     * Test Resource service for path computation.
+     * Tests Resource service for path computation.
      */
-    private class MockPathResourceService extends ResourceServiceAdapter {
+    public class MockPathResourceService extends ResourceServiceAdapter {
         private final Map<Resource, ResourceConsumer> assignment = new HashMap<>();
         private Map<ResourceId, List<ResourceAllocation>> resourcesAllocations = new HashMap<>();
 
         @Override
+        public Optional<ResourceAllocation> allocate(ResourceConsumer consumer, Resource resources) {
+            List<ResourceAllocation> allocations = allocate(consumer, ImmutableList.of(resources));
+            if (allocations.isEmpty()) {
+                return Optional.empty();
+            }
+
+            assert allocations.size() == 1;
+            ResourceAllocation allocation = allocations.get(0);
+            assert allocation.resource().equals(resources);
+
+            // cast is ensured by the assertions above
+            return Optional.of(allocation);
+        }
+
+        @Override
         public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) {
             for (Resource resource: resources) {
                 if (resource instanceof ContinuousResource) {
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
new file mode 100644
index 0000000..5b0d869
--- /dev/null
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
@@ -0,0 +1,1026 @@
+package org.onosproject.pce.pceservice;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
+import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.TE_COST;
+import static org.onosproject.net.resource.Resources.continuous;
+import static org.onosproject.pce.pceservice.LspType.SR_WITHOUT_SIGNALLING;
+import static org.onosproject.pce.pceservice.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
+import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
+import static org.onosproject.pce.pceservice.PathComputationTest.D1;
+import static org.onosproject.pce.pceservice.PathComputationTest.D2;
+import static org.onosproject.pce.pceservice.PathComputationTest.D3;
+import static org.onosproject.pce.pceservice.PathComputationTest.D4;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
+import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
+import static org.onosproject.incubator.net.tunnel.Tunnel.State.ESTABLISHED;
+
+import java.net.URISyntaxException;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.graph.GraphPathSearch;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.util.Bandwidth;
+import org.onosproject.common.DefaultTopologyGraph;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+import org.onosproject.incubator.net.tunnel.DefaultTunnel;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.Tunnel.State;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelEvent;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelListener;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Device;
+import org.onosproject.net.DefaultAnnotations.Builder;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.packet.DefaultInboundPacket;
+import org.onosproject.net.packet.DefaultPacketContext;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.net.packet.PacketServiceAdapter;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.topology.DefaultTopologyEdge;
+import org.onosproject.net.topology.DefaultTopologyVertex;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.PathServiceAdapter;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyEdge;
+import org.onosproject.net.topology.TopologyGraph;
+import org.onosproject.net.topology.TopologyServiceAdapter;
+import org.onosproject.net.topology.TopologyVertex;
+import org.onosproject.pce.pceservice.PathComputationTest.MockPathResourceService;
+import org.onosproject.pce.pceservice.constraint.CostConstraint;
+import org.onosproject.pce.pcestore.api.PceStore;
+import org.onosproject.pce.util.LabelResourceAdapter;
+import org.onosproject.pce.util.PceStoreAdapter;
+import org.onosproject.pce.util.TunnelServiceAdapter;
+import org.onosproject.pce.util.FlowObjServiceAdapter;
+import org.onosproject.store.service.TestStorageService;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests the functions of PceManager.
+ */
+public class PceManagerTest {
+
+    private PathComputationTest pathCompTest = new PathComputationTest();
+    private MockPathResourceService resourceService = pathCompTest.new MockPathResourceService();
+    private MockTopologyService topologyService = new MockTopologyService();
+    private MockPathService pathService = new MockPathService();
+    private PceManager pceManager = new PceManager();
+    private MockCoreService coreService = new MockCoreService();
+    private MockTunnelServiceAdapter tunnelService = new MockTunnelServiceAdapter();
+    private TestStorageService storageService = new TestStorageService();
+    private PacketService packetService = new MockPacketService();
+    private MockDeviceService deviceService = new MockDeviceService();
+    private MockFlowObjService flowObjectiveService = new MockFlowObjService();
+    private PceStore pceStore = new PceStoreAdapter();
+    private LabelResourceService labelResourceService = new LabelResourceAdapter();
+
+    public static ProviderId providerId = new ProviderId("pce", "foo");
+    private static final String L3 = "L3";
+    private static final String LSRID = "lsrId";
+    private static final String PCECC_CAPABILITY = "pceccCapability";
+    private static final String SR_CAPABILITY = "srCapability";
+    private static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
+
+    private TopologyGraph graph = null;
+    private Device deviceD1, deviceD2, deviceD3, deviceD4;
+    private Device pcepDeviceD1, pcepDeviceD2, pcepDeviceD3, pcepDeviceD4;
+    private Link link1, link2, link3, link4;
+    private static int flowsDownloaded;
+    private TunnelListener tunnelListener;
+
+    @Before
+    public void startUp() {
+        pceManager.pathService = pathService;
+        pceManager.resourceService = resourceService;
+        pceManager.tunnelService = tunnelService;
+        pceManager.coreService = coreService;
+        pceManager.storageService = storageService;
+        pceManager.packetService = packetService;
+        pceManager.deviceService = deviceService;
+        pceManager.labelRsrcService = labelResourceService;
+        pceManager.flowObjectiveService = flowObjectiveService;
+        pceManager.pceStore = pceStore;
+        pceManager.activate();
+    }
+
+    private void build4RouterTopo(boolean setCost, boolean setPceccCap, boolean setSrCap,
+                                 boolean setLabelStackCap, int bandwidth) {
+        Set<TopologyVertex> vertexes = new HashSet<TopologyVertex>();
+        vertexes.add(D1);
+        vertexes.add(D2);
+        vertexes.add(D3);
+        vertexes.add(D4);
+
+        Set<TopologyEdge> edges = new HashSet<TopologyEdge>();
+        link1 = PathComputationTest.addLink(D1.deviceId().toString(), 10, D2.deviceId().toString(), 20, setCost, 50);
+        TopologyEdge edge1 = new DefaultTopologyEdge(D1, D2, link1);
+        edges.add(edge1);
+
+        link2 = PathComputationTest.addLink(D2.deviceId().toString(), 30, D4.deviceId().toString(), 40, setCost, 20);
+        TopologyEdge edge2 = new DefaultTopologyEdge(D2, D4, link2);
+        edges.add(edge2);
+
+        link3 = PathComputationTest.addLink(D1.deviceId().toString(), 80, D3.deviceId().toString(), 70, setCost, 100);
+        TopologyEdge edge3 = new DefaultTopologyEdge(D1, D3, link3);
+        edges.add(edge3);
+
+        link4 = PathComputationTest.addLink(D3.deviceId().toString(), 60, D4.deviceId().toString(), 50, setCost, 80);
+        TopologyEdge edge4 = new DefaultTopologyEdge(D3, D4, link4);
+        edges.add(edge4);
+
+        graph = new DefaultTopologyGraph(vertexes, edges);
+
+        DefaultAnnotations.Builder builderDev1 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev3 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev4 = DefaultAnnotations.builder();
+
+        builderDev1.set(AnnotationKeys.TYPE, L3);
+        builderDev1.set(LSRID, "1.1.1.1");
+
+        builderDev2.set(AnnotationKeys.TYPE, L3);
+        builderDev2.set(LSRID, "2.2.2.2");
+
+        builderDev3.set(AnnotationKeys.TYPE, L3);
+        builderDev3.set(LSRID, "3.3.3.3");
+
+        builderDev4.set(AnnotationKeys.TYPE, L3);
+        builderDev4.set(LSRID, "4.4.4.4");
+
+        if (setSrCap) {
+            builderDev1.set(SR_CAPABILITY, "true");
+            builderDev2.set(SR_CAPABILITY, "true");
+            builderDev3.set(SR_CAPABILITY, "true");
+            builderDev4.set(SR_CAPABILITY, "true");
+        }
+
+        if (setPceccCap) {
+            builderDev1.set(PCECC_CAPABILITY, "true");
+            builderDev2.set(PCECC_CAPABILITY, "true");
+            builderDev3.set(PCECC_CAPABILITY, "true");
+            builderDev4.set(PCECC_CAPABILITY, "true");
+        }
+
+        if (setLabelStackCap) {
+            builderDev1.set(LABEL_STACK_CAPABILITY, "true");
+            builderDev2.set(LABEL_STACK_CAPABILITY, "true");
+            builderDev3.set(LABEL_STACK_CAPABILITY, "true");
+            builderDev4.set(LABEL_STACK_CAPABILITY, "true");
+        }
+
+        deviceD1 = new MockDevice(D1.deviceId(), builderDev1.build());
+        deviceD2 = new MockDevice(D2.deviceId(), builderDev2.build());
+        deviceD3 = new MockDevice(D3.deviceId(), builderDev3.build());
+        deviceD4 = new MockDevice(D4.deviceId(), builderDev4.build());
+
+        deviceService.addDevice(deviceD1);
+        deviceService.addDevice(deviceD2);
+        deviceService.addDevice(deviceD3);
+        deviceService.addDevice(deviceD4);
+
+        pcepDeviceD1 = new MockDevice(DeviceId.deviceId(PathComputationTest.PCEPDEVICE1), builderDev1.build());
+        deviceService.addDevice(pcepDeviceD1);
+
+        pcepDeviceD2 = new MockDevice(DeviceId.deviceId(PathComputationTest.PCEPDEVICE2), builderDev1.build());
+        deviceService.addDevice(pcepDeviceD2);
+
+        pcepDeviceD3 = new MockDevice(DeviceId.deviceId(PathComputationTest.PCEPDEVICE3), builderDev1.build());
+        deviceService.addDevice(pcepDeviceD3);
+
+        pcepDeviceD4 = new MockDevice(DeviceId.deviceId(PathComputationTest.PCEPDEVICE4), builderDev1.build());
+        deviceService.addDevice(pcepDeviceD4);
+
+        if (bandwidth != 0) {
+            List<Resource> resources = new LinkedList<>();
+            resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(bandwidth));
+
+            resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(bandwidth));
+
+            resourceService.allocate(IntentId.valueOf(bandwidth), resources);
+        }
+    }
+
+    /**
+     * Tests path success with (IGP) cost constraint for signalled LSP.
+     */
+    @Test
+    public void setupPathTest1() {
+        build4RouterTopo(true, false, false, false, 0); // IGP cost is set here.
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(true));
+    }
+
+    /**
+     * Tests path failure with (IGP) cost constraint for signalled LSP.
+     */
+    @Test
+    public void setupPathTest2() {
+        build4RouterTopo(false, false, false, false, 0); // TE cost is set here, not IGP.
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path success with TE-cost constraint for signalled LSP.
+     */
+    @Test
+    public void setupPathTest3() {
+        build4RouterTopo(false, false, false, false, 0); // TE cost is set here.
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(true));
+    }
+
+    /**
+     * Tests path failure with TE-cost constraint for signalled LSP.
+     */
+    @Test
+    public void setupPathTest4() {
+        build4RouterTopo(true, false, false, false, 0); // IGP cost is set here, not TE.
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path success with (IGP) cost constraint for non-SR non-signalled LSP.
+     */
+    @Test
+    public void setupPathTest5() {
+        build4RouterTopo(true, true, false, false, 0);
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        assertThat(result, is(true));
+    }
+
+    /**
+     * Tests path success with TE-cost constraint for non-SR non-sgnalled LSP.
+     */
+    @Test
+    public void setupPathTest6() {
+        build4RouterTopo(false, true, false, false, 0);
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        assertThat(result, is(true));
+    }
+
+    /**
+     * Tests path failure with TE-cost constraint for non-SR non-signalled LSP(CR). Label capability not registered.
+     */
+    @Test
+    public void setupPathTest7() {
+        build4RouterTopo(true, false, false, false, 0);
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path failure as bandwidth is requested but is not registered.
+     */
+    @Test
+    public void setupPathTest8() {
+        build4RouterTopo(true, false, false, false, 0);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path failure as bandwidth requested is more than registered.
+     */
+    @Test
+    public void setupPathTest9() {
+        build4RouterTopo(false, false, false, false, 5);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path setup failure(without signalling). Label capability is not present.
+     */
+    @Test
+    public void setupPathTest10() {
+        build4RouterTopo(false, false, false, false, 0);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path setup without failure for LSP with signalling and with bandwidth reservation.
+     */
+    @Test
+    public void setupPathTest11() {
+        build4RouterTopo(false, true, true, true, 15);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        LabelResourceId node1Label = LabelResourceId.labelResourceId(5200);
+        LabelResourceId node2Label = LabelResourceId.labelResourceId(5201);
+
+        pceManager.pceStore.addGlobalNodeLabel(D1.deviceId(), node1Label);
+        pceManager.pceStore.addGlobalNodeLabel(D2.deviceId(), node2Label);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        assertThat(result, is(false));
+    }
+
+    /**
+     * Tests path setup without signalling and with bandwidth reservation.
+     */
+    @Test
+    public void setupPathTest12() {
+        build4RouterTopo(false, true, true, true, 15);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        LabelResourceId node1Label = LabelResourceId.labelResourceId(5200);
+        LabelResourceId node2Label = LabelResourceId.labelResourceId(5201);
+
+        pceManager.pceStore.addGlobalNodeLabel(D1.deviceId(), node1Label);
+        pceManager.pceStore.addGlobalNodeLabel(D2.deviceId(), node2Label);
+
+        LabelResourceId link1Label = LabelResourceId.labelResourceId(5202);
+        pceManager.pceStore.addAdjLabel(link1, link1Label);
+
+        LabelResourceId link2Label = LabelResourceId.labelResourceId(5203);
+        pceManager.pceStore.addAdjLabel(link2, link2Label);
+
+        LabelResourceId link3Label = LabelResourceId.labelResourceId(5204);
+        pceManager.pceStore.addAdjLabel(link3, link3Label);
+
+        LabelResourceId link4Label = LabelResourceId.labelResourceId(5205);
+        pceManager.pceStore.addAdjLabel(link4, link4Label);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        assertThat(result, is(true));
+    }
+
+    /**
+     * Tests path setup without cost/bandwidth constraints.
+     */
+    @Test
+    public void setupPathTest13() {
+        build4RouterTopo(false, false, false, false, 0);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING);
+        assertThat(result, is(true));
+    }
+
+    /**
+     * Tests path update with increase in bandwidth.
+     */
+    @Test
+    public void updatePathTest1() {
+        build4RouterTopo(false, true, true, true, 100);
+
+        // Setup tunnel.
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        constraints.add(bwConstraint);
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        assertThat(result, is(true));
+
+        // Change constraint and update it.
+        constraints = new LinkedList<>();
+        bwConstraint = new BandwidthConstraint(Bandwidth.bps(50.0));
+        constraints.add(bwConstraint);
+        constraints.add(costConstraint);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+
+        Tunnel tunnel = tunnels.iterator().next();
+
+        // Stimulate the effect of LSP ids from protocol msg.
+        tunnelService.updateTunnelWithLspIds(tunnel, "123", "1", State.ACTIVE);
+
+        result = pceManager.updatePath(tunnel.tunnelId(), constraints);
+        assertThat(result, is(true));
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(2));
+    }
+
+    /**
+     * Tests path update with decrease in bandwidth.
+     */
+    @Test
+    public void updatePathTest2() {
+        build4RouterTopo(false, true, true, true, 100);
+
+        // Setup tunnel.
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        constraints.add(bwConstraint);
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        LabelResourceId node1Label = LabelResourceId.labelResourceId(5200);
+        LabelResourceId node2Label = LabelResourceId.labelResourceId(5201);
+
+        pceManager.pceStore.addGlobalNodeLabel(D1.deviceId(), node1Label);
+        pceManager.pceStore.addGlobalNodeLabel(D2.deviceId(), node2Label);
+
+        LabelResourceId link1Label = LabelResourceId.labelResourceId(5202);
+        pceManager.pceStore.addAdjLabel(link1, link1Label);
+
+        LabelResourceId link2Label = LabelResourceId.labelResourceId(5203);
+        pceManager.pceStore.addAdjLabel(link2, link2Label);
+
+        LabelResourceId link3Label = LabelResourceId.labelResourceId(5204);
+        pceManager.pceStore.addAdjLabel(link3, link3Label);
+
+        LabelResourceId link4Label = LabelResourceId.labelResourceId(5205);
+        pceManager.pceStore.addAdjLabel(link4, link4Label);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        assertThat(result, is(true));
+
+        // Change constraint and update it.
+        constraints.remove(bwConstraint);
+        bwConstraint = new BandwidthConstraint(Bandwidth.bps(70.0));
+        constraints.add(bwConstraint);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+
+        for (Tunnel tunnel : tunnels) {
+            result = pceManager.updatePath(tunnel.tunnelId(), constraints);
+            assertThat(result, is(true));
+        }
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(2));
+    }
+
+    /**
+     * Tests path update without cost/bandwidth constraints.
+     */
+    @Test
+    public void updatePathTest3() {
+        build4RouterTopo(false, true, true, true, 100);
+
+        // Setup tunnel.
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING);
+        assertThat(result, is(true));
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+
+        for (Tunnel tunnel : tunnels) {
+            result = pceManager.updatePath(tunnel.tunnelId(), null);
+            assertThat(result, is(true));
+        }
+
+        Iterable<Tunnel> queryTunnelResult = pceManager.queryAllPath();
+        assertThat((int) queryTunnelResult.spliterator().getExactSizeIfKnown(), is(2));
+    }
+
+    /**
+     * Tests path release.
+     */
+    @Test
+    public void releasePathTest1() {
+        build4RouterTopo(false, false, false, false, 5);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+        boolean result;
+        for (Tunnel tunnel : tunnels) {
+            result = pceManager.releasePath(tunnel.tunnelId());
+            assertThat(result, is(true));
+        }
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(0));
+    }
+
+    /**
+     * Tests path release failure.
+     */
+    @Test
+    public void releasePathTest2() {
+        build4RouterTopo(false, false, false, false, 5);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+
+        // Random tunnel id.
+        boolean result = pceManager.releasePath(TunnelId.valueOf("111"));
+        assertThat(result, is(false));
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+    }
+
+    /**
+     * Tests packet in to trigger label DB sync.
+     */
+    @Test
+    public void packetProcessingTest() throws URISyntaxException {
+
+        build4RouterTopo(false, true, true, true, 0); // This also initializes devices etc.
+
+        final int srcHost = 2;
+        final int dstHost = 5;
+
+        LabelResourceId node1Label = LabelResourceId.labelResourceId(5200);
+        LabelResourceId node2Label = LabelResourceId.labelResourceId(5201);
+
+        pceManager.pceStore.addGlobalNodeLabel(D1.deviceId(), node1Label);
+        pceManager.pceStore.addGlobalNodeLabel(D2.deviceId(), node2Label);
+
+        ConnectPoint src = new ConnectPoint(D1.deviceId(), PortNumber.portNumber(srcHost));
+        ConnectPoint dst = new ConnectPoint(D2.deviceId(), PortNumber.portNumber(dstHost));
+
+        Link link1 = DefaultLink.builder().src(src).dst(dst).state(ACTIVE).type(DIRECT)
+                .providerId(new ProviderId("eth", "1")).build();
+
+        LabelResourceId link1Label = LabelResourceId.labelResourceId(5204);
+        pceManager.pceStore.addAdjLabel(link1, link1Label);
+
+        Ethernet eth;
+        IPv4 ipv4;
+
+        ipv4 = new IPv4();
+        eth = new Ethernet();
+        eth.setEtherType(Ethernet.TYPE_IPV4);
+        eth.setPayload(ipv4);
+
+        eth.setSourceMACAddress("00:00:00:10:00:0" + srcHost).setDestinationMACAddress("00:00:00:10:00:0" + dstHost);
+
+        InboundPacket inPkt = new DefaultInboundPacket(new ConnectPoint(D1.deviceId(), PortNumber.portNumber(srcHost)),
+                                                       eth, ByteBuffer.wrap(eth.serialize()));
+
+        pktProcessor.process(new MockPcepPacketContext(inPkt, null));
+        assertThat(flowsDownloaded, is(4));
+    }
+
+    /**
+     * Tests tunnel events added and removed.
+     */
+    @Test
+    public void tunnelEventTest1() {
+        build4RouterTopo(false, true, true, true, 15);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        LabelResourceId node1Label = LabelResourceId.labelResourceId(5200);
+        LabelResourceId node2Label = LabelResourceId.labelResourceId(5201);
+
+        pceManager.pceStore.addGlobalNodeLabel(D1.deviceId(), node1Label);
+        pceManager.pceStore.addGlobalNodeLabel(D2.deviceId(), node2Label);
+
+        LabelResourceId link1Label = LabelResourceId.labelResourceId(5202);
+        pceManager.pceStore.addAdjLabel(link1, link1Label);
+
+        LabelResourceId link2Label = LabelResourceId.labelResourceId(5203);
+        pceManager.pceStore.addAdjLabel(link2, link2Label);
+
+        LabelResourceId link3Label = LabelResourceId.labelResourceId(5204);
+        pceManager.pceStore.addAdjLabel(link3, link3Label);
+
+        LabelResourceId link4Label = LabelResourceId.labelResourceId(5205);
+        pceManager.pceStore.addAdjLabel(link4, link4Label);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING);
+        assertThat(pceStore.getTunnelInfoCount(), is(1));
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+
+        for (Tunnel tunnel : tunnels) {
+            TunnelEvent event = new TunnelEvent(TunnelEvent.Type.TUNNEL_ADDED, tunnel);
+            tunnelListener.event(event);
+
+            pceManager.releasePath(tunnel.tunnelId());
+
+            event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED, tunnel);
+            tunnelListener.event(event);
+        }
+
+        assertThat(pceStore.getTunnelInfoCount(), is(0));
+    }
+
+    /**
+     * Tests label allocation/removal in CR case based on tunnel event.
+     */
+    @Test
+    public void tunnelEventTest2() {
+        build4RouterTopo(false, true, true, true, 15);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        assertThat(pceStore.getTunnelInfoCount(), is(1));
+
+        TunnelEvent event;
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        for (Tunnel tunnel : tunnels) {
+            event = new TunnelEvent(TunnelEvent.Type.TUNNEL_ADDED, tunnel);
+            tunnelListener.event(event);
+
+            // Stimulate the effect of LSP ids from protocol msg.
+            tunnelService.updateTunnelWithLspIds(tunnel, "123", "1", ESTABLISHED);
+        }
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        for (Tunnel tunnel : tunnels) {
+            event = new TunnelEvent(TunnelEvent.Type.TUNNEL_UPDATED, tunnel);
+            tunnelListener.event(event);
+
+            pceManager.releasePath(tunnel.tunnelId());
+
+            event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED, tunnel);
+            tunnelListener.event(event);
+        }
+
+        assertThat(pceStore.getTunnelInfoCount(), is(0));
+    }
+
+    /**
+     * Tests handling UNSTABLE state based on tunnel event.
+     */
+    @Test
+    public void tunnelEventTest3() {
+        build4RouterTopo(false, true, true, true, 15);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+
+        constraints.add(costConstraint);
+        constraints.add(bwConstraint);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        assertThat(pceStore.getTunnelInfoCount(), is(1));
+        assertThat(pceStore.getFailedPathInfoCount(), is(0));
+
+        TunnelEvent event;
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        for (Tunnel tunnel : tunnels) {
+            event = new TunnelEvent(TunnelEvent.Type.TUNNEL_ADDED, tunnel);
+            tunnelListener.event(event);
+
+            // Stimulate the effect of LSP ids from protocol msg.
+            tunnelService.updateTunnelWithLspIds(tunnel, "123", "1", UNSTABLE);
+        }
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        for (Tunnel tunnel : tunnels) {
+            event = new TunnelEvent(TunnelEvent.Type.TUNNEL_UPDATED, tunnel);
+            tunnelListener.event(event);
+        }
+        assertThat(pceStore.getTunnelInfoCount(), is(1));
+        assertThat(pceStore.getFailedPathInfoCount(), is(1));
+    }
+
+    @After
+    public void tearDown() {
+        pceManager.deactivate();
+        pceManager.pathService = null;
+        pceManager.resourceService = null;
+        pceManager.tunnelService = null;
+        pceManager.coreService = null;
+        pceManager.storageService = null;
+        pceManager.packetService = null;
+        pceManager.deviceService = null;
+        pceManager.labelRsrcService = null;
+        pceManager.flowObjectiveService = null;
+        pceManager.pceStore = null;
+        flowsDownloaded = 0;
+    }
+
+    private class MockTopologyService extends TopologyServiceAdapter {
+        @Override
+        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
+            DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
+            DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
+            Set<TopologyVertex> vertices = graph.getVertexes();
+            if (!vertices.contains(srcV) || !vertices.contains(dstV)) {
+                // src or dst not part of the current graph
+                return ImmutableSet.of();
+            }
+
+            GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = PathComputationTest.graphSearch()
+                    .search(graph, srcV, dstV, weight, ALL_PATHS);
+            ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
+            for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
+                builder.add(PathComputationTest.networkPath(path));
+            }
+            return builder.build();
+        }
+    }
+
+    private class MockPathService extends PathServiceAdapter {
+
+        @Override
+        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
+            // If either edge is null, bail with no paths.
+            if (src == null || dst == null) {
+                return ImmutableSet.of();
+            }
+
+            // Otherwise get all paths between the source and destination edge
+            // devices.
+            return topologyService.getPaths(null, (DeviceId) src, (DeviceId) dst, weight);
+        }
+    }
+
+    private class MockTunnelServiceAdapter extends TunnelServiceAdapter {
+        private HashMap<TunnelId, Tunnel> tunnelIdAsKeyStore = new HashMap<TunnelId, Tunnel>();
+        private int tunnelIdCounter = 0;
+
+        @Override
+        public TunnelId setupTunnel(ApplicationId producerId, ElementId srcElementId, Tunnel tunnel, Path path) {
+            TunnelId tunnelId = TunnelId.valueOf(String.valueOf(++tunnelIdCounter));
+            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(), tunnel.src(), tunnel.dst(), tunnel.type(),
+                                                      tunnel.state(), tunnel.groupId(), tunnelId, tunnel.tunnelName(),
+                                                      path, tunnel.annotations());
+            tunnelIdAsKeyStore.put(tunnelId, tunnelToInsert);
+            return tunnelId;
+        }
+
+        @Override
+        public void addListener(TunnelListener listener) {
+            tunnelListener = listener;
+        }
+
+        /**
+         * Stimulates the effect of receiving PLSP id and LSP id from protocol PCRpt msg.
+         */
+        public TunnelId updateTunnelWithLspIds(Tunnel tunnel, String pLspId, String localLspId, State state) {
+            TunnelId tunnelId = tunnel.tunnelId();
+            Builder annotationBuilder = DefaultAnnotations.builder();
+            annotationBuilder.putAll(tunnel.annotations());
+
+            // PCRpt in response to PCInitate msg will carry PLSP id allocated by PCC.
+            if (tunnel.annotations().value(PLSP_ID) == null) {
+                annotationBuilder.set(PLSP_ID, pLspId);
+            }
+
+            // Signalled LSPs will carry local LSP id allocated by signalling protocol(PCC).
+            if (tunnel.annotations().value(LOCAL_LSP_ID) == null) {
+                annotationBuilder.set(LOCAL_LSP_ID, localLspId);
+            }
+            SparseAnnotations annotations = annotationBuilder.build();
+            tunnelIdAsKeyStore.remove(tunnelId, tunnel);
+
+            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(), tunnel.src(), tunnel.dst(), tunnel.type(),
+                                                      state, tunnel.groupId(), tunnelId, tunnel.tunnelName(),
+                                                      tunnel.path(), annotations);
+
+            tunnelIdAsKeyStore.put(tunnelId, tunnelToInsert);
+
+            return tunnelId;
+        }
+
+        @Override
+        public boolean downTunnel(ApplicationId producerId, TunnelId tunnelId) {
+            for (TunnelId tunnelIdKey : tunnelIdAsKeyStore.keySet()) {
+                if (tunnelIdKey.equals(tunnelId)) {
+                    tunnelIdAsKeyStore.remove(tunnelId);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public Tunnel queryTunnel(TunnelId tunnelId) {
+            for (TunnelId tunnelIdKey : tunnelIdAsKeyStore.keySet()) {
+                if (tunnelIdKey.equals(tunnelId)) {
+                    return tunnelIdAsKeyStore.get(tunnelId);
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public Collection<Tunnel> queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) {
+            Collection<Tunnel> result = new HashSet<Tunnel>();
+            Tunnel tunnel = null;
+            for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
+                tunnel = tunnelIdAsKeyStore.get(tunnelId);
+
+                if ((null != tunnel) && (src.equals(tunnel.src())) && (dst.equals(tunnel.dst()))) {
+                    result.add(tunnel);
+                }
+            }
+
+            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+        }
+
+        @Override
+        public Collection<Tunnel> queryTunnel(Tunnel.Type type) {
+            Collection<Tunnel> result = new HashSet<Tunnel>();
+
+            for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
+                result.add(tunnelIdAsKeyStore.get(tunnelId));
+            }
+
+            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+        }
+    }
+
+    public static class MockCoreService extends CoreServiceAdapter {
+
+        @Override
+        public ApplicationId registerApplication(String name) {
+            return new DefaultApplicationId(1, name);
+        }
+
+        @Override
+        public IdGenerator getIdGenerator(String topic) {
+            return new IdGenerator() {
+                private AtomicLong counter = new AtomicLong(0);
+
+                @Override
+                public long getNewId() {
+                    return counter.getAndIncrement();
+                }
+            };
+        }
+    }
+
+    private class MockDevice extends DefaultDevice {
+        MockDevice(DeviceId id, Annotations annotations) {
+            super(null, id, null, null, null, null, null, null, annotations);
+        }
+    }
+
+    private class MockDeviceService extends DeviceServiceAdapter {
+        List<Device> devices = new LinkedList<>();
+
+        private void addDevice(Device dev) {
+            devices.add(dev);
+        }
+
+        @Override
+        public Device getDevice(DeviceId deviceId) {
+            for (Device dev : devices) {
+                if (dev.id().equals(deviceId)) {
+                    return dev;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public Iterable<Device> getAvailableDevices() {
+            return devices;
+        }
+    }
+
+    private PacketProcessor pktProcessor = null;
+
+    private class MockPacketService extends PacketServiceAdapter {
+        @Override
+        public void addProcessor(PacketProcessor processor, int priority) {
+            pktProcessor = processor;
+        }
+    }
+
+    // Minimal PacketContext to make core and applications happy.
+    final class MockPcepPacketContext extends DefaultPacketContext {
+        private MockPcepPacketContext(InboundPacket inPkt, OutboundPacket outPkt) {
+            super(System.currentTimeMillis(), inPkt, outPkt, false);
+        }
+
+        @Override
+        public void send() {
+        }
+    }
+
+    public static class MockFlowObjService extends FlowObjServiceAdapter {
+        @Override
+        public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
+            ++flowsDownloaded;
+        }
+    }
+}
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceccSrTeBeHandlerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceccSrTeBeHandlerTest.java
index 93f7c69..2a419b5 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceccSrTeBeHandlerTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceccSrTeBeHandlerTest.java
@@ -33,6 +33,8 @@
 import org.junit.Test;
 
 import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
 import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
 import org.onosproject.incubator.net.resource.label.LabelResourceService;
 import org.onosproject.incubator.net.tunnel.LabelStack;
@@ -41,6 +43,7 @@
 import org.onosproject.net.DefaultPath;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
 import org.onosproject.net.Path;
 import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.net.provider.ProviderId;
@@ -61,6 +64,9 @@
     protected LabelResourceAdminService labelRsrcAdminService;
     protected LabelResourceService labelRsrcService;
     protected PceStore pceStore;
+    private FlowObjectiveService flowObjectiveService;
+    private CoreService coreService;
+    private ApplicationId appId;
     private ProviderId providerId;
     private DeviceId deviceId1;
     private DeviceId deviceId2;
@@ -88,8 +94,11 @@
         srTeHandler = PceccSrTeBeHandler.getInstance();
         labelRsrcService = new LabelResourceAdapter();
         labelRsrcAdminService = new LabelResourceAdapter();
+        flowObjectiveService = new PceManagerTest.MockFlowObjService();
+        coreService = new PceManagerTest.MockCoreService();
+        appId = coreService.registerApplication("org.onosproject.pce");
         pceStore = new PceStoreAdapter();
-        srTeHandler.initialize(labelRsrcAdminService, labelRsrcService, pceStore);
+        srTeHandler.initialize(labelRsrcAdminService, labelRsrcService, flowObjectiveService, appId, pceStore);
 
         // Creates path
         // Creates list of links
@@ -446,39 +455,39 @@
         // check node-label of deviceId1
         List<LabelResourceId> labelList = labelStack.labelResources();
         Iterator<LabelResourceId> iterator = labelList.iterator();
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(4097)));
 
         // check adjacency label of deviceId1
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(5122)));
 
         // check node-label of deviceId2
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(4098)));
 
         // check adjacency label of deviceId2
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(5123)));
 
         // check node-label of deviceId3
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(4099)));
 
         // check adjacency label of deviceId3
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(5124)));
 
         // check node-label of deviceId4
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(4100)));
 
         // check adjacency label of deviceId4
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(5125)));
 
         // check node-label of deviceId5
-        labelId = (LabelResourceId) iterator.next();
+        labelId = iterator.next();
         assertThat(labelId, is(LabelResourceId.labelResourceId(4101)));
     }
 }
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/util/FlowObjServiceAdapter.java b/apps/pce/app/src/test/java/org/onosproject/pce/util/FlowObjServiceAdapter.java
new file mode 100644
index 0000000..a7a7e2b
--- /dev/null
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/util/FlowObjServiceAdapter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.util;
+
+import java.util.List;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+
+/**
+ * Test implementation of FlowObjectiveService.
+ */
+public class FlowObjServiceAdapter implements FlowObjectiveService {
+
+    private ForwardingObjective forwardingObjective;
+    @Override
+    public void filter(DeviceId deviceId, FilteringObjective filteringObjective) {
+
+    }
+
+    @Override
+    public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
+        this.forwardingObjective = forwardingObjective;
+    }
+
+    @Override
+    public void next(DeviceId deviceId, NextObjective nextObjective) {
+
+    }
+
+    @Override
+    public int allocateNextId() {
+        return 0;
+    }
+
+    @Override
+    public void initPolicy(String policy) {
+
+    }
+
+    public ForwardingObjective forwardingObjective() {
+        return forwardingObjective;
+    }
+
+    @Override
+    public List<String> getNextMappings() {
+        return null;
+    }
+}
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/util/TunnelServiceAdapter.java b/apps/pce/app/src/test/java/org/onosproject/pce/util/TunnelServiceAdapter.java
new file mode 100644
index 0000000..2a75eaf
--- /dev/null
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/util/TunnelServiceAdapter.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.util;
+
+import java.util.Collection;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.Tunnel.Type;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelListener;
+import org.onosproject.incubator.net.tunnel.TunnelName;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.incubator.net.tunnel.TunnelSubscription;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.Path;
+
+/**
+ * Provides test implementation of class TunnelService.
+ */
+public class TunnelServiceAdapter implements TunnelService {
+
+    @Override
+    public void addListener(TunnelListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeListener(TunnelListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Tunnel borrowTunnel(ApplicationId consumerId, TunnelId tunnelId, Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelName tunnelName,
+                                           Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst,
+                                           Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Type type,
+                                           Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public TunnelId setupTunnel(ApplicationId producerId, ElementId srcElementId, Tunnel tunnel, Path path) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean downTunnel(ApplicationId producerId, TunnelId tunnelId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean returnTunnel(ApplicationId consumerId, TunnelId tunnelId, Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean returnTunnel(ApplicationId consumerId, TunnelName tunnelName, Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Type type,
+                                Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst,
+                                Annotations... annotations) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Tunnel queryTunnel(TunnelId tunnelId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<TunnelSubscription> queryTunnelSubscription(ApplicationId consumerId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Tunnel> queryTunnel(Type type) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Tunnel> queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Tunnel> queryAllTunnels() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int tunnelCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public Iterable<Tunnel> getTunnels(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java
index 63ad05d..18292b7 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepAnnotationKeys.java
@@ -56,4 +56,15 @@
      * Annotation key for the identification of initiated LSP.
      */
     public static final String PCE_INIT = "pceInit";
+
+    /**
+     * Annotation key for the cost type.
+     */
+    public static final String COST_TYPE = "costType";
+
+    /**
+     * Annotation key for the Delegation.
+     * Whether LSPs are delegated or not
+     */
+    public static final String DELEGATE = "delegate";
 }