[ONOS] PCEP provider changes, added node listeners to topology provider

Change-Id: I98bc6445ee78a8f0bf53f897f0a25f678ec7fc99
diff --git a/providers/pcep/topology/BUCK b/providers/pcep/topology/BUCK
index 56ba605..7a64a61 100644
--- a/providers/pcep/topology/BUCK
+++ b/providers/pcep/topology/BUCK
@@ -3,6 +3,9 @@
     '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
     '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
     '//apps/pcep-api:onos-apps-pcep-api',
+    '//protocols/pcep/api:onos-protocols-pcep-api',
+    '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+    '//core/api:onos-api-tests',
 ]
 
 osgi_jar_with_tests (
diff --git a/providers/pcep/topology/pom.xml b/providers/pcep/topology/pom.xml
index 689e924..50a6364 100644
--- a/providers/pcep/topology/pom.xml
+++ b/providers/pcep/topology/pom.xml
@@ -24,10 +24,20 @@
   <artifactId>onos-pcep-provider-topology</artifactId>
   <packaging>bundle</packaging>
   <description>PCEP topology provider</description>
-  	<dependencies>
-		<dependency>
-			<groupId>org.onosproject</groupId>
-			<artifactId>onos-app-pcep-api</artifactId>
-		</dependency>
-	</dependencies>
-</project>
\ No newline at end of file
+     <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>
+        <dependency>
+             <groupId>org.onosproject</groupId>
+             <artifactId>onos-api</artifactId>
+             <classifier>tests</classifier>
+             <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/providers/pcep/topology/src/main/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProvider.java b/providers/pcep/topology/src/main/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProvider.java
index 75a53f3..38239ed 100644
--- a/providers/pcep/topology/src/main/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProvider.java
+++ b/providers/pcep/topology/src/main/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProvider.java
@@ -62,6 +62,10 @@
 import org.onosproject.pcep.api.PcepOperator.OperationType;
 import org.onosproject.pcep.api.PcepSwitch;
 import org.onosproject.pcep.api.PcepSwitchListener;
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepClientController;
+import org.onosproject.pcep.controller.PcepNodeListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -115,18 +119,40 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ClusterService clusterService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PcepClientController pcepClientController;
+
     private DeviceProviderService deviceProviderService;
     private LinkProviderService linkProviderService;
 
     private HashMap<Long, List<PortDescription>> portMap = new HashMap<>();
     private InternalLinkProvider listener = new InternalLinkProvider();
 
+    /*
+     * For the client supporting SR capability.
+     */
+    public static final String SR_CAPABILITY = "srCapability";
+
+    /*
+     * For the client supporting PCECC capability.
+     */
+    public static final String PCECC_CAPABILITY = "pceccCapability";
+
+    /*
+     * For the client supporting label stack capability.
+     */
+    public static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
+
+    public static final String LSRID = "lsrId";
+    private static final String UNKNOWN = "unknown";
+
     @Activate
     public void activate() {
         linkProviderService = linkProviderRegistry.register(this);
         deviceProviderService = deviceProviderRegistry.register(this);
         controller.addListener(listener);
         controller.addLinkListener(listener);
+        pcepClientController.addNodeListener(listener);
     }
 
     @Deactivate
@@ -135,6 +161,7 @@
         linkProviderService = null;
         controller.removeListener(listener);
         controller.removeLinkListener(listener);
+        pcepClientController.removeNodeListener(listener);
     }
 
     private List<PortDescription> buildPortDescriptions(PcepDpid dpid,
@@ -225,7 +252,7 @@
     }
 
     private class InternalLinkProvider
