NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / TunnelInterfaceStateListener.java
index cdae7499f0b2073a7f9dd0140b3e6fb169164957..85d3dc0af934035d128bd329cacdfbd4408e4209 100644 (file)
@@ -7,43 +7,44 @@
  */
 package org.opendaylight.netvirt.vpnmanager;
 
-import static java.util.stream.Collectors.toList;
+import static java.util.Collections.emptyList;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Strings;
 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.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-import javax.annotation.PostConstruct;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.utils.JvmGlobalLocks;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -61,25 +62,27 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.Tep
 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.rev160406.DcGatewayIpList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
 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.port.op.data.PortOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
-        TunnelInterfaceStateListener> {
+public class TunnelInterfaceStateListener extends AbstractAsyncDataTreeChangeListener<StateTunnelList> {
 
     private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
 
@@ -91,6 +94,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
     private final JobCoordinator jobCoordinator;
     private final VpnUtil vpnUtil;
+    private static final int RETRY_COUNT = 3;
 
     protected enum UpdateRouteAction {
         ADVERTISE_ROUTE, WITHDRAW_ROUTE
@@ -120,7 +124,9 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                         final VpnSubnetRouteHandler vpnSubnetRouteHandler,
                                         final JobCoordinator jobCoordinator,
                                         VpnUtil vpnUtil) {
-        super(StateTunnelList.class, TunnelInterfaceStateListener.class);
+        super(dataBroker, LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class),
+                Executors.newListeningSingleThreadExecutor("TunnelInterfaceStateListener", LOG));
         this.dataBroker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.fibManager = fibManager;
@@ -129,35 +135,32 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
         this.jobCoordinator = jobCoordinator;
         this.vpnUtil = vpnUtil;
+        start();
     }
 
-    @PostConstruct
     public void start() {
         LOG.info("{} start", getClass().getSimpleName());
-        registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
     }
 
     @Override
-    protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
-        return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
     }
 
-    @Override
-    protected TunnelInterfaceStateListener getDataTreeChangeListener() {
-        return TunnelInterfaceStateListener.this;
-    }
 
     @Override
-    protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
+    public void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
         LOG.trace("remove: Tunnel deletion---- {}", del);
         if (isGreTunnel(del)) {
-            programDcGwLoadBalancingGroup(del, NwConstants.DEL_FLOW);
+            programDcGwLoadBalancingGroup(del, NwConstants.MOD_FLOW, false);
         }
         handleTunnelEventForDPN(del, TunnelAction.TUNNEL_EP_DELETE);
     }
 
     @Override
-    protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
+    public void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
                           StateTunnelList update) {
         LOG.trace("update: Tunnel updation---- {}", update);
         LOG.info("update: ITM Tunnel {} of type {} state event changed from :{} to :{}",
@@ -170,50 +173,54 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                     update.getTunnelInterfaceName());
             return;
         }
+        boolean isTunnelUp = TunnelOperStatus.Up == update.getOperState();
         if (isGreTunnel(update)) {
-            programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW);
+            programDcGwLoadBalancingGroup(update, NwConstants.MOD_FLOW, isTunnelUp);
         }
 
         //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
