Support for multiple route paths
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / TunnelInterfaceStateListener.java
index e2b38829d240e3d812f52bfe01727826e56ada8b..d0de55018b9fcd220163fc0935b26ed073ae45d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,52 +8,68 @@
 package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
+import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpnInterfaceListOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class TunnelInterfaceStateListener extends AbstractDataChangeListener<StateTunnelList>
-        implements AutoCloseable{
+public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
+    TunnelInterfaceStateListener> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
     private final DataBroker dataBroker;
     private final IBgpManager bgpManager;
-    private IFibManager fibManager;
-    private ItmRpcService itmRpcService;
+    private final IFibManager fibManager;
+    private final ItmRpcService itmRpcService;
+    private OdlInterfaceRpcService intfRpcService;
+    private VpnInterfaceManager vpnInterfaceManager;
+    private VpnSubnetRouteHandler vpnSubnetRouteHandler;
+
     protected enum UpdateRouteAction {
         ADVERTISE_ROUTE, WITHDRAW_ROUTE
     }
 
+    protected enum TunnelAction {
+        TUNNEL_EP_ADD,
+        TUNNEL_EP_DELETE,
+        TUNNEL_EP_UPDATE
+    }
+
     /**
-     * Responsible for listening to tunnel interface state change
+     * Responsible for listening to tunnel interface state change.
      *
      * @param dataBroker dataBroker
      * @param bgpManager bgpManager
@@ -61,224 +77,318 @@ public class TunnelInterfaceStateListener extends AbstractDataChangeListener<Sta
      * @param itmRpcService itmRpcService
      */
     public TunnelInterfaceStateListener(final DataBroker dataBroker,
-                                        final IBgpManager bgpManager,
-                                        final IFibManager fibManager,
-                                        final ItmRpcService itmRpcService) {
-        super(StateTunnelList.class);
+        final IBgpManager bgpManager,
+        final IFibManager fibManager,
+        final ItmRpcService itmRpcService,
+        final OdlInterfaceRpcService ifaceMgrRpcService,
+        final VpnInterfaceManager vpnInterfaceManager,
+        final VpnSubnetRouteHandler vpnSubnetRouteHandler) {
+        super(StateTunnelList.class, TunnelInterfaceStateListener.class);
         this.dataBroker = dataBroker;
         this.bgpManager = bgpManager;
         this.fibManager = fibManager;
         this.itmRpcService = itmRpcService;
+        this.intfRpcService = ifaceMgrRpcService;
+        this.vpnInterfaceManager = vpnInterfaceManager;
+        this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
     }
 
     public void start() {
         LOG.info("{} start", getClass().getSimpleName());
-        listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                getWildCardPath(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
+        registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
     }
 
-    private InstanceIdentifier<StateTunnelList> getWildCardPath() {
+    @Override
+    protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
         return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
     }
 
     @Override
-    public void close() throws Exception {
-        if (listenerRegistration != null) {
-            listenerRegistration.close();
-            listenerRegistration = null;
-        }
-        LOG.info("{} close", getClass().getSimpleName());
+    protected TunnelInterfaceStateListener getDataTreeChangeListener() {
+        return TunnelInterfaceStateListener.this;
     }
 
     @Override
     protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
         LOG.trace("Tunnel deletion---- {}", del);
-        handlePrefixesForDPNs(del, UpdateRouteAction.WITHDRAW_ROUTE);
+        handleTunnelEventForDPN(del, UpdateRouteAction.WITHDRAW_ROUTE, TunnelAction.TUNNEL_EP_DELETE);
     }
 
     @Override
-    protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original, StateTunnelList update) {
+    protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
+        StateTunnelList update) {
         LOG.trace("Tunnel updation---- {}", update);
         LOG.trace("ITM Tunnel {} of type {} state event changed from :{} to :{}",
-                update.getTunnelInterfaceName(),
-                fibManager.getTransportTypeStr(update.getTransportType().toString()),
-                original.isTunnelState(), update.isTunnelState());
+            update.getTunnelInterfaceName(),
+            fibManager.getTransportTypeStr(update.getTransportType().toString()),
+            original.getOperState(), update.getOperState());
         //withdraw all prefixes in all vpns for this dpn
-        boolean isTunnelUp = update.isTunnelState();
-        handlePrefixesForDPNs(update, isTunnelUp ? UpdateRouteAction.ADVERTISE_ROUTE :
-                UpdateRouteAction.WITHDRAW_ROUTE);
+        TunnelOperStatus tunOpStatus = update.getOperState();
+        if ((tunOpStatus != TunnelOperStatus.Down) && (tunOpStatus != TunnelOperStatus.Up)) {
+            LOG.trace("Returning from unsupported tunnelOperStatus {}", tunOpStatus);
+            return;
+        }
+        boolean isTunnelUp = (tunOpStatus == TunnelOperStatus.Up);
+        handleTunnelEventForDPN(update,
+            isTunnelUp ? UpdateRouteAction.ADVERTISE_ROUTE : UpdateRouteAction.WITHDRAW_ROUTE,
+            TunnelAction.TUNNEL_EP_UPDATE);
     }
 
     @Override
     protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
         LOG.trace("Tunnel addition---- {}", add);
-
-        if (!add.isTunnelState()) {
+        TunnelOperStatus tunOpStatus = add.getOperState();
+        if ((tunOpStatus != TunnelOperStatus.Down) && (tunOpStatus != TunnelOperStatus.Up)) {
+            LOG.trace("Returning from unsupported tunnelOperStatus {}", tunOpStatus);
+            return;
+        }
+        boolean isTunnelUp = (tunOpStatus == TunnelOperStatus.Up);
+        if (!isTunnelUp) {
             LOG.trace("Tunnel {} is not yet UP.",
-                    add.getTunnelInterfaceName());
+                add.getTunnelInterfaceName());
             return;
         } else {
             LOG.trace("ITM Tunnel ,type {} ,State is UP b/w src: {} and dest: {}",
-                    fibManager.getTransportTypeStr(add.getTransportType().toString()),
-                    add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
-            handlePrefixesForDPNs(add, UpdateRouteAction.ADVERTISE_ROUTE);
+                fibManager.getTransportTypeStr(add.getTransportType().toString()),
+                add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
+            handleTunnelEventForDPN(add, UpdateRouteAction.ADVERTISE_ROUTE, TunnelAction.TUNNEL_EP_ADD);
         }
     }
 
-    private void handlePrefixesForDPNs(StateTunnelList stateTunnelList, UpdateRouteAction action) {
-        BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
-        BigInteger destDpnId;
-        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, UpdateRouteAction action,
+        TunnelAction tunnelAction) {
+        final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
+        final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
         String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
+        String rd;
+        BigInteger remoteDpnId = null;
+        boolean isTepDeletedOnDpn = false;
 
-        InstanceIdentifier.InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
-        InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
-        Optional<VpnInstances> vpnInstances = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
-        long tunTypeVal = 0, vpnId;
+        LOG.trace("Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ", srcDpnId, srcTepIp, destTepIp);
+        int tunTypeVal = getTunnelType(stateTunnelList);
 
-        if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
-        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
-        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
-        } else {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
-        }
         LOG.trace("tunTypeVal is {}", tunTypeVal);
 
