Migrate ListenableFutures.addErrorLogging() users
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / FloatingIPListener.java
index e1cc57e5c685b81138d5af03e50d0e242d14141e..020a685b79d7b4c61d9ce4a5f079833948d12109 100644 (file)
@@ -7,21 +7,25 @@
  */
 package org.opendaylight.netvirt.natservice.internal;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import javax.annotation.PostConstruct;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+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.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
@@ -29,6 +33,7 @@ import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetDestinationIp;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
@@ -43,9 +48,17 @@ import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
+import org.opendaylight.netvirt.natservice.api.NatSwitchCache;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 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.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
@@ -59,74 +72,80 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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 FloatingIPListener extends AsyncDataTreeChangeListenerBase<InternalToExternalPortMap, FloatingIPListener> {
+public class FloatingIPListener extends AbstractAsyncDataTreeChangeListener<InternalToExternalPortMap> {
     private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IMdsalApiManager mdsalManager;
     private final OdlInterfaceRpcService interfaceManager;
     private final FloatingIPHandler floatingIPHandler;
     private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
     private final JobCoordinator coordinator;
+    private final CentralizedSwitchScheduler centralizedSwitchScheduler;
+    private final NatSwitchCache natSwitchCache;
 
     @Inject
     public FloatingIPListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
                               final OdlInterfaceRpcService interfaceManager,
                               final FloatingIPHandler floatingIPHandler,
                               final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
-                              final JobCoordinator coordinator) {
-        super(InternalToExternalPortMap.class, FloatingIPListener.class);
+                              final JobCoordinator coordinator,
+                              final CentralizedSwitchScheduler centralizedSwitchScheduler,
+                              final NatSwitchCache natSwitchCache) {
+        super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(FloatingIpInfo.class)
+                .child(RouterPorts.class).child(Ports.class).child(InternalToExternalPortMap.class),
+                Executors.newListeningSingleThreadExecutor("FloatingIPListener", LOG));
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.mdsalManager = mdsalManager;
         this.interfaceManager = interfaceManager;
         this.floatingIPHandler = floatingIPHandler;
         this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
         this.coordinator = coordinator;
+        this.centralizedSwitchScheduler = centralizedSwitchScheduler;
+        this.natSwitchCache = natSwitchCache;
     }
 
-    @Override
-    @PostConstruct
     public void init() {
         LOG.info("{} init", getClass().getSimpleName());
-        registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
-    }
-
-    @Override
-    protected InstanceIdentifier<InternalToExternalPortMap> getWildCardPath() {
-        return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class)
-                .child(InternalToExternalPortMap.class);
     }
 
     @Override
-    protected FloatingIPListener getDataTreeChangeListener() {
-        return FloatingIPListener.this;
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
     }
 
     @Override
-    protected void add(final InstanceIdentifier<InternalToExternalPortMap> identifier,
+    public void add(final InstanceIdentifier<InternalToExternalPortMap> identifier,
                        final InternalToExternalPortMap mapping) {
-        LOG.trace("FloatingIPListener add ip mapping method - key: {} value: {}",mapping.getKey(), mapping);
+        LOG.trace("FloatingIPListener add ip mapping method - key: {} value: {}",mapping.key(), mapping);
         processFloatingIPAdd(identifier, mapping);
     }
 
     @Override
-    protected void remove(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap mapping) {
-        LOG.trace("FloatingIPListener remove ip mapping method - kkey: {} value: {}",mapping.getKey(), mapping);
+    public void remove(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap mapping) {
+        LOG.trace("FloatingIPListener remove ip mapping method - kkey: {} value: {}",mapping.key(), mapping);
         processFloatingIPDel(identifier, mapping);
     }
 
     @Override
-    protected void update(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap
+    public void update(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap
             original, InternalToExternalPortMap update) {
         LOG.trace("FloatingIPListener update ip mapping method - key: {}, original: {}, update: {}",
-                update.getKey(), original, update);
+                update.key(), original, update);
     }
 
-    private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, InternalToExternalPortMap mapping, long routerId, long
-            associatedVpn) {
+    @Nullable
+    private FlowEntity buildPreDNATFlowEntity(Uint64 dpId, InternalToExternalPortMap mapping, Uint32 routerId,
+                                              Uint32 associatedVpn) {
         String externalIp = mapping.getExternalIp();
         Uuid floatingIpId = mapping.getExternalId();
         //Get the FIP MAC address for DNAT
@@ -137,7 +156,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
             return null;
         }
         LOG.debug("buildPreDNATFlowEntity : Bulding DNAT Flow entity for ip {} ", externalIp);
-        long segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
+        Uint32 segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
         LOG.debug("buildPreDNATFlowEntity : Segment id {} in build preDNAT Flow", segmentId);
 
         List<MatchInfo> matches = new ArrayList<>();
@@ -154,7 +173,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         actionsInfos.add(new ActionSetDestinationIp(internalIp, "32"));
 
         List<InstructionInfo> instructions = new ArrayList<>();
-        instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(segmentId),
+        instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
                 MetaDataUtil.METADATA_MASK_VRFID));
         instructions.add(new InstructionApplyActions(actionsInfos));
         instructions.add(new InstructionGotoTable(NwConstants.DNAT_TABLE));
@@ -168,16 +187,17 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         return flowEntity;
     }
 
-    private FlowEntity buildDNATFlowEntity(BigInteger dpId, InternalToExternalPortMap mapping, long routerId, long
+    private FlowEntity buildDNATFlowEntity(Uint64 dpId, InternalToExternalPortMap mapping, Uint32 routerId, Uint32
             associatedVpn) {
         String externalIp = mapping.getExternalIp();
         LOG.info("buildDNATFlowEntity : Bulding DNAT Flow entity for ip {} ", externalIp);
 
-        long segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
+        Uint32 segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
         LOG.debug("buildDNATFlowEntity : Segment id {} in build DNAT", segmentId);
 
         List<MatchInfo> matches = new ArrayList<>();
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         matches.add(MatchEthernetType.IPV4);
         String internalIp = mapping.getInternalIp();
@@ -187,8 +207,9 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 //        actionsInfos.add(new ActionSetDestinationIp(internalIp, "32"));
 
         List<InstructionInfo> instructions = new ArrayList<>();
-//        instructions.add(new InstructionWriteMetadata(BigInteger.valueOf
+//        instructions.add(new InstructionWriteMetadata(Uint64.valueOf
 //                (routerId), MetaDataUtil.METADATA_MASK_VRFID));
+        actionsInfos.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
         actionsInfos.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
         instructions.add(new InstructionApplyActions(actionsInfos));
         //instructions.add(new InstructionGotoTable(NatConstants.L3_FIB_TABLE));
@@ -203,12 +224,12 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 
     }
 
-    private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long
-            routerId, long associatedVpn) {
+    private FlowEntity buildPreSNATFlowEntity(Uint64 dpId, String internalIp, String externalIp, Uint32 vpnId, Uint32
+            routerId, Uint32 associatedVpn) {
 
         LOG.debug("buildPreSNATFlowEntity : Building PSNAT Flow entity for ip {} ", internalIp);
 
-        long segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
+        Uint32 segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
 
         LOG.debug("buildPreSNATFlowEntity : Segment id {} in build preSNAT flow", segmentId);
 
@@ -217,14 +238,16 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 
         matches.add(new MatchIpv4Source(internalIp, "32"));
 
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<ActionInfo> actionsInfos = new ArrayList<>();
         actionsInfos.add(new ActionSetSourceIp(externalIp, "32"));
 
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(
-                new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
+                new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
+                        MetaDataUtil.METADATA_MASK_VRFID));
         instructions.add(new InstructionApplyActions(actionsInfos));
         instructions.add(new InstructionGotoTable(NwConstants.SNAT_TABLE));
 
@@ -237,7 +260,8 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         return flowEntity;
     }
 
-    private FlowEntity buildSNATFlowEntity(BigInteger dpId, InternalToExternalPortMap mapping, long vpnId, Uuid
+    @Nullable
+    private FlowEntity buildSNATFlowEntity(Uint64 dpId, InternalToExternalPortMap mapping, Uint32 vpnId, Uuid
             externalNetworkId) {
         String internalIp = mapping.getInternalIp();
         LOG.debug("buildSNATFlowEntity : Building SNAT Flow entity for ip {} ", internalIp);
@@ -249,12 +273,14 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         }
 
         List<MatchInfo> matches = new ArrayList<>();
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
         matches.add(MatchEthernetType.IPV4);
         String externalIp = mapping.getExternalIp();
         matches.add(new MatchIpv4Source(externalIp, "32"));
 
         List<ActionInfo> actionsInfo = new ArrayList<>();
+        actionsInfo.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
         Uuid floatingIpId = mapping.getExternalId();
         String macAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
         if (macAddress != null) {
@@ -277,56 +303,59 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 
     }
 
-    private void createDNATTblEntry(BigInteger dpnId, InternalToExternalPortMap mapping, long routerId, long vpnId,
-                                    long associatedVpnId, WriteTransaction writeFlowInvTx) {
+    private void createDNATTblEntry(Uint64 dpnId, InternalToExternalPortMap mapping, Uint32 routerId,
+                                    Uint32 associatedVpnId, TypedReadWriteTransaction<Configuration> confTx) {
         FlowEntity preFlowEntity = buildPreDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
         if (preFlowEntity == null) {
             LOG.error("createDNATTblEntry : Flow entity received as NULL. "
                     + "Cannot proceed with installation of Pre-DNAT flow table {} --> table {} on DpnId {}",
                     NwConstants.PDNAT_TABLE, NwConstants.DNAT_TABLE, dpnId);
         } else {
-            mdsalManager.addFlowToTx(preFlowEntity, writeFlowInvTx);
+            mdsalManager.addFlow(confTx, preFlowEntity);
             FlowEntity flowEntity = buildDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
             if (flowEntity != null) {
-                mdsalManager.addFlowToTx(flowEntity, writeFlowInvTx);
+                mdsalManager.addFlow(confTx, flowEntity);
             }
         }
     }
 
-    private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId,
-                                    WriteTransaction removeFlowInvTx) {
+    private void removeDNATTblEntry(Uint64 dpnId, String internalIp, String externalIp, Uint32 routerId,
+            TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
         FlowEntity preFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, externalIp, routerId);
-        mdsalManager.removeFlowToTx(preFlowEntity, removeFlowInvTx);
+        mdsalManager.removeFlow(confTx, preFlowEntity);
 
         FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, routerId);
         if (flowEntity != null) {
-            mdsalManager.removeFlowToTx(flowEntity, removeFlowInvTx);
+            mdsalManager.removeFlow(confTx, flowEntity);
         }
     }
 
