[ONOS-2287,ONOS-2288]Pcep TunnelProvider implementation

Change-Id: I4184336c200f1060e93be5dc28076ba35f6b98f4
diff --git a/core/api/src/main/java/org/onosproject/net/ConnectPoint.java b/core/api/src/main/java/org/onosproject/net/ConnectPoint.java
index b5ff42c..0d13f4a 100644
--- a/core/api/src/main/java/org/onosproject/net/ConnectPoint.java
+++ b/core/api/src/main/java/org/onosproject/net/ConnectPoint.java
@@ -85,6 +85,23 @@
     }
 
     /**
+     * Returns the identifier of the infrastructure device if the connection
+     * point belongs to a network element which is indeed an ip of pcc
+     * client identifier.
+     *
+     * @return network element identifier as a pcc client identifier
+     * @throws java.lang.IllegalStateException if connection point is not
+     *                                         associated with a pcc client
+     */
+    public IpElementId ipElementId() {
+        if (elementId instanceof IpElementId) {
+            return (IpElementId) elementId;
+        }
+        throw new IllegalStateException("Connection point not associated " +
+                                                "with an pcc client");
+    }
+
+    /**
      * Returns the connection port number.
      *
      * @return port number
diff --git a/core/api/src/main/java/org/onosproject/net/IpElementId.java b/core/api/src/main/java/org/onosproject/net/IpElementId.java
new file mode 100644
index 0000000..9e19b62
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/IpElementId.java
@@ -0,0 +1,61 @@
+package org.onosproject.net;
+
+import java.util.Objects;
+import org.onlab.packet.IpAddress;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Represent for a Element ID using ip address.
+ */
+public final class IpElementId extends ElementId {
+
+    private final IpAddress ipAddress;
+
+    /**
+     * Public construction is prohibited.
+     * @param ipAddress ip address
+     */
+    private IpElementId(IpAddress ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    /**
+     * Create a IP Element ID.
+     * @param ipAddress IP address
+     * @return IpElementId
+     */
+    public static IpElementId ipElement(IpAddress ipAddress) {
+        return new IpElementId(ipAddress);
+    }
+
+    /**
+     * Returns the ip address.
+     *
+     * @return ipAddress
+     */
+    public IpAddress ipAddress() {
+        return ipAddress;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ipAddress);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof IpElementId) {
+            final IpElementId other = (IpElementId) obj;
+            return Objects.equals(this.ipAddress, other.ipAddress);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).add("ipAddress", ipAddress).toString();
+    }
+}
diff --git a/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepFactoryVer1.java b/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepFactoryVer1.java
index 55da289..bc52f3e 100644
--- a/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepFactoryVer1.java
+++ b/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepFactoryVer1.java
@@ -220,5 +220,4 @@
     public PcepLabelRangeResvMsg.Builder buildPcepLabelRangeResvMsg() {
         return new PcepLabelRangeResvMsgVer1.Builder();
     }
-
 }
diff --git a/providers/pcep/tunnel/pom.xml b/providers/pcep/tunnel/pom.xml
index 5420a7f..ac9a17f 100644
--- a/providers/pcep/tunnel/pom.xml
+++ b/providers/pcep/tunnel/pom.xml
@@ -1,19 +1,23 @@
 <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/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>org.onosproject</groupId>
-		<artifactId>onos-pcep-providers</artifactId>
-		<version>1.3.0-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<artifactId>onos-pcep-provider-tunnel</artifactId>
-	<packaging>bundle</packaging>
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-pcep-providers</artifactId>
+        <version>1.3.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>onos-pcep-provider-tunnel</artifactId>
+    <packaging>bundle</packaging>
     <description>PCEP-based tunnel provider</description>
-	<dependencies>
-		<dependency>
-			<groupId>org.onosproject</groupId>
-			<artifactId>onos-app-pcep-api</artifactId>
-		</dependency>
-	</dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-pcep-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-pcep-controller-api</artifactId>
+        </dependency>
+    </dependencies>
 </project>
