[ONOS-2606] Bgp local RIB implementation.

Change-Id: I39eadec95fa1e1328c73efabb2a50bb438075809
diff --git a/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java b/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
index cc87eb3..0930e8e 100755
--- a/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
+++ b/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
@@ -95,6 +95,20 @@
     int connectedPeerCount();
 
     /**
+     * Return BGP local RIB instance with VPN.
+     *
+     * @return BGPLocalRibImpl local RIB with VPN
+     */
+    BgpLocalRib bgpLocalRibVpn();
+
+    /**
+     * Return BGP local RIB instance.
+     *
+     * @return BGPLocalRibImpl local RIB
+     */
+    BgpLocalRib bgpLocalRib();
+
+    /**
      * Return BGP peer manager.
      *
      * @return BGPPeerManager peer manager instance
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
index 8754563..45be255 100755
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
@@ -440,7 +440,9 @@
                 // which we obviously don't want.
                 log.debug("{}:removal called", getPeerInfoString());
                 if (bgpPeer != null) {
+                    BgpPeerImpl peer = (BgpPeerImpl) bgpPeer;
                     peerManager.removeConnectedPeer(thisbgpId);
+                    peer.updateLocalRIBOnPeerDisconnect();
                 }
 
                 // Retry connection if connection is lost to bgp speaker/peer
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
index 716cc0c..ac94822 100755
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
@@ -21,8 +21,14 @@
 import java.util.TreeMap;
 
 import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
 import org.onosproject.bgp.controller.BgpCfg;
+import org.onosproject.bgp.controller.BgpConnectPeer;
+import org.onosproject.bgp.controller.BgpController;
+import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpPeer;
 import org.onosproject.bgp.controller.BgpPeerCfg;
+import org.onosproject.bgp.controller.impl.BgpControllerImpl.BgpPeerManagerImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,12 +54,16 @@
 
     private Ip4Address routerId = null;
     private TreeMap<String, BgpPeerCfg> bgpPeerTree = new TreeMap<>();
+    private BgpConnectPeer connectPeer;
+    private BgpPeerManagerImpl peerManager;
+    private BgpController bgpController;
 
-    /**
+    /*
      * Constructor to initialize the values.
      */