-    private void createSNATTblEntry(BigInteger dpnId, InternalToExternalPortMap mapping, long vpnId, long routerId,
-                                    long associatedVpnId, Uuid externalNetworkId, WriteTransaction writeFlowInvTx) {
+    private void createSNATTblEntry(Uint64 dpnId, InternalToExternalPortMap mapping, Uint32 vpnId, Uint32 routerId,
+                                    Uint32 associatedVpnId, Uuid externalNetworkId,
+                                    TypedReadWriteTransaction<Configuration> confTx) {
         FlowEntity preFlowEntity = buildPreSNATFlowEntity(dpnId, mapping.getInternalIp(), mapping.getExternalIp(),
             vpnId, routerId, associatedVpnId);
-        mdsalManager.addFlowToTx(preFlowEntity, writeFlowInvTx);
+        mdsalManager.addFlow(confTx, preFlowEntity);
 
         FlowEntity flowEntity = buildSNATFlowEntity(dpnId, mapping, vpnId, externalNetworkId);
         if (flowEntity != null) {
-            mdsalManager.addFlowToTx(flowEntity, writeFlowInvTx);
+            mdsalManager.addFlow(confTx, flowEntity);
         }
     }
 
-    private void removeSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId,
-                                    WriteTransaction removeFlowInvTx) {
+    private void removeSNATTblEntry(Uint64 dpnId, String internalIp, String externalIp, Uint32 routerId, Uint32 vpnId,
+                                    TypedReadWriteTransaction<Configuration> removeFlowInvTx)
+            throws ExecutionException, InterruptedException {
         FlowEntity preFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId);
-        mdsalManager.removeFlowToTx(preFlowEntity, removeFlowInvTx);
+        mdsalManager.removeFlow(removeFlowInvTx, preFlowEntity);
 
         FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, externalIp, vpnId);
         if (flowEntity != null) {
-            mdsalManager.removeFlowToTx(flowEntity, removeFlowInvTx);
+            mdsalManager.removeFlow(removeFlowInvTx, flowEntity);
         }
     }
 
+    @Nullable
     private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> portIid,
                                  LogicalDatastoreType dataStoreType) {
         Optional<RouterPorts> rtrPort =
@@ -337,19 +366,10 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
             return null;
         }
 
-        Uuid extNwId = rtrPort.get().getExternalNetworkId();
-        return extNwId;
+        return rtrPort.get().getExternalNetworkId();
     }
 
-    private long getVpnId(Uuid extNwId, Uuid floatingIpExternalId) {
-        Uuid subnetId = NatUtil.getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpExternalId);
-        if (subnetId != null) {
-            long vpnId = NatUtil.getVpnId(dataBroker, subnetId.getValue());
-            if (vpnId != NatConstants.INVALID_ID) {
-                LOG.debug("getVpnId : Got vpnId {} for floatingIpExternalId {}", vpnId, floatingIpExternalId);
-                return vpnId;
-            }
-        }
+    private Uuid getVpnUuid(Uuid extNwId, Uuid floatingIpExternalId) {
 
         InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class,
                 new NetworksKey(extNwId)).build();
@@ -358,55 +378,60 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
                         LogicalDatastoreType.CONFIGURATION, nwId);
         if (!nw.isPresent()) {
             LOG.error("getVpnId : Unable to read external network for {}", extNwId);
-            return NatConstants.INVALID_ID;
+            return null;
+        }
+
+        ProviderTypes providerType = nw.get().getProviderNetworkType();
+        if (providerType == ProviderTypes.FLAT || providerType == ProviderTypes.VLAN) {
+            Uuid subnetId = NatUtil
+                .getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpExternalId);
+            if (subnetId != null) {
+                return subnetId;
+            }
         }
 
         Uuid vpnUuid = nw.get().getVpnid();
         if (vpnUuid == null) {
             LOG.error("getVpnId : Unable to read vpn from External network: {}", extNwId);
-            return NatConstants.INVALID_ID;
+            return null;
         }
+        return vpnUuid;
+    }
 