-            implements PcepSwitchListener, PcepLinkListener {
+            implements PcepSwitchListener, PcepLinkListener, PcepNodeListener {
 
         @Override
         public void switchAdded(PcepDpid dpid) {
@@ -306,6 +333,51 @@
             }
         }
 
+        @Override
+        public void addNode(PcepClient pc) {
+            if (deviceProviderService == null) {
+                return;
+            }
+
+            //Right now device URI for PCEP devices is their LSRID
+            DeviceId deviceId = deviceId(uri(new PcepDpid(pc.getPccId().id().getIp4Address().toInt())));
+            ChassisId cId = new ChassisId();
+
+            Device.Type deviceType = Device.Type.ROUTER;
+
+            DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
+            //PCC capabilities (SR, PCECC and PCECC-SR)
+            annotationBuilder.set(SR_CAPABILITY, String.valueOf(pc.capability().srCapability()));
+            annotationBuilder.set(PCECC_CAPABILITY, String.valueOf(pc.capability().pceccCapability()));
+            annotationBuilder.set(LABEL_STACK_CAPABILITY, String.valueOf(pc.capability().labelStackCapability()));
+            //PccId is the lsrId contained in openMsg, if not present it will be the socket address
+            annotationBuilder.set(LSRID, String.valueOf(pc.getPccId().id()));
+
+            DeviceDescription description = new DefaultDeviceDescription(
+                    deviceId.uri(),
+                    deviceType,
+                    UNKNOWN,
+                    UNKNOWN,
+                    UNKNOWN,
+                    UNKNOWN,
+                    cId,
+                    annotationBuilder.build());
+
+            deviceProviderService.deviceConnected(deviceId, description);
+        }
+
+        @Override
+        public void deleteNode(PccId pccId) {
+            if (deviceProviderService == null || deviceService == null) {
+                return;
+            }
+            //TODO: In device manager, in deviceDisconnected() method, get the device but null check is not validated
+            if (deviceService.getDevice(DeviceId.deviceId(uri(new PcepDpid(pccId.id()
+                    .getIp4Address().toInt())))) == null) {
+                return;
+            }
+            deviceProviderService.deviceDisconnected(deviceId(uri(new PcepDpid(pccId.id().getIp4Address().toInt()))));
+        }
     }
 
     @Override
