PCEP Protocol code restructured to move under PCEP Server code for more readability. Later Client code can be added under client folder.

Change-Id: Ie79599a170d94d8e0a00e0d034b083b3894199ee
diff --git a/protocols/pcep/server/BUCK b/protocols/pcep/server/BUCK
new file mode 100644
index 0000000..1835e30
--- /dev/null
+++ b/protocols/pcep/server/BUCK
@@ -0,0 +1,11 @@
+BUNDLES = [
+    '//protocols/pcep/server/api:onos-protocols-pcep-server-api',
+    '//protocols/pcep/server/ctl:onos-protocols-pcep-server-ctl',
+]
+
+onos_app (
+  title = 'PCEP Server Module',
+  category = 'Utility',
+  url = 'http://onosproject.org',
+  included_bundles = BUNDLES,
+)
diff --git a/protocols/pcep/server/api/BUCK b/protocols/pcep/server/api/BUCK
new file mode 100644
index 0000000..8104425
--- /dev/null
+++ b/protocols/pcep/server/api/BUCK
@@ -0,0 +1,12 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+    '//apps/pcep-api:onos-apps-pcep-api',
+    '//incubator/api:onos-incubator-api',
+    '//lib:netty',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+)
+
diff --git a/protocols/pcep/server/api/pom.xml b/protocols/pcep/server/api/pom.xml
new file mode 100644
index 0000000..0861ad3
--- /dev/null
+++ b/protocols/pcep/server/api/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2015-present Open Networking Foundation
+  ~
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-pcep-server</artifactId>
+        <version>1.12.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-pcep-server-api</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>ONOS Pcep client controller subsystem API</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-pcep-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-pcepio</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-misc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-api</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/ClientCapability.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/ClientCapability.java
new file mode 100644
index 0000000..2a6c71a
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/ClientCapability.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of capabilities supported by client.
+ */
+public class ClientCapability {
+    private boolean pceccCapability;
+    private boolean statefulPceCapability;
+    private boolean pcInstantiationCapability;
+    private boolean labelStackCapability;
+    private boolean srCapability;
+
+    /**
+     * Creates new instance of client capability.
+     *
+     * @param pceccCapability represents PCECC capability
+     * @param statefulPceCapability represents stateful PCE capability
+     * @param pcInstantiationCapability represents PC initiation capability
+     * @param labelStackCapability represents S bit is set in PCECC capability
+     * @param srCapability represents SR capability
+     */
+    public ClientCapability(boolean pceccCapability, boolean statefulPceCapability, boolean pcInstantiationCapability,
+            boolean labelStackCapability, boolean srCapability) {
+        this.pceccCapability = pceccCapability;
+        this.statefulPceCapability = statefulPceCapability;
+        this.pcInstantiationCapability = pcInstantiationCapability;
+        this.labelStackCapability = labelStackCapability;
+        this.srCapability = srCapability;
+    }
+
+    /**
+     * Obtains label stack capability.
+     *
+     * @return true if client supports PCECC capability with S bit set otherwise false
+     */
+    public boolean labelStackCapability() {
+        return labelStackCapability;
+    }
+
+    /**
+     * Obtains segment routing capability.
+     *
+     * @return true if client supports SR capability otherwise false
+     */
+    public boolean srCapability() {
+        return srCapability;
+    }
+
+    /**
+     * Obtains PCECC capability.
+     *
+     * @return true if client supports PCECC capability otherwise false
+     */
+    public boolean pceccCapability() {
+        return pceccCapability;
+    }
+
+    /**
+     * Obtains stateful PCE capability.
+     *
+     * @return true if client supports stateful PCE capability otherwise false
+     */
+    public boolean statefulPceCapability() {
+        return statefulPceCapability;
+    }
+
+    /**
+     * Obtains PC initiation capability.
+     *
+     * @return true if client supports PC initiation capability otherwise false
+     */
+    public boolean pcInstantiationCapability() {
+        return pcInstantiationCapability;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(pceccCapability, statefulPceCapability, pcInstantiationCapability, labelStackCapability,
+                srCapability);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ClientCapability) {
+            ClientCapability other = (ClientCapability) obj;
+            return Objects.equals(pceccCapability, other.pceccCapability)
+                    && Objects.equals(statefulPceCapability, other.statefulPceCapability)
+                    && Objects.equals(pcInstantiationCapability, other.pcInstantiationCapability)
+                    && Objects.equals(labelStackCapability, other.labelStackCapability)
+                    && Objects.equals(srCapability, other.srCapability);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("pceccCapability", pceccCapability)
+                .add("statefulPceCapability", statefulPceCapability)
+                .add("pcInstantiationCapability", pcInstantiationCapability)
+                .add("labelStackCapability", labelStackCapability)
+                .add("srCapability", srCapability)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/LspKey.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/LspKey.java
new file mode 100644
index 0000000..2cba240
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/LspKey.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of LSP info, it will be unique for each LSP.
+ */
+public class LspKey {
+    private int plspId;
+    private short localLspId;
+
+    /**
+     * Creates new instance of LspInfo.
+     *
+     * @param plspId LSP id assigned per tunnel per session
+     * @param localLspId LSP id assigned per tunnel
+     */
+    public LspKey(int plspId, short localLspId) {
+        this.plspId = plspId;
+        this.localLspId = localLspId;
+    }
+
+    /**
+     * Obtains PLSP id.
+     *
+     * @return LSP id assigned per tunnel per session
+     */
+    public int plspId() {
+        return plspId;
+    }
+
+    /**
+     * Obtains local LSP id.
+     *
+     * @return LSP id assigned per tunnel
+     */
+    public short localLspId() {
+        return localLspId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(plspId, localLspId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof LspKey) {
+            LspKey other = (LspKey) obj;
+            return Objects.equals(plspId, other.plspId)
+                    && Objects.equals(localLspId, other.localLspId);
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("plspId", plspId)
+                .add("localLspId", localLspId)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/LspType.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/LspType.java
new file mode 100644
index 0000000..6cfcd37
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/LspType.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * Representation of LSP type.
+ */
+public enum LspType {
+    /**
+     * Signifies that path is created via signaling mode.
+     */
+    WITH_SIGNALLING(0),
+
+    /**
+     * Signifies that path is created via SR mode.
+     */
+    SR_WITHOUT_SIGNALLING(1),
+
+    /**
+     * Signifies that path is created via without signaling and without SR mode.
+     */
+    WITHOUT_SIGNALLING_AND_WITHOUT_SR(2);
+
+    int value;
+
+    /**
+     * Assign val with the value as the LSP type.
+     *
+     * @param val LSP type
+     */
+    LspType(int val) {
+        value = val;
+    }
+
+    /**
+     * Returns value of LSP type.
+     *
+     * @return LSP type
+     */
+    public byte type() {
+        return (byte) value;
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PccId.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PccId.java
new file mode 100644
index 0000000..9fdd605
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PccId.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.util.Identifier;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * The class representing a network client pc ip.
+ * This class is immutable.
+ */
+public final class PccId extends Identifier<IpAddress> {
+
+    private static final String SCHEME = "l3";
+    private static final long UNKNOWN = 0;
+
+    /**
+     * Private constructor.
+     */
+    private PccId(IpAddress ipAddress) {
+        super(ipAddress);
+    }
+
+    /**
+     * Create a PccId from ip address.
+     *
+     * @param ipAddress IP address
+     * @return ipAddress
+     */
+    public static PccId pccId(IpAddress ipAddress) {
+        return new PccId(ipAddress);
+    }
+
+    /**
+     * Returns the ip address.
+     *
+     * @return ipAddress
+     */
+    public IpAddress ipAddress() {
+        return identifier;
+    }
+
+    /**
+     * Returns PccId created from the given client URI.
+     *
+     * @param uri device URI
+     * @return pccid
+     */
+    public static PccId pccid(URI uri) {
+        checkArgument(uri.getScheme().equals(SCHEME), "Unsupported URI scheme");
+        return new PccId(IpAddress.valueOf(uri.getSchemeSpecificPart()));
+    }
+
+    /**
+     * Produces client URI from the given DPID.
+     *
+     * @param pccid client pccid
+     * @return client URI
+     */
+    public static URI uri(PccId pccid) {
+        return uri(pccid.ipAddress());
+    }
+
+    /**
+     * Produces client URI from the given ip address.
+     *
+     * @param ipAddress ip of client
+     * @return client URI
+     */
+    public static URI uri(IpAddress ipAddress) {
+        try {
+            return new URI(SCHEME, ipAddress.toString(), null);
+        } catch (URISyntaxException e) {
+            return null;
+        }
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepAnnotationKeys.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepAnnotationKeys.java
new file mode 100644
index 0000000..bdcd35a
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepAnnotationKeys.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * Collection of keys for annotation for PCEP tunnels.
+ */
+public final class PcepAnnotationKeys {
+
+    /**
+     *  Prohibits instantiation.
+     */
+    private PcepAnnotationKeys() {
+    }
+
+    /**
+     * Annotation key for bandwidth.
+     * The value for this key is interpreted as Mbps.
+     */
+    public static final String BANDWIDTH = "bandwidth";
+
+    /**
+     * Annotation key for the LSP signaling type.
+     */
+    public static final String LSP_SIG_TYPE = "lspSigType";
+
+    /**
+     * Annotation key for the PCC tunnel id.
+     */
+    public static final String PCC_TUNNEL_ID = "PccTunnelId";
+
+    /**
+     * Annotation key for the LSP id assigned per tunnel per session.
+     */
+    public static final String PLSP_ID = "PLspId";
+
+    /**
+     * Annotation key for the LSP id assigned per tunnel.
+     */
+    public static final String LOCAL_LSP_ID = "localLspId";
+
+    /**
+     * Annotation key for the identification of initiated LSP.
+     */
+    public static final String PCE_INIT = "pceInit";
+
+    /**
+     * Annotation key for the cost type.
+     */
+    public static final String COST_TYPE = "costType";
+
+    /**
+     * Annotation key for the Delegation.
+     * Whether LSPs are delegated or not
+     */
+    public static final String DELEGATE = "delegate";
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepCfg.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepCfg.java
new file mode 100644
index 0000000..af5debf
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepCfg.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * PCEP peer state information.
+ */
+
+public interface PcepCfg {
+
+    State getState();
+
+    void setState(State state);
+
+    enum State {
+        /**
+         * Signifies that its just created.
+         */
+        INIT,
+
+        /**
+         * Signifies that only IP Address is configured.
+         */
+        OPENWAIT,
+
+        /**
+         * Signifies that only Autonomous System is configured.
+         */
+        KEEPWAIT,
+
+        /**
+         * Signifies that both IP and Autonomous System is configured.
+         */
+        ESTABLISHED,
+
+        /**
+         * Signifies that both IP and Autonomous System is down.
+         */
+        DOWN
+    }
+
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClient.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClient.java
new file mode 100644
index 0000000..cace76a
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClient.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server;
+
+import java.util.List;
+
+import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepStateReport;
+
+/**
+ * Represents to provider facing side of a path computation client(pcc).
+ */
+public interface PcepClient {
+
+    /**
+     * Writes the message to the driver.
+     *
+     * @param msg the message to write
+     */
+    void sendMessage(PcepMessage msg);
+
+    /**
+     * Writes the PcepMessage list to the driver.
+     *
+     * @param msgs the messages to be written
+     */
+    void sendMessage(List<PcepMessage> msgs);
+
+    /**
+     * Handle a message from the pcc.
+     *
+     * @param fromClient the message to handle
+     */
+    void handleMessage(PcepMessage fromClient);
+
+    /**
+     * Provides the factory for this PCEP version.
+     *
+     * @return PCEP version specific factory.
+     */
+    PcepFactory factory();
+
+    /**
+     * Gets a string version of the ID for this pcc.
+     *
+     * @return string version of the ID
+     */
+    String getStringId();
+
+    /**
+     * Gets the ipAddress of the client.
+     *
+     * @return the client pccId in IPAddress format
+     */
+    PccId getPccId();
+
+    /**
+     * Checks if the pcc is still connected.
+     *
+     * @return true if client is connected, false otherwise
+     */
+    boolean isConnected();
+
+    /**
+     * Disconnects the pcc by closing the TCP connection. Results in a call
+     * to the channel handler's channelDisconnected method for cleanup.
+     */
+    void disconnectClient();
+
+    /**
+     * Indicates if this pcc is optical.
+     *
+     * @return true if optical
+     */
+    boolean isOptical();
+
+    /**
+     * Identifies the channel used to communicate with the pcc.
+     *
+     * @return string representation of the connection to the client
+     */
+    String channelId();
+
+    /**
+     * Sets the status of LSP state synchronization.
+     *
+     * @param syncStatus LSP synchronization status to be set
+     */
+    void setLspDbSyncStatus(PcepSyncStatus syncStatus);
+
+    /**
+     * Indicates the LSP state synchronization status of this pcc.
+     *
+     * @return LSP state synchronization status.
+     */
+    PcepSyncStatus lspDbSyncStatus();
+
+    /**
+     * Sets the status of label DB synchronization.
+     *
+     * @param syncStatus label DB synchronization status to be set
+     */
+    void setLabelDbSyncStatus(PcepSyncStatus syncStatus);
+
+    /**
+     * Indicates the label DB synchronization status of this pcc.
+     *
+     * @return label DB synchronization status.
+     */
+    PcepSyncStatus labelDbSyncStatus();
+
+    /**
+     * Sets capability negotiated during open message exchange.
+     *
+     * @param capability supported by client
+     */
+    void setCapability(ClientCapability capability);
+
+    /**
+     * Obtains capability supported by client.
+     *
+     * @return capability supported by client
+     */
+    ClientCapability capability();
+
+    /**
+     * Adds PCEP device when session is successfully established.
+     *
+     * @param pc PCEP client details
+     */
+    void addNode(PcepClient pc);
+
+    /**
+     * Removes PCEP device when session is disconnected.
+     *
+     * @param pccId PCEP client ID
+     */
+    void deleteNode(PccId pccId);
+
+     /**
+     * Sets D flag for the given LSP and its LSP info.
+     *
+     * @param lspKey contains LSP info
+     * @param dFlag delegation flag in LSP object
+     */
+    void setLspAndDelegationInfo(LspKey lspKey, boolean dFlag);
+
+    /**
+     * Returns delegation flag for the given LSP info.
+     *
+     * @param lspKey contains LSP info
+     * @return delegation flag
+     */
+    Boolean delegationInfo(LspKey lspKey);
+
+    /**
+     * Creates a temporary cache to hold report messages received during LSPDB sync.
+     *
+     * @param pccId PCC id which is the key to store report messages
+     */
+    void initializeSyncMsgList(PccId pccId);
+
+    /**
+     * Returns the list of report messages received during LSPDB sync.
+     *
+     * @param pccId PCC id which is the key for all the report messages
+     * @return list of report messages received during LSPDB sync
+     */
+    List<PcepStateReport> getSyncMsgList(PccId pccId);
+
+    /**
+     * Removes the list of report messages received during LSPDB sync.
+     *
+     * @param pccId PCC id which is the key for all the report messages
+     */
+    void removeSyncMsgList(PccId pccId);
+
+    /**
+     * Adds report message received during LSPDB sync into temporary cache.
+     *
+     * @param pccId PCC id which is the key to store report messages
+     * @param rptMsg the report message to be stored
+     */
+    void addSyncMsgToList(PccId pccId, PcepStateReport rptMsg);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClientController.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClientController.java
new file mode 100644
index 0000000..226944e
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClientController.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server;
+
+import org.onosproject.incubator.net.tunnel.DefaultLabelStack;
+import org.onosproject.incubator.net.tunnel.LabelStack;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.net.Path;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.types.PcepValueType;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstraction of an Pcep client controller. Serves as a one stop
+ * shop for obtaining Pcep devices and (un)register listeners
+ * on pcep events
+ */
+public interface PcepClientController {
+
+    /**
+     * Returns list of pcc clients connected to this Pcep controller.
+     *
+     * @return list of PcepClient elements
+     */
+    Collection<PcepClient> getClients();
+
+    /**
+     * Returns the actual pcc client for the given ip address.
+     *
+     * @param pccId the id of the pcc client to fetch
+     * @return the interface to this pcc client
+     */
+    PcepClient getClient(PccId pccId);
+
+    /**
+     * Register a listener for meta events that occur to pcep
+     * devices.
+     *
+     * @param listener the listener to notify
+     */
+    void addListener(PcepClientListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to unregister
+     */
+    void removeListener(PcepClientListener listener);
+
+    /**
+     * Register a listener for PCEP msg events.
+     *
+     * @param listener the listener to notify
+     */
+    void addEventListener(PcepEventListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to unregister
+     */
+    void removeEventListener(PcepEventListener listener);
+
+    /**
+     * Register a listener for PCEP msg events[carrying node descriptor details].
+     *
+     * @param listener the listener to notify
+     */
+    void addNodeListener(PcepNodeListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to be unregistered
+     */
+    void removeNodeListener(PcepNodeListener listener);
+
+    /**
+     * Send a message to a particular pcc client.
+     *
+     * @param pccId the id of the client to send message.
+     * @param msg the message to send
+     */
+    void writeMessage(PccId pccId, PcepMessage msg);
+
+    /**
+     * Process a message and notify the appropriate listeners.
+     *
+     * @param pccId id of the client the message arrived on
+     * @param msg the message to process.
+     */
+    void processClientMessage(PccId pccId, PcepMessage msg);
+
+    /**
+     * Close all connected PCC clients.
+     */
+    void closeConnectedClients();
+
+    /**
+     * Create label stack from the given path.
+     *
+     * @param path from which label stack is to be computed
+     * @return the label stack
+     */
+    public LabelStack computeLabelStack(Path path);
+
+    /**
+     * Allocates and downloads local labels for the given LSP.
+     *
+     * @param tunnel for which local labels have to be assigned and downloaded
+     * @return success or failure
+     */
+    public boolean allocateLocalLabel(Tunnel tunnel);
+
+    /**
+     * Creates label stack for ERO object from network resource.
+     *
+     * @param labelStack label stack
+     * @param path (hop list)
+     * @return list of ERO sub-objects
+     */
+    public LinkedList<PcepValueType> createPcepLabelStack(DefaultLabelStack labelStack, Path path);
+
+    /**
+     * Returns list of PCEP exceptions.
+     *
+     * @return PcepExceptions
+     */
+    public Map<String, List<String>> getPcepExceptions();
+
+    /**
+     * Returns all the pcep error messages received .
+     *
+     * @return PcepErrorMsg
+     */
+    public Map<Integer, Integer> getPcepErrorMsg();
+
+    /**
+     * Returns the pcep session details.
+     *
+     * @return PcepSession
+     */
+    public Map<String, String> getPcepSessionMap();
+
+    /**
+     * Returns the pcep sessionid information.
+     *
+     * @return PcepSessionId
+     */
+    public Map<String, Byte> getPcepSessionIdMap();
+
+    /**
+     * Creates detailed information about pcep error value and type per peer.
+     *
+     * @param peerId id of the peer which sent the error message
+     * @param errorType the error type of the error message received
+     * @param errValue the error value of the error message received
+     */
+    void peerErrorMsg(String peerId, Integer errorType, Integer errValue);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClientListener.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClientListener.java
new file mode 100644
index 0000000..5a0d5bc
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepClientListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * Allows for providers interested in PCC client events to be notified.
+ */
+public interface PcepClientListener {
+
+    /**
+     * Notify that the PCC was connected.
+     *
+     * @param pccId the id of the client that connected
+     */
+    void clientConnected(PccId pccId);
+
+    /**
+     * Notify that the PCC was disconnected.
+     *
+     * @param pccId the id of the client that disconnected.
+     */
+    void clientDisconnected(PccId pccId);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepErrorDetail.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepErrorDetail.java
new file mode 100644
index 0000000..37ea6d0
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepErrorDetail.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * PCEP error message details.
+ */
+public class PcepErrorDetail {
+
+    private Map<Integer, String> sessionEstablishmentFailureMap = new TreeMap<>();
+    private Map<Integer, String> unknownObjectMap = new TreeMap<>();
+    private Map<Integer, String> notSupportedObjectMap = new TreeMap<>();
+    private Map<Integer, String> policyViolationMap = new TreeMap<>();
+    private Map<Integer, String> mandatoryObjectMissingMap = new TreeMap<>();
+    private Map<Integer, String> receptionOfInvalidObjectMap = new TreeMap<>();
+    private Map<Integer, String> invalidOperationMap = new TreeMap<>();
+
+
+    public Map sessionEstablishmentFailure() {
+        sessionEstablishmentFailureMap.put(1, "Reception of an invalid Open message or a non Open message.");
+        sessionEstablishmentFailureMap.put(2, "no Open message received before the expiration of the OpenWait timer");
+        sessionEstablishmentFailureMap.put(3, "unacceptable and non-negotiable session characteristics");
+        sessionEstablishmentFailureMap.put(4, "unacceptable but negotiable session characteristics");
+        sessionEstablishmentFailureMap.put(5, "reception of a second Open message with still " +
+                "unacceptable session characteristics");
+        sessionEstablishmentFailureMap.put(6, "reception of a PCErr message proposing unacceptable " +
+                "session characteristics");
+        sessionEstablishmentFailureMap.put(7, "No Keepalive or PCErr message received before the " +
+                "expiration of the KeepWait timer");
+        sessionEstablishmentFailureMap.put(8, "PCEP version not supported");
+        return sessionEstablishmentFailureMap;
+    }
+
+
+    public Map unknownObject() {
+        unknownObjectMap.put(1, "Unrecognized object class");
+        unknownObjectMap.put(2, "Unrecognized object type");
+        return unknownObjectMap;
+    }
+
+    public Map notSupportedObject() {
+        notSupportedObjectMap.put(1, "Not Supported object class");
+        notSupportedObjectMap.put(2, "Not Supported object type");
+        return notSupportedObjectMap;
+    }
+
+
+    public Map policyViolation() {
+        policyViolationMap.put(1, "C bit of the METRIC object set (request rejected)");
+        policyViolationMap.put(2, "O bit of the RP object cleared (request rejected)");
+        return policyViolationMap;
+    }
+
+
+
+    public Map mandatoryObjectMissing() {
+        mandatoryObjectMissingMap.put(1, "RP object missing");
+        mandatoryObjectMissingMap.put(2, "RRO missing for a re-optimization request (R bit of the RP object set)");
+        mandatoryObjectMissingMap.put(2, "END-POINTS object missing");
+        return mandatoryObjectMissingMap;
+
+    }
+
+
+    public Map receptionOfInvalidObject() {
+        receptionOfInvalidObjectMap.put(1, "reception of an object with P flag not set although the P flag must be" +
+                "set according to this specification.");
+        return receptionOfInvalidObjectMap;
+    }
+
+    public Map invalidOperation() {
+        invalidOperationMap.put(1, "Attempted LSP Update Request for a non-delegated LSP.  The PCEP-ERROR Object" +
+                " is followed by the LSP Object that identifies the LSP.");
+        invalidOperationMap.put(2, "Attempted LSP Update Request if the" +
+                " stateful PCE capability was not" +
+                " advertised.");
+        invalidOperationMap.put(3, "Attempted LSP Update Request for an LSP" +
+                "identified by an unknown PLSP-ID.");
+        invalidOperationMap.put(4, "A PCE indicates to a PCC that it has" +
+                " exceeded the resource limit allocated" +
+                " for its state, and thus it cannot" +
+                " accept and process its LSP State Report" +
+                " message.");
+        invalidOperationMap.put(5, "Attempted LSP State Report if active" +
+                " stateful PCE capability was not" +
+                " advertised.");
+        return invalidOperationMap;
+    }
+
+
+
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepErrorType.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepErrorType.java
new file mode 100644
index 0000000..8d51999
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepErrorType.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * PCEP error message type information.
+ */
+public enum  PcepErrorType {
+    SESSIONESTABLISHMENTFAILURE(1),
+    CAPABALITYNOTSUPPORTED(2),
+    UNKNOWNOBJECT(3),
+    NOTSUPPORTEDOBJECT(4),
+    POLICYVIOLATION(5),
+    MANDATORYOBJECTMISSING(6),
+    SYNCHRONIZEDPATHCOMPUTATIONREQUESTMISSING(7),
+    UNKNOWNREQUESTREFERENCE(8),
+    ESTABLISHINGSECONDPCEPSESSION(9),
+    RECEPTIONOFINVALIDOBJECT(10),
+    INVALIDOPERATION(19),
+    VIRTUALNETWORKTLVMISSING(255);
+
+    int value;
+
+    /**
+     * Creates an instance of Pcep Error Type.
+     *
+     * @param value represents Error type
+     */
+    PcepErrorType(int value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value representing Pcep Error Type.
+     *
+     * @return value represents Error Type
+     */
+    public  int value() {
+        return value;
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepEventListener.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepEventListener.java
new file mode 100644
index 0000000..06d49ed
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepEventListener.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server;
+
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.pcepio.protocol.PcepMessage;
+/**
+ * Notifies providers about PCEP message events.
+ */
+public interface PcepEventListener {
+
+    /**
+     * Handles the message event.
+     *
+     * @param pccId id of the pcc
+     * @param msg the message
+     */
+    void handleMessage(PccId pccId, PcepMessage msg);
+
+    /**
+     * Handles end of LSPDB sync actions.
+     *
+     * @param tunnel the tunnel on which action needs to be taken
+     * @param endOfSyncAction the action that needs to be taken for the tunnel
+     */
+    void handleEndOfSyncAction(Tunnel tunnel, PcepLspSyncAction endOfSyncAction);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepLspStatus.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepLspStatus.java
new file mode 100644
index 0000000..9ced00a
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepLspStatus.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+import org.onosproject.incubator.net.tunnel.Tunnel.State;
+
+/**
+ * Representation of the PCEP LSP state.
+ */
+public enum PcepLspStatus {
+
+    /**
+     * Signifies that the LSP is not active.
+     */
+    DOWN,
+
+    /**
+     * Signifies that the LSP is signalled.
+     */
+    UP,
+
+    /**
+     * Signifies that the LSP is up and carrying traffic.
+     */
+    ACTIVE,
+
+    /**
+     * Signifies that the LSP is being torn down, resources are being released.
+     */
+    GOING_DOWN,
+
+    /**
+     * Signifies that the LSP is being signalled.
+     */
+    GOING_UP;
+
+    /**
+     * Returns the applicable PCEP LSP status corresponding to ONOS tunnel state.
+     *
+     * @param tunnelState ONOS tunnel state
+     * @return LSP status as per protocol
+     */
+    public static PcepLspStatus getLspStatusFromTunnelStatus(State tunnelState) {
+
+        switch (tunnelState) {
+
+        case INIT:
+            return PcepLspStatus.DOWN;
+
+        case ESTABLISHED:
+            return PcepLspStatus.GOING_UP;
+
+        case ACTIVE:
+            return PcepLspStatus.UP;
+
+        case FAILED: // fall through
+        case INACTIVE: // LSP is administratively down.
+        default:
+            return PcepLspStatus.DOWN;
+        }
+    }
+
+    /**
+     * Returns the applicable ONOS tunnel state corresponding to PCEP LSP status.
+     *
+     * @param lspState PCEP LSP status
+     * @return tunnel state
+     */
+    public static State getTunnelStatusFromLspStatus(PcepLspStatus lspState) {
+
+        switch (lspState) {
+
+        case DOWN:
+            return State.FAILED;
+
+        case UP: // fall through
+        case ACTIVE:
+            return State.ACTIVE;
+
+        case GOING_DOWN:
+            return State.FAILED;
+
+        case GOING_UP:
+            return State.ESTABLISHED;
+
+        default:
+            return State.FAILED;
+        }
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepLspSyncAction.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepLspSyncAction.java
new file mode 100644
index 0000000..c120df3
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepLspSyncAction.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * Representation of actions to be taken for LSPs on end of LSP-DB sync.
+ */
+public enum PcepLspSyncAction {
+
+    /**
+     * Specifies that delete message for PCE intiiated tunnel should be sent.
+     */
+    SEND_DELETE(0),
+
+    /**
+     * Specifies that update message should be sent.
+     */
+    SEND_UPDATE(1),
+
+    /**
+     * Specifies that the tunnel should be removed from PCE.
+     */
+    REMOVE(2),
+
+    /**
+     * Specifies that the status of the tunnel should be set as unstable.
+     */
+    UNSTABLE(3);
+
+    int value;
+
+    /**
+     * Assigns val with the value for actions to be taken for LSPs on end of LSP-DB sync.
+     *
+     * @param val sync status
+     */
+    PcepLspSyncAction(int val) {
+        value = val;
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepNodeListener.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepNodeListener.java
new file mode 100644
index 0000000..1bb0b95
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepNodeListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * Notifies providers about PCEP node events.
+ */
+public interface PcepNodeListener {
+
+    /**
+     * Notifies that the node was added.
+     *
+     * @param pc PCEP client details
+     */
+    void addDevicePcepConfig(PcepClient pc);
+
+    /**
+     * Notifies that the node was removed.
+     *
+     * @param pccId PCEP client ID
+     */
+    void deleteDevicePcepConfig(PccId pccId);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepPacketStats.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepPacketStats.java
new file mode 100644
index 0000000..5802cc5
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepPacketStats.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * The representation for PCEP packet statistics.
+ */
+public interface PcepPacketStats {
+
+    /**
+     * Returns the count for no of packets sent out.
+     *
+     * @return int value of no of packets sent
+     */
+    int outPacketCount();
+
+    /**
+     * Returns the count for no of packets received.
+     *
+     * @return int value of no of packets sent
+     */
+    int inPacketCount();
+
+    /**
+     * Returns the count for no of wrong packets received.
+     *
+     * @return int value of no of wrong packets received
+     */
+    int wrongPacketCount();
+
+    /**
+     * Returns the time value.
+     *
+     * @return long value of time
+     */
+    long getTime();
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepSyncStatus.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepSyncStatus.java
new file mode 100644
index 0000000..e487b95
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/PcepSyncStatus.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+/**
+ * Representation of PCEP database sync status on session establishment.
+ */
+public enum PcepSyncStatus {
+
+    /**
+     * Specifies that the DB state is not synchronized.
+     */
+    NOT_SYNCED(0),
+
+    /**
+     * Specifies that the DB state is currently undergoing synchronization.
+     */
+    IN_SYNC(1),
+
+    /**
+     * Specifies that the DB state synchronization is completed.
+     */
+    SYNCED(2);
+
+    int value;
+
+    /**
+     * Assign val with the value as the sync status.
+     *
+     * @param val sync status
+     */
+    PcepSyncStatus(int val) {
+        value = val;
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/SrpIdGenerators.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/SrpIdGenerators.java
new file mode 100644
index 0000000..8d73287
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/SrpIdGenerators.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+
+/**
+ * Unique Srp Id generator for pcep messages.
+ */
+public final class SrpIdGenerators {
+
+    private static final Logger log = getLogger(SrpIdGenerators.class);
+    private static final AtomicInteger SRP_ID_GEN = new AtomicInteger();
+    private static final int MAX_SRP_ID = 0x7FFFFFFF;
+    private static int srpId;
+
+    /**
+     * Default constructor.
+     */
+    private SrpIdGenerators() {
+    }
+
+    /**
+     * Get the next srp id.
+     *
+     * @return srp id
+     */
+    public static int create() {
+        do {
+            if (srpId >= MAX_SRP_ID) {
+                if (SRP_ID_GEN.get() >= MAX_SRP_ID) {
+                    SRP_ID_GEN.set(0);
+                }
+            }
+            srpId = SRP_ID_GEN.incrementAndGet();
+        } while (srpId > MAX_SRP_ID);
+        return srpId;
+    }
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepAgent.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepAgent.java
new file mode 100644
index 0000000..42f25cc
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepAgent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.driver;
+
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcepio.protocol.PcepMessage;
+
+/**
+ * Responsible for keeping track of the current set Pcep clients
+ * connected to the system.
+ *
+ */
+public interface PcepAgent {
+
+    /**
+     * Add a pcc client that has just connected to the system.
+     *
+     * @param pccId the id of pcc client to add
+     * @param pc the actual pce client object.
+     * @return true if added, false otherwise.
+     */
+    boolean addConnectedClient(PccId pccId, PcepClient pc);
+
+    /**
+     * Checks if the activation for this pcc client is valid.
+     *
+     * @param pccId the id of pcc client to check
+     * @return true if valid, false otherwise
+     */
+    boolean validActivation(PccId pccId);
+
+    /**
+     * Clear all state in controller client maps for a pcc client that has
+     * disconnected from the local controller. Also release control for
+     * that pccIds client from the global repository. Notify client listeners.
+     *
+     * @param pccIds the id of pcc client to remove.
+     */
+    void removeConnectedClient(PccId pccIds);
+
+    /**
+     * Process a message coming from a pcc client.
+     *
+     * @param pccId the id of pcc client the message was received.
+     * @param m the message to process
+     */
+    void processPcepMessage(PccId pccId, PcepMessage m);
+
+    /**
+     * Adds PCEP device when session is successfully established.
+     *
+     * @param pc PCEP client details
+     */
+    void addNode(PcepClient pc);
+
+    /**
+     * Removes PCEP device when session is disconnected.
+     *
+     * @param pccId PCEP client ID
+     */
+    void deleteNode(PccId pccId);
+
+    /**
+     * Analyzes report messages received during LSP DB sync again tunnel store and takes necessary actions.
+     *
+     * @param pccId the id of pcc client
+     * @return success or failure
+     */
+    boolean analyzeSyncMsgList(PccId pccId);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepClientDriver.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepClientDriver.java
new file mode 100644
index 0000000..58fc33f
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepClientDriver.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.driver;
+
+import org.jboss.netty.channel.Channel;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepPacketStats;
+import org.onosproject.pcepio.protocol.PcepVersion;
+
+
+/**
+ * Represents the driver side of an Path computation client(pcc).
+ *
+ */
+public interface PcepClientDriver extends PcepClient {
+
+    /**
+     * Sets the Pcep agent to be used. This method
+     * can only be called once.
+     *
+     * @param agent the agent to set.
+     */
+    void setAgent(PcepAgent agent);
+
+    /**
+     * Announce to the Pcep agent that this pcc client has connected.
+     *
+     * @return true if successful, false if duplicate switch.
+     */
+    boolean connectClient();
+
+    /**
+     * Remove this pcc client from the Pcep agent.
+     */
+    void removeConnectedClient();
+
+    /**
+     * Sets the PCEP version for this pcc.
+     *
+     * @param pcepVersion the version to set.
+     */
+    void setPcVersion(PcepVersion pcepVersion);
+
+    /**
+     * Sets the associated Netty channel for this pcc.
+     *
+     * @param channel the Netty channel
+     */
+    void setChannel(Channel channel);
+
+
+    /**
+     * Sets the keep alive time for this pcc.
+     *
+     * @param keepAliveTime the keep alive time to set.
+     */
+    void setPcKeepAliveTime(byte keepAliveTime);
+
+    /**
+     * Sets the dead time for this pcc.
+     *
+     * @param deadTime the dead timer value to set.
+     */
+    void setPcDeadTime(byte deadTime);
+
+    /**
+     * Sets the session id for this pcc.
+     *
+     * @param sessionId the session id value to set.
+     */
+    void setPcSessionId(byte sessionId);
+
+    /**
+     * Sets whether the pcc is connected.
+     *
+     * @param connected whether the pcc is connected
+     */
+    void setConnected(boolean connected);
+
+    /**
+     * Initializes the behavior.
+     *
+     * @param pccId id of pcc
+     * @param pcepVersion Pcep version
+     * @param pktStats Pcep Packet Stats
+     */
+    void init(PccId pccId, PcepVersion pcepVersion, PcepPacketStats pktStats);
+
+    /**
+     * Checks whether the handshake is complete.
+     *
+     * @return true is finished, false if not.
+     */
+    boolean isHandshakeComplete();
+
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepClientDriverFactory.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepClientDriverFactory.java
new file mode 100644
index 0000000..46e04ff
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/PcepClientDriverFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.driver;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.pcepio.protocol.PcepVersion;
+
+/**
+ * Pcc Client factory which returns concrete pcc client objects for the
+ * physical pcc client in use.
+ *
+ */
+public interface PcepClientDriverFactory {
+
+
+    /**
+     * Constructs the real Pcep Client representation.
+     *
+     * @param pccIpAddress the ip address for this pcc client.
+     * @param pcepVersion the Pcep version in use
+     * @return the Pcep client representation.
+     */
+    PcepClientDriver getPcepClientImpl(IpAddress pccIpAddress,
+            PcepVersion pcepVersion);
+}
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/package-info.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/package-info.java
new file mode 100644
index 0000000..6e542e7
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/driver/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * PCEP client controller driver API.
+ */
+package org.onosproject.pcep.server.driver;
diff --git a/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/package-info.java b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/package-info.java
new file mode 100644
index 0000000..8ed1233
--- /dev/null
+++ b/protocols/pcep/server/api/src/main/java/org/onosproject/pcep/server/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * PCEP client controller API.
+ */
+package org.onosproject.pcep.server;
diff --git a/protocols/pcep/server/ctl/BUCK b/protocols/pcep/server/ctl/BUCK
new file mode 100644
index 0000000..e247e20
--- /dev/null
+++ b/protocols/pcep/server/ctl/BUCK
@@ -0,0 +1,17 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:NETTY',
+    '//lib:JACKSON',
+    '//lib:KRYO',
+    '//incubator/api:onos-incubator-api',
+    '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+    '//protocols/pcep/server/api:onos-protocols-pcep-server-api',
+    '//core/store/serializers:onos-core-serializers',
+    '//apps/pcep-api:onos-apps-pcep-api',
+    '//lib:netty',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+)
+
diff --git a/protocols/pcep/server/ctl/pom.xml b/protocols/pcep/server/ctl/pom.xml
new file mode 100644
index 0000000..69b62fd
--- /dev/null
+++ b/protocols/pcep/server/ctl/pom.xml
@@ -0,0 +1,69 @@
+<!--
+  ~ Copyright 2015-present Open Networking Foundation
+  ~
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-pcep-server</artifactId>
+        <version>1.12.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-pcep-server-impl</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>ONOS PCEP client controller subsystem API implementation</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-pcep-server-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-misc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-serializers</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfo.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfo.java
new file mode 100644
index 0000000..be262f0
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfo.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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/server/ctl/src/main/java/org/onosproject/pcelabelstore/DistributedPceLabelStore.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/DistributedPceLabelStore.java
new file mode 100644
index 0000000..4c6a3cf
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/DistributedPceLabelStore.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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/server/ctl/src/main/java/org/onosproject/pcelabelstore/PcepLabelOp.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/PcepLabelOp.java
new file mode 100644
index 0000000..d879a86
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/PcepLabelOp.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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;
+
+/**
+ * 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/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/LspLocalLabelInfo.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/LspLocalLabelInfo.java
new file mode 100644
index 0000000..666449a
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/LspLocalLabelInfo.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/PceLabelStore.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/PceLabelStore.java
new file mode 100644
index 0000000..c732f25
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/PceLabelStore.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/package-info.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/package-info.java
new file mode 100644
index 0000000..9147dba
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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/server/ctl/src/main/java/org/onosproject/pcelabelstore/package-info.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/package-info.java
new file mode 100644
index 0000000..0b4e482
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcelabelstore/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java
new file mode 100644
index 0000000..c547b35
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java
@@ -0,0 +1,579 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server.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.server.LspType;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepAnnotationKeys;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepClientController;
+import org.onosproject.pcep.server.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.server.PcepAnnotationKeys.BANDWIDTH;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.LSP_SIG_TYPE;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.PCE_INIT;
+import static org.onosproject.pcep.server.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 deviceService device service
+     * @param pceStore pce label store
+     * @param clientController client controller
+     */
+    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.isEmpty())) {
+            // 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.isEmpty())) {
+                    // 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.isEmpty())) {
+           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.isEmpty())) {
+           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/server/ctl/src/main/java/org/onosproject/pcep/server/impl/Controller.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/Controller.java
new file mode 100644
index 0000000..c85e22a
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/Controller.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import static org.onlab.util.Tools.groupedThreads;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetSocketAddress;
+import java.util.Map;
+import java.util.LinkedList;
+import java.util.TreeMap;
+import java.util.List;
+import java.util.HashMap;
+import java.util.concurrent.Executors;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepCfg;
+import org.onosproject.pcep.server.PcepPacketStats;
+import org.onosproject.pcep.server.driver.PcepAgent;
+import org.onosproject.pcep.server.driver.PcepClientDriver;
+import org.onosproject.pcepio.protocol.PcepFactories;
+import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The main controller class. Handles all setup and network listeners -
+ * Distributed ownership control of pcc through IControllerRegistryService
+ */
+public class Controller {
+
+    private static final Logger log = LoggerFactory.getLogger(Controller.class);
+
+    private static final PcepFactory FACTORY1 = PcepFactories.getFactory(PcepVersion.PCEP_1);
+    private PcepCfg pcepConfig = new PcepConfig();
+    private ChannelGroup cg;
+
+    // Configuration options
+    private int pcepPort = 4189;
+    private int workerThreads = 10;
+
+    // Start time of the controller
+    private long systemStartTime;
+
+    private PcepAgent agent;
+
+    private Map<String, String> peerMap = new TreeMap<>();
+    private Map<String, List<String>> pcepExceptionMap = new TreeMap<>();
+    private Map<Integer, Integer> pcepErrorMsg = new TreeMap<>();
+    private Map<String, Byte> sessionMap = new TreeMap<>();
+    private LinkedList<String> pcepExceptionList = new LinkedList<String>();
+
+    private NioServerSocketChannelFactory execFactory;
+
+    // Perf. related configuration
+    private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
+
+    /**
+     * pcep session information.
+     *
+     * @param peerId id of the peer with which the session is being formed
+     * @param status pcep session status
+     * @param sessionId pcep session id
+     */
+    public void peerStatus(String peerId, String status, byte sessionId) {
+        if (peerId != null) {
+            peerMap.put(peerId, status);
+            sessionMap.put(peerId, sessionId);
+        } else {
+            log.debug("Peer Id is null");
+        }
+    }
+
+    /**
+     * Pcep session exceptions information.
+     *
+     * @param peerId id of the peer which has generated the exception
+     * @param exception pcep session exception
+     */
+    public void peerExceptions(String peerId, String exception) {
+        if (peerId != null) {
+            pcepExceptionList.add(exception);
+            pcepExceptionMap.put(peerId, pcepExceptionList);
+        } else {
+            log.debug("Peer Id is null");
+        }
+        if (pcepExceptionList.size() > 10) {
+            pcepExceptionList.clear();
+            pcepExceptionList.add(exception);
+            pcepExceptionMap.put(peerId, pcepExceptionList);
+        }
+    }
+
+    /**
+     * Create a map of pcep error messages received.
+     *
+     * @param peerId id of the peer which has sent the error message
+     * @param errorType error type of pcep error messgae
+     * @param errValue error value of pcep error messgae
+     */
+    public void peerErrorMsg(String peerId, Integer errorType, Integer errValue) {
+        if (peerId == null) {
+            pcepErrorMsg.put(errorType, errValue);
+        } else {
+            if (pcepErrorMsg.size() > 10) {
+                pcepErrorMsg.clear();
+            }
+            pcepErrorMsg.put(errorType, errValue);
+        }
+    }
+
+    /**
+     * Returns the pcep session details.
+     *
+     * @return pcep session details
+     */
+    public Map<String, Byte> mapSession() {
+        return this.sessionMap;
+    }
+
+
+
+    /**
+     * Returns factory version for processing pcep messages.
+     *
+     * @return instance of factory version
+     */
+    public PcepFactory getPcepMessageFactory1() {
+        return FACTORY1;
+    }
+
+    /**
+     * To get system start time.
+     *
+     * @return system start time in milliseconds
+     */
+    public long getSystemStartTime() {
+        return (this.systemStartTime);
+    }
+
+    /**
+     * Returns the list of pcep peers with session information.
+     *
+     * @return pcep peer information
+     */
+    public  Map<String, String> mapPeer() {
+        return this.peerMap;
+    }
+
+    /**
+     * Returns the list of pcep exceptions per peer.
+     *
+     * @return pcep exceptions
+     */
+    public  Map<String, List<String>> exceptionsMap() {
+        return this.pcepExceptionMap;
+    }
+
+    /**
+     * Returns the type and value of pcep error messages.
+     *
+     * @return pcep error message
+     */
+    public Map<Integer, Integer> mapErrorMsg() {
+        return this.pcepErrorMsg;
+    }
+
+    /**
+     * Tell controller that we're ready to accept pcc connections.
+     */
+    public void run() {
+        try {
+            final ServerBootstrap bootstrap = createServerBootStrap();
+
+            bootstrap.setOption("reuseAddr", true);
+            bootstrap.setOption("child.keepAlive", true);
+            bootstrap.setOption("child.tcpNoDelay", true);
+            bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
+
+            ChannelPipelineFactory pfact = new PcepPipelineFactory(this);
+
+            bootstrap.setPipelineFactory(pfact);
+            InetSocketAddress sa = new InetSocketAddress(pcepPort);
+            cg = new DefaultChannelGroup();
+            cg.add(bootstrap.bind(sa));
+            log.debug("Listening for PCC connection on {}", sa);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Creates server boot strap.
+     *
+     * @return ServerBootStrap
+     */
+    private ServerBootstrap createServerBootStrap() {
+        if (workerThreads == 0) {
+            execFactory = new NioServerSocketChannelFactory(
+                    Executors.newCachedThreadPool(groupedThreads("onos/pcep", "boss-%d")),
+                    Executors.newCachedThreadPool(groupedThreads("onos/pcep", "worker-%d")));
+            return new ServerBootstrap(execFactory);
+        } else {
+            execFactory = new NioServerSocketChannelFactory(
+                    Executors.newCachedThreadPool(groupedThreads("onos/pcep", "boss-%d")),
+                    Executors.newCachedThreadPool(groupedThreads("onos/pcep", "worker-%d")), workerThreads);
+            return new ServerBootstrap(execFactory);
+        }
+    }
+
+    /**
+     * Initialize internal data structures.
+     */
+    public void init() {
+        // These data structures are initialized here because other
+        // module's startUp() might be called before ours
+        this.systemStartTime = System.currentTimeMillis();
+    }
+
+    public Map<String, Long> getMemory() {
+        Map<String, Long> m = new HashMap<>();
+        Runtime runtime = Runtime.getRuntime();
+        m.put("total", runtime.totalMemory());
+        m.put("free", runtime.freeMemory());
+        return m;
+    }
+
+    public Long getUptime() {
+        RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
+        return rb.getUptime();
+    }
+
+    /**
+     * Creates instance of Pcep client.
+     *
+     * @param pccId pcc identifier
+     * @param sessionID session id
+     * @param pv pcep version
+     * @param pktStats pcep packet statistics
+     * @return instance of PcepClient
+     */
+    protected PcepClientDriver getPcepClientInstance(PccId pccId, int sessionID, PcepVersion pv,
+            PcepPacketStats pktStats) {
+        PcepClientDriver pcepClientDriver = new PcepClientImpl();
+        pcepClientDriver.init(pccId, pv, pktStats);
+        pcepClientDriver.setAgent(agent);
+        return pcepClientDriver;
+    }
+
+    /**
+     * Starts the pcep controller.
+     *
+     * @param ag Pcep agent
+     */
+    public void start(PcepAgent ag) {
+        log.info("Started");
+        this.agent = ag;
+        this.init();
+        this.run();
+    }
+
+    /**
+     * Stops the pcep controller.
+     */
+    public void stop() {
+        log.info("Stopped");
+        execFactory.shutdown();
+        cg.close();
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/LabelType.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/LabelType.java
new file mode 100644
index 0000000..ca7cc7c
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/LabelType.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server.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/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java
new file mode 100644
index 0000000..8d50149
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.pcep.server.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.server.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.server.PccId;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepClientController;
+import org.onosproject.pcep.server.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 clientController client controller
+     * @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.isEmpty()) {
+            // 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, element.getValue(),
+                                        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.isEmpty()) {
+            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.isEmpty())) {
+            // 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/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java
new file mode 100644
index 0000000..dce5fa0
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java
@@ -0,0 +1,725 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.ClosedChannelException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.handler.timeout.IdleState;
+import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
+import org.jboss.netty.handler.timeout.IdleStateEvent;
+import org.jboss.netty.handler.timeout.IdleStateHandler;
+import org.jboss.netty.handler.timeout.ReadTimeoutException;
+import org.onlab.packet.IpAddress;
+import org.onosproject.pcep.server.ClientCapability;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepCfg;
+import org.onosproject.pcep.server.driver.PcepClientDriver;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepError;
+import org.onosproject.pcepio.protocol.PcepErrorInfo;
+import org.onosproject.pcepio.protocol.PcepErrorMsg;
+import org.onosproject.pcepio.protocol.PcepErrorObject;
+import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepOpenMsg;
+import org.onosproject.pcepio.protocol.PcepOpenObject;
+import org.onosproject.pcepio.protocol.PcepType;
+import org.onosproject.pcepio.protocol.PcepVersion;
+import org.onosproject.pcepio.types.IPv4RouterIdOfLocalNodeSubTlv;
+import org.onosproject.pcepio.types.NodeAttributesTlv;
+import org.onosproject.pcepio.types.PceccCapabilityTlv;
+import org.onosproject.pcepio.types.SrPceCapabilityTlv;
+import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
+import org.onosproject.pcepio.types.PcepErrorDetailInfo;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onosproject.pcep.server.PcepSyncStatus.NOT_SYNCED;
+
+/**
+ * Channel handler deals with the pcc client connection and dispatches
+ * messages from client to the appropriate locations.
+ */
+class PcepChannelHandler extends IdleStateAwareChannelHandler {
+    static final byte DEADTIMER_MAXIMUM_VALUE = (byte) 0xFF;
+    static final byte KEEPALIVE_MULTIPLE_FOR_DEADTIMER = 4;
+    private static final Logger log = LoggerFactory.getLogger(PcepChannelHandler.class);
+    private final Controller controller;
+    private PcepClientDriver pc;
+    private PccId thispccId;
+    private Channel channel;
+    private byte sessionId = 0;
+    private byte keepAliveTime;
+    private byte deadTime;
+    private ClientCapability capability;
+    private PcepPacketStatsImpl pcepPacketStats;
+    static final int MAX_WRONG_COUNT_PACKET = 5;
+    static final int BYTE_MASK = 0xFF;
+
+    // State needs to be volatile because the HandshakeTimeoutHandler
+    // needs to check if the handshake is complete
+    private volatile ChannelState state;
+    private String peerAddr;
+    private SocketAddress address;
+    private InetSocketAddress inetAddress;
+    // When a pcc client with a ip addresss is found (i.e we already have a
+    // connected client with the same ip), the new client is immediately
+    // disconnected. At that point netty callsback channelDisconnected() which
+    // proceeds to cleaup client state - we need to ensure that it does not cleanup
+    // client state for the older (still connected) client
+    private volatile Boolean duplicatePccIdFound;
+
+    //Indicates the pcep version used by this pcc client
+    protected PcepVersion pcepVersion;
+    protected PcepFactory factory1;
+
+    /**
+     * Create a new unconnected PcepChannelHandler.
+     * @param controller parent controller
+     */
+    PcepChannelHandler(Controller controller) {
+        this.controller = controller;
+        this.state = ChannelState.INIT;
+        factory1 = controller.getPcepMessageFactory1();
+        duplicatePccIdFound = Boolean.FALSE;
+        pcepPacketStats = new PcepPacketStatsImpl();
+    }
+
+    /**
+     * To disconnect a PCC.
+     */
+    public void disconnectClient() {
+        pc.disconnectClient();
+    }
+
+    //*************************
+    //  Channel State Machine
+    //*************************
+
+    @Override
+    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+        channel = e.getChannel();
+        log.info("PCC connected from {}", channel.getRemoteAddress());
+
+        address = channel.getRemoteAddress();
+        if (!(address instanceof InetSocketAddress)) {
+            throw new IOException("Invalid peer connection.");
+        }
+
+        inetAddress = (InetSocketAddress) address;
+        peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString();
+
+        // Wait for open message from pcc client
+        setState(ChannelState.OPENWAIT);
+        controller.peerStatus(peerAddr, PcepCfg.State.OPENWAIT.toString(), sessionId);
+    }
+
+    @Override
+    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+        log.info("Pcc disconnected callback for pc:{}. Cleaning up ...", getClientInfoString());
+        controller.peerStatus(peerAddr, PcepCfg.State.DOWN.toString(), sessionId);
+
+        channel = e.getChannel();
+        address = channel.getRemoteAddress();
+        if (!(address instanceof InetSocketAddress)) {
+            throw new IOException("Invalid peer connection.");
+        }
+
+        inetAddress = (InetSocketAddress) address;
+        peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString();
+
+        if (thispccId != null) {
+            if (!duplicatePccIdFound) {
+                // if the disconnected client (on this ChannelHandler)
+                // was not one with a duplicate-dpid, it is safe to remove all
+                // state for it at the controller. Notice that if the disconnected
+                // client was a duplicate-ip, calling the method below would clear
+                // all state for the original client (with the same ip),
+                // which we obviously don't want.
+                log.debug("{}:removal called", getClientInfoString());
+                if (pc != null) {
+                    pc.removeConnectedClient();
+                }
+            } else {
+                // A duplicate was disconnected on this ChannelHandler,
+                // this is the same client reconnecting, but the original state was
+                // not cleaned up - XXX check liveness of original ChannelHandler
+                log.debug("{}:duplicate found", getClientInfoString());
+                duplicatePccIdFound = Boolean.FALSE;
+            }
+        } else {
+            log.warn("no pccip in channelHandler registered for " + "disconnected client {}", getClientInfoString());
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
+        PcepErrorMsg errMsg;
+        log.info("exceptionCaught: " + e.toString());
+
+        if (e.getCause() instanceof ReadTimeoutException) {
+            if (ChannelState.OPENWAIT == state) {
+                // When ReadTimeout timer is expired in OPENWAIT state, it is considered
+                // OpenWait timer.
+                errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_2);
+                log.debug("Sending PCEP-ERROR message to PCC.");
+                controller.peerExceptions(peerAddr, e.getCause().toString());
+                channel.write(Collections.singletonList(errMsg));
+                channel.close();
+                state = ChannelState.INIT;
+                return;
+            } else if (ChannelState.KEEPWAIT == state) {
+                // When ReadTimeout timer is expired in KEEPWAIT state, is is considered
+                // KeepWait timer.
+                errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_7);
+                log.debug("Sending PCEP-ERROR message to PCC.");
+                controller.peerExceptions(peerAddr, e.getCause().toString());
+                channel.write(Collections.singletonList(errMsg));
+                channel.close();
+                state = ChannelState.INIT;
+                return;
+            }
+        } else if (e.getCause() instanceof ClosedChannelException) {
+            controller.peerExceptions(peerAddr, e.getCause().toString());
+            log.debug("Channel for pc {} already closed", getClientInfoString());
+        } else if (e.getCause() instanceof IOException) {
+            controller.peerExceptions(peerAddr, e.getCause().toString());
+            log.error("Disconnecting client {} due to IO Error: {}", getClientInfoString(), e.getCause().getMessage());
+            if (log.isDebugEnabled()) {
+                // still print stack trace if debug is enabled
+                log.debug("StackTrace for previous Exception: ", e.getCause());
+            }
+            channel.close();
+        } else if (e.getCause() instanceof PcepParseException) {
+            controller.peerExceptions(peerAddr, e.getCause().toString());
+            PcepParseException errMsgParse = (PcepParseException) e.getCause();
+            byte errorType = errMsgParse.getErrorType();
+            byte errorValue = errMsgParse.getErrorValue();
+
+            if ((errorType == (byte) 0x0) && (errorValue == (byte) 0x0)) {
+                processUnknownMsg();
+            } else {
+                errMsg = getErrorMsg(errorType, errorValue);
+                log.debug("Sending PCEP-ERROR message to PCC.");
+                channel.write(Collections.singletonList(errMsg));
+            }
+        } else if (e.getCause() instanceof RejectedExecutionException) {
+            log.warn("Could not process message: queue full");
+            controller.peerExceptions(peerAddr, e.getCause().toString());
+        } else {
+            log.error("Error while processing message from client " + getClientInfoString() + "state " + this.state);
+            controller.peerExceptions(peerAddr, e.getCause().toString());
+            channel.close();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getClientInfoString();
+    }
+
+    @Override
+    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
+        if (!isHandshakeComplete()) {
+            return;
+        }
+
+        if (e.getState() == IdleState.READER_IDLE) {
+            // When no message is received on channel for read timeout, then close
+            // the channel
+            log.info("Disconnecting client {} due to read timeout", getClientInfoString());
+            ctx.getChannel().close();
+        } else if (e.getState() == IdleState.WRITER_IDLE) {
+            // Send keep alive message
+            log.debug("Sending keep alive message due to IdleState timeout " + pc.toString());
+            pc.sendMessage(Collections.singletonList(pc.factory().buildKeepaliveMsg().build()));
+        }
+    }
+
+    @Override
+    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+        if (e.getMessage() instanceof List) {
+            @SuppressWarnings("unchecked")
+            List<PcepMessage> msglist = (List<PcepMessage>) e.getMessage();
+            for (PcepMessage pm : msglist) {
+                // Do the actual packet processing
+                state.processPcepMessage(this, pm);
+            }
+        } else {
+            state.processPcepMessage(this, (PcepMessage) e.getMessage());
+        }
+    }
+
+    /**
+     * Is this a state in which the handshake has completed.
+     *
+     * @return true if the handshake is complete
+     */
+    public boolean isHandshakeComplete() {
+        return this.state.isHandshakeComplete();
+    }
+
+    /**
+     * To set the handshake status.
+     *
+     * @param handshakeComplete value is handshake status
+     */
+    public void setHandshakeComplete(boolean handshakeComplete) {
+        this.state.setHandshakeComplete(handshakeComplete);
+    }
+
+    /**
+     * To handle the pcep message.
+     *
+     * @param m pcep message
+     */
+    private void dispatchMessage(PcepMessage m) {
+        pc.handleMessage(m);
+    }
+
+    /**
+     * Adds PCEP device configuration with capabilities once session is established.
+     */
+    private void addNode() {
+        pc.addNode(pc);
+    }
+
+    /**
+     * Deletes PCEP device configuration when session is disconnected.
+     */
+    private void deleteNode() {
+        pc.deleteNode(pc.getPccId());
+    }
+
+    /**
+     * Return a string describing this client based on the already available
+     * information (ip address and/or remote socket).
+     *
+     * @return display string
+     */
+    private String getClientInfoString() {
+        if (pc != null) {
+            return pc.toString();
+        }
+        String channelString;
+        if (channel == null || channel.getRemoteAddress() == null) {
+            channelString = "?";
+        } else {
+            channelString = channel.getRemoteAddress().toString();
+        }
+        String pccIpString;
+        // TODO : implement functionality to get pcc id string
+        pccIpString = "?";
+        return String.format("[%s PCCIP[%s]]", channelString, pccIpString);
+    }
+
+    /**
+     * Update the channels state. Only called from the state machine.
+     *
+     * @param state
+     */
+    private void setState(ChannelState state) {
+        this.state = state;
+    }
+
+    /**
+     * Send handshake open message.
+     *
+     * @throws IOException,PcepParseException
+     */
+    private void sendHandshakeOpenMessage() throws IOException, PcepParseException {
+        PcepOpenObject pcepOpenobj = factory1.buildOpenObject()
+                .setSessionId(sessionId)
+                .setKeepAliveTime(keepAliveTime)
+                .setDeadTime(deadTime)
+                .build();
+        PcepMessage msg = factory1.buildOpenMsg()
+                .setPcepOpenObj(pcepOpenobj)
+                .build();
+        log.debug("Sending OPEN message to {}", channel.getRemoteAddress());
+        channel.write(Collections.singletonList(msg));
+    }
+
+    //Capability negotiation
+    private void capabilityNegotiation(PcepOpenMsg pOpenmsg) {
+        LinkedList<PcepValueType> tlvList = pOpenmsg.getPcepOpenObject().getOptionalTlv();
+        boolean pceccCapability = false;
+        boolean statefulPceCapability = false;
+        boolean pcInstantiationCapability = false;
+        boolean labelStackCapability = false;
+        boolean srCapability = false;
+
+        ListIterator<PcepValueType> listIterator = tlvList.listIterator();
+        while (listIterator.hasNext()) {
+            PcepValueType tlv = listIterator.next();
+
+            switch (tlv.getType()) {
+                case PceccCapabilityTlv.TYPE:
+                    pceccCapability = true;
+                    if (((PceccCapabilityTlv) tlv).sBit()) {
+                        labelStackCapability = true;
+                    }
+                    break;
+                case StatefulPceCapabilityTlv.TYPE:
+                    statefulPceCapability = true;
+                    StatefulPceCapabilityTlv stetefulPcCapTlv = (StatefulPceCapabilityTlv) tlv;
+                    if (stetefulPcCapTlv.getIFlag()) {
+                        pcInstantiationCapability = true;
+                    }
+                    break;
+                case SrPceCapabilityTlv.TYPE:
+                    srCapability = true;
+                    break;
+                default:
+                    continue;
+            }
+        }
+        this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability,
+                labelStackCapability, srCapability);
+    }
+
+    /**
+     * Send keep alive message.
+     *
+     * @throws IOException        when channel is disconnected
+     * @throws PcepParseException while building keep alive message
+     */
+    private void sendKeepAliveMessage() throws IOException, PcepParseException {
+        PcepMessage msg = factory1.buildKeepaliveMsg().build();
+        log.debug("Sending KEEPALIVE message to {}", channel.getRemoteAddress());
+        channel.write(Collections.singletonList(msg));
+    }
+
+    /**
+     * Send error message and close channel with pcc.
+     */
+    private void sendErrMsgAndCloseChannel() {
+        // TODO send error message
+        //Remove PCEP device from topology
+        deleteNode();
+        channel.close();
+    }
+
+    /**
+     * Send error message when an invalid message is received.
+     *
+     * @throws PcepParseException while building error message
+     */
+    private void sendErrMsgForInvalidMsg() throws PcepParseException {
+        byte errorType = 0x02;
+        byte errorValue = 0x00;
+        PcepErrorMsg errMsg = getErrorMsg(errorType, errorValue);
+        channel.write(Collections.singletonList(errMsg));
+    }
+
+    /**
+     * Builds pcep error message based on error value and error type.
+     *
+     * @param errorType  pcep error type
+     * @param errorValue pcep error value
+     * @return pcep error message
+     * @throws PcepParseException while bulding error message
+     */
+    public PcepErrorMsg getErrorMsg(byte errorType, byte errorValue) throws PcepParseException {
+        LinkedList<PcepErrorObject> llerrObj = new LinkedList<>();
+        PcepErrorMsg errMsg;
+
+        PcepErrorObject errObj = factory1.buildPcepErrorObject()
+                .setErrorValue(errorValue)
+                .setErrorType(errorType)
+                .build();
+
+        llerrObj.add(errObj);
+
+        //If Error caught in other than Openmessage
+        LinkedList<PcepError> llPcepErr = new LinkedList<>();
+
+        PcepError pcepErr = factory1.buildPcepError()
+                .setErrorObjList(llerrObj)
+                .build();
+
+        llPcepErr.add(pcepErr);
+
+        PcepErrorInfo errInfo = factory1.buildPcepErrorInfo()
+                .setPcepErrorList(llPcepErr)
+                .build();
+
+        errMsg = factory1.buildPcepErrorMsg()
+                .setPcepErrorInfo(errInfo)
+                .build();
+        return errMsg;
+    }
+
+    /**
+     * Process unknown pcep message received.
+     *
+     * @throws PcepParseException while building pcep error message
+     */
+    public void processUnknownMsg() throws PcepParseException {
+        Date now = null;
+        if (pcepPacketStats.wrongPacketCount() == 0) {
+            now = new Date();
+            pcepPacketStats.setTime(now.getTime());
+            pcepPacketStats.addWrongPacket();
+            sendErrMsgForInvalidMsg();
+        }
+
+        if (pcepPacketStats.wrongPacketCount() > 1) {
+            Date lastest = new Date();
+            pcepPacketStats.addWrongPacket();
+            //converting to seconds
+            if (((lastest.getTime() - pcepPacketStats.getTime()) / 1000) > 60) {
+                now = lastest;
+                pcepPacketStats.setTime(now.getTime());
+                pcepPacketStats.resetWrongPacket();
+                pcepPacketStats.addWrongPacket();
+            } else if (((int) (lastest.getTime() - now.getTime()) / 1000) < 60) {
+                if (MAX_WRONG_COUNT_PACKET <= pcepPacketStats.wrongPacketCount()) {
+                    //reset once wrong packet count reaches MAX_WRONG_COUNT_PACKET
+                    pcepPacketStats.resetWrongPacket();
+                    // max wrong packets received send error message and close the session
+                    sendErrMsgAndCloseChannel();
+                }
+            }
+        }
+    }
+
+    /**
+     * The state machine for handling the client/channel state. All state
+     * transitions should happen from within the state machine (and not from other
+     * parts of the code)
+     */
+    enum ChannelState {
+        /**
+         * Initial state before channel is connected.
+         */
+        INIT(false) {
+
+        },
+        /**
+         * Once the session is established, wait for open message.
+         */
+        OPENWAIT(false) {
+            @Override
+            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+
+                log.info("Message received in OPEN WAIT State");
+
+                //check for open message
+                if (m.getType() != PcepType.OPEN) {
+                    // When the message type is not open message increment the wrong packet statistics
+                    h.processUnknownMsg();
+                    log.debug("Message is not OPEN message");
+                } else {
+
+                    h.pcepPacketStats.addInPacket();
+                    PcepOpenMsg pOpenmsg = (PcepOpenMsg) m;
+                    //Do Capability negotiation.
+                    h.capabilityNegotiation(pOpenmsg);
+                    log.debug("Sending handshake OPEN message");
+                    h.sessionId = pOpenmsg.getPcepOpenObject().getSessionId();
+                    h.pcepVersion = pOpenmsg.getPcepOpenObject().getVersion();
+
+                    //setting keepalive and deadTimer
+                    byte yKeepalive = pOpenmsg.getPcepOpenObject().getKeepAliveTime();
+                    byte yDeadTimer = pOpenmsg.getPcepOpenObject().getDeadTime();
+                    h.keepAliveTime = yKeepalive;
+                    if (yKeepalive < yDeadTimer) {
+                        h.deadTime = yDeadTimer;
+                    } else {
+                        if (DEADTIMER_MAXIMUM_VALUE > (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER)) {
+                            h.deadTime = (byte) (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER);
+                        } else {
+                            h.deadTime = DEADTIMER_MAXIMUM_VALUE;
+                        }
+                    }
+
+                        /*
+                         * If MPLS LSR id and PCEP session socket IP addresses are not same,
+                         * the MPLS LSR id will be encoded in separate TLV.
+                         * We always maintain session information based on LSR ids.
+                         * The socket IP is stored in channel.
+                         */
+                    LinkedList<PcepValueType> optionalTlvs = pOpenmsg.getPcepOpenObject().getOptionalTlv();
+                    if (optionalTlvs != null) {
+                        for (PcepValueType optionalTlv : optionalTlvs) {
+                            if (optionalTlv instanceof NodeAttributesTlv) {
+                                List<PcepValueType> subTlvs = ((NodeAttributesTlv) optionalTlv)
+                                        .getllNodeAttributesSubTLVs();
+                                if (subTlvs == null) {
+                                    break;
+                                }
+                                for (PcepValueType subTlv : subTlvs) {
+                                    if (subTlv instanceof IPv4RouterIdOfLocalNodeSubTlv) {
+                                        h.thispccId = PccId.pccId(IpAddress
+                                                .valueOf(((IPv4RouterIdOfLocalNodeSubTlv) subTlv).getInt()));
+                                        break;
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                    }
+
+                    if (h.thispccId == null) {
+                        final SocketAddress address = h.channel.getRemoteAddress();
+                        if (!(address instanceof InetSocketAddress)) {
+                            throw new IOException("Invalid client connection. Pcc is indentifed based on IP");
+                        }
+
+                        final InetSocketAddress inetAddress = (InetSocketAddress) address;
+                        h.thispccId = PccId.pccId(IpAddress.valueOf(inetAddress.getAddress()));
+                    }
+
+                    h.sendHandshakeOpenMessage();
+                    h.pcepPacketStats.addOutPacket();
+                    h.setState(KEEPWAIT);
+                    h.controller.peerStatus(h.peerAddr.toString(), PcepCfg.State.KEEPWAIT.toString(), h.sessionId);
+                }
+            }
+        },
+        /**
+         * Once the open messages are exchanged, wait for keep alive message.
+         */
+        KEEPWAIT(false) {
+            @Override
+            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+                log.info("Message received in KEEPWAIT state");
+                //check for keep alive message
+                if (m.getType() != PcepType.KEEP_ALIVE) {
+                    // When the message type is not keep alive message increment the wrong packet statistics
+                    h.processUnknownMsg();
+                    log.error("Message is not KEEPALIVE message");
+                } else {
+                    // Set the client connected status
+                    h.pcepPacketStats.addInPacket();
+                    log.debug("sending keep alive message in KEEPWAIT state");
+                    h.pc = h.controller.getPcepClientInstance(h.thispccId, h.sessionId, h.pcepVersion,
+                            h.pcepPacketStats);
+                    //Get pc instance and set capabilities
+                    h.pc.setCapability(h.capability);
+
+                    // Initilialize DB sync status.
+                    h.pc.setLspDbSyncStatus(NOT_SYNCED);
+                    h.pc.setLabelDbSyncStatus(NOT_SYNCED);
+
+                    // set the status of pcc as connected
+                    h.pc.setConnected(true);
+                    h.pc.setChannel(h.channel);
+
+                    // set any other specific parameters to the pcc
+                    h.pc.setPcVersion(h.pcepVersion);
+                    h.pc.setPcSessionId(h.sessionId);
+                    h.pc.setPcKeepAliveTime(h.keepAliveTime);
+                    h.pc.setPcDeadTime(h.deadTime);
+                    int keepAliveTimer = h.keepAliveTime & BYTE_MASK;
+                    int deadTimer = h.deadTime & BYTE_MASK;
+                    if (0 == h.keepAliveTime) {
+                        h.deadTime = 0;
+                    }
+                    // handle keep alive and dead time
+                    if (keepAliveTimer != PcepPipelineFactory.DEFAULT_KEEP_ALIVE_TIME
+                            || deadTimer != PcepPipelineFactory.DEFAULT_DEAD_TIME) {
+
+                        h.channel.getPipeline().replace("idle", "idle",
+                                new IdleStateHandler(PcepPipelineFactory.TIMER, deadTimer, keepAliveTimer, 0));
+                    }
+                    log.debug("Dead timer : " + deadTimer);
+                    log.debug("Keep alive time : " + keepAliveTimer);
+
+                    //set the state handshake completion.
+
+                    h.sendKeepAliveMessage();
+                    h.pcepPacketStats.addOutPacket();
+                    h.setHandshakeComplete(true);
+
+                    if (!h.pc.connectClient()) {
+                        disconnectDuplicate(h);
+                    } else {
+                        h.setState(ESTABLISHED);
+                     h.controller.peerStatus(h.peerAddr.toString(), PcepCfg.State.ESTABLISHED.toString(), h.sessionId);
+                        //Session is established, add a network configuration with LSR id and device capabilities.
+                        h.addNode();
+                    }
+                }
+            }
+        },
+        /**
+         * Once the keep alive messages are exchanged, the state is established.
+         */
+        ESTABLISHED(true) {
+            @Override
+            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+
+                //h.channel.getPipeline().remove("waittimeout");
+                log.debug("Message received in established state " + m.getType());
+                //dispatch the message
+                h.dispatchMessage(m);
+            }
+        };
+        private boolean handshakeComplete;
+
+        ChannelState(boolean handshakeComplete) {
+            this.handshakeComplete = handshakeComplete;
+        }
+
+        void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+            // do nothing
+        }
+
+        /**
+         * Is this a state in which the handshake has completed.
+         *
+         * @return true if the handshake is complete
+         */
+        public boolean isHandshakeComplete() {
+            return this.handshakeComplete;
+        }
+
+        /**
+         * Sets handshake complete status.
+         *
+         * @param handshakeComplete status of handshake
+         */
+        public void setHandshakeComplete(boolean handshakeComplete) {
+            this.handshakeComplete = handshakeComplete;
+        }
+
+        protected void disconnectDuplicate(PcepChannelHandler h) {
+            log.error("Duplicated Pcc IP or incompleted cleanup - " + "disconnecting channel {}",
+                    h.getClientInfoString());
+            h.duplicatePccIdFound = Boolean.TRUE;
+            h.channel.disconnect();
+        }
+
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java
new file mode 100644
index 0000000..2ddc819
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java
@@ -0,0 +1,1230 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ListIterator;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+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.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.server.LspKey;
+import org.onosproject.pcep.server.LspType;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepClientController;
+import org.onosproject.pcep.server.PcepClientListener;
+import org.onosproject.pcep.server.PcepEventListener;
+import org.onosproject.pcep.server.PcepLspStatus;
+import org.onosproject.pcep.server.PcepNodeListener;
+import org.onosproject.pcep.server.SrpIdGenerators;
+import org.onosproject.pcep.server.driver.PcepAgent;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcInitiatedLspRequest;
+import org.onosproject.pcepio.protocol.PcepError;
+import org.onosproject.pcepio.protocol.PcepErrorInfo;
+import org.onosproject.pcepio.protocol.PcepErrorMsg;
+import org.onosproject.pcepio.protocol.PcepErrorObject;
+import org.onosproject.pcepio.protocol.PcepFactory;
+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;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import static org.onosproject.pcep.server.PcepSyncStatus.IN_SYNC;
+import static org.onosproject.pcep.server.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
+import static org.onosproject.pcep.server.LspType.WITH_SIGNALLING;
+import static org.onosproject.pcep.server.PcepLspSyncAction.REMOVE;
+import static org.onosproject.pcep.server.PcepLspSyncAction.SEND_UPDATE;
+import static org.onosproject.pcep.server.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.server.PcepAnnotationKeys.BANDWIDTH;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.LOCAL_LSP_ID;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.LSP_SIG_TYPE;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.PCC_TUNNEL_ID;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.PCE_INIT;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.PLSP_ID;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.DELEGATE;
+import static org.onosproject.pcep.server.PcepAnnotationKeys.COST_TYPE;
+import static org.onosproject.pcep.server.PcepSyncStatus.SYNCED;
+import static org.onosproject.pcep.server.PcepSyncStatus.NOT_SYNCED;
+
+/**
+ * Implementation of PCEP client controller.
+ */
+@Component(immediate = true)
+@Service
+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<>();
+
+    protected PcepClientAgent agent = new PcepClientAgent();
+    protected Set<PcepClientListener> pcepClientListener = new HashSet<>();
+
+    protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
+    protected Set<PcepNodeListener> pcepNodeListener = 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";
+
+    private BasicPceccHandler crHandler;
+    private PceccSrTeBeHandler srTeHandler;
+
+    private DeviceListener deviceListener = new InternalDeviceListener();
+    private LinkListener linkListener = new InternalLinkListener();
+    private InternalConfigListener cfgListener = new InternalConfigListener();
+    private Map<Integer, Integer> pcepErrorMsg = new TreeMap<>();
+
+    @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");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        // Close all connected clients
+        closeConnectedClients();
+        deviceService.removeListener(deviceListener);
+        linkService.removeListener(linkListener);
+        netCfgService.removeListener(cfgListener);
+        ctrl.stop();
+        log.info("Stopped");
+    }
+
+    @Override
+    public void peerErrorMsg(String peerId, Integer errorType, Integer errValue) {
+        if (peerId == null) {
+            pcepErrorMsg.put(errorType, errValue);
+        } else {
+            if (pcepErrorMsg.size() > 10) {
+                pcepErrorMsg.clear();
+            }
+            pcepErrorMsg.put(errorType, errValue);
+        }
+    }
+
+    @Override
+    public Map<String, List<String>> getPcepExceptions() {
+        return this.ctrl.exceptionsMap();
+    }
+
+    @Override
+    public Map<Integer, Integer> getPcepErrorMsg() {
+        return pcepErrorMsg;
+    }
+
+
+    @Override
+    public Map<String, String> getPcepSessionMap() {
+        return this.ctrl.mapPeer();
+    }
+
+    @Override
+    public Map<String, Byte> getPcepSessionIdMap() {
+        return this.ctrl.mapSession();
+    }
+
+    @Override
+    public Collection<PcepClient> getClients() {
+        return connectedClients.values();
+    }
+
+    @Override
+    public PcepClient getClient(PccId pccId) {
+        return connectedClients.get(pccId);
+    }
+
+    @Override
+    public void addListener(PcepClientListener listener) {
+        if (!pcepClientListener.contains(listener)) {
+            this.pcepClientListener.add(listener);
+        }
+    }
+
+    @Override
+    public void removeListener(PcepClientListener listener) {
+        this.pcepClientListener.remove(listener);
+    }
+
+    @Override
+    public void addEventListener(PcepEventListener listener) {
+        pcepEventListener.add(listener);
+    }
+
+    @Override
+    public void removeEventListener(PcepEventListener listener) {
+        pcepEventListener.remove(listener);
+    }
+
+    @Override
+    public void writeMessage(PccId pccId, PcepMessage msg) {
+        this.getClient(pccId).sendMessage(msg);
+    }
+
+    @Override
+    public void addNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.add(listener);
+    }
+
+    @Override
+    public void removeNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.remove(listener);
+    }
+
+    @Override
+    public void processClientMessage(PccId pccId, PcepMessage msg) {
+        PcepClient pc = getClient(pccId);
+
+        switch (msg.getType()) {
+        case NONE:
+            break;
+        case OPEN:
+            break;
+        case KEEP_ALIVE:
+            break;
+        case PATH_COMPUTATION_REQUEST:
+            break;
+        case PATH_COMPUTATION_REPLY:
+            break;
+        case NOTIFICATION:
+            break;
+        case ERROR:
+            break;
+        case INITIATE:
+            if (!pc.capability().pcInstantiationCapability()) {
+                pc.sendMessage(Collections.singletonList(getErrMsg(pc.factory(), ERROR_TYPE_19,
+                        ERROR_VALUE_5)));
+            }
+            break;
+        case UPDATE:
+            if (!pc.capability().statefulPceCapability()) {
+                pc.sendMessage(Collections.singletonList(getErrMsg(pc.factory(), ERROR_TYPE_19,
+                        ERROR_VALUE_5)));
+            }
+            break;
+        case LABEL_UPDATE:
+            if (!pc.capability().pceccCapability()) {
+                pc.sendMessage(Collections.singletonList(getErrMsg(pc.factory(), ERROR_TYPE_19,
+                        ERROR_VALUE_5)));
+            }
+            break;
+        case CLOSE:
+            log.info("Sending Close Message  to {" + pccId.toString() + "}");
+            pc.sendMessage(Collections.singletonList(pc.factory().buildCloseMsg().build()));
+            //now disconnect client
+            pc.disconnectClient();
+            break;
+        case REPORT:
+            //Only update the listener if respective capability is supported else send PCEP-ERR msg
+            if (pc.capability().statefulPceCapability()) {
+
+                ListIterator<PcepStateReport> listIterator = ((PcepReportMsg) msg).getStateReportList().listIterator();
+                while (listIterator.hasNext()) {
+                    PcepStateReport stateRpt = listIterator.next();
+                    PcepLspObject lspObj = stateRpt.getLspObject();
+                    if (lspObj.getSFlag()) {
+                        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(IN_SYNC);
+                            pc.initializeSyncMsgList(pccId);
+                        }
+                        // Store stateRpt in temporary cache.
+                        pc.addSyncMsgToList(pccId, stateRpt);
+
+                        // Don't send to provider as of now.
+                        continue;
+                    } else if (lspObj.getPlspId() == 0) {
+                        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(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);
+                                // 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.
+                                agent.analyzeSyncMsgList(pccId);
+                            }
+                            continue;
+                        }
+                    }
+
+                    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);
+                    PcepMessage pcReportMsg = pc.factory().buildReportMsg().setStateReportList((llPcRptList))
+                            .build();
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleMessage(pccId, pcReportMsg);
+                    }
+                }
+            } else {
+                // Send PCEP-ERROR message.
+                pc.sendMessage(Collections.singletonList(getErrMsg(pc.factory(),
+                        ERROR_TYPE_19, ERROR_VALUE_5)));
+            }
+            break;
+        case LABEL_RANGE_RESERV:
+            break;
+        case LS_REPORT: //TODO: need to handle LS report to add or remove node
+            break;
+        case MAX:
+            break;
+        case END:
+            break;
+        default:
+            break;
+        }
+    }
+
+    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;
+        for (PccId id : connectedClients.keySet()) {
+            pc = getClient(id);
+            pc.disconnectClient();
+        }
+    }
+
+    /**
+     * Returns pcep error message with specific error type and value.
+     *
+     * @param factory represents pcep factory
+     * @param errorType pcep error type
+     * @param errorValue pcep error value
+     * @return pcep error message
+     */
+    public PcepErrorMsg getErrMsg(PcepFactory factory, byte errorType, byte errorValue) {
+        LinkedList<PcepError> llPcepErr = new LinkedList<>();
+
+        LinkedList<PcepErrorObject> llerrObj = new LinkedList<>();
+        PcepErrorMsg errMsg;
+
+        PcepErrorObject errObj = factory.buildPcepErrorObject().setErrorValue(errorValue).setErrorType(errorType)
+                .build();
+
+        llerrObj.add(errObj);
+        PcepError pcepErr = factory.buildPcepError().setErrorObjList(llerrObj).build();
+
+        llPcepErr.add(pcepErr);
+
+        PcepErrorInfo errInfo = factory.buildPcepErrorInfo().setPcepErrorList(llPcepErr).build();
+
+        errMsg = factory.buildPcepErrorMsg().setPcepErrorInfo(errInfo).build();
+        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 label stack
+     * @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
+     * they are.
+     */
+    public class PcepClientAgent implements PcepAgent {
+
+        private final Logger log = LoggerFactory.getLogger(PcepClientAgent.class);
+
+        @Override
+        public boolean addConnectedClient(PccId pccId, PcepClient pc) {
+
+            if (connectedClients.get(pccId) != null) {
+                log.error("Trying to add connectedClient but found a previous "
+                        + "value for pcc ip: {}", pccId.toString());
+                return false;
+            } else {
+                log.debug("Added Client {}", pccId.toString());
+                connectedClients.put(pccId, pc);
+                for (PcepClientListener l : pcepClientListener) {
+                    l.clientConnected(pccId);
+                }
+                return true;
+            }
+        }
+
+        @Override
+        public boolean validActivation(PccId pccId) {
+            if (connectedClients.get(pccId) == null) {
+                log.error("Trying to activate client but is not in "
+                        + "connected client: pccIp {}. Aborting ..", pccId.toString());
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public void removeConnectedClient(PccId pccId) {
+
+            connectedClients.remove(pccId);
+            for (PcepClientListener l : pcepClientListener) {
+                log.warn("Removal for {}", pccId.toString());
+                l.clientDisconnected(pccId);
+            }
+        }
+
+        @Override
+        public void processPcepMessage(PccId pccId, PcepMessage m) {
+            processClientMessage(pccId, m);
+        }
+
+        @Override
+        public void addNode(PcepClient pc) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.addDevicePcepConfig(pc);
+            }
+        }
+
+        @Override
+        public void deleteNode(PccId pccId) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.deleteDevicePcepConfig(pccId);
+            }
+        }
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        @Override
+        public boolean analyzeSyncMsgList(PccId pccId) {
+            PcepClient pc = getClient(pccId);
+            /*
+             * 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. So two separate lists with separate keys are maintained.
+             */
+            Map<LspKey, Tunnel> preSyncLspDbByKey = new HashMap<>();
+            Map<String, Tunnel> preSyncLspDbByName = new HashMap<>();
+
+            // Query tunnel service and fetch all the tunnels with this PCC as ingress.
+            // Organize into two maps, with LSP key if known otherwise with symbolic path name, for quick search.
+            Collection<Tunnel> queriedTunnels = tunnelService.queryTunnel(Tunnel.Type.MPLS);
+            for (Tunnel tunnel : queriedTunnels) {
+                if (((IpTunnelEndPoint) tunnel.src()).ip().equals(pccId.ipAddress())) {
+                    String pLspId = tunnel.annotations().value(PLSP_ID);
+                    if (pLspId != null) {
+                        String localLspId = tunnel.annotations().value(LOCAL_LSP_ID);
+                        checkNotNull(localLspId);
+                        LspKey lspKey = new LspKey(Integer.valueOf(pLspId), Short.valueOf(localLspId));
+                        preSyncLspDbByKey.put(lspKey, tunnel);
+                    } else {
+                        preSyncLspDbByName.put(tunnel.tunnelName().value(), tunnel);
+                    }
+                }
+            }
+
+            List<PcepStateReport> syncStateRptList = pc.getSyncMsgList(pccId);
+            if (syncStateRptList == null) {
+                // When there are no LSPs to sync, directly end-of-sync PCRpt will come and the
+                // list will be null.
+                syncStateRptList = Collections.EMPTY_LIST;
+                log.debug("No LSPs reported from PCC during sync.");
+            }
+
+            Iterator<PcepStateReport> stateRptListIterator = syncStateRptList.iterator();
+
+            // For every report, fetch PLSP id, local LSP id and symbolic path name from the message.
+            while (stateRptListIterator.hasNext()) {
+                PcepStateReport stateRpt = stateRptListIterator.next();
+                Tunnel tunnel = null;
+
+                PcepLspObject lspObj = stateRpt.getLspObject();
+                ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
+                StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv = null;
+                SymbolicPathNameTlv pathNameTlv = 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;
+                    }
+                }
+
+                LspKey lspKeyOfRpt = new LspKey(lspObj.getPlspId(), ipv4LspIdenTlv.getLspId());
+                tunnel = preSyncLspDbByKey.get(lspKeyOfRpt);
+                // PCE tunnel is matched with PCRpt LSP. Now delete it from the preSyncLspDb list as the residual
+                // non-matching list will be processed at the end.
+                if (tunnel != null) {
+                    preSyncLspDbByKey.remove(lspKeyOfRpt);
+                } else if (pathNameTlv != null) {
+                    tunnel = preSyncLspDbByName.get(Arrays.toString(pathNameTlv.getValue()));
+                    if (tunnel != null) {
+                        preSyncLspDbByName.remove(tunnel.tunnelName().value());
+                    }
+                }
+
+                if (tunnel == null) {
+                    // If remove flag is set, and tunnel is not known to PCE, ignore it.
+                    if (lspObj.getCFlag() && !lspObj.getRFlag()) {
+                        // For initiated LSP, need to send PCInit delete msg.
+                        try {
+                            PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(SrpIdGenerators.create())
+                                    .setRFlag(true).build();
+                            PcInitiatedLspRequest releaseLspRequest = pc.factory().buildPcInitiatedLspRequest()
+                                    .setLspObject(lspObj).setSrpObject(srpobj).build();
+                            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList
+                                    = new LinkedList<PcInitiatedLspRequest>();
+                            llPcInitiatedLspRequestList.add(releaseLspRequest);
+
+                            PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
+                                    .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList).build();
+
+                            pc.sendMessage(Collections.singletonList(pcInitiateMsg));
+                        } catch (PcepParseException e) {
+                            log.error("Exception occured while sending initiate delete message {}", e.getMessage());
+                        }
+                        continue;
+                    }
+                }
+
+                if (!lspObj.getCFlag()) {
+                    // For learned LSP process both add/update PCRpt.
+                    LinkedList<PcepStateReport> llPcRptList = new LinkedList<>();
+                    llPcRptList.add(stateRpt);
+                    PcepMessage pcReportMsg = pc.factory().buildReportMsg().setStateReportList((llPcRptList))
+                            .build();
+
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleMessage(pccId, pcReportMsg);
+                    }
+                    continue;
+                }
+
+                // Implied that tunnel != null and lspObj.getCFlag() is set
+                // State different for PCC sent LSP and PCE known LSP, send PCUpd msg.
+                State tunnelState = PcepLspStatus
+                        .getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
+                if (tunnelState != tunnel.state()) {
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleEndOfSyncAction(tunnel, SEND_UPDATE);
+                    }
+                }
+            }
+
+            // Check which tunnels are extra at PCE that were not reported by PCC.
+            Map<Object, Tunnel> preSyncLspDb = (Map) preSyncLspDbByKey;
+            handleResidualTunnels(preSyncLspDb);
+            preSyncLspDbByKey = null;
+
+            preSyncLspDb = (Map) preSyncLspDbByName;
+            handleResidualTunnels(preSyncLspDb);
+            preSyncLspDbByName = null;
+            preSyncLspDb = null;
+
+            pc.removeSyncMsgList(pccId);
+            return true;
+        }
+
+        /*
+         * Go through the tunnels which are known by PCE but were not reported by PCC during LSP DB sync and take
+         * appropriate actions.
+         */
+        private void handleResidualTunnels(Map<Object, Tunnel> preSyncLspDb) {
+            for (Tunnel pceExtraTunnel : preSyncLspDb.values()) {
+                if (pceExtraTunnel.annotations().value(PCE_INIT) == null
+                        || "false".equalsIgnoreCase(pceExtraTunnel.annotations().value(PCE_INIT))) {
+                    // PCC initiated tunnels should be removed from tunnel store.
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleEndOfSyncAction(pceExtraTunnel, REMOVE);
+                    }
+                } else {
+                    // PCE initiated tunnels should be initiated again.
+                    for (PcepEventListener l : pcepEventListener) {
+                        l.handleEndOfSyncAction(pceExtraTunnel, UNSTABLE);
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * 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/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientImpl.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientImpl.java
new file mode 100644
index 0000000..7e52c19
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientImpl.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.jboss.netty.channel.Channel;
+import org.onlab.packet.IpAddress;
+import org.onosproject.pcep.server.ClientCapability;
+import org.onosproject.pcep.server.LspKey;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepPacketStats;
+import org.onosproject.pcep.server.PcepSyncStatus;
+import org.onosproject.pcep.server.driver.PcepAgent;
+import org.onosproject.pcep.server.driver.PcepClientDriver;
+import org.onosproject.pcepio.protocol.PcepFactories;
+import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepStateReport;
+import org.onosproject.pcepio.protocol.PcepVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * An abstract representation of an OpenFlow switch. Can be extended by others
+ * to serve as a base for their vendor specific representation of a switch.
+ */
+public class PcepClientImpl implements PcepClientDriver {
+
+    protected final Logger log = LoggerFactory.getLogger(PcepClientImpl.class);
+
+    private static final String SHUTDOWN_MSG = "Worker has already been shutdown";
+
+    private Channel channel;
+    protected String channelId;
+
+    private boolean connected;
+    protected boolean startDriverHandshakeCalled;
+    protected boolean isHandShakeComplete;
+    private PcepSyncStatus lspDbSyncStatus;
+    private PcepSyncStatus labelDbSyncStatus;
+    private PccId pccId;
+    private PcepAgent agent;
+
+    private ClientCapability capability;
+    private PcepVersion pcepVersion;
+    private byte keepAliveTime;
+    private byte deadTime;
+    private byte sessionId;
+    private PcepPacketStatsImpl pktStats;
+    private Map<LspKey, Boolean> lspDelegationInfo = new HashMap<>();
+    private Map<PccId, List<PcepStateReport>> syncRptCache = new HashMap<>();
+
+    @Override
+    public void init(PccId pccId, PcepVersion pcepVersion, PcepPacketStats pktStats) {
+        this.pccId = pccId;
+        this.pcepVersion = pcepVersion;
+        this.pktStats = (PcepPacketStatsImpl) pktStats;
+    }
+
+    @Override
+    public final void disconnectClient() {
+        this.channel.close();
+    }
+
+    @Override
+    public void setCapability(ClientCapability capability) {
+        this.capability = capability;
+    }
+
+    @Override
+    public ClientCapability capability() {
+        return capability;
+    }
+
+    @Override
+    public final void sendMessage(PcepMessage m) {
+        log.debug("Sending message to {}", channel.getRemoteAddress());
+        try {
+            channel.write(Collections.singletonList(m));
+            this.pktStats.addOutPacket();
+        } catch (RejectedExecutionException e) {
+            log.warn(e.getMessage());
+            if (!e.getMessage().contains(SHUTDOWN_MSG)) {
+                throw e;
+            }
+        }
+    }
+
+    @Override
+    public final void sendMessage(List<PcepMessage> msgs) {
+        try {
+            channel.write(msgs);
+            this.pktStats.addOutPacket(msgs.size());
+        } catch (RejectedExecutionException e) {
+            log.warn(e.getMessage());
+            if (!e.getMessage().contains(SHUTDOWN_MSG)) {
+                throw e;
+            }
+        }
+    }
+
+    @Override
+    public final boolean isConnected() {
+        return this.connected;
+    }
+
+    @Override
+    public final void setConnected(boolean connected) {
+        this.connected = connected;
+    };
+
+    @Override
+    public final void setChannel(Channel channel) {
+        this.channel = channel;
+        final SocketAddress address = channel.getRemoteAddress();
+        if (address instanceof InetSocketAddress) {
+            final InetSocketAddress inetAddress = (InetSocketAddress) address;
+            final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress());
+            if (ipAddress.isIp4()) {
+                channelId = ipAddress.toString() + ':' + inetAddress.getPort();
+            } else {
+                channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort();
+            }
+        }
+    };
+
+    @Override
+    public String channelId() {
+        return channelId;
+    }
+
+    @Override
+    public final PccId getPccId() {
+        return this.pccId;
+    }
+
+    @Override
+    public final String getStringId() {
+        return this.pccId.toString();
+    }
+
+    @Override
+    public final void setPcVersion(PcepVersion pcepVersion) {
+        this.pcepVersion = pcepVersion;
+    }
+
+    @Override
+    public void setPcKeepAliveTime(byte keepAliveTime) {
+        this.keepAliveTime = keepAliveTime;
+    }
+
+    @Override
+    public void setPcDeadTime(byte deadTime) {
+        this.deadTime = deadTime;
+    }
+
+    @Override
+    public void setPcSessionId(byte sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    @Override
+    public void setLspDbSyncStatus(PcepSyncStatus syncStatus) {
+        log.debug("LSP DB sync status set from {} to {}", this.lspDbSyncStatus, syncStatus);
+        this.lspDbSyncStatus = syncStatus;
+    }
+
+    @Override
+    public PcepSyncStatus lspDbSyncStatus() {
+        return lspDbSyncStatus;
+    }
+
+    @Override
+    public void setLabelDbSyncStatus(PcepSyncStatus syncStatus) {
+
+        PcepSyncStatus syncOldStatus = labelDbSyncStatus();
+        this.labelDbSyncStatus = syncStatus;
+        log.debug("Label DB sync status set from {} to {}", syncOldStatus, syncStatus);
+        if ((syncOldStatus == PcepSyncStatus.IN_SYNC) && (syncStatus == PcepSyncStatus.SYNCED)) {
+            // Perform end of LSP DB sync actions.
+            this.agent.analyzeSyncMsgList(pccId);
+        }
+    }
+
+    @Override
+    public PcepSyncStatus labelDbSyncStatus() {
+        return labelDbSyncStatus;
+    }
+
+    @Override
+    public final void handleMessage(PcepMessage m) {
+        this.pktStats.addInPacket();
+        this.agent.processPcepMessage(pccId, m);
+    }
+
+    @Override
+    public void addNode(PcepClient pc) {
+        this.agent.addNode(pc);
+    }
+
+    @Override
+    public void deleteNode(PccId pccId) {
+        this.agent.deleteNode(pccId);
+    }
+
+    @Override
+    public final boolean connectClient() {
+        return this.agent.addConnectedClient(pccId, this);
+    }
+
+    @Override
+    public final void removeConnectedClient() {
+        this.agent.removeConnectedClient(pccId);
+    }
+
+    @Override
+    public PcepFactory factory() {
+        return PcepFactories.getFactory(pcepVersion);
+    }
+
+    @Override
+    public boolean isHandshakeComplete() {
+        return isHandShakeComplete;
+    }
+
+    @Override
+    public final void setAgent(PcepAgent ag) {
+        if (this.agent == null) {
+            this.agent = ag;
+        }
+    }
+
+    @Override
+    public void setLspAndDelegationInfo(LspKey lspKey, boolean dFlag) {
+        lspDelegationInfo.put(lspKey, dFlag);
+    }
+
+    @Override
+    public Boolean delegationInfo(LspKey lspKey) {
+        return lspDelegationInfo.get(lspKey);
+    }
+
+    @Override
+    public void initializeSyncMsgList(PccId pccId) {
+        List<PcepStateReport> rptMsgList = new LinkedList<>();
+        syncRptCache.put(pccId, rptMsgList);
+    }
+
+    @Override
+    public List<PcepStateReport> getSyncMsgList(PccId pccId) {
+        return syncRptCache.get(pccId);
+    }
+
+    @Override
+    public void removeSyncMsgList(PccId pccId) {
+        syncRptCache.remove(pccId);
+    }
+
+    @Override
+    public void addSyncMsgToList(PccId pccId, PcepStateReport rptMsg) {
+        List<PcepStateReport> rptMsgList = syncRptCache.get(pccId);
+        rptMsgList.add(rptMsg);
+        syncRptCache.put(pccId, rptMsgList);
+    }
+
+    @Override
+    public boolean isOptical() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("channel", channelId())
+                .add("pccId", getPccId())
+                .toString();
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepConfig.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepConfig.java
new file mode 100644
index 0000000..e6b5fe1
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepConfig.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepCfg;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.TreeMap;
+
+
+public class PcepConfig implements PcepCfg {
+
+    protected static final Logger log = LoggerFactory.getLogger(PcepConfig.class);
+
+    private State state = State.INIT;
+    private PccId pccId;
+    private TreeMap<String, PcepCfg> bgpPeerTree = new TreeMap<>();
+
+    @Override
+    public State getState() {
+        return state;
+    }
+
+    @Override
+    public void setState(State state) {
+        this.state = state;
+    }
+
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepControllerImpl.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepControllerImpl.java
new file mode 100644
index 0000000..8d9bc23
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepControllerImpl.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import com.google.common.collect.Sets;
+
+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.Service;
+import org.onosproject.net.DeviceId;
+import org.onosproject.pcep.api.PcepController;
+import org.onosproject.pcep.api.PcepDpid;
+import org.onosproject.pcep.api.PcepLinkListener;
+import org.onosproject.pcep.api.PcepSwitch;
+import org.onosproject.pcep.api.PcepSwitchListener;
+import org.onosproject.pcep.api.PcepTunnel;
+import org.onosproject.pcep.api.PcepTunnelListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+
+/**
+ * Implementation of PCEP controller [protocol].
+ */
+@Component(immediate = true)
+@Service
+public class PcepControllerImpl implements PcepController {
+
+    private static final Logger log = LoggerFactory.getLogger(PcepControllerImpl.class);
+
+    protected Set<PcepTunnelListener> pcepTunnelListener = Sets.newHashSet();
+    protected Set<PcepLinkListener> pcepLinkListener = Sets.newHashSet();
+    protected Set<PcepSwitchListener> pcepSwitchListener = Sets.newHashSet();
+
+    private final Controller ctrl = new Controller();
+
+    @Activate
+    public void activate() {
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        log.info("Stopped");
+    }
+
+    @Override
+    public Iterable<PcepSwitch> getSwitches() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public PcepSwitch getSwitch(PcepDpid did) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void addListener(PcepSwitchListener listener) {
+        this.pcepSwitchListener.add(listener);
+    }
+
+    @Override
+    public void removeListener(PcepSwitchListener listener) {
+        this.pcepSwitchListener.remove(listener);
+    }
+
+    @Override
+    public void addLinkListener(PcepLinkListener listener) {
+        this.pcepLinkListener.add(listener);
+    }
+
+    @Override
+    public void removeLinkListener(PcepLinkListener listener) {
+        this.pcepLinkListener.remove(listener);
+    }
+
+    @Override
+    public void addTunnelListener(PcepTunnelListener listener) {
+        this.pcepTunnelListener.add(listener);
+    }
+
+    @Override
+    public void removeTunnelListener(PcepTunnelListener listener) {
+        this.pcepTunnelListener.remove(listener);
+    }
+
+    @Override
+    public PcepTunnel applyTunnel(DeviceId srcDid, DeviceId dstDid, long srcPort, long dstPort, long bandwidth,
+            String name) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Boolean deleteTunnel(String id) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Boolean updateTunnelBandwidth(String id, long bandwidth) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void getTunnelStatistics(String pcepTunnelId) {
+        // TODO Auto-generated method stub
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepMessageDecoder.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepMessageDecoder.java
new file mode 100644
index 0000000..2c21b73
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepMessageDecoder.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+import org.onosproject.pcepio.exceptions.PcepOutOfBoundMessageException;
+import org.onosproject.pcepio.protocol.PcepFactories;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepMessageReader;
+import org.onosproject.pcepio.util.HexDump;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Decode an pcep message from a Channel, for use in a netty pipeline.
+ */
+public class PcepMessageDecoder extends FrameDecoder {
+
+    protected static final Logger log = LoggerFactory.getLogger(PcepMessageDecoder.class);
+
+    @Override
+    protected Object decode(ChannelHandlerContext ctx, Channel channel,
+            ChannelBuffer buffer) throws Exception {
+        log.debug("Message received.");
+        if (!channel.isConnected()) {
+            log.info("Channel is not connected.");
+            // In testing, I see decode being called AFTER decode last.
+            // This check avoids that from reading corrupted frames
+            return null;
+        }
+
+        HexDump.pcepHexDump(buffer);
+
+        // Buffer can contain multiple messages, also may contain out of bound message.
+        // Read the message one by one from buffer and parse it. If it encountered out of bound message,
+        // then mark the reader index and again take the next chunk of messages from the channel
+        // and parse again from the marked reader index.
+        PcepMessageReader<PcepMessage> reader = PcepFactories.getGenericReader();
+        List<PcepMessage> msgList = (List<PcepMessage>) ctx.getAttachment();
+
+        if (msgList == null) {
+            msgList = new LinkedList<>();
+        }
+
+        try {
+            while (buffer.readableBytes() > 0) {
+                buffer.markReaderIndex();
+                PcepMessage message = reader.readFrom(buffer);
+                msgList.add(message);
+            }
+            ctx.setAttachment(null);
+            return msgList;
+        } catch (PcepOutOfBoundMessageException e) {
+            log.debug("PCEP message decode error");
+            buffer.resetReaderIndex();
+            buffer.discardReadBytes();
+            ctx.setAttachment(msgList);
+        }
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepMessageEncoder.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepMessageEncoder.java
new file mode 100644
index 0000000..4c26f88
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepMessageEncoder.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.util.HexDump;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Encode an pcep message for output into a ChannelBuffer, for use in a
+ * netty pipeline.
+ */
+public class PcepMessageEncoder extends OneToOneEncoder {
+    protected static final Logger log = LoggerFactory.getLogger(PcepMessageEncoder.class);
+
+    @Override
+    protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
+        log.debug("Sending message");
+        if (!(msg instanceof List)) {
+            log.debug("Invalid msg.");
+            return msg;
+        }
+
+        @SuppressWarnings("unchecked")
+        List<PcepMessage> msglist = (List<PcepMessage>) msg;
+
+        ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
+
+        for (PcepMessage pm : msglist) {
+            pm.writeTo(buf);
+        }
+
+        HexDump.pcepHexDump(buf);
+
+        return buf;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepPacketStatsImpl.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepPacketStatsImpl.java
new file mode 100644
index 0000000..1659247
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepPacketStatsImpl.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import org.onosproject.pcep.server.PcepPacketStats;
+
+/**
+ * The implementation for PCEP packet statistics.
+ */
+public class PcepPacketStatsImpl implements PcepPacketStats {
+
+    private int inPacketCount;
+    private int outPacketCount;
+    private int wrongPacketCount;
+    private long time;
+
+    /**
+     * Default constructor.
+     */
+    public PcepPacketStatsImpl() {
+        this.inPacketCount = 0;
+        this.outPacketCount = 0;
+        this.wrongPacketCount = 0;
+        this.time = 0;
+    }
+
+    @Override
+    public int outPacketCount() {
+        return outPacketCount;
+    }
+
+    @Override
+    public int inPacketCount() {
+        return inPacketCount;
+    }
+
+    @Override
+    public int wrongPacketCount() {
+        return wrongPacketCount;
+    }
+
+    /**
+     * Increments the received packet counter.
+     */
+    public void addInPacket() {
+        this.inPacketCount++;
+    }
+
+    /**
+     * Increments the sent packet counter.
+     */
+    public void addOutPacket() {
+        this.outPacketCount++;
+    }
+
+    /**
+     * Increments the sent packet counter by specified value.
+     *
+     * @param value of no of packets sent
+     */
+    public void addOutPacket(int value) {
+        this.outPacketCount = this.outPacketCount + value;
+    }
+
+    /**
+     * Increments the wrong packet counter.
+     */
+    public void addWrongPacket() {
+        this.wrongPacketCount++;
+    }
+
+    /**
+     * Resets wrong packet count.
+     */
+    public void resetWrongPacket() {
+        this.wrongPacketCount = 0;
+    }
+
+    @Override
+    public long getTime() {
+        return this.time;
+    }
+
+    /**
+     * Sets the time value.
+     *
+     * @param time long value of time
+     */
+    public void setTime(long time) {
+        this.time = time;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepPipelineFactory.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepPipelineFactory.java
new file mode 100644
index 0000000..f1932e9
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepPipelineFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.server.impl;
+
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.handler.timeout.IdleStateHandler;
+import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
+import org.jboss.netty.util.ExternalResourceReleasable;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timer;
+
+/**
+ * Creates a ChannelPipeline for a server-side pcep channel.
+ */
+public class PcepPipelineFactory
+    implements ChannelPipelineFactory, ExternalResourceReleasable {
+
+    protected Controller controller;
+    static final Timer TIMER = new HashedWheelTimer();
+    protected IdleStateHandler idleHandler;
+    protected ReadTimeoutHandler readTimeoutHandler;
+    static final int DEFAULT_KEEP_ALIVE_TIME = 30;
+    static final int DEFAULT_DEAD_TIME = 120;
+    static final int DEFAULT_WAIT_TIME = 60;
+
+    public PcepPipelineFactory(Controller controller) {
+        super();
+        this.controller = controller;
+        this.idleHandler = new IdleStateHandler(TIMER, DEFAULT_DEAD_TIME, DEFAULT_KEEP_ALIVE_TIME, 0);
+        this.readTimeoutHandler = new ReadTimeoutHandler(TIMER, DEFAULT_WAIT_TIME);
+    }
+
+    @Override
+    public ChannelPipeline getPipeline() throws Exception {
+        PcepChannelHandler handler = new PcepChannelHandler(controller);
+
+        ChannelPipeline pipeline = Channels.pipeline();
+        pipeline.addLast("pcepmessagedecoder", new PcepMessageDecoder());
+        pipeline.addLast("pcepmessageencoder", new PcepMessageEncoder());
+        pipeline.addLast("idle", idleHandler);
+        pipeline.addLast("waittimeout", readTimeoutHandler);
+        pipeline.addLast("handler", handler);
+        return pipeline;
+    }
+
+    @Override
+    public void releaseExternalResources() {
+        TIMER.stop();
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/package-info.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/package-info.java
new file mode 100644
index 0000000..4fd2660
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Implementation of the PCEP client controller subsystem.
+ */
+package org.onosproject.pcep.server.impl;
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfoTest.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfoTest.java
new file mode 100644
index 0000000..4b99e2c
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/DefaultLspLocalLabelInfoTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import com.google.common.testing.EqualsTester;
+
+import org.junit.Test;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+
+/**
+ * Unit tests for DefaultLspLocalLabelInfo class.
+ */
+public class DefaultLspLocalLabelInfoTest {
+
+    /**
+     * Checks the operation of equals() methods.
+     */
+    @Test
+    public void testEquals() {
+        // create same two objects.
+        DeviceId deviceId1 = DeviceId.deviceId("foo");
+        LabelResourceId inLabelId1 = LabelResourceId.labelResourceId(1);
+        LabelResourceId outLabelId1 = LabelResourceId.labelResourceId(2);
+        PortNumber inPort1 = PortNumber.portNumber(5122);
+        PortNumber outPort1 = PortNumber.portNumber(5123);
+
+        LspLocalLabelInfo lspLocalLabel1 = DefaultLspLocalLabelInfo.builder()
+                .deviceId(deviceId1)
+                .inLabelId(inLabelId1)
+                .outLabelId(outLabelId1)
+                .inPort(inPort1)
+                .outPort(outPort1)
+                .build();
+
+        // create same object as above object
+        LspLocalLabelInfo sameLocalLabel1 = DefaultLspLocalLabelInfo.builder()
+                .deviceId(deviceId1)
+                .inLabelId(inLabelId1)
+                .outLabelId(outLabelId1)
+                .inPort(inPort1)
+                .outPort(outPort1)
+                .build();
+
+        // Create different object.
+        DeviceId deviceId2 = DeviceId.deviceId("goo");
+        LabelResourceId inLabelId2 = LabelResourceId.labelResourceId(3);
+        LabelResourceId outLabelId2 = LabelResourceId.labelResourceId(4);
+        PortNumber inPort2 = PortNumber.portNumber(5124);
+        PortNumber outPort2 = PortNumber.portNumber(5125);
+
+        LspLocalLabelInfo lspLocalLabel2 = DefaultLspLocalLabelInfo.builder()
+                .deviceId(deviceId2)
+                .inLabelId(inLabelId2)
+                .outLabelId(outLabelId2)
+                .inPort(inPort2)
+                .outPort(outPort2)
+                .build();
+
+        new EqualsTester().addEqualityGroup(lspLocalLabel1, sameLocalLabel1)
+                          .addEqualityGroup(lspLocalLabel2)
+                          .testEquals();
+    }
+
+    /**
+     * Checks the construction of a DefaultLspLocalLabelInfo object.
+     */
+    @Test
+    public void testConstruction() {
+        DeviceId deviceId = DeviceId.deviceId("foo");
+        LabelResourceId inLabelId = LabelResourceId.labelResourceId(1);
+        LabelResourceId outLabelId = LabelResourceId.labelResourceId(2);
+        PortNumber inPort = PortNumber.portNumber(5122);
+        PortNumber outPort = PortNumber.portNumber(5123);
+
+        LspLocalLabelInfo lspLocalLabel = DefaultLspLocalLabelInfo.builder()
+                .deviceId(deviceId)
+                .inLabelId(inLabelId)
+                .outLabelId(outLabelId)
+                .inPort(inPort)
+                .outPort(outPort)
+                .build();
+
+        assertThat(deviceId, is(lspLocalLabel.deviceId()));
+        assertThat(inLabelId, is(lspLocalLabel.inLabelId()));
+        assertThat(outLabelId, is(lspLocalLabel.outLabelId()));
+        assertThat(inPort, is(lspLocalLabel.inPort()));
+        assertThat(outPort, is(lspLocalLabel.outPort()));
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/DistributedPceLabelStoreTest.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/DistributedPceLabelStoreTest.java
new file mode 100644
index 0000000..185ffd1
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/DistributedPceLabelStoreTest.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+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.tunnel.TunnelId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+import org.onosproject.pcelabelstore.util.TestStorageService;
+
+/**
+ * Unit tests for DistributedPceStore class.
+ */
+public class DistributedPceLabelStoreTest {
+
+    private DistributedPceLabelStore distrPceStore;
+    private DeviceId deviceId1 = DeviceId.deviceId("foo");
+    private DeviceId deviceId2 = DeviceId.deviceId("goo");
+    private DeviceId deviceId3 = DeviceId.deviceId("yaa");
+    private DeviceId deviceId4 = DeviceId.deviceId("zoo");
+    private LabelResourceId labelId1 = LabelResourceId.labelResourceId(1);
+    private LabelResourceId labelId2 = LabelResourceId.labelResourceId(2);
+    private LabelResourceId labelId3 = LabelResourceId.labelResourceId(3);
+    private LabelResourceId labelId4 = LabelResourceId.labelResourceId(4);
+    private PortNumber portNumber1 = PortNumber.portNumber(1);
+    private PortNumber portNumber2 = PortNumber.portNumber(2);
+    private PortNumber portNumber3 = PortNumber.portNumber(3);
+    private PortNumber portNumber4 = PortNumber.portNumber(4);
+    private ConnectPoint srcConnectionPoint1 = new ConnectPoint(deviceId1, portNumber1);
+    private ConnectPoint dstConnectionPoint2 = new ConnectPoint(deviceId2, portNumber2);
+    private ConnectPoint srcConnectionPoint3 = new ConnectPoint(deviceId3, portNumber3);
+    private ConnectPoint dstConnectionPoint4 = new ConnectPoint(deviceId4, portNumber4);
+    private LabelResource labelResource1 = new DefaultLabelResource(deviceId1, labelId1);
+    private LabelResource labelResource2 = new DefaultLabelResource(deviceId2, labelId2);
+    private LabelResource labelResource3 = new DefaultLabelResource(deviceId3, labelId3);
+    private LabelResource labelResource4 = new DefaultLabelResource(deviceId4, labelId4);
+    private Link link1;
+    private Link link2;
+    private List<LabelResource> labelList1 = new LinkedList<>();
+    private List<LabelResource> labelList2 = new LinkedList<>();
+    private TunnelId tunnelId1 = TunnelId.valueOf("1");
+    private TunnelId tunnelId2 = TunnelId.valueOf("2");
+    private TunnelId tunnelId3 = TunnelId.valueOf("3");
+    private TunnelId tunnelId4 = TunnelId.valueOf("4");
+
+    List<LspLocalLabelInfo> lspLocalLabelInfoList1 = new LinkedList<>();
+    List<LspLocalLabelInfo> lspLocalLabelInfoList2 = new LinkedList<>();
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() throws Exception {
+       distrPceStore = new DistributedPceLabelStore();
+       // initialization
+       distrPceStore.storageService = new TestStorageService();
+       distrPceStore.activate();
+
+       // Initialization of member variables
+       link1 = DefaultLink.builder()
+                          .providerId(new ProviderId("eth", "1"))
+                          .annotations(DefaultAnnotations.builder().set("key1", "yahoo").build())
+                          .src(srcConnectionPoint1)
+                          .dst(dstConnectionPoint2)
+                          .type(Link.Type.DIRECT)
+                          .state(Link.State.ACTIVE)
+                          .build();
+       link2 = DefaultLink.builder()
+                          .providerId(new ProviderId("mac", "2"))
+                          .annotations(DefaultAnnotations.builder().set("key2", "google").build())
+                          .src(srcConnectionPoint3)
+                          .dst(dstConnectionPoint4)
+                          .type(Link.Type.DIRECT)
+                          .state(Link.State.ACTIVE)
+                          .build();
+       labelList1.add(labelResource1);
+       labelList1.add(labelResource2);
+       labelList2.add(labelResource3);
+       labelList2.add(labelResource4);
+
+       // Create pceccTunnelInfo1
+       DeviceId deviceId1 = DeviceId.deviceId("foo");
+       LabelResourceId inLabelId1 = LabelResourceId.labelResourceId(1);
+       LabelResourceId outLabelId1 = LabelResourceId.labelResourceId(2);
+
+       LspLocalLabelInfo lspLocalLabel1 = DefaultLspLocalLabelInfo.builder()
+               .deviceId(deviceId1)
+               .inLabelId(inLabelId1)
+               .outLabelId(outLabelId1)
+               .build();
+       lspLocalLabelInfoList1.add(lspLocalLabel1);
+       distrPceStore.addTunnelInfo(tunnelId1, lspLocalLabelInfoList1);
+
+       // Create pceccTunnelInfo2
+       DeviceId deviceId2 = DeviceId.deviceId("foo");
+       LabelResourceId inLabelId2 = LabelResourceId.labelResourceId(3);
+       LabelResourceId outLabelId2 = LabelResourceId.labelResourceId(4);
+
+       LspLocalLabelInfo lspLocalLabel2 = DefaultLspLocalLabelInfo.builder()
+               .deviceId(deviceId2)
+               .inLabelId(inLabelId2)
+               .outLabelId(outLabelId2)
+               .build();
+       lspLocalLabelInfoList2.add(lspLocalLabel2);
+       distrPceStore.addTunnelInfo(tunnelId2, lspLocalLabelInfoList2);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Checks the operation of addGlobalNodeLabel() method.
+     */
+    @Test
+    public void testAddGlobalNodeLabel() {
+        // add device with label
+        distrPceStore.addGlobalNodeLabel(deviceId1, labelId1);
+        assertThat(distrPceStore.existsGlobalNodeLabel(deviceId1), is(true));
+        assertThat(distrPceStore.getGlobalNodeLabel(deviceId1), is(labelId1));
+        distrPceStore.addGlobalNodeLabel(deviceId2, labelId2);
+        assertThat(distrPceStore.existsGlobalNodeLabel(deviceId2), is(true));
+        assertThat(distrPceStore.getGlobalNodeLabel(deviceId2), is(labelId2));
+    }
+
+    /**
+     * Checks the operation of addAdjLabel() method.
+     */
+    @Test
+    public void testAddAdjLabel() {
+        // link with list of labels
+        distrPceStore.addAdjLabel(link1, labelId1);
+        assertThat(distrPceStore.existsAdjLabel(link1), is(true));
+        assertThat(distrPceStore.getAdjLabel(link1), is(labelId1));
+        distrPceStore.addAdjLabel(link2, labelId2);
+        assertThat(distrPceStore.existsAdjLabel(link2), is(true));
+        assertThat(distrPceStore.getAdjLabel(link2), is(labelId2));
+    }
+
+    /**
+     * Checks the operation of addTunnelInfo() method.
+     */
+    @Test
+    public void testAddTunnelInfo() {
+        // TunnelId with device label store information
+        distrPceStore.addTunnelInfo(tunnelId1, lspLocalLabelInfoList1);
+        assertThat(distrPceStore.existsTunnelInfo(tunnelId1), is(true));
+        assertThat(distrPceStore.getTunnelInfo(tunnelId1), is(lspLocalLabelInfoList1));
+        distrPceStore.addTunnelInfo(tunnelId2, lspLocalLabelInfoList2);
+        assertThat(distrPceStore.existsTunnelInfo(tunnelId2), is(true));
+        assertThat(distrPceStore.getTunnelInfo(tunnelId2), is(lspLocalLabelInfoList2));
+    }
+
+    /**
+     * Checks the operation of existsGlobalNodeLabel() method.
+     */
+    @Test
+    public void testExistsGlobalNodeLabel() {
+        testAddGlobalNodeLabel();
+
+        assertThat(distrPceStore.existsGlobalNodeLabel(deviceId1), is(true));
+        assertThat(distrPceStore.existsGlobalNodeLabel(deviceId2), is(true));
+        assertThat(distrPceStore.existsGlobalNodeLabel(deviceId3), is(false));
+        assertThat(distrPceStore.existsGlobalNodeLabel(deviceId4), is(false));
+    }
+
+    /**
+     * Checks the operation of existsAdjLabel() method.
+     */
+    @Test
+    public void testExistsAdjLabel() {
+        testAddAdjLabel();
+
+        assertThat(distrPceStore.existsAdjLabel(link1), is(true));
+        assertThat(distrPceStore.existsAdjLabel(link2), is(true));
+    }
+
+    /**
+     * Checks the operation of existsTunnelInfo() method.
+     */
+    @Test
+    public void testExistsTunnelInfo() {
+        testAddTunnelInfo();
+
+        assertThat(distrPceStore.existsTunnelInfo(tunnelId1), is(true));
+        assertThat(distrPceStore.existsTunnelInfo(tunnelId2), is(true));
+        assertThat(distrPceStore.existsTunnelInfo(tunnelId3), is(false));
+        assertThat(distrPceStore.existsTunnelInfo(tunnelId4), is(false));
+    }
+
+    /**
+     * Checks the operation of getGlobalNodeLabelCount() method.
+     */
+    @Test
+    public void testGetGlobalNodeLabelCount() {
+        testAddGlobalNodeLabel();
+
+        assertThat(distrPceStore.getGlobalNodeLabelCount(), is(2));
+    }
+
+    /**
+     * Checks the operation of getAdjLabelCount() method.
+     */
+    @Test
+    public void testGetAdjLabelCount() {
+        testAddAdjLabel();
+
+        assertThat(distrPceStore.getAdjLabelCount(), is(2));
+    }
+
+    /**
+     * Checks the operation of getTunnelInfoCount() method.
+     */
+    @Test
+    public void testGetTunnelInfoCount() {
+        testAddTunnelInfo();
+
+        assertThat(distrPceStore.getTunnelInfoCount(), is(2));
+    }
+
+    /**
+     * Checks the operation of getGlobalNodeLabels() method.
+     */
+    @Test
+    public void testGetGlobalNodeLabels() {
+        testAddGlobalNodeLabel();
+
+        Map<DeviceId, LabelResourceId> nodeLabelMap = distrPceStore.getGlobalNodeLabels();
+        assertThat(nodeLabelMap, is(notNullValue()));
+        assertThat(nodeLabelMap.isEmpty(), is(false));
+        assertThat(nodeLabelMap.size(), is(2));
+    }
+
+    /**
+     * Checks the operation of getAdjLabels() method.
+     */
+    @Test
+    public void testGetAdjLabels() {
+        testAddAdjLabel();
+
+        Map<Link, LabelResourceId> adjLabelMap = distrPceStore.getAdjLabels();
+        assertThat(adjLabelMap, is(notNullValue()));
+        assertThat(adjLabelMap.isEmpty(), is(false));
+        assertThat(adjLabelMap.size(), is(2));
+    }
+
+    /**
+     * Checks the operation of getTunnelInfos() method.
+     */
+    @Test
+    public void testGetTunnelInfos() {
+        testAddTunnelInfo();
+
+        Map<TunnelId, List<LspLocalLabelInfo>> tunnelInfoMap = distrPceStore.getTunnelInfos();
+        assertThat(tunnelInfoMap, is(notNullValue()));
+        assertThat(tunnelInfoMap.isEmpty(), is(false));
+        assertThat(tunnelInfoMap.size(), is(2));
+    }
+
+    /**
+     * Checks the operation of getGlobalNodeLabel() method.
+     */
+    @Test
+    public void testGetGlobalNodeLabel() {
+        testAddGlobalNodeLabel();
+
+        // deviceId1 with labelId1
+        assertThat(deviceId1, is(notNullValue()));
+        assertThat(distrPceStore.getGlobalNodeLabel(deviceId1), is(labelId1));
+
+        // deviceId2 with labelId2
+        assertThat(deviceId2, is(notNullValue()));
+        assertThat(distrPceStore.getGlobalNodeLabel(deviceId2), is(labelId2));
+    }
+
+    /**
+     * Checks the operation of getAdjLabel() method.
+     */
+    @Test
+    public void testGetAdjLabel() {
+        testAddAdjLabel();
+
+        // link1 with labels
+        assertThat(link1, is(notNullValue()));
+        assertThat(distrPceStore.getAdjLabel(link1), is(labelId1));
+
+        // link2 with labels
+        assertThat(link2, is(notNullValue()));
+        assertThat(distrPceStore.getAdjLabel(link2), is(labelId2));
+    }
+
+    /**
+     * Checks the operation of getTunnelInfo() method.
+     */
+    @Test
+    public void testGetTunnelInfo() {
+        testAddTunnelInfo();
+
+        // tunnelId1 with device label store info
+        assertThat(tunnelId1, is(notNullValue()));
+        assertThat(distrPceStore.getTunnelInfo(tunnelId1), is(lspLocalLabelInfoList1));
+
+        // tunnelId2 with device label store info
+        assertThat(tunnelId2, is(notNullValue()));
+        assertThat(distrPceStore.getTunnelInfo(tunnelId2), is(lspLocalLabelInfoList2));
+    }
+
+    /**
+     * Checks the operation of removeGlobalNodeLabel() method.
+     */
+    @Test
+    public void testRemoveGlobalNodeLabel() {
+        testAddGlobalNodeLabel();
+
+        assertThat(distrPceStore.removeGlobalNodeLabel(deviceId1), is(true));
+        assertThat(distrPceStore.removeGlobalNodeLabel(deviceId2), is(true));
+    }
+
+    /**
+     * Checks the operation of removeAdjLabel() method.
+     */
+    @Test
+    public void testRemoveAdjLabel() {
+        testAddAdjLabel();
+
+        assertThat(distrPceStore.removeAdjLabel(link1), is(true));
+        assertThat(distrPceStore.removeAdjLabel(link2), is(true));
+    }
+
+    /**
+     * Checks the operation of removeTunnelInfo() method.
+     */
+    @Test
+    public void testRemoveTunnelInfo() {
+        testAddTunnelInfo();
+
+        assertThat(distrPceStore.removeTunnelInfo(tunnelId1), is(true));
+        assertThat(distrPceStore.removeTunnelInfo(tunnelId2), is(true));
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/label/BasicPceccHandlerTest.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/label/BasicPceccHandlerTest.java
new file mode 100644
index 0000000..201b701
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/label/BasicPceccHandlerTest.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.label;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.onosproject.net.Link.Type.DIRECT;
+import java.util.Iterator;
+import java.util.List;
+import java.util.LinkedList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.core.GroupId;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelName;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.DefaultTunnel;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.Path;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+import org.onosproject.pcelabelstore.util.LabelResourceAdapter;
+import org.onosproject.pcelabelstore.util.MockDeviceService;
+import org.onosproject.pcelabelstore.util.PceLabelStoreAdapter;
+import org.onosproject.pcep.server.impl.BasicPceccHandler;
+import org.onosproject.pcep.server.impl.PcepClientControllerImpl;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Link;
+
+/**
+ * Unit tests for BasicPceccHandler class.
+ */
+public class BasicPceccHandlerTest {
+
+    public static final long LOCAL_LABEL_SPACE_MIN = 5122;
+    public static final long LOCAL_LABEL_SPACE_MAX = 9217;
+    private static final String L3 = "L3";
+    private static final String LSRID = "lsrId";
+
+    private BasicPceccHandler pceccHandler;
+    protected LabelResourceService labelRsrcService;
+    protected MockDeviceService deviceService;
+    protected PceLabelStore pceStore;
+    private TunnelEndPoint src = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(23423));
+    private TunnelEndPoint dst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(32421));
+    private GroupId groupId = new GroupId(92034);
+    private TunnelName tunnelName = TunnelName.tunnelName("TunnelName");
+    private TunnelId tunnelId = TunnelId.valueOf("41654654");
+    private ProviderId producerName = new ProviderId("producer1", "13");
+    private Path path;
+    private Tunnel tunnel;
+    List<LspLocalLabelInfo> lspLocalLabelInfoList;
+    private Device deviceD1, deviceD2, deviceD3, deviceD4, deviceD5;
+    private DeviceId deviceId1;
+    private DeviceId deviceId2;
+    private DeviceId deviceId3;
+    private DeviceId deviceId4;
+    private DeviceId deviceId5;
+    private PortNumber port1;
+    private PortNumber port2;
+    private PortNumber port3;
+    private PortNumber port4;
+    private PortNumber port5;
+
+    @Before
+    public void setUp() throws Exception {
+       pceccHandler = BasicPceccHandler.getInstance();
+       labelRsrcService = new LabelResourceAdapter();
+       pceStore = new PceLabelStoreAdapter();
+       deviceService = new MockDeviceService();
+       pceccHandler.initialize(labelRsrcService,
+                              deviceService,
+                              pceStore,
+                              new PcepClientControllerImpl());
+
+       // Create tunnel test
+       // Link
+       ProviderId providerId = new ProviderId("of", "foo");
+       deviceId1 = DeviceId.deviceId("of:A");
+       deviceId2 = DeviceId.deviceId("of:B");
+       deviceId3 = DeviceId.deviceId("of:C");
+       deviceId4 = DeviceId.deviceId("of:D");
+       deviceId5 = DeviceId.deviceId("of:E");
+       port1 = PortNumber.portNumber(1);
+       port2 = PortNumber.portNumber(2);
+       port3 = PortNumber.portNumber(3);
+       port4 = PortNumber.portNumber(4);
+       port5 = PortNumber.portNumber(5);
+       List<Link> linkList = new LinkedList<>();
+
+       // Making L3 devices
+       DefaultAnnotations.Builder builderDev1 = DefaultAnnotations.builder();
+       builderDev1.set(AnnotationKeys.TYPE, L3);
+       builderDev1.set(LSRID, "1.1.1.1");
+       deviceD1 = new MockDevice(deviceId1, builderDev1.build());
+       deviceService.addDevice(deviceD1);
+
+       // Making L3 devices
+       DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
+       builderDev2.set(AnnotationKeys.TYPE, L3);
+       builderDev2.set(LSRID, "2.2.2.2");
+       deviceD2 = new MockDevice(deviceId2, builderDev2.build());
+       deviceService.addDevice(deviceD2);
+
+       // Making L3 devices
+       DefaultAnnotations.Builder builderDev3 = DefaultAnnotations.builder();
+       builderDev3.set(AnnotationKeys.TYPE, L3);
+       builderDev3.set(LSRID, "3.3.3.3");
+       deviceD3 = new MockDevice(deviceId3, builderDev3.build());
+       deviceService.addDevice(deviceD3);
+
+       // Making L3 devices
+       DefaultAnnotations.Builder builderDev4 = DefaultAnnotations.builder();
+       builderDev4.set(AnnotationKeys.TYPE, L3);
+       builderDev4.set(LSRID, "4.4.4.4");
+       deviceD4 = new MockDevice(deviceId4, builderDev4.build());
+       deviceService.addDevice(deviceD4);
+
+       // Making L3 devices
+       DefaultAnnotations.Builder builderDev5 = DefaultAnnotations.builder();
+       builderDev5.set(AnnotationKeys.TYPE, L3);
+       builderDev5.set(LSRID, "5.5.5.5");
+       deviceD5 = new MockDevice(deviceId5, builderDev5.build());
+       deviceService.addDevice(deviceD5);
+
+       Link l1 = DefaultLink.builder()
+                            .providerId(providerId)
+                            .annotations(DefaultAnnotations.builder().set("key1", "yahoo").build())
+                            .src(new ConnectPoint(deviceId1, port1))
+                            .dst(new ConnectPoint(deviceId2, port2))
+                            .type(DIRECT)
+                            .state(Link.State.ACTIVE)
+                            .build();
+       linkList.add(l1);
+       Link l2 = DefaultLink.builder()
+                            .providerId(providerId)
+                            .annotations(DefaultAnnotations.builder().set("key2", "yahoo").build())
+                            .src(new ConnectPoint(deviceId2, port2))
+                            .dst(new ConnectPoint(deviceId3, port3))
+                            .type(DIRECT)
+                            .state(Link.State.ACTIVE)
+                            .build();
+       linkList.add(l2);
+       Link l3 = DefaultLink.builder()
+                            .providerId(providerId)
+                            .annotations(DefaultAnnotations.builder().set("key3", "yahoo").build())
+                            .src(new ConnectPoint(deviceId3, port3))
+                            .dst(new ConnectPoint(deviceId4, port4))
+                            .type(DIRECT)
+                            .state(Link.State.ACTIVE)
+                            .build();
+       linkList.add(l3);
+       Link l4 = DefaultLink.builder()
+                            .providerId(providerId)
+                            .annotations(DefaultAnnotations.builder().set("key4", "yahoo").build())
+                            .src(new ConnectPoint(deviceId4, port4))
+                            .dst(new ConnectPoint(deviceId5, port5))
+                            .type(DIRECT)
+                            .state(Link.State.ACTIVE)
+                            .build();
+       linkList.add(l4);
+
+       // Path
+       path = new DefaultPath(providerId, linkList, 10);
+
+       // Tunnel
+       tunnel = new DefaultTunnel(producerName, src, dst, Tunnel.Type.VXLAN,
+                                  Tunnel.State.ACTIVE, groupId, tunnelId,
+                                  tunnelName, path);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Checks the operation of getInstance() method.
+     */
+    @Test
+    public void testGetInstance() {
+        assertThat(pceccHandler, is(notNullValue()));
+    }
+
+    /**
+     * Checks the operation of allocateLabel() method.
+     */
+    @Test
+    public void testAllocateLabel() {
+       Iterator<LspLocalLabelInfo> iterator;
+       LspLocalLabelInfo lspLocalLabelInfo;
+       DeviceId deviceId;
+       LabelResourceId inLabelId;
+       LabelResourceId outLabelId;
+       PortNumber inPort;
+       PortNumber outPort;
+
+       // check allocation result
+       assertThat(pceccHandler.allocateLabel(tunnel), is(true));
+
+       // Check list of devices with IN and OUT labels whether stored properly in store
+       lspLocalLabelInfoList = pceStore.getTunnelInfo(tunnel.tunnelId());
+       iterator = lspLocalLabelInfoList.iterator();
+
+       // Retrieve values and check device5
+       lspLocalLabelInfo = iterator.next();
+       deviceId = lspLocalLabelInfo.deviceId();
+       inLabelId = lspLocalLabelInfo.inLabelId();
+       outLabelId = lspLocalLabelInfo.outLabelId();
+       inPort = lspLocalLabelInfo.inPort();
+       outPort = lspLocalLabelInfo.outPort();
+
+       assertThat(deviceId, is(deviceId5));
+       assertThat(inLabelId, is(notNullValue()));
+       assertThat(outLabelId, is(nullValue()));
+       assertThat(inPort, is(port5));
+       assertThat(outPort, is(nullValue()));
+
+       // Next element check
+       // Retrieve values and check device4
+       lspLocalLabelInfo = iterator.next();
+       deviceId = lspLocalLabelInfo.deviceId();
+       inLabelId = lspLocalLabelInfo.inLabelId();
+       outLabelId = lspLocalLabelInfo.outLabelId();
+       inPort = lspLocalLabelInfo.inPort();
+       outPort = lspLocalLabelInfo.outPort();
+
+       assertThat(deviceId, is(deviceId4));
+       assertThat(inLabelId, is(notNullValue()));
+       assertThat(outLabelId, is(notNullValue()));
+       assertThat(inPort, is(port4));
+       assertThat(outPort, is(port5));
+
+       // Next element check
+       // Retrieve values and check device3
+       lspLocalLabelInfo = iterator.next();
+       deviceId = lspLocalLabelInfo.deviceId();
+       inLabelId = lspLocalLabelInfo.inLabelId();
+       outLabelId = lspLocalLabelInfo.outLabelId();
+       inPort = lspLocalLabelInfo.inPort();
+       outPort = lspLocalLabelInfo.outPort();
+
+       assertThat(deviceId, is(deviceId3));
+       assertThat(inLabelId, is(notNullValue()));
+       assertThat(outLabelId, is(notNullValue()));
+       assertThat(inPort, is(port3));
+       assertThat(outPort, is(port4));
+
+       // Next element check
+       // Retrieve values and check device2
+       lspLocalLabelInfo = iterator.next();
+       deviceId = lspLocalLabelInfo.deviceId();
+       inLabelId = lspLocalLabelInfo.inLabelId();
+       outLabelId = lspLocalLabelInfo.outLabelId();
+       inPort = lspLocalLabelInfo.inPort();
+       outPort = lspLocalLabelInfo.outPort();
+
+       assertThat(deviceId, is(deviceId2));
+       assertThat(inLabelId, is(notNullValue()));
+       assertThat(outLabelId, is(notNullValue()));
+       assertThat(inPort, is(port2));
+       assertThat(outPort, is(port3));
+
+       // Next element check
+       // Retrieve values and check device1
+       lspLocalLabelInfo = iterator.next();
+       deviceId = lspLocalLabelInfo.deviceId();
+       inLabelId = lspLocalLabelInfo.inLabelId();
+       outLabelId = lspLocalLabelInfo.outLabelId();
+       inPort = lspLocalLabelInfo.inPort();
+       outPort = lspLocalLabelInfo.outPort();
+
+       assertThat(deviceId, is(deviceId1));
+       assertThat(inLabelId, is(nullValue()));
+       assertThat(outLabelId, is(notNullValue()));
+       assertThat(inPort, is(nullValue()));
+       assertThat(outPort, is(port2));
+    }
+
+    /**
+     * Checks the operation of releaseLabel() method.
+     */
+    @Test
+    public void testReleaseLabel() {
+       // Release tunnels
+       assertThat(pceccHandler.allocateLabel(tunnel), is(true));
+       pceccHandler.releaseLabel(tunnel);
+
+       // Retrieve from store. Store should not contain this tunnel info.
+       lspLocalLabelInfoList = pceStore.getTunnelInfo(tunnel.tunnelId());
+       assertThat(lspLocalLabelInfoList, is(nullValue()));
+    }
+
+    private class MockDevice extends DefaultDevice {
+        MockDevice(DeviceId id, Annotations annotations) {
+            super(null, id, null, null, null, null, null, null, annotations);
+        }
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/label/PceccSrTeBeHandlerTest.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/label/PceccSrTeBeHandlerTest.java
new file mode 100644
index 0000000..38ea63a
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/label/PceccSrTeBeHandlerTest.java
@@ -0,0 +1,490 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.label;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.onosproject.net.Link.Type.DIRECT;
+import java.util.Iterator;
+import java.util.List;
+import java.util.LinkedList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+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.LabelStack;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.Path;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+import org.onosproject.pcelabelstore.util.LabelResourceAdapter;
+import org.onosproject.pcelabelstore.util.MockDeviceService;
+import org.onosproject.pcelabelstore.util.MockNetConfigRegistryAdapter;
+import org.onosproject.pcelabelstore.util.MockPcepClientController;
+import org.onosproject.pcelabelstore.util.PceLabelStoreAdapter;
+import org.onosproject.pcelabelstore.util.PcepClientAdapter;
+import org.onosproject.pcep.api.DeviceCapability;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.impl.PceccSrTeBeHandler;
+import org.onosproject.pcepio.protocol.PcepVersion;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Link;
+
+/**
+ * Unit tests for PceccSrTeBeHandler class.
+ */
+public class PceccSrTeBeHandlerTest {
+
+    public static final long GLOBAL_LABEL_SPACE_MIN = 4097;
+    public static final long GLOBAL_LABEL_SPACE_MAX = 5121;
+    private static final String L3 = "L3";
+    private static final String LSRID = "lsrId";
+
+    private PceccSrTeBeHandler srTeHandler;
+    private LabelResourceAdminService labelRsrcAdminService;
+    private LabelResourceService labelRsrcService;
+    private PceLabelStore pceStore;
+    private MockDeviceService deviceService;
+    private MockNetConfigRegistryAdapter netCfgService = new MockNetConfigRegistryAdapter();
+    private MockPcepClientController clientController = new MockPcepClientController();
+    private ProviderId providerId;
+    private DeviceId deviceId1, deviceId2, deviceId3, deviceId4, deviceId5;
+    private Device deviceD1;
+    private Device deviceD2;
+    private Device deviceD3;
+    private Device deviceD4;
+    private Device deviceD5;
+    private PortNumber port1;
+    private PortNumber port2;
+    private PortNumber port3;
+    private PortNumber port4;
+    private PortNumber port5;
+    private Link link1;
+    private Link link2;
+    private Link link3;
+    private Link link4;
+    private Path path1;
+    LabelResourceId labelId;
+
+    @Before
+    public void setUp() throws Exception {
+        // Initialization of member variables
+        srTeHandler = PceccSrTeBeHandler.getInstance();
+        labelRsrcService = new LabelResourceAdapter();
+        labelRsrcAdminService = new LabelResourceAdapter();
+        pceStore = new PceLabelStoreAdapter();
+        deviceService = new MockDeviceService();
+
+        srTeHandler.initialize(labelRsrcAdminService,
+                               labelRsrcService,
+                               clientController,
+                               pceStore,
+                               deviceService);
+
+        // Creates path
+        // Creates list of links
+        providerId = new ProviderId("of", "foo");
+
+        PccId pccId1 = PccId.pccId(IpAddress.valueOf("11.1.1.1"));
+        PccId pccId2 = PccId.pccId(IpAddress.valueOf("12.1.1.1"));
+        PccId pccId3 = PccId.pccId(IpAddress.valueOf("13.1.1.1"));
+        PccId pccId4 = PccId.pccId(IpAddress.valueOf("14.1.1.1"));
+        PccId pccId5 = PccId.pccId(IpAddress.valueOf("15.1.1.1"));
+
+        PcepClientAdapter pc1 = new PcepClientAdapter();
+        pc1.init(pccId1, PcepVersion.PCEP_1);
+
+        PcepClientAdapter pc2 = new PcepClientAdapter();
+        pc2.init(pccId2, PcepVersion.PCEP_1);
+
+        PcepClientAdapter pc3 = new PcepClientAdapter();
+        pc3.init(pccId3, PcepVersion.PCEP_1);
+
+        PcepClientAdapter pc4 = new PcepClientAdapter();
+        pc4.init(pccId4, PcepVersion.PCEP_1);
+
+        PcepClientAdapter pc5 = new PcepClientAdapter();
+        pc5.init(pccId5, PcepVersion.PCEP_1);
+
+        clientController.addClient(pccId1, pc1);
+        clientController.addClient(pccId2, pc2);
+        clientController.addClient(pccId3, pc3);
+        clientController.addClient(pccId4, pc4);
+        clientController.addClient(pccId5, pc5);
+
+        deviceId1 = DeviceId.deviceId("11.1.1.1");
+        deviceId2 = DeviceId.deviceId("12.1.1.1");
+        deviceId3 = DeviceId.deviceId("13.1.1.1");
+        deviceId4 = DeviceId.deviceId("14.1.1.1");
+        deviceId5 = DeviceId.deviceId("15.1.1.1");
+
+        // Devices
+        DefaultAnnotations.Builder builderDev1 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev3 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev4 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev5 = DefaultAnnotations.builder();
+
+        builderDev1.set(AnnotationKeys.TYPE, L3);
+        builderDev1.set(LSRID, "11.1.1.1");
+
+        builderDev2.set(AnnotationKeys.TYPE, L3);
+        builderDev2.set(LSRID, "12.1.1.1");
+
+        builderDev3.set(AnnotationKeys.TYPE, L3);
+        builderDev3.set(LSRID, "13.1.1.1");
+
+        builderDev4.set(AnnotationKeys.TYPE, L3);
+        builderDev4.set(LSRID, "14.1.1.1");
+
+        builderDev5.set(AnnotationKeys.TYPE, L3);
+        builderDev5.set(LSRID, "15.1.1.1");
+
+        deviceD1 = new MockDevice(deviceId1, builderDev1.build());
+        deviceD2 = new MockDevice(deviceId2, builderDev2.build());
+        deviceD3 = new MockDevice(deviceId3, builderDev3.build());
+        deviceD4 = new MockDevice(deviceId4, builderDev4.build());
+        deviceD5 = new MockDevice(deviceId5, builderDev5.build());
+
+        deviceService.addDevice(deviceD1);
+        deviceService.addDevice(deviceD2);
+        deviceService.addDevice(deviceD3);
+        deviceService.addDevice(deviceD4);
+        deviceService.addDevice(deviceD5);
+
+        DeviceCapability device1Cap = netCfgService.addConfig(deviceId1, DeviceCapability.class);
+        device1Cap.setLabelStackCap(true).setLocalLabelCap(false).setSrCap(true).apply();
+
+        DeviceCapability device2Cap = netCfgService.addConfig(deviceId2, DeviceCapability.class);
+        device2Cap.setLabelStackCap(true).setLocalLabelCap(false).setSrCap(true).apply();
+
+        DeviceCapability device3Cap = netCfgService.addConfig(deviceId3, DeviceCapability.class);
+        device3Cap.setLabelStackCap(true).setLocalLabelCap(false).setSrCap(true).apply();
+
+        DeviceCapability device4Cap = netCfgService.addConfig(deviceId4, DeviceCapability.class);
+        device4Cap.setLabelStackCap(true).setLocalLabelCap(false).setSrCap(true).apply();
+
+        DeviceCapability device5Cap = netCfgService.addConfig(deviceId5, DeviceCapability.class);
+        device5Cap.setLabelStackCap(true).setLocalLabelCap(false).setSrCap(true).apply();
+
+        // Port Numbers
+        port1 = PortNumber.portNumber(1);
+        port2 = PortNumber.portNumber(2);
+        port3 = PortNumber.portNumber(3);
+        port4 = PortNumber.portNumber(4);
+        port5 = PortNumber.portNumber(5);
+        List<Link> linkList = new LinkedList<>();
+
+        link1 = DefaultLink.builder().providerId(providerId)
+                .annotations(DefaultAnnotations.builder().set("key1", "yahoo").build())
+                .src(new ConnectPoint(deviceD1.id(), port1)).dst(new ConnectPoint(deviceD2.id(), port2)).type(DIRECT)
+                .state(Link.State.ACTIVE).build();
+        linkList.add(link1);
+        link2 = DefaultLink.builder().providerId(providerId)
+                .annotations(DefaultAnnotations.builder().set("key2", "yahoo").build())
+                .src(new ConnectPoint(deviceD2.id(), port2)).dst(new ConnectPoint(deviceD3.id(), port3)).type(DIRECT)
+                .state(Link.State.ACTIVE).build();
+        linkList.add(link2);
+        link3 = DefaultLink.builder().providerId(providerId)
+                .annotations(DefaultAnnotations.builder().set("key3", "yahoo").build())
+                .src(new ConnectPoint(deviceD3.id(), port3)).dst(new ConnectPoint(deviceD4.id(), port4)).type(DIRECT)
+                .state(Link.State.ACTIVE).build();
+        linkList.add(link3);
+        link4 = DefaultLink.builder().providerId(providerId)
+                .annotations(DefaultAnnotations.builder().set("key4", "yahoo").build())
+                .src(new ConnectPoint(deviceD4.id(), port4)).dst(new ConnectPoint(deviceD5.id(), port5)).type(DIRECT)
+                .state(Link.State.ACTIVE).build();
+        linkList.add(link4);
+
+        // Path
+        path1 = new DefaultPath(providerId, linkList, 10);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Checks the operation of getInstance() method.
+     */
+    @Test
+    public void testGetInstance() {
+        assertThat(srTeHandler, is(notNullValue()));
+    }
+
+    /**
+     * Checks the operation of reserveGlobalPool() method.
+     */
+    @Test
+    public void testReserveGlobalPool() {
+        assertThat(srTeHandler.reserveGlobalPool(GLOBAL_LABEL_SPACE_MIN, GLOBAL_LABEL_SPACE_MAX), is(true));
+    }
+
+    /**
+     * Checks the operation of allocateNodeLabel() method on node label.
+     */
+    @Test
+    public void testAllocateNodeLabel() {
+        // Specific device D1.deviceId
+
+        //device 1
+        String lsrId1 = "11.1.1.1";
+        // Allocate node label for specific device D1deviceId
+        assertThat(srTeHandler.allocateNodeLabel(deviceId1, lsrId1), is(true));
+        // Retrieve label from store
+        LabelResourceId labelId = pceStore.getGlobalNodeLabel(deviceId1);
+        // Check whether label is generated for this device D1.deviceId()
+        assertThat(labelId, is(notNullValue()));
+
+        // device 2
+        String lsrId2 = "12.1.1.1";
+        // Allocate node label for specific device D2.deviceId()
+        assertThat(srTeHandler.allocateNodeLabel(deviceId2, lsrId2), is(true));
+        // Retrieve label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId2);
+        // Check whether label is generated for this device D2.deviceId()
+        assertThat(labelId, is(notNullValue()));
+
+        // device 3
+        String lsrId3 = "13.1.1.1";
+        // Allocate node label for specific device D3.deviceId()
+        assertThat(srTeHandler.allocateNodeLabel(deviceId3, lsrId3), is(true));
+        // Retrieve label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId3);
+        // Check whether label is generated for this device D3.deviceId()
+        assertThat(labelId, is(notNullValue()));
+
+        // device 4
+        String lsrId4 = "14.1.1.1";
+        // Allocate node label for specific device D4.deviceId()
+        assertThat(srTeHandler.allocateNodeLabel(deviceId4, lsrId4), is(true));
+        // Retrieve label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId4);
+        // Check whether label is generated for this device D4.deviceId()
+        assertThat(labelId, is(notNullValue()));
+
+        // device 5
+        String lsrId5 = "15.1.1.1";
+        // Allocate node label for specific device D5.deviceId()
+        assertThat(srTeHandler.allocateNodeLabel(deviceId5, lsrId5), is(true));
+        // Retrieve label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId5);
+        // Check whether label is generated for this device D5.deviceId()
+        assertThat(labelId, is(notNullValue()));
+    }
+
+    /**
+     * Checks the operation of releaseNodeLabel() method on node label.
+     */
+    @Test
+    public void testReleaseNodeLabelSuccess() {
+        testAllocateNodeLabel();
+        // Specific device D1.deviceId()
+
+        //device 1
+        String lsrId1 = "11.1.1.1";
+        // Check whether successfully released node label
+        assertThat(srTeHandler.releaseNodeLabel(deviceId1, lsrId1), is(true));
+        // Check whether successfully removed label from store
+        LabelResourceId labelId = pceStore.getGlobalNodeLabel(deviceId1);
+        assertThat(labelId, is(nullValue()));
+
+        //device 2
+        String lsrId2 = "12.1.1.1";
+        // Check whether successfully released node label
+        assertThat(srTeHandler.releaseNodeLabel(deviceId2, lsrId2), is(true));
+        // Check whether successfully removed label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId2);
+        assertThat(labelId, is(nullValue()));
+
+        //device 3
+        String lsrId3 = "13.1.1.1";
+        // Check whether successfully released node label
+        assertThat(srTeHandler.releaseNodeLabel(deviceId3, lsrId3), is(true));
+        // Check whether successfully removed label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId3);
+        assertThat(labelId, is(nullValue()));
+
+        //device 4
+        String lsrId4 = "14.1.1.1";
+        // Check whether successfully released node label
+        assertThat(srTeHandler.releaseNodeLabel(deviceId4, lsrId4), is(true));
+        // Check whether successfully removed label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId4);
+        assertThat(labelId, is(nullValue()));
+
+        //device 5
+        String lsrId5 = "15.1.1.1";
+        // Check whether successfully released node label
+        assertThat(srTeHandler.releaseNodeLabel(deviceId5, lsrId5), is(true));
+        // Check whether successfully removed label from store
+        labelId = pceStore.getGlobalNodeLabel(deviceId5);
+        assertThat(labelId, is(nullValue()));
+    }
+
+    @Test
+    public void testReleaseNodeLabelFailure() {
+        testAllocateNodeLabel();
+
+        //device 6
+        String lsrId6 = "16.1.1.1";
+        // Check whether successfully released node label
+        DeviceId deviceId6 = DeviceId.deviceId("foo6");
+        assertThat(srTeHandler.releaseNodeLabel(deviceId6, lsrId6), is(false));
+    }
+
+    /**
+     * Checks the operation of allocateAdjacencyLabel() method on adjacency label.
+     */
+    @Test
+    public void testAllocateAdjacencyLabel() {
+        // test link1
+        // Check whether adjacency label is allocated successfully.
+        assertThat(srTeHandler.allocateAdjacencyLabel(link1), is(true));
+        // Retrieve from store and check whether adjacency label is generated successfully for this device.
+        LabelResourceId labelId = pceStore.getAdjLabel(link1);
+        assertThat(labelId, is(notNullValue()));
+
+        // test link2
+        // Check whether adjacency label is allocated successfully.
+        assertThat(srTeHandler.allocateAdjacencyLabel(link2), is(true));
+        // Retrieve from store and check whether adjacency label is generated successfully for this device.
+        labelId = pceStore.getAdjLabel(link2);
+        assertThat(labelId, is(notNullValue()));
+
+        // test link3
+        // Check whether adjacency label is allocated successfully.
+        assertThat(srTeHandler.allocateAdjacencyLabel(link3), is(true));
+        // Retrieve from store and check whether adjacency label is generated successfully for this device.
+        labelId = pceStore.getAdjLabel(link3);
+        assertThat(labelId, is(notNullValue()));
+
+        // test link4
+        // Check whether adjacency label is allocated successfully.
+        assertThat(srTeHandler.allocateAdjacencyLabel(link4), is(true));
+        // Retrieve from store and check whether adjacency label is generated successfully for this device.
+        labelId = pceStore.getAdjLabel(link4);
+        assertThat(labelId, is(notNullValue()));
+    }
+
+    /**
+     * Checks the operation of releaseAdjacencyLabel() method on adjacency label.
+     */
+    @Test
+    public void testReleaseAdjacencyLabel() {
+        // Test link1
+        // Check whether adjacency label is released successfully.
+        assertThat(srTeHandler.allocateAdjacencyLabel(link1), is(true));
+        assertThat(srTeHandler.releaseAdjacencyLabel(link1), is(true));
+        // Retrieve from store and check whether adjacency label is removed successfully for this device.
+        LabelResourceId labelId = pceStore.getAdjLabel(link1);
+        assertThat(labelId, is(nullValue()));
+
+        // Test link2
+        // Check whether adjacency label is released successfully.
+        assertThat(srTeHandler.allocateAdjacencyLabel(link2), is(true));
+        assertThat(srTeHandler.releaseAdjacencyLabel(link2), is(true));
+        // Retrieve from store and check whether adjacency label is removed successfully for this device.
+        labelId = pceStore.getAdjLabel(link2);
+        assertThat(labelId, is(nullValue()));
+    }
+
+    /**
+     * Checks the operation of computeLabelStack() method.
+     */
+    @Test
+    public void testComputeLabelStack() {
+        // Allocate node labels to each devices
+        labelId = LabelResourceId.labelResourceId(4097);
+        pceStore.addGlobalNodeLabel(deviceId1, labelId);
+        labelId = LabelResourceId.labelResourceId(4098);
+        pceStore.addGlobalNodeLabel(deviceId2, labelId);
+        labelId = LabelResourceId.labelResourceId(4099);
+        pceStore.addGlobalNodeLabel(deviceId3, labelId);
+        labelId = LabelResourceId.labelResourceId(4100);
+        pceStore.addGlobalNodeLabel(deviceId4, labelId);
+        labelId = LabelResourceId.labelResourceId(4101);
+        pceStore.addGlobalNodeLabel(deviceId5, labelId);
+
+        // Allocate adjacency labels to each devices
+        labelId = LabelResourceId.labelResourceId(5122);
+        pceStore.addAdjLabel(link1, labelId);
+        labelId = LabelResourceId.labelResourceId(5123);
+        pceStore.addAdjLabel(link2, labelId);
+        labelId = LabelResourceId.labelResourceId(5124);
+        pceStore.addAdjLabel(link3, labelId);
+        labelId = LabelResourceId.labelResourceId(5125);
+        pceStore.addAdjLabel(link4, labelId);
+
+        // Compute label stack
+        LabelStack labelStack = srTeHandler.computeLabelStack(path1);
+
+        List<LabelResourceId> labelList = labelStack.labelResources();
+        Iterator<LabelResourceId> iterator = labelList.iterator();
+
+        // check adjacency label of D1.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(5122)));
+
+        // check node-label of D2.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(4098)));
+
+        // check adjacency label of D2.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(5123)));
+
+        // check node-label of D3.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(4099)));
+
+        // check adjacency label of D3.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(5124)));
+
+        // check node-label of D4.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(4100)));
+
+        // check adjacency label of D4.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(5125)));
+
+        // check node-label of D5.deviceId()
+        labelId = iterator.next();
+        assertThat(labelId, is(LabelResourceId.labelResourceId(4101)));
+    }
+
+    private class MockDevice extends DefaultDevice {
+        MockDevice(DeviceId id, Annotations annotations) {
+            super(null, id, null, null, null, null, null, null, annotations);
+        }
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/ConsistentMapAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/ConsistentMapAdapter.java
new file mode 100644
index 0000000..8111693
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/ConsistentMapAdapter.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.DistributedPrimitive;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.Versioned;
+
+/**
+ * Testing adapter for the consistent map.
+ */
+public class ConsistentMapAdapter<K, V> implements ConsistentMap<K, V> {
+
+    @Override
+    public String name() {
+        return null;
+    }
+
+    @Override
+    public DistributedPrimitive.Type primitiveType() {
+        return DistributedPrimitive.Type.CONSISTENT_MAP;
+    }
+
+    @Override
+    public int size() {
+        return 0;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    @Override
+    public boolean containsKey(K key) {
+        return false;
+    }
+
+    @Override
+    public boolean containsValue(V value) {
+        return false;
+    }
+
+    @Override
+    public Versioned<V> get(K key) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> getOrDefault(K key, V defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> computeIf(K key, Predicate<? super V> condition,
+                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> put(K key, V value) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> putAndGet(K key, V value) {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> remove(K key) {
+        return null;
+    }
+
+    @Override
+    public void clear() {
+
+    }
+
+    @Override
+    public Set<K> keySet() {
+        return null;
+    }
+
+    @Override
+    public Collection<Versioned<V>> values() {
+        return null;
+    }
+
+    @Override
+    public Set<Map.Entry<K, Versioned<V>>> entrySet() {
+        return null;
+    }
+
+    @Override
+    public Versioned<V> putIfAbsent(K key, V value) {
+        return null;
+    }
+
+    @Override
+    public boolean remove(K key, V value) {
+        return false;
+    }
+
+    @Override
+    public boolean remove(K key, long version) {
+        return false;
+    }
+
+    @Override
+    public Versioned replace(K key, V value) {
+        return null;
+    }
+
+    @Override
+    public boolean replace(K key, V oldValue, V newValue) {
+        return false;
+    }
+
+    @Override
+    public boolean replace(K key, long oldVersion, V newValue) {
+        return false;
+    }
+
+    @Override
+    public void addListener(MapEventListener<K, V> listener, Executor executor) {
+
+    }
+
+    @Override
+    public void removeListener(MapEventListener<K, V> listener) {
+
+    }
+
+    @Override
+    public Map<K, V> asJavaMap() {
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/DistributedSetAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/DistributedSetAdapter.java
new file mode 100644
index 0000000..ae457b1
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/DistributedSetAdapter.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+import org.onosproject.store.service.AsyncDistributedSet;
+import org.onosproject.store.service.SetEventListener;
+
+/**
+ * Testing adapter for the distributed set.
+ */
+public class DistributedSetAdapter<E> implements AsyncDistributedSet<E> {
+    @Override
+    public CompletableFuture<Void> addListener(SetEventListener<E> listener) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Void> removeListener(SetEventListener<E> listener) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> add(E element) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(E element) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Integer> size() {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> isEmpty() {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> contains(E element) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> addAll(Collection<? extends E> c) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsAll(Collection<? extends E> c) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> retainAll(Collection<? extends E> c) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> removeAll(Collection<? extends E> c) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<? extends Set<E>> getAsImmutableSet() {
+        return null;
+    }
+
+    @Override
+    public String name() {
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/EventuallyConsistentMapAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/EventuallyConsistentMapAdapter.java
new file mode 100644
index 0000000..c030369
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/EventuallyConsistentMapAdapter.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiFunction;
+
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+
+/**
+ * Testing adapter for EventuallyConsistentMap.
+ */
+public class EventuallyConsistentMapAdapter<K, V> implements EventuallyConsistentMap<K, V> {
+
+    @Override
+    public String name() {
+        return null;
+    }
+
+    @Override
+    public Type primitiveType() {
+        return Type.EVENTUALLY_CONSISTENT_MAP;
+    }
+
+    @Override
+    public int size() {
+        return 0;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    @Override
+    public boolean containsKey(K key) {
+        return false;
+    }
+
+    @Override
+    public boolean containsValue(V value) {
+        return false;
+    }
+
+    @Override
+    public V get(K key) {
+        return null;
+    }
+
+    @Override
+    public void put(K key, V value) {
+
+    }
+
+    @Override
+    public V remove(K key) {
+        return null;
+    }
+
+    @Override
+    public void remove(K key, V value) {
+
+    }
+
+    @Override
+    public V compute(K key, BiFunction<K, V, V> recomputeFunction) {
+        return null;
+    }
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> m) {
+
+    }
+
+    @Override
+    public void clear() {
+
+    }
+
+    @Override
+    public Set<K> keySet() {
+        return null;
+    }
+
+    @Override
+    public Collection<V> values() {
+        return null;
+    }
+
+    @Override
+    public Set<Map.Entry<K, V>> entrySet() {
+        return null;
+    }
+
+    @Override
+    public void addListener(EventuallyConsistentMapListener<K, V> listener) {
+
+    }
+
+    @Override
+    public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
+
+    }
+
+    @Override
+    public CompletableFuture<Void> destroy() {
+        return CompletableFuture.completedFuture(null);
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/LabelResourceAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/LabelResourceAdapter.java
new file mode 100644
index 0000000..92ebbe6
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/LabelResourceAdapter.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Random;
+import java.util.Set;
+
+import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceDelegate;
+import org.onosproject.incubator.net.resource.label.LabelResourceEvent;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceListener;
+import org.onosproject.incubator.net.resource.label.LabelResourcePool;
+import org.onosproject.incubator.net.resource.label.LabelResourceProvider;
+import org.onosproject.incubator.net.resource.label.LabelResourceProviderRegistry;
+import org.onosproject.incubator.net.resource.label.LabelResourceProviderService;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceEvent.Type;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.provider.AbstractListenerProviderRegistry;
+import org.onosproject.net.provider.AbstractProviderService;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * Provides test implementation of class LabelResourceService.
+ */
+public class LabelResourceAdapter
+        extends AbstractListenerProviderRegistry<LabelResourceEvent, LabelResourceListener,
+                                                 LabelResourceProvider, LabelResourceProviderService>
+        implements LabelResourceService, LabelResourceAdminService, LabelResourceProviderRegistry {
+    public static final long GLOBAL_LABEL_SPACE_MIN = 4097;
+    public static final long GLOBAL_LABEL_SPACE_MAX = 5121;
+    public static final long LOCAL_LABEL_SPACE_MIN = 5122;
+    public static final long LOCAL_LABEL_SPACE_MAX = 9217;
+
+    private Random random = new Random();
+
+    @Override
+    public boolean createDevicePool(DeviceId deviceId,
+                                    LabelResourceId beginLabel,
+                                    LabelResourceId endLabel) {
+       return true;
+    }
+
+    @Override
+    public boolean createGlobalPool(LabelResourceId beginLabel,
+                                    LabelResourceId endLabel) {
+       return true;
+    }
+
+    @Override
+    public boolean destroyDevicePool(DeviceId deviceId) {
+       return true;
+    }
+
+    @Override
+    public boolean destroyGlobalPool() {
+       return true;
+    }
+
+    public long getLabelId(long min, long max) {
+      return random.nextInt((int) max - (int) min + 1) + (int) min;
+    }
+
+    @Override
+    public Collection<LabelResource> applyFromDevicePool(DeviceId deviceId,
+                                                  long applyNum) {
+        Collection<LabelResource> labelList = new LinkedList<>();
+        LabelResource label = new DefaultLabelResource(deviceId,
+                                  LabelResourceId.labelResourceId(
+                                  getLabelId(LOCAL_LABEL_SPACE_MIN, LOCAL_LABEL_SPACE_MAX)));
+        labelList.add(label);
+        return labelList;
+    }
+
+    @Override
+    public Collection<LabelResource> applyFromGlobalPool(long applyNum) {
+        Collection<LabelResource> labelList = new LinkedList<>();
+        LabelResource label = new DefaultLabelResource(DeviceId.deviceId("foo"),
+                                  LabelResourceId.labelResourceId(
+                                  getLabelId(GLOBAL_LABEL_SPACE_MIN, GLOBAL_LABEL_SPACE_MAX)));
+        labelList.add(label);
+        return labelList;
+    }
+
+    @Override
+    public boolean releaseToDevicePool(Multimap<DeviceId, LabelResource> release) {
+       return true;
+    }
+
+    @Override
+    public boolean releaseToGlobalPool(Set<LabelResourceId> release) {
+       return true;
+    }
+
+    @Override
+    public boolean isDevicePoolFull(DeviceId deviceId) {
+       return false;
+    }
+
+    @Override
+    public boolean isGlobalPoolFull() {
+       return false;
+    }
+
+    @Override
+    public long getFreeNumOfDevicePool(DeviceId deviceId) {
+       return 4;
+    }
+
+    @Override
+    public long getFreeNumOfGlobalPool() {
+       return 4;
+    }
+
+    @Override
+    public LabelResourcePool getDeviceLabelResourcePool(DeviceId deviceId) {
+       return null;
+    }
+
+    @Override
+    public LabelResourcePool getGlobalLabelResourcePool() {
+       return null;
+    }
+
+    private class InternalLabelResourceDelegate implements LabelResourceDelegate {
+        @Override
+        public void notify(LabelResourceEvent event) {
+            post(event);
+        }
+
+    }
+
+    private class InternalDeviceListener implements DeviceListener {
+        @Override
+        public void event(DeviceEvent event) {
+            Device device = event.subject();
+            if (Type.DEVICE_REMOVED.equals(event.type())) {
+                destroyDevicePool(device.id());
+            }
+        }
+    }
+
+    private class InternalLabelResourceProviderService
+            extends AbstractProviderService<LabelResourceProvider>
+            implements LabelResourceProviderService {
+
+        protected InternalLabelResourceProviderService(LabelResourceProvider provider) {
+            super(provider);
+        }
+
+        @Override
+        public void deviceLabelResourcePoolDetected(DeviceId deviceId,
+                                                    LabelResourceId beginLabel,
+                                                    LabelResourceId endLabel) {
+            checkNotNull(deviceId, "deviceId is not null");
+            checkNotNull(beginLabel, "beginLabel is not null");
+            checkNotNull(endLabel, "endLabel is not null");
+            createDevicePool(deviceId, beginLabel, endLabel);
+        }
+
+        @Override
+        public void deviceLabelResourcePoolDestroyed(DeviceId deviceId) {
+            checkNotNull(deviceId, "deviceId is not null");
+            destroyDevicePool(deviceId);
+        }
+
+    }
+
+    @Override
+    protected LabelResourceProviderService createProviderService(LabelResourceProvider provider) {
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockDeviceService.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockDeviceService.java
new file mode 100644
index 0000000..571dd01
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockDeviceService.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.Device;
+import org.onosproject.net.Device.Type;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+
+/**
+ * Test fixture for the device service.
+ */
+public class MockDeviceService implements DeviceService {
+    private List<Device> devices = new LinkedList<>();
+    private DeviceListener listener;
+
+    /**
+     * Adds a new device.
+     *
+     * @param dev device to be added
+     */
+    public void addDevice(Device dev) {
+        devices.add(dev);
+    }
+
+    /**
+     * Removes the specified device.
+     *
+     * @param dev device to be removed
+     */
+    public void removeDevice(Device dev) {
+        devices.remove(dev);
+    }
+
+    @Override
+    public Device getDevice(DeviceId deviceId) {
+        for (Device dev : devices) {
+            if (dev.id().equals(deviceId)) {
+                return dev;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Iterable<Device> getAvailableDevices() {
+        return devices;
+    }
+
+    @Override
+    public void addListener(DeviceListener listener) {
+        this.listener = listener;
+    }
+
+    /**
+     * Get the listener.
+     */
+    public DeviceListener getListener() {
+        return listener;
+    }
+
+    @Override
+    public void removeListener(DeviceListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public int getDeviceCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public Iterable<Device> getDevices() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Iterable<Device> getDevices(Type type) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Iterable<Device> getAvailableDevices(Type type) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public MastershipRole getRole(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<Port> getPorts(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<PortStatistics> getPortStatistics(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Port getPort(DeviceId deviceId, PortNumber portNumber) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isAvailable(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public String localStatus(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockNetConfigRegistryAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockNetConfigRegistryAdapter.java
new file mode 100644
index 0000000..785900b
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockNetConfigRegistryAdapter.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.ConfigApplyDelegate;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.SubjectFactory;
+import org.onosproject.pcep.api.DeviceCapability;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/* Mock test for network config registry. */
+public class MockNetConfigRegistryAdapter implements NetworkConfigService, NetworkConfigRegistry {
+    private ConfigFactory cfgFactory;
+    private Map<DeviceId, DeviceCapability> classConfig = new HashMap<>();
+
+    @Override
+    public void registerConfigFactory(ConfigFactory configFactory) {
+        cfgFactory = configFactory;
+    }
+
+    @Override
+    public void unregisterConfigFactory(ConfigFactory configFactory) {
+        cfgFactory = null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
+        if (configClass == DeviceCapability.class) {
+            DeviceCapability devCap = new DeviceCapability();
+            classConfig.put((DeviceId) subject, devCap);
+
+            JsonNode node = new ObjectNode(new MockJsonNode());
+            ObjectMapper mapper = new ObjectMapper();
+            ConfigApplyDelegate delegate = new InternalApplyDelegate();
+            devCap.init((DeviceId) subject, null, node, mapper, delegate);
+            return (C) devCap;
+        }
+
+        return null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
+        classConfig.remove(subject);
+    }
+
+    @Override
+    public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+        if (configClass == DeviceCapability.class) {
+            return (C) classConfig.get(subject);
+        }
+        return null;
+    }
+
+    private class MockJsonNode extends JsonNodeFactory {
+    }
+
+    // Auxiliary delegate to receive notifications about changes applied to
+    // the network configuration - by the apps.
+    private class InternalApplyDelegate implements ConfigApplyDelegate {
+        @Override
+        public void onApply(Config config) {
+            //configs.put(config.subject(), config.node());
+        }
+    }
+
+    @Override
+    public void addListener(NetworkConfigListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeListener(NetworkConfigListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Set<ConfigFactory> getConfigFactories() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Set<Class> getSubjectClasses() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SubjectFactory getSubjectFactory(String subjectClassKey) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SubjectFactory getSubjectFactory(Class subjectClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S> Set<S> getSubjects(Class<S> subjectClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S> Set<? extends Config<S>> getConfigs(S subject) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S, C extends Config<S>> C applyConfig(String subjectClassKey, S subject, String configKey, JsonNode json) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <S> void removeConfig(String subjectClassKey, S subject, String configKey) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public <S> void removeConfig(S subject) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public <S> void removeConfig() {
+        // TODO Auto-generated method stub
+
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockPcepClientController.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockPcepClientController.java
new file mode 100644
index 0000000..07bf81c
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/MockPcepClientController.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+
+
+import org.onosproject.incubator.net.tunnel.DefaultLabelStack;
+import org.onosproject.incubator.net.tunnel.LabelStack;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.net.Path;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepClientController;
+import org.onosproject.pcep.server.PcepClientListener;
+import org.onosproject.pcep.server.PcepEventListener;
+import org.onosproject.pcep.server.PcepNodeListener;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.types.PcepValueType;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.List;
+
+public class MockPcepClientController implements PcepClientController {
+
+    Map<PccId, PcepClient> clientMap = new HashMap<>();
+
+    @Override
+    public Collection<PcepClient> getClients() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void addClient(PccId pccId, PcepClient pc) {
+        clientMap.put(pccId, pc);
+        return;
+    }
+
+    @Override
+    public PcepClient getClient(PccId pccId) {
+        return clientMap.get(pccId);
+    }
+
+    @Override
+    public void addListener(PcepClientListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeListener(PcepClientListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void addEventListener(PcepEventListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeEventListener(PcepEventListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void addNodeListener(PcepNodeListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeNodeListener(PcepNodeListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void writeMessage(PccId pccId, PcepMessage msg) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void processClientMessage(PccId pccId, PcepMessage msg) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void closeConnectedClients() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public LabelStack computeLabelStack(Path path) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public LinkedList<PcepValueType> createPcepLabelStack(DefaultLabelStack labelStack, Path path) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Map<String, List<String>> getPcepExceptions() {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, Integer> getPcepErrorMsg() {
+        return null;
+    }
+
+    @Override
+    public Map<String, String> getPcepSessionMap() {
+        return null;
+    }
+
+    @Override
+    public Map<String, Byte> getPcepSessionIdMap() {
+        return null;
+    }
+
+    @Override
+    public void peerErrorMsg(String peerId, Integer errorType, Integer errValue) {
+
+    }
+
+    @Override
+    public boolean allocateLocalLabel(Tunnel tunnel) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/PceLabelStoreAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/PceLabelStoreAdapter.java
new file mode 100644
index 0000000..23ed95f
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/PceLabelStoreAdapter.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+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 org.onosproject.pcelabelstore.api.LspLocalLabelInfo;
+import org.onosproject.pcelabelstore.api.PceLabelStore;
+
+/**
+ * Provides test implementation of PceStore.
+ */
+public class PceLabelStoreAdapter implements PceLabelStore {
+
+    // Mapping device with global node label
+    private ConcurrentMap<DeviceId, LabelResourceId> globalNodeLabelMap = new ConcurrentHashMap<>();
+
+    // Mapping link with adjacency label
+    private ConcurrentMap<Link, LabelResourceId> adjLabelMap = new ConcurrentHashMap<>();
+
+    // Mapping tunnel with device local info with tunnel consumer id
+    private ConcurrentMap<TunnelId, List<LspLocalLabelInfo>> tunnelInfoMap = new ConcurrentHashMap<>();
+
+
+    // Locally maintain LSRID to device id mapping for better performance.
+    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
+
+    @Override
+    public boolean existsGlobalNodeLabel(DeviceId id) {
+        return globalNodeLabelMap.containsKey(id);
+    }
+
+    @Override
+    public boolean existsAdjLabel(Link link) {
+        return adjLabelMap.containsKey(link);
+    }
+
+    @Override
+    public boolean existsTunnelInfo(TunnelId tunnelId) {
+        return tunnelInfoMap.containsKey(tunnelId);
+    }
+
+    @Override
+    public int getGlobalNodeLabelCount() {
+        return globalNodeLabelMap.size();
+    }
+
+    @Override
+    public int getAdjLabelCount() {
+        return adjLabelMap.size();
+    }
+
+    @Override
+    public int getTunnelInfoCount() {
+        return tunnelInfoMap.size();
+    }
+
+    @Override
+    public boolean removeTunnelInfo(TunnelId tunnelId) {
+        tunnelInfoMap.remove(tunnelId);
+        if (tunnelInfoMap.containsKey(tunnelId)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public Map<DeviceId, LabelResourceId> getGlobalNodeLabels() {
+       return globalNodeLabelMap.entrySet().stream()
+                 .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()));
+    }
+
+    @Override
+    public Map<Link, LabelResourceId> getAdjLabels() {
+       return adjLabelMap.entrySet().stream()
+                 .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()));
+    }
+
+    @Override
+    public LabelResourceId getGlobalNodeLabel(DeviceId id) {
+        return globalNodeLabelMap.get(id);
+    }
+
+    @Override
+    public LabelResourceId getAdjLabel(Link link) {
+        return adjLabelMap.get(link);
+    }
+
+    @Override
+    public List<LspLocalLabelInfo> getTunnelInfo(TunnelId tunnelId) {
+        return tunnelInfoMap.get(tunnelId);
+    }
+
+    @Override
+    public void addGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId) {
+        globalNodeLabelMap.put(deviceId, labelId);
+    }
+
+    @Override
+    public void addAdjLabel(Link link, LabelResourceId labelId) {
+        adjLabelMap.put(link, labelId);
+    }
+
+    @Override
+    public void addTunnelInfo(TunnelId tunnelId, List<LspLocalLabelInfo> lspLocalLabelInfoList) {
+        tunnelInfoMap.put(tunnelId, lspLocalLabelInfoList);
+    }
+
+    @Override
+    public boolean removeGlobalNodeLabel(DeviceId id) {
+        globalNodeLabelMap.remove(id);
+        if (globalNodeLabelMap.containsKey(id)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean removeAdjLabel(Link link) {
+        adjLabelMap.remove(link);
+        if (adjLabelMap.containsKey(link)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addLsrIdDevice(String lsrId, DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean removeLsrIdDevice(String lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public DeviceId getLsrIdDevice(String lsrId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean addPccLsr(DeviceId lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean removePccLsr(DeviceId lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean hasPccLsr(DeviceId lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Map<TunnelId, List<LspLocalLabelInfo>> getTunnelInfos() {
+        return tunnelInfoMap.entrySet().stream()
+                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()));
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/PcepClientAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/PcepClientAdapter.java
new file mode 100644
index 0000000..7ab16ef
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/PcepClientAdapter.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.jboss.netty.channel.Channel;
+import org.onosproject.pcep.server.ClientCapability;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.LspKey;
+import org.onosproject.pcep.server.PcepClient;
+import org.onosproject.pcep.server.PcepSyncStatus;
+import org.onosproject.pcepio.protocol.PcepFactories;
+import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepStateReport;
+import org.onosproject.pcepio.protocol.PcepVersion;
+
+/**
+ * Representation of PCEP client adapter.
+ */
+public class PcepClientAdapter implements PcepClient {
+
+    private Channel channel;
+    protected String channelId;
+
+    private boolean connected;
+    private PccId pccId;
+    private ClientCapability capability;
+
+    private PcepVersion pcepVersion;
+    private PcepSyncStatus lspDbSyncStatus;
+    private PcepSyncStatus labelDbSyncStatus;
+    private Map<LspKey, Boolean> lspDelegationInfo = new HashMap<>();
+
+    /**
+     * Initialize instance with specified parameters.
+     *
+     * @param pccId PCC id
+     * @param pcepVersion PCEP message version
+     */
+    public void init(PccId pccId, PcepVersion pcepVersion) {
+        this.pccId = pccId;
+        this.pcepVersion = pcepVersion;
+    }
+
+    @Override
+    public final void disconnectClient() {
+        this.channel.close();
+    }
+
+    @Override
+    public final void sendMessage(PcepMessage m) {
+    }
+
+    @Override
+    public final void sendMessage(List<PcepMessage> msgs) {
+        try {
+            PcepMessage pcepMsg = msgs.get(0);
+            assertNotNull("PCEP MSG should be created.", pcepMsg);
+        } catch (RejectedExecutionException e) {
+            throw e;
+        }
+    }
+
+    @Override
+    public final boolean isConnected() {
+        return this.connected;
+    }
+
+    @Override
+    public String channelId() {
+        return channelId;
+    }
+
+    @Override
+    public final PccId getPccId() {
+        return this.pccId;
+    };
+
+    @Override
+    public final String getStringId() {
+        return this.pccId.toString();
+    }
+
+    @Override
+    public final void handleMessage(PcepMessage m) {
+    }
+
+    @Override
+    public boolean isOptical() {
+        return false;
+    }
+
+    @Override
+    public PcepFactory factory() {
+        return PcepFactories.getFactory(pcepVersion);
+    }
+
+    @Override
+    public void setLspDbSyncStatus(PcepSyncStatus syncStatus) {
+        this.lspDbSyncStatus = syncStatus;
+    }
+
+    @Override
+    public PcepSyncStatus lspDbSyncStatus() {
+        return lspDbSyncStatus;
+    }
+
+    @Override
+    public void setLabelDbSyncStatus(PcepSyncStatus syncStatus) {
+        this.labelDbSyncStatus = syncStatus;
+    }
+
+    @Override
+    public PcepSyncStatus labelDbSyncStatus() {
+        return labelDbSyncStatus;
+    }
+
+    @Override
+    public void setCapability(ClientCapability capability) {
+        this.capability = capability;
+    }
+
+    @Override
+    public ClientCapability capability() {
+        return capability;
+    }
+
+    @Override
+    public void addNode(PcepClient pc) {
+    }
+
+    @Override
+    public void deleteNode(PccId pccId) {
+    }
+
+    @Override
+    public void setLspAndDelegationInfo(LspKey lspKey, boolean dFlag) {
+        lspDelegationInfo.put(lspKey, dFlag);
+    }
+
+    @Override
+    public Boolean delegationInfo(LspKey lspKey) {
+        return lspDelegationInfo.get(lspKey);
+    }
+
+    @Override
+    public void initializeSyncMsgList(PccId pccId) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public List<PcepStateReport> getSyncMsgList(PccId pccId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void removeSyncMsgList(PccId pccId) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void addSyncMsgToList(PccId pccId, PcepStateReport rptMsg) {
+        // TODO Auto-generated method stub
+
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/StorageServiceAdapter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/StorageServiceAdapter.java
new file mode 100644
index 0000000..2f97c7d
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/StorageServiceAdapter.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import org.onosproject.store.service.AsyncDocumentTree;
+import org.onosproject.store.service.AsyncConsistentMultimap;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
+import org.onosproject.store.service.AtomicCounterBuilder;
+import org.onosproject.store.service.AtomicCounterMapBuilder;
+import org.onosproject.store.service.AtomicIdGeneratorBuilder;
+import org.onosproject.store.service.AtomicValueBuilder;
+import org.onosproject.store.service.ConsistentMapBuilder;
+import org.onosproject.store.service.ConsistentMultimapBuilder;
+import org.onosproject.store.service.ConsistentTreeMapBuilder;
+import org.onosproject.store.service.DistributedSetBuilder;
+import org.onosproject.store.service.DocumentTreeBuilder;
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+import org.onosproject.store.service.LeaderElectorBuilder;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.Topic;
+import org.onosproject.store.service.TransactionContextBuilder;
+import org.onosproject.store.service.WorkQueue;
+
+/**
+ * Adapter for the storage service.
+ */
+public class StorageServiceAdapter implements StorageService {
+    @Override
+    public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
+        return null;
+    }
+
+    @Override
+    public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() {
+        return null;
+    }
+
+    @Override
+    public <V> DocumentTreeBuilder<V> documentTreeBuilder() {
+        return null;
+    }
+
+    @Override
+    public <E> DistributedSetBuilder<E> setBuilder() {
+        return null;
+    }
+
+    @Override
+    public AtomicCounterBuilder atomicCounterBuilder() {
+        return null;
+    }
+
+    @Override
+    public AtomicIdGeneratorBuilder atomicIdGeneratorBuilder() {
+        return null;
+    }
+
+    @Override
+    public <V> AtomicValueBuilder<V> atomicValueBuilder() {
+        return null;
+    }
+
+    @Override
+    public TransactionContextBuilder transactionContextBuilder() {
+        return null;
+    }
+
+    @Override
+    public LeaderElectorBuilder leaderElectorBuilder() {
+        return null;
+    }
+
+    @Override
+    public <E> WorkQueue<E> getWorkQueue(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <K, V> AsyncConsistentMultimap<K, V> getAsyncSetMultimap(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <V> AsyncConsistentTreeMap<V> getAsyncTreeMap(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <T> Topic<T> getTopic(String name, Serializer serializer) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer) {
+        return null;
+    }
+
+    public <K, V> ConsistentMultimapBuilder<K, V> consistentMultimapBuilder() {
+        return null;
+    }
+
+    @Override
+    public <K> AtomicCounterMapBuilder<K> atomicCounterMapBuilder() {
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestAtomicCounter.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestAtomicCounter.java
new file mode 100644
index 0000000..88ca5e1
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestAtomicCounter.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.onosproject.store.service.AsyncAtomicCounter;
+import org.onosproject.store.service.AtomicCounterBuilder;
+
+/**
+ * Test implementation of atomic counter.
+ */
+public final class TestAtomicCounter implements AsyncAtomicCounter {
+    final AtomicLong value;
+
+    @Override
+    public String name() {
+        return null;
+    }
+
+    private TestAtomicCounter() {
+        value = new AtomicLong();
+    }
+
+    @Override
+    public CompletableFuture<Long> incrementAndGet() {
+        return CompletableFuture.completedFuture(value.incrementAndGet());
+    }
+
+    @Override
+    public CompletableFuture<Long> getAndIncrement() {
+        return CompletableFuture.completedFuture(value.getAndIncrement());
+    }
+
+    @Override
+    public CompletableFuture<Long> getAndAdd(long delta) {
+        return CompletableFuture.completedFuture(value.getAndAdd(delta));
+    }
+
+    @Override
+    public CompletableFuture<Long> addAndGet(long delta) {
+        return CompletableFuture.completedFuture(value.addAndGet(delta));
+    }
+
+    @Override
+    public CompletableFuture<Void> set(long value) {
+        this.value.set(value);
+        return CompletableFuture.completedFuture(null);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> compareAndSet(long expectedValue, long updateValue) {
+        return CompletableFuture.completedFuture(value.compareAndSet(expectedValue, updateValue));
+    }
+
+    @Override
+    public CompletableFuture<Long> get() {
+        return CompletableFuture.completedFuture(value.get());
+    }
+
+    public static AtomicCounterBuilder builder() {
+        return new Builder();
+    }
+
+    public static class Builder extends AtomicCounterBuilder {
+        @Override
+        public AsyncAtomicCounter build() {
+            return new TestAtomicCounter();
+        }
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestConsistentMap.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestConsistentMap.java
new file mode 100644
index 0000000..b67cdc9
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestConsistentMap.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.onosproject.store.primitives.ConsistentMapBackedJavaMap;
+import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.ConsistentMapBuilder;
+import org.onosproject.store.service.MapEvent;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.Versioned;
+
+import com.google.common.base.Objects;
+
+/**
+ * Test implementation of the consistent map.
+ */
+public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
+
+    private final List<MapEventListener<K, V>> listeners;
+    private final Map<K, Versioned<V>> map;
+    private final String mapName;
+    private final AtomicLong counter = new AtomicLong(0);
+
+    private TestConsistentMap(String mapName) {
+        map = new HashMap<>();
+        listeners = new LinkedList<>();
+        this.mapName = mapName;
+    }
+
+    private Versioned<V> version(V v) {
+        return new Versioned<>(v, counter.incrementAndGet(), System.currentTimeMillis());
+    }
+
+    /**
+     * Notify all listeners of an event.
+     */
+    private void notifyListeners(String mapName,
+                                 K key, Versioned<V> newvalue, Versioned<V> oldValue) {
+        MapEvent<K, V> event = new MapEvent<>(mapName, key, newvalue, oldValue);
+        listeners.forEach(
+                listener -> listener.event(event)
+        );
+    }
+
+    @Override
+    public int size() {
+        return map.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(K key) {
+        return map.containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(V value) {
+        return map.containsValue(value);
+    }
+
+    @Override
+    public Versioned<V> get(K key) {
+        return map.get(key);
+    }
+
+    @Override
+    public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+        AtomicBoolean updated = new AtomicBoolean(false);
+        Versioned<V> result = map.compute(key, (k, v) -> {
+            if (v == null) {
+                updated.set(true);
+                return version(mappingFunction.apply(key));
+            }
+            return v;
+        });
+        if (updated.get()) {
+            notifyListeners(mapName, key, result, null);
+        }
+        return result;
+    }
+
+    @Override
+    public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+            AtomicBoolean updated = new AtomicBoolean(false);
+            AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
+            Versioned<V> result = map.compute(key, (k, v) -> {
+                    updated.set(true);
+                    previousValue.set(v);
+                    return version(remappingFunction.apply(k, Versioned.valueOrNull(v)));
+                });
+            if (updated.get()) {
+                notifyListeners(mapName, key, result, previousValue.get());
+            }
+            return result;
+    }
+
+    @Override
+    public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        AtomicBoolean updated = new AtomicBoolean(false);
+        AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
+        Versioned<V> result = map.compute(key, (k, v) -> {
+            if (v != null) {
+                updated.set(true);
+                previousValue.set(v);
+                return version(remappingFunction.apply(k, v.value()));
+            }
+            return v;
+        });
+        if (updated.get()) {
+            notifyListeners(mapName, key, result, previousValue.get());
+        }
+        return result;
+    }
+
+    @Override
+    public Versioned<V> computeIf(K key, Predicate<? super V> condition,
+                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        AtomicBoolean updated = new AtomicBoolean(false);
+        AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
+        Versioned<V> result = map.compute(key, (k, v) -> {
+            if (condition.test(Versioned.valueOrNull(v))) {
+                previousValue.set(v);
+                updated.set(true);
+                return version(remappingFunction.apply(k, Versioned.valueOrNull(v)));
+            }
+            return v;
+        });
+        if (updated.get()) {
+            notifyListeners(mapName, key, result, previousValue.get());
+        }
+        return result;
+    }
+
+    @Override
+    public Versioned<V> put(K key, V value) {
+        Versioned<V> newValue = version(value);
+        Versioned<V> previousValue = map.put(key, newValue);
+        notifyListeners(mapName, key, newValue, previousValue);
+        return previousValue;
+    }
+
+    @Override
+    public Versioned<V> putAndGet(K key, V value) {
+        Versioned<V> newValue = version(value);
+        Versioned<V> previousValue = map.put(key, newValue);
+        notifyListeners(mapName, key, newValue, previousValue);
+        return newValue;
+    }
+
+    @Override
+    public Versioned<V> remove(K key) {
+        Versioned<V> result = map.remove(key);
+        notifyListeners(mapName, key, null, result);
+        return result;
+    }
+
+    @Override
+    public void clear() {
+        map.keySet().forEach(this::remove);
+    }
+
+    @Override
+    public Set<K> keySet() {
+        return map.keySet();
+    }
+
+    @Override
+    public Collection<Versioned<V>> values() {
+        return map.values()
+                .stream()
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public Set<Map.Entry<K, Versioned<V>>> entrySet() {
+        return map.entrySet();
+    }
+
+    @Override
+    public Versioned<V> putIfAbsent(K key, V value) {
+        Versioned<V> newValue = version(value);
+        Versioned<V> result =  map.putIfAbsent(key, newValue);
+        if (result == null) {
+            notifyListeners(mapName, key, newValue, result);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean remove(K key, V value) {
+        Versioned<V> existingValue = map.get(key);
+        if (Objects.equal(Versioned.valueOrNull(existingValue), value)) {
+            map.remove(key);
+            notifyListeners(mapName, key, null, existingValue);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean remove(K key, long version) {
+        Versioned<V> existingValue = map.get(key);
+        if (existingValue == null) {
+            return false;
+        }
+        if (existingValue.version() == version) {
+            map.remove(key);
+            notifyListeners(mapName, key, null, existingValue);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Versioned<V> replace(K key, V value) {
+        Versioned<V> existingValue = map.get(key);
+        if (existingValue == null) {
+            return null;
+        }
+        Versioned<V> newValue = version(value);
+        Versioned<V> result = map.put(key, newValue);
+        notifyListeners(mapName, key, newValue, result);
+        return result;
+    }
+
+    @Override
+    public boolean replace(K key, V oldValue, V newValue) {
+        Versioned<V> existingValue = map.get(key);
+        if (existingValue == null || !existingValue.value().equals(oldValue)) {
+            return false;
+        }
+        Versioned<V> value = version(newValue);
+        Versioned<V> result = map.put(key, value);
+        notifyListeners(mapName, key, value, result);
+        return true;
+    }
+
+    @Override
+    public boolean replace(K key, long oldVersion, V newValue) {
+        Versioned<V> existingValue = map.get(key);
+        if (existingValue == null || existingValue.version() != oldVersion) {
+            return false;
+        }
+        Versioned<V> value = version(newValue);
+        Versioned<V> result = map.put(key, value);
+        notifyListeners(mapName, key, value, result);
+        return true;
+    }
+
+    @Override
+    public void addListener(MapEventListener<K, V> listener) {
+        listeners.add(listener);
+    }
+
+    @Override
+    public void removeListener(MapEventListener<K, V> listener) {
+        listeners.remove(listener);
+    }
+
+    @Override
+    public Map<K, V> asJavaMap() {
+        return new ConsistentMapBackedJavaMap<>(this);
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder<K, V> extends ConsistentMapBuilder<K, V> {
+
+        @Override
+        public ConsistentMap<K, V> build() {
+            return new TestConsistentMap<>(name());
+        }
+
+        @Override
+        public AsyncConsistentMap<K, V> buildAsyncMap() {
+            return null;
+        }
+
+    }
+
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestDistributedSet.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestDistributedSet.java
new file mode 100644
index 0000000..011aa08
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestDistributedSet.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onosproject.store.primitives.DefaultDistributedSet;
+import org.onosproject.store.service.AsyncDistributedSet;
+import org.onosproject.store.service.DistributedSet;
+import org.onosproject.store.service.DistributedSetBuilder;
+import org.onosproject.store.service.SetEvent;
+import org.onosproject.store.service.SetEventListener;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Test implementation of the distributed set.
+ */
+public final class TestDistributedSet<E> extends DistributedSetAdapter<E> {
+    private final List<SetEventListener<E>> listeners;
+    private final Set<E> set;
+    private final String setName;
+
+    /**
+     * Public constructor.
+     *
+     * @param setName name to be assigned to this set
+     */
+    public TestDistributedSet(String setName) {
+        set = new HashSet<>();
+        listeners = new LinkedList<>();
+        this.setName = setName;
+    }
+
+    /**
+     * Notify all listeners of a set event.
+     *
+     * @param event the SetEvent
+     */
+    private void notifyListeners(SetEvent<E> event) {
+        listeners.forEach(
+                listener -> listener.event(event)
+        );
+    }
+
+    @Override
+    public CompletableFuture<Void> addListener(SetEventListener<E> listener) {
+        listeners.add(listener);
+        return CompletableFuture.completedFuture(null);
+    }
+
+    @Override
+    public CompletableFuture<Void> removeListener(SetEventListener<E> listener) {
+        listeners.remove(listener);
+        return CompletableFuture.completedFuture(null);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> add(E element) {
+        SetEvent<E> event =
+                new SetEvent<>(setName, SetEvent.Type.ADD, element);
+        notifyListeners(event);
+        return CompletableFuture.completedFuture(set.add(element));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(E element) {
+        SetEvent<E> event =
+                new SetEvent<>(setName, SetEvent.Type.REMOVE, element);
+        notifyListeners(event);
+        return CompletableFuture.completedFuture(set.remove(element));
+    }
+
+    @Override
+    public CompletableFuture<Integer> size() {
+        return CompletableFuture.completedFuture(set.size());
+    }
+
+    @Override
+    public CompletableFuture<Boolean> isEmpty() {
+        return CompletableFuture.completedFuture(set.isEmpty());
+    }
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        removeAll(ImmutableSet.copyOf(set));
+        return CompletableFuture.completedFuture(null);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> contains(E element) {
+        return CompletableFuture.completedFuture(set.contains(element));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> addAll(Collection<? extends E> c) {
+        c.forEach(this::add);
+        return CompletableFuture.completedFuture(true);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsAll(Collection<? extends E> c) {
+        return CompletableFuture.completedFuture(set.containsAll(c));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> retainAll(Collection<? extends E> c) {
+        Set notInSet2;
+        notInSet2 = Sets.difference(set, (Set<?>) c);
+        return removeAll(ImmutableSet.copyOf(notInSet2));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> removeAll(Collection<? extends E> c) {
+        c.forEach(this::remove);
+        return CompletableFuture.completedFuture(true);
+    }
+
+    @Override
+    public CompletableFuture<? extends Set<E>> getAsImmutableSet() {
+        return CompletableFuture.completedFuture(ImmutableSet.copyOf(set));
+    }
+
+    @Override
+    public String name() {
+        return this.setName;
+    }
+
+    @Override
+    public DistributedSet<E> asDistributedSet() {
+        return new DefaultDistributedSet<>(this, 0);
+    }
+
+    @Override
+    public DistributedSet<E> asDistributedSet(long timeoutMillis) {
+        return new DefaultDistributedSet<>(this, timeoutMillis);
+    }
+
+    /**
+     * Returns a new Builder instance.
+     *
+     * @return Builder
+     **/
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder constructor that instantiates a TestDistributedSet.
+     *
+     * @param <E>
+     */
+    public static class Builder<E> extends DistributedSetBuilder<E> {
+        @Override
+        public AsyncDistributedSet<E> build() {
+            return new TestDistributedSet(name());
+        }
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java
new file mode 100644
index 0000000..6c34554
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.store.Timestamp;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+
+import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
+import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
+
+/**
+ * Testing version of an Eventually Consistent Map.
+ */
+
+public final class TestEventuallyConsistentMap<K, V> extends EventuallyConsistentMapAdapter<K, V> {
+
+    private final HashMap<K, V> map;
+    private final String mapName;
+    private final List<EventuallyConsistentMapListener<K, V>> listeners;
+    private final BiFunction<K, V, Collection<NodeId>> peerUpdateFunction;
+
+    private TestEventuallyConsistentMap(String mapName,
+                                        BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) {
+        map = new HashMap<>();
+        listeners = new LinkedList<>();
+        this.mapName = mapName;
+        this.peerUpdateFunction = peerUpdateFunction;
+    }
+
+    /**
+     * Notify all listeners of an event.
+     */
+    private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) {
+        listeners.forEach(
+                listener -> listener.event(event)
+        );
+    }
+
+    @Override
+    public int size() {
+        return map.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(K key) {
+        return map.containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(V value) {
+        return map.containsValue(value);
+    }
+
+    @Override
+    public V get(K key) {
+        return map.get(key);
+    }
+
+    @Override
+    public void put(K key, V value) {
+        map.put(key, value);
+        EventuallyConsistentMapEvent<K, V> addEvent =
+                new EventuallyConsistentMapEvent<>(mapName, PUT, key, value);
+        notifyListeners(addEvent);
+        if (peerUpdateFunction != null) {
+            peerUpdateFunction.apply(key, value);
+        }
+    }
+
+    @Override
+    public V remove(K key) {
+        V result = map.remove(key);
+        if (result != null) {
+            EventuallyConsistentMapEvent<K, V> removeEvent =
+                    new EventuallyConsistentMapEvent<>(mapName, REMOVE,
+                            key, map.get(key));
+            notifyListeners(removeEvent);
+        }
+        return result;
+    }
+
+    @Override
+    public void remove(K key, V value) {
+        boolean removed = map.remove(key, value);
+        if (removed) {
+            EventuallyConsistentMapEvent<K, V> removeEvent =
+                    new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, value);
+            notifyListeners(removeEvent);
+        }
+    }
+
+    @Override
+    public V compute(K key, BiFunction<K, V, V> recomputeFunction) {
+        return map.compute(key, recomputeFunction);
+    }
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> m) {
+        map.putAll(m);
+    }
+
+    @Override
+    public void clear() {
+        map.clear();
+    }
+
+    @Override
+    public Set<K> keySet() {
+        return map.keySet();
+    }
+
+    @Override
+    public Collection<V> values() {
+        return map.values();
+    }
+
+    @Override
+    public Set<Map.Entry<K, V>> entrySet() {
+        return map.entrySet();
+    }
+
+    public static <K, V> Builder<K, V> builder() {
+        return new Builder<>();
+    }
+
+    @Override
+    public void addListener(EventuallyConsistentMapListener<K, V> listener) {
+        listeners.add(listener);
+    }
+
+    @Override
+    public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
+        listeners.remove(listener);
+    }
+
+    public static class Builder<K, V> implements EventuallyConsistentMapBuilder<K, V> {
+        private String name;
+        private BiFunction<K, V, Collection<NodeId>> peerUpdateFunction;
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withName(String name) {
+            this.name = name;
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace.Builder serializerBuilder) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace serializer) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V>
+        withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withEventExecutor(ExecutorService executor) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor(ExecutorService executor) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(ScheduledExecutorService executor) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V>
+        withPeerUpdateFunction(BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) {
+            this.peerUpdateFunction = peerUpdateFunction;
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled() {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(long period, TimeUnit unit) {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withFasterConvergence() {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMapBuilder<K, V> withPersistence() {
+            return this;
+        }
+
+        @Override
+        public EventuallyConsistentMap<K, V> build() {
+            if (name == null) {
+                name = "test";
+            }
+            return new TestEventuallyConsistentMap<>(name, peerUpdateFunction);
+        }
+    }
+
+}
+
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestStorageService.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestStorageService.java
new file mode 100644
index 0000000..84ae028
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestStorageService.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.util;
+
+import org.onosproject.store.service.AsyncConsistentMultimap;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
+import org.onosproject.store.service.AsyncDocumentTree;
+import org.onosproject.store.service.AtomicCounterBuilder;
+import org.onosproject.store.service.AtomicValueBuilder;
+import org.onosproject.store.service.ConsistentMapBuilder;
+import org.onosproject.store.service.ConsistentMultimapBuilder;
+import org.onosproject.store.service.DistributedSetBuilder;
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+import org.onosproject.store.service.LeaderElectorBuilder;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.Topic;
+import org.onosproject.store.service.TransactionContextBuilder;
+import org.onosproject.store.service.WorkQueue;
+
+public class TestStorageService extends StorageServiceAdapter {
+
+
+    @Override
+    public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
+        return TestEventuallyConsistentMap.builder();
+    }
+
+    @Override
+    public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() {
+        return TestConsistentMap.builder();
+    }
+
+    @Override
+    public <K, V> ConsistentMultimapBuilder<K, V> consistentMultimapBuilder() {
+        return null;
+    }
+
+    @Override
+    public <E> DistributedSetBuilder<E> setBuilder() {
+        return TestDistributedSet.builder();
+    }
+
+    @Override
+    public AtomicCounterBuilder atomicCounterBuilder() {
+        return TestAtomicCounter.builder();
+    }
+
+    @Override
+    public <V> AtomicValueBuilder<V> atomicValueBuilder() {
+        throw new UnsupportedOperationException("atomicValueBuilder");
+    }
+
+    @Override
+    public TransactionContextBuilder transactionContextBuilder() {
+        throw new UnsupportedOperationException("transactionContextBuilder");
+    }
+
+    @Override
+    public LeaderElectorBuilder leaderElectorBuilder() {
+        return null;
+    }
+
+    @Override
+    public <E> WorkQueue<E> getWorkQueue(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <K, V> AsyncConsistentMultimap<K, V> getAsyncSetMultimap(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <V> AsyncConsistentTreeMap<V> getAsyncTreeMap(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <T> Topic<T> getTopic(String name, Serializer serializer) {
+        return null;
+    }
+
+    @Override
+    public <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer) {
+        return null;
+    }
+}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcep/controller/impl/PcepClientControllerImplTest.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcep/controller/impl/PcepClientControllerImplTest.java
new file mode 100644
index 0000000..73ff8d6
--- /dev/null
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcep/controller/impl/PcepClientControllerImplTest.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 org.onosproject.pcep.server.PcepLspSyncAction.SEND_UPDATE;
+import static org.onosproject.pcep.server.PcepLspSyncAction.UNSTABLE;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelConfig;
+import org.jboss.netty.channel.ChannelFactory;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.tunnel.DefaultTunnel;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelListener;
+import org.onosproject.incubator.net.tunnel.TunnelName;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.incubator.net.tunnel.TunnelSubscription;
+import org.onosproject.incubator.net.tunnel.Tunnel.Type;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.Path;
+import org.onosproject.pcep.server.ClientCapability;
+import org.onosproject.pcep.server.PccId;
+import org.onosproject.pcep.server.PcepEventListener;
+import org.onosproject.pcep.server.PcepLspSyncAction;
+import org.onosproject.pcep.server.PcepPacketStats;
+import org.onosproject.pcep.server.PcepSyncStatus;
+import org.onosproject.pcep.server.driver.PcepAgent;
+import org.onosproject.pcep.server.impl.PcepClientControllerImpl;
+import org.onosproject.pcep.server.impl.PcepClientImpl;
+import org.onosproject.pcep.server.impl.PcepPacketStatsImpl;
+import org.onosproject.pcepio.exceptions.PcepOutOfBoundMessageException;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepFactories;
+import org.onosproject.pcepio.protocol.PcepInitiateMsg;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepMessageReader;
+import org.onosproject.pcepio.protocol.PcepVersion;
+import com.google.common.collect.ImmutableSet;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+public class PcepClientControllerImplTest {
+    TestPcepClientControllerImpl controllerImpl = new TestPcepClientControllerImpl();
+    TunnelService tunnelService = new MockTunnelService();
+    private PcepEventListener listener;
+    private Channel channel;
+
+    @Before
+    public void startUp() {
+        controllerImpl.setTunnelService(tunnelService);
+        listener = new PcepEventListenerAdapter();
+        controllerImpl.addEventListener(listener);
+        channel = new MockChannel();
+    }
+
+    @After
+    public void tearDown() {
+        controllerImpl.removeEventListener(listener);
+        listener = null;
+        controllerImpl.setTunnelService(null);
+    }
+
+    @Test
+    public void tunnelProviderAddedTest1() throws PcepParseException, PcepOutOfBoundMessageException {
+        PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
+
+        byte[] reportMsg = new byte[] {0x20, 0x0a, 0x00, (byte) 0x50, 0x21, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x00, 0x00, 0x01, // SRP object
+                                        0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                        0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x24, // LSP object
+                                        0x00, 0x00, 0x10, (byte) 0xAB,
+                                        0x00, 0x11, 0x00, 0x02, 0x54, 0x31, 0x00, 0x00, // symbolic path tlv
+                                        0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                        0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05,
+                                        0x05, 0x05, 0x05,
+
+                                        0x07, 0x10, 0x00, 0x14, // ERO object
+                                        0x01, 0x08, (byte) 0x01, 0x01, // ERO IPv4 sub objects
+                                        0x01, 0x01, 0x04, 0x00,
+                                        0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00, };
+
+        ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
+        buffer.writeBytes(reportMsg);
+
+        PcepMessageReader<PcepMessage> reader = PcepFactories.getGenericReader();
+        PcepMessage message = reader.readFrom(buffer);
+
+        PcepClientImpl pc = new PcepClientImpl();
+        PcepPacketStats pktStats = new PcepPacketStatsImpl();
+
+        pc.init(pccId, PcepVersion.PCEP_1, pktStats);
+        pc.setChannel(channel);
+        pc.setAgent(controllerImpl.agent());
+        pc.setConnected(true);
+        pc.setCapability(new ClientCapability(true, true, true, true, true));
+
+        controllerImpl.agent().addConnectedClient(pccId, pc);
+        controllerImpl.processClientMessage(pccId, message);
+
+        pc.setLspDbSyncStatus(PcepSyncStatus.SYNCED);
+        pc.setLabelDbSyncStatus(PcepSyncStatus.IN_SYNC);
+        pc.setLabelDbSyncStatus(PcepSyncStatus.SYNCED);
+
+        List<PcepMessage> deleteMsgs = ((MockChannel) channel).msgsWritten();
+        assertThat(deleteMsgs.size(), is(1));
+
+        for (PcepMessage msg : deleteMsgs) {
+            assertThat(((PcepInitiateMsg) msg).getPcInitiatedLspRequestList().getFirst().getSrpObject().getRFlag(),
+                       is(true));
+        }
+    }
+
+    @Test
+    public void tunnelProviderAddedTest2() throws PcepParseException, PcepOutOfBoundMessageException {
+        PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
+
+        byte[] reportMsg = new byte[] {0x20, 0x0a, 0x00, (byte) 0x50, 0x21, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x00, 0x00, 0x01, // SRP object
+                                        0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV
+                                        0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x24, 0x00, // LSP object
+                                        0x00, 0x10, (byte) 0xAB,
+                                        0x00, 0x11, 0x00, 0x02, 0x54, 0x31, 0x00, 0x00, // symbolic path tlv
+                                        0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV
+                                        0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05,
+                                        0x05, 0x05, 0x05,
+
+                                        0x07, 0x10, 0x00, 0x14, // ERO object
+                                        0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects
+                                        0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00, };
+
+        ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
+        buffer.writeBytes(reportMsg);
+
+        PcepMessageReader<PcepMessage> reader = PcepFactories.getGenericReader();
+        PcepMessage message = reader.readFrom(buffer);
+
+        PcepClientImpl pc = new PcepClientImpl();
+        PcepPacketStats pktStats = new PcepPacketStatsImpl();
+
+        pc.init(pccId, PcepVersion.PCEP_1, pktStats);
+        pc.setChannel(channel);
+        pc.setAgent(controllerImpl.agent());
+        pc.setConnected(true);
+        pc.setCapability(new ClientCapability(true, true, true, true, true));
+
+        controllerImpl.agent().addConnectedClient(pccId, pc);
+        controllerImpl.processClientMessage(pccId, message);
+
+        pc.setLspDbSyncStatus(PcepSyncStatus.SYNCED);
+        pc.setLabelDbSyncStatus(PcepSyncStatus.IN_SYNC);
+        pc.setLabelDbSyncStatus(PcepSyncStatus.SYNCED);
+    }
+
+    class PcepEventListenerAdapter implements PcepEventListener {
+
+        public List<PcepMessage> handledMsg = new ArrayList<>();
+        public List<Tunnel> tunnelsToBeUpdatedToNw = new ArrayList<>();
+        public List<Tunnel> deletedFromNwTunnels = new ArrayList<>();
+
+        @Override
+        public void handleMessage(PccId pccId, PcepMessage msg) {
+            handledMsg.add(msg);
+        }
+
+        @Override
+        public void handleEndOfSyncAction(Tunnel tunnel, PcepLspSyncAction endOfSyncAction) {
+            if (endOfSyncAction == SEND_UPDATE) {
+                tunnelsToBeUpdatedToNw.add(tunnel);
+                return;
+            } else if (endOfSyncAction == UNSTABLE) {
+                deletedFromNwTunnels.add(tunnel);
+            }
+        }
+    }
+
+    class MockChannel implements Channel {
+        private List<PcepMessage> msgOnWire = new ArrayList<>();
+
+        @Override
+        public ChannelFuture write(Object o) {
+            if (o instanceof List<?>) {
+                @SuppressWarnings("unchecked")
+                List<PcepMessage> msgs = (List<PcepMessage>) o;
+                for (PcepMessage msg : msgs) {
+                    if (msg instanceof PcepInitiateMsg) {
+                        msgOnWire.add(msg);
+                    }
+                }
+            }
+            return null;
+        }
+
+        public List<PcepMessage> msgsWritten() {
+            return msgOnWire;
+        }
+
+        @Override
+        public int compareTo(Channel o) {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+        @Override
+        public Integer getId() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFactory getFactory() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public Channel getParent() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelConfig getConfig() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelPipeline getPipeline() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public boolean isOpen() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean isBound() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean isConnected() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public SocketAddress getLocalAddress() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public SocketAddress getRemoteAddress() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture write(Object message, SocketAddress remoteAddress) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture bind(SocketAddress localAddress) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture connect(SocketAddress remoteAddress) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture disconnect() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture unbind() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture close() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture getCloseFuture() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public int getInterestOps() {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+        @Override
+        public boolean isReadable() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean isWritable() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public ChannelFuture setInterestOps(int interestOps) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public ChannelFuture setReadable(boolean readable) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public boolean getUserDefinedWritability(int index) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public void setUserDefinedWritability(int index, boolean isWritable) {
+            // TODO Auto-generated method stub
+
+        }
+
+        @Override
+        public Object getAttachment() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public void setAttachment(Object attachment) {
+            // TODO Auto-generated method stub
+
+        }
+    }
+
+    class MockTunnelService implements TunnelService {
+        private HashMap<TunnelId, Tunnel> tunnelIdAsKeyStore = new HashMap<TunnelId, Tunnel>();
+        private int tunnelIdCounter = 0;
+
+        @Override
+        public TunnelId setupTunnel(ApplicationId producerId, ElementId srcElementId, Tunnel tunnel, Path path) {
+            TunnelId tunnelId = TunnelId.valueOf(String.valueOf(++tunnelIdCounter));
+            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(), tunnel.src(), tunnel.dst(), tunnel.type(),
+                                                      tunnel.state(), tunnel.groupId(), tunnelId, tunnel.tunnelName(),
+                                                      path, tunnel.annotations());
+            tunnelIdAsKeyStore.put(tunnelId, tunnelToInsert);
+            return tunnelId;
+        }
+
+        @Override
+        public Tunnel queryTunnel(TunnelId tunnelId) {
+            for (TunnelId tunnelIdKey : tunnelIdAsKeyStore.keySet()) {
+                if (tunnelIdKey.equals(tunnelId)) {
+                    return tunnelIdAsKeyStore.get(tunnelId);
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public Collection<Tunnel> queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) {
+            Collection<Tunnel> result = new HashSet<Tunnel>();
+            Tunnel tunnel = null;
+            for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
+                tunnel = tunnelIdAsKeyStore.get(tunnelId);
+
+                if ((null != tunnel) && (src.equals(tunnel.src())) && (dst.equals(tunnel.dst()))) {
+                    result.add(tunnel);
+                }
+            }
+
+            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+        }
+
+        @Override
+        public Collection<Tunnel> queryTunnel(Tunnel.Type type) {
+            Collection<Tunnel> result = new HashSet<Tunnel>();
+
+            for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
+                result.add(tunnelIdAsKeyStore.get(tunnelId));
+            }
+
+            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+        }
+
+        @Override
+        public Collection<Tunnel> queryAllTunnels() {
+            Collection<Tunnel> result = new HashSet<Tunnel>();
+
+            for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
+                result.add(tunnelIdAsKeyStore.get(tunnelId));
+            }
+
+            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+        }
+
+        @Override
+        public void addListener(TunnelListener listener) {
+            // TODO Auto-generated method stub
+
+        }
+
+        @Override
+        public void removeListener(TunnelListener listener) {
+            // TODO Auto-generated method stub
+
+        }
+
+        @Override
+        public Tunnel borrowTunnel(ApplicationId consumerId, TunnelId tunnelId, Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelName tunnelName,
+                                               Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst,
+                                               Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst,
+                                               Type type, Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public boolean downTunnel(ApplicationId producerId, TunnelId tunnelId) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean returnTunnel(ApplicationId consumerId, TunnelId tunnelId, Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean returnTunnel(ApplicationId consumerId, TunnelName tunnelName, Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Type type,
+                                    Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst,
+                                    Annotations... annotations) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public Collection<TunnelSubscription> queryTunnelSubscription(ApplicationId consumerId) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public int tunnelCount() {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+        @Override
+        public Iterable<Tunnel> getTunnels(DeviceId deviceId) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    }
+
+    private class TestPcepClientControllerImpl extends PcepClientControllerImpl {
+        public void setTunnelService(TunnelService tunnelService) {
+            this.tunnelService = tunnelService;
+        }
+
+        public PcepAgent agent() {
+            return this.agent;
+        }
+    }
+}
diff --git a/protocols/pcep/server/pom.xml b/protocols/pcep/server/pom.xml
new file mode 100755
index 0000000..4ee228c
--- /dev/null
+++ b/protocols/pcep/server/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2015-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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-pcep-protocol</artifactId>
+        <version>1.12.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-pcep-server</artifactId>
+    <packaging>pom</packaging>
+
+    <description>ONOS Pcep Server Protocol subsystem</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <modules>
+        <module>api</module>
+        <module>ctl</module>
+    </modules>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>