-    public BgpConfig() {
-
+    public BgpConfig(BgpController bgpController) {
+        this.bgpController = bgpController;
+        this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager();
         this.holdTime = DEFAULT_HOLD_TIMER;
         this.maxConnRetryTime = DEFAULT_CONN_RETRY_TIME;
         this.maxConnRetryCount = DEFAULT_CONN_RETRY_COUNT;
@@ -172,7 +182,12 @@
 
         if (lspeer != null) {
             lspeer.setSelfInnitConnection(true);
-            // TODO: initiate peer connection
+
+            if (lspeer.connectPeer() == null) {
+                connectPeer = new BgpConnectPeerImpl(bgpController, routerid, Controller.getBgpPortNum());
+                lspeer.setConnectPeer(connectPeer);
+                connectPeer.connectPeer();
+            }
             return true;
         }
 
@@ -185,7 +200,6 @@
 
         if (lspeer != null) {
 
-            //TODO DISCONNECT PEER
             disconnectPeer(routerid);
             lspeer.setSelfInnitConnection(false);
             lspeer = this.bgpPeerTree.remove(routerid);
@@ -204,7 +218,12 @@
 
         if (lspeer != null) {
 
-            //TODO DISCONNECT PEER
+            BgpPeer disconnPeer = peerManager.getPeer(BgpId.bgpId(IpAddress.valueOf(routerid)));
+            if (disconnPeer != null) {
+                // TODO: send notification peer deconfigured
+                disconnPeer.disconnectPeer();
+            }
+            lspeer.connectPeer().disconnectPeer();
             lspeer.setState(BgpPeerCfg.State.IDLE);
             lspeer.setSelfInnitConnection(false);
             log.debug("Disconnected : " + routerid + " successfully");
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
index 6a14e85..51ab68b 100755
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
@@ -16,6 +16,8 @@
 
 package org.onosproject.bgp.controller.impl;
 
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArraySet;
@@ -29,11 +31,16 @@
 import org.onosproject.bgp.controller.BgpCfg;
 import org.onosproject.bgp.controller.BgpController;
 import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpLocalRib;
 import org.onosproject.bgp.controller.BgpPeer;
 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.BgpUpdateMsg;
+import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.MpReachNlri;
+import org.onosproject.bgpio.types.MpUnReachNlri;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,11 +54,14 @@
 
     protected BgpPeerManagerImpl peerManager = new BgpPeerManagerImpl();
 
+    private BgpLocalRib bgplocalRIB = new BgpLocalRibImpl(this);
+    private BgpLocalRib bgplocalRIBVpn = new BgpLocalRibImpl(this);
+
     protected Set<BgpNodeListener> bgpNodeListener = new CopyOnWriteArraySet<>();
 
     final Controller ctrl = new Controller(this);
 
-    private BgpConfig bgpconfig = new BgpConfig();
+    private BgpConfig bgpconfig = new BgpConfig(this);
 
     @Activate
     public void activate() {
@@ -100,6 +110,8 @@
     @Override
     public void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException {
 
+        BgpPeer peer = getPeer(bgpId);
+
         switch (msg.getType()) {
         case OPEN:
             // TODO: Process Open message
@@ -111,7 +123,23 @@
             // TODO: Process notificatoin message
             break;
         case UPDATE:
-            // TODO: Process update message
+            BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
+            List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
+            if (pathAttr == null) {
+               log.debug("llPathAttr is null, cannot process update message");
+               break;
+            }
+            Iterator<BgpValueType> listIterator = pathAttr.iterator();
+            boolean isLinkstate = false;
+            while (listIterator.hasNext()) {
+                BgpValueType attr = listIterator.next();
+                if ((attr instanceof MpReachNlri) || (attr instanceof MpUnReachNlri)) {
+                    isLinkstate = true;
+                }
+            }
+            if (isLinkstate) {
+                peer.buildAdjRibIn(pathAttr);
+            }
             break;
         default:
             // TODO: Process other message
@@ -215,4 +243,24 @@
     public int connectedPeerCount() {
         return connectedPeers.size();
     }
+
+    /**
+     * Gets the BGP local RIB.
+     *
+     * @return bgplocalRIB BGP local RIB.
+     */
+    @Override
+    public BgpLocalRib bgpLocalRib() {
+        return bgplocalRIB;
+    }
+
+    /**
+     * Gets the BGP local RIB with VPN.
+     *
+     * @return bgplocalRIBVpn BGP VPN local RIB .
+     */
+    @Override
+    public BgpLocalRib bgpLocalRibVpn() {
+        return bgplocalRIBVpn;
+    }
 }
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
new file mode 100755
index 0000000..44b1905
--- /dev/null
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+package org.onosproject.bgp.controller.impl;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.onosproject.bgp.controller.BgpController;
+import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpLocalRib;
+import org.onosproject.bgp.controller.BgpNodeListener;
+import org.onosproject.bgp.controller.BgpSessionInfo;
+import org.onosproject.bgpio.protocol.BgpLSNlri;
+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.BgpPrefixIPv4LSNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier;
+import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
+import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib;
+import org.onosproject.bgpio.types.RouteDistinguisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implementation of local RIB.
+ */
+public class BgpLocalRibImpl implements BgpLocalRib {
+
+    private static final Logger log = LoggerFactory.getLogger(BgpLocalRibImpl.class);
+    private BgpController bgpController;
+
+    private Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> nodeTree = new TreeMap<>();
+    private Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib> linkTree = new TreeMap<>();
+    private Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib> prefixTree = new TreeMap<>();
+
+    private Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnNodeTree
+                                                                                                   = new TreeMap<>();
+    private Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnLinkTree
+                                                                                                   = new TreeMap<>();
+    private Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnPrefixTree
+                                                                                                   = new TreeMap<>();
+
+    public BgpLocalRibImpl(BgpController bgpController) {
+        this.bgpController = bgpController;
+    }
+
+    /**
+     * Gets node NLRI tree.
+     *
+     * @return node tree
+     */
+    public Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> nodeTree() {
+        return nodeTree;
+    }
+
+    /**
+     * Gets link NLRI tree.
+     *
+     * @return link tree
+     */
+    public Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib> linkTree() {
+        return linkTree;
+    }
+
+    /**
+     * Gets prefix NLRI tree.
+     *
+     * @return prefix tree
+     */
+    public Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib> prefixTree() {
+        return prefixTree;
+    }
+
+    /**
+     * Gets VPN node NLRI tree.
+     *
+     * @return vpn node NLRI tree
+     */
+    public Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnNodeTree() {
+        return vpnNodeTree;
+    }
+
+    /**
+     * Gets VPN link NLRI tree.
+     *
+     * @return vpn link NLRI Tree
+     */
+    public Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnLinkTree() {
+        return vpnLinkTree;
+    }
+
+    /**
+     * Gets VPN prefix NLRI tree.
+     *
+     * @return vpn prefix NLRI Tree
+     */
+    public Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnPrefixTree() {
+        return vpnPrefixTree;
+    }
+
+    @Override
+    public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) {
+        int decisionResult;
+
+        log.debug("Add to local RIB {}", details.toString());
+
+        PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+                                                               sessionInfo.remoteBgpId().ipAddress(),
+                                                               sessionInfo.remoteBgpIdentifier(),
+                                                               sessionInfo.remoteBgpASNum(),
+                                                               sessionInfo.isIbgpSession(), details);
+        if (nlri instanceof BgpNodeLSNlriVer4) {
+            BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors();
+            if (nodeTree.containsKey(nodeLsIdentifier)) {
+                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+                // Compare local RIB entry with the current attribute
+                decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
+                if (decisionResult < 0) {
+                    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);
+                }
+                log.debug("Local RIB ad node: {}", detailsLocRib.toString());
+            }
+        } else if (nlri instanceof BgpLinkLsNlriVer4) {
+            BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier();
+            if (linkTree.containsKey(linkLsIdentifier)) {
+                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+                // Compare local RIB entry with the current attribute
+                decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
+                if (decisionResult < 0) {
+                    linkTree.replace(linkLsIdentifier, detailsLocRib);
+                    log.debug("Local RIB update link: {}", detailsLocRib.toString());
+                }
+            } else {
+                linkTree.put(linkLsIdentifier, detailsLocRib);
+                log.debug("Local RIB add link: {}", detailsLocRib.toString());
+            }
+        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+            BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier();
+            if (prefixTree.containsKey(prefixIdentifier)) {
+                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+                // Compare local RIB entry with the current attribute
+                decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib);
+                if (decisionResult < 0) {
+                    prefixTree.replace(prefixIdentifier, detailsLocRib);
+                    log.debug("Local RIB update prefix: {}", detailsLocRib.toString());
+                }
+            } else {
+                prefixTree.put(prefixIdentifier, detailsLocRib);
+                log.debug("Local RIB add prefix: {}", detailsLocRib.toString());
+            }
+        }
+    }
+
+    @Override
+    public void delete(BgpLSNlri nlri) {
+        log.debug("Delete from local RIB.");
+
+        // Update local RIB
+        decisionProcess(nlri);
+    }
+
+    /**
+     * Update local RIB based on selection algorithm.
+     *
+     * @param nlri NLRI to update
+     */
+    public void decisionProcess(BgpLSNlri nlri) {
+        checkNotNull(nlri);
+        if (nlri instanceof BgpNodeLSNlriVer4) {
+            selectionProcessNode(nlri, false);
+        } else if (nlri instanceof BgpLinkLsNlriVer4) {
+            selectionProcessLink(nlri, false);
+        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+            selectionProcessPrefix(nlri, false);
+        }
+    }
+
+    /**
+     * Update VPN local RIB .
+     *
+     * @param nlri NLRI to update
+     * @param routeDistinguisher VPN id to update
+     */
+    public void decisionProcess(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
+        checkNotNull(nlri);
+        if (nlri instanceof BgpNodeLSNlriVer4) {
+            if (vpnNodeTree.containsKey(routeDistinguisher)) {
+                selectionProcessNode(nlri, true);
+                if (nodeTree.size() == 0) {
+                    vpnNodeTree.remove(routeDistinguisher);
+                }
+            }
+        } else if (nlri instanceof BgpLinkLsNlriVer4) {
+            if (vpnLinkTree.containsKey(routeDistinguisher)) {
+                selectionProcessLink(nlri, true);
+                if (linkTree.size() == 0) {
+                    vpnLinkTree.remove(routeDistinguisher);
+                }
+            }
+        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+            if (vpnPrefixTree.containsKey(routeDistinguisher)) {
+                selectionProcessPrefix(nlri, true);
+                if (prefixTree.size() == 0) {
+                    vpnPrefixTree.remove(routeDistinguisher);
+                }
+            }
+        }
+    }
+
+     /**
+     * Selection process for local RIB node.
+     *
+     * @param nlri NLRI to update
+     * @param isVpnRib true if VPN  local RIB, otherwise false
+     */
+    public void selectionProcessNode(BgpLSNlri nlri, boolean isVpnRib) {
+        BgpPeerImpl peer;
+        BgpSessionInfo sessionInfo;
+        int decisionResult;
+        boolean containsKey;
+
+        BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors();
+
+        if (nodeTree.containsKey(nodeLsIdentifier)) {
+            for (BgpNodeListener l : bgpController.listener()) {
+                l.deleteNode((BgpNodeLSNlriVer4) nlri);
+            }
+            log.debug("Local RIB delete node: {}", nodeLsIdentifier.toString());
+            nodeTree.remove(nodeLsIdentifier);
+        }
+
+        for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
+            peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));
+
+            if (nodeTree.containsKey(nodeLsIdentifier)) {
+                containsKey = (!isVpnRib) ? (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) :
+                                            (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier));
+
+                if (!containsKey) {
+                    continue;
+                }
+                sessionInfo = peer.sessionInfo();
+                PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+                                                                sessionInfo.remoteBgpId().ipAddress(),
+                                                                sessionInfo.remoteBgpIdentifier(),
+                                                                sessionInfo.remoteBgpASNum(),
+                                                                sessionInfo.isIbgpSession(),
+                                                                (!isVpnRib) ?
+                                                                (peer.adjacencyRib().nodeTree()
+                                                                                    .get(nodeLsIdentifier)) :
+                                                                (peer.vpnAdjacencyRib().nodeTree()
+                                                                                        .get(nodeLsIdentifier)));
+                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+                decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
+                if (decisionResult < 0) {
+                    nodeTree.replace(nodeLsIdentifier, detailsLocRib);
+                    log.debug("Local RIB node updated: {}", detailsLocRib.toString());
+                }
+            } else {
+                if (!isVpnRib) {
+                    if (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) {
+                        add(peer.sessionInfo(), nlri, peer.adjacencyRib().nodeTree().get(nodeLsIdentifier));
+                    }
+                } else {
+                    if (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) {
+                        add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().nodeTree().get(nodeLsIdentifier));
+                    }
+                }
+            }
+        }
+    }
+
+     /**
+     * Selection process for local RIB link.
+     *
+     * @param nlri NLRI to update
+     * @param isVpnRib true if VPN local RIB, otherwise false
+     */
+    public void selectionProcessLink(BgpLSNlri nlri, boolean isVpnRib) {
+        BgpPeerImpl peer;
+        BgpSessionInfo sessionInfo;
+        int decisionResult;
+        boolean containsKey;
+
+        BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier();
+
+        if (linkTree.containsKey(linkLsIdentifier)) {
+            log.debug("Local RIB remove link: {}", linkLsIdentifier.toString());
+            linkTree.remove(linkLsIdentifier);
+        }
+
+        for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
+            peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));
+
+            if (linkTree.containsKey(linkLsIdentifier)) {
+
+                containsKey = (!isVpnRib) ? (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) :
+                                            (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier));
+
+                if (!containsKey) {
+                    continue;
+                }
+
+                sessionInfo = peer.sessionInfo();
+
+                PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+                                                            sessionInfo.remoteBgpId().ipAddress(),
+                                                            sessionInfo.remoteBgpIdentifier(),
+                                                            sessionInfo.remoteBgpASNum(),
+                                                            sessionInfo.isIbgpSession(),
+                                                            ((!isVpnRib) ?
+                                                            (peer.adjacencyRib().linkTree().get(linkLsIdentifier)) :
+                                                            (peer.vpnAdjacencyRib().linkTree()
+                                                                                   .get(linkLsIdentifier))));
+
+                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+                decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
+                if (decisionResult < 0) {
+                    linkTree.replace(linkLsIdentifier, detailsLocRib);
+                    log.debug("Local RIB link updated: {}", detailsLocRib.toString());
+                }
+            } else {
+                if (!isVpnRib) {
+                    if (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) {
+                        add(peer.sessionInfo(), nlri, peer.adjacencyRib().linkTree().get(linkLsIdentifier));
+                    }
+                } else {
+                    if (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier)) {
+                        add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().linkTree().get(linkLsIdentifier));
+                    }
+                }
+            }
+        }
+    }
+
+     /**
+     * Selection process for local RIB prefix.
+     *
+     * @param nlri NLRI to update
+     * @param isVpnRib true if VPN local RIB, otherwise false
+     */
+    public void selectionProcessPrefix(BgpLSNlri nlri, boolean isVpnRib) {
+        BgpPeerImpl peer;
+        BgpSessionInfo sessionInfo;
+        int decisionResult;
+        boolean containsKey;
+
+        BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier();
+        if (prefixTree.containsKey(prefixIdentifier)) {
+            log.debug("Local RIB remove prefix: {}", prefixIdentifier.toString());
+            prefixTree.remove(prefixIdentifier);
+        }
+
+        for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
+            peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));
+
+            if (prefixTree.containsKey(prefixIdentifier)) {
+
+                containsKey = (!isVpnRib) ? (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) :
+                                            (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier));
+                if (!containsKey) {
+                    continue;
+                }
+                sessionInfo = peer.sessionInfo();
+
+                PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+                                                                sessionInfo.remoteBgpId().ipAddress(),
+                                                                sessionInfo.remoteBgpIdentifier(),
+                                                                sessionInfo.remoteBgpASNum(),
+                                                                sessionInfo.isIbgpSession(),
+                                                                ((!isVpnRib) ?
+                                                                (peer.adjacencyRib().prefixTree()
+                                                                                    .get(prefixIdentifier)) :
+                                                                (peer.vpnAdjacencyRib().prefixTree()
+                                                                                       .get(prefixIdentifier))));
+
+                BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+                decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib);
+                if (decisionResult < 0) {
+                    prefixTree.replace(prefixIdentifier, detailsLocRib);
+                    log.debug("local RIB prefix updated: {}", detailsLocRib.toString());
+                }
+            } else {
+                    if (!isVpnRib) {
+                        if (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) {
+                            add(peer.sessionInfo(), nlri, peer.adjacencyRib().prefixTree().get(prefixIdentifier));
+                    } else {
+                        if (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier)) {
+                            add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().prefixTree().get(prefixIdentifier));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details,
+                    RouteDistinguisher routeDistinguisher) {
+        add(sessionInfo, nlri, details);
+        if (nlri instanceof BgpNodeLSNlriVer4) {
+            if (!vpnNodeTree.containsKey(routeDistinguisher)) {
+                vpnNodeTree.put(routeDistinguisher, nodeTree);
+            }
+        } else if (nlri instanceof BgpLinkLsNlriVer4) {
+            if (!vpnLinkTree.containsKey(routeDistinguisher)) {
+                vpnLinkTree.put(routeDistinguisher, linkTree);
+            }
+        } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+            if (!vpnPrefixTree.containsKey(routeDistinguisher)) {
+                vpnPrefixTree.put(routeDistinguisher, prefixTree);
+            }
+        }
+    }
+
+    @Override
+    public void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
+        // Update local RIB
+        decisionProcess(nlri, routeDistinguisher);
+    }
+
+    /**
+     * Update local RIB node based on avaliable peer adjacency RIB.
+     *
+     * @param o adjacency-in/VPN adjacency-in
+     */
+    public void localRIBUpdateNode(Object o) {
+
+        if (o instanceof AdjRibIn) {
+            AdjRibIn adjRib = (AdjRibIn) o;
+            log.debug("Update local RIB node.");
+
+            Set<BgpNodeLSIdentifier> nodeKeys = adjRib.nodeTree().keySet();
+            for (BgpNodeLSIdentifier key : nodeKeys) {
+                PathAttrNlriDetails pathAttrNlri = adjRib.nodeTree().get(key);
+
+                BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(), pathAttrNlri
+                                                                   .protocolID().getType(), key, false, null);
+                decisionProcess(nodeNlri);
+            }
+        }
+
+        if (o instanceof VpnAdjRibIn) {
+            VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
+            log.debug("Update local RIB VPN node.");
+            Set<RouteDistinguisher> nodeKeysVpn = vpnAdjRib.vpnNodeTree().keySet();
+            Map<BgpNodeLSIdentifier, PathAttrNlriDetails> node;
+            for (RouteDistinguisher keyVpnNode : nodeKeysVpn) {
+                node = vpnAdjRib.vpnNodeTree().get(keyVpnNode);
+
+                Set<BgpNodeLSIdentifier> vpnNodeKeys = node.keySet();
+                for (BgpNodeLSIdentifier key : vpnNodeKeys) {
+                    PathAttrNlriDetails pathAttrNlri = vpnAdjRib.nodeTree().get(key);
+                    BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(),
+                                                                      pathAttrNlri.protocolID().getType(),
+                                                                      key, true, keyVpnNode);
+                    decisionProcess(nodeNlri, keyVpnNode);
+                }
+            }
+        }
+    }
+
+    /**
+     * Update localRIB link based on avaliable peer adjacency RIB.
+     *
+     * @param o adjacency-in/VPN adjacency-in
+     */
+    public void localRIBUpdateLink(Object o) {
+
+        if (o instanceof AdjRibIn) {
+            AdjRibIn adjRib = (AdjRibIn) o;
+            log.debug("Update local RIB link.");
+
+            Set<BgpLinkLSIdentifier> linkKeys = adjRib.linkTree().keySet();
+            for (BgpLinkLSIdentifier key : linkKeys) {
+                PathAttrNlriDetails pathAttrNlri = adjRib.linkTree().get(key);
+                BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(),
+                                                                   pathAttrNlri.identifier(), key, null, false);
+                decisionProcess(linkNlri);
+            }
+        }
+
+        if (o instanceof VpnAdjRibIn) {
+            VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
+            log.debug("Update local RIB VPN link");
+
+            Set<RouteDistinguisher> linkKeysVpn = vpnAdjRib.vpnLinkTree().keySet();
+            Map<BgpLinkLSIdentifier, PathAttrNlriDetails> link;
+            for (RouteDistinguisher keyVpnLink : linkKeysVpn) {
+                link = vpnAdjRib.vpnLinkTree().get(keyVpnLink);
+
+                Set<BgpLinkLSIdentifier> vpnLinkKeys = link.keySet();
+                for (BgpLinkLSIdentifier key : vpnLinkKeys) {
+                    PathAttrNlriDetails pathAttrNlri = vpnAdjRib.linkTree().get(key);
+                    BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(),
+                                                                       pathAttrNlri.identifier(), key, keyVpnLink,
+                                                                       true);
+                    decisionProcess(linkNlri, keyVpnLink);
+                }
+            }
+        }
+    }
+
+    /**
+     * Update localRIB prefix based on avaliable peer adjacency RIB.
+     *
+     * @param o instance of adjacency-in/VPN adjacency-in
+     */
+    public void localRIBUpdatePrefix(Object o) {
+
+        if (o instanceof AdjRibIn) {
+            AdjRibIn adjRib = (AdjRibIn) o;
+            log.debug("Update local RIB prefix.");
+
+            Set<BgpPrefixLSIdentifier> prefixKeys = adjRib.prefixTree().keySet();
+            for (BgpPrefixLSIdentifier key : prefixKeys) {
+                PathAttrNlriDetails pathAttrNlri = adjRib.prefixTree().get(key);
+                BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(
+                                                                             pathAttrNlri.identifier(),
+                                                                             pathAttrNlri.protocolID().getType(),
+                                                                             key, null, false);
+                decisionProcess(prefixNlri);
+            }
+        }
+
+        if (o instanceof VpnAdjRibIn) {
+            VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
+            log.debug("Update local RIB VPN prefix.");
+
+            Set<RouteDistinguisher> prefixKeysVpn = vpnAdjRib.vpnPrefixTree().keySet();
+            Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefix;
+            for (RouteDistinguisher keyVpnPrefix : prefixKeysVpn) {
+                prefix = vpnAdjRib.vpnPrefixTree().get(keyVpnPrefix);
+
+                Set<BgpPrefixLSIdentifier> vpnPrefixKeys = prefix.keySet();
+                for (BgpPrefixLSIdentifier key : vpnPrefixKeys) {
+                    PathAttrNlriDetails pathAttrNlri = vpnAdjRib.prefixTree().get(key);
+                    BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(pathAttrNlri.identifier(),
+                                                                                     pathAttrNlri.protocolID()
+                                                                                             .getType(), key,
+                                                                                     keyVpnPrefix, true);
+                    decisionProcess(prefixNlri, keyVpnPrefix);
+                }
+            }
+        }
+    }
+
+    /**
+     * Update localRIB.
+     *
+     * @param adjRibIn adjacency RIB-in
+     */
+    public void localRIBUpdate(AdjRibIn adjRibIn) {
+        log.debug("Update local RIB.");
+
+        localRIBUpdateNode(adjRibIn);
+        localRIBUpdateLink(adjRibIn);
+        localRIBUpdatePrefix(adjRibIn);
+    }
+
+    /**
+     * Update localRIB.
+     *
+     * @param vpnAdjRibIn VPN adjacency RIB-in
+     */
+    public void localRIBUpdate(VpnAdjRibIn vpnAdjRibIn) {
+        log.debug("Update VPN local RIB.");
+
+        localRIBUpdateNode(vpnAdjRibIn);
+        localRIBUpdateLink(vpnAdjRibIn);
+        localRIBUpdatePrefix(vpnAdjRibIn);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).omitNullValues().add("nodeTree", nodeTree)
+                .add("linkTree", linkTree).add("prefixTree", prefixTree).add("vpnNodeTree", vpnNodeTree)
+                .add("vpnLinkTree", vpnLinkTree).add("vpnPrefixTree", vpnPrefixTree).toString();
+    }
+}
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
index 57a924a..e3f09f3 100644
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
@@ -28,6 +28,7 @@
 import org.onosproject.bgp.controller.BgpController;
 import org.onosproject.bgp.controller.BgpPeer;
 import org.onosproject.bgp.controller.BgpSessionInfo;