\ No newline at end of file
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java
new file mode 100644
index 0000000..7355aaa
--- /dev/null
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelApiMapper.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.pcep.tunnel.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.collections.map.MultiKeyMap;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelProviderService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Entity to provide tunnel DB and mapping for request/response between CORE to PCEP
+ * and PCEP to PCC.
+ */
+public class PcepTunnelApiMapper {
+    protected static final Logger log = LoggerFactory.getLogger(PcepTunnelApiMapper.class);
+
+    static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
+    // Map to store all the tunnel requests.
+    private Map<Integer, PcepTunnelData> tunnelRequestQueue;
+    //Map to store all core related tunnel requests.
+    private Map<TunnelId, PcepTunnelData> coreTunnelRequestQueue;
+    //Map to store all the created tunnels.
+    private Map<Integer, PcepTunnelData> tunnelDB;
+    // Map to store the tunnel ids, given by core and given by pcc.
+    private Map<TunnelId, Integer> tunnelIdMap;
+    //Map to store all the learnt tunnels.
+    private MultiKeyMap pccTunnelDB = new MultiKeyMap();
+
+    TunnelProviderService tunnelApiMapperservice;
+
+    /**
+     * Default constructor.
+     */
+    public PcepTunnelApiMapper() {
+        //TODO check if the map need to initialize
+        tunnelRequestQueue = new HashMap<Integer, PcepTunnelData>();
+        coreTunnelRequestQueue = new HashMap<TunnelId, PcepTunnelData>();
+        tunnelDB = new HashMap<Integer, PcepTunnelData>();
+        tunnelIdMap = new HashMap<TunnelId, Integer>();
+    }
+
+    /**
+     * Add tunnels to tunnel Request queues.
+     *
+     * @param srpId srp id
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void addToTunnelRequestQueue(int srpId, PcepTunnelData pcepTunnelData) {
+        tunnelRequestQueue.put(new Integer(srpId), pcepTunnelData);
+        log.debug("Tunnel Added to TunnelRequestQueue");
+    }
+
+    /**
+     * Map between Tunnel ID and pcc provided Tunnel ID.
+     *
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void addToTunnelIdMap(PcepTunnelData pcepTunnelData) {
+        int value = pcepTunnelData.statefulIpv4IndentifierTlv().getTunnelId() & 0xFFFF;
+        tunnelIdMap.put(pcepTunnelData.tunnel().tunnelId(), (new Integer(value)));
+        log.debug("Tunnel ID Added to tunnelIdMap");
+    }
+
+    /**
+     * Add tunnels to core tunnel request queue.
+     *
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void addToCoreTunnelRequestQueue(PcepTunnelData pcepTunnelData) {
+        coreTunnelRequestQueue.put(pcepTunnelData.tunnel().tunnelId(), pcepTunnelData);
+        log.debug("Tunnel Added to CoreTunnelRequestQueue");
+    }
+
+    /**
+     * Removes tunnels from the core tunnel request queue.
+     *
+     * @param tunnelId tunnel id
+     */
+    public void removeFromCoreTunnelRequestQueue(TunnelId tunnelId) {
+        coreTunnelRequestQueue.remove(tunnelId);
+        log.debug("Tunnnel create response sent to core and removed from CoreTunnelRequestQueue");
+    }
+
+    /**
+     * Handle the report which comes after initiate message.
+     *
+     * @param srpId srp id
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void handleCreateTunnelRequestQueue(int srpId, PcepTunnelData pcepTunnelData) {
+
+        int value = tunnelIdMap.get(pcepTunnelData.tunnel().tunnelId());
+        tunnelDB.put(new Integer(value), pcepTunnelData);
+        tunnelRequestQueue.remove(new Integer(srpId), pcepTunnelData);
+        log.debug("Tunnel Added to TunnelDBQueue and removed from TunnelRequestQueue. tunnel id {}"
+                + (new Integer(value)).toString());
+    }
+
+    /**
+     * Handle report which comes for update message.
+     *
+     * @param srpId srp id
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void handleUpdateTunnelRequestQueue(int srpId, PcepTunnelData pcepTunnelData) {
+        if (pcepTunnelData.rptFlag()) {
+            pcepTunnelData.setRptFlag(false);
+            int value = tunnelIdMap.get(pcepTunnelData.tunnel().tunnelId());
+            tunnelDB.put(new Integer(value), pcepTunnelData);
+            tunnelRequestQueue.remove(new Integer(srpId), pcepTunnelData);
+            log.debug("Tunnel Added to TunnelDBQueue and removed from TunnelRequestQueue. tunnel id {}" ,
+                      (new Integer(value)).toString());
+        } else {
+            pcepTunnelData.setRptFlag(true);
+            tunnelRequestQueue.put(new Integer(srpId), pcepTunnelData);
+            log.debug("Tunnel updated in TunnelRequestQueue");
+        }
+    }
+
+    /**
+     * Handle report for tunnel Release request.
+     *
+     * @param srpId srp id
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void handleRemoveFromTunnelRequestQueue(int srpId, PcepTunnelData pcepTunnelData) {
+
+        int value = tunnelIdMap.get(pcepTunnelData.tunnel().tunnelId());
+        tunnelIdMap.remove(pcepTunnelData.tunnel().tunnelId());
+        tunnelDB.remove(new Integer(value));
+        tunnelRequestQueue.remove(srpId);
+        log.debug("Tunnel removed from  TunnelDBQueue and TunnelRequestQueue");
+    }
+
+    /**
+     * Returns PcepTunnelData from the tunnel request queue.
+     *
+     * @param srpId srp id
+     * @return PcepTunnelData pcep tunnel data
+     */
+    public PcepTunnelData getDataFromTunnelRequestQueue(int srpId) {
+        return tunnelRequestQueue.get(new Integer(srpId));
+
+    }
+
+    /**
+     * Returns PcepTunnelData from the tunnel DB.
+     *
+     * @param tunnelId tunnel id
+     * @return PcepTunnelData pcep tunnel data
+     */
+    public PcepTunnelData getDataFromTunnelDBQueue(TunnelId tunnelId) {
+        int value = tunnelIdMap.get(tunnelId);
+        return tunnelDB.get((new Integer(value)));
+    }
+
+    /**
+     * Checks whether the tunnel exist in tunnel request queue.
+     *
+     * @param srpId srp id
+     * @return true if tunnel exist in reuest queue, false otherwise
+     */
+    public boolean checkFromTunnelRequestQueue(int srpId) {
+        boolean retValue = tunnelRequestQueue.containsKey(srpId);
+        return retValue;
+    }
+
+    /**
+     * Returns whether tunnel exist in tunnel db.
+     *
+     * @param tunnelId
+     * @return true/false
+     */
+    public boolean checkFromTunnelDBQueue(TunnelId tunnelId) {
+        int value = tunnelIdMap.get(tunnelId);
+        boolean retValue = tunnelDB.containsKey((new Integer(value)));
+        return retValue;
+    }
+
+    /**
+     * Add Learnt tunnels to pcc tunnel DB.
+     *
+     * @param pcepTunnelData pcep tunnel data
+     */
+    public void addPccTunnelDB(PcepTunnelData pcepTunnelData) {
+        pccTunnelDB.put(pcepTunnelData.statefulIpv4IndentifierTlv().getTunnelId() & 0xFFFFL,
+                        pcepTunnelData.statefulIpv4IndentifierTlv().getIpv4IngressAddress(), pcepTunnelData);
+    }
+}
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelData.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelData.java
new file mode 100644
index 0000000..f796a2d
--- /dev/null
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelData.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.pcep.tunnel.impl;
+
+import java.util.Objects;
+
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.Path;
+import org.onosproject.pcepio.types.StatefulIPv4LspIdentidiersTlv;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * To store all tunnel related information from Core and Path computation client.
+ */
+public class PcepTunnelData {
+
+    private Tunnel tunnel;
+    private Path path;
+    private int plspId;
+    private ElementId elementId;
+    private RequestType requestType;
+    private boolean rptFlag;
+
+    // data need to store from LSP object
+    private boolean lspAFlag;
+    private boolean lspDFlag;
+    private byte lspOFlag;
+    private short tunnelId;
+    private int extTunnelId;
+    private short lspId;
+    private StatefulIPv4LspIdentidiersTlv statefulIpv4IndentifierTlv;
+
+    /**
+     * Default constructor.
+     */
+    public PcepTunnelData() {
+        this.elementId = null;
+        this.tunnel = null;
+        this.path = null;
+        this.requestType = null;
+        this.rptFlag = false;
+        this.plspId = 0;
+    }
+
+    /**
+     * Constructor to initialize Tunnel, Path and Request type.
+     *
+     * @param tunnel mpls tunnel
+     * @param path Path in network
+     * @param requestType request type for tunnel
+     */
+    public PcepTunnelData(Tunnel tunnel, Path path, RequestType requestType) {
+        this.tunnel = tunnel;
+        this.path = path;
+        this.requestType = requestType;
+    }
+
+    /**
+     * Constructor to initialize ElemendId, Tunnel, Path and Request type.
+     *
+     * @param elementId Ip element id
+     * @param tunnel mpls tunnel
+     * @param path Path in network
+     * @param requestType request type for tunnel
+     */
+    public PcepTunnelData(ElementId elementId, Tunnel tunnel, Path path, RequestType requestType) {
+        this.elementId = elementId;
+        this.tunnel = tunnel;
+        this.path = path;
+        this.requestType = requestType;
+    }
+
+    /**
+     * Constructor to initialize Tunnel and Request type.
+     *
+     * @param tunnel Tunnel from core
+     * @param requestType request type for tunnel
+     */
+    public PcepTunnelData(Tunnel tunnel, RequestType requestType) {
+        this.tunnel = tunnel;
+        this.requestType = requestType;
+    }
+
+    /**
+     * Constructor to initialize ElementId, Tunnel and Request type.
+     *
+     * @param elementId Ip element id
+     * @param tunnel mpls tunnel
+     * @param requestType request type for tunnel
+     */
+    public PcepTunnelData(ElementId elementId, Tunnel tunnel, RequestType requestType) {
+        this.elementId = elementId;
+        this.tunnel = tunnel;
+        this.requestType = requestType;
+    }
+
+    /**
+     * Sets ip element id.
+     *
+     * @param elementId Ip element id
+     */
+    public void setElementId(ElementId elementId) {
+        this.elementId = elementId;
+    }
+
+    /**
+     * Sets tunnel.
+     *
+     * @param tunnel mpls tunnel
+     */
+    public void setTunnel(Tunnel tunnel) {
+        this.tunnel = tunnel;
+    }
+
+    /**
+     * Sets Path.
+     *
+     * @param path Path in network
+     */
+    public void setPath(Path path) {
+        this.path = path;
+    }
+
+    /**
+     * Request type for tunnel.
+     *
+     * @param requestType request type for tunnel
+     */
+    public void setRequestType(RequestType requestType) {
+        this.requestType = requestType;
+    }
+
+    /**
+     * Sets plspid generated from pcc.
+     *
+     * @param plspId plsp identifier
+     */
+    public void setPlspId(int plspId) {
+        this.plspId = plspId;
+    }
+
+    /**
+     * Sets A flag from lsp object.
+     *
+     * @param value A flag value
+     */
+    public void setLspAFlag(boolean value) {
+        this.lspAFlag = value;
+    }
+
+    /**
+     * Sets OF flag from lsp object.
+     *
+     * @param value OF flag value
+     */
+    public void setLspOFlag(byte value) {
+        this.lspOFlag = value;
+    }
+
+    /**
+     * Sets tunnel id from PCC.
+     *
+     * @param value tunnel id value
+     */
+    public void setTunnelId(short value) {
+        this.tunnelId = value;
+    }
+
+    /**
+     * Sets extended tunnel id from PCC.
+     *
+     * @param value extended tunnel id value
+     */
+    public void setExtTunnelId(int value) {
+        this.extTunnelId = value;
+    }
+
+    /**
+     * Sets lsp id from pcc.
+     *
+     * @param value lsp id
+     */
+    public void setLspId(short value) {
+        this.lspId = value;
+    }
+
+    /**
+     * Sets statefulIpv4Identifiers tlv.
+     * @param value statefulIpv4Identifiers tlv
+     */
+    public void setStatefulIpv4IndentifierTlv(StatefulIPv4LspIdentidiersTlv value) {
+        this.statefulIpv4IndentifierTlv = value;
+    }
+
+    /**
+     * Sets report flag.
+     *
+     * @param rptFlag report flag
+     */
+    public void setRptFlag(boolean rptFlag) {
+        this.rptFlag = rptFlag;
+    }
+
+    /**
+     * Sets D flag from lsp object.
+     *
+     * @param value D flag value
+     */
+    public void setLspDFlag(boolean value) {
+        this.lspDFlag = value;
+    }
+
+    /**
+     * To get Ip element id.
+     *
+     * @return Ip elemend id
+     */
+    public ElementId elementId() {
+        return this.elementId;
+    }
+
+    /**
+     * To get Tunnel.
+     *
+     * @return tunnel
+     */
+    public Tunnel tunnel() {
+        return this.tunnel;
+    }
+
+    /**
+     * To get Path.
+     *
+     * @return path
+     */
+    public Path path() {
+        return this.path;
+    }
+
+    /**
+     * To get request type.
+     *
+     * @return request type
+     */
+    public RequestType requestType() {
+        return this.requestType;
+    }
+
+    /**
+     * To get pLspId.
+     *
+     * @return pLspId
+     */
+    public int plspId() {
+        return this.plspId;
+    }
+
+    /**
+     * To get A flag.
+     *
+     * @return A flag
+     */
+    public boolean lspAFlag() {
+        return this.lspAFlag;
+    }
+
+    /**
+     * To get OF flag.
+     *
+     * @return OF flag
+     */
+    public byte lspOFlag() {
+        return this.lspOFlag;
+    }
+
+    /**
+     * To get tunnel id.
+     *
+     * @return tunnel id
+     */
+    public short tunnelId() {
+        return this.tunnelId;
+    }
+
+    /**
+     * To get extended tunnel id.
+     *
+     * @return extended tunnel id
+     */
+    public int extTunnelId() {
+        return this.extTunnelId;
+    }
+
+    /**
+     * To get pLspId.
+     *
+     * @return pLspId
+     */
+    public short lspId() {
+        return this.lspId;
+    }
+
+    /**
+     * To get D Flag.
+     *
+     * @return d flag
+     */
+    public boolean lspDFlag() {
+        return this.lspDFlag;
+    }
+
+    /**
+     * To get statefulIpv4Indentifier tlv.
+     *
+     * @return statefulIpv4Indentifier tlv
+     */
+    public StatefulIPv4LspIdentidiersTlv statefulIpv4IndentifierTlv() {
+        return this.statefulIpv4IndentifierTlv;
+    }
+
+    /**
+     * To get report flag.
+     *
+     * @return report flag
+     */
+    public boolean rptFlag() {
+        return this.rptFlag;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof PcepTunnelData) {
+            PcepTunnelData other = (PcepTunnelData) obj;
+            return Objects.equals(tunnel, other.tunnel)
+                    && Objects.equals(path, other.path)
+                    && Objects.equals(plspId, other.plspId)
+                    && Objects.equals(elementId, other.elementId)
+                    && Objects.equals(requestType, other.requestType)
+                    && Objects.equals(rptFlag, other.rptFlag)
+                    && Objects.equals(lspAFlag, other.lspAFlag)
+                    && Objects.equals(lspDFlag, other.lspDFlag)
+                    && Objects.equals(lspOFlag, other.lspOFlag)
+                    && Objects.equals(tunnelId, other.tunnelId)
+                    && Objects.equals(extTunnelId, other.extTunnelId)
+                    && Objects.equals(lspId, other.lspId)
+                    && Objects.equals(statefulIpv4IndentifierTlv, other.statefulIpv4IndentifierTlv);
+        }
+
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(tunnel, path, plspId, elementId, requestType, rptFlag, lspAFlag,
+                            lspDFlag, lspOFlag, tunnelId, extTunnelId, lspId, statefulIpv4IndentifierTlv);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).add("Tunnel", tunnel)
+                .add("Path", path).add("PlspId", plspId).add("ElementId", elementId)
+                .add("RequestType", requestType).add("RptFlag", rptFlag).add("LspAFlag", lspAFlag)
+                .add("LspDFlag", lspDFlag).add("LspOFlag", lspOFlag).add("TunnelId", tunnelId)
+                .add("ExtTunnelid", extTunnelId).add("LspId", lspId)
+                .add("StatefulIpv4IndentifierTlv", statefulIpv4IndentifierTlv).toString();
+    }
+}
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
index 4a7cbca..e859870 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
@@ -16,13 +16,18 @@
 package org.onosproject.provider.pcep.tunnel.impl;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.DefaultAnnotations.EMPTY;
 import static org.onosproject.net.DeviceId.deviceId;
 import static org.onosproject.net.PortNumber.portNumber;