diff --git a/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepClientAdapter.java b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepClientAdapter.java
new file mode 100644
index 0000000..034deaa
--- /dev/null
+++ b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepClientAdapter.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.pcep.topology.impl;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.jboss.netty.channel.Channel;
+import org.onosproject.pcep.controller.ClientCapability;
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepSyncStatus;
+import org.onosproject.pcepio.protocol.PcepFactories;
+import org.onosproject.pcepio.protocol.PcepFactory;
+import org.onosproject.pcepio.protocol.PcepMessage;
+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;
+
+    /**
+     * 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) {
+    }
+}
diff --git a/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepClientControllerAdapter.java b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepClientControllerAdapter.java
new file mode 100644
index 0000000..5153ab2
--- /dev/null
+++ b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepClientControllerAdapter.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.pcep.topology.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.onlab.packet.IpAddress;
+import org.onosproject.pcep.controller.ClientCapability;
+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.pcep.controller.PcepNodeListener;
+import org.onosproject.pcep.controller.driver.PcepAgent;
+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.PcepVersion;
+
+import com.google.common.collect.Sets;
+
+import static org.onosproject.pcepio.types.PcepErrorDetailInfo.ERROR_TYPE_19;
+import static org.onosproject.pcepio.types.PcepErrorDetailInfo.ERROR_VALUE_5;
+
+/**
+ * Representation of PCEP client controller adapter.
+ */
+public class PcepClientControllerAdapter implements PcepClientController {
+
+    protected ConcurrentHashMap<PccId, PcepClient> connectedClients =
+            new ConcurrentHashMap<PccId, PcepClient>();
+
+    protected PcepClientAgent agent = new PcepClientAgent();
+    protected Set<PcepClientListener> pcepClientListener = new HashSet<>();
+
+    protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
+    public Set<PcepNodeListener> pcepNodeListener = Sets.newHashSet();
+
+    @Activate
+    public void activate() {
+    }
+
+    @Deactivate
+    public void deactivate() {
+    }
+
+    @Override
+    public Collection<PcepClient> getClients() {
+        return connectedClients.values();
+    }
+
+    @Override
+    public PcepClient getClient(PccId pccId) {
+        if (null != connectedClients.get(pccId)) {
+            return connectedClients.get(pccId);
+        }
+        PcepClientAdapter pc = new PcepClientAdapter();
+        if (pccId.ipAddress().equals(IpAddress.valueOf(0xC010103))
+            || pccId.ipAddress().equals(IpAddress.valueOf(0xB6024E22))) {
+            pc.setCapability(new ClientCapability(true, false, false, false, false));
+        } else {
+            pc.setCapability(new ClientCapability(true, true, true, false, false));
+        }
+        pc.init(PccId.pccId(pccId.ipAddress()), PcepVersion.PCEP_1);
+        connectedClients.put(pccId, pc);
+        return pc;
+    }
+
+    @Override
+    public void addListener(PcepClientListener listener) {
+        if (!pcepClientListener.contains(listener)) {
+            this.pcepClientListener.add(listener);
+        }
+    }
+
+    @Override
+    public void addNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.add(listener);
+    }
+
+    @Override
+    public void removeNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.remove(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 processClientMessage(PccId pccId, PcepMessage msg) {
+
+        PcepClient pc = getClient(pccId);
+
+        switch (msg.getType()) {
+        case NONE:
+            break;
+        case OPEN:
+            break;
+        case KEEP_ALIVE:
+            //log.debug("Sending Keep Alive Message  to {" + pccIpAddress.toString() + "}");
+            pc.sendMessage(Collections.singletonList(pc.factory().buildKeepaliveMsg().build()));
+            break;
+        case PATH_COMPUTATION_REQUEST:
+            break;
+        case PATH_COMPUTATION_REPLY:
+            break;
+        case NOTIFICATION:
+            break;
+        case ERROR:
+            break;
+        case CLOSE:
+            //log.debug("Sending Close Message  to { }", pccIpAddress.toString());
+            pc.sendMessage(Collections.singletonList(pc.factory().buildCloseMsg().build()));
+            break;
+        case INITIATE:
+            if (!pc.capability().pcInstantiationCapability()) {
+                pc.sendMessage(Collections.singletonList(getErrMsg(pc.factory(),
+                        ERROR_TYPE_19, ERROR_VALUE_5)));
+            }
+            break;
+        case REPORT:
+            //Only update the listener if respective capability is supported else send PCEP-ERR msg
+            if (pc.capability().statefulPceCapability()) {
+                for (PcepEventListener l : pcepEventListener) {
+                    l.handleMessage(pccId, msg);
+                }
+            } else {
+                // Send PCEP-ERROR message.
+                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 MAX:
+            break;
+        case END:
+            break;
+        default:
+            break;
+        }
+    }
+
+    @Override
+    public void closeConnectedClients() {
+        PcepClient pc;
+        for (PccId id : connectedClients.keySet()) {
+            pc = getClient(id);
+            pc.disconnectClient();
+        }
+    }
+
+    private 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;
+    }
+
+    /**
+     * 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 {
+
+        @Override
+        public boolean addConnectedClient(PccId pccId, PcepClient pc) {
+
+            if (connectedClients.get(pccId) != null) {
+                return false;
+            } else {
+                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 switches: pccIp {}. Aborting ..", pccIpAddress.toString());
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public void removeConnectedClient(PccId pccId) {
+            connectedClients.remove(pccId);
+            for (PcepClientListener l : pcepClientListener) {
+                //log.warn("removal for {}", pccIpAddress.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.addNode(pc);
+            }
+        }
+
+        @Override
+        public void deleteNode(PccId pccId) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.deleteNode(pccId);
+            }
+        }
+    }
+}
diff --git a/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepControllerAdapter.java b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepControllerAdapter.java
new file mode 100644
index 0000000..6b8bda9
--- /dev/null
+++ b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepControllerAdapter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.provider.pcep.topology.impl;
+
+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;
+
+/**
+ * Implementation of PCEP controller.
+ */
+public class PcepControllerAdapter implements PcepController {
+
+    @Override
+    public Iterable<PcepSwitch> getSwitches() {
+        return null;
+    }
+
+    @Override
+    public PcepSwitch getSwitch(PcepDpid did) {
+        return null;
+    }
+
+    @Override
+    public void addListener(PcepSwitchListener listener) {
+
+    }
+
+    @Override
+    public void removeListener(PcepSwitchListener listener) {
+    }
+
+    @Override
+    public void addLinkListener(PcepLinkListener listener) {
+    }
+
+    @Override
+    public void removeLinkListener(PcepLinkListener listener) {
+    }
+
+    @Override
+    public void addTunnelListener(PcepTunnelListener listener) {
+    }
+
+    @Override
+    public void removeTunnelListener(PcepTunnelListener listener) {
+    }
+
+    @Override
+    public PcepTunnel applyTunnel(DeviceId srcDid, DeviceId dstDid, long srcPort, long dstPort, long bandwidth,
+                                  String name) {
+        return null;
+    }
+
+    @Override
+    public Boolean deleteTunnel(String id) {
+        return null;
+    }
+
+    @Override
+    public Boolean updateTunnelBandwidth(String id, long bandwidth) {
+        return null;
+    }
+
+    @Override
+    public void getTunnelStatistics(String pcepTunnelId) {
+
+    }
+}
diff --git a/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProviderTest.java b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProviderTest.java
new file mode 100644
index 0000000..65a4c02
--- /dev/null
+++ b/providers/pcep/topology/src/test/java/org/onosproject/provider/pcep/topology/impl/PcepTopologyProviderTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.onosproject.provider.pcep.topology.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.provider.pcep.topology.impl.PcepTopologyProvider.LABEL_STACK_CAPABILITY;
+import static org.onosproject.provider.pcep.topology.impl.PcepTopologyProvider.LSRID;
+import static org.onosproject.provider.pcep.topology.impl.PcepTopologyProvider.PCECC_CAPABILITY;
+import static org.onosproject.provider.pcep.topology.impl.PcepTopologyProvider.SR_CAPABILITY;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.ChassisId;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceProvider;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.link.LinkDescription;
+import org.onosproject.net.link.LinkProvider;
+import org.onosproject.net.link.LinkProviderRegistry;
+import org.onosproject.net.link.LinkProviderService;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.pcep.controller.ClientCapability;
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
+import org.onosproject.pcep.controller.PcepNodeListener;
+
+/**
+ * Test for PCEP topology provider.
+ */
+public class PcepTopologyProviderTest {
+    private static final String UNKNOWN = new String("unknown");
+    public static ProviderId providerId = new ProviderId("l3", "foo");
+    private final PcepClientControllerAdapter clientController = new PcepClientControllerAdapter();
+    private final PcepTopologyProvider provider = new PcepTopologyProvider();
+    private final MockDeviceRegistry nodeRegistry = new MockDeviceRegistry();
+    private final PcepControllerAdapter controller = new PcepControllerAdapter();
+    private final MockLinkRegistry linkRegistry = new MockLinkRegistry();
+    private final MockDeviceService deviceService = new MockDeviceService();
+    private Map<DeviceId, Device> deviceMap = new HashMap<>();
+
+    @Before
+    public void startUp() {
+        provider.pcepClientController = clientController;
+        provider.deviceProviderRegistry = nodeRegistry;
+        provider.linkProviderRegistry = linkRegistry;
+        provider.controller = controller;
+        provider.deviceService = deviceService;
+        provider.activate();
+    }
+
+    @After
+    public void tearDown() {
+        provider.deactivate();
+        provider.deviceProviderRegistry = null;
+        provider.pcepClientController = null;
+        provider.linkProviderRegistry = null;
+        provider.controller = null;
+        provider.deviceService = null;
+    }
+
+    /* Class implement device test registry */
+    private class MockLinkRegistry implements LinkProviderRegistry {
+        LinkProvider linkProvider;
+        Set<Link> links = new HashSet<>();
+
+        @Override
+        public LinkProviderService register(LinkProvider provider) {
+            this.linkProvider = provider;
+            return new MockProviderService();
+        }
+
+        @Override
+        public void unregister(LinkProvider provider) {
+            // TODO Auto-generated method stub
+        }
+
+        @Override
+        public Set<ProviderId> getProviders() {
+            return null;
+        }
+
+        private class MockProviderService implements LinkProviderService {
+
+            @Override
+            public void linkDetected(LinkDescription linkDescription) {
+                links.add(DefaultLink.builder().src(linkDescription.src())
+                        .dst(linkDescription.dst()).state(ACTIVE).type(linkDescription.type())
+                        .providerId(ProviderId.NONE).build());
+            }
+
+            @Override
+            public void linkVanished(LinkDescription linkDescription) {
+                links.remove(DefaultLink.builder().src(linkDescription.src())
+                        .dst(linkDescription.dst()).state(ACTIVE).type(linkDescription.type())
+                        .providerId(ProviderId.NONE).build());
+            }
+
+            @Override
+            public void linksVanished(ConnectPoint connectPoint) {
+                // TODO Auto-generated method stub
+            }
+
+            @Override
+            public void linksVanished(DeviceId deviceId) {
+                // TODO Auto-generated method stub
+            }
+
+            @Override
+            public LinkProvider provider() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+        }
+    }
+
+    /* Class implement device test registry */
+    private class MockDeviceRegistry implements DeviceProviderRegistry {
+        DeviceProvider provider;
+
+        Set<DeviceId> connected = new HashSet<>();
+
+        @Override
+        public DeviceProviderService register(DeviceProvider provider) {
+            this.provider = provider;
+            return new MockProviderService();
+        }
+
+        @Override
+        public void unregister(DeviceProvider provider) {
+        }
+
+        @Override
+        public Set<ProviderId> getProviders() {
+            return null;
+        }
+
+        private class MockProviderService implements DeviceProviderService {
+
+            @Override
+            public DeviceProvider provider() {
+                return null;
+            }
+
+            @Override
+            public void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription) {
+                connected.add(deviceId);
+                Device device = new DefaultDevice(ProviderId.NONE, deviceId, Device.Type.ROUTER, UNKNOWN, UNKNOWN,
+                        UNKNOWN, UNKNOWN, new ChassisId(), deviceDescription.annotations());
+                deviceMap.put(deviceId, device);
+            }
+
+            @Override
+            public void deviceDisconnected(DeviceId deviceId) {
+                connected.remove(deviceId);
+                deviceMap.remove(deviceId);
+            }
+
+            @Override
+            public void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions) {
+                // TODO Auto-generated method stub
+            }
+
+            @Override
+            public void portStatusChanged(DeviceId deviceId, PortDescription portDescription) {
+                // TODO Auto-generated method stub
+            }
+
+            @Override
+            public void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response) {
+                // TODO Auto-generated method stub
+            }
+
+            @Override
+            public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) {
+                // TODO Auto-generated method stub
+            }
+        }
+    }
+
+    /* Mock test for device service */
+    private class MockDeviceService extends DeviceServiceAdapter {
+        @Override
+        public Device getDevice(DeviceId deviceId) {
+            return deviceMap.get(deviceId);
+        }
+    }
+
+    /**
+     * Adds the PCEP device and removes it.
+     */
+    @Test
+    public void testPcepTopologyProviderTestAddDevice1() {
+        PcepClient pc = clientController.getClient(PccId.pccId(IpAddress.valueOf("1.1.1.1")));
+        for (PcepNodeListener l : clientController.pcepNodeListener) {
+            pc.setCapability(new ClientCapability(true, true, false, true, true));
+            l.addNode(pc);
+            assertThat(nodeRegistry.connected.size(), is(1));
+            assertThat(deviceMap.keySet().iterator().next(), is(DeviceId.deviceId("l3:1.1.1.1")));
+            assertThat(deviceMap.values().iterator().next().annotations().value(LABEL_STACK_CAPABILITY), is("true"));
+            assertThat(deviceMap.values().iterator().next().annotations().value(LSRID), is("1.1.1.1"));
+            assertThat(deviceMap.values().iterator().next().annotations().value(PCECC_CAPABILITY), is("true"));
+            assertThat(deviceMap.values().iterator().next().annotations().value(SR_CAPABILITY), is("true"));
+
+            l.deleteNode(pc.getPccId());
+            assertThat(nodeRegistry.connected.size(), is(0));
+        }
+    }
+}
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java
index daf315a..2babb3a 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientAdapter.java
@@ -139,4 +139,12 @@
     public ClientCapability capability() {
         return capability;
     }