+import org.onosproject.bgp.controller.BgpLocalRib;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpFactories;
 import org.onosproject.bgpio.protocol.BgpFactory;
@@ -61,9 +62,28 @@
     protected boolean isHandShakeComplete = false;
     private BgpSessionInfo sessionInfo;
     private BgpPacketStatsImpl pktStats;
+    private BgpLocalRib bgplocalRIB;
+    private BgpLocalRib bgplocalRIBVpn;
     private AdjRibIn adjRib;
     private VpnAdjRibIn vpnAdjRib;
 
+    /**
+     * Return the adjacency RIB-IN.
+     *
+     * @return adjRib the adjacency RIB-IN
+     */
+    public AdjRibIn adjacencyRib() {
+        return adjRib;
+    }
+
+    /**
+     * Return the adjacency RIB-IN with VPN.
+     *
+     * @return vpnAdjRib the adjacency RIB-IN with VPN
+     */
+    public VpnAdjRibIn vpnAdjacencyRib() {
+        return vpnAdjRib;
+    }
 
     @Override
     public BgpSessionInfo sessionInfo() {
@@ -81,6 +101,8 @@
         this.bgpController = bgpController;
         this.sessionInfo = sessionInfo;
         this.pktStats = pktStats;
+        this.bgplocalRIB =  bgpController.bgpLocalRib();
+        this.bgplocalRIBVpn =  bgpController.bgpLocalRibVpn();
         this.adjRib = new AdjRibIn();
         this.vpnAdjRib = new VpnAdjRibIn();
     }