+import static org.onosproject.pcep.api.PcepDpid.uri;
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Optional;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -31,9 +36,12 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.DefaultTunnel;
 import org.onosproject.incubator.net.tunnel.DefaultTunnelDescription;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
 import org.onosproject.incubator.net.tunnel.OpticalLogicId;
 import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
 import org.onosproject.incubator.net.tunnel.Tunnel;
@@ -50,9 +58,11 @@
 import org.onosproject.net.DefaultPath;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.ElementId;
+import org.onosproject.net.IpElementId;
 import org.onosproject.net.Link;
 import org.onosproject.net.Path;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
 import org.onosproject.net.provider.AbstractProvider;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.pcep.api.PcepController;
@@ -60,9 +70,34 @@
 import org.onosproject.pcep.api.PcepHopNodeDescription;
 import org.onosproject.pcep.api.PcepOperator.OperationType;
 import org.onosproject.pcep.api.PcepTunnel;
-import org.onosproject.pcep.api.PcepTunnel.PathState;
 import org.onosproject.pcep.api.PcepTunnel.PATHTYPE;
+import org.onosproject.pcep.api.PcepTunnel.PathState;
 import org.onosproject.pcep.api.PcepTunnelListener;
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepClientController;
+import org.onosproject.pcep.controller.PcepClientListener;
+import org.onosproject.pcep.controller.PcepEventListener;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcInitiatedLspRequest;
+import org.onosproject.pcepio.protocol.PcepAttribute;
+import org.onosproject.pcepio.protocol.PcepBandwidthObject;
+import org.onosproject.pcepio.protocol.PcepEndPointsObject;
+import org.onosproject.pcepio.protocol.PcepEroObject;
+import org.onosproject.pcepio.protocol.PcepInitiateMsg;
+import org.onosproject.pcepio.protocol.PcepLspObject;
+import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepMsgPath;
+import org.onosproject.pcepio.protocol.PcepReportMsg;
+import org.onosproject.pcepio.protocol.PcepRroObject;
+import org.onosproject.pcepio.protocol.PcepSrpObject;
+import org.onosproject.pcepio.protocol.PcepStateReport;
+import org.onosproject.pcepio.protocol.PcepUpdateMsg;
+import org.onosproject.pcepio.protocol.PcepUpdateRequest;
+import org.onosproject.pcepio.types.IPv4SubObject;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.onosproject.pcepio.types.StatefulIPv4LspIdentidiersTlv;
+import org.onosproject.pcepio.types.SymbolicPathNameTlv;
 import org.slf4j.Logger;
 
 import static org.onosproject.pcep.api.PcepDpid.*;
