[Goldeneye] [ONOS-4161] BGP L3 Topology

Change-Id: I81ae4e88f6ab75202b98ed03cbe1597d0f6ddd1e
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
old mode 100755
new mode 100644
index 768e764..338c472
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
@@ -128,4 +128,25 @@
      * @return node listener
      */
     Set<BgpNodeListener> listener();
+
+    /**
+     * Register a listener for BGP message events.
+     *
+     * @param listener the listener to notify
+     */
+    void addLinkListener(BgpLinkListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to unregister
+     */
+    void removeLinkListener(BgpLinkListener listener);
+
+    /**
+     * Return BGP link listener.
+     *
+     * @return link listener
+     */
+    Set<BgpLinkListener> linkListener();
 }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java
old mode 100755
new mode 100644
index efa3b14..0acfb78
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java
@@ -20,12 +20,9 @@
 import java.util.List;
 import java.util.ListIterator;
 
-import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
-import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
-import org.onosproject.bgpio.types.AreaIDTlv;
 import org.onosproject.bgpio.types.AutonomousSystemTlv;
 import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
 import org.onosproject.bgpio.types.BgpValueType;
@@ -49,9 +46,9 @@
     public static final int NODE_DESCRIPTOR_REMOTE = 2;
 
     /**
-     * Initialize bgp id to generate URI.
+     * Initialize BGP id to generate URI.
      *
-     * @param linkNlri node Nlri.
+     * @param linkNlri node NLRI.
      * @param nodeDescriptorType node descriptor type, local/remote
      */
     public BgpDpid(final BgpLinkLsNlriVer4 linkNlri, int nodeDescriptorType) {
@@ -61,26 +58,13 @@
             this.stringBuilder.append("RD=").append(linkNlri.getRouteDistinguisher()
                                             .getRouteDistinguisher()).append(":");
         }
+        this.stringBuilder.append(":ROUTINGUNIVERSE=").append(((BgpLinkLsNlriVer4) linkNlri).getIdentifier());
 
-        try {
-            if ((linkNlri.getProtocolId() == BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_ONE)
-                || (linkNlri.getProtocolId() == BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_TWO)) {
-                this.stringBuilder.append("PROTO=").append("ISIS").append(":ID=")
-                                                                               .append(linkNlri.getIdentifier());
-            } else {
-                this.stringBuilder.append("PROTO=").append(linkNlri.getProtocolId()).append(":ID=")
-                                                                               .append(linkNlri.getIdentifier());
-            }
-
-            if (nodeDescriptorType == NODE_DESCRIPTOR_LOCAL) {
-                add(linkNlri.localNodeDescriptors());
-            } else if (nodeDescriptorType == NODE_DESCRIPTOR_REMOTE) {
-                add(linkNlri.remoteNodeDescriptors());
-            }
-        } catch (BgpParseException e) {
-            log.info("Exception BgpId string: " + e.toString());
+        if (nodeDescriptorType == NODE_DESCRIPTOR_LOCAL) {
+            add(linkNlri.localNodeDescriptors());
+        } else if (nodeDescriptorType == NODE_DESCRIPTOR_REMOTE) {
+            add(linkNlri.remoteNodeDescriptors());
         }
-
     }
 
     /*
@@ -96,72 +80,52 @@
     }
 
     /**
-     * Initialize bgp id to generate URI.
+     * Initialize BGP id to generate URI.
      *
-     * @param nodeNlri node Nlri.
+     * @param nlri node NLRI.
      */