+    private Uint32 getVpnId(Uuid extNwId, Uuid floatingIpExternalId) {
+        Uuid vpnUuid = getVpnUuid(extNwId, floatingIpExternalId);
         //Get the id using the VPN UUID (also vpn instance name)
-        return NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+        return vpnUuid != null ? NatUtil.getVpnId(dataBroker, vpnUuid.getValue()) : NatConstants.INVALID_ID;
     }
 
     private void processFloatingIPAdd(final InstanceIdentifier<InternalToExternalPortMap> identifier,
                                       final InternalToExternalPortMap mapping) {
-        LOG.trace("processFloatingIPAdd key: {}, value: {}", mapping.getKey(), mapping);
+        LOG.trace("processFloatingIPAdd key: {}, value: {}", mapping.key(), mapping);
 
         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
         String interfaceName = pKey.getPortName();
 
         InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
-        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.getKey(), () -> {
-            WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            createNATFlowEntries(interfaceName, mapping, portIid, routerId, writeFlowInvTx);
-            //final submit call for writeFlowInvTx
-            futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-            return futures;
-        }, NatConstants.NAT_DJC_MAX_RETRIES);
+        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.key(), () -> Collections.singletonList(
+                txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                    tx -> createNATFlowEntries(interfaceName, mapping, portIid, routerId, null, tx))),
+                NatConstants.NAT_DJC_MAX_RETRIES);
     }
 
     private void processFloatingIPDel(final InstanceIdentifier<InternalToExternalPortMap> identifier,
                                       final InternalToExternalPortMap mapping) {
-        LOG.trace("processFloatingIPDel : key: {}, value: {}", mapping.getKey(), mapping);
+        LOG.trace("processFloatingIPDel : key: {}, value: {}", mapping.key(), mapping);
 
         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
         String interfaceName = pKey.getPortName();
 
         InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
-        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.getKey(), () -> {
-            WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            removeNATFlowEntries(interfaceName, mapping, portIid, routerId, null, removeFlowInvTx);
-            //final submit call for removeFlowInvTx
-            futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
-            return futures;
-        }, NatConstants.NAT_DJC_MAX_RETRIES);
+        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.key(), () -> Collections.singletonList(
+                txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                    tx -> removeNATFlowEntries(interfaceName, mapping, portIid, routerId, null, tx))),
+                NatConstants.NAT_DJC_MAX_RETRIES);
     }
 
     private InetAddress getInetAddress(String ipAddr) {
@@ -423,24 +448,68 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         return getInetAddress(mapping.getInternalIp()) != null && getInetAddress(mapping.getExternalIp()) != null;
     }
 
+    private Uint64 getAssociatedDpnWithExternalInterface(final String routerName, Uuid extNwId, Uint64 dpnId,
+            String interfaceName) {
+        //Get the DPN on which this interface resides
+        if (dpnId == null) {
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
+                .state.Interface interfaceState = NatUtil.getInterfaceStateFromOperDS(dataBroker, interfaceName);
+            if (interfaceState != null) {
+                dpnId = NatUtil.getDpIdFromInterface(interfaceState);
+            }
+        }
+        Uint64 updatedDpnId = dpnId;
+        if (updatedDpnId != null && updatedDpnId.equals(Uint64.ZERO)) {
+            LOG.debug("getAssociatedDpnWithExternalInterface : The interface {} is not associated with any dpn",
+                    interfaceName);
+            return updatedDpnId;
+        }
+        ProviderTypes providerType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNwId);
+        if (providerType == null) {
+            LOG.warn("getAssociatedDpnWithExternalInterface : Provider Network Type for router {} and"
+                    + " externalNetwork {} is missing.", routerName, extNwId);
+            return updatedDpnId;
+        }
+
+        // For FLAT and VLAN provider networks, we have to ensure that dpn hosting the VM has connectivity
+        // to External Network via provider_mappings. In case the dpn does not have the provider mappings,
+        // traffic from the VM has to be forwarded to the NAPT Switch (which is scheduled based on the provider
+        // mappings) and then sent out on the external Network.
+        if (providerType == ProviderTypes.FLAT || providerType == ProviderTypes.VLAN) {
+            String providerNet = NatUtil.getElanInstancePhysicalNetwok(extNwId.getValue(), dataBroker);
+            boolean isDpnConnected = natSwitchCache.isSwitchConnectedToExternal(updatedDpnId, providerNet);
+            if (!isDpnConnected) {
+                updatedDpnId = centralizedSwitchScheduler.getCentralizedSwitch(routerName);
+            }
+        }
+        return updatedDpnId;
+    }
+
     void createNATFlowEntries(String interfaceName, final InternalToExternalPortMap mapping,
-                              final InstanceIdentifier<RouterPorts> portIid, final String routerName,
-                              WriteTransaction writeFlowInvTx) {
+            final InstanceIdentifier<RouterPorts> portIid, final String routerName, @Nullable Uint64 dpnId,
+            TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
         if (!validateIpMapping(mapping)) {
             LOG.error("createNATFlowEntries : Not a valid ip addresses in the mapping {}", mapping);
             return;
         }
 
-        //Get the DPN on which this interface resides
-        BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
+        Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.CONFIGURATION);
+        if (extNwId == null) {
+            LOG.error("createNATFlowEntries : External network associated with interface {} could not be retrieved",
+                    interfaceName);
+            return;
+        }
 
-        if (dpnId.equals(BigInteger.ZERO)) {
+        // For Overlay Networks, get the DPN on which this interface resides.
+        // For FLAT/VLAN Networks, get the DPN with provider_mappings for external network.
+        dpnId = getAssociatedDpnWithExternalInterface(routerName, extNwId, dpnId, interfaceName);
+        if (dpnId == null || dpnId.equals(Uint64.ZERO)) {
             LOG.warn("createNATFlowEntries : No DPN for interface {}. NAT flow entries for ip mapping {} will "
-                + "not be installed", interfaceName, mapping);
+                    + "not be installed", interfaceName, mapping);
             return;
         }
 