@@ -73,14 +108,13 @@
  */
 @Component(immediate = true)
 @Service
-public class PcepTunnelProvider extends AbstractProvider
-        implements TunnelProvider {
+public class PcepTunnelProvider extends AbstractProvider implements TunnelProvider {
 
     private static final Logger log = getLogger(PcepTunnelProvider.class);
     private static final long MAX_BANDWIDTH = 99999744;
     private static final long MIN_BANDWIDTH = 64;
     private static final String BANDWIDTH_UINT = "kbps";
-    static final String PROVIDER_ID = "org.onosproject.provider.tunnel.default";
+    static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
 
     private static final String TUNNLE_NOT_NULL = "Create failed,The given port may be wrong or has been occupied.";
 
@@ -90,23 +124,30 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PcepController controller;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PcepClientController pcepClientController;
     TunnelProviderService service;
 
     HashMap<String, TunnelId> tunnelMap = new HashMap<String, TunnelId>();
 
-    private InnerTunnerProvider listener = new InnerTunnerProvider();
+    private InnerTunnelProvider listener = new InnerTunnelProvider();
+
+    protected PcepTunnelApiMapper pcepTunnelAPIMapper = new PcepTunnelApiMapper();
+    private static final int DEFAULT_BANDWIDTH_VALUE = 10;
 
     /**
      * Creates a Tunnel provider.
      */
     public PcepTunnelProvider() {
-        super(new ProviderId("default", PROVIDER_ID));
+        super(new ProviderId("pcep", PROVIDER_ID));
     }
 
     @Activate
     public void activate() {
         service = tunnelProviderRegistry.register(this);
         controller.addTunnelListener(listener);
+        pcepClientController.addListener(listener);
+        pcepClientController.addEventListener(listener);
         log.info("Started");
     }
 
@@ -114,47 +155,173 @@
     public void deactivate() {
         tunnelProviderRegistry.unregister(this);
         controller.removeTunnelListener(listener);
+        pcepClientController.removeListener(listener);
         log.info("Stopped");
     }
 
     @Override
     public void setupTunnel(Tunnel tunnel, Path path) {
-        // TODO Auto-generated method stub
+        if (tunnel.type() != Tunnel.Type.MPLS) {
+            log.error("Tunnel Type MPLS is only supported");
+            return;
+        }
 
+        // check for tunnel end points
+        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
+            log.error("Tunnel source or destination is not valid");
+            return;
+        }
+
+        // Get the pcc client
+        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpTunnelEndPoint) tunnel.src()).ip()));
+
+        if (!(pc instanceof PcepClient)) {
+            log.error("There is no PCC connected with ip addresss {}"
+                    + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
+            return;
+        }
+        pcepSetupTunnel(tunnel, path, pc);
     }
 
     @Override
     public void setupTunnel(ElementId srcElement, Tunnel tunnel, Path path) {
-        // TODO Auto-generated method stub
 
+        if (tunnel.type() != Tunnel.Type.MPLS) {
+            log.error("Tunnel Type MPLS is only supported");
+            return;
+        }
+
+        if (!(srcElement instanceof IpElementId)) {
+            log.error("Element id is not valid");
+            return;
+        }
+
+        // check for tunnel end points
+        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
+            log.error("Tunnel source or destination is not valid");
+            return;
+        }
+
+        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpElementId) srcElement).ipAddress()));
+
+        if (!(pc instanceof PcepClient)) {
+            log.error("There is no PCC connected with ip addresss {}"
+                    + ((IpElementId) srcElement).ipAddress().toString());
+            return;
+        }
+        pcepSetupTunnel(tunnel, path, pc);
     }
 
     @Override
     public void releaseTunnel(Tunnel tunnel) {
-        // TODO Auto-generated method stub
 
+        if (tunnel.type() != Tunnel.Type.MPLS) {
+            log.error("Tunnel Type MPLS is only supported");
+            return;
+        }
+
+        // check for tunnel end points
+        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
+            log.error("Tunnel source or destination is not valid");
+            return;
+        }
+
+        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpTunnelEndPoint) tunnel.src()).ip()));
+
+        if (!(pc instanceof PcepClient)) {
+            log.error("There is no PCC connected with ip addresss {}"
+                    + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
+            return;
+        }
+        pcepReleaseTunnel(tunnel, pc);
     }
 
     @Override
     public void releaseTunnel(ElementId srcElement, Tunnel tunnel) {
-        // TODO Auto-generated method stub
+        if (tunnel.type() != Tunnel.Type.MPLS) {
+            log.error("Tunnel Type MPLS is only supported");
+            return;
+        }
 
+        if (!(srcElement instanceof IpElementId)) {
+            log.error("Element id is not valid");
+            return;
+        }
+
+        // check for tunnel end points
+        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
+            log.error("Tunnel source or destination is not valid");
+            return;
+        }
+
+        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpElementId) srcElement).ipAddress()));
+
+        if (!(pc instanceof PcepClient)) {
+            log.error("There is no PCC connected with ip addresss {}"
+                    + ((IpElementId) srcElement).ipAddress().toString());
+            return;
+        }
+        pcepReleaseTunnel(tunnel, pc);
     }
 
     @Override
     public void updateTunnel(Tunnel tunnel, Path path) {
-        // TODO Auto-generated method stub
+        if (tunnel.type() != Tunnel.Type.MPLS) {
+            log.error("Tunnel Type MPLS is only supported");
+            return;
+        }
 
+        // check for tunnel end points
+        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
+            log.error("Tunnel source or destination is not valid");
+            return;
+        }
+
+        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpTunnelEndPoint) tunnel.src()).ip()));
+
+        if (!(pc instanceof PcepClient)) {
+            log.error("There is no PCC connected with ip addresss {}"
+                    + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
+            return;
+        }
+        pcepUpdateTunnel(tunnel, path, pc);
     }
 
     @Override
     public void updateTunnel(ElementId srcElement, Tunnel tunnel, Path path) {
-        // TODO Auto-generated method stub
 
+        if (tunnel.type() != Tunnel.Type.MPLS) {
+            log.error("Tunnel Type MPLS is only supported");
+            return;
+        }
+
+        if (!(srcElement instanceof IpElementId)) {
+            log.error("Element id is not valid");
+            return;
+        }
+
+        // check for tunnel end points
+        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
+            log.error("Tunnel source or destination is not valid");
+            return;
+        }
+
+        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpElementId) srcElement).ipAddress()));
+
+        if (!(pc instanceof PcepClient)) {
+            log.error("There is no PCC connected with ip addresss {}"
+                    + ((IpElementId) srcElement).ipAddress().toString());
+            return;
+        }
+        pcepUpdateTunnel(tunnel, path, pc);
     }
 
     @Override
     public TunnelId tunnelAdded(TunnelDescription tunnel) {
+        if (tunnel.type() == Tunnel.Type.MPLS) {
+            pcepTunnelAPIMapper.removeFromCoreTunnelRequestQueue(tunnel.id());
+            return service.tunnelAdded(tunnel);
+        }
 
         long bandwidth = Long
                 .parseLong(tunnel.annotations().value("bandwidth"));
@@ -185,7 +352,7 @@
         PcepTunnel pcepTunnel = controller.applyTunnel(srcId, dstId, srcPort,
                                                        dstPort, bandwidth,
                                                        tunnel.tunnelName()
-                                                               .value());
+                                                       .value());
 
         checkNotNull(pcepTunnel, TUNNLE_NOT_NULL);
         TunnelDescription tunnelAdded = buildOpticalTunnel(pcepTunnel, null);