+
+    @Override
+    public void addNode(PcepClient pc) {
+    }
+
+    @Override
+    public void deleteNode(PccId pccId) {
+    }
 }
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientControllerAdapter.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientControllerAdapter.java
index 822d8b6..39d863b 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientControllerAdapter.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepClientControllerAdapter.java
@@ -31,6 +31,7 @@
 import org.onosproject.pcep.controller.PcepClientController;
 import org.onosproject.pcep.controller.PcepClientListener;
 import org.onosproject.pcep.controller.PcepEventListener;
+import org.onosproject.pcep.controller.PcepNodeListener;
 import org.onosproject.pcep.controller.driver.PcepAgent;
 import org.onosproject.pcepio.protocol.PcepError;
 import org.onosproject.pcepio.protocol.PcepErrorInfo;
@@ -57,6 +58,7 @@
     protected Set<PcepClientListener> pcepClientListener = new HashSet<>();
 
     protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
+    public Set<PcepNodeListener> pcepNodeListener = Sets.newHashSet();
 
     @Activate
     public void activate() {
@@ -79,9 +81,9 @@
         PcepClientAdapter pc = new PcepClientAdapter();
         if (pccId.ipAddress().equals(IpAddress.valueOf(0xC010103))
             || pccId.ipAddress().equals(IpAddress.valueOf(0xB6024E22))) {
-            pc.setCapability(new ClientCapability(true, false, false));
+            pc.setCapability(new ClientCapability(true, false, false, false, false));
         } else {
-            pc.setCapability(new ClientCapability(true, true, true));
+            pc.setCapability(new ClientCapability(true, true, true, false, false));
         }
         pc.init(PccId.pccId(pccId.ipAddress()), PcepVersion.PCEP_1);
         connectedClients.put(pccId, pc);
@@ -96,6 +98,16 @@
     }
 
     @Override