-    public BgpDpid(final BgpNodeLSNlriVer4 nodeNlri) {
+    public BgpDpid(final BgpNodeLSNlriVer4 nlri) {
         this.stringBuilder = new StringBuilder("");
-
-        if (nodeNlri.getRouteDistinguisher() != null) {
-            this.stringBuilder.append("RD=").append(nodeNlri.getRouteDistinguisher()
-                                            .getRouteDistinguisher()).append(":");
+        if (((BgpNodeLSNlriVer4) nlri).getRouteDistinguisher() != null) {
+            this.stringBuilder.append("RD=")
+                    .append(((BgpNodeLSNlriVer4) nlri).getRouteDistinguisher().getRouteDistinguisher()).append(":");
         }
 
-        try {
-            if ((nodeNlri.getProtocolId() == BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_ONE)
-                || (nodeNlri.getProtocolId() == BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_TWO)) {
-
-                this.stringBuilder.append("PROTO=").append("ISIS").append(":ID=")
-                                                                               .append(nodeNlri.getIdentifier());
-            } else {
-                this.stringBuilder.append("PROTO=").append(nodeNlri.getProtocolId()).append(":ID=")
-                                                                               .append(nodeNlri.getIdentifier());
-            }
-            add(nodeNlri.getLocalNodeDescriptors());
-
-        } catch (BgpParseException e) {
-            log.info("Exception node string: " + e.toString());
-        }
+        this.stringBuilder.append(":ROUTINGUNIVERSE=").append(((BgpNodeLSNlriVer4) nlri).getIdentifier());
+        add(((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors().getNodedescriptors());
+        log.info("BgpDpid :: add");
     }
 
-    BgpDpid add(final Object value) {
-      NodeDescriptors nodeDescriptors = null;
-        if (value instanceof  BgpNodeLSIdentifier) {
-            BgpNodeLSIdentifier nodeLsIdentifier = (BgpNodeLSIdentifier) value;
-            nodeDescriptors = nodeLsIdentifier.getNodedescriptors();
-        } else if (value instanceof  NodeDescriptors) {
-            nodeDescriptors = (NodeDescriptors) value;
-        }
-
-        if (nodeDescriptors != null) {
-            List<BgpValueType> subTlvs = nodeDescriptors.getSubTlvs();
+    /**
+     * Obtains instance of this class by appending stringBuilder with node descriptor value.
+     *
+     * @param value node descriptor
+     * @return instance of this class
+     */
+    public BgpDpid add(final NodeDescriptors value) {
+        log.info("BgpDpid :: add function");
+        if (value != null) {
+            List<BgpValueType> subTlvs = value.getSubTlvs();
             ListIterator<BgpValueType> listIterator = subTlvs.listIterator();
             while (listIterator.hasNext()) {
                 BgpValueType tlv = listIterator.next();
                 if (tlv.getType() == AutonomousSystemTlv.TYPE) {
-                    AutonomousSystemTlv autonomousSystem = (AutonomousSystemTlv) tlv;
-                    this.stringBuilder.append(":AS=").append(autonomousSystem.getAsNum());
+                    this.stringBuilder.append(":ASN=").append(((AutonomousSystemTlv) tlv).getAsNum());
                 } else if (tlv.getType() == BgpLSIdentifierTlv.TYPE) {
-                    BgpLSIdentifierTlv lsIdentifierTlv = (BgpLSIdentifierTlv) tlv;
-                    this.stringBuilder.append(":LSID=").append(lsIdentifierTlv.getBgpLsIdentifier());
-                } else if (tlv.getType() ==  AreaIDTlv.TYPE) {
-                    AreaIDTlv areaIdTlv = (AreaIDTlv) tlv;
-                    this.stringBuilder.append(":AREA=").append(areaIdTlv.getAreaID());
+                    this.stringBuilder.append(":DOMAINID=").append(((BgpLSIdentifierTlv) tlv).getBgpLsIdentifier());
                 } else if (tlv.getType() == NodeDescriptors.IGP_ROUTERID_TYPE) {
                     if (tlv instanceof IsIsNonPseudonode) {
-                        IsIsNonPseudonode isisNonPseudonode = (IsIsNonPseudonode) tlv;
-                        this.stringBuilder.append(":ISOID=").append(isoNodeIdString(isisNonPseudonode.getIsoNodeId()));
+                        this.stringBuilder.append(":ISOID=").append(
+                                isoNodeIdString(((IsIsNonPseudonode) tlv).getIsoNodeId()));
                     } else if (tlv instanceof IsIsPseudonode) {
-                        IsIsPseudonode isisPseudonode = (IsIsPseudonode) tlv;
-                        this.stringBuilder.append(":ISOID=").append(isoNodeIdString(isisPseudonode.getIsoNodeId()));
+                        IsIsPseudonode isisPseudonode = ((IsIsPseudonode) tlv);
+                        this.stringBuilder.append(":ISOID=").append(
+                                isoNodeIdString(((IsIsPseudonode) tlv).getIsoNodeId()));
                         this.stringBuilder.append(":PSN=").append(isisPseudonode.getPsnIdentifier());
                     } else if (tlv instanceof OspfNonPseudonode) {
-                        OspfNonPseudonode ospfNonPseudonode = (OspfNonPseudonode) tlv;
-                        this.stringBuilder.append(":RID=").append(ospfNonPseudonode.getrouterID());
+                        this.stringBuilder.append(":RID=").append(((OspfNonPseudonode) tlv).getrouterID());
                     } else if (tlv instanceof OspfPseudonode) {
-                        OspfPseudonode ospfPseudonode = (OspfPseudonode) tlv;
-                        this.stringBuilder.append(":RID=").append(ospfPseudonode.getrouterID());
+                        this.stringBuilder.append(":RID=").append(((OspfPseudonode) tlv).getrouterID());
                     }
                 }
             }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java
index 8b34e31..9ecfb77 100755
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java
@@ -12,24 +12,29 @@
  */
 package org.onosproject.bgp.controller;
 
+import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
 
 /**
- * Allows for providers interested in Link events to be notified.
+ * Allows for providers interested in link events to be notified.
  */
 public interface BgpLinkListener {
 
     /**
-     * Notify that got a packet of link from network and need do processing.
+     * Notify that got a packet of link from network and adds link.
      *
-     * @param linkNlri bgp link
+     * @param linkNlri BGP link NLRI
+     * @param details path attributes and NLRI information
+     * @throws BgpParseException BGP parse exception
      */
-    void addLink(BgpLinkLsNlriVer4 linkNlri);
+    void addLink(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details) throws BgpParseException;
 
     /**
-     * Notify that got a packet of link from network and need do processing.
+     * Notify that got a packet of link from network and remove link.
      *
-     * @param linkNlri bgp link
+     * @param linkNlri BGP link NLRI
+     * @throws BgpParseException BGP parse exception
      */
-    void deleteLink(BgpLinkLsNlriVer4 linkNlri);
+    void deleteLink(BgpLinkLsNlriVer4 linkNlri) throws BgpParseException;
 }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java
index 636c1c8..d811b27 100755
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java
@@ -13,6 +13,7 @@
 
 package org.onosproject.bgp.controller;
 
+import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
 import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
 import org.onosproject.bgpio.types.RouteDistinguisher;
@@ -27,16 +28,18 @@
      *
      * @param sessionInfo session info
      * @param nlri network layer reach info
-     * @param details nlri details
+     * @param details path attributes and NLRI information
+     * @throws BgpParseException while adding NLRI to local rib
      */
-    void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details);
+    void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) throws BgpParseException;
 
     /**
      * Removes NLRI identifier if it exists.
      *
      * @param nlri info
+     * @throws BgpParseException while deleting NLRI from local rib
      */
-    void delete(BgpLSNlri nlri);
+    void delete(BgpLSNlri nlri) throws BgpParseException;
 
     /**
      * Update NLRI identifier mapped with route distinguisher if it exists in tree otherwise add NLRI infomation mapped
@@ -46,15 +49,17 @@
      * @param nlri info
      * @param details has pathattribute, protocol id and identifier
      * @param routeDistinguisher unique for each VPN
+     * @throws BgpParseException while adding NLRI updation
      */
     void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details,
-                    RouteDistinguisher routeDistinguisher);
+                    RouteDistinguisher routeDistinguisher) throws BgpParseException;
 
     /**
      * Removes VPN NLRI identifier mapped to route distinguisher if it exists.
      *
      * @param nlri info
      * @param routeDistinguisher unique for each VPN
+     * @throws BgpParseException while deleting NLRI from local rib
      */
-    void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher);
+    void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) throws BgpParseException;
 }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java
index 726d931..121f339 100755
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java
@@ -13,6 +13,7 @@
 package org.onosproject.bgp.controller;
 
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
 
 /**
  * Allows for providers interested in node events to be notified.
@@ -22,14 +23,15 @@
     /**
      * Notifies that the node was added.
      *
-     * @param nodeNlri node rechability info
+     * @param nodeNlri node reachability info
+     * @param details attributes and nlri details
      */
-    void addNode(BgpNodeLSNlriVer4 nodeNlri);
+    void addNode(BgpNodeLSNlriVer4 nodeNlri, PathAttrNlriDetails details);
 
     /**
      * Notifies that the node was removed.
      *
-     * @param nodeNlri node rechability info
+     * @param nodeNlri node reachability info
      */
     void deleteNode(BgpNodeLSNlriVer4 nodeNlri);
 }
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java
index 5abfbb3..84b3ee0 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java
@@ -260,6 +260,14 @@
                 log.debug("NodeDescriptor compare subtlv's");
                 for (BgpValueType tlv : ((NodeDescriptors) o).subTlvs) {
                     if (tlv.getType() == tlv1.getType()) {
+                        if (tlv.getType() == IGP_ROUTERID_TYPE) {
+                            if ((tlv1 instanceof IsIsNonPseudonode && tlv instanceof IsIsPseudonode)
+                                || (tlv1 instanceof IsIsPseudonode && tlv instanceof IsIsNonPseudonode)
+                                || (tlv1 instanceof OspfNonPseudonode && tlv instanceof OspfPseudonode)
+                                || (tlv1 instanceof OspfPseudonode && tlv instanceof OspfNonPseudonode)) {
+                                continue;
+                            }
+                        }
                         int result = subTlvs.get(subTlvs.indexOf(tlv1)).compareTo(
                                 ((NodeDescriptors) o).subTlvs.get(((NodeDescriptors) o).subTlvs.indexOf(tlv)));
                         if (result != 0) {
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
old mode 100755
new mode 100644
index 4e1b7fb..f270cf3
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
@@ -23,6 +23,7 @@
 import org.onosproject.bgp.controller.BgpCfg;
 import org.onosproject.bgp.controller.BgpController;
 import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpLinkListener;
 import org.onosproject.bgp.controller.BgpLocalRib;
 import org.onosproject.bgp.controller.BgpNodeListener;
 import org.onosproject.bgp.controller.BgpPeer;
@@ -58,6 +59,7 @@
     private BgpLocalRib bgplocalRibVpn = new BgpLocalRibImpl(this);
 
     protected Set<BgpNodeListener> bgpNodeListener = new CopyOnWriteArraySet<>();
+    protected Set<BgpLinkListener> bgpLinkListener = new CopyOnWriteArraySet<>();
 
     final Controller ctrl = new Controller(this);
 
@@ -278,4 +280,19 @@
     public BgpLocalRib bgpLocalRibVpn() {
         return bgplocalRibVpn;
     }
+
+    @Override
+    public void addLinkListener(BgpLinkListener listener) {
+        this.bgpLinkListener.add(listener);
+    }
+
+    @Override
+    public void removeLinkListener(BgpLinkListener listener) {
+        this.bgpLinkListener.remove(listener);
+    }
+
+    @Override
+    public Set<BgpLinkListener> linkListener() {
+        return bgpLinkListener;
+    }
 }
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
index c4773ff..54daefc 100755
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
@@ -14,11 +14,14 @@
 package org.onosproject.bgp.controller.impl;
 
 import com.google.common.base.MoreObjects;
+
 import org.onosproject.bgp.controller.BgpController;
 import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpLinkListener;
 import org.onosproject.bgp.controller.BgpLocalRib;
 import org.onosproject.bgp.controller.BgpNodeListener;
 import org.onosproject.bgp.controller.BgpSessionInfo;
+import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
@@ -116,7 +119,7 @@
     }
 
     @Override
-    public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) {
+    public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) throws BgpParseException {
         int decisionResult;
 
         log.debug("Add to local RIB {}", details.toString());
@@ -133,13 +136,16 @@
                 // Compare local RIB entry with the current attribute
                 decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
                 if (decisionResult < 0) {
+                    for (BgpNodeListener l : bgpController.listener()) {
+                        l.addNode((BgpNodeLSNlriVer4) nlri, details);
+                    }
                     nodeTree.replace(nodeLsIdentifier, detailsLocRib);
                     log.debug("Local RIB update node: {}", detailsLocRib.toString());
                 }
             } else {
                 nodeTree.put(nodeLsIdentifier, detailsLocRib);
                 for (BgpNodeListener l : bgpController.listener()) {
-                    l.addNode((BgpNodeLSNlriVer4) nlri);
+                    l.addNode((BgpNodeLSNlriVer4) nlri, details);
                 }
                 log.debug("Local RIB ad node: {}", detailsLocRib.toString());
             }