-        BigInteger srcDpnId = new BigInteger(update.getSrcInfo().getTepDeviceId());
-        String srcTepIp = String.valueOf(update.getSrcInfo().getTepIp().getValue());
+        Uint64 srcDpnId = Uint64.valueOf(update.getSrcInfo().getTepDeviceId()).intern();
+        String srcTepIp = update.getSrcInfo().getTepIp().stringValue();
         List<VpnInstanceOpDataEntry> vpnInstanceOpData = vpnUtil.getAllVpnInstanceOpData();
         if (vpnInstanceOpData == null) {
             LOG.trace("update: No vpnInstanceOpdata present");
             return;
         }
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx ->
-                vpnInstanceOpData.stream()
-                        .filter(opData -> opData.getVpnToDpnList() != null
-                                && opData.getVpnToDpnList().stream().anyMatch(
-                                    vpnToDpn -> vpnToDpn.getDpnId().equals(srcDpnId)))
-                        .forEach(opData -> {
-                            List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
-                                    opData.getVpnId());
-                            prefixes.forEach(destPrefix -> {
-                                VrfEntry vrfEntry = vpnUtil.getVrfEntry(opData.getVrfId(),
-                                        destPrefix.getDestPrefix());
-                                if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
-                                    return;
+        vpnInstanceOpData.stream()
+                .filter(opData -> opData.getVpnToDpnList() != null
+                        && opData.getVpnToDpnList().stream().anyMatch(
+                            vpnToDpn -> Objects.equals(vpnToDpn.getDpnId(), srcDpnId)))
+                .forEach(opData -> {
+                    List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
+                            opData.getVpnId());
+                    prefixes.forEach(destPrefix -> {
+                        VrfEntry vrfEntry = vpnUtil.getVrfEntry(opData.getVrfId(),
+                                destPrefix.getDestPrefix());
+                        if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
+                            return;
+                        }
+                        List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+                        routePaths.forEach(routePath -> {
+                            if (Objects.equals(routePath.getNexthopAddress(), srcTepIp)) {
+                                String prefix = destPrefix.getDestPrefix();
+                                String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(opData.getVpnInstanceName(),
+                                        prefix);
+                                // FIXME: separate out to somehow?
+                                final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnPrefixKey);
+                                lock.lock();
+                                try {
+                                    fibManager.refreshVrfEntry(opData.getVrfId(), prefix);
+                                } finally {
+                                    lock.unlock();
                                 }
-                                List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
-                                routePaths.forEach(routePath -> {
-                                    if (routePath.getNexthopAddress().equals(srcTepIp)) {
-                                        String prefix = destPrefix.getDestPrefix();
-                                        String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(opData.getVpnInstanceName(),
-                                                prefix);
-                                        synchronized (vpnPrefixKey.intern()) {
-                                            fibManager.refreshVrfEntry(opData.getVrfId(), prefix);
-                                        }
-                                    }
-                                });
-                            });
-                        })
-        ), LOG, "Error updating route paths for FIB entries");
+                            }
+                        });
+                    });
+                });
     }
 
     @Override
-    protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
+    public void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
         LOG.trace("add: Tunnel addition---- {}", add);
         TunnelOperStatus tunOpStatus = add.getOperState();
         if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
@@ -224,12 +231,15 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         if (tunOpStatus != TunnelOperStatus.Up) {
             LOG.error("add: Tunnel {} is not yet UP.", add.getTunnelInterfaceName());
         }
+        boolean isTunnelUp = TunnelOperStatus.Up == add.getOperState();
         if (isGreTunnel(add)) {
-            programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW);
+            programDcGwLoadBalancingGroup(add, NwConstants.ADD_FLOW, isTunnelUp);
         }
         LOG.info("add: ITM Tunnel ,type {} ,added between src: {} and dest: {}",
-                fibManager.getTransportTypeStr(add.getTransportType().toString()),
-                add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
+                fibManager.getTransportTypeStr(add.getTransportType() != null
+                        ? add.getTransportType().toString() : "Invalid"),
+                add.getSrcInfo() != null ? add.getSrcInfo().getTepDeviceId() : "0",
+                add.getDstInfo() != null ? add.getDstInfo().getTepDeviceId() : "0");
         handleTunnelEventForDPN(add, TunnelAction.TUNNEL_EP_ADD);
     }
 
@@ -250,11 +260,14 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, 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());
+        final Uint64 srcDpnId = stateTunnelList.getSrcInfo() != null
+                ? Uint64.valueOf(stateTunnelList.getSrcInfo().getTepDeviceId()).intern() : Uint64.ZERO;
+        final String srcTepIp = stateTunnelList.getSrcInfo() != null
+                ? stateTunnelList.getSrcInfo().getTepIp().stringValue() : "0";
+        String destTepIp = stateTunnelList.getDstInfo() != null
+                ? stateTunnelList.getDstInfo().getTepIp().stringValue() : "0";
         String rd;
-        BigInteger remoteDpnId = null;
+        Uint64 remoteDpnId = null;
         boolean isTepDeletedOnDpn = false;
 
         LOG.info("handleTunnelEventForDPN: Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
@@ -276,7 +289,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                 // 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;
+                String endpointIpForDPN;
                 try {
                     endpointIpForDPN = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
                 } catch (Exception e) {
@@ -305,7 +318,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                     + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
                             rpcResult.getErrors());
                 } else {
-                    srcDpninterfacelist = rpcResult.getResult().getInterfaces();
+                    srcDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
                 }
             } catch (Exception e) {
                 LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList for srcDpnid {}"
@@ -313,7 +326,8 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
             }
             // 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());