-        long dcgwPresentStatus = VpnConstants.DCGWPresentStatus.Invalid.getValue();
-        if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-            Future<RpcResult<IsDcgwPresentOutput>> result;
+        try {
+            if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
+                LOG.trace(" Tunnel ADD event received for Dpn {} VTEP Ip {} ", srcDpnId, srcTepIp);
+            } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE) {
+                LOG.trace(" Tunnel DELETE event received for Dpn {} VTEP Ip {} ", srcDpnId, srcTepIp);
+                // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
+                // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
+                // Update the adj for the vpninterfaces for a DPN on which TEP is deleted.
+                // Update the adj & VRF for the vpninterfaces for a DPN on which TEP is deleted.
+                // Dont update the adj & VRF for vpninterfaces for a DPN on which TEP is not deleted.
+                String endpointIpForDPN = null;
+                try {
+                    endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
+                } catch (Exception e) {
+                    /* this dpn does not have the VTEP */
+                    endpointIpForDPN = null;
+                }
+
+                if (endpointIpForDPN == null) {
+                    LOG.trace("Tunnel TEP is deleted on Dpn {} VTEP Ip {}", srcDpnId, srcTepIp);
+                    isTepDeletedOnDpn = true;
+                }
+            }
+
+            // Get the list of VpnInterfaces from Intf Mgr for a SrcDPN on which TEP is added/deleted
+            Future<RpcResult<GetDpnInterfaceListOutput>> result;
+            List<String> srcDpninterfacelist = new ArrayList<>();
+            List<String> destDpninterfacelist = new ArrayList<>();
             try {
-                result = itmRpcService.isDcgwPresent(new IsDcgwPresentInputBuilder()
-                        .setDcgwIp(destTepIp)
-                        .build());
-                RpcResult<IsDcgwPresentOutput> rpcResult = result.get();
+                result =
+                    intfRpcService.getDpnInterfaceList(new GetDpnInterfaceListInputBuilder().setDpid(srcDpnId).build());
+                RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
                 if (!rpcResult.isSuccessful()) {
-                    LOG.warn("RPC Call to isDcgwPresent {} returned with Errors {}", destTepIp, rpcResult.getErrors());
+                    LOG.warn("RPC Call to GetDpnInterfaceList for dpnid {} returned with Errors {}", srcDpnId,
+                        rpcResult.getErrors());
                 } else {
-                    dcgwPresentStatus = rpcResult.getResult().getRetVal();
+                    srcDpninterfacelist = rpcResult.getResult().getInterfacesList();
                 }
             } catch (Exception e) {
-                LOG.warn("Exception {} when querying for isDcgwPresent {}, trace {}", e, destTepIp, e.getStackTrace());
+                LOG.warn("Exception when querying for GetDpnInterfaceList for dpnid {}", srcDpnId, e);
             }
-        }
 
-        if (vpnInstances.isPresent()) {
-            List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
-            Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
-            LOG.trace("vpnInstIter {}", vpnInstIter);
-            while (vpnInstIter.hasNext()) {
-                VpnInstance vpnInstance = vpnInstIter.next();
-                LOG.trace("vpnInstance {}", vpnInstance);
-                vpnId = VpnUtil.getVpnId(dataBroker, vpnInstance.getVpnInstanceName());
+            // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
+            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+                remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
                 try {
-                    String rd = VpnUtil.getRdFromVpnInstance(vpnInstance);
-                    InstanceIdentifier<VpnToDpnList> srcId =
-                            VpnUtil.getVpnToDpnListIdentifier(rd, srcDpnId);
-                    Optional<VpnToDpnList> srcDpnInVpn =
-                            VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, srcId);
-                    if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                        destDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
-                        InstanceIdentifier<VpnToDpnList> destId =
-                                VpnUtil.getVpnToDpnListIdentifier(rd, destDpnId);
-                        Optional<VpnToDpnList> destDpnInVpn =
-                                VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, destId);
-                        if (!(srcDpnInVpn.isPresent() &&
-                                destDpnInVpn.isPresent())) {
-                            LOG.trace(" srcDpn {} - destDPN {}, do not share the VPN {} with rd {}.",
-                                    srcDpnId, destDpnId, vpnInstance.getVpnInstanceName(), rd);
-                            continue;
+                    result = intfRpcService.getDpnInterfaceList(
+                        new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
+                    RpcResult<GetDpnInterfaceListOutput> rpcResult = result.get();
+                    if (!rpcResult.isSuccessful()) {
+                        LOG.warn("RPC Call to GetDpnInterfaceList for dpnid {} returned with Errors {}", srcDpnId,
+                            rpcResult.getErrors());
+                    } else {
+                        destDpninterfacelist = rpcResult.getResult().getInterfacesList();
+                    }
+                } catch (Exception e) {
+                    LOG.warn("Exception when querying for GetDpnInterfaceList for dpnid {}", srcDpnId, e);
+                }
+            }
+
+            /*
+             * Iterate over the list of VpnInterface for a SrcDpn on which TEP is added or deleted and read the adj.
+             * Update the adjacencies with the updated nexthop.
+             */
+            Iterator<String> interfacelistIter = srcDpninterfacelist.iterator();
+            String intfName = null;
+            List<Uuid> subnetList = new ArrayList<>();
+            Map<Long, String> vpnIdRdMap = new HashMap<>();
+
+            while (interfacelistIter.hasNext()) {
+                intfName = interfacelistIter.next();
+                final VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, intfName);
+                if (vpnInterface != null) {
+
+                    DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                    dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
+                            new UpdateVpnInterfaceOnTunnelEvent(dataBroker,
+                                    vpnInterfaceManager,
+                                    tunnelAction,
+                                    vpnInterface,
+                                    stateTunnelList,
+                                    isTepDeletedOnDpn));
+
+                    // Populate the List of subnets
+                    InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
+                        InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
+                            new PortOpDataEntryKey(intfName)).build();
+                    Optional<PortOpDataEntry> optionalPortOp =
+                        VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+                    if (optionalPortOp.isPresent()) {
+                        Uuid subnetId = optionalPortOp.get().getSubnetId();
+                        if (!subnetList.contains(subnetId)) {
+                            subnetList.add(subnetId);
                         }
                     }