@@ -151,10 +157,16 @@
                 decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
                 if (decisionResult < 0) {
                     linkTree.replace(linkLsIdentifier, detailsLocRib);
+                    for (BgpLinkListener l : bgpController.linkListener()) {
+                        l.addLink((BgpLinkLsNlriVer4) nlri, details);
+                    }
                     log.debug("Local RIB update link: {}", detailsLocRib.toString());
                 }
             } else {
                 linkTree.put(linkLsIdentifier, detailsLocRib);
+                for (BgpLinkListener l : bgpController.linkListener()) {
+                    l.addLink((BgpLinkLsNlriVer4) nlri, details);
+                }
                 log.debug("Local RIB add link: {}", detailsLocRib.toString());
             }
         } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
@@ -175,7 +187,7 @@
     }
 
     @Override
-    public void delete(BgpLSNlri nlri) {
+    public void delete(BgpLSNlri nlri) throws BgpParseException {
         log.debug("Delete from local RIB.");
 
         // Update local RIB
@@ -186,8 +198,9 @@
      * Update local RIB based on selection algorithm.
      *
      * @param nlri NLRI to update
+     * @throws BgpParseException while updating to local RIB
      */
-    public void decisionProcess(BgpLSNlri nlri) {
+    public void decisionProcess(BgpLSNlri nlri) throws BgpParseException {
         checkNotNull(nlri);
         if (nlri instanceof BgpNodeLSNlriVer4) {
             selectionProcessNode(nlri, false);
@@ -203,8 +216,9 @@
      *
      * @param nlri NLRI to update
      * @param routeDistinguisher VPN id to update
+     * @throws BgpParseException BGP parse exception
      */
-    public void decisionProcess(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
+    public void decisionProcess(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) throws BgpParseException {
         checkNotNull(nlri);
         if (nlri instanceof BgpNodeLSNlriVer4) {
             if (vpnNodeTree.containsKey(routeDistinguisher)) {
@@ -235,8 +249,9 @@
      *
      * @param nlri NLRI to update
      * @param isVpnRib true if VPN  local RIB, otherwise false
+     * @throws BgpParseException throws BGP parse exception
      */
-    public void selectionProcessNode(BgpLSNlri nlri, boolean isVpnRib) {
+    public void selectionProcessNode(BgpLSNlri nlri, boolean isVpnRib) throws BgpParseException {
         BgpPeerImpl peer;
         BgpSessionInfo sessionInfo;
         int decisionResult;
@@ -298,8 +313,9 @@
      *
      * @param nlri NLRI to update
      * @param isVpnRib true if VPN local RIB, otherwise false
+     * @throws BgpParseException BGP parse exception
      */
-    public void selectionProcessLink(BgpLSNlri nlri, boolean isVpnRib) {
+    public void selectionProcessLink(BgpLSNlri nlri, boolean isVpnRib) throws BgpParseException {
         BgpPeerImpl peer;
         BgpSessionInfo sessionInfo;
         int decisionResult;
@@ -309,6 +325,9 @@
 
         if (linkTree.containsKey(linkLsIdentifier)) {
             log.debug("Local RIB remove link: {}", linkLsIdentifier.toString());
+            for (BgpLinkListener l : bgpController.linkListener()) {
+                l.deleteLink((BgpLinkLsNlriVer4) nlri);
+            }
             linkTree.remove(linkLsIdentifier);
         }
 
@@ -361,8 +380,9 @@
      *
      * @param nlri NLRI to update
      * @param isVpnRib true if VPN local RIB, otherwise false
+     * @throws BgpParseException BGP parse exception
      */
-    public void selectionProcessPrefix(BgpLSNlri nlri, boolean isVpnRib) {
+    public void selectionProcessPrefix(BgpLSNlri nlri, boolean isVpnRib) throws BgpParseException {
         BgpPeerImpl peer;
         BgpSessionInfo sessionInfo;
         int decisionResult;
@@ -419,7 +439,7 @@
 
     @Override
     public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details,
-                    RouteDistinguisher routeDistinguisher) {
+                    RouteDistinguisher routeDistinguisher) throws BgpParseException {
         add(sessionInfo, nlri, details);
         if (nlri instanceof BgpNodeLSNlriVer4) {
             if (!vpnNodeTree.containsKey(routeDistinguisher)) {
@@ -437,7 +457,7 @@
     }
 
     @Override
-    public void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
+    public void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) throws BgpParseException {
         // Update local RIB
         decisionProcess(nlri, routeDistinguisher);
     }
@@ -446,8 +466,9 @@
      * Update local RIB node based on avaliable peer adjacency RIB.
      *
      * @param o adjacency-in/VPN adjacency-in
+     * @throws BgpParseException BGP parse exception
      */
-    public void localRibUpdateNode(Object o) {
+    public void localRibUpdateNode(Object o) throws BgpParseException {
 
         if (o instanceof AdjRibIn) {
             AdjRibIn adjRib = (AdjRibIn) o;
@@ -487,8 +508,9 @@
      * Update localRIB link based on avaliable peer adjacency RIB.
      *
      * @param o adjacency-in/VPN adjacency-in
+     * @throws BgpParseException BGP parse exceptions
      */
-    public void localRibUpdateLink(Object o) {
+    public void localRibUpdateLink(Object o) throws BgpParseException {
 
         if (o instanceof AdjRibIn) {
             AdjRibIn adjRib = (AdjRibIn) o;
@@ -528,8 +550,9 @@
      * Update localRIB prefix based on avaliable peer adjacency RIB.
      *
      * @param o instance of adjacency-in/VPN adjacency-in
+     * @throws BgpParseException BGP parse exception
      */
-    public void localRibUpdatePrefix(Object o) {
+    public void localRibUpdatePrefix(Object o) throws BgpParseException {
 
         if (o instanceof AdjRibIn) {
             AdjRibIn adjRib = (AdjRibIn) o;
@@ -572,8 +595,9 @@
      * Update localRIB.
      *
      * @param adjRibIn adjacency RIB-in
+     * @throws BgpParseException BGP parse exception
      */
-    public void localRibUpdate(AdjRibIn adjRibIn) {
+    public void localRibUpdate(AdjRibIn adjRibIn) throws BgpParseException {
         log.debug("Update local RIB.");
 
         localRibUpdateNode(adjRibIn);
@@ -585,8 +609,9 @@
      * Update localRIB.
      *
      * @param vpnAdjRibIn VPN adjacency RIB-in
+     * @throws BgpParseException BGP parse exception
      */
-    public void localRibUpdate(VpnAdjRibIn vpnAdjRibIn) {
+    public void localRibUpdate(VpnAdjRibIn vpnAdjRibIn) throws BgpParseException {
         log.debug("Update VPN local RIB.");
 
         localRibUpdateNode(vpnAdjRibIn);
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
index aa02f2c..7ee6aa1 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
@@ -425,8 +425,9 @@
      *
      * @param peerImpl BGP peer instance
      * @param nlri NLRI information
+     * @throws BgpParseException BGP parse exception
      */
-    public void callRemove(BgpPeerImpl peerImpl, List<BgpLSNlri> nlri) {
+    public void callRemove(BgpPeerImpl peerImpl, List<BgpLSNlri> nlri) throws BgpParseException {
         ListIterator<BgpLSNlri> listIterator = nlri.listIterator();
         while (listIterator.hasNext()) {
             BgpLSNlri nlriInfo = listIterator.next();
@@ -479,8 +480,9 @@
     /**
      * Update localRIB on peer disconnect.
      *
+     * @throws BgpParseException while updating local RIB
      */
-    public void updateLocalRibOnPeerDisconnect() {
+    public void updateLocalRibOnPeerDisconnect() throws BgpParseException {
         BgpLocalRibImpl localRib = (BgpLocalRibImpl) bgplocalRib;
         BgpLocalRibImpl localRibVpn = (BgpLocalRibImpl) bgplocalRibVpn;
 
@@ -490,7 +492,6 @@
 
     /**
      * Update peer flow specification RIB on peer disconnect.
-     *
      */
     public void updateFlowSpecOnPeerDisconnect() {
 
diff --git a/providers/bgp/topology/src/main/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProvider.java b/providers/bgp/topology/src/main/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProvider.java
index 064745d..7807d5f 100755
--- a/providers/bgp/topology/src/main/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProvider.java
+++ b/providers/bgp/topology/src/main/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProvider.java
@@ -15,6 +15,11 @@
 
 import static org.onosproject.bgp.controller.BgpDpid.uri;
 import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.Device.Type.ROUTER;
+import static org.onosproject.net.Device.Type.VIRTUAL;
+
+import java.util.List;
+import java.util.Set;
 
 import org.onlab.packet.ChassisId;
 import org.apache.felix.scr.annotations.Activate;
@@ -24,10 +29,31 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.onosproject.bgp.controller.BgpController;
 import org.onosproject.bgp.controller.BgpDpid;
+import org.onosproject.bgp.controller.BgpLinkListener;
 import org.onosproject.bgp.controller.BgpNodeListener;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
+import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
+import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
+import org.onosproject.bgpio.types.AutonomousSystemTlv;
+import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
+import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.IPv4AddressTlv;
+import org.onosproject.bgpio.types.IsIsNonPseudonode;
+import org.onosproject.bgpio.types.IsIsPseudonode;
+import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
+import org.onosproject.bgpio.types.OspfNonPseudonode;
+import org.onosproject.bgpio.types.OspfPseudonode;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
 import org.onosproject.net.MastershipRole;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DefaultDeviceDescription;
@@ -35,6 +61,13 @@
 import org.onosproject.net.device.DeviceProvider;
 import org.onosproject.net.device.DeviceProviderRegistry;
 import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.link.DefaultLinkDescription;
+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.link.LinkService;
 import org.onosproject.net.provider.AbstractProvider;
 import org.onosproject.net.provider.ProviderId;
 import org.slf4j.Logger;
@@ -44,7 +77,7 @@
  * Provider which uses an BGP controller to detect network infrastructure topology.
  */
 @Component(immediate = true)
-public class BgpTopologyProvider extends AbstractProvider implements DeviceProvider {
+public class BgpTopologyProvider extends AbstractProvider implements DeviceProvider, LinkProvider {
 
     public BgpTopologyProvider() {
         super(new ProviderId("bgp", "org.onosproject.provider.bgp"));
@@ -56,42 +89,100 @@
     protected DeviceProviderRegistry deviceProviderRegistry;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkProviderRegistry linkProviderRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected BgpController controller;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkService linkService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
     private DeviceProviderService deviceProviderService;
+    private LinkProviderService linkProviderService;
 
     private InternalBgpProvider listener = new InternalBgpProvider();
     private static final String UNKNOWN = "unknown";
+    public static final long IDENTIFIER_SET = 0x100000000L;
+    public static final String AS_NUMBER = "asNumber";
+    public static final String DOMAIN_IDENTIFIER = "domainIdentifier";
+    public static final String ROUTING_UNIVERSE = "routingUniverse";
+    public static final long PSEUDO_PORT = 0xffffffff;
 
     @Activate
     public void activate() {
+        log.debug("BgpTopologyProvider activate");
         deviceProviderService = deviceProviderRegistry.register(this);
+        linkProviderService = linkProviderRegistry.register(this);
         controller.addListener(listener);
+        controller.addLinkListener(listener);
     }
 
     @Deactivate
     public void deactivate() {
+        log.debug("BgpTopologyProvider deactivate");
+        deviceProviderRegistry.unregister(this);
+        deviceProviderService = null;
+        linkProviderRegistry.unregister(this);
+        linkProviderService = null;
         controller.removeListener(listener);
+        controller.removeLinkListener(listener);
     }
 
     /*
      * Implements device and link update.
      */
-    private class InternalBgpProvider implements BgpNodeListener {
+    private class InternalBgpProvider implements BgpNodeListener, BgpLinkListener {
 
         @Override
-        public void addNode(BgpNodeLSNlriVer4 nodeNlri) {
+        public void addNode(BgpNodeLSNlriVer4 nodeNlri, PathAttrNlriDetails details) {
             log.debug("Add node {}", nodeNlri.toString());
 
             if (deviceProviderService == null) {
                 return;
             }
+            Device.Type deviceType = ROUTER;
             BgpDpid nodeUri = new BgpDpid(nodeNlri);
             DeviceId deviceId = deviceId(uri(nodeUri.toString()));
             ChassisId cId = new ChassisId();
 
-            DeviceDescription description = new DefaultDeviceDescription(uri(nodeUri.toString()), Device.Type.ROUTER,
-                                                                         UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, cId);
+            DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
+
+            newBuilder.set(AnnotationKeys.TYPE, "L3");
+            newBuilder.set(ROUTING_UNIVERSE, Long.toString(nodeNlri.getIdentifier()));
+
+            List<BgpValueType> tlvs = nodeNlri.getLocalNodeDescriptors().getNodedescriptors().getSubTlvs();
+            for (BgpValueType tlv : tlvs) {
+                if (tlv instanceof AutonomousSystemTlv) {
+                    newBuilder.set(AS_NUMBER, Integer.toString(((AutonomousSystemTlv) tlv).getAsNum()));
+                } else if (tlv instanceof BgpLSIdentifierTlv) {
+                    newBuilder.set(DOMAIN_IDENTIFIER,
+                            Integer.toString(((BgpLSIdentifierTlv) tlv).getBgpLsIdentifier()));
+                }
+                if (tlv.getType() == NodeDescriptors.IGP_ROUTERID_TYPE) {
+                    if (tlv instanceof IsIsPseudonode) {
+                        deviceType = VIRTUAL;
+                        newBuilder.set(AnnotationKeys.ROUTER_ID, new String(((IsIsPseudonode) tlv).getIsoNodeId()));
+                    } else if (tlv instanceof OspfPseudonode) {
+                        deviceType = VIRTUAL;
+                        newBuilder
+                                .set(AnnotationKeys.ROUTER_ID, Integer.toString(((OspfPseudonode) tlv).getrouterID()));
+                    } else if (tlv instanceof IsIsNonPseudonode) {
+                        newBuilder.set(AnnotationKeys.ROUTER_ID, new String(((IsIsNonPseudonode) tlv).getIsoNodeId()));
+                    } else if (tlv instanceof OspfNonPseudonode) {
+                        newBuilder.set(AnnotationKeys.ROUTER_ID,
+                                Integer.toString(((OspfNonPseudonode) tlv).getrouterID()));
+                    }
+                }
+            }
+
+            DeviceDescription description = new DefaultDeviceDescription(uri(nodeUri.toString()), deviceType, UNKNOWN,
+                    UNKNOWN, UNKNOWN, UNKNOWN, cId, newBuilder.build());
             deviceProviderService.deviceConnected(deviceId, description);
 
         }
@@ -104,8 +195,131 @@
                 return;
             }
 
-            BgpDpid nodeUri = new BgpDpid(nodeNlri);
-            deviceProviderService.deviceDisconnected(deviceId(uri(nodeUri.toString())));
+            BgpDpid deviceUri = new BgpDpid(nodeNlri);
+            DeviceId deviceId = deviceId(uri(deviceUri.toString()));
+            deviceProviderService.deviceDisconnected(deviceId);
+        }
+
+        @Override
+        public void addLink(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details) throws BgpParseException {
+            log.debug("Addlink {}", linkNlri.toString());
+
+            if (linkProviderService == null) {
+                return;
+            }
+            LinkDescription linkDes = buildLinkDes(linkNlri, details, true);
+            linkProviderService.linkDetected(linkDes);
+        }
+
+        //Build link description.
+        private LinkDescription buildLinkDes(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details, boolean isAddLink)
+                throws BgpParseException {
+            long srcAddress = 0;
+            long dstAddress = 0;
+            boolean localPseduo = false;
+            boolean remotePseduo = false;
+
+            List<BgpValueType> localTlvs = linkNlri.getLinkIdentifier().localNodeDescriptors().getSubTlvs();
+            for (BgpValueType localTlv : localTlvs) {
+                if (localTlv instanceof IsIsPseudonode || localTlv instanceof OspfPseudonode) {
+                    localPseduo = true;
+                }
+            }
+            List<BgpValueType> remoteTlvs = linkNlri.getLinkIdentifier().remoteNodeDescriptors().getSubTlvs();
+            for (BgpValueType remoteTlv : remoteTlvs) {
+                if (remoteTlv instanceof IsIsPseudonode || remoteTlv instanceof OspfPseudonode) {
+                    remotePseduo = true;
+                }
+            }
+
+            List<BgpValueType> tlvs = linkNlri.getLinkIdentifier().linkDescriptors();
+            for (BgpValueType tlv : tlvs) {
+                if (tlv instanceof LinkLocalRemoteIdentifiersTlv) {
+                    srcAddress = ((LinkLocalRemoteIdentifiersTlv) tlv).getLinkLocalIdentifier();
+                    //Set 32nd bit.
+                    srcAddress = srcAddress | IDENTIFIER_SET;
+                    dstAddress = ((LinkLocalRemoteIdentifiersTlv) tlv).getLinkRemoteIdentifier();
+                    dstAddress = dstAddress | IDENTIFIER_SET;
+                } else if (tlv instanceof IPv4AddressTlv) {
+                    if (tlv.getType() == BgpLinkLSIdentifier.IPV4_INTERFACE_ADDRESS_TYPE) {
+                        srcAddress = ((IPv4AddressTlv) tlv).address().toInt();
+                    } else {
+                        dstAddress = ((IPv4AddressTlv) tlv).address().toInt();
+                    }
+                }
+            }
+
+            DeviceId srcId = deviceId(uri(new BgpDpid(linkNlri, BgpDpid.NODE_DESCRIPTOR_LOCAL).toString()));
+            DeviceId dstId = deviceId(uri(new BgpDpid(linkNlri, BgpDpid.NODE_DESCRIPTOR_REMOTE).toString()));
+
+            if (localPseduo && srcAddress == 0) {
+                srcAddress = PSEUDO_PORT;
+            } else if (remotePseduo && dstAddress == 0) {
+                dstAddress = PSEUDO_PORT;
+            }
+
+            ConnectPoint src = new ConnectPoint(srcId, PortNumber.portNumber(srcAddress));
+            ConnectPoint dst = new ConnectPoint(dstId, PortNumber.portNumber(dstAddress));
+            BgpNodeLSNlriVer4 srcNodeNlri = new BgpNodeLSNlriVer4(linkNlri.getIdentifier(), linkNlri.getProtocolId()
+                    .getType(), new BgpNodeLSIdentifier(linkNlri.getLinkIdentifier().localNodeDescriptors()), false,
+                    linkNlri.getRouteDistinguisher());
+
+            BgpNodeLSNlriVer4 dstNodeNlri = new BgpNodeLSNlriVer4(linkNlri.getIdentifier(), linkNlri.getProtocolId()
+                    .getType(), new BgpNodeLSIdentifier(linkNlri.getLinkIdentifier().remoteNodeDescriptors()), false,
+                    linkNlri.getRouteDistinguisher());
+
+            addOrDeletePseudoNode(isAddLink, localPseduo, remotePseduo, srcNodeNlri,
+                     dstNodeNlri, srcId, dstId, details);
+            return new DefaultLinkDescription(src, dst, Link.Type.DIRECT, false);
+        }
+
+        private void addOrDeletePseudoNode(boolean isAddLink, boolean localPseduo, boolean remotePseduo,
+                BgpNodeLSNlriVer4 srcNodeNlri, BgpNodeLSNlriVer4 dstNodeNlri, DeviceId srcId, DeviceId dstId,
+                PathAttrNlriDetails details) {
+            if (isAddLink) {
+                if (localPseduo) {
+                    if (deviceService.getDevice(srcId) == null) {
+                        for (BgpNodeListener l : controller.listener()) {
+                            l.addNode(srcNodeNlri, details);
+                        }
+                    }
+                } else if (remotePseduo) {
+                    if (deviceService.getDevice(dstId) == null) {
+                        for (BgpNodeListener l : controller.listener()) {
+                            l.addNode(dstNodeNlri, details);
+                        }
+                    }
+                }
+            } else {
+                if (localPseduo) {
+                    Set<Link> links = linkService.getDeviceLinks(srcId);
+                    if (links == null || links.isEmpty()) {
+                        for (BgpNodeListener l : controller.listener()) {
+                            l.deleteNode(srcNodeNlri);
+                        }
+                    }
+                } else if (remotePseduo) {
+                    log.info("Remote pseudo delete link ");
+                    Set<Link> links = linkService.getDeviceLinks(dstId);
+                    if (links == null || links.isEmpty()) {
+                        for (BgpNodeListener l : controller.listener()) {
+                            l.deleteNode(dstNodeNlri);
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void deleteLink(BgpLinkLsNlriVer4 linkNlri) throws BgpParseException {
+            log.debug("Delete link {}", linkNlri.toString());
+
+            if (linkProviderService == null) {
+                return;
+            }
+
+            LinkDescription linkDes = buildLinkDes(linkNlri, null, false);
+            linkProviderService.linkVanished(linkDes);
         }
     }
 
diff --git a/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java b/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java
new file mode 100644
index 0000000..c2f7d25
--- /dev/null
+++ b/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2016 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.bgp.topology.impl;
+
+import org.onosproject.bgp.controller.BgpCfg;
+import org.onosproject.bgp.controller.BgpController;
+import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpLinkListener;
+import org.onosproject.bgp.controller.BgpLocalRib;
+import org.onosproject.bgp.controller.BgpNodeListener;
+import org.onosproject.bgp.controller.BgpPeer;
+import org.onosproject.bgp.controller.BgpPeerManager;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpMessage;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Adapter implementation for BGP controller.
+ */
+public class BgpControllerAdapter implements BgpController {
+    @Override
+    public Iterable<BgpPeer> getPeers() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BgpPeer getPeer(BgpId bgpId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void writeMsg(BgpId bgpId, BgpMessage msg) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void processBgpPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void closeConnectedPeers() {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public BgpCfg getConfig() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int connectedPeerCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public BgpLocalRib bgpLocalRibVpn() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BgpLocalRib bgpLocalRib() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BgpPeerManager peerManager() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Map<BgpId, BgpPeer> connectedPeers() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Set<BgpNodeListener> listener() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Set<BgpLinkListener> linkListener() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void addListener(BgpNodeListener listener) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void removeListener(BgpNodeListener listener) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addLinkListener(BgpLinkListener listener) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void removeLinkListener(BgpLinkListener listener) {
+        // TODO Auto-generated method stub
+    }
+}
diff --git a/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java b/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java
index 7a810ee..21e2a98 100755
--- a/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java
+++ b/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java
@@ -12,11 +12,13 @@
  */
 package org.onosproject.provider.bgp.topology.impl;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.onosproject.net.Link.State.ACTIVE;
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -27,59 +29,80 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.onosproject.bgp.controller.BgpCfg;
-import org.onosproject.bgp.controller.BgpController;
-import org.onosproject.bgp.controller.BgpId;
-import org.onosproject.bgp.controller.BgpPeer;
-import org.onosproject.bgp.controller.BgpLocalRib;
+import org.onlab.packet.ChassisId;
+import org.onosproject.bgp.controller.BgpLinkListener;
 import org.onosproject.bgp.controller.BgpNodeListener;
-import org.onosproject.bgp.controller.BgpPeerManager;
 import org.onosproject.bgpio.exceptions.BgpParseException;
-import org.onosproject.bgpio.protocol.BgpMessage;
+import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
+import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType;
 import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
+import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
 import org.onosproject.bgpio.types.AutonomousSystemTlv;
 import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.IsIsNonPseudonode;
+import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
 import org.onosproject.bgpio.types.RouteDistinguisher;
 import org.onosproject.bgpio.util.Constants;
+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;
 
+/**
+ * Test for BGP topology provider.
+ */
 public class BgpTopologyProviderTest {
+    private static final DeviceId DID2 = DeviceId.deviceId("bgp:rd=0::routinguniverse=0:asn=10");
+    private static final String UNKNOWN = new String("unknown");
+    public static ProviderId providerId = new ProviderId("bgp", "foo");
 
-    private static final DeviceId DID1 = DeviceId
-            .deviceId("bgp:rd=0:proto=direct:id=0:as=100");
-    private static final DeviceId DID2 = DeviceId
-            .deviceId("bgp:rd=0:proto=direct:id=0:as=10");
-    private static final DeviceId DID3 = DeviceId
-            .deviceId("bgp:rd=0:proto=direct:id=0:as=100");
     private final BgpTopologyProvider provider = new BgpTopologyProvider();
     private final TestDeviceRegistry nodeRegistry = new TestDeviceRegistry();
-    private final TestController controller = new TestController();
+    private final TestLinkRegistry linkRegistry = new TestLinkRegistry();
+    private final MockBgpController controller = new MockBgpController();
+    private MockDeviceService deviceService = new MockDeviceService();
+    private Map<DeviceId, Device> deviceMap = new HashMap<>();
+
 
     @Before
     public void startUp() {
         provider.deviceProviderRegistry = nodeRegistry;
+        provider.linkProviderRegistry = linkRegistry;
         provider.controller = controller;
+        provider.deviceService = deviceService;
         provider.activate();
-        assertNotNull("provider should be registered", nodeRegistry.provider);
-        assertNotNull("listener should be registered", controller.nodeListener);
+        assertThat("device provider should be registered", not(nodeRegistry.provider));
+        assertThat("link provider should be registered", not(linkRegistry.linkProvider));
+        assertThat("node listener should be registered", not(controller.nodeListener));
+        assertThat("link listener should be registered", not(controller.linkListener));
     }
 
     @After
     public void tearDown() {
         provider.deactivate();
-        assertNull("listener should be removed", controller.nodeListener);
         provider.controller = null;
+        provider.deviceService = null;
         provider.deviceProviderRegistry = null;
+        assertThat(controller.nodeListener, is(new HashSet<BgpNodeListener>()));
+        assertThat(controller.linkListener, is(new HashSet<BgpLinkListener>()));
     }
 
     /* Class implement device test registry */
@@ -112,15 +135,19 @@
 
             @Override
             public void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription) {
-                if (deviceId.equals(DID1)) {
+                if (!deviceId.equals(DID2)) {
                     connected.add(deviceId);
+                    Device device = new DefaultDevice(BgpTopologyProviderTest.providerId, deviceId, Device.Type.ROUTER,
+                            UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, new ChassisId());
+                    deviceMap.put(deviceId, device);
                 }
             }
 
             @Override
             public void deviceDisconnected(DeviceId deviceId) {
-                if (deviceId.equals(DID1)) {
+                if (!deviceId.equals(DID2)) {
                     connected.remove(deviceId);
+                    deviceMap.remove(deviceId);
                 }
             }
 
@@ -150,9 +177,65 @@
         }
     }
 
-    /* class implement test controller */
-    private class TestController implements BgpController {
+    /* Class implement device test registry */
+    private class TestLinkRegistry implements LinkProviderRegistry {
+        LinkProvider linkProvider;
+        Set<Link> links = new HashSet<>();
+
+        @Override
+        public LinkProviderService register(LinkProvider provider) {
+            this.linkProvider = provider;
+            return new TestProviderService();
+        }
+
+        @Override
+        public void unregister(LinkProvider provider) {
+            // TODO Auto-generated method stub
+        }
+
+        @Override
+        public Set<ProviderId> getProviders() {
+            return null;
+        }
+
+        private class TestProviderService implements LinkProviderService {
+
+            @Override
+            public void linkDetected(LinkDescription linkDescription) {
+                links.add(DefaultLink.builder().src(linkDescription.src())
+                        .dst(linkDescription.dst()).state(ACTIVE).type(linkDescription.type())
+                        .providerId(BgpTopologyProviderTest.providerId).build());
+            }
+
+            @Override
+            public void linkVanished(LinkDescription linkDescription) {
+                links.remove(DefaultLink.builder().src(linkDescription.src())
+                        .dst(linkDescription.dst()).state(ACTIVE).type(linkDescription.type())
+                        .providerId(BgpTopologyProviderTest.providerId).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;
+            }
+        }
+    }
+
+    /* Test class for BGP controller */
+    private class MockBgpController extends BgpControllerAdapter {
         protected Set<BgpNodeListener> nodeListener = new CopyOnWriteArraySet<>();
+        protected Set<BgpLinkListener> linkListener = new CopyOnWriteArraySet<>();
 
         @Override
         public void addListener(BgpNodeListener nodeListener) {
@@ -161,88 +244,34 @@
 
         @Override
         public void removeListener(BgpNodeListener nodeListener) {
-            this.nodeListener = null;
+            this.nodeListener.remove(nodeListener);
         }
 
         @Override
-        public Iterable<BgpPeer> getPeers() {
-            // TODO Auto-generated method stub
-            return null;
+        public void addLinkListener(BgpLinkListener linkListener) {
+            this.linkListener.add(linkListener);
         }
 
         @Override
-        public BgpPeer getPeer(BgpId bgpId) {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public void writeMsg(BgpId bgpId, BgpMessage msg) {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public void processBgpPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public void closeConnectedPeers() {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public BgpCfg getConfig() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public int connectedPeerCount() {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-
-        @Override
-        public BgpLocalRib bgpLocalRibVpn() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public BgpLocalRib bgpLocalRib() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public BgpPeerManager peerManager() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public Map<BgpId, BgpPeer> connectedPeers() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public Set<BgpNodeListener> listener() {
-            // TODO Auto-generated method stub
-            return null;
+        public void removeLinkListener(BgpLinkListener linkListener) {
+            this.linkListener.remove(linkListener);
         }
     }
 
-    /* Validate node is added to the device validating URI, RIB should get updated properly */
+    /* Mock test for device service */
+    private class MockDeviceService extends DeviceServiceAdapter {
+        @Override
+        public Device getDevice(DeviceId deviceId) {
+            return deviceMap.get(deviceId);
+        }
+    }
+
+    /**
+     * Validate node is added to the device validating URI, RIB should get updated properly.
+     */
     @Test
     public void bgpTopologyProviderTestAddDevice1() {
-        int deviceAddCount = 0;
-        LinkedList<BgpValueType> subTlvs;
-        subTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
         BgpValueType tlv = new AutonomousSystemTlv(100);
         short deslength = AutonomousSystemTlv.LENGTH;
         short desType = AutonomousSystemTlv.TYPE;
@@ -253,18 +282,23 @@
         BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                            new RouteDistinguisher());
 
-        nodeNlri.setNodeLSIdentifier(localNodeDescriptors);
+        PathAttrNlriDetails details = new PathAttrNlriDetails();
+        details.setIdentifier(0);
+        details.setProtocolID(ProtocolType.DIRECT);
+        List<BgpValueType> pathAttributes = new LinkedList<>();
+        details.setPathAttribute(pathAttributes);
+
         for (BgpNodeListener l : controller.nodeListener) {
-            l.addNode(nodeNlri);
-            deviceAddCount = nodeRegistry.connected.size();
-            assertTrue(deviceAddCount == 1);
+            l.addNode(nodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(1));
             l.deleteNode(nodeNlri);
-            deviceAddCount = nodeRegistry.connected.size();
-            assertTrue(deviceAddCount == 0);
+            assertThat(nodeRegistry.connected.size(), is(0));
         }
     }
 
-    /* Validate node is not added to the device for invalid URI, RIB count should be zero */
+    /**
+     * Validate node is not added to the device for invalid URI, RIB count should be zero.
+     */
     @Test
     public void bgpTopologyProviderTestAddDevice2() {
         LinkedList<BgpValueType> subTlvs;
@@ -272,6 +306,12 @@
         short deslength = AutonomousSystemTlv.LENGTH;
         short desType = AutonomousSystemTlv.TYPE;
 
+        PathAttrNlriDetails details = new PathAttrNlriDetails();
+        details.setIdentifier(0);
+        details.setProtocolID(ProtocolType.DIRECT);
+        List<BgpValueType> pathAttributes = new LinkedList<>();
+        details.setPathAttribute(pathAttributes);
+
         subTlvs = new LinkedList<>();
         subTlvs.add(tlv);
         BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
@@ -279,14 +319,16 @@
         BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                            new RouteDistinguisher());
 
-        nodeNlri.setNodeLSIdentifier(localNodeDescriptors);
+
         for (BgpNodeListener l : controller.nodeListener) {
-            l.addNode(nodeNlri);
-            assertTrue("Failed to add device", (nodeRegistry.connected.size() == 0));
+            l.addNode(nodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(0));
         }
     }
 
-    /* Delete node when node does not exist, RIB count should be zero */
+    /**
+     * Delete node when node does not exist, RIB count should be zero.
+     */
     @Test
     public void bgpTopologyProviderTestAddDevice3() {
         LinkedList<BgpValueType> subTlvs;
@@ -301,10 +343,173 @@
         BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                            new RouteDistinguisher());
 
-        nodeNlri.setNodeLSIdentifier(localNodeDescriptors);
         for (BgpNodeListener l : controller.nodeListener) {
             l.deleteNode(nodeNlri);
-            assertTrue("Failed to add device", (nodeRegistry.connected.size() == 0));
+            assertThat(nodeRegistry.connected.size(), is(0));
+        }
+    }
+
+    /**
+     * Add a link and two devices.
+     *
+     * @throws BgpParseException while adding a link.
+     */
+    @Test
+    public void bgpTopologyProviderTestAddLink1() throws BgpParseException {
+        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> linkdes = new LinkedList<>();
+        BgpValueType tlv = new AutonomousSystemTlv(10);
+        short deslength = AutonomousSystemTlv.LENGTH;
+        short desType = AutonomousSystemTlv.TYPE;
+
+        localTlvs.add(tlv);
+        remoteTlvs.add(tlv);
+        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
+        localTlvs.add(tlv);
+        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
+        remoteTlvs.add(tlv);
+        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
+        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
+        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
+        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
+                                                           new RouteDistinguisher());
+
+        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
+        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
+                                                           new RouteDistinguisher());
+
+        PathAttrNlriDetails details = new PathAttrNlriDetails();
+        details.setIdentifier(0);
+        details.setProtocolID(ProtocolType.DIRECT);
+        List<BgpValueType> pathAttributes = new LinkedList<>();
+        details.setPathAttribute(pathAttributes);
+
+        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
+        linkdes.add(tlv);
+        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
+        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
+                new RouteDistinguisher(), false);
+        for (BgpNodeListener l : controller.nodeListener) {
+            l.addNode(nodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(1));
+            l.addNode(remNodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(2));
+        }
+        for (BgpLinkListener l : controller.linkListener) {
+            l.addLink(linkNlri, details);
+            assertThat(linkRegistry.links.size(), is(1));
+        }
+    }
+
+    /**
+     * Add a link and delete a link.
+     *
+     * @throws BgpParseException while adding or removing the link
+     */
+    @Test
+    public void bgpTopologyProviderTestAddLink2() throws BgpParseException {
+        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> linkdes = new LinkedList<>();
+        BgpValueType tlv = new AutonomousSystemTlv(10);
+        short deslength = AutonomousSystemTlv.LENGTH;
+        short desType = AutonomousSystemTlv.TYPE;
+
+        localTlvs.add(tlv);
+        remoteTlvs.add(tlv);
+        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
+        localTlvs.add(tlv);
+        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
+        remoteTlvs.add(tlv);
+        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
+        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
+        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
+        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
+                                                           new RouteDistinguisher());
+
+        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
+        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
+                                                           new RouteDistinguisher());
+
+        PathAttrNlriDetails details = new PathAttrNlriDetails();
+        details.setIdentifier(0);
+        details.setProtocolID(ProtocolType.DIRECT);
+        List<BgpValueType> pathAttributes = new LinkedList<>();
+        details.setPathAttribute(pathAttributes);
+
+        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
+        linkdes.add(tlv);
+        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
+        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
+                new RouteDistinguisher(), false);
+        for (BgpNodeListener l : controller.nodeListener) {
+            l.addNode(nodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(1));
+            l.addNode(remNodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(2));
+            l.deleteNode(nodeNlri);
+            assertThat(nodeRegistry.connected.size(), is(1));
+        }
+        for (BgpLinkListener l : controller.linkListener) {
+            l.addLink(linkNlri, details);
+            assertThat(linkRegistry.links.size(), is(1));
+            l.deleteLink(linkNlri);
+            assertThat(linkRegistry.links.size(), is(0));
+        }
+    }
+
+    /**
+     * Invalid link.
+     *
+     * @throws BgpParseException while adding or deleting a link
+     */
+    @Test
+    public void bgpTopologyProviderTestDeleteLink3() throws BgpParseException {
+        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
+        LinkedList<BgpValueType> linkdes = new LinkedList<>();
+        BgpValueType tlv = new AutonomousSystemTlv(10);
+        short deslength = AutonomousSystemTlv.LENGTH;
+        short desType = AutonomousSystemTlv.TYPE;
+
+        localTlvs.add(tlv);
+        remoteTlvs.add(tlv);
+        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
+        localTlvs.add(tlv);
+        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
+        remoteTlvs.add(tlv);
+        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
+        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
+        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
+        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
+                                                           new RouteDistinguisher());
+
+        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
+        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
+                                                           new RouteDistinguisher());
+
+        PathAttrNlriDetails details = new PathAttrNlriDetails();
+        details.setIdentifier(0);
+        details.setProtocolID(ProtocolType.DIRECT);
+        List<BgpValueType> pathAttributes = new LinkedList<>();
+        details.setPathAttribute(pathAttributes);
+
+        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
+        linkdes.add(tlv);
+        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
+        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
+                new RouteDistinguisher(), false);
+        for (BgpNodeListener l : controller.nodeListener) {
+            l.addNode(nodeNlri, details);
+            l.addNode(remNodeNlri, details);
+            assertThat(nodeRegistry.connected.size(), is(2));
+            l.deleteNode(nodeNlri);
+            assertThat(nodeRegistry.connected.size(), is(1));
+        }
+        for (BgpLinkListener l : controller.linkListener) {
+            l.deleteLink(linkNlri);
+            assertThat(linkRegistry.links.size(), is(0));
         }
     }
 }