-        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         if (routerId == NatConstants.INVALID_ID) {
             LOG.error("createNATFlowEntries : Could not retrieve router id for {} to create NAT Flow entries",
                     routerName);
@@ -449,7 +518,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         //Check if the router to vpn association is present
         //long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
         Uuid associatedVpn = NatUtil.getVpnForRouter(dataBroker, routerName);
-        long associatedVpnId = NatConstants.INVALID_ID;
+        Uint32 associatedVpnId = NatConstants.INVALID_ID;
         if (associatedVpn == null) {
             LOG.debug("createNATFlowEntries : Router {} is not assicated with any BGP VPN instance", routerName);
         } else {
@@ -460,14 +529,16 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
             //routerId = associatedVpnId;
         }
 
-        Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.CONFIGURATION);
-        if (extNwId == null) {
-            LOG.error("createNATFlowEntries : External network associated with interface {} could not be retrieved",
-                interfaceName);
+        Uuid vpnUuid = getVpnUuid(extNwId, mapping.getExternalId());
+
+        LOG.trace("createNATFlowEntries : vpnUuid {} for External Network {}", vpnUuid, extNwId);
+        if (vpnUuid == null) {
+            LOG.error("createNATFlowEntries : No VPN associated with Ext nw {}. Unable to create SNAT table entry "
+                    + "for fixed ip {}", extNwId, mapping.getInternalIp());
             return;
         }
-        long vpnId = getVpnId(extNwId, mapping.getExternalId());
-        if (vpnId < 0) {
+        VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnUuid.getValue());
+        if (vpnInstance == null || vpnInstance.getVpnId() == null) {
             LOG.error("createNATFlowEntries : No VPN associated with Ext nw {}. Unable to create SNAT table entry "
                     + "for fixed ip {}", extNwId, mapping.getInternalIp());
             return;
@@ -475,25 +546,28 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         //Install the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
         if (!isSnatEnabled) {
-            addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, writeFlowInvTx, true);
+            addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, true);
         }
         //Create the DNAT and SNAT table entries
-        createDNATTblEntry(dpnId, mapping, routerId, vpnId, associatedVpnId, writeFlowInvTx);
-        createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, extNwId, writeFlowInvTx);
-        floatingIPHandler.onAddFloatingIp(dpnId, routerName, routerId, extNwId, interfaceName, mapping, writeFlowInvTx);
-    }
-
-    void createNATFlowEntries(BigInteger dpnId,  String interfaceName, String routerName, Uuid externalNetworkId,
-                              InternalToExternalPortMap mapping, WriteTransaction writeFlowInvTx) {
-        String internalIp = mapping.getInternalIp();
-        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 vpnId = vpnInstance.getVpnId();
+        String vrfId = vpnInstance.getVrfId();
+        createDNATTblEntry(dpnId, mapping, routerId, associatedVpnId, confTx);
+        createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, extNwId, confTx);
+        floatingIPHandler.onAddFloatingIp(dpnId, routerName, routerId, extNwId, interfaceName, mapping,
+            vrfId, confTx);
+    }
+
+    void createNATFlowEntries(Uint64 dpnId,  String interfaceName, String routerName, Uuid externalNetworkId,
+                              InternalToExternalPortMap mapping, TypedReadWriteTransaction<Configuration> confTx)
+            throws ExecutionException, InterruptedException {
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         if (routerId == NatConstants.INVALID_ID) {
             LOG.error("createNATFlowEntries : Could not retrieve router id for {} to create NAT Flow entries",
                     routerName);
             return;
         }
         //Check if the router to vpn association is present
-        long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
+        Uint32 associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
         if (associatedVpnId == NatConstants.INVALID_ID) {
             LOG.debug("createNATFlowEntries : Router {} is not assicated with any BGP VPN instance", routerName);
         } else {
@@ -502,40 +576,51 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
             //routerId = associatedVpnId;
         }
 
-        long vpnId = getVpnId(externalNetworkId, mapping.getExternalId());
-        if (vpnId < 0) {
-            LOG.error("createNATFlowEntries : Unable to create SNAT table entry for fixed ip {}", internalIp);
+        Uuid vpnUuid = getVpnUuid(externalNetworkId, mapping.getExternalId());
+        LOG.trace("createNATFlowEntries : vpnUuid {} for External Network {}", vpnUuid, externalNetworkId);
+        if (vpnUuid == null) {
+            LOG.error("createNATFlowEntries : No vpnUuid associated with Ext nw {}. Unable to create SNAT table entry"
+                    + " for fixed ip {}", externalNetworkId, mapping.getInternalIp());
+            return;
+        }
+        VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnUuid.getValue());
+        if (vpnInstance == null || vpnInstance.getVpnId() == null) {
+            LOG.error("createNATFlowEntries: VpnInstance associated with Ext nw {}. Unable to create SNAT table entry"
+                    + " for fixed ip {}",externalNetworkId, mapping.getInternalIp());
             return;
         }
         //Install the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
         if (!isSnatEnabled) {
-            addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, writeFlowInvTx, true);
+            addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, true);
         }
         //Create the DNAT and SNAT table entries
