NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / TunnelInterfaceStateListener.java
index fef94d9a83dd3b349eb65f4926a937944d91a85a..85d3dc0af934035d128bd329cacdfbd4408e4209 100644 (file)
@@ -8,43 +8,42 @@
 package org.opendaylight.netvirt.vpnmanager;
 
 import static java.util.Collections.emptyList;
-import static java.util.stream.Collectors.toList;
 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
-import static org.opendaylight.netvirt.vpnmanager.VpnUtil.requireNonNullElse;
 
-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.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.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.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;
@@ -63,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);
 
@@ -93,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
@@ -122,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;
@@ -131,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 :{}",
@@ -172,12 +173,13 @@ 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());
+        Uint64 srcDpnId = Uint64.valueOf(update.getSrcInfo().getTepDeviceId()).intern();
         String srcTepIp = update.getSrcInfo().getTepIp().stringValue();
         List<VpnInstanceOpDataEntry> vpnInstanceOpData = vpnUtil.getAllVpnInstanceOpData();
         if (vpnInstanceOpData == null) {
@@ -203,8 +205,13 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                 String prefix = destPrefix.getDestPrefix();
                                 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(opData.getVpnInstanceName(),
                                         prefix);
-                                synchronized (vpnPrefixKey.intern()) {
+                                // FIXME: separate out to somehow?
+                                final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnPrefixKey);
+                                lock.lock();
+                                try {
                                     fibManager.refreshVrfEntry(opData.getVrfId(), prefix);
+                                } finally {
+                                    lock.unlock();
                                 }
                             }
                         });
@@ -213,7 +220,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     }
 
     @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 = stateTunnelList.getSrcInfo().getTepIp().stringValue();
-        String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
+        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 {} ",
@@ -305,7 +318,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                     + " destTepIP {} returned with Errors {}", srcDpnId, srcTepIp, destTepIp,
                             rpcResult.getErrors());
                 } else {
-                    srcDpninterfacelist = requireNonNullElse(rpcResult.getResult().getInterfaces(), emptyList());
+                    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 = requireNonNullElse(rpcResult.getResult().getInterfaces(), emptyList());
+                        destDpninterfacelist = rpcResult.getResult().nonnullInterfaces();
                     }
                 } catch (Exception e) {
                     LOG.error("handleTunnelEventForDPN: Exception when querying for GetDpnInterfaceList"
@@ -337,7 +351,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
              * Update the adjacencies with the updated nexthop.
              */
             List<Uuid> subnetList = new ArrayList<>();
-            Map<Long, String> vpnIdRdMap = new HashMap<>();
+            Map<Uint32, String> vpnIdRdMap = new HashMap<>();
             Set<String> listVpnName = new HashSet<>();
 
             for (Interfaces interfaces : srcDpninterfacelist) {
@@ -378,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()) {
@@ -403,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);
@@ -412,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 = stateTunnelList.getDstInfo().getTepIp().stringValue();
-        String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
+        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);
@@ -462,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);
                     }
@@ -476,7 +512,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                             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 {}"
@@ -484,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,
@@ -500,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);
         }
@@ -542,6 +578,9 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
 
     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) {
@@ -558,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 = dcGwIp.stringValue();
-        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 emptyList();
-        }
-        return dcGatewayIpListConfig.getDcGatewayIp()
-                .stream()
-                .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
-                .map(dcGwIp -> dcGwIp.getIpAddress().stringValue()).sorted()
-                .collect(toList());
-    }
-
     private boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
         String ifaceName = stateTunnelList.getTunnelInterfaceName();
         if (getTunnelType(stateTunnelList) == VpnConstants.ITMTunnelLocType.Internal.getValue()) {