-                    if (srcDpnInVpn.isPresent()) {
-                        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                                .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
-                                vpnInterfaces = srcDpnInVpn.get().getVpnInterfaces();
-                        for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                                .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
-                            InstanceIdentifier<VpnInterface> vpnIntfId =
-                                    VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
-                            LOG.trace("vpnInterface {}", vpnInterface);
-                            InstanceIdentifier<Adjacencies> path =
-                                    vpnIntfId.augmentation(Adjacencies.class);
-                            Optional<Adjacencies> adjacencies =
-                                    VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
-                            LOG.trace("adjacencies {}", adjacencies);
-                            if (adjacencies.isPresent()) {
-                                List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
-                                Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
-
-                                while (adjacencyIterator.hasNext()) {
-                                    Adjacency adjacency = adjacencyIterator.next();
-                                    try {
-                                        if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
-                                            LOG.info("VPNInterfaceManager : Added Fib Entry rd {} prefix {} nextHop {} label {}",
-                                                    rd, adjacency.getIpAddress(), adjacency.getNextHopIpList(),
-                                                    adjacency.getLabel());
-//                                            vrf = new VrfEntryBuilder().set
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                                                fibManager.handleRemoteRoute(true,
-                                                        new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId()),
-                                                        new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
-                                                        VpnUtil.getVpnId(dataBroker, vpnInstance.getVpnInstanceName()),
-                                                        rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
-                                            }
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-                                                fibManager.populateFibOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
-                                            }
-                                        } else if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
-                                            LOG.info("VPNInterfaceManager : Removed Fib entry rd {} prefix {}",
-                                                    rd, adjacency.getIpAddress());
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                                                fibManager.handleRemoteRoute(false, srcDpnId,
-                                                        new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
-                                                        vpnId, rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
-                                            }
-                                            if ((tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) &&
-                                                    (dcgwPresentStatus == VpnConstants.DCGWPresentStatus.Absent.getValue())) {
-                                                bgpManager.withdrawPrefix(rd, adjacency.getIpAddress());
-                                                fibManager.cleanUpDpnForVpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp, null);
-                                            }
-                                        }
-                                    } catch (Exception e) {
-                                        LOG.error("Exception when updating prefix {} in vrf {} to BGP",
-                                                adjacency.getIpAddress(), rd);
-                                    }
-                                }
-                            } else {
-                                LOG.trace("no adjacencies present for path {}.", path);
+                    //Populate the map for VpnId-to-Rd
+                    long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
+                    rd = VpnUtil.getVpnRd(dataBroker, vpnInterface.getVpnInstanceName());
+                    vpnIdRdMap.put(vpnId, rd);
+                }
+            }
+
+            /*
+             * Iterate over the list of VpnInterface for destDPN and get the prefix .
+             * Create remote rule for each of those prefix on srcDPN.
+             */
+            interfacelistIter = destDpninterfacelist.iterator();
+            while (interfacelistIter.hasNext()) {
+                intfName = interfacelistIter.next();
+                final VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, intfName);
+                if (vpnInterface != null) {
+                    Adjacencies adjacencies = vpnInterface.getAugmentation(Adjacencies.class);
+                    List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
+                            : Collections.emptyList();
+                    String prefix = null;
+                    long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
+                    if (vpnIdRdMap.containsKey(vpnId)) {
+                        rd = vpnIdRdMap.get(vpnId);
+                        LOG.trace(" Remote DpnId {} VpnId {} rd {} VpnInterface {}", remoteDpnId, vpnId, rd,
+                            vpnInterface);
+                        for (Adjacency adj : adjList) {
+                            prefix = adj.getIpAddress();
+                            long label = adj.getLabel();
+                            if ((tunnelAction == TunnelAction.TUNNEL_EP_ADD)
+                                && (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue())) {
+                                fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp, label);
                             }
-                        }
-                        // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
-                        //    fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(dataBroker, vpnInstance.getVpnInstanceName()), rd);
-                        // }
-                        // Go through all the VrfEntries and withdraw and readvertise the prefixes to BGP for which the nextHop is the SrcTepIp
-                        if ((action == UpdateRouteAction.ADVERTISE_ROUTE) &&
-                                (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
-                            List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, rd);
-                            if (vrfEntries != null) {
-                                for (VrfEntry vrfEntry : vrfEntries) {
-                                    String destPrefix = vrfEntry.getDestPrefix().trim();
-                                    int vpnLabel = vrfEntry.getLabel().intValue();
-                                    List<String> nextHops = vrfEntry.getNextHopAddressList();
-                                    if (nextHops.contains(srcTepIp.trim())) {
-                                        bgpManager.withdrawPrefix(rd, destPrefix);
-                                        bgpManager.advertisePrefix(rd, destPrefix, nextHops, vpnLabel);
-                                    }
-                                }
+
+                            if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE)
+                                && (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue())) {
+                                fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp, label);
                             }
                         }
-                    } else {
-                        LOG.trace("dpnInVpn check failed for srcDpnId {}.", srcDpnId);
                     }
-                } catch (Exception e) {
-                    LOG.error("updatePrefixesForDPN {} in vpn {} failed", 0, vpnInstance.getVpnInstanceName(), e);
                 }
             }
+
+            //Iterate over the VpnId-to-Rd map.
+            for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
+                Long vpnId = entry.getKey();
+                rd = entry.getValue();
+                if ((tunnelAction == TunnelAction.TUNNEL_EP_ADD)
+                    && (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
+                    fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
+                } else if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE)
+                    && (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
+                    fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
+                }
+            }
+
+            if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
+                for (Uuid subnetId : subnetList) {
+                    // Populate the List of subnets
+                    vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
+                }
+            }
+
+            if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE) && isTepDeletedOnDpn) {
+                for (Uuid subnetId : subnetList) {
+                    // Populate the List of subnets
+                    vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Unable to handle the tunnel event.", e);
+            return;
+        }
+    }
+
+
+    private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
+        private VpnInterface vpnInterface;
+        private StateTunnelList stateTunnelList;
+        private VpnInterfaceManager vpnInterfaceManager;
+        private DataBroker broker;
+        private TunnelAction tunnelAction;
+        private boolean isTepDeletedOnDpn;
+
+        UpdateVpnInterfaceOnTunnelEvent(DataBroker broker,
+            VpnInterfaceManager vpnInterfaceManager,
+            TunnelAction tunnelAction,
+            VpnInterface vpnInterface,
+            StateTunnelList stateTunnelList,
+            boolean isTepDeletedOnDpn) {
+            this.broker = broker;
+            this.vpnInterfaceManager = vpnInterfaceManager;
+            this.stateTunnelList = stateTunnelList;
+            this.vpnInterface = vpnInterface;
+            this.tunnelAction = tunnelAction;
+            this.isTepDeletedOnDpn = isTepDeletedOnDpn;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+
+            if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
+                vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList);
+            }
+
+            if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE) && isTepDeletedOnDpn) {
+                vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList);
+            }
+
+            return null;
+        }
+    }
+
+    private int getTunnelType(StateTunnelList stateTunnelList) {
+        int tunTypeVal = 0;
+        if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
+        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
+        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
         } else {
-            LOG.trace("No vpn instances present.");
+            tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
         }
+        return tunTypeVal;
     }
 }