-        createDNATTblEntry(dpnId, mapping, routerId, vpnId, associatedVpnId, writeFlowInvTx);
-        createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, externalNetworkId, writeFlowInvTx);
+        Uint32 vpnId = vpnInstance.getVpnId();
+        String vrfId = vpnInstance.getVrfId();
+        createDNATTblEntry(dpnId, mapping, routerId, associatedVpnId, confTx);
+        createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, externalNetworkId, confTx);
         floatingIPHandler.onAddFloatingIp(dpnId, routerName, routerId, externalNetworkId, interfaceName, mapping,
-                writeFlowInvTx);
+            vrfId, confTx);
     }
 
-    void createNATOnlyFlowEntries(BigInteger dpnId, String routerName, String associatedVPN,
-                                  Uuid externalNetworkId, InternalToExternalPortMap mapping) {
-        String internalIp = mapping.getInternalIp();
+    void createNATOnlyFlowEntries(Uint64 dpnId, String routerName, @Nullable String associatedVPN,
+                                  Uuid externalNetworkId, InternalToExternalPortMap mapping)
+            throws ExecutionException, InterruptedException {
         //String segmentId = associatedVPN == null ? routerName : associatedVPN;
         LOG.debug("createNATOnlyFlowEntries : Retrieving vpn id for VPN {} to proceed with create NAT Flows",
                 routerName);
-        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         if (routerId == NatConstants.INVALID_ID) {
             LOG.error("createNATOnlyFlowEntries : Could not retrieve vpn id for {} to create NAT Flow entries",
                     routerName);
             return;
         }
-        long associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVPN);
+        Uint32 associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVPN);
         LOG.debug("createNATOnlyFlowEntries : Associated VPN Id {} for router {}", associatedVpnId, routerName);
-        long vpnId = getVpnId(externalNetworkId, mapping.getExternalId());
-        if (vpnId < 0) {
-            LOG.error("createNATOnlyFlowEntries : Unable to create SNAT table entry for fixed ip {}", internalIp);
+        Uint32 vpnId = getVpnId(externalNetworkId, mapping.getExternalId());
+        if (vpnId.longValue() < 0) {
+            LOG.error("createNATOnlyFlowEntries : Unable to create SNAT table entry for fixed ip {}",
+                    mapping.getInternalIp());
             return;
         }
         //Install the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
@@ -551,7 +636,8 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         mdsalManager.installFlow(flowEntity);
 
         String externalIp = mapping.getExternalIp();
-        preFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
+        preFlowEntity = buildPreSNATFlowEntity(dpnId, mapping.getInternalIp(), externalIp, vpnId,
+                routerId, associatedVpnId);
         mdsalManager.installFlow(preFlowEntity);
 
         flowEntity = buildSNATFlowEntity(dpnId, mapping, vpnId, externalNetworkId);
@@ -562,42 +648,53 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
     }
 
     void removeNATFlowEntries(String interfaceName, final InternalToExternalPortMap mapping,
-                              InstanceIdentifier<RouterPorts> portIid, final String routerName, BigInteger dpnId,
-                              WriteTransaction removeFlowInvTx) {
-        String internalIp = mapping.getInternalIp();
-        String externalIp = mapping.getExternalIp();
-        //Get the DPN on which this interface resides
+            InstanceIdentifier<RouterPorts> portIid, final String routerName, @Nullable Uint64 dpnId,
+            TypedReadWriteTransaction<Configuration> removeFlowInvTx) throws ExecutionException, InterruptedException {
+        Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.OPERATIONAL);
+        if (extNwId == null) {
+            LOG.error("removeNATFlowEntries : External network associated with interface {} could not be retrieved",
+                    interfaceName);
+            return;
+        }
+
+        // For Overlay Networks, get the DPN on which this interface resides.
+        // For FLAT/VLAN Networks, get the DPN with provider_mappings for external network.
         if (dpnId == null) {
-            dpnId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
-            if (dpnId.equals(BigInteger.ZERO)) {
+            dpnId = getAssociatedDpnWithExternalInterface(routerName, extNwId,
+                    NatUtil.getDpnForInterface(interfaceManager, interfaceName), interfaceName);
+            if (dpnId == null || dpnId.equals(Uint64.ZERO)) {
                 LOG.warn("removeNATFlowEntries: Abort processing Floating ip configuration. No DPN for port: {}",
                         interfaceName);
                 return;
             }
         }
 
-        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         if (routerId == NatConstants.INVALID_ID) {
             LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries",
                     routerName);
             return;
         }
 
+        String internalIp = mapping.getInternalIp();
+        String externalIp = mapping.getExternalIp();
+
         //Delete the DNAT and SNAT table entries
         removeDNATTblEntry(dpnId, internalIp, externalIp, routerId, removeFlowInvTx);
-
-        Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.OPERATIONAL);
-        if (extNwId == null) {
-            LOG.error("removeNATFlowEntries : External network associated with interface {} could not be retrieved",
-                interfaceName);
+        Uuid vpnUuid = getVpnUuid(extNwId, mapping.getExternalId());
+        if (vpnUuid == null) {
+            LOG.error("removeNATFlowEntries : No VPN associated with Ext nw {}. Unable to remove SNAT table entry "
+                    + "for fixed ip {}", extNwId, mapping.getInternalIp());
             return;
         }
-        long vpnId = getVpnId(extNwId, mapping.getExternalId());
-        if (vpnId < 0) {
-            LOG.error("removeNATFlowEntries : No VPN associated with ext nw {}. Unable to delete SNAT table "
-                + "entry for fixed ip {}", extNwId, internalIp);
+        VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnUuid.getValue());
+        if (vpnInstance == null || vpnInstance.getVpnId() == null) {
+            LOG.error("removeNATFlowEntries: No VPN associated with Ext nw {}. Unable to create SNAT table entry "
+                + "for fixed ip {}", extNwId, mapping.getInternalIp());
             return;
         }
+        Uint32 vpnId = vpnInstance.getVpnId();
+        String vrfId = vpnInstance.getVrfId();
         removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, removeFlowInvTx);
         //Remove the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
@@ -611,45 +708,49 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         }
         if (provType == ProviderTypes.VXLAN) {
             floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, routerId, extNwId, mapping,
-                    NatConstants.DEFAULT_L3VNI_VALUE, removeFlowInvTx);
-            removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
+                    NatConstants.DEFAULT_L3VNI_VALUE, vrfId, removeFlowInvTx);
+            removeOperationalDS(routerName, interfaceName, internalIp);
             return;
         }
-        long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
-        if (label < 0) {
+        Uint32 label = getOperationalIpMapping(routerName, interfaceName, internalIp);
+        if (label.longValue() < 0) {
             LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}",
                     internalIp, routerId);
             return;
         }
-        floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, routerId, extNwId, mapping, (int) label,
+        floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, routerId, extNwId, mapping, label, vrfId,
                 removeFlowInvTx);
-        removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
+        removeOperationalDS(routerName, interfaceName, internalIp);
     }
 
-    void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName,
-                              InternalToExternalPortMap mapping, WriteTransaction removeFlowInvTx) {
+    void removeNATFlowEntries(Uint64 dpnId, String interfaceName, String vpnName, String routerName,
+                              InternalToExternalPortMap mapping, TypedReadWriteTransaction<Configuration> confTx)
+            throws ExecutionException, InterruptedException {
         String internalIp = mapping.getInternalIp();
         String externalIp = mapping.getExternalIp();
-        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         if (routerId == NatConstants.INVALID_ID) {
             LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries",
                     routerName);
             return;
         }
 
-        long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
-        if (vpnId == NatConstants.INVALID_ID) {
-            LOG.warn("removeNATFlowEntries : VPN Id not found for {} to remove NAT flow entries {}",
-                    vpnName, internalIp);
+        VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnName);
+        if (vpnInstance == null || vpnInstance.getVpnId() == null) {
+            LOG.warn("removeNATFlowEntries: VPN Id not found for {} to remove NAT flow entries {}",
+                vpnName, internalIp);
+            return;
         }
+        Uint32 vpnId = vpnInstance.getVpnId();
+        String vrfId = vpnInstance.getVrfId();
 
         //Delete the DNAT and SNAT table entries
-        removeDNATTblEntry(dpnId, internalIp, externalIp, routerId, removeFlowInvTx);
-        removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, removeFlowInvTx);
+        removeDNATTblEntry(dpnId, internalIp, externalIp, routerId, confTx);
+        removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, confTx);
         //Remove the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
         if (!isSnatEnabled) {
-            addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, removeFlowInvTx, false);
+            addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, false);
         }
         Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker,routerName);
         ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, externalNetworkId);
@@ -658,30 +759,36 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
             return;
         }
         if (provType == ProviderTypes.VXLAN) {
-            floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE,
-                    removeFlowInvTx, provType);
-            removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
+            floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE, vrfId,
+                    confTx, provType);
+            removeOperationalDS(routerName, interfaceName, internalIp);
             return;
         }
-        long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
-        if (label < 0) {
+        Uint32 label = getOperationalIpMapping(routerName, interfaceName, internalIp);
+        if (label != null && label.longValue() < 0) {
             LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}",
                     internalIp, routerId);
             return;
         }
-        floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, label, removeFlowInvTx, provType);
-        removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
+        if (provType == ProviderTypes.VXLAN) {
+            floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE, vrfId,
+                confTx, provType);
+            removeOperationalDS(routerName, interfaceName, internalIp);
+            return;
+        }
+        floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, label, vrfId, confTx, provType);
+        removeOperationalDS(routerName, interfaceName, internalIp);
     }
 
-    protected long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
+    protected Uint32 getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
         InstanceIdentifier<InternalToExternalPortMap> intExtPortMapIdentifier =
             NatUtil.getIntExtPortMapIdentifier(routerId, interfaceName, internalIp);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
-                LogicalDatastoreType.OPERATIONAL, intExtPortMapIdentifier).toJavaUtil().map(
+                LogicalDatastoreType.OPERATIONAL, intExtPortMapIdentifier).map(
                 InternalToExternalPortMap::getLabel).orElse(NatConstants.INVALID_ID);
     }
 
-    static void updateOperationalDS(DataBroker dataBroker, String routerId, String interfaceName, long label,
+    static void updateOperationalDS(DataBroker dataBroker, String routerId, String interfaceName, Uint32 label,
                                     String internalIp, String externalIp) {
 
         LOG.info("updateOperationalDS : Updating operational DS for floating ip config : {} with label {}",
@@ -690,7 +797,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         Optional<Ports> optPorts =
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                         LogicalDatastoreType.OPERATIONAL, portsId);
-        InternalToExternalPortMap intExtPortMap = new InternalToExternalPortMapBuilder().setKey(new
+        InternalToExternalPortMap intExtPortMap = new InternalToExternalPortMapBuilder().withKey(new
                 InternalToExternalPortMapKey(internalIp)).setInternalIp(internalIp).setExternalIp(externalIp)
                 .setLabel(label).build();
         if (optPorts.isPresent()) {
@@ -703,20 +810,20 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
                     interfaceName, internalIp);
             List<InternalToExternalPortMap> intExtPortMapList = new ArrayList<>();
             intExtPortMapList.add(intExtPortMap);
-            Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName)
+            Ports ports = new PortsBuilder().withKey(new PortsKey(interfaceName)).setPortName(interfaceName)
                     .setInternalToExternalPortMap(intExtPortMapList).build();
             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
         }
     }
 
-    void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
+    void removeOperationalDS(String routerId, String interfaceName, String internalIp) {
         LOG.info("removeOperationalDS : Remove operational DS for floating ip config: {}", internalIp);
         InstanceIdentifier<InternalToExternalPortMap> intExtPortMapId = NatUtil.getIntExtPortMapIdentifier(routerId,
                 interfaceName, internalIp);
         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, intExtPortMapId);
     }
 
-    private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String externalIp, long routerId) {
+    private FlowEntity buildPreDNATDeleteFlowEntity(Uint64 dpId, String externalIp, Uint32 routerId) {
 
         LOG.info("buildPreDNATDeleteFlowEntity : Bulding Delete DNAT Flow entity for ip {} ", externalIp);
 
@@ -731,7 +838,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 
 
 
-    private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId) {
+    private FlowEntity buildDNATDeleteFlowEntity(Uint64 dpId, String internalIp, Uint32 routerId) {
 
         LOG.info("buildDNATDeleteFlowEntity : Bulding Delete DNAT Flow entity for ip {} ", internalIp);
 
@@ -745,7 +852,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 
     }
 
-    private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId) {
+    private FlowEntity buildPreSNATDeleteFlowEntity(Uint64 dpId, String internalIp, Uint32 routerId) {
 
         LOG.info("buildPreSNATDeleteFlowEntity : Building Delete PSNAT Flow entity for ip {} ", internalIp);
 
@@ -757,7 +864,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         return flowEntity;
     }
 
-    private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String externalIp, long routerId) {
+    private FlowEntity buildSNATDeleteFlowEntity(Uint64 dpId, String externalIp, Uint32 routerId) {
 
         LOG.info("buildSNATDeleteFlowEntity : Building Delete SNAT Flow entity for ip {} ", externalIp);
 
@@ -770,15 +877,17 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         return flowEntity;
     }
 
-    private void addOrDelDefaultFibRouteForDnat(BigInteger dpnId, String routerName,
-                                                long routerId, WriteTransaction tx, boolean create) {
-        Boolean wrTxPresent = true;
-        if (tx == null) {
-            wrTxPresent = false;
-            tx = dataBroker.newWriteOnlyTransaction();
+    private void addOrDelDefaultFibRouteForDnat(Uint64 dpnId, String routerName, Uint32 routerId,
+            @Nullable TypedReadWriteTransaction<Configuration> confTx, boolean create)
+            throws ExecutionException, InterruptedException {
+        if (confTx == null) {
+            LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                newTx -> addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, newTx, create)), LOG,
+                "Error handling default FIB route for DNAT");
+            return;
         }
         //Check if the router to bgp-vpn association is present
-        long associatedVpnId = NatConstants.INVALID_ID;
+        Uint32 associatedVpnId = NatConstants.INVALID_ID;
         Uuid associatedVpn = NatUtil.getVpnForRouter(dataBroker, routerName);
         if (associatedVpn != null) {
             associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVpn.getValue());
@@ -787,25 +896,22 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
             if (associatedVpnId != NatConstants.INVALID_ID) {
                 LOG.debug("addOrDelDefaultFibRouteForDnat: Install NAT default route on DPN {} for the router {} with "
                         + "vpn-id {}", dpnId, routerName, associatedVpnId);
-                defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, associatedVpnId, routerId, tx);
+                defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, associatedVpnId, routerId, confTx);
             } else {
                 LOG.debug("addOrDelDefaultFibRouteForDnat: Install NAT default route on DPN {} for the router {} with "
                         + "vpn-id {}", dpnId, routerName, routerId);
-                defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId, tx);
+                defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId, confTx);
             }
         } else {
             if (associatedVpnId != NatConstants.INVALID_ID) {
                 LOG.debug("addOrDelDefaultFibRouteForDnat: Remove NAT default route on DPN {} for the router {} "
                         + "with vpn-id {}", dpnId, routerName, associatedVpnId);
-                defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, associatedVpnId, routerId, tx);
+                defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, associatedVpnId, routerId, confTx);
             } else {
                 LOG.debug("addOrDelDefaultFibRouteForDnat: Remove NAT default route on DPN {} for the router {} "
                         + "with vpn-id {}", dpnId, routerName, routerId);
-                defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId, tx);
+                defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId, confTx);
             }
         }
-        if (!wrTxPresent) {
-            tx.submit();
-        }
     }
 }