@@ -119,22 +141,31 @@
                 PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr);
                 if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) {
                     adjRib.add(nlriInfo, details);
+                    bgplocalRIB.add(sessionInfo(), nlriInfo, details);
                 } else {
                     vpnAdjRib.addVpn(nlriInfo, details, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
+                    bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details,
+                                       ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
                 }
             } else if (nlriInfo instanceof BgpLinkLsNlriVer4) {
                 PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr);
                 if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) {
                     adjRib.add(nlriInfo, details);
+                    bgplocalRIB.add(sessionInfo(), nlriInfo, details);
                 } else {
                     vpnAdjRib.addVpn(nlriInfo, details, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
+                    bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details,
+                                       ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
                 }
             } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) {
                 PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr);
                 if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) {
                     adjRib.add(nlriInfo, details);
+                    bgplocalRIB.add(sessionInfo(), nlriInfo, details);
                 } else {
                     vpnAdjRib.addVpn(nlriInfo, details, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher());
+                    bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details,
+                                       ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher());
                 }
             }
         }
@@ -170,20 +201,26 @@
             if (nlriInfo instanceof BgpNodeLSNlriVer4) {
                 if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) {
                     adjRib.remove(nlriInfo);
+                    bgplocalRIB.delete(nlriInfo);
                 } else {
                     vpnAdjRib.removeVpn(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
+                    bgplocalRIBVpn.delete(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
                 }
             } else if (nlriInfo instanceof BgpLinkLsNlriVer4) {
                 if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) {
                     adjRib.remove(nlriInfo);
+                    bgplocalRIB.delete(nlriInfo);
                 } else {
                     vpnAdjRib.removeVpn(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
+                    bgplocalRIBVpn.delete(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
                 }
             } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) {
                 if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) {
                     adjRib.remove(nlriInfo);
+                    bgplocalRIB.delete(nlriInfo);
                 } else {
                     vpnAdjRib.removeVpn(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher());
+                    bgplocalRIBVpn.delete(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher());
                 }
             }
         }
@@ -207,6 +244,18 @@
         return vpnAdjRib;
     }
 
+    /**
+     * Update localRIB on peer disconnect.
+     *
+     */
+    public void updateLocalRIBOnPeerDisconnect() {
+        BgpLocalRibImpl localRib = (BgpLocalRibImpl) bgplocalRIB;
+        BgpLocalRibImpl localRibVpn = (BgpLocalRibImpl) bgplocalRIBVpn;
+
+        localRib.localRIBUpdate(adjacencyRib());
+        localRibVpn.localRIBUpdate(vpnAdjacencyRib());
+    }
+
     // ************************
     // Channel related
     // ************************
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 30bb447..37576e4 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
@@ -31,6 +31,7 @@
 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.onosproject.bgp.controller.BgpNodeListener;
 import org.onosproject.bgp.controller.BgpPeerManager;
 import org.onosproject.bgpio.exceptions.BgpParseException;
@@ -208,6 +209,17 @@
             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() {