+                remoteDpnId = Uint64.valueOf(stateTunnelList.getDstInfo() != null
+                        ? stateTunnelList.getDstInfo().getTepDeviceId() : "0").intern();
                 try {
                     result = intfRpcService.getDpnInterfaceList(
                             new GetDpnInterfaceListInputBuilder().setDpid(remoteDpnId).build());
@@ -323,7 +337,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                         + " srcTepIP {} destTepIp {} returned with Errors {}", remoteDpnId, srcTepIp,
                                 destTepIp, rpcResult.getErrors());
                     } else {
-                        destDpninterfacelist = rpcResult.getResult().getInterfaces();
+                        destDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
                     }
                 } catch (Exception e) {
                     LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
@@ -336,20 +350,16 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
              * 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<Interfaces> interfacelistIter = srcDpninterfacelist.iterator();
-            Interfaces interfaces = null;
-            String intfName = null;
             List<Uuid> subnetList = new ArrayList<>();
-            Map<Long, String> vpnIdRdMap = new HashMap<>();
+            Map<Uint32, String> vpnIdRdMap = new HashMap<>();
             Set<String> listVpnName = new HashSet<>();
 
-            while (interfacelistIter.hasNext()) {
-                interfaces = interfacelistIter.next();
+            for (Interfaces interfaces : srcDpninterfacelist) {
                 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
                     LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
                     continue;
                 }
-                intfName = interfaces.getInterfaceName();
+                String intfName = interfaces.getInterfaceName();
                 VpnInterface vpnInterface =
                      vpnUtil.getConfiguredVpnInterface(intfName);
                 if (vpnInterface != null) {
@@ -365,14 +375,12 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
              * 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()) {
-                interfaces = interfacelistIter.next();
+            for (Interfaces interfaces : destDpninterfacelist) {
                 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
                     LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
                     continue;
                 }
-                intfName = interfaces.getInterfaceName();
+                String intfName = interfaces.getInterfaceName();
                 VpnInterface vpnInterface =
                         vpnUtil.getConfiguredVpnInterface(intfName);
                 if (vpnInterface != null) {
@@ -384,8 +392,8 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
             }
 
             //Iterate over the VpnId-to-Rd map.
-            for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
-                Long vpnId = entry.getKey();
+            for (Map.Entry<Uint32, String> entry : vpnIdRdMap.entrySet()) {
+                Uint32 vpnId = entry.getKey();
                 rd = entry.getValue();
                 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
                     && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
@@ -409,6 +417,24 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                     }
                 }
             }
+            /*
+             * Program the BGP routes of all the VPNs which have footprint on the source DPN.
+             *
+             * DC-GW LB groups are programmed in DJC Jobs, so DJC with same key is used here to make sure
+             * groups are programmed first, then only BGP routes are programmed.
+             */
+            jobCoordinator.enqueueJob(FibHelper.getJobKeyForDcGwLoadBalancingGroup(srcDpnId), () -> {
+                listVpnName.forEach(vpnName -> {
+                    Uint32 vpnId = vpnUtil.getVpnId(vpnName);
+                    final String vrfId = vpnIdRdMap.get(vpnId);
+                    if ((tunnelAction == TunnelAction.TUNNEL_EP_ADD)
+                            && (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
+                        fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, vrfId,
+                                srcTepIp, destTepIp);
+                    }
+                });
+                return Collections.emptyList();
+            },RETRY_COUNT);
         } catch (RuntimeException e) {
             LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
                     + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
@@ -418,19 +444,23 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList,
-                                            Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
+                                            Map<Uint32, String> vpnIdRdMap, TunnelAction tunnelAction,
                                             boolean isTepDeletedOnDpn, List<Uuid> subnetList,
                                             TunnelEventProcessingMethod method,
                                             VpnInterface cfgVpnInterface) {
         String rd;
         String intfName = cfgVpnInterface.getName();
-        final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
-        String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
-        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+        final Uint64 srcDpnId = Uint64.valueOf(stateTunnelList.getSrcInfo() != null
+                ? stateTunnelList.getSrcInfo().getTepDeviceId() : "0").intern();
+        String destTepIp = stateTunnelList.getDstInfo() != null ? stateTunnelList.getDstInfo().getTepIp().stringValue()
+                : null;
+        String srcTepIp = stateTunnelList.getSrcInfo() != null ? stateTunnelList.getSrcInfo().getTepIp().stringValue()
+                : null;
         int tunTypeVal = getTunnelType(stateTunnelList);
-        BigInteger remoteDpnId = null;
+        Uint64 remoteDpnId = null;
         if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-            remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
+            remoteDpnId = Uint64.valueOf(stateTunnelList.getDstInfo() != null
+                    ? stateTunnelList.getDstInfo().getTepDeviceId() : "0").intern();
         }
         if (cfgVpnInterface.getVpnInstanceNames() == null) {
             LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
@@ -468,7 +498,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                             }
                         }
                         //Populate the map for VpnId-to-Rd
