Move PCE label handling from APP to protocol.

Change-Id: I26ae21b27ac2dc9ae3302030f6860e0e371c342c
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfo.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfo.java
new file mode 100644
index 0000000..636d605
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfo.java
@@ -0,0 +1,209 @@
+/*
+ * 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.pcelabelstore;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+
+/**
+ * Local node details including IN and OUT labels as well as IN and OUT port details.
+ */
+public final class DefaultLspLocalLabelInfo implements LspLocalLabelInfo {
+
+    private final DeviceId deviceId;
+    private final LabelResourceId inLabelId;
+    private final LabelResourceId outLabelId;
+    private final PortNumber inPort;
+    private final PortNumber outPort;
+
+    /**
+     * Initialization of member variables.
+     *
+     * @param deviceId device id
+     * @param inLabelId in label id of a node
+     * @param outLabelId out label id of a node
+     * @param inPort input port
+     * @param outPort remote port
+     */
+    private DefaultLspLocalLabelInfo(DeviceId deviceId,
+                                     LabelResourceId inLabelId,
+                                     LabelResourceId outLabelId,
+                                     PortNumber inPort,
+                                     PortNumber outPort) {
+       this.deviceId = deviceId;
+       this.inLabelId = inLabelId;
+       this.outLabelId = outLabelId;
+       this.inPort = inPort;
+       this.outPort = outPort;
+    }
+
+    /**
+     * Initialization of member variables for serialization.
+     */
+    private DefaultLspLocalLabelInfo() {
+       this.deviceId = null;
+       this.inLabelId = null;
+       this.outLabelId = null;
+       this.inPort = null;
+       this.outPort = null;
+    }
+
+    @Override
+    public DeviceId deviceId() {
+       return deviceId;
+    }
+
+    @Override
+    public LabelResourceId inLabelId() {
+       return inLabelId;
+    }
+
+    @Override
+    public LabelResourceId outLabelId() {
+       return outLabelId;
+    }
+
+    @Override
+    public PortNumber inPort() {
+       return inPort;
+    }
+
+    @Override
+    public PortNumber outPort() {
+       return outPort;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(deviceId, inLabelId, outLabelId, inPort, outPort);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LspLocalLabelInfo) {
+            final DefaultLspLocalLabelInfo other = (DefaultLspLocalLabelInfo) obj;
+            return Objects.equals(this.deviceId, other.deviceId) &&
+                    Objects.equals(this.inLabelId, other.inLabelId) &&
+                    Objects.equals(this.outLabelId, other.outLabelId) &&
+                    Objects.equals(this.inPort, other.inPort) &&
+                    Objects.equals(this.outPort, other.outPort);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .omitNullValues()
+                .add("DeviceId", deviceId)
+                .add("InLabelId", inLabelId)
+                .add("OutLabelId", outLabelId)
+                .add("InPort", inPort)
+                .add("OutPort", outPort)
+                .toString();
+    }
+
+    /**
+     * Creates and returns a new builder instance that clones an existing object.
+     *
+     * @param deviceLabelInfo device label information
+     * @return new builder
+     */
+    public static Builder builder(LspLocalLabelInfo deviceLabelInfo) {
+        return new Builder(deviceLabelInfo);
+    }
+
+    /**
+     * Creates and returns a new builder instance.
+     *
+     * @return new builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder.
+     */
+    public static final class Builder implements LspLocalLabelInfo.Builder {
+        private DeviceId deviceId;
+        private LabelResourceId inLabelId;
+        private LabelResourceId outLabelId;
+        private PortNumber inPort;
+        private PortNumber outPort;
+
+        /**
+         * Constructs default builder.
+         */
+        private Builder() {
+        }
+
+        /**
+         * Initializes member variables with existing object.
+         */
+        private Builder(LspLocalLabelInfo deviceLabelInfo) {
+            this.deviceId = deviceLabelInfo.deviceId();
+            this.inLabelId = deviceLabelInfo.inLabelId();
+            this.outLabelId = deviceLabelInfo.outLabelId();
+            this.inPort = deviceLabelInfo.inPort();
+            this.outPort = deviceLabelInfo.outPort();
+        }
+
+        @Override
+        public Builder deviceId(DeviceId id) {
+            this.deviceId = id;
+            return this;
+        }
+
+        @Override
+        public Builder inLabelId(LabelResourceId id) {
+            this.inLabelId = id;
+            return this;
+        }
+
+        @Override
+        public Builder outLabelId(LabelResourceId id) {
+            this.outLabelId = id;
+            return this;
+        }
+
+        @Override
+        public Builder inPort(PortNumber port) {
+            this.inPort = port;
+            return this;
+        }
+
+        @Override
+        public Builder outPort(PortNumber port) {
+            this.outPort = port;
+            return this;
+        }
+
+        @Override
+        public LspLocalLabelInfo build() {
+            return new DefaultLspLocalLabelInfo(deviceId, inLabelId, outLabelId, inPort, outPort);
+        }
+    }
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/DistributedPceLabelStore.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/DistributedPceLabelStore.java
new file mode 100644
index 0000000..9121058
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/DistributedPceLabelStore.java
@@ -0,0 +1,296 @@
+/*
+ * 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.pcelabelstore;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the pool of available labels to devices, links and tunnels.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedPceLabelStore implements PceLabelStore {
+
+    private static final String DEVICE_ID_NULL = "Device ID cannot be null";
+    private static final String LABEL_RESOURCE_ID_NULL = "Label Resource Id cannot be null";
+    private static final String LINK_NULL = "LINK cannot be null";
+    private static final String PCECC_TUNNEL_INFO_NULL = "PCECC Tunnel Info cannot be null";
+    private static final String TUNNEL_ID_NULL = "Tunnel Id cannot be null";
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+
+    // Mapping device with global node label
+    private ConsistentMap<DeviceId, LabelResourceId> globalNodeLabelMap;
+
+    // Mapping link with adjacency label
+    private ConsistentMap<Link, LabelResourceId> adjLabelMap;
+
+    // Mapping tunnel id with local labels.
+    private ConsistentMap<TunnelId, List<LspLocalLabelInfo>> tunnelLabelInfoMap;
+
+    // Locally maintain LSRID to device id mapping for better performance.
+    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
+
+    // List of PCC LSR ids whose BGP device information was not available to perform
+    // label db sync.
+    private HashSet<DeviceId> pendinglabelDbSyncPccMap = new HashSet<>();
+
+    @Activate
+    protected void activate() {
+        globalNodeLabelMap = storageService.<DeviceId, LabelResourceId>consistentMapBuilder()
+                .withName("onos-pce-globalnodelabelmap")
+                .withSerializer(Serializer.using(
+                        new KryoNamespace.Builder()
+                                .register(KryoNamespaces.API)
+                                .register(LabelResourceId.class)
+                                .build()))
+                .build();
+
+        adjLabelMap = storageService.<Link, LabelResourceId>consistentMapBuilder()
+                .withName("onos-pce-adjlabelmap")
+                .withSerializer(Serializer.using(
+                        new KryoNamespace.Builder()
+                                .register(KryoNamespaces.API)
+                                .register(Link.class,
+                                          LabelResource.class,
+                                          LabelResourceId.class)
+                                .build()))
+                .build();
+
+        tunnelLabelInfoMap = storageService.<TunnelId, List<LspLocalLabelInfo>>consistentMapBuilder()
+                .withName("onos-pce-tunnellabelinfomap")
+                .withSerializer(Serializer.using(
+                        new KryoNamespace.Builder()
+                                .register(KryoNamespaces.API)
+                                .register(TunnelId.class,
+                                          DefaultLspLocalLabelInfo.class,
+                                          LabelResourceId.class,
+                                          DeviceId.class)
+                                .build()))
+                .build();
+
+        log.info("Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        log.info("Stopped");
+    }
+
+    @Override
+    public boolean existsGlobalNodeLabel(DeviceId id) {
+        checkNotNull(id, DEVICE_ID_NULL);
+        return globalNodeLabelMap.containsKey(id);
+    }
+
+    @Override
+    public boolean existsAdjLabel(Link link) {
+        checkNotNull(link, LINK_NULL);
+        return adjLabelMap.containsKey(link);
+    }
+
+    @Override
+    public boolean existsTunnelInfo(TunnelId tunnelId) {
+        checkNotNull(tunnelId, TUNNEL_ID_NULL);
+        return tunnelLabelInfoMap.containsKey(tunnelId);
+    }
+
+    @Override
+    public int getGlobalNodeLabelCount() {
+        return globalNodeLabelMap.size();
+    }
+
+    @Override
+    public int getAdjLabelCount() {
+        return adjLabelMap.size();
+    }
+
+    @Override
+    public int getTunnelInfoCount() {
+        return tunnelLabelInfoMap.size();
+    }
+
+    @Override
+    public Map<DeviceId, LabelResourceId> getGlobalNodeLabels() {
+       return globalNodeLabelMap.entrySet().stream()
+                 .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().value()));
+    }
+
+    @Override
+    public Map<Link, LabelResourceId> getAdjLabels() {
+       return adjLabelMap.entrySet().stream()
+                 .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().value()));
+    }
+
+    @Override
+    public Map<TunnelId, List<LspLocalLabelInfo>> getTunnelInfos() {
+       return tunnelLabelInfoMap.entrySet().stream()
+                 .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().value()));
+    }
+
+    @Override
+    public LabelResourceId getGlobalNodeLabel(DeviceId id) {
+        checkNotNull(id, DEVICE_ID_NULL);
+        return globalNodeLabelMap.get(id) == null ? null : globalNodeLabelMap.get(id).value();
+    }
+
+    @Override
+    public LabelResourceId getAdjLabel(Link link) {
+        checkNotNull(link, LINK_NULL);
+        return adjLabelMap.get(link) == null ? null : adjLabelMap.get(link).value();
+    }
+
+    @Override
+    public List<LspLocalLabelInfo> getTunnelInfo(TunnelId tunnelId) {
+        checkNotNull(tunnelId, TUNNEL_ID_NULL);
+        return tunnelLabelInfoMap.get(tunnelId) == null ? null : tunnelLabelInfoMap.get(tunnelId).value();
+    }
+
+    @Override
+    public void addGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId) {
+        checkNotNull(deviceId, DEVICE_ID_NULL);
+        checkNotNull(labelId, LABEL_RESOURCE_ID_NULL);
+
+        globalNodeLabelMap.put(deviceId, labelId);
+    }
+
+    @Override
+    public void addAdjLabel(Link link, LabelResourceId labelId) {
+        checkNotNull(link, LINK_NULL);
+        checkNotNull(labelId, LABEL_RESOURCE_ID_NULL);
+
+        adjLabelMap.put(link, labelId);
+    }
+
+    @Override
+    public void addTunnelInfo(TunnelId tunnelId, List<LspLocalLabelInfo> lspLocalLabelInfoList) {
+        checkNotNull(tunnelId, TUNNEL_ID_NULL);
+        checkNotNull(lspLocalLabelInfoList, PCECC_TUNNEL_INFO_NULL);
+
+        tunnelLabelInfoMap.put(tunnelId, lspLocalLabelInfoList);
+    }
+
+    @Override
+    public boolean removeGlobalNodeLabel(DeviceId id) {
+        checkNotNull(id, DEVICE_ID_NULL);
+
+        if (globalNodeLabelMap.remove(id) == null) {
+            log.error("SR-TE node label deletion for device {} has failed.", id.toString());
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean removeAdjLabel(Link link) {
+        checkNotNull(link, LINK_NULL);
+
+        if (adjLabelMap.remove(link) == null) {
+            log.error("Adjacency label deletion for link {} hash failed.", link.toString());
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean removeTunnelInfo(TunnelId tunnelId) {
+        checkNotNull(tunnelId, TUNNEL_ID_NULL);
+
+        if (tunnelLabelInfoMap.remove(tunnelId) == null) {
+            log.error("Tunnel info deletion for tunnel id {} has failed.", tunnelId.toString());
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addLsrIdDevice(String lsrId, DeviceId deviceId) {
+        checkNotNull(lsrId);
+        checkNotNull(deviceId);
+
+        lsrIdDeviceIdMap.put(lsrId, deviceId);
+        return true;
+    }
+
+    @Override
+    public boolean removeLsrIdDevice(String lsrId) {
+        checkNotNull(lsrId);
+
+        lsrIdDeviceIdMap.remove(lsrId);
+        return true;
+    }
+
+    @Override
+    public DeviceId getLsrIdDevice(String lsrId) {
+        checkNotNull(lsrId);
+
+        return lsrIdDeviceIdMap.get(lsrId);
+
+    }
+
+    @Override
+    public boolean addPccLsr(DeviceId lsrId) {
+        checkNotNull(lsrId);
+        pendinglabelDbSyncPccMap.add(lsrId);
+        return true;
+    }
+
+    @Override
+    public boolean removePccLsr(DeviceId lsrId) {
+        checkNotNull(lsrId);
+        pendinglabelDbSyncPccMap.remove(lsrId);
+        return true;
+    }
+
+    @Override
+    public boolean hasPccLsr(DeviceId lsrId) {
+        checkNotNull(lsrId);
+        return pendinglabelDbSyncPccMap.contains(lsrId);
+
+    }
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/PcepLabelOp.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/PcepLabelOp.java
new file mode 100644
index 0000000..4e7ef83
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/PcepLabelOp.java
@@ -0,0 +1,21 @@
+package org.onosproject.pcelabelstore;
+
+/**
+ * Representation of label operation over PCEP.
+ */
+public enum PcepLabelOp {
+    /**
+     * Signifies that the label operation is addition.
+     */
+    ADD,
+
+    /**
+     * Signifies that the label operation is modification. This is reserved for future.
+     */
+    MODIFY,
+
+    /**
+     * Signifies that the label operation is deletion.
+     */
+    REMOVE
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/LspLocalLabelInfo.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/LspLocalLabelInfo.java
new file mode 100644
index 0000000..8ab861e
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/LspLocalLabelInfo.java
@@ -0,0 +1,114 @@
+/*
+ * 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.pcelabelstore.api;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+
+/**
+ * Abstraction of an entity providing LSP local label information.
+ */
+public interface LspLocalLabelInfo {
+
+    /**
+     * Returns device id.
+     *
+     * @return device id
+     */
+    DeviceId deviceId();
+
+    /**
+     * Returns in label id of a device.
+     *
+     * @return in label resource id
+     */
+    LabelResourceId inLabelId();
+
+    /**
+     * Returns out label id of a device.
+     *
+     * @return node out label resource id
+     */
+    LabelResourceId outLabelId();
+
+    /**
+     * Returns in port of an incoming label.
+     *
+     * @return in port
+     */
+    PortNumber inPort();
+
+    /**
+     * Returns next hop of an outgoing label.
+     *
+     * @return out port
+     */
+    PortNumber outPort();
+
+    /**
+     * LspLocalLabelInfo Builder.
+     */
+    interface Builder {
+
+        /**
+         * Returns builder object of a device id.
+         *
+         * @param id device id
+         * @return builder object of device id
+         */
+        Builder deviceId(DeviceId id);
+
+        /**
+         * Returns builder object of in label.
+         *
+         * @param id in label id
+         * @return builder object of in label id
+         */
+        Builder inLabelId(LabelResourceId id);
+
+        /**
+         * Returns builder object of out label.
+         *
+         * @param id out label id
+         * @return builder object of out label id
+         */
+        Builder outLabelId(LabelResourceId id);
+
+        /**
+         * Returns builder object of in port of an incoming label.
+         *
+         * @param port in port
+         * @return builder object of in port
+         */
+        Builder inPort(PortNumber port);
+
+        /**
+         * Returns builder object of next hop of an outgoing label.
+         *
+         * @param port out port
+         * @return builder object of out port
+         */
+        Builder outPort(PortNumber port);
+
+        /**
+         * Builds object of device local label info.
+         *
+         * @return object of device local label info.
+         */
+        LspLocalLabelInfo build();
+    }
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/PceLabelStore.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/PceLabelStore.java
new file mode 100644
index 0000000..8037478
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/PceLabelStore.java
@@ -0,0 +1,217 @@
+/*
+ * 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.pcelabelstore.api;
+
+import java.util.List;
+
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import java.util.Map;
+
+/**
+ * Abstraction of an entity providing pool of available labels to devices, links and tunnels.
+ */
+public interface PceLabelStore {
+    /**
+     * Checks whether device id is present in global node label store.
+     *
+     * @param id device id
+     * @return success of failure
+     */
+    boolean existsGlobalNodeLabel(DeviceId id);
+
+    /**
+     * Checks whether link is present in adjacency label store.
+     *
+     * @param link link between devices
+     * @return success of failure
+     */
+    boolean existsAdjLabel(Link link);
+
+    /**
+     * Checks whether tunnel id is present in tunnel info store.
+     *
+     * @param tunnelId tunnel id
+     * @return success of failure
+     */
+    boolean existsTunnelInfo(TunnelId tunnelId);
+
+    /**
+     * Retrieves the node label count.
+     *
+     * @return node label count
+     */
+    int getGlobalNodeLabelCount();
+
+    /**
+     * Retrieves the adjacency label count.
+     *
+     * @return adjacency label count
+     */
+    int getAdjLabelCount();
+
+    /**
+     * Retrieves the tunnel info count.
+     *
+     * @return tunnel info count
+     */
+    int getTunnelInfoCount();
+
+    /**
+     * Retrieves device id and label pairs collection from global node label store.
+     *
+     * @return collection of device id and label pairs
+     */
+    Map<DeviceId, LabelResourceId> getGlobalNodeLabels();
+
+    /**
+     * Retrieves link and label pairs collection from adjacency label store.
+     *
+     * @return collection of link and label pairs
+     */
+    Map<Link, LabelResourceId> getAdjLabels();
+
+    /**
+     * Retrieves tunnel id and pcecc tunnel info pairs collection from tunnel info store.
+     *
+     * @return collection of tunnel id and pcecc tunnel info pairs
+     */
+    Map<TunnelId, List<LspLocalLabelInfo>> getTunnelInfos();
+
+    /**
+     * Retrieves node label for specified device id.
+     *
+     * @param id device id
+     * @return node label
+     */
+    LabelResourceId getGlobalNodeLabel(DeviceId id);
+
+    /**
+     * Retrieves adjacency label for specified link.
+     *
+     * @param link between devices
+     * @return adjacency label
+     */
+    LabelResourceId getAdjLabel(Link link);
+
+    /**
+     * Retrieves local label info with tunnel consumer id from tunnel info store.
+     *
+     * @param tunnelId tunnel id
+     * @return pcecc tunnel info
+     */
+    List<LspLocalLabelInfo> getTunnelInfo(TunnelId tunnelId);
+
+    /**
+     * Stores node label into global node label store.
+     *
+     * @param deviceId device id
+     * @param labelId node label id
+     */
+    void addGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId);
+
+    /**
+     * Stores adjacency label into adjacency label store.
+     *
+     * @param link link between nodes
+     * @param labelId link label id
+     */
+    void addAdjLabel(Link link, LabelResourceId labelId);
+
+    /**
+     * Stores local label info with tunnel consumer id into tunnel info store for specified tunnel id.
+     *
+     * @param tunnelId tunnel id
+     * @param lspLocalLabelInfoList local label info
+     */
+    void addTunnelInfo(TunnelId tunnelId, List<LspLocalLabelInfo> lspLocalLabelInfoList);
+
+    /**
+     * Removes device label from global node label store for specified device id.
+     *
+     * @param id device id
+     * @return success or failure
+     */
+    boolean removeGlobalNodeLabel(DeviceId id);
+
+    /**
+     * Removes adjacency label from adjacency label store for specified link information.
+     *
+     * @param link between nodes
+     * @return success or failure
+     */
+    boolean removeAdjLabel(Link link);
+
+    /**
+     * Removes local label info with tunnel consumer id from tunnel info store for specified tunnel id.
+     *
+     * @param tunnelId tunnel id
+     * @return success or failure
+     */
+    boolean removeTunnelInfo(TunnelId tunnelId);
+
+    /**
+     * Adds lsrid to device id mapping.
+     *
+     * @param lsrId lsrId of the device
+     * @param deviceId device id
+     * @return success or failure
+     */
+    boolean addLsrIdDevice(String lsrId, DeviceId deviceId);
+
+    /**
+     * Removes lsrid to device id mapping.
+     *
+     * @param lsrId lsrId of the device
+     * @return success or failure
+     */
+    boolean removeLsrIdDevice(String lsrId);
+
+    /**
+     * Gets lsrid to device id mapping.
+     *
+     * @param lsrId lsrId of the device
+     * @return device id of the lsrId
+     */
+    DeviceId getLsrIdDevice(String lsrId);
+
+    /**
+     * Adds lsrId of the PCC in form of device id for the PCC for which sync is pending due to non-availability of BGP.
+     * device.
+     *
+     * @param lsrId LSR id of the PCC in form of device id
+     * @return success or failure
+     */
+    public boolean addPccLsr(DeviceId lsrId);
+
+    /**
+     * Removes lsrId of the PCC in form of device id for the PCC for which pending sync is done.
+     *
+     * @param lsrId LSR id of the PCC in form of device id
+     * @return success or failure
+     */
+    public boolean removePccLsr(DeviceId lsrId);
+
+    /**
+     * Gets lsrId of the PCC in form of device id.
+     *
+     * @param lsrId LSR id of the PCC in form of device id
+     * @return success or failure
+     */
+    public boolean hasPccLsr(DeviceId lsrId);
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/package-info.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/package-info.java
new file mode 100644
index 0000000..ca084d6
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * PCE store service API.
+ */
+package org.onosproject.pcelabelstore.api;
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/package-info.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/package-info.java
new file mode 100644
index 0000000..c32c094
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcelabelstore/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * PCE store application.
+ */
+package org.onosproject.pcelabelstore;
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/BasicPceccHandler.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/BasicPceccHandler.java
new file mode 100644
index 0000000..192b909
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/BasicPceccHandler.java
@@ -0,0 +1,577 @@
+/*
+ * 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.pcep.controller.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.LinkedList;
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+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.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.pcelabelstore.DefaultLspLocalLabelInfo;
+import org.onosproject.pcelabelstore.PcepLabelOp;
+import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+import org.onosproject.pcep.controller.LspType;
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepAnnotationKeys;
+import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepClientController;
+import org.onosproject.pcep.controller.SrpIdGenerators;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepAttribute;
+import org.onosproject.pcepio.protocol.PcepBandwidthObject;
+import org.onosproject.pcepio.protocol.PcepEroObject;
+import org.onosproject.pcepio.protocol.PcepLabelObject;
+import org.onosproject.pcepio.protocol.PcepLabelUpdate;
+import org.onosproject.pcepio.protocol.PcepLabelUpdateMsg;
+import org.onosproject.pcepio.protocol.PcepLspObject;
+import org.onosproject.pcepio.protocol.PcepMsgPath;
+import org.onosproject.pcepio.protocol.PcepSrpObject;
+import org.onosproject.pcepio.protocol.PcepUpdateMsg;
+import org.onosproject.pcepio.protocol.PcepUpdateRequest;
+import org.onosproject.pcepio.types.IPv4SubObject;
+import org.onosproject.pcepio.types.NexthopIPv4addressTlv;
+import org.onosproject.pcepio.types.PathSetupTypeTlv;
+import org.onosproject.pcepio.types.PcepLabelDownload;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
+import org.onosproject.pcepio.types.SymbolicPathNameTlv;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.BANDWIDTH;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.LSP_SIG_TYPE;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.PCE_INIT;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.DELEGATE;
+
+/**
+ * Basic PCECC handler.
+ * In Basic PCECC, after path computation will configure IN and OUT label to nodes.
+ * [X]OUT---link----IN[Y]OUT---link-----IN[Z] where X, Y and Z are nodes.
+ * For generating labels, will go thorough links in the path from Egress to Ingress.
+ * In each link, will take label from destination node local pool as IN label,
+ * and assign this label as OUT label to source node.
+ */
+public final class BasicPceccHandler {
+    private static final Logger log = LoggerFactory.getLogger(BasicPceccHandler.class);
+    public static final int OUT_LABEL_TYPE = 0;
+    public static final int IN_LABEL_TYPE = 1;
+    public static final long IDENTIFIER_SET = 0x100000000L;
+    public static final long SET = 0xFFFFFFFFL;
+    private static final String LSRID = "lsrId";
+    private static final String LABEL_RESOURCE_SERVICE_NULL = "Label Resource Service cannot be null";
+    private static final String PCE_STORE_NULL = "PCE Store cannot be null";
+    private static BasicPceccHandler crHandlerInstance = null;
+    private LabelResourceService labelRsrcService;
+    private DeviceService deviceService;
+    private PceLabelStore pceStore;
+    private PcepClientController clientController;
+    private PcepLabelObject labelObj;
+
+    /**
+     * Initializes default values.
+     */
+    private BasicPceccHandler() {
+    }
+
+    /**
+     * Returns single instance of this class.
+     *
+     * @return this class single instance
+     */
+    public static BasicPceccHandler getInstance() {
+        if (crHandlerInstance == null) {
+            crHandlerInstance = new BasicPceccHandler();
+        }
+        return crHandlerInstance;
+    }
+
+    /**
+     * Initialization of label manager and pce store.
+     *
+     * @param labelRsrcService label resource service
+     * @param pceStore pce label store
+     */
+    public void initialize(LabelResourceService labelRsrcService,
+                           DeviceService deviceService,
+                           PceLabelStore pceStore,
+                           PcepClientController clientController) {
+        this.labelRsrcService = labelRsrcService;
+        this.deviceService = deviceService;
+        this.pceStore = pceStore;
+        this.clientController = clientController;
+    }
+
+    /**
+     * Allocates labels from local resource pool and configure these (IN and OUT) labels into devices.
+     *
+     * @param tunnel tunnel between ingress to egress
+     * @return success or failure
+     */
+    public boolean allocateLabel(Tunnel tunnel) {
+        long applyNum = 1;
+        boolean isLastLabelToPush = false;
+        Collection<LabelResource> labelRscList;
+
+        checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
+        checkNotNull(pceStore, PCE_STORE_NULL);
+
+        List<Link> linkList = tunnel.path().links();
+        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<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);
+                if ((labelRscList != null) && (labelRscList.size() > 0)) {
+                    // Link label value is taken from destination device local pool.
+                    // [X]OUT---link----IN[Y]OUT---link-----IN[Z] where X, Y and Z are nodes.
+                    // Link label value is used as OUT and IN for both ends
+                    // (source and destination devices) of the link.
+                    // Currently only one label is allocated to a device (destination device).
+                    // So, no need to iterate through list
+                    Iterator<LabelResource> labelIterator = labelRscList.iterator();
+                    DefaultLabelResource defaultLabelResource = (DefaultLabelResource) labelIterator.next();
+                    LabelResourceId labelId = defaultLabelResource.labelResourceId();
+                    log.debug("Allocated local label: " + labelId.toString()
+                              + "to device: " + defaultLabelResource.deviceId().toString());
+                    PortNumber dstPort = link.dst().port();
+
+                    // Check whether this is last link label to push
+                    if (!iterator.hasPrevious()) {
+                       isLastLabelToPush = true;
+                    }
+
+                    try {
+                        // Push into destination device
+                        // Destination device IN port is link.dst().port()
+                        pushLocalLabels(dstDeviceId, labelId, dstPort, tunnel, false,
+                                            Long.valueOf(LabelType.IN_LABEL.value), PcepLabelOp.ADD);
+
+                        // Push into source device
+                        // Source device OUT port will be link.dst().port(). Means its remote port used to send packet.
+                        pushLocalLabels(srcDeviceId, labelId, dstPort, tunnel, isLastLabelToPush,
+                                            Long.valueOf(LabelType.OUT_LABEL.value), PcepLabelOp.ADD);
+                    } catch (PcepParseException e) {
+                        log.error("Failed to push local label for device {} or {} for tunnel {}.",
+                                  dstDeviceId.toString(), srcDeviceId.toString(), tunnel.tunnelName().toString());
+                    }
+
+                    // Add or update pcecc tunnel info in pce store.
+                    updatePceccTunnelInfoInStore(srcDeviceId, dstDeviceId, labelId, dstPort,
+                                                 tunnel);
+                } else {
+                    log.error("Unable to allocate label to device id {}.", dstDeviceId.toString());
+                    releaseLabel(tunnel);
+                    return false;
+                }
+            }
+        } else {
+           log.error("Tunnel {} is having empty links.", tunnel.toString());
+           return false;
+        }
+        return true;
+    }
+
+    /**
+     * Updates list of local labels of PCECC tunnel info in pce store.
+     *
+     * @param srcDeviceId source device in a link
+     * @param dstDeviceId destination device in a link
+     * @param labelId label id of a link
+     * @param dstPort destination device port number of a link
+     * @param tunnel tunnel
+     */
+    public void updatePceccTunnelInfoInStore(DeviceId srcDeviceId, DeviceId dstDeviceId, LabelResourceId labelId,
+                                                PortNumber dstPort, Tunnel tunnel) {
+       // First try to retrieve device from store and update its label id if it is exists,
+       // otherwise add it
+       boolean dstDeviceUpdated = false;
+       boolean srcDeviceUpdated = false;
+
+       List<LspLocalLabelInfo> lspLabelInfoList = pceStore.getTunnelInfo(tunnel.tunnelId());
+       if ((lspLabelInfoList != null) && (lspLabelInfoList.size() > 0)) {
+           for (int i = 0; i < lspLabelInfoList.size(); ++i) {
+               LspLocalLabelInfo lspLocalLabelInfo =
+                       lspLabelInfoList.get(i);
+               LspLocalLabelInfo.Builder lspLocalLabelInfoBuilder = null;
+               if (dstDeviceId.equals(lspLocalLabelInfo.deviceId())) {
+                   lspLocalLabelInfoBuilder = DefaultLspLocalLabelInfo.builder(lspLocalLabelInfo);
+                   lspLocalLabelInfoBuilder.inLabelId(labelId);
+                   // Destination device IN port will be link destination port
+                   lspLocalLabelInfoBuilder.inPort(dstPort);
+                   dstDeviceUpdated = true;
+               } else if (srcDeviceId.equals(lspLocalLabelInfo.deviceId())) {
+                   lspLocalLabelInfoBuilder = DefaultLspLocalLabelInfo.builder(lspLocalLabelInfo);
+                   lspLocalLabelInfoBuilder.outLabelId(labelId);
+                   // Source device OUT port will be link destination (remote) port
+                   lspLocalLabelInfoBuilder.outPort(dstPort);
+                   srcDeviceUpdated = true;
+               }
+
+               // Update
+               if ((lspLocalLabelInfoBuilder != null) && (dstDeviceUpdated || srcDeviceUpdated)) {
+                   lspLabelInfoList.set(i, lspLocalLabelInfoBuilder.build());
+               }
+           }
+       }
+
+       // If it is not found in store then add it to store
+       if (!dstDeviceUpdated || !srcDeviceUpdated) {
+           // If tunnel info itself not available then create new one, otherwise add node to list.
+           if (lspLabelInfoList == null) {
+              lspLabelInfoList = new LinkedList<>();
+           }
+
+           if (!dstDeviceUpdated) {
+               LspLocalLabelInfo lspLocalLabelInfo = DefaultLspLocalLabelInfo.builder()
+                   .deviceId(dstDeviceId)
+                   .inLabelId(labelId)
+                   .outLabelId(null)
+                   .inPort(dstPort) // Destination device IN port will be link destination port
+                   .outPort(null)
+                   .build();
+               lspLabelInfoList.add(lspLocalLabelInfo);
+           }
+
+           if (!srcDeviceUpdated) {
+               LspLocalLabelInfo lspLocalLabelInfo = DefaultLspLocalLabelInfo.builder()
+                   .deviceId(srcDeviceId)
+                   .inLabelId(null)
+                   .outLabelId(labelId)
+                   .inPort(null)
+                   .outPort(dstPort) // Source device OUT port will be link destination (remote) port
+                   .build();
+               lspLabelInfoList.add(lspLocalLabelInfo);
+           }
+
+           pceStore.addTunnelInfo(tunnel.tunnelId(), lspLabelInfoList);
+       }
+    }
+
+    /**
+     * Deallocates unused labels to device pools.
+     *
+     * @param tunnel tunnel between ingress to egress
+     */
+    public void releaseLabel(Tunnel tunnel) {
+
+       checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
+       checkNotNull(pceStore, PCE_STORE_NULL);
+
+       Multimap<DeviceId, LabelResource> release = ArrayListMultimap.create();
+       List<LspLocalLabelInfo> lspLocalLabelInfoList = pceStore.getTunnelInfo(tunnel.tunnelId());
+       if ((lspLocalLabelInfoList != null) && (lspLocalLabelInfoList.size() > 0)) {
+           for (Iterator<LspLocalLabelInfo> iterator = lspLocalLabelInfoList.iterator(); iterator.hasNext();) {
+               LspLocalLabelInfo lspLocalLabelInfo = iterator.next();
+               DeviceId deviceId = lspLocalLabelInfo.deviceId();
+               LabelResourceId inLabelId = lspLocalLabelInfo.inLabelId();
+               LabelResourceId outLabelId = lspLocalLabelInfo.outLabelId();
+               PortNumber inPort = lspLocalLabelInfo.inPort();
+               PortNumber outPort = lspLocalLabelInfo.outPort();
+
+               try {
+                   // Push into device
+                   if ((outLabelId != null) && (outPort != null)) {
+                       pushLocalLabels(deviceId, outLabelId, outPort, tunnel, false,
+                                       Long.valueOf(LabelType.OUT_LABEL.value), PcepLabelOp.REMOVE);
+                   }
+
+                   if ((inLabelId != null) && (inPort != null)) {
+                       pushLocalLabels(deviceId, inLabelId, inPort, tunnel, false,
+                                       Long.valueOf(LabelType.IN_LABEL.value), PcepLabelOp.REMOVE);
+                   }
+               } catch (PcepParseException e) {
+                   log.error("Failed to push local label for device {}for tunnel {}.", deviceId.toString(),
+                             tunnel.tunnelName().toString());
+               }
+
+               // List is stored from egress to ingress. So, using IN label id to release.
+               // Only one local label is assigned to device (destination node)
+               // and that is used as OUT label for source node.
+               // No need to release label for last node in the list from pool because label was not allocated to
+               // ingress node (source node).
+               if ((iterator.hasNext()) && (inLabelId != null)) {
+                   LabelResource labelRsc = new DefaultLabelResource(deviceId, inLabelId);
+                   release.put(deviceId, labelRsc);
+               }
+           }
+       }
+
+       // Release from label pool
+       if (!release.isEmpty()) {
+          labelRsrcService.releaseToDevicePool(release);
+       }
+
+       pceStore.removeTunnelInfo(tunnel.tunnelId());
+   }
+
+   //Pushes local labels to the device which is specific to path [CR-case].
+   private void pushLocalLabels(DeviceId deviceId, LabelResourceId labelId,
+            PortNumber portNum, Tunnel tunnel,
+            Boolean isBos, Long labelType, PcepLabelOp type) throws PcepParseException {
+
+        checkNotNull(deviceId);
+        checkNotNull(labelId);
+        checkNotNull(portNum);
+        checkNotNull(tunnel);
+        checkNotNull(labelType);
+        checkNotNull(type);
+
+        PcepClient pc = getPcepClient(deviceId);
+        if (pc == null) {
+            log.error("PCEP client not found");
+            return;
+        }
+
+        PcepLspObject lspObj;
+        LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
+        LinkedList<PcepLabelObject> labelObjects = new LinkedList<>();
+        PcepSrpObject srpObj;
+        PcepLabelDownload labelDownload = new PcepLabelDownload();
+        LinkedList<PcepValueType> optionalTlv = new LinkedList<>();
+
+        long portNo = portNum.toLong();
+        portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
+
+        optionalTlv.add(NexthopIPv4addressTlv.of((int) portNo));
+
+        PcepLabelObject labelObj = pc.factory().buildLabelObject()
+                                   .setOFlag(labelType == OUT_LABEL_TYPE ? true : false)
+                                   .setOptionalTlv(optionalTlv)
+                                   .setLabel((int) labelId.labelId())
+                                   .build();
+
+        /**
+         * Check whether transit node or not. For transit node, label update message should include IN and OUT labels.
+         * Hence store IN label object and next when out label comes add IN and OUT label objects and encode label
+         * update message and send to specified client.
+         */
+        if (!deviceId.equals(tunnel.path().src().deviceId()) && !deviceId.equals(tunnel.path().dst().deviceId())) {
+            //Device is transit node
+            if (labelType == OUT_LABEL_TYPE) {
+                //Store label object having IN label value
+                this.labelObj = labelObj;
+                return;
+            }
+            //Add IN label object
+            labelObjects.add(this.labelObj);
+        }
+
+        //Add OUT label object in case of transit node
+        labelObjects.add(labelObj);
+
+        srpObj = getSrpObject(pc, type, false);
+
+        String lspId = tunnel.annotations().value(PcepAnnotationKeys.LOCAL_LSP_ID);
+        String plspId = tunnel.annotations().value(PcepAnnotationKeys.PLSP_ID);
+        String tunnelIdentifier = tunnel.annotations().value(PcepAnnotationKeys.PCC_TUNNEL_ID);
+
+        LinkedList<PcepValueType> tlvs = new LinkedList<>();
+        StatefulIPv4LspIdentifiersTlv lspIdTlv = new StatefulIPv4LspIdentifiersTlv(((IpTunnelEndPoint) tunnel.src())
+                .ip().getIp4Address().toInt(), Short.valueOf(lspId), Short.valueOf(tunnelIdentifier),
+                ((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt(),
+                ((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt());
+        tlvs.add(lspIdTlv);
+
+        if (tunnel.tunnelName().value() != null) {
+            SymbolicPathNameTlv pathNameTlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
+            tlvs.add(pathNameTlv);
+        }
+
+        boolean delegated = (tunnel.annotations().value(DELEGATE) == null) ? false
+                                                                           : Boolean.valueOf(tunnel.annotations()
+                                                                                   .value(DELEGATE));
+        boolean initiated = (tunnel.annotations().value(PCE_INIT) == null) ? false
+                                                                           : Boolean.valueOf(tunnel.annotations()
+                                                                                   .value(PCE_INIT));
+
+        lspObj = pc.factory().buildLspObject()
+                .setRFlag(false)
+                .setAFlag(true)
+                .setDFlag(delegated)
+                .setCFlag(initiated)
+                .setPlspId(Integer.valueOf(plspId))
+                .setOptionalTlv(tlvs)
+                .build();
+
+        labelDownload.setLabelList(labelObjects);
+        labelDownload.setLspObject(lspObj);
+        labelDownload.setSrpObject(srpObj);
+
+        labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
+                            .setLabelDownload(labelDownload)
+                            .build());
+
+        PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
+                                      .setPcLabelUpdateList(labelUpdateList)
+                                      .build();
+
+        pc.sendMessage(labelMsg);
+
+        //If isBos is true, label download is done along the LSP, send PCEP update message.
+        if (isBos) {
+            sendPcepUpdateMsg(pc, lspObj, tunnel);
+        }
+    }
+
+   //Sends PCEP update message.
+   private void sendPcepUpdateMsg(PcepClient pc, PcepLspObject lspObj, Tunnel tunnel) throws PcepParseException {
+       LinkedList<PcepUpdateRequest> updateRequestList = new LinkedList<>();
+       LinkedList<PcepValueType> subObjects = createEroSubObj(tunnel.path());
+
+       if (subObjects == null) {
+           log.error("ERO subjects not present");
+           return;
+       }
+
+       // set PathSetupTypeTlv of SRP object
+       LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+       LspType lspSigType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
+       llOptionalTlv.add(new PathSetupTypeTlv(lspSigType.type()));
+
+       PcepSrpObject srpObj = pc.factory().buildSrpObject()
+                              .setRFlag(false)
+                              .setSrpID(SrpIdGenerators.create())
+                              .setOptionalTlv(llOptionalTlv)
+                              .build();
+
+       PcepEroObject eroObj = pc.factory().buildEroObject()
+                             .setSubObjects(subObjects)
+                             .build();
+
+       float  iBandwidth = 0;
+       if (tunnel.annotations().value(BANDWIDTH) != null) {
+           //iBandwidth = Float.floatToIntBits(Float.parseFloat(tunnel.annotations().value(BANDWIDTH)));
+           iBandwidth = Float.parseFloat(tunnel.annotations().value(BANDWIDTH));
+       }
+       // build bandwidth object
+       PcepBandwidthObject bandwidthObject = pc.factory().buildBandwidthObject()
+                                             .setBandwidth(iBandwidth)
+                                             .build();
+       // build pcep attribute
+       PcepAttribute pcepAttribute = pc.factory().buildPcepAttribute()
+                                     .setBandwidthObject(bandwidthObject)
+                                     .build();
+
+       PcepMsgPath msgPath = pc.factory().buildPcepMsgPath()
+                             .setEroObject(eroObj)
+                             .setPcepAttribute(pcepAttribute)
+                             .build();
+
+       PcepUpdateRequest updateReq = pc.factory().buildPcepUpdateRequest()
+                                    .setSrpObject(srpObj)
+                                    .setMsgPath(msgPath)
+                                    .setLspObject(lspObj)
+                                    .build();
+
+       updateRequestList.add(updateReq);
+
+       //TODO: P = 1 is it P flag in PCEP obj header
+       PcepUpdateMsg updateMsg = pc.factory().buildUpdateMsg()
+                                 .setUpdateRequestList(updateRequestList)
+                                 .build();
+
+       pc.sendMessage(updateMsg);
+   }
+
+   private LinkedList<PcepValueType> createEroSubObj(Path path) {
+       LinkedList<PcepValueType> subObjects = new LinkedList<>();
+       List<Link> links = path.links();
+       ConnectPoint source = null;
+       ConnectPoint destination = null;
+       IpAddress ipDstAddress = null;
+       IpAddress ipSrcAddress = null;
+       PcepValueType subObj = null;
+       long portNo;
+
+       for (Link link : links) {
+           source = link.src();
+           if (!(source.equals(destination))) {
+               //set IPv4SubObject for ERO object
+               portNo = source.port().toLong();
+               portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
+               ipSrcAddress = Ip4Address.valueOf((int) portNo);
+               subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
+               subObjects.add(subObj);
+           }
+
+           destination = link.dst();
+           portNo = destination.port().toLong();
+           portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
+           ipDstAddress = Ip4Address.valueOf((int) portNo);
+           subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
+           subObjects.add(subObj);
+       }
+       return subObjects;
+   }
+
+   private PcepSrpObject getSrpObject(PcepClient pc, PcepLabelOp type, boolean bSFlag)
+           throws PcepParseException {
+       PcepSrpObject srpObj;
+       boolean bRFlag = false;
+
+       if (!type.equals(PcepLabelOp.ADD)) {
+           // To cleanup labels, R bit is set
+           bRFlag = true;
+       }
+
+       srpObj = pc.factory().buildSrpObject()
+               .setRFlag(bRFlag)
+               .setSFlag(bSFlag)
+               .setSrpID(SrpIdGenerators.create())
+               .build();
+
+       return srpObj;
+   }
+
+   /**
+    * Returns PCEP client.
+    *
+    * @return PCEP client
+    */
+   private PcepClient getPcepClient(DeviceId deviceId) {
+       Device device = deviceService.getDevice(deviceId);
+
+       // In future projections instead of annotations will be used to fetch LSR ID.
+       String lsrId = device.annotations().value(LSRID);
+       PcepClient pcc = clientController.getClient(PccId.pccId(IpAddress.valueOf(lsrId)));
+       return pcc;
+   }
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/LabelType.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/LabelType.java
new file mode 100644
index 0000000..133011d
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/LabelType.java
@@ -0,0 +1,52 @@
+/*
+ * 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.pcep.controller.impl;
+
+/**
+ * Describes about Label type.
+ */
+public enum LabelType {
+    /**
+     * Signifies in label id of a device.
+     */
+    OUT_LABEL(0),
+
+    /**
+     * Signifies out label id of a device.
+     */
+    IN_LABEL(1);
+
+    int value;
+
+    /**
+     * Assign val with the value as the Label type.
+     *
+     * @param val Label type
+     */
+    LabelType(int val) {
+        value = val;
+    }
+
+    /**
+     * Returns value of Label type.
+     *
+     * @return label type
+     */
+    public byte type() {
+        return (byte) value;
+    }
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PceccSrTeBeHandler.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PceccSrTeBeHandler.java
new file mode 100644
index 0000000..f6fe132
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PceccSrTeBeHandler.java
@@ -0,0 +1,584 @@
+/*
+ * 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.pcep.controller.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+import org.onlab.packet.IpAddress;
+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.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+import org.onosproject.incubator.net.tunnel.DefaultLabelStack;
+import org.onosproject.incubator.net.tunnel.LabelStack;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.pcelabelstore.PcepLabelOp;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepClientController;
+import org.onosproject.pcep.controller.SrpIdGenerators;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepFecObjectIPv4;
+import org.onosproject.pcepio.protocol.PcepFecObjectIPv4Adjacency;
+import org.onosproject.pcepio.protocol.PcepLabelObject;
+import org.onosproject.pcepio.protocol.PcepLabelUpdate;
+import org.onosproject.pcepio.protocol.PcepLabelUpdateMsg;
+import org.onosproject.pcepio.protocol.PcepSrpObject;
+import org.onosproject.pcepio.types.PcepLabelMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * PCE SR-BE and SR-TE functionality.
+ * SR-BE: Each node (PCC) is allocated a node-SID (label) by the PCECC. The PCECC sends PCLabelUpd to
+ * update the label map of each node to all the nodes in the domain.
+ * SR-TE: apart from node-SID, Adj-SID is used where each adjacency is allocated an Adj-SID (label) by the PCECC.
+ * The PCECC sends PCLabelUpd to update the label map of each Adj to the corresponding nodes in the domain.
+ */
+public final class PceccSrTeBeHandler {
+    private static final Logger log = LoggerFactory.getLogger(PceccSrTeBeHandler.class);
+
+    private static final String LABEL_RESOURCE_ADMIN_SERVICE_NULL = "Label Resource Admin Service cannot be null";
+    private static final String LABEL_RESOURCE_SERVICE_NULL = "Label Resource Service cannot be null";
+    private static final String PCE_STORE_NULL = "PCE Store cannot be null";
+    private static final String DEVICE_ID_NULL = "Device-Id cannot be null";
+    private static final String LSR_ID_NULL = "LSR-Id cannot be null";
+    private static final String LINK_NULL = "Link cannot be null";
+    private static final String PATH_NULL = "Path cannot be null";
+    private static final String LSR_ID = "lsrId";
+    private static PceccSrTeBeHandler srTeHandlerInstance = null;
+    private LabelResourceAdminService labelRsrcAdminService;
+    private LabelResourceService labelRsrcService;
+    private DeviceService deviceService;
+    private PcepClientController clientController;
+    private PceLabelStore pceStore;
+
+    /**
+     * Initializes default values.
+     */
+    private PceccSrTeBeHandler() {
+    }
+
+    /**
+     * Returns single instance of this class.
+     *
+     * @return this class single instance
+     */
+    public static PceccSrTeBeHandler getInstance() {
+        if (srTeHandlerInstance == null) {
+            srTeHandlerInstance = new PceccSrTeBeHandler();
+        }
+        return srTeHandlerInstance;
+    }
+
+    /**
+     * Initialization of label manager interfaces and pce store.
+     *
+     * @param labelRsrcAdminService label resource admin service
+     * @param labelRsrcService label resource service
+     * @param pceStore PCE label store
+     * @param deviceService device service
+     */
+    public void initialize(LabelResourceAdminService labelRsrcAdminService,
+                           LabelResourceService labelRsrcService,
+                           PcepClientController clientController,
+                           PceLabelStore pceStore,
+                           DeviceService deviceService) {
+        this.labelRsrcAdminService = labelRsrcAdminService;
+        this.labelRsrcService = labelRsrcService;
+        this.clientController = clientController;
+        this.pceStore = pceStore;
+        this.deviceService = deviceService;
+    }
+
+    /**
+     * Reserves the global label pool.
+     *
+     * @param beginLabel minimum value of global label space
+     * @param endLabel maximum value of global label space
+     * @return success or failure
+     */
+    public boolean reserveGlobalPool(long beginLabel, long endLabel) {
+        checkNotNull(labelRsrcAdminService, LABEL_RESOURCE_ADMIN_SERVICE_NULL);
+        return labelRsrcAdminService.createGlobalPool(LabelResourceId.labelResourceId(beginLabel),
+                                                      LabelResourceId.labelResourceId(endLabel));
+    }
+
+    /**
+     * Retrieve lsr-id from device annotation.
+     *
+     * @param deviceId specific device id from which lsr-id needs to be retrieved
+     * @return lsr-id of a device
+     */
+    public String getLsrId(DeviceId deviceId) {
+        checkNotNull(deviceId, DEVICE_ID_NULL);
+        Device device = deviceService.getDevice(deviceId);
+        if (device == null) {
+            log.debug("Device is not available for device id {} in device service.", deviceId.toString());
+            return null;
+        }
+
+        // Retrieve lsr-id from device
+        if (device.annotations() == null) {
+            log.debug("Device {} does not have annotation.", device.toString());
+            return null;
+        }
+
+        String lsrId = device.annotations().value(LSR_ID);
+        if (lsrId == null) {
+            log.debug("The lsr-id of device {} is null.", device.toString());
+            return null;
+        }
+        return lsrId;
+    }
+
+    /**
+     * Allocates node label from global node label pool to specific device.
+     * Configure this device with labels and lsrid mapping of all other devices and vice versa.
+     *
+     * @param specificDeviceId node label needs to be allocated to specific device
+     * @param specificLsrId lsrid of specific device
+     * @return success or failure
+     */
+    public boolean allocateNodeLabel(DeviceId specificDeviceId, String specificLsrId) {
+        long applyNum = 1; // For each node only one node label
+        LabelResourceId specificLabelId = null;
+
+        checkNotNull(specificDeviceId, DEVICE_ID_NULL);
+        checkNotNull(specificLsrId, LSR_ID_NULL);
+        checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
+        checkNotNull(pceStore, PCE_STORE_NULL);
+
+        // Check whether node-label was already configured for this specific device.
+        if (pceStore.getGlobalNodeLabel(specificDeviceId) != null) {
+            log.debug("Node label was already configured for device {}.", specificDeviceId.toString());
+            return false;
+        }
+
+        // The specificDeviceId is the new device and is not there in the pce store.
+        // So, first generate its label and configure label and its lsr-id to it.
+        Collection<LabelResource> result = labelRsrcService.applyFromGlobalPool(applyNum);
+        if (result.size() > 0) {
+            // Only one element (label-id) to retrieve
+            Iterator<LabelResource> iterator = result.iterator();
+            DefaultLabelResource defaultLabelResource = (DefaultLabelResource) iterator.next();
+            specificLabelId = defaultLabelResource.labelResourceId();
+            if (specificLabelId == null) {
+                log.error("Unable to retrieve global node label for a device id {}.", specificDeviceId.toString());
+                return false;
+            }
+        } else {
+            log.error("Unable to allocate global node label for a device id {}.", specificDeviceId.toString());
+            return false;
+        }
+
+        // store it
+        pceStore.addGlobalNodeLabel(specificDeviceId, specificLabelId);
+
+        // Push its label information into specificDeviceId
+        PcepClient pcc = getPcepClient(specificDeviceId);
+        try {
+            pushGlobalNodeLabel(pcc,
+                                specificLabelId,
+                                IpAddress.valueOf(specificLsrId).getIp4Address().toInt(),
+                                PcepLabelOp.ADD,
+                                false);
+        } catch (PcepParseException e) {
+            log.error("Failed to push global node label for LSR {}.", specificLsrId.toString());
+        }
+
+        // Configure (node-label, lsr-id) mapping of each devices into specific device and vice versa.
+        for (Map.Entry<DeviceId, LabelResourceId> element : pceStore.getGlobalNodeLabels().entrySet()) {
+            DeviceId otherDevId = element.getKey();
+
+            // Get lsr-id of a device
+            String otherLsrId = getLsrId(otherDevId);
+            if (otherLsrId == null) {
+                log.error("The lsr-id of device id {} is null.", otherDevId.toString());
+                releaseNodeLabel(specificDeviceId, specificLsrId);
+                return false;
+            }
+
+            // Push to device
+            // Push label information of specificDeviceId to otherDevId in list and vice versa.
+            if (!otherDevId.equals(specificDeviceId)) {
+                try {
+                    pushGlobalNodeLabel(getPcepClient(otherDevId),
+                                        specificLabelId,
+                                        IpAddress.valueOf(specificLsrId).getIp4Address().toInt(),
+                                        PcepLabelOp.ADD,
+                                        false);
+
+                    pushGlobalNodeLabel(pcc, specificLabelId,
+                                        IpAddress.valueOf(otherLsrId).getIp4Address().toInt(),
+                                        PcepLabelOp.ADD,
+                                        false);
+                } catch (PcepParseException e) {
+                    log.error("Failed to push global node label for LSR {} or LSR {}.", specificLsrId.toString(),
+                              otherLsrId.toString());
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Releases assigned node label of specific device from global node label pool and pce store.
+     * and remove configured this node label from all other devices.
+     *
+     * @param specificDeviceId node label needs to be released for specific device
+     * @param specificLsrId lsrid of specific device
+     * @return success or failure
+     */
+    public boolean releaseNodeLabel(DeviceId specificDeviceId, String specificLsrId) {
+        checkNotNull(specificDeviceId, DEVICE_ID_NULL);
+        checkNotNull(specificLsrId, LSR_ID_NULL);
+        checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
+        checkNotNull(pceStore, PCE_STORE_NULL);
+        boolean retValue = true;
+
+        // Release node label entry of this specific device from all other devices
+        // Retrieve node label of this specific device from store
+        LabelResourceId labelId = pceStore.getGlobalNodeLabel(specificDeviceId);
+        if (labelId == null) {
+            log.error("Unable to retrieve label of a device id {} from store.", specificDeviceId.toString());
+            return false;
+        }
+
+        // Go through all devices in the pce store and remove label entry from device
+        for (Map.Entry<DeviceId, LabelResourceId> element : pceStore.getGlobalNodeLabels().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)) {
+                try {
+                    pushGlobalNodeLabel(getPcepClient(otherDevId),
+                                        labelId,
+                                        IpAddress.valueOf(specificLsrId).getIp4Address().toInt(),
+                                        PcepLabelOp.REMOVE,
+                                        false);
+                } catch (PcepParseException e) {
+                    log.error("Failed to push global node label for LSR {}.", specificLsrId.toString());
+                }
+            }
+        }
+
+        // Release from label manager
+        Set<LabelResourceId> release = new HashSet<>();
+        release.add(labelId);
+        if (!labelRsrcService.releaseToGlobalPool(release)) {
+            log.error("Unable to release label id {} from label manager.", labelId.toString());
+            retValue = false;
+        }
+
+        // Remove from store
+        if (!pceStore.removeGlobalNodeLabel(specificDeviceId)) {
+            log.error("Unable to remove global node label id {} from store.", labelId.toString());
+            retValue = false;
+        }
+        return retValue;
+    }
+
+    /**
+     * Allocates adjacency label to a link from local resource pool by a specific device id.
+     *
+     * @param link between devices
+     * @return success or failure
+     */
+    public boolean allocateAdjacencyLabel(Link link) {
+        long applyNum = 1; // Single label to each link.
+        DeviceId srcDeviceId = link.src().deviceId();
+        Collection<LabelResource> labelList;
+
+        checkNotNull(link, LINK_NULL);
+        checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
+        checkNotNull(pceStore, PCE_STORE_NULL);
+
+        // Checks whether adjacency label was already allocated
+        LabelResourceId labelId = pceStore.getAdjLabel(link);
+        if (labelId != null) {
+            log.debug("Adjacency label {} was already allocated for a link {}.", labelId.toString(), link.toString());
+            return false;
+        }
+
+        // Allocate adjacency label to a link from label manager.
+        // Take label from source device pool to allocate.
+        labelList = labelRsrcService.applyFromDevicePool(srcDeviceId, applyNum);
+        if (labelList.size() <= 0) {
+            log.error("Unable to allocate label to a device id {}.", srcDeviceId.toString());
+            return false;
+        }
+
+        // Currently only one label to a device. So, no need to iterate through list
+        Iterator<LabelResource> iterator = labelList.iterator();
+        DefaultLabelResource defaultLabelResource = (DefaultLabelResource) iterator.next();
+        labelId = defaultLabelResource.labelResourceId();
+        if (labelId == null) {
+            log.error("Unable to allocate label to a device id {}.", srcDeviceId.toString());
+            return false;
+        }
+        log.debug("Allocated adjacency label {} to a link {}.", labelId.toString(), link.toString());
+
+        // Push adjacency label to device
+        try {
+            pushAdjacencyLabel(getPcepClient(srcDeviceId), labelId, (int) link.src().port().toLong(),
+                               (int) link.dst().port().toLong(), PcepLabelOp.ADD);
+        } catch (PcepParseException e) {
+            log.error("Failed to push adjacency label for link {}-{}.", (int) link.src().port().toLong(),
+                      (int) link.dst().port().toLong());
+        }
+
+        // Save in store
+        pceStore.addAdjLabel(link, labelId);
+        return true;
+    }
+
+    /**
+      * Releases unused adjacency labels from device pools.
+      *
+      * @param link between devices
+      * @return success or failure
+      */
+    public boolean releaseAdjacencyLabel(Link link) {
+        checkNotNull(link, LINK_NULL);
+        checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
+        checkNotNull(pceStore, PCE_STORE_NULL);
+        boolean retValue = true;
+
+        // Retrieve link label from store
+        LabelResourceId labelId = pceStore.getAdjLabel(link);
+        if (labelId == null) {
+            log.error("Unabel to retrieve label for a link {} from store.", link.toString());
+            return false;
+        }
+
+        // Device
+        DeviceId srcDeviceId = link.src().deviceId();
+
+        // Release adjacency label from device
+        try {
+            pushAdjacencyLabel(getPcepClient(srcDeviceId), labelId, (int) link.src().port().toLong(),
+                               (int) link.dst().port().toLong(), PcepLabelOp.REMOVE);
+        } catch (PcepParseException e) {
+            log.error("Failed to push adjacency label for link {}-{}.", (int) link.src().port().toLong(),
+                      (int) link.dst().port().toLong());
+        }
+
+
+        // Release link label from label manager
+        Multimap<DeviceId, LabelResource> release = ArrayListMultimap.create();
+        DefaultLabelResource defaultLabelResource = new DefaultLabelResource(srcDeviceId, labelId);
+        release.put(srcDeviceId, defaultLabelResource);
+        if (!labelRsrcService.releaseToDevicePool(release)) {
+            log.error("Unable to release label id {} from label manager.", labelId.toString());
+            retValue = false;
+        }
+
+        // Remove adjacency label from store
+        if (!pceStore.removeAdjLabel(link)) {
+            log.error("Unable to remove adjacency label id {} from store.", labelId.toString());
+            retValue = false;
+        }
+        return retValue;
+    }
+
+    /**
+     * Computes label stack for a path.
+     *
+     * @param path lsp path
+     * @return label stack
+     */
+    public LabelStack computeLabelStack(Path path) {
+        checkNotNull(path, PATH_NULL);
+        // Label stack is linked list to make labels in order.
+        List<LabelResourceId> labelStack = new LinkedList<>();
+        List<Link> linkList = path.links();
+        if ((linkList != null) && (linkList.size() > 0)) {
+            // Path: [x] ---- [y] ---- [z]
+            // For other than last link, add only source[x] device label.
+            // For the last link, add both source[y] and destination[z] device labels.
+            // For all links add adjacency label
+            Link link = null;
+            LabelResourceId nodeLabelId = null;
+            LabelResourceId adjLabelId = null;
+            DeviceId deviceId = null;
+            for (Iterator<Link> iterator = linkList.iterator(); iterator.hasNext();) {
+                link = iterator.next();
+                // Add adjacency label for this link
+                adjLabelId = pceStore.getAdjLabel(link);
+                if (adjLabelId == null) {
+                    log.error("Adjacency label id is null for a link {}.", link.toString());
+                    return null;
+                }
+                labelStack.add(adjLabelId);
+
+                deviceId = link.dst().deviceId();
+                nodeLabelId = pceStore.getGlobalNodeLabel(deviceId);
+                if (nodeLabelId == null) {
+                    log.error("Unable to find node label for a device id {} in store.", deviceId.toString());
+                    return null;
+                }
+                labelStack.add(nodeLabelId);
+            }
+        } else {
+            log.debug("Empty link in path.");
+            return null;
+        }
+        return new DefaultLabelStack(labelStack);
+    }
+
+    //Pushes node labels to the specified device.
+    void pushGlobalNodeLabel(PcepClient pc, LabelResourceId labelId,
+            int labelForNode, PcepLabelOp type, boolean isBos) throws PcepParseException {
+
+        checkNotNull(pc);
+        checkNotNull(labelId);
+        checkNotNull(type);
+
+        LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
+        PcepFecObjectIPv4 fecObject = pc.factory().buildFecObjectIpv4()
+                                      .setNodeID(labelForNode)
+                                      .build();
+
+        boolean bSFlag = false;
+        if (pc.labelDbSyncStatus() == IN_SYNC && !isBos) {
+            // Need to set sync flag in all messages till sync completes.
+            bSFlag = true;
+        }
+
+        PcepSrpObject srpObj = getSrpObject(pc, type, bSFlag);
+
+        //Global NODE-SID as label object
+        PcepLabelObject labelObject = pc.factory().buildLabelObject()
+                                      .setLabel((int) labelId.labelId())
+                                      .build();
+
+        PcepLabelMap labelMap = new PcepLabelMap();
+        labelMap.setFecObject(fecObject);
+        labelMap.setLabelObject(labelObject);
+        labelMap.setSrpObject(srpObj);
+
+        labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
+                            .setLabelMap(labelMap)
+                            .build());
+
+        PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
+                                      .setPcLabelUpdateList(labelUpdateList)
+                                      .build();
+        pc.sendMessage(labelMsg);
+
+        if (isBos) {
+            // Sync is completed.
+            pc.setLabelDbSyncStatus(SYNCED);
+        }
+    }
+
+    //Pushes adjacency labels to the specified device.
+    void pushAdjacencyLabel(PcepClient pc, LabelResourceId labelId, int srcPortNo,
+                                    int dstPortNo, PcepLabelOp type)
+            throws PcepParseException {
+
+        checkNotNull(pc);
+        checkNotNull(labelId);
+        checkNotNull(type);
+
+        LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
+        PcepFecObjectIPv4Adjacency fecAdjObject = pc.factory().buildFecIpv4Adjacency()
+                                                  .seRemoteIPv4Address(dstPortNo)
+                                                  .seLocalIPv4Address(srcPortNo)
+                                                  .build();
+
+        boolean bSFlag = false;
+        if (pc.labelDbSyncStatus() == IN_SYNC) {
+            // Need to set sync flag in all messages till sync completes.
+            bSFlag = true;
+        }
+
+        PcepSrpObject srpObj = getSrpObject(pc, type, bSFlag);
+
+        //Adjacency label object
+        PcepLabelObject labelObject = pc.factory().buildLabelObject()
+                                      .setLabel((int) labelId.labelId())
+                                      .build();
+
+        PcepLabelMap labelMap = new PcepLabelMap();
+        labelMap.setFecObject(fecAdjObject);
+        labelMap.setLabelObject(labelObject);
+        labelMap.setSrpObject(srpObj);
+
+        labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
+                            .setLabelMap(labelMap)
+                            .build());
+
+        PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
+                                      .setPcLabelUpdateList(labelUpdateList)
+                                      .build();
+        pc.sendMessage(labelMsg);
+    }
+
+    private PcepSrpObject getSrpObject(PcepClient pc, PcepLabelOp type, boolean bSFlag)
+            throws PcepParseException {
+        PcepSrpObject srpObj;
+        boolean bRFlag = false;
+
+        if (!type.equals(PcepLabelOp.ADD)) {
+            // To cleanup labels, R bit is set
+            bRFlag = true;
+        }
+
+        srpObj = pc.factory().buildSrpObject()
+                .setRFlag(bRFlag)
+                .setSFlag(bSFlag)
+                .setSrpID(SrpIdGenerators.create())
+                .build();
+
+        return srpObj;
+    }
+
+    /**
+     * Returns PCEP client.
+     *
+     * @return PCEP client
+     */
+    private PcepClient getPcepClient(DeviceId deviceId) {
+        Device device = deviceService.getDevice(deviceId);
+
+        // In future projections instead of annotations will be used to fetch LSR ID.
+        String lsrId = device.annotations().value(LSR_ID);
+        PcepClient pcc = clientController.getClient(PccId.pccId(IpAddress.valueOf(lsrId)));
+        return pcc;
+    }
+}
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
index f1458ab..3a1c74c 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
@@ -26,6 +26,7 @@
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -34,12 +35,40 @@
 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.Ip4Address;
+import org.onlab.packet.IpAddress;
+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.incubator.net.tunnel.DefaultLabelStack;
+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.TunnelService;
 import org.onosproject.incubator.net.tunnel.Tunnel.State;
+import org.onosproject.mastership.MastershipService;
+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.MastershipRole;
+import org.onosproject.net.Path;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.link.LinkListener;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.pcelabelstore.PcepLabelOp;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+import org.onosproject.pcep.api.DeviceCapability;
 import org.onosproject.pcep.controller.LspKey;
+import org.onosproject.pcep.controller.LspType;
 import org.onosproject.pcep.controller.PccId;
 import org.onosproject.pcep.controller.PcepClient;
 import org.onosproject.pcep.controller.PcepClientController;
@@ -47,8 +76,6 @@
 import org.onosproject.pcep.controller.PcepEventListener;
 import org.onosproject.pcep.controller.PcepLspStatus;
 import org.onosproject.pcep.controller.PcepNodeListener;
-import org.onosproject.pcep.controller.PcepPacketListener;
-import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcep.controller.SrpIdGenerators;
 import org.onosproject.pcep.controller.driver.PcepAgent;
 import org.onosproject.pcepio.exceptions.PcepParseException;
@@ -61,10 +88,15 @@
 import org.onosproject.pcepio.protocol.PcepInitiateMsg;
 import org.onosproject.pcepio.protocol.PcepLspObject;
 import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepNai;
 import org.onosproject.pcepio.protocol.PcepReportMsg;
 import org.onosproject.pcepio.protocol.PcepSrpObject;
 import org.onosproject.pcepio.protocol.PcepStateReport;
+import org.onosproject.pcepio.types.PathSetupTypeTlv;
+import org.onosproject.pcepio.types.PcepNaiIpv4Adjacency;
+import org.onosproject.pcepio.types.PcepNaiIpv4NodeId;
 import org.onosproject.pcepio.types.PcepValueType;
+import org.onosproject.pcepio.types.SrEroSubObject;
 import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
 import org.onosproject.pcepio.types.SymbolicPathNameTlv;
 import org.slf4j.Logger;
@@ -74,11 +106,23 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.controller.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
+import static org.onosproject.pcep.controller.LspType.WITH_SIGNALLING;
 import static org.onosproject.pcep.controller.PcepLspSyncAction.REMOVE;
 import static org.onosproject.pcep.controller.PcepLspSyncAction.SEND_UPDATE;
 import static org.onosproject.pcep.controller.PcepLspSyncAction.UNSTABLE;
 import static org.onosproject.pcepio.types.PcepErrorDetailInfo.ERROR_TYPE_19;
 import static org.onosproject.pcepio.types.PcepErrorDetailInfo.ERROR_VALUE_5;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.BANDWIDTH;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.LOCAL_LSP_ID;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.LSP_SIG_TYPE;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.PCC_TUNNEL_ID;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.PCE_INIT;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.PLSP_ID;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.DELEGATE;
+import static org.onosproject.pcep.controller.PcepAnnotationKeys.COST_TYPE;
+import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
+import static org.onosproject.pcep.controller.PcepSyncStatus.NOT_SYNCED;
 
 /**
  * Implementation of PCEP client controller.
@@ -88,10 +132,33 @@
 public class PcepClientControllerImpl implements PcepClientController {
 
     private static final Logger log = LoggerFactory.getLogger(PcepClientControllerImpl.class);
+    private static final long IDENTIFIER_SET = 0x100000000L;
+    private static final long SET = 0xFFFFFFFFL;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkService linkService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TunnelService tunnelService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigService netCfgService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected MastershipService mastershipService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LabelResourceAdminService labelRsrcAdminService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LabelResourceService labelRsrcService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PceLabelStore pceStore;
+
     protected ConcurrentHashMap<PccId, PcepClient> connectedClients =
             new ConcurrentHashMap<>();
 
@@ -100,25 +167,44 @@
 
     protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
     protected Set<PcepNodeListener> pcepNodeListener = Sets.newHashSet();
-    protected Set<PcepPacketListener> pcepPacketListener = Sets.newHashSet();
+
+    // LSR-id and device-id mapping for checking capability if L3 device is not
+    // having its capability
+    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
 
     private final Controller ctrl = new Controller();
+    public static final long GLOBAL_LABEL_SPACE_MIN = 4097;
+    public static final long GLOBAL_LABEL_SPACE_MAX = 5121;
+    private static final String LSRID = "lsrId";
+    private static final String DEVICE_NULL = "Device-cannot be null";
+    private static final String LINK_NULL = "Link-cannot be null";
 
-    public static final String BANDWIDTH = "bandwidth";
-    public static final String LSP_SIG_TYPE = "lspSigType";
-    public static final String PCC_TUNNEL_ID = "PccTunnelId";
-    public static final String PLSP_ID = "PLspId";
-    public static final String LOCAL_LSP_ID = "localLspId";
-    public static final String PCE_INIT = "pceInit";
-    public static final String COST_TYPE = "costType";
-    public static final String DELEGATE = "delegation";
+    private BasicPceccHandler crHandler;
+    private PceccSrTeBeHandler srTeHandler;
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected TunnelService tunnelService;
+    private DeviceListener deviceListener = new InternalDeviceListener();
+    private LinkListener linkListener = new InternalLinkListener();
+    private InternalConfigListener cfgListener = new InternalConfigListener();
 
     @Activate
     public void activate() {
         ctrl.start(agent);
+        crHandler = BasicPceccHandler.getInstance();
+        crHandler.initialize(labelRsrcService, deviceService, pceStore, this);
+
+        srTeHandler = PceccSrTeBeHandler.getInstance();
+        srTeHandler.initialize(labelRsrcAdminService, labelRsrcService, this, pceStore,
+                               deviceService);
+
+        deviceService.addListener(deviceListener);
+        linkService.addListener(linkListener);
+        netCfgService.addListener(cfgListener);
+
+        // Reserve global node pool
+        if (!srTeHandler.reserveGlobalPool(GLOBAL_LABEL_SPACE_MIN, GLOBAL_LABEL_SPACE_MAX)) {
+            log.debug("Global node pool was already reserved.");
+        }
+
         log.info("Started");
     }
 
@@ -126,6 +212,9 @@
     public void deactivate() {
         // Close all connected clients
         closeConnectedClients();
+        deviceService.removeListener(deviceListener);
+        linkService.removeListener(linkListener);
+        netCfgService.removeListener(cfgListener);
         ctrl.stop();
         log.info("Stopped");
     }
@@ -163,16 +252,6 @@
     }
 
     @Override
-    public void addPacketListener(PcepPacketListener listener) {
-        pcepPacketListener.add(listener);
-    }
-
-    @Override
-    public void removePacketListener(PcepPacketListener listener) {
-        pcepPacketListener.remove(listener);
-    }
-
-    @Override
     public void writeMessage(PccId pccId, PcepMessage msg) {
         this.getClient(pccId).sendMessage(msg);
     }
@@ -239,10 +318,10 @@
                     PcepStateReport stateRpt = listIterator.next();
                     PcepLspObject lspObj = stateRpt.getLspObject();
                     if (lspObj.getSFlag()) {
-                        if (pc.lspDbSyncStatus() != PcepSyncStatus.IN_SYNC) {
+                        if (pc.lspDbSyncStatus() != IN_SYNC) {
                             log.debug("LSP DB sync started for PCC {}", pc.getPccId().id().toString());
                             // Initialize LSP DB sync and temporary cache.
-                            pc.setLspDbSyncStatus(PcepSyncStatus.IN_SYNC);
+                            pc.setLspDbSyncStatus(IN_SYNC);
                             pc.initializeSyncMsgList(pccId);
                         }
                         // Store stateRpt in temporary cache.
@@ -251,18 +330,24 @@
                         // Don't send to provider as of now.
                         continue;
                     } else if (lspObj.getPlspId() == 0) {
-                        if (pc.lspDbSyncStatus() == PcepSyncStatus.IN_SYNC
-                                || pc.lspDbSyncStatus() == PcepSyncStatus.NOT_SYNCED) {
+                        if (pc.lspDbSyncStatus() == IN_SYNC
+                                || pc.lspDbSyncStatus() == NOT_SYNCED) {
                             // Set end of LSPDB sync.
                             log.debug("LSP DB sync completed for PCC {}", pc.getPccId().id().toString());
-                            pc.setLspDbSyncStatus(PcepSyncStatus.SYNCED);
+                            pc.setLspDbSyncStatus(SYNCED);
 
                             // Call packet provider to initiate label DB sync (only if PCECC capable).
                             if (pc.capability().pceccCapability()) {
                                 log.debug("Trigger label DB sync for PCC {}", pc.getPccId().id().toString());
                                 pc.setLabelDbSyncStatus(IN_SYNC);
-                                for (PcepPacketListener l : pcepPacketListener) {
-                                    l.sendPacketIn(pccId);
+                                // Get lsrId of the PCEP client from the PCC ID. Session info is based on lsrID.
+                                String lsrId = String.valueOf(pccId.ipAddress());
+                                DeviceId pccDeviceId = DeviceId.deviceId(lsrId);
+                                try {
+                                    syncLabelDb(pccDeviceId);
+                                    pc.setLabelDbSyncStatus(SYNCED);
+                                } catch (PcepParseException e) {
+                                    log.error("Exception caught in sending label masg to PCC while in sync.");
                                 }
                             } else {
                                 // If label db sync is not to be done, handle end of LSPDB sync actions.
@@ -272,6 +357,27 @@
                         }
                     }
 
+                    PcepLspStatus pcepLspStatus = PcepLspStatus.values()[lspObj.getOFlag()];
+                    LspType lspType = getLspType(stateRpt.getSrpObject());
+
+                    // Download (or remove) labels for basic PCECC LSPs.
+                    if (lspType.equals(WITHOUT_SIGNALLING_AND_WITHOUT_SR)) {
+                        boolean isRemove = lspObj.getRFlag();
+                        Tunnel tunnel = null;
+
+                        if (isRemove || pcepLspStatus.equals(PcepLspStatus.GOING_UP)) {
+                            tunnel = getTunnel(lspObj);
+                        }
+
+                        if (tunnel != null) {
+                            if (isRemove) {
+                                crHandler.releaseLabel(tunnel);
+                            } else {
+                                crHandler.allocateLabel(tunnel);
+                            }
+                        }
+                    }
+
                     // It's a usual report message while sync is not undergoing. So process it immediately.
                     LinkedList<PcepStateReport> llPcRptList = new LinkedList<>();
                     llPcRptList.add(stateRpt);
@@ -300,6 +406,113 @@
         }
     }
 
+    private LspType getLspType(PcepSrpObject srpObj) {
+        LspType lspType = WITH_SIGNALLING;
+
+        if (null != srpObj) {
+            LinkedList<PcepValueType> llOptionalTlv = srpObj.getOptionalTlv();
+            ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
+
+            while (listIterator.hasNext()) {
+                PcepValueType tlv = listIterator.next();
+                switch (tlv.getType()) {
+                case PathSetupTypeTlv.TYPE:
+                    lspType = LspType.values()[Integer.valueOf(((PathSetupTypeTlv) tlv).getPst())];
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+        return lspType;
+    }
+
+    private Tunnel getTunnel(PcepLspObject lspObj) {
+        ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
+        StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv = null;
+        SymbolicPathNameTlv pathNameTlv = null;
+        Tunnel tunnel = null;
+        while (listTlvIterator.hasNext()) {
+            PcepValueType tlv = listTlvIterator.next();
+            switch (tlv.getType()) {
+            case StatefulIPv4LspIdentifiersTlv.TYPE:
+                ipv4LspIdenTlv = (StatefulIPv4LspIdentifiersTlv) tlv;
+                break;
+            case SymbolicPathNameTlv.TYPE:
+                pathNameTlv = (SymbolicPathNameTlv) tlv;
+                break;
+            default:
+                break;
+            }
+        }
+        /*
+         * Draft says: The LSP-IDENTIFIERS TLV MUST be included in the LSP object in PCRpt messages for
+         * RSVP-signaled LSPs. For ONOS PCECC implementation, it is mandatory.
+         */
+        if (ipv4LspIdenTlv == null) {
+            log.error("Stateful IPv4 identifier TLV is null in PCRpt msg.");
+            return null;
+        }
+        IpTunnelEndPoint tunnelEndPointSrc = IpTunnelEndPoint
+                .ipTunnelPoint(IpAddress.valueOf(ipv4LspIdenTlv.getIpv4IngressAddress()));
+        IpTunnelEndPoint tunnelEndPointDst = IpTunnelEndPoint
+                .ipTunnelPoint(IpAddress.valueOf(ipv4LspIdenTlv.getIpv4EgressAddress()));
+        Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnelEndPointSrc, tunnelEndPointDst);
+
+        for (Tunnel tunnelObj : tunnelQueryResult) {
+            if (tunnelObj.annotations().value(PLSP_ID) == null) {
+                /*
+                 * PLSP_ID is null while Tunnel is created at PCE and PCInit msg carries it as 0. It is allocated by
+                 * PCC and in that case it becomes the first PCRpt msg from PCC for this LSP, and hence symbolic
+                 * path name must be carried in the PCRpt msg. Draft says: The SYMBOLIC-PATH-NAME TLV "MUST" be
+                 * included in the LSP object in the LSP State Report (PCRpt) message when during a given PCEP
+                 * session an LSP is "first" reported to a PCE.
+                 */
+                if ((pathNameTlv != null)
+                        && Arrays.equals(tunnelObj.tunnelName().value().getBytes(), pathNameTlv.getValue())) {
+                    tunnel = tunnelObj;
+                    break;
+                }
+                continue;
+            }
+            if ((Integer.valueOf(tunnelObj.annotations().value(PLSP_ID)) == lspObj.getPlspId())) {
+                if ((Integer
+                        .valueOf(tunnelObj.annotations().value(LOCAL_LSP_ID)) == ipv4LspIdenTlv.getLspId())) {
+                    tunnel = tunnelObj;
+                    break;
+                }
+            }
+        }
+
+        if (tunnel == null || tunnel.annotations().value(PLSP_ID) != null) {
+            return tunnel;
+        }
+
+        // The returned tunnel is used just for filling values in Label message. So manipulate locally
+        // and return so that to allocate label, we don't need to wait for the tunnel in the "core"
+        // to be updated, as that depends on listener mechanism and there may be timing/multi-threading issues.
+        Builder annotationBuilder = DefaultAnnotations.builder();
+        annotationBuilder.set(BANDWIDTH, tunnel.annotations().value(BANDWIDTH));
+        annotationBuilder.set(COST_TYPE, tunnel.annotations().value(COST_TYPE));
+        annotationBuilder.set(LSP_SIG_TYPE, tunnel.annotations().value(LSP_SIG_TYPE));
+        annotationBuilder.set(PCE_INIT, tunnel.annotations().value(PCE_INIT));
+        annotationBuilder.set(DELEGATE, tunnel.annotations().value(DELEGATE));
+        annotationBuilder.set(PLSP_ID, String.valueOf(lspObj.getPlspId()));
+        annotationBuilder.set(PCC_TUNNEL_ID, String.valueOf(ipv4LspIdenTlv.getTunnelId()));
+        annotationBuilder.set(LOCAL_LSP_ID, tunnel.annotations().value(LOCAL_LSP_ID));
+
+        Tunnel updatedTunnel = new DefaultTunnel(tunnel.providerId(), tunnel.src(),
+                            tunnel.dst(), tunnel.type(),
+                            tunnel.state(), tunnel.groupId(),
+                            tunnel.tunnelId(),
+                            tunnel.tunnelName(),
+                            tunnel.path(),
+                            tunnel.resource(),
+                            annotationBuilder.build());
+
+        return updatedTunnel;
+    }
+
     @Override
     public void closeConnectedClients() {
         PcepClient pc;
@@ -337,6 +550,294 @@
         return errMsg;
     }
 
+    private boolean syncLabelDb(DeviceId deviceId) throws PcepParseException {
+        checkNotNull(deviceId);
+
+        DeviceId actualDevcieId = pceStore.getLsrIdDevice(deviceId.toString());
+        if (actualDevcieId == null) {
+            log.error("Device not available {}.", deviceId.toString());
+            pceStore.addPccLsr(deviceId);
+            return false;
+        }
+        PcepClient pc = connectedClients.get(PccId.pccId(IpAddress.valueOf(deviceId.toString())));
+
+        Device specificDevice = deviceService.getDevice(actualDevcieId);
+        if (specificDevice == null) {
+            log.error("Unable to find device for specific device id {}.", actualDevcieId.toString());
+            return false;
+        }
+
+        if (pceStore.getGlobalNodeLabel(actualDevcieId) != null) {
+            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.pushGlobalNodeLabel(pc, entry.getValue(),
+                                    IpAddress.valueOf(srcLsrId).getIp4Address().toInt(),
+                                    PcepLabelOp.ADD, false);
+            }
+
+            Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
+            for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
+                if (entry.getKey().src().deviceId().equals(actualDevcieId)) {
+                    srTeHandler.pushAdjacencyLabel(pc,
+                                       entry.getValue(),
+                                       (int) entry.getKey().src().port().toLong(),
+                                       (int) entry.getKey().dst().port().toLong(),
+                                       PcepLabelOp.ADD
+                                       );
+                }
+            }
+        }
+
+        srTeHandler.pushGlobalNodeLabel(pc, LabelResourceId.labelResourceId(0),
+                            0, PcepLabelOp.ADD, true);
+
+        log.debug("End of label DB sync for device {}", actualDevcieId);
+
+        if (mastershipService.getLocalRole(specificDevice.id()) == MastershipRole.MASTER) {
+            // Allocate node-label to this specific device.
+            allocateNodeLabel(specificDevice);
+
+            // Allocate adjacency label
+            Set<Link> links = linkService.getDeviceEgressLinks(specificDevice.id());
+            if (links != null) {
+                for (Link link : links) {
+                    allocateAdjacencyLabel(link);
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Allocates node label to specific device.
+     *
+     * @param specificDevice device to which node label needs to be allocated
+     */
+    public void allocateNodeLabel(Device specificDevice) {
+        checkNotNull(specificDevice, DEVICE_NULL);
+
+        DeviceId deviceId = specificDevice.id();
+
+        // Retrieve lsrId of a specific device
+        if (specificDevice.annotations() == null) {
+            log.debug("Device {} does not have annotations.", specificDevice.toString());
+            return;
+        }
+
+        String lsrId = specificDevice.annotations().value(LSRID);
+        if (lsrId == null) {
+            log.debug("Unable to retrieve lsr-id of a device {}.", specificDevice.toString());
+            return;
+        }
+
+        // Get capability config from netconfig
+        DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(lsrId), DeviceCapability.class);
+        if (cfg == null) {
+            log.error("Unable to find corresponding capability for a lsrd {} from NetConfig.", lsrId);
+            // Save info. When PCEP session is comes up then allocate node-label
+            lsrIdDeviceIdMap.put(lsrId, specificDevice.id());
+            return;
+        }
+
+        // Check whether device has SR-TE Capability
+        if (cfg.labelStackCap()) {
+            srTeHandler.allocateNodeLabel(deviceId, lsrId);
+        }
+    }
+
+    /**
+     * Releases node label of a specific device.
+     *
+     * @param specificDevice this device label and lsr-id information will be
+     *            released in other existing devices
+     */
+    public void releaseNodeLabel(Device specificDevice) {
+        checkNotNull(specificDevice, DEVICE_NULL);
+
+        DeviceId deviceId = specificDevice.id();
+
+        // Retrieve lsrId of a specific device
+        if (specificDevice.annotations() == null) {
+            log.debug("Device {} does not have annotations.", specificDevice.toString());
+            return;
+        }
+
+        String lsrId = specificDevice.annotations().value(LSRID);
+        if (lsrId == null) {
+            log.debug("Unable to retrieve lsr-id of a device {}.", specificDevice.toString());
+            return;
+        }
+
+        // Get capability config from netconfig
+        DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(lsrId), DeviceCapability.class);
+        if (cfg == null) {
+            log.error("Unable to find corresponding capabilty for a lsrd {} from NetConfig.", lsrId);
+            return;
+        }
+
+        // Check whether device has SR-TE Capability
+        if (cfg.labelStackCap()) {
+            if (!srTeHandler.releaseNodeLabel(deviceId, lsrId)) {
+                log.error("Unable to release node label for a device id {}.", deviceId.toString());
+            }
+        }
+    }
+
+    /**
+     * Allocates adjacency label for a link.
+     *
+     * @param link link
+     */
+    public void allocateAdjacencyLabel(Link link) {
+        checkNotNull(link, LINK_NULL);
+
+        Device specificDevice = deviceService.getDevice(link.src().deviceId());
+
+        // Retrieve lsrId of a specific device
+        if (specificDevice.annotations() == null) {
+            log.debug("Device {} does not have annotations.", specificDevice.toString());
+            return;
+        }
+
+        String lsrId = specificDevice.annotations().value(LSRID);
+        if (lsrId == null) {
+            log.debug("Unable to retrieve lsr-id of a device {}.", specificDevice.toString());
+            return;
+        }
+
+        // Get capability config from netconfig
+        DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(lsrId), DeviceCapability.class);
+        if (cfg == null) {
+            log.error("Unable to find corresponding capabilty for a lsrd {} from NetConfig.", lsrId);
+            // Save info. When PCEP session comes up then allocate adjacency
+            // label
+            if (lsrIdDeviceIdMap.get(lsrId) != null) {
+                lsrIdDeviceIdMap.put(lsrId, specificDevice.id());
+            }
+            return;
+        }
+
+        // Check whether device has SR-TE Capability
+        if (cfg.labelStackCap()) {
+            srTeHandler.allocateAdjacencyLabel(link);
+        }
+    }
+
+    /**
+     * Releases allocated adjacency label of a link.
+     *
+     * @param link link
+     */
+    public void releaseAdjacencyLabel(Link link) {
+        checkNotNull(link, LINK_NULL);
+
+        Device specificDevice = deviceService.getDevice(link.src().deviceId());
+
+        // Retrieve lsrId of a specific device
+        if (specificDevice.annotations() == null) {
+            log.debug("Device {} does not have annotations.", specificDevice.toString());
+            return;
+        }
+
+        String lsrId = specificDevice.annotations().value(LSRID);
+        if (lsrId == null) {
+            log.debug("Unable to retrieve lsr-id of a device {}.", specificDevice.toString());
+            return;
+        }
+
+        // Get capability config from netconfig
+        DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(lsrId), DeviceCapability.class);
+        if (cfg == null) {
+            log.error("Unable to find corresponding capabilty for a lsrd {} from NetConfig.", lsrId);
+            return;
+        }
+
+        // Check whether device has SR-TE Capability
+        if (cfg.labelStackCap()) {
+            if (!srTeHandler.releaseAdjacencyLabel(link)) {
+                log.error("Unable to release adjacency labels for a link {}.", link.toString());
+            }
+        }
+    }
+
+    @Override
+    public LabelStack computeLabelStack(Path path) {
+        return srTeHandler.computeLabelStack(path);
+    }
+
+    @Override
+    public boolean allocateLocalLabel(Tunnel tunnel) {
+        return crHandler.allocateLabel(tunnel);
+    }
+
+    /**
+     * Creates label stack for ERO object from network resource.
+     *
+     * @param labelStack
+     * @param path (hop list)
+     * @return list of ERO subobjects
+     */
+    @Override
+    public LinkedList<PcepValueType> createPcepLabelStack(DefaultLabelStack labelStack, Path path) {
+        checkNotNull(labelStack);
+
+        LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
+        Iterator<Link> links = path.links().iterator();
+        LabelResourceId label = null;
+        Link link = null;
+        PcepValueType subObj = null;
+        PcepNai nai = null;
+        Device dstNode = null;
+        long srcPortNo, dstPortNo;
+
+        ListIterator<LabelResourceId> labelListIterator = labelStack.labelResources().listIterator();
+        while (labelListIterator.hasNext()) {
+            label = labelListIterator.next();
+            link = links.next();
+
+            srcPortNo = link.src().port().toLong();
+            srcPortNo = ((srcPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? srcPortNo & SET : srcPortNo;
+
+            dstPortNo = link.dst().port().toLong();
+            dstPortNo = ((dstPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? dstPortNo & SET : dstPortNo;
+
+            nai = new PcepNaiIpv4Adjacency((int) srcPortNo, (int) dstPortNo);
+            subObj = new SrEroSubObject(PcepNaiIpv4Adjacency.ST_TYPE, false, false, false, true, (int) label.labelId(),
+                                        nai);
+            llSubObjects.add(subObj);
+
+            dstNode = deviceService.getDevice(link.dst().deviceId());
+            nai = new PcepNaiIpv4NodeId(Ip4Address.valueOf(dstNode.annotations().value(LSRID)).toInt());
+
+            if (!labelListIterator.hasNext()) {
+                log.error("Malformed label stack.");
+            }
+            label = labelListIterator.next();
+            subObj = new SrEroSubObject(PcepNaiIpv4NodeId.ST_TYPE, false, false, false, true, (int) label.labelId(),
+                                        nai);
+            llSubObjects.add(subObj);
+        }
+        return llSubObjects;
+    }
+
     /**
      * Implementation of an Pcep Agent which is responsible for
      * keeping track of connected clients and the state in which
@@ -370,7 +871,6 @@
                         + "connected client: pccIp {}. Aborting ..", pccId.toString());
                 return false;
             }
-
             return true;
         }
 
@@ -479,7 +979,7 @@
                 } else if (pathNameTlv != null) {
                     tunnel = preSyncLspDbByName.get(Arrays.toString(pathNameTlv.getValue()));
                     if (tunnel != null) {
-                        preSyncLspDbByName.remove(tunnel.tunnelName());
+                        preSyncLspDbByName.remove(tunnel.tunnelName().value());
                     }
                 }
 
@@ -566,4 +1066,130 @@
             }
         }
     }
+
+    /*
+     * Handle device events.
+     */
+    private class InternalDeviceListener implements DeviceListener {
+        @Override
+        public void event(DeviceEvent event) {
+            Device specificDevice = event.subject();
+            if (specificDevice == null) {
+                log.error("Unable to find device from device event.");
+                return;
+            }
+
+            switch (event.type()) {
+
+            case DEVICE_ADDED:
+                // Node-label allocation is being done during Label DB Sync.
+                // So, when device is detected, no need to do node-label
+                // allocation.
+                String lsrId = specificDevice.annotations().value(LSRID);
+                if (lsrId != null) {
+                    pceStore.addLsrIdDevice(lsrId, specificDevice.id());
+
+                    // Search in failed DB sync store. If found, trigger label DB sync.
+                    DeviceId pccDeviceId = DeviceId.deviceId(lsrId);
+                    if (pceStore.hasPccLsr(pccDeviceId)) {
+                        log.debug("Continue to perform label DB sync for device {}.", pccDeviceId.toString());
+                        try {
+                            syncLabelDb(pccDeviceId);
+                        } catch (PcepParseException e) {
+                            log.error("Exception caught in sending label masg to PCC while in sync.");
+                        }
+                        pceStore.removePccLsr(pccDeviceId);
+                    }
+                }
+                break;
+
+            case DEVICE_REMOVED:
+                // Release node-label
+                if (mastershipService.getLocalRole(specificDevice.id()) == MastershipRole.MASTER) {
+                    releaseNodeLabel(specificDevice);
+                }
+
+                if (specificDevice.annotations().value(LSRID) != null) {
+                    pceStore.removeLsrIdDevice(specificDevice.annotations().value(LSRID));
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+    /*
+     * Handle link events.
+     */
+    private class InternalLinkListener implements LinkListener {
+        @Override
+        public void event(LinkEvent event) {
+            Link link = event.subject();
+
+            switch (event.type()) {
+
+            case LINK_ADDED:
+                // Allocate adjacency label
+                if (mastershipService.getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
+                    allocateAdjacencyLabel(link);
+                }
+                break;
+
+            case LINK_REMOVED:
+                // Release adjacency label
+                if (mastershipService.getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
+                    releaseAdjacencyLabel(link);
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+    private class InternalConfigListener implements NetworkConfigListener {
+
+        @Override
+        public void event(NetworkConfigEvent event) {
+
+            if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED)
+                    && event.configClass().equals(DeviceCapability.class)) {
+
+                DeviceId deviceIdLsrId = (DeviceId) event.subject();
+                String lsrId = deviceIdLsrId.toString();
+                DeviceId deviceId = lsrIdDeviceIdMap.get(lsrId);
+                if (deviceId == null) {
+                    log.debug("Unable to find device id for a lsr-id {} from lsr-id and device-id map.", lsrId);
+                    return;
+                }
+
+                DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(lsrId), DeviceCapability.class);
+                if (cfg == null) {
+                    log.error("Unable to find corresponding capabilty for a lsrd {}.", lsrId);
+                    return;
+                }
+
+                if (cfg.labelStackCap()) {
+                    if (mastershipService.getLocalRole(deviceId) == MastershipRole.MASTER) {
+                        // Allocate node-label
+                        srTeHandler.allocateNodeLabel(deviceId, lsrId);
+
+                        // Allocate adjacency label to links which are
+                        // originated from this specific device id
+                        Set<Link> links = linkService.getDeviceEgressLinks(deviceId);
+                        for (Link link : links) {
+                            if (!srTeHandler.allocateAdjacencyLabel(link)) {
+                                return;
+                            }
+                        }
+                    }
+                }
+                // Remove lsrId info from map
+                lsrIdDeviceIdMap.remove(lsrId);
+            }
+        }
+    }
 }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepControllerImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepControllerImpl.java
index 24193bd..64230c5 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepControllerImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepControllerImpl.java
@@ -111,13 +111,13 @@
     @Override
     public Boolean deleteTunnel(String id) {
         // TODO Auto-generated method stub
-        return null;
+        return false;
     }
 
     @Override
     public Boolean updateTunnelBandwidth(String id, long bandwidth) {
         // TODO Auto-generated method stub
-        return null;
+        return false;
     }
 
     @Override