+    public void addNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.add(listener);
+    }
+
+    @Override
+    public void removeNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.remove(listener);
+    }
+
+    @Override
     public void removeListener(PcepClientListener listener) {
         this.pcepClientListener.remove(listener);
     }
@@ -254,5 +266,19 @@
         public void processPcepMessage(PccId pccId, PcepMessage m) {
             processClientMessage(pccId, m);
         }
+
+        @Override
+        public void addNode(PcepClient pc) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.addNode(pc);
+            }
+        }
+
+        @Override
+        public void deleteNode(PccId pccId) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.deleteNode(pccId);
+            }
+        }
     }
 }
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java
index 2abab75..9d80daf 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelAddedTest.java
@@ -261,7 +261,7 @@
         tunnelService.setupTunnel(null, null, tunnel, null);
 
         PccId pccId = PccId.pccId(IpAddress.valueOf(0x4e1f0400));
-        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
+        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true, false, false));
         controller.getClient(pccId).setLspDbSyncStatus(SYNCED);
 
         // Process update message.
@@ -310,7 +310,7 @@
 
         PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
         controller.getClient(pccId).setLspDbSyncStatus(SYNCED);
-        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
+        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true, false, false));
         controller.processClientMessage(pccId, message);
 
         assertThat(registry.tunnelIdCounter, is((long) 1));
@@ -356,7 +356,7 @@
         PcepMessage message1 = reader1.readFrom(buffer1);
 
         PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
-        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
+        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true, false, false));
         controller.processClientMessage(pccId, message1);
 
         /* create 2nd LSP */
@@ -495,7 +495,7 @@
         PcepMessage message1 = reader1.readFrom(buffer1);
 
         PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1"));
-        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true));
+        controller.getClient(pccId).setCapability(new ClientCapability(true, true, true, false, false));
         controller.processClientMessage(pccId, message1);
 
         /* create 2nd LSP */