@@ -197,6 +364,11 @@
 
     @Override
     public void tunnelRemoved(TunnelDescription tunnel) {
+        if (tunnel.type() == Tunnel.Type.MPLS) {
+            pcepTunnelAPIMapper.removeFromCoreTunnelRequestQueue(tunnel.id());
+            service.tunnelRemoved(tunnel);
+        }
+
         Tunnel tunnelOld = tunnelQueryById(tunnel.id());
         checkNotNull(tunnelOld, "The tunnel id is not exsited.");
         if (tunnelOld.type() != Tunnel.Type.VLAN) {
@@ -215,6 +387,10 @@
 
     @Override
     public void tunnelUpdated(TunnelDescription tunnel) {
+        if (tunnel.type() == Tunnel.Type.MPLS) {
+            pcepTunnelAPIMapper.removeFromCoreTunnelRequestQueue(tunnel.id());
+            service.tunnelUpdated(tunnel);
+        }
 
         Tunnel tunnelOld = tunnelQueryById(tunnel.id());
         if (tunnelOld.type() != Tunnel.Type.VLAN) {
@@ -380,7 +556,6 @@
      * @return corresponding tunnel id of the a tunnel key.
      */
     private TunnelId getTunnelId(String tunnelKey) {
-
         for (String key : tunnelMap.keySet()) {
             if (key.equals(tunnelKey)) {
                 return tunnelMap.get(key);
@@ -405,11 +580,274 @@
 
     }
 
-    private class InnerTunnerProvider implements PcepTunnelListener {
+    /**
+     * Creates list of hops for ERO object from Path.
+     *
+     * @param path network path
+     * @return list of ipv4 subobjects
+     */
+    private LinkedList<PcepValueType> createPcepPath(Path path) {
+        LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
+        List<Link> listLink = path.links();
+        ConnectPoint source = null;
+        ConnectPoint destination = null;
+        IpAddress ipDstAddress = null;
+        IpAddress ipSrcAddress = null;
+        PcepValueType subObj = null;
+
+        for (Link link : listLink) {
+            source = link.src();
+            if (!(source.equals(destination))) {
+                //set IPv4SubObject for ERO object
+                ipSrcAddress = source.ipElementId().ipAddress();
+                subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
+                llSubObjects.add(subObj);
+            }
+
+            destination = link.dst();
+            ipDstAddress = destination.ipElementId().ipAddress();
+            subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
+            llSubObjects.add(subObj);
+        }
+        return llSubObjects;
+    }
+
+    /**
+     * Creates PcInitiated lsp request list for setup tunnel.
+     *
+     * @param tunnel mpls tunnel
+     * @param path network path
+     * @param pc pcep client
+     * @param srpId unique id for pcep message
+     * @return list of PcInitiatedLspRequest
+     * @throws PcepParseException while building pcep objects fails
+     */
+    LinkedList<PcInitiatedLspRequest> createPcInitiatedLspReqList(Tunnel tunnel, Path path,
+                                                                  PcepClient pc, int srpId)
+                                                                          throws PcepParseException {
+        PcepValueType tlv;
+        LinkedList<PcepValueType> llSubObjects = createPcepPath(path);
+
+        if (null == llSubObjects || 0 == llSubObjects.size()) {
+            log.error("There is no link information to create tunnel");
+            return null;
+        }
+
+        //build SRP object
+        PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(false).build();
+
+        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+        LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<PcInitiatedLspRequest>();
+        // set LSP identifiers TLV
+        tlv = new StatefulIPv4LspIdentidiersTlv((((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
+                                                (short) 0, (short) 0, 0,
+                                                (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
+        llOptionalTlv.add(tlv);
+        //set SymbolicPathNameTlv of LSP object
+        tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
+        llOptionalTlv.add(tlv);
+
+        //build LSP object
+        PcepLspObject lspobj = pc.factory().buildLspObject().setAFlag(true).setOFlag((byte) 0).setPlspId(0)
+                .setOptionalTlv(llOptionalTlv).build();
+
+        //build ENDPOINTS object
+        PcepEndPointsObject endpointsobj = pc.factory().buildEndPointsObject()
+                .setSourceIpAddress(((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt())
+                .setDestIpAddress(((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt())
+                .setPFlag(true).build();
+
+        //build ERO object
+        PcepEroObject eroobj = pc.factory().buildEroObject().setSubObjects(llSubObjects).build();
+
+        int iBandwidth = DEFAULT_BANDWIDTH_VALUE;
+        if (null != tunnel.annotations().value("bandwidth")) {
+            iBandwidth = Integer.parseInt(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();
+
+        PcInitiatedLspRequest initiateLspRequest = pc.factory().buildPcInitiatedLspRequest().setSrpObject(srpobj)
+                .setLspObject(lspobj).setEndPointsObject(endpointsobj).setEroObject(eroobj)
+                .setPcepAttribute(pcepAttribute).build();
+        llPcInitiatedLspRequestList.add(initiateLspRequest);
+        return llPcInitiatedLspRequestList;
+    }
+
+    /**
+     * To send initiate tunnel message to pcc.
+     *
+     * @param tunnel mpls tunnel info
+     * @param path explicit route for the tunnel
+     * @param pc pcep client to send message
+     */
+    private void pcepSetupTunnel(Tunnel tunnel, Path path, PcepClient pc) {
+        try {
+            int srpId = SrpIdGenerators.create();
+            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, RequestType.CREATE);
+
+            pcepTunnelAPIMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
+
+            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = createPcInitiatedLspReqList(tunnel, path,
+                                                                                                        pc, srpId);
+            if (null == llPcInitiatedLspRequestList || 0 == llPcInitiatedLspRequestList.size()) {
+                log.error("Failed to create PcInitiatedLspRequestList");
+                return;
+            }
+
+            //build PCInitiate message
+            PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
+                    .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList)
+                    .build();
+
+            pc.sendMessage(Collections.singletonList(pcInitiateMsg));
+
+            pcepTunnelAPIMapper.addToTunnelRequestQueue(srpId, pcepTunnelData);
+        } catch (PcepParseException e) {
+            log.error("PcepParseException occurred while processing setup tunnel {}", e.getMessage());
+        }
+    }
+
+    /**
+     * To send Release tunnel message to pcc.
+     *
+     * @param tunnel mpls tunnel info
+     * @param pc pcep client to send message
+     */
+    private void pcepReleaseTunnel(Tunnel tunnel, PcepClient pc) {
+        try {
+            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, RequestType.DELETE);
+            pcepTunnelAPIMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
+            int srpId = SrpIdGenerators.create();
+            TunnelId tunnelId = tunnel.tunnelId();
+            int plspId = 0;
+            StatefulIPv4LspIdentidiersTlv statefulIpv4IndentifierTlv = null;
+
+            if (!(pcepTunnelAPIMapper.checkFromTunnelDBQueue(tunnelId))) {
+                log.error("Tunnel doesnot exists. Tunnel id {}" + tunnelId.toString());
+                return;
+            } else {
+                PcepTunnelData pcepTunnelDbData = pcepTunnelAPIMapper.getDataFromTunnelDBQueue(tunnelId);
+                plspId = pcepTunnelDbData.plspId();
+                statefulIpv4IndentifierTlv = pcepTunnelDbData.statefulIpv4IndentifierTlv();
+            }
+            // build srp object
+            PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(true).build();
+
+            PcepValueType tlv;
+            LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<PcInitiatedLspRequest>();
+
+            if (null != statefulIpv4IndentifierTlv) {
+                tlv = statefulIpv4IndentifierTlv;
+            } else {
+                tlv = new StatefulIPv4LspIdentidiersTlv((
+                        ((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
+                        (short) 0, (short) 0, 0,
+                        (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
+            }
+            llOptionalTlv.add(tlv);
+            tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
+            llOptionalTlv.add(tlv);
+            // build lsp object, set r flag as false to delete the tunnel
+            PcepLspObject lspobj = pc.factory().buildLspObject().setRFlag(false).setPlspId(plspId)
+                    .setOptionalTlv(llOptionalTlv).build();
+
+            PcInitiatedLspRequest releaseLspRequest = pc.factory().buildPcInitiatedLspRequest().setSrpObject(srpobj)
+                    .setLspObject(lspobj).build();
+
+            llPcInitiatedLspRequestList.add(releaseLspRequest);
+
+            PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
+                    .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList).build();
+
+            pc.sendMessage(Collections.singletonList(pcInitiateMsg));
+
+            pcepTunnelAPIMapper.addToTunnelRequestQueue(srpId, pcepTunnelData);
+        } catch (PcepParseException e) {
+            log.error("PcepParseException occurred while processing release tunnel {}", e.getMessage());
+        }
+    }
+
+    /**
+     * To send Update tunnel request message to pcc.
+     *
+     * @param tunnel mpls tunnel info
+     * @param path explicit route for the tunnel
+     * @param pc pcep client to send message
+     */
+    private void pcepUpdateTunnel(Tunnel tunnel, Path path, PcepClient pc) {
+        try {
+            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, RequestType.UPDATE);
+            pcepTunnelAPIMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
+            int srpId = SrpIdGenerators.create();
+            TunnelId tunnelId = tunnel.tunnelId();
+            PcepValueType tlv;
+            int plspId = 0;
+
+            LinkedList<PcepValueType> llSubObjects = createPcepPath(path);
+            LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+            LinkedList<PcepUpdateRequest> llUpdateRequestList = new LinkedList<PcepUpdateRequest>();
+
+            //build SRP object
+            PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(false).build();
+
+            if (!(pcepTunnelAPIMapper.checkFromTunnelDBQueue(tunnelId))) {
+                log.error("Tunnel doesnot exists in DB");
+                return;
+            } else {
+                PcepTunnelData pcepTunnelDBData = pcepTunnelAPIMapper.getDataFromTunnelDBQueue(tunnelId);
+                plspId = pcepTunnelDBData.plspId();
+            }
+
+            tlv = new StatefulIPv4LspIdentidiersTlv((((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
+                                                    (short) 0, (short) 0, 0,
+                                                    (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
+            llOptionalTlv.add(tlv);
+
+            if (tunnel.tunnelName().value() != null) {
+                tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
+                llOptionalTlv.add(tlv);
+            }
+
+            // build lsp object
+            PcepLspObject lspobj = pc.factory().buildLspObject().setAFlag(true).setPlspId(plspId)
+                    .setOptionalTlv(llOptionalTlv).build();
+            // build ero object
+            PcepEroObject eroobj = pc.factory().buildEroObject().setSubObjects(llSubObjects).build();
+
+            int iBandwidth = DEFAULT_BANDWIDTH_VALUE;
+            if (null != tunnel.annotations().value("bandwidth")) {
+                iBandwidth = Integer.parseInt(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();
+            // build pcep msg path
+            PcepMsgPath msgPath = pc.factory().buildPcepMsgPath().setEroObject(eroobj).setPcepAttribute(pcepAttribute)
+                    .build();
+
+            PcepUpdateRequest updateRequest = pc.factory().buildPcepUpdateRequest().setSrpObject(srpobj)
+                    .setLspObject(lspobj).setMsgPath(msgPath).build();
+
+            llUpdateRequestList.add(updateRequest);
+
+            PcepUpdateMsg pcUpdateMsg = pc.factory().buildUpdateMsg().setUpdateRequestList(llUpdateRequestList).build();
+
+            pc.sendMessage(Collections.singletonList(pcUpdateMsg));
+            pcepTunnelAPIMapper.addToTunnelRequestQueue(srpId, pcepTunnelData);
+        } catch (PcepParseException e) {
+            log.error("PcepParseException occurred while processing release tunnel {}", e.getMessage());
+        }
+    }
+
+    private class InnerTunnelProvider implements PcepTunnelListener, PcepEventListener, PcepClientListener {
 
         @Override
         public void handlePCEPTunnel(PcepTunnel pcepTunnel) {
-
             TunnelDescription tunnel = null;
             // instance and id identify a tunnel together
             String tunnelKey = String.valueOf(pcepTunnel.getInstance())
@@ -442,9 +880,263 @@
 
             default:
                 log.error("Invalid tunnel operation");
+            }
+        }
 
+        @Override
+        public void handleMessage(PccId pccId, PcepMessage msg) {
+            try {
+                log.debug("tunnel provider handle message {}", msg.getType().toString());
+                switch (msg.getType()) {
+                case REPORT:
+                    int srpId = 0;
+                    LinkedList<PcepStateReport> llStateReportList = null;
+                    llStateReportList = ((PcepReportMsg) msg).getStateReportList();
+                    ListIterator<PcepStateReport> listIterator = llStateReportList.listIterator();
+                    PcepSrpObject srpObj = null;
+                    PcepLspObject lspObj = null;
+                    while (listIterator.hasNext()) {
+                        PcepStateReport stateRpt = listIterator.next();
+                        srpObj = stateRpt.getSrpObject();
+                        lspObj = stateRpt.getLspObject();
+
+                        if (srpObj instanceof PcepSrpObject) {
+                            srpId = srpObj.getSrpID();
+                        }
+
+                        log.debug("Plsp ID in handle message " + lspObj.getPlspId());
+                        log.debug("SRP ID in handle message " + srpId);
+
+                        if (!(pcepTunnelAPIMapper.checkFromTunnelRequestQueue(srpId))) {
+
+                            // Check the sync status
+                            if (lspObj.getSFlag()) {
+                                handleSyncReport(stateRpt);
+                            } else if (!pcepClientController.getClient(pccId).isSyncComplete()) {
+                                // sync is done
+                                pcepClientController.getClient(pccId).setIsSyncComplete(true);
+                            }
+                            continue;
+                        }
+
+                        handleReportMessage(srpId, lspObj);
+                    }
+                    break;
+
+                default:
+                    log.debug("Received unsupported message type {}", msg.getType().toString());
+                }
+            } catch (Exception e) {
+                log.error("Exception occured while processing report message {}", e.getMessage());
+            }
+        }
+
+        /**
+         * Handles report message for setup/update/delete tunnel request.
+         *
+         * @param srpId unique identifier for pcep message
+         * @param lspObj lsp object
+         */
+        private void handleReportMessage(int srpId, PcepLspObject lspObj) {
+            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
+            PcepTunnelData pcepTunnelData = pcepTunnelAPIMapper.getDataFromTunnelRequestQueue(srpId);
+            SparseAnnotations annotations = (SparseAnnotations) pcepTunnelData.tunnel().annotations();
+
+            // store the values required from report message
+            pcepTunnelData.setPlspId(lspObj.getPlspId());
+            pcepTunnelData.setLspAFlag(lspObj.getAFlag());
+            pcepTunnelData.setLspOFlag(lspObj.getOFlag());
+            pcepTunnelData.setLspDFlag(lspObj.getDFlag());
+
+            StatefulIPv4LspIdentidiersTlv ipv4LspTlv = null;
+            ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
+            while (listTlvIterator.hasNext()) {
+                PcepValueType tlv = listTlvIterator.next();
+                if (tlv.getType() == StatefulIPv4LspIdentidiersTlv.TYPE) {
+                    ipv4LspTlv = (StatefulIPv4LspIdentidiersTlv) tlv;
+                    break;
+                }
+            }
+            if (null != ipv4LspTlv) {
+                pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspTlv);
             }
 
+            Path path = pcepTunnelData.path();
+            Tunnel tunnel = pcepTunnelData.tunnel();
+            DefaultTunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(),
+                                                                       tunnel.dst(), tunnel.type(), tunnel.groupId(),
+                                                                       providerId, tunnel.tunnelName(), path,
+                                                                       annotations);
+
+            if (RequestType.CREATE == pcepTunnelData.requestType()) {
+                log.debug("Report received for create request");
+
+                pcepTunnelAPIMapper.handleCreateTunnelRequestQueue(srpId, pcepTunnelData);
+                if (0 == lspObj.getOFlag()) {
+                    log.warn("The tunnel is in down state");
+                }
+                tunnelAdded(td);
+            }
+            if (RequestType.DELETE == pcepTunnelData.requestType()) {
+                log.debug("Report received for delete request");
+                pcepTunnelAPIMapper.handleRemoveFromTunnelRequestQueue(srpId, pcepTunnelData);
+                tunnelRemoved(td);
+            }
+
+            if (RequestType.UPDATE == pcepTunnelData.requestType()) {
+                log.debug("Report received for update request");
+                pcepTunnelData.setRptFlag(true);
+                pcepTunnelAPIMapper.addToTunnelIdMap(pcepTunnelData);
+                pcepTunnelAPIMapper.handleUpdateTunnelRequestQueue(srpId, pcepTunnelData);
+
+                if (0 == lspObj.getOFlag()) {
+                    log.warn("The tunnel is in down state");
+                }
+                if (!(pcepTunnelAPIMapper.checkFromTunnelRequestQueue(srpId))) {
+                    tunnelUpdated(td);
+                }
+            }
+        }
+
+        /**
+         * Handles sync report received from pcc.
+         *
+         * @param stateRpt pcep state report
+         */
+        private void handleSyncReport(PcepStateReport stateRpt) {
+            PcepLspObject lspObj = stateRpt.getLspObject();
+            PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
+            checkNotNull(msgPath);
+            PcepRroObject rroObj = msgPath.getRroObject();
+            checkNotNull(rroObj);
+            int bandwidth = 0;
+
+            log.debug("Handle Sync report received from PCC.");
+
+            if (0 == lspObj.getOFlag()) {
+                log.warn("The PCC reported tunnel is in down state");
+            }
+            log.debug("Sync report received");
+
+            if (null != msgPath.getBandwidthObject()) {
+                bandwidth = msgPath.getBandwidthObject().getBandwidth();
+            }
+
+            buildAndStorePcepTunnelData(lspObj, rroObj, bandwidth);
+        }
+
+        /**
+         * To build Path in network from RRO object.
+         *
+         * @param rroObj rro object
+         * @param providerId provider id
+         * @return path object
+         */
+        private Path buildPathFromRroObj(PcepRroObject rroObj, ProviderId providerId) {
+            checkNotNull(rroObj);
+            List<Link> links = new ArrayList<Link>();
+            LinkedList<PcepValueType> llSubObj = rroObj.getSubObjects();
+            if (0 == llSubObj.size()) {
+                log.error("RRO in report message does not have hop information");
+            }
+            ListIterator<PcepValueType> tlvIterator = llSubObj.listIterator();
+
+            ConnectPoint src = null;
+            ConnectPoint dst = null;
+            boolean isSrcSet = false;
+            while (tlvIterator.hasNext()) {
+                PcepValueType subObj = tlvIterator.next();
+                switch (subObj.getType()) {
+
+                case IPv4SubObject.TYPE:
+
+                    IPv4SubObject ipv4SubObj = (IPv4SubObject) subObj;
+                    if (!isSrcSet) {
+                        IpAddress srcIp = IpAddress.valueOf(ipv4SubObj.getIpAddress());
+                        src = new ConnectPoint(IpElementId.ipElement(srcIp), PortNumber.portNumber(0));
+                        isSrcSet = true;
+                    } else {
+                        IpAddress dstIp = IpAddress.valueOf(ipv4SubObj.getIpAddress());
+                        dst = new ConnectPoint(IpElementId.ipElement(dstIp), PortNumber.portNumber(0));
+                        Link link = new DefaultLink(providerId, src, dst, Link.Type.DIRECT, EMPTY);
+                        links.add(link);
+                        src = dst;
+                    }
+                    break;
+                default:
+                    // the other sub objects are not required
+                }
+            }
+            return new DefaultPath(providerId, links, 0, EMPTY);
+        }
+
+        /**
+         * To build pcepTunnelData and informs core about the pcc reported tunnel.
+         *
+         * @param lspObj pcep lsp object
+         * @param rroObj pcep rro object
+         * @param bandwidth bandwidth of tunnel
+         */
+        private void buildAndStorePcepTunnelData(PcepLspObject lspObj, PcepRroObject rroObj,
+                                                 int bandwidth) {
+
+            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
+
+            // StatefulIPv4LspIdentidiersTlv in LSP object will have the source and destination address.
+            StatefulIPv4LspIdentidiersTlv lspIdenTlv = null;
+            SymbolicPathNameTlv pathNameTlv = null;
+            LinkedList<PcepValueType> llOptionalTlv = lspObj.getOptionalTlv();
+            ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
+            while (listIterator.hasNext()) {
+                PcepValueType tlv = listIterator.next();
+                switch (tlv.getType()) {
+                case StatefulIPv4LspIdentidiersTlv.TYPE:
+                    lspIdenTlv = (StatefulIPv4LspIdentidiersTlv) tlv;
+                    break;
+                case SymbolicPathNameTlv.TYPE:
+                    pathNameTlv = (SymbolicPathNameTlv) tlv;
+                    break;
+                default:
+                    // currently this tlv is not required
+                }
+            }
+
+            IpTunnelEndPoint tunnelEndPointSrc;
+            tunnelEndPointSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(lspIdenTlv.getIpv4IngressAddress()));
+            IpTunnelEndPoint tunnelEndPointDst;
+            tunnelEndPointDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(lspIdenTlv.getIpv4EgressAddress()));
+
+            Path path = buildPathFromRroObj(rroObj, providerId);
+
+            SparseAnnotations annotations = DefaultAnnotations.builder()
+                    .set("bandwidth", (new Integer(bandwidth)).toString())
+                    .build();
+
+            DefaultTunnelDescription td = new DefaultTunnelDescription(null, tunnelEndPointSrc,
+                                                                       tunnelEndPointDst, Tunnel.Type.MPLS,
+                                                                       new DefaultGroupId(0), providerId,
+                                                                       TunnelName.tunnelName(pathNameTlv.toString()),
+                                                                       path, annotations);
+            TunnelId tId = tunnelAdded(td);
+
+            Tunnel tunnel = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, Tunnel.Type.MPLS,
+                                              new DefaultGroupId(0), tId,
+                                              TunnelName.tunnelName(pathNameTlv.toString()), path, annotations);
+
+            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, RequestType.LSP_STATE_RPT);
+            pcepTunnelData.setStatefulIpv4IndentifierTlv(lspIdenTlv);
+            pcepTunnelAPIMapper.addPccTunnelDB(pcepTunnelData);
+            pcepTunnelAPIMapper.addToTunnelIdMap(pcepTunnelData);
+        }
+
+        @Override
+        public void clientConnected(PccId pccId) {
+            // TODO
+        }
+
+        @Override
+        public void clientDisconnected(PccId pccId) {
+            // TODO
         }
     }
 
@@ -452,5 +1144,4 @@
     public Tunnel tunnelQueryById(TunnelId tunnelId) {
         return service.tunnelQueryById(tunnelId);
     }
-
 }
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/RequestType.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/RequestType.java
new file mode 100644
index 0000000..5185445
--- /dev/null
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/RequestType.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.pcep.tunnel.impl;
+
+/**
+ * Enum of request types between pcc and pcep.
+ */
+public enum RequestType {
+    /**
+     * Specifies the request type for PCC is to create new tunnel.
+     */
+    CREATE,
+
+    /**
+     * Specifies the request type for PCC is to update existing tunnel.
+     */
+    UPDATE,
+
+    /**
+     * Specifies the request type for PCC is to delete existing tunnel.
+     */
+    DELETE,
+
+    /**
+     * Specifies the request type for PCC to report existing tunnel.
+     */
+    LSP_STATE_RPT;
+}
\ No newline at end of file
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/SrpIdGenerators.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/SrpIdGenerators.java
new file mode 100644
index 0000000..5b5a5fb
--- /dev/null
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/SrpIdGenerators.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.pcep.tunnel.impl;
+
+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;
+    }
+}