-                        long vpnId = vpnUtil.getVpnId(vpnName);
+                        Uint32 vpnId = vpnUtil.getVpnId(vpnName);
                         rd = vpnUtil.getVpnRd(vpnName);
                         vpnIdRdMap.put(vpnId, rd);
                     }
@@ -478,10 +508,11 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                     if (opVpnInterface.isPresent()) {
                         VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
                         AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
-                        List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
-                                : Collections.emptyList();
+                        List<Adjacency> adjList =
+                            adjacencies != null && adjacencies.getAdjacency() != null ? adjacencies.getAdjacency()
+                                : emptyList();
                         String prefix = null;
-                        long vpnId = vpnUtil.getVpnId(vpnInterface.getVpnInstanceName());
+                        Uint32 vpnId = vpnUtil.getVpnId(vpnInterface.getVpnInstanceName());
                         if (vpnIdRdMap.containsKey(vpnId)) {
                             rd = vpnIdRdMap.get(vpnId);
                             LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {}"
@@ -489,7 +520,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                     destTepIp);
                             for (Adjacency adj : adjList) {
                                 prefix = adj.getIpAddress();
-                                long label = adj.getLabel();
+                                Uint32 label = adj.getLabel();
                                 if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
                                         && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
                                     fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp,
@@ -505,7 +536,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                     }
                 }
             }
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("handleTunnelEventForDPN: Failed to read data store for interface {} srcDpn {} srcTep {} "
                     + "dstTep {}", intfName, srcDpnId, srcTepIp, destTepIp);
         }
@@ -530,24 +561,26 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         @Override
         public List<ListenableFuture<Void>> call() {
             List<ListenableFuture<Void>> futures = new ArrayList<>(2);
-            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx ->
-                    futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx -> {
-                        if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
-                            vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList, confTx,
-                                    operTx);
-                        }
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx ->
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
+                    if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
+                        vpnInterfaceManager.updateVpnInterfaceOnTepAdd(vpnInterface, stateTunnelList, confTx, operTx);
+                    }
 
-                        if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
-                            vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList, confTx,
-                                    operTx);
-                        }
-                    }))));
+                    if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
+                        vpnInterfaceManager.updateVpnInterfaceOnTepDelete(vpnInterface, stateTunnelList, confTx,
+                            operTx);
+                    }
+                }))));
             return futures;
         }
     }
 
     private int getTunnelType(StateTunnelList stateTunnelList) {
         int tunTypeVal = 0;
+        if (stateTunnelList.getDstInfo() == null) {
+            return VpnConstants.ITMTunnelLocType.Invalid.getValue();
+        }
         if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
             tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
         } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
@@ -564,31 +597,14 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         return del.getTransportType() == TunnelTypeMplsOverGre.class;
     }
 
-    private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove) {
+    private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove, boolean isTunnelUp) {
         IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
-        String dcGwIpAddress = String.valueOf(dcGwIp.getValue());
-        List<String> availableDcGws = getDcGwIps();
-        BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
-        boolean isTunnelUp = TunnelOperStatus.Up == tunnelState.getOperState();
-        fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp,
+        String dcGwIpAddress = String.valueOf(dcGwIp.stringValue());
+        Uint64 dpId = Uint64.valueOf(tunnelState.getSrcInfo().getTepDeviceId()).intern();
+        fibManager.programDcGwLoadBalancingGroup(dpId, dcGwIpAddress, addOrRemove, isTunnelUp,
                 tunnelState.getTransportType());
     }
 
-    private List<String> getDcGwIps() {
-        InstanceIdentifier<DcGatewayIpList> dcGatewayIpListid =
-                InstanceIdentifier.builder(DcGatewayIpList.class).build();
-        DcGatewayIpList dcGatewayIpListConfig =
-                MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, dcGatewayIpListid).orNull();
-        if (dcGatewayIpListConfig == null) {
-            return Collections.EMPTY_LIST;
-        }
-        return dcGatewayIpListConfig.getDcGatewayIp()
-                .stream()
-                .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
-                .map(dcGwIp -> String.valueOf(dcGwIp.getIpAddress().getValue())).sorted()
-                .collect(toList());
-    }
-
     private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
         String ifaceName = stateTunnelList.getTunnelInterfaceName();
         if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {