VpnEngine: Robust handling of (lock, ID allocation/release) failures
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / ExternalRoutersListener.java
index 1d978d65c19d29b3f8fe1c635f00717efe1623a7..1aaac13b3f0c0b9742e4e29c13af83503881d1eb 100644 (file)
@@ -13,8 +13,10 @@ import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
+
 import java.math.BigInteger;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -144,6 +146,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.V
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 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;
 
@@ -152,8 +156,8 @@ import org.slf4j.LoggerFactory;
 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener> {
     private static final Logger LOG = LoggerFactory.getLogger(ExternalRoutersListener.class);
 
-    private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
-    private static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
+    private static final Uint64 COOKIE_TUNNEL = Uint64.valueOf("9000000", 16).intern();
+    private static final Uint64 COOKIE_VM_LFIB_TABLE = Uint64.valueOf("8000022", 16).intern();
 
     private final DataBroker dataBroker;
     private final ManagedNewTransactionRunner txRunner;
@@ -255,7 +259,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         // Populate the router-id-name container
         String routerName = routers.getRouterName();
         LOG.info("add : external router event for {}", routerName);
-        long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
         try {
@@ -264,14 +268,14 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     () -> Collections.singletonList(
                         txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
                             LOG.info("add : Installing NAT default route on all dpns part of router {}", routerName);
-                            long bgpVpnId = NatConstants.INVALID_ID;
+                            Uint32 bgpVpnId = NatConstants.INVALID_ID;
                             if (bgpVpnUuid != null) {
                                 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
                             }
                             addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, confTx);
                             // Allocate Primary Napt Switch for this router
-                            BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName);
-                            if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
+                            Uint64 primarySwitchId = getPrimaryNaptSwitch(routerName);
+                            if (primarySwitchId != null && !primarySwitchId.equals(Uint64.ZERO)) {
                                 handleEnableSnat(routers, routerId, primarySwitchId, bgpVpnId, confTx);
                             }
                         }
@@ -285,7 +289,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public void handleEnableSnat(Routers routers, long routerId, BigInteger primarySwitchId, long bgpVpnId,
+    public void handleEnableSnat(Routers routers, Uint32 routerId, Uint64 primarySwitchId, Uint32 bgpVpnId,
                                  TypedWriteTransaction<Configuration> confTx) {
         String routerName = routers.getRouterName();
         LOG.info("handleEnableSnat : Handling SNAT for router {}", routerName);
@@ -304,15 +308,15 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
 
         if (bgpVpnId != NatConstants.INVALID_ID) {
-            installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, false, confTx,
-                    extNwProvType);
+            installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId,
+                routers.getNetworkId(),false, confTx, extNwProvType);
         } else {
             // write metadata and punt
             installOutboundMissEntry(routerName, routerId, primarySwitchId, confTx);
-            handlePrimaryNaptSwitch(primarySwitchId, routerName, routerId, confTx);
+            handlePrimaryNaptSwitch(primarySwitchId, routerName, routerId, routers.getNetworkId(), confTx);
             // Now install entries in SNAT tables to point to Primary for each router
-            List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
-            for (BigInteger dpnId : switches) {
+            List<Uint64> switches = naptSwitchSelector.getDpnsForVpn(routerName);
+            for (Uint64 dpnId : switches) {
                 // Handle switches and NAPT switches separately
                 if (!dpnId.equals(primarySwitchId)) {
                     LOG.debug("handleEnableSnat : Handle Ordinary switch");
@@ -329,6 +333,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             for (String externalIpAddrPrefix : externalIps) {
                 LOG.debug("handleEnableSnat : Calling handleSnatReverseTraffic for primarySwitchId {}, "
                     + "routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
+                externalIpAddrPrefix = NatUtil.validateAndAddNetworkMask(externalIpAddrPrefix);
                 handleSnatReverseTraffic(confTx, primarySwitchId, routers, routerId, routerName, externalIpAddrPrefix
                 );
             }
@@ -336,25 +341,29 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         LOG.debug("handleEnableSnat : Exit");
     }
 
-    private BigInteger getPrimaryNaptSwitch(String routerName) {
+    private Uint64 getPrimaryNaptSwitch(String routerName) {
         // Allocate Primary Napt Switch for this router
-        BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
-        if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
+        Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
+        if (primarySwitchId != null && !primarySwitchId.equals(Uint64.ZERO)) {
             LOG.debug("getPrimaryNaptSwitch : Primary NAPT switch with DPN ID {} is already elected for router {}",
                 primarySwitchId, routerName);
             return primarySwitchId;
         }
+        return selectNewNAPTSwitch(routerName);
+    }
+
+    private Uint64 selectNewNAPTSwitch(String routerName) {
         // Allocated an id from VNI pool for the Router.
         natOverVxlanUtil.getRouterVni(routerName, NatConstants.INVALID_ID);
-        primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
+        Uint64 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName, null);
         LOG.debug("getPrimaryNaptSwitch : Primary NAPT switch DPN ID {}", primarySwitchId);
 
         return primarySwitchId;
     }
 
-    protected void installNaptPfibExternalOutputFlow(String routerName, Long routerId, BigInteger dpnId,
+    protected void installNaptPfibExternalOutputFlow(String routerName, Uint32 routerId, Uint64 dpnId,
                                                      TypedWriteTransaction<Configuration> confTx) {
-        Long extVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
+        Uint32 extVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
         if (extVpnId == NatConstants.INVALID_ID) {
             LOG.error("installNaptPfibExternalOutputFlow - not found extVpnId for router {}", routerId);
             extVpnId = routerId;
@@ -368,7 +377,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         for (String ip : externalIps) {
             Uuid subnetId = getSubnetIdForFixedIp(ip);
             if (subnetId != null) {
-                long subnetVpnId = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
+                Uint32 subnetVpnId = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
                 if (subnetVpnId != NatConstants.INVALID_ID) {
                     extVpnId = subnetVpnId;
                 }
@@ -393,7 +402,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return null;
     }
 
-    protected void subnetRegisterMapping(Routers routerEntry, Long segmentId) {
+    protected void subnetRegisterMapping(Routers routerEntry, Uint32 segmentId) {
         LOG.debug("subnetRegisterMapping : Fetching values from extRouters model");
         List<String> externalIps = NatUtil.getIpsListFromExternalIps(routerEntry.getExternalIps());
         int counter = 0;
@@ -485,7 +494,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    private void addOrDelDefFibRouteToSNAT(String routerName, long routerId, long bgpVpnId,
+    private void addOrDelDefFibRouteToSNAT(String routerName, Uint32 routerId, Uint32 bgpVpnId,
             Uuid bgpVpnUuid, boolean create, TypedReadWriteTransaction<Configuration> confTx)
             throws ExecutionException, InterruptedException {
         //Check if BGP VPN exists. If exists then invoke the new method.
@@ -510,9 +519,9 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         addOrDelDefaultFibRouteForSNAT(routerName, routerId, create, confTx);
     }
 
-    private void addOrDelDefaultFibRouteForSNAT(String routerName, long routerId, boolean create,
+    private void addOrDelDefaultFibRouteForSNAT(String routerName, Uint32 routerId, boolean create,
             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
-        List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
+        List<Uint64> switches = naptSwitchSelector.getDpnsForVpn(routerName);
         if (switches.isEmpty()) {
             LOG.info("addOrDelDefaultFibRouteForSNAT : No switches found for router {}", routerName);
             return;
@@ -522,7 +531,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     + "default NAT route in FIB", routerName);
             return;
         }
-        for (BigInteger dpnId : switches) {
+        for (Uint64 dpnId : switches) {
             if (create) {
                 LOG.debug("addOrDelDefaultFibRouteForSNAT : installing default NAT route for router {} in dpn {} "
                         + "for the internal vpn-id {}", routerId, dpnId, routerId);
@@ -535,15 +544,15 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    private void addDefaultFibRouteForSnatWithBgpVpn(String routerName, long routerId,
-        long bgpVpnId, TypedWriteTransaction<Configuration> confTx) {
-        List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
+    private void addDefaultFibRouteForSnatWithBgpVpn(String routerName, Uint32 routerId,
+                                                     Uint32 bgpVpnId, TypedWriteTransaction<Configuration> confTx) {
+        List<Uint64> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
         if (dpnIds.isEmpty()) {
             LOG.error("addOrDelDefaultFibRouteForSNATWIthBgpVpn: No dpns are part of router {} to program "
                 + "default NAT flows for BGP-VPN {}", routerName, bgpVpnId);
             return;
         }
-        for (BigInteger dpnId : dpnIds) {
+        for (Uint64 dpnId : dpnIds) {
             if (bgpVpnId != NatConstants.INVALID_ID) {
                 LOG.debug("addOrDelDefaultFibRouteForSnatWithBgpVpn : installing default NAT route for router {} "
                     + "in dpn {} for the BGP vpnID {}", routerId, dpnId, bgpVpnId);
@@ -556,16 +565,16 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    private void removeDefaultFibRouteForSnatWithBgpVpn(String routerName, long routerId,
-            long bgpVpnId, TypedReadWriteTransaction<Configuration> confTx)
+    private void removeDefaultFibRouteForSnatWithBgpVpn(String routerName, Uint32 routerId, Uint32 bgpVpnId,
+                                                        TypedReadWriteTransaction<Configuration> confTx)
             throws ExecutionException, InterruptedException {
-        List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
+        List<Uint64> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
         if (dpnIds.isEmpty()) {
             LOG.error("addOrDelDefaultFibRouteForSNATWIthBgpVpn: No dpns are part of router {} to program "
                 + "default NAT flows for BGP-VPN {}", routerName, bgpVpnId);
             return;
         }
-        for (BigInteger dpnId : dpnIds) {
+        for (Uint64 dpnId : dpnIds) {
             if (bgpVpnId != NatConstants.INVALID_ID) {
                 LOG.debug("addOrDelDefaultFibRouteForSnatWithBgpVpn : removing default NAT route for router {} "
                     + "in dpn {} for the BGP vpnID {}", routerId, dpnId, bgpVpnId);
@@ -578,7 +587,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    protected void installOutboundMissEntry(String routerName, long routerId, BigInteger primarySwitchId,
+    protected void installOutboundMissEntry(String routerName, Uint32 routerId, Uint64 primarySwitchId,
         TypedWriteTransaction<Configuration> confTx) {
         LOG.debug("installOutboundMissEntry : Router ID from getVpnId {}", routerId);
         if (routerId != NatConstants.INVALID_ID) {
@@ -591,22 +600,22 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID, int protocol) {
+    public String getFlowRefOutbound(Uint64 dpnId, short tableId, Uint32 routerID, int protocol) {
         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
                 .FLOWID_SEPARATOR + routerID + NatConstants.FLOWID_SEPARATOR + protocol;
     }
 
-    private String getFlowRefNaptPreFib(BigInteger dpnId, short tableId, long vpnId) {
+    private String getFlowRefNaptPreFib(Uint64 dpnId, short tableId, Uint32 vpnId) {
         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
                 .FLOWID_SEPARATOR + vpnId;
     }
 
-    public BigInteger getCookieOutboundFlow(long routerId) {
-        return NwConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
-            BigInteger.valueOf(routerId));
+    public Uint64 getCookieOutboundFlow(Uint32 routerId) {
+        return Uint64.valueOf((NwConstants.COOKIE_OUTBOUND_NAPT_TABLE).toJava().add(
+                new BigInteger("0110001", 16)).add(BigInteger.valueOf(routerId.longValue())));
     }
 
-    private ActionLearn getLearnActionForPunt(int protocol, int hardTimeout, BigInteger cookie) {
+    private ActionLearn getLearnActionForPunt(int protocol, int hardTimeout, Uint64 cookie) {
         long l4SrcPortField;
         long l4DstPortField;
         int l4portFieldLen = NxmOfFieldType.NXM_OF_TCP_SRC.getFlowModHeaderLenInt();
@@ -638,11 +647,12 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                 NwConstants.OUTBOUND_NAPT_TABLE, 0, 0, flowMods);
     }
 
-    private FlowEntity buildIcmpDropFlow(BigInteger dpnId, long routerId, long vpnId) {
+    private FlowEntity buildIcmpDropFlow(Uint64 dpnId, Uint32 routerId, Uint32 vpnId) {
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
         matches.add(MatchIpProtocol.ICMP);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<ActionInfo> actionInfos = new ArrayList<>();
         actionInfos.add(new ActionDrop());
@@ -658,13 +668,14 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return flow;
     }
 
-    protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId, int protocol) {
+    protected FlowEntity buildOutboundFlowEntity(Uint64 dpId, Uint32 routerId, int protocol) {
         LOG.debug("buildOutboundFlowEntity : called for dpId {} and routerId{}", dpId, routerId);
-        BigInteger cookie = getCookieOutboundFlow(routerId);
+        Uint64 cookie = getCookieOutboundFlow(routerId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
         matches.add(new MatchIpProtocol((short)protocol));
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<InstructionInfo> instructions = new ArrayList<>();
         List<ActionInfo> actionsInfos = new ArrayList<>();
@@ -682,7 +693,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return flowEntity;
     }
 
-    public void createOutboundTblEntry(BigInteger dpnId, long routerId, TypedWriteTransaction<Configuration> confTx) {
+    public void createOutboundTblEntry(Uint64 dpnId, Uint32 routerId, TypedWriteTransaction<Configuration> confTx) {
         LOG.debug("createOutboundTblEntry : called for dpId {} and routerId {}", dpnId, routerId);
         FlowEntity tcpflowEntity = buildOutboundFlowEntity(dpnId, routerId, NwConstants.IP_PROT_TCP);
         LOG.debug("createOutboundTblEntry : Installing tcp flow {}", tcpflowEntity);
@@ -698,7 +709,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     }
 
     @Nullable
-    protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
+    protected String getTunnelInterfaceName(Uint64 srcDpId, Uint64 dstDpId) {
         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
         RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
         try {
@@ -736,7 +747,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return null;
     }
 
-    protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName, long routerId,
+    protected void installSnatMissEntryForPrimrySwch(Uint64 dpnId, String routerName, Uint32 routerId,
         TypedWriteTransaction<Configuration> confTx) {
 
         LOG.debug("installSnatMissEntry : called for for the primary NAPT switch dpnId {} ", dpnId);
@@ -745,19 +756,19 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         mdsalManager.addFlow(confTx, flowEntity);
     }
 
-    protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo,
-            String routerName, long routerId) {
+    protected void installSnatMissEntry(Uint64 dpnId, List<BucketInfo> bucketInfo,
+            String routerName, Uint32 routerId) {
         LOG.debug("installSnatMissEntry : called for dpnId {} with primaryBucket {} ",
             dpnId, bucketInfo.get(0));
         // Install the select group
-        long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
+        Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
             NatUtil.getGroupIdKey(routerName));
         if (groupId == NatConstants.INVALID_ID) {
             LOG.error("installSnatMissEntry: Unable to obtain group ID for Key: {}", routerName);
             return;
         }
         GroupEntity groupEntity =
-            MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
+            MDSALUtil.buildGroupEntity(dpnId, groupId.longValue(), routerName, GroupTypes.GroupAll, bucketInfo);
         LOG.debug("installSnatMissEntry : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
         mdsalManager.syncInstallGroup(groupEntity);
         // Install miss entry pointing to group
@@ -771,26 +782,27 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         mdsalManager.installFlow(flowEntity);
     }
 
-    void installGroup(BigInteger dpnId, String routerName, long groupId, List<BucketInfo> bucketInfo) {
+    void installGroup(Uint64 dpnId, String routerName, Uint32 groupId, List<BucketInfo> bucketInfo) {
         GroupEntity groupEntity =
-            MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
+            MDSALUtil.buildGroupEntity(dpnId, groupId.longValue(), routerName, GroupTypes.GroupAll, bucketInfo);
         LOG.debug("installGroup : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
         mdsalManager.syncInstallGroup(groupEntity);
     }
 
-    private FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long routerId, long groupId) {
+    private FlowEntity buildSnatFlowEntity(Uint64 dpId, String routerName, Uint32 routerId, Uint32 groupId) {
         LOG.debug("buildSnatFlowEntity : called for dpId {}, routerName {} and groupId {}",
                 dpId, routerName, groupId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<ActionInfo> actionsInfo = new ArrayList<>();
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager, idManager,
+        Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager, idManager,
                 routerId, routerName);
-        actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
+        actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
         LOG.debug("buildSnatFlowEntity : Setting the tunnel to the list of action infos {}", actionsInfo);
-        actionsInfo.add(new ActionGroup(groupId));
+        actionsInfo.add(new ActionGroup(groupId.longValue()));
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionApplyActions(actionsInfo));
         String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
@@ -802,13 +814,14 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return flowEntity;
     }
 
-    private FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName, long routerId) {
+    private FlowEntity buildSnatFlowEntityForPrmrySwtch(Uint64 dpId, String routerName, Uint32 routerId) {
 
         LOG.debug("buildSnatFlowEntityForPrmrySwtch : called for primary NAPT switch dpId {}, routerName {}", dpId,
             routerName);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
@@ -823,7 +836,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     }
 
     // TODO : Replace this with ITM Rpc once its available with full functionality
-    protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName, long routerId,
+    protected void installTerminatingServiceTblEntry(Uint64 dpnId, String routerName, Uint32 routerId,
         TypedWriteTransaction<Configuration> confTx) {
 
         LOG.debug("installTerminatingServiceTblEntry : for switch {}, routerName {}",
@@ -840,34 +853,34 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
 
     }
 
-    private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName, long routerId) {
+    private FlowEntity buildTsFlowEntity(Uint64 dpId, String routerName, Uint32 routerId) {
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager,
+        Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager,
                 idManager, routerId, routerName);
-        matches.add(new MatchTunnelId(BigInteger.valueOf(tunnelId)));
-        String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, tunnelId);
+        matches.add(new MatchTunnelId(tunnelId));
+        String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, Uint32.valueOf(tunnelId.longValue()));
         List<InstructionInfo> instructions = new ArrayList<>();
-        instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId),
+        instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
                 MetaDataUtil.METADATA_MASK_VRFID));
         instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
-                NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0, NwConstants.COOKIE_TS_TABLE, matches,
-                instructions);
+                NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
+                NwConstants.COOKIE_TS_TABLE, matches, instructions);
         return flowEntity;
     }
 
-    public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
+    public String getFlowRefTs(Uint64 dpnId, short tableId, Uint32 routerID) {
         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
                 .FLOWID_SEPARATOR + routerID;
     }
 
-    public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
+    public static String getFlowRefSnat(Uint64 dpnId, short tableId, String routerID) {
         return NatConstants.SNAT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
                 .FLOWID_SEPARATOR + routerID;
     }
 
-    protected void handleSwitches(BigInteger dpnId, String routerName, long routerId, BigInteger primarySwitchId) {
+    protected void handleSwitches(Uint64 dpnId, String routerName, Uint32 routerId, Uint64 primarySwitchId) {
         LOG.debug("handleSwitches : Installing SNAT miss entry in switch {}", dpnId);
         List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
         String ifNamePrimary = getTunnelInterfaceName(dpnId, primarySwitchId);
@@ -892,8 +905,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         installSnatMissEntry(dpnId, listBucketInfo, routerName, routerId);
     }
 
-    List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId,
-                                                     BigInteger primarySwitchId, String routerName, long routerId) {
+    List<BucketInfo> getBucketInfoForNonNaptSwitches(Uint64 nonNaptSwitchId,
+                                                     Uint64 primarySwitchId, String routerName, Uint32 routerId) {
         List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
         String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
         List<BucketInfo> listBucketInfo = new ArrayList<>();
@@ -918,7 +931,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return listBucketInfo;
     }
 
-    protected void handlePrimaryNaptSwitch(BigInteger dpnId, String routerName, long routerId,
+    protected void handlePrimaryNaptSwitch(Uint64 dpnId, String routerName, Uint32 routerId, Uuid externalNwUuid,
         TypedWriteTransaction<Configuration> confTx) {
 
        /*
@@ -943,12 +956,12 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         if (networkId != null) {
             Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
             if (vpnUuid != null) {
-                long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+                Uint32 extVpnId = NatUtil.getExternalVpnIdForExtNetwork(dataBroker, externalNwUuid);
                 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + networkId, () -> {
                     installNaptPfibEntriesForExternalSubnets(routerName, dpnId, null);
                     //Install the NAPT PFIB TABLE which forwards outgoing packet to FIB Table matching on the VPN ID.
-                    if (vpnId != NatConstants.INVALID_ID) {
-                        installNaptPfibEntry(dpnId, vpnId, null);
+                    if (extVpnId != null && extVpnId != NatConstants.INVALID_ID) {
+                        installNaptPfibEntry(dpnId, extVpnId, null);
                     }
                     return Collections.emptyList();
                 });
@@ -960,7 +973,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public void installNaptPfibEntry(BigInteger dpnId, long segmentId,
+    public void installNaptPfibEntry(Uint64 dpnId, Uint32 segmentId,
             @Nullable TypedWriteTransaction<Configuration> confTx) {
         LOG.debug("installNaptPfibEntry : called for dpnId {} and segmentId {} ", dpnId, segmentId);
         FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
@@ -971,16 +984,17 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
+    public FlowEntity buildNaptPfibFlowEntity(Uint64 dpId, Uint32 segmentId) {
 
         LOG.debug("buildNaptPfibFlowEntity : called for dpId {}, segmentId {}", dpId, segmentId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
-        listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
+        listActionInfo.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
         instructionInfo.add(new InstructionApplyActions(listActionInfo));
 
@@ -992,8 +1006,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return flowEntity;
     }
 
-    public void handleSnatReverseTraffic(TypedWriteTransaction<Configuration> confTx, BigInteger dpnId, Routers router,
-        long routerId, String routerName, String externalIp) {
+    public void handleSnatReverseTraffic(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId, Routers router,
+                                         Uint32 routerId, String routerName, String externalIp) {
         LOG.debug("handleSnatReverseTraffic : entry for DPN ID {}, routerId {}, externalIp: {}",
             dpnId, routerId, externalIp);
         Uuid networkId = router.getNetworkId();
@@ -1001,6 +1015,24 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             LOG.error("handleSnatReverseTraffic : networkId is null for the router ID {}", routerId);
             return;
         }
+        Collection<Uuid> externalSubnetList = NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps());
+        // FLAT/VLAN case having external-subnet as VPN
+        String externalSubnetVpn = null;
+        if (externalSubnetList != null && !externalSubnetList.isEmpty()) {
+            for (Uuid externalSubnetId : externalSubnetList) {
+                Optional<Subnets> externalSubnet = NatUtil
+                    .getOptionalExternalSubnets(dataBroker, externalSubnetId);
+                // externalSubnet data model will exist for FLAT/VLAN external netowrk UCs.
+                if (externalSubnet.isPresent()) {
+                    externalSubnetVpn = externalSubnetId.getValue();
+                    advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE,
+                        externalSubnetVpn, routerId, routerName,
+                        externalIp, networkId, router, confTx);
+                }
+            }
+            return;
+        }
+        // VXVLAN/GRE case having Internet-VPN
         final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
         if (vpnName == null) {
             LOG.error("handleSnatReverseTraffic : No VPN associated with ext nw {} to handle add external ip "
@@ -1013,8 +1045,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             dpnId, routerId, externalIp);
     }
 
-    public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName,
-                                                final long routerId, final String routerName, final String externalIp,
+    public void advToBgpAndInstallFibAndTsFlows(final Uint64 dpnId, final short tableId, final String vpnName,
+                                                final Uint32 routerId, final String routerName, final String externalIp,
                                                 final Uuid extNetworkId, @Nullable final Routers router,
                                                 final TypedWriteTransaction<Configuration> confTx) {
         LOG.debug("advToBgpAndInstallFibAndTsFlows : entry for DPN ID {}, tableId {}, vpnname {} "
@@ -1045,7 +1077,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             if (result.isSuccessful()) {
                 LOG.debug("advToBgpAndInstallFibAndTsFlows : inside apply with result success");
                 GenerateVpnLabelOutput output = result.getResult();
-                final long label = output.getLabel();
+                final Uint32 label = output.getLabel();
 
                 int externalIpInDsFlag = 0;
                 //Get IPMaps from the DB for the router ID
@@ -1074,9 +1106,9 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     return Futures.immediateFailedFuture(new Exception(errMsg));
                 }
                 //Inform BGP
-                long l3vni = 0;
+                Uint32 l3vni = Uint32.ZERO;
                 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
-                    l3vni = natOverVxlanUtil.getInternetVpnVni(vpnName, l3vni).longValue();
+                    l3vni = natOverVxlanUtil.getInternetVpnVni(vpnName, l3vni);
                 }
                 Routers extRouter = router != null ? router :
                     NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
@@ -1146,11 +1178,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             String externalIp) {
         List<Instruction> fibTableCustomInstructions = new ArrayList<>();
         Routers router = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
-        long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker,
+        Uint32 externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker,
                 externalIp, router);
         int instructionIndex = 0;
         if (externalSubnetVpnId != NatConstants.INVALID_ID) {
-            BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
+            Uint64 subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId.longValue());
             fibTableCustomInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
                     MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(instructionIndex));
             instructionIndex++;
@@ -1160,11 +1192,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return fibTableCustomInstructions;
     }
 
-    private void makeLFibTableEntry(BigInteger dpId, long serviceId, short tableId,
+    private void makeLFibTableEntry(Uint64 dpId, Uint32 serviceId, short tableId,
         TypedWriteTransaction<Configuration> confTx) {
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.MPLS_UNICAST);
-        matches.add(new MatchMplsLabel(serviceId));
+        matches.add(new MatchMplsLabel(serviceId.longValue()));
 
         List<Instruction> instructions = new ArrayList<>();
         List<ActionInfo> actionsInfos = new ArrayList<>();
@@ -1186,7 +1218,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         LOG.debug("makeLFibTableEntry : LFIB Entry for dpID {} : label : {} modified successfully", dpId, serviceId);
     }
 
-    private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, long l3Vni,
+    private void makeTunnelTableEntry(Uint64 dpnId, Uint32 serviceId, Uint32 l3Vni,
         List<Instruction> customInstructions, TypedWriteTransaction<Configuration> confTx,
         ProviderTypes extNwProvType) {
 
@@ -1196,76 +1228,98 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             dpnId, serviceId, customInstructions);
 
         if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
-            mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
+            mkMatches.add(new MatchTunnelId(Uint64.valueOf(l3Vni)));
         } else {
-            mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
+            mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
         }
 
         Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
             getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
                 NatConstants.DEFAULT_VPN_INTERNAL_TUNNEL_TABLE_PRIORITY,
-                String.format("%s:%d", "TST Flow Entry ", serviceId), 0, 0,
-                COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
+                String.format("%s:%s", "TST Flow Entry ", serviceId), 0, 0,
+                Uint64.valueOf(COOKIE_TUNNEL.toJava().add(BigInteger.valueOf(serviceId.longValue()))),
+                mkMatches, customInstructions);
 
         mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
     }
 
-    protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
+    protected InstanceIdentifier<RouterIds> getRoutersIdentifier(Uint32 routerId) {
         return InstanceIdentifier.builder(RouterIdName.class).child(RouterIds.class,
             new RouterIdsKey(routerId)).build();
     }
 
-    private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
-        return NatConstants.SNAT_FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants
-                .FLOWID_SEPARATOR + id + NwConstants.FLOWID_SEPARATOR + ipAddress;
+    private String getFlowRef(Uint64 dpnId, short tableId, Uint32 id, String ipAddress) {
+        return NatConstants.SNAT_FLOWID_PREFIX + dpnId.toString() + NwConstants.FLOWID_SEPARATOR + tableId
+                + NwConstants.FLOWID_SEPARATOR + id + NwConstants.FLOWID_SEPARATOR + ipAddress;
     }
 
     @Override
     protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
+        LOG.trace("update : origRouter: {} updatedRouter: {}", original, update);
         String routerName = original.getRouterName();
-        Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         if (routerId == NatConstants.INVALID_ID) {
             LOG.error("update : external router event - Invalid routerId for routerName {}", routerName);
             return;
         }
-        // Check if its update on SNAT flag
-        boolean originalSNATEnabled = original.isEnableSnat();
-        boolean updatedSNATEnabled = update.isEnableSnat();
-        LOG.debug("update :called with originalFlag and updatedFlag for SNAT enabled "
-            + "as {} and {}", originalSNATEnabled, updatedSNATEnabled);
-        /* Get Primary Napt Switch for existing router from "router-to-napt-switch" DS.
-         * if dpnId value is null or zero then go for electing new Napt switch for existing router.
-         */
-        long bgpVpnId = NatConstants.INVALID_ID;
-        Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
-        if (bgpVpnUuid != null) {
-            bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
-        }
-        BigInteger dpnId = getPrimaryNaptSwitch(routerName);
-        final long finalBgpVpnId = bgpVpnId;
         coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.key(), () -> {
             List<ListenableFuture<Void>> futures = new ArrayList<>();
             futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeFlowInvTx -> {
                 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, removeFlowInvTx -> {
+                    Uint32 bgpVpnId = NatConstants.INVALID_ID;
+                    Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
+                    if (bgpVpnUuid != null) {
+                        bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
+                    }
+                    //BigInteger dpnId = getPrimaryNaptSwitch(routerName);
+                    /* Get Primary Napt Switch for existing router from "router-to-napt-switch" DS.
+                     * if dpnId value is null or zero then go for electing new Napt switch for existing router.
+                     */
+                    Uint64 dpnId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
+                    boolean isPrimaryNaptSwitchNotSelected = (dpnId == null || dpnId.equals(Uint64
+                            .valueOf(BigInteger.ZERO)));
                     Uuid networkId = original.getNetworkId();
-                    if (originalSNATEnabled != updatedSNATEnabled) {
-                        if (originalSNATEnabled) {
-                            if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
-                                // Router has no interface attached
+                    // Check if its update on SNAT flag
+                    boolean originalSNATEnabled = original.isEnableSnat();
+                    boolean updatedSNATEnabled = update.isEnableSnat();
+                    LOG.debug("update :called with originalFlag and updatedFlag for SNAT enabled "
+                            + "as {} and {} with Elected Dpn {}(isPrimaryNaptSwitchNotSelected:{})",
+                        originalSNATEnabled, updatedSNATEnabled, dpnId, isPrimaryNaptSwitchNotSelected);
+                    // Cluster Reboot Case Handling
+                    // 1. DPN not elected during add event(due to none of the OVS connected)
+                    // 2. Update event called with changes of parameters(but enableSnat is not changed)
+                    // 3. First Elect dpnId and process other changes with valid dpnId
+                    if (originalSNATEnabled != updatedSNATEnabled || isPrimaryNaptSwitchNotSelected) {
+                        if (originalSNATEnabled && !updatedSNATEnabled) {
+                            if (isPrimaryNaptSwitchNotSelected) {
+                                LOG.info("No Action to be taken when SNAT is disabled "
+                                    + "with no Napt Switch Election for Router {}", routerName);
                                 return;
                             }
                             //SNAT disabled for the router
                             Uuid networkUuid = original.getNetworkId();
                             LOG.info("update : SNAT disabled for Router {}", routerName);
                             Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
-                            handleDisableSnat(original, networkUuid, externalIps, false, null, dpnId, routerId,
-                                    removeFlowInvTx);
-                        } else {
-                            LOG.info("update : SNAT enabled for Router {}", original.getRouterName());
-                            addOrDelDefFibRouteToSNAT(routerName, routerId, finalBgpVpnId, bgpVpnUuid,
-                                    true, writeFlowInvTx);
-                            handleEnableSnat(update, routerId, dpnId, finalBgpVpnId, writeFlowInvTx);
+                            final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
+                            handleDisableSnat(original, networkUuid, externalIps, false, vpnName,
+                                    dpnId, routerId, removeFlowInvTx);
+                        }  else if (updatedSNATEnabled) {
+                            LOG.info("update : SNAT enabled for Router {}", routerName);
+                            addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid,
+                                true, writeFlowInvTx);
+                            if (isPrimaryNaptSwitchNotSelected) {
+                                dpnId = selectNewNAPTSwitch(routerName);
+                                if (dpnId != null && !dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
+                                    handleEnableSnat(update, routerId, dpnId, bgpVpnId, removeFlowInvTx);
+                                } else {
+                                    LOG.error("update : Failed to elect Napt Switch During update event"
+                                        + " of router {}", routerName);
+                                }
+                            }
                         }
+                        LOG.info("update : no need to process external/subnet changes as it's will taken care"
+                            + "in handleDisableSnat/handleEnableSnat");
+                        return;
                     }
                     if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
                         NatUtil.installRouterGwFlows(txRunner, vpnManager, original, dpnId, NwConstants.DEL_FLOW);
@@ -1278,7 +1332,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         return;
                     }
                     //Check if the Update is on External IPs
-                    LOG.debug("update : Checking if this is update on External IPs");
+                    LOG.debug("update : Checking if this is update on External IPs for router {}", routerName);
                     List<String> originalExternalIps = NatUtil.getIpsListFromExternalIps(original.getExternalIps());
                     List<String> updatedExternalIps = NatUtil.getIpsListFromExternalIps(update.getExternalIps());
 
@@ -1286,8 +1340,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     Set<String> removedExternalIps = new HashSet<>(originalExternalIps);
                     removedExternalIps.removeAll(updatedExternalIps);
                     if (removedExternalIps.size() > 0) {
-                        LOG.debug("update : Start processing of the External IPs removal during the update "
-                                + "operation");
+                        LOG.debug("update : Start processing of the External IPs removal for router {}", routerName);
                         vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
                                 removedExternalIps, original.getExtGwMacAddress(),
                                 dpnId, networkId);
@@ -1463,15 +1516,15 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                             naptManager.removeNaptPortPool(externalIp);
                         }
                         LOG.debug(
-                                "update : End processing of the External IPs removal during the update operation");
+                                "update : End processing of the External IPs removal for router {}", routerName);
                     }
 
                     //Check if the External IPs are added during the update.
                     Set<String> addedExternalIps = new HashSet<>(updatedExternalIps);
                     addedExternalIps.removeAll(originalExternalIps);
                     if (addedExternalIps.size() != 0) {
-                        LOG.debug("update : Start processing of the External IPs addition during the update "
-                                + "operation");
+                        LOG.debug("update : Start processing of the External IPs addition for router {}",
+                            routerName);
                         vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps,
                                 update.getExtGwMacAddress(), dpnId,
                                 update.getNetworkId());
@@ -1498,7 +1551,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     }
 
                     //Check if its Update on subnets
-                    LOG.debug("update : Checking if this is update on subnets");
+                    LOG.debug("update : Checking if this is update on subnets for router {}", routerName);
                     List<Uuid> originalSubnetIds = original.getSubnetIds();
                     List<Uuid> updatedSubnetIds = update.getSubnetIds();
                     Set<Uuid> addedSubnetIds =
@@ -1510,7 +1563,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     //Check if the Subnet IDs are added during the update.
                     if (addedSubnetIds.size() != 0) {
                         LOG.debug(
-                                "update : Start processing of the Subnet IDs addition during the update operation");
+                                "update : Start processing of the Subnet IDs addition for router {}", routerName);
                         for (Uuid addedSubnetId : addedSubnetIds) {
                 /*
                     1) Select the least loaded external IP for the subnet and store the mapping of the
@@ -1525,7 +1578,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                                         writeFlowInvTx);
                             }
                         }
-                        LOG.debug("update : End processing of the Subnet IDs addition during the update operation");
+                        LOG.debug("update : End processing of the Subnet IDs addition for router {}", routerName);
                     }
 
                     //Check if the Subnet IDs are removed during the update.
@@ -1533,7 +1586,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     removedSubnetIds.removeAll(updatedSubnetIds);
                     if (removedSubnetIds.size() != 0) {
                         LOG.debug(
-                                "update : Start processing of the Subnet IDs removal during the update operation");
+                                "update : Start processing of the Subnet IDs removal for router {}", routerName);
                         for (Uuid removedSubnetId : removedSubnetIds) {
                             String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
                             if (subnetAddr != null) {
@@ -1571,7 +1624,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                                 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
                             }
                         }
-                        LOG.debug("update : End processing of the Subnet IDs removal during the update operation");
+                        LOG.debug("update : End processing of the Subnet IDs removal for router {}", routerName);
                     }
                 }));
             }));
@@ -1594,7 +1647,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             for (ExternalCounters ext : externalIpsCounters.nonnullExternalCounters()) {
                 for (ExternalIpCounter externalIpCount : ext.nonnullExternalIpCounter()) {
                     if (externalIpCount.getExternalIp().equals(externalIp)) {
-                        if (externalIpCount.getCounter() != 0) {
+                        if (externalIpCount.getCounter().toJava() != 0) {
                             return true;
                         }
                         break;
@@ -1605,7 +1658,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return false;
     }
 
-    private void allocateExternalIp(BigInteger dpnId, Routers router, long routerId, String routerName,
+    private void allocateExternalIp(Uint64 dpnId, Routers router, Uint32 routerId, String routerName,
             Uuid networkId, String subnetIp, TypedWriteTransaction<Configuration> writeFlowInvTx) {
         String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
         try {
@@ -1637,7 +1690,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             // allocated to any of the subnets)
             // If external IP is already assigned a route, (, do not re-advertise to the BGP
             String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
-            Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
+            Uint32 label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
             if (label != null) {
                 //update
                 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
@@ -1657,11 +1710,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
             if (vpnName != null) {
                 LOG.debug("allocateExternalIp : Retrieved vpnName {} for networkId {}", vpnName, networkId);
-                if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
+                if (dpnId == null || dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
                     LOG.debug("allocateExternalIp : Best effort for getting primary napt switch when router i/f are"
                         + "added after gateway-set");
                     dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
-                    if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
+                    if (dpnId == null || dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
                         LOG.error("allocateExternalIp : dpnId is null or Zero for the router {}", routerName);
                         return;
                     }
@@ -1674,7 +1727,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     }
 
     @Nullable
-    protected Long checkExternalIpLabel(long routerId, String externalIp) {
+    protected Uint32 checkExternalIpLabel(Uint32 routerId, String externalIp) {
         List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
         for (IpMap ipMap : ipMaps) {
             if (ipMap.getExternalIp().equals(externalIp)) {
@@ -1714,13 +1767,13 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
                 LOG.info("remove : Removing default NAT route from FIB on all dpns part of router {} ",
                         routerName);
-                Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+                Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
                 if (routerId == NatConstants.INVALID_ID) {
                     LOG.error("remove : Remove external router event - Invalid routerId for routerName {}",
                             routerName);
                     return;
                 }
-                long bgpVpnId = NatConstants.INVALID_ID;
+                Uint32 bgpVpnId = NatConstants.INVALID_ID;
                 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
                 if (bgpVpnUuid != null) {
                     bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
@@ -1729,8 +1782,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         tx);
                 Uuid networkUuid = router.getNetworkId();
 
-                BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
-                if (primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)) {
+                Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
+                if (primarySwitchId == null || primarySwitchId.equals(Uint64.ZERO)) {
                     // No NAPT switch for external router, probably because the router is not attached to
                     // any
                     // internal networks
@@ -1741,7 +1794,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     return;
                 } else {
                     Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
-                    handleDisableSnat(router, networkUuid, externalIps, true, null, primarySwitchId,
+                    final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid);
+                    handleDisableSnat(router, networkUuid, externalIps, true, vpnName, primarySwitchId,
                             routerId, tx);
                 }
                 if (NatUtil.releaseId(idManager, NatConstants.ODL_VNI_POOL_NAME, routerName)
@@ -1752,22 +1806,22 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     }
 
     public void handleDisableSnat(Routers router, Uuid networkUuid, @NonNull Collection<String> externalIps,
-                                  boolean routerFlag, @Nullable String vpnName, BigInteger naptSwitchDpnId,
-                                  long routerId, TypedReadWriteTransaction<Configuration> removeFlowInvTx) {
+                                  boolean routerFlag, @Nullable String vpnName, Uint64 naptSwitchDpnId,
+                                  Uint32 routerId, TypedReadWriteTransaction<Configuration> removeFlowInvTx) {
         LOG.info("handleDisableSnat : Entry");
         String routerName = router.getRouterName();
         try {
             if (routerFlag) {
                 removeNaptSwitch(routerName);
             } else {
-                updateNaptSwitch(routerName, BigInteger.ZERO);
+                updateNaptSwitch(routerName, Uint64.valueOf(BigInteger.ZERO));
             }
 
             LOG.debug("handleDisableSnat : Remove the ExternalCounter model for the router ID {}", routerId);
             naptManager.removeExternalCounter(routerId);
 
             LOG.debug("handleDisableSnat : got primarySwitch as dpnId {}", naptSwitchDpnId);
-            if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)) {
+            if (naptSwitchDpnId == null || naptSwitchDpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
                 LOG.error("handleDisableSnat : Unable to retrieve the primary NAPT switch for the "
                     + "router ID {} from RouterNaptSwitch model", routerId);
                 return;
@@ -1809,13 +1863,13 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    public void handleDisableSnatInternetVpn(String routerName, long routerId, Uuid networkUuid,
+    public void handleDisableSnatInternetVpn(String routerName, Uint32 routerId, Uuid networkUuid,
                                              @NonNull Collection<String> externalIps,
                                              String vpnId, TypedReadWriteTransaction<Configuration> writeFlowInvTx) {
         LOG.debug("handleDisableSnatInternetVpn: Started to process handle disable snat for router {} "
                 + "with internet vpn {}", routerName, vpnId);
         try {
-            BigInteger naptSwitchDpnId = null;
+            Uint64 naptSwitchDpnId = null;
             InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch =
                 NatUtil.buildNaptSwitchRouterIdentifier(routerName);
             Optional<RouterToNaptSwitch> rtrToNapt;
@@ -1862,7 +1916,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
+    public void updateNaptSwitch(String routerName, Uint64 naptSwitchId) {
         RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().withKey(new RouterToNaptSwitchKey(routerName))
             .setPrimarySwitchId(naptSwitchId).build();
         try {
@@ -1887,8 +1941,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         NatEvpnUtil.releaseLPortTagForRouter(dataBroker, idManager, routerName);
     }
 
-    public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName,
-                                                BigInteger dpnId, Uuid networkId, String vpnName,
+    public void removeNaptFlowsFromActiveSwitch(Uint32 routerId, String routerName,
+                                                Uint64 dpnId, Uuid networkId, String vpnName,
                                                 @NonNull Collection<String> externalIps,
                                                 Collection<Uuid> externalSubnetList,
                                                 TypedReadWriteTransaction<Configuration> confTx,
@@ -1896,7 +1950,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             throws InterruptedException, ExecutionException {
 
         LOG.debug("removeNaptFlowsFromActiveSwitch : Remove NAPT flows from Active switch");
-        BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
+        Uint64 cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
 
         //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
         // traffic which comes from the  VMs of the NAPT switches)
@@ -1910,9 +1964,9 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
 
         //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
         // traffic which comes from the VMs of the non NAPT switches)
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil,
+        Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil,
                 elanManager, idManager, routerId, routerName);
-        String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tunnelId);
+        String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, Uint32.valueOf(tunnelId.longValue()));
         FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
         LOG.info(
             "removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active switch with the DPN ID {} "
@@ -1954,8 +2008,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         //Remove the NAPT PFIB TABLE (47->21) which forwards the incoming packet to FIB Table matching on the
         // External Subnet Vpn Id.
         for (Uuid externalSubnetId : externalSubnetList) {
-            long subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
-            if (subnetVpnId != -1 && !NatUtil.checkForRoutersWithSameExtSubnetAndNaptSwitch(
+            Uint32 subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
+            if (subnetVpnId != NatConstants.INVALID_ID && !NatUtil.checkForRoutersWithSameExtSubnetAndNaptSwitch(
                 dataBroker, externalSubnetId, routerName, dpnId)) {
                 String natPfibSubnetFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, subnetVpnId);
                 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE,
@@ -1980,7 +2034,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             // Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
             // - This does not work since ext-routers is deleted already - no network info
             //Get the VPN ID from the ExternalNetworks model
-            long vpnId = -1;
+            Uint32 vpnId = NatConstants.INVALID_ID;
             if (vpnName == null || vpnName.isEmpty()) {
                 // ie called from router delete cases
                 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
@@ -2054,11 +2108,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    protected void removeNaptFibExternalOutputFlows(long routerId, BigInteger dpnId, Uuid networkId,
+    protected void removeNaptFibExternalOutputFlows(Uint32 routerId, Uint64 dpnId, Uuid networkId,
                                                     @NonNull Collection<String> externalIps,
                                                     TypedReadWriteTransaction<Configuration> writeFlowInvTx)
             throws ExecutionException, InterruptedException {
-        long extVpnId = NatConstants.INVALID_ID;
+        Uint32 extVpnId = NatConstants.INVALID_ID;
         if (networkId != null) {
             Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
             if (vpnUuid != null) {
@@ -2092,15 +2146,15 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return ip;
     }
 
-    public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName,
-                                                           BigInteger dpnId, Uuid networkId, String vpnName,
+    public void removeNaptFlowsFromActiveSwitchInternetVpn(Uint32 routerId, String routerName,
+                                                           Uint64 dpnId, Uuid networkId, String vpnName,
                                                            TypedReadWriteTransaction<Configuration> writeFlowInvTx)
             throws ExecutionException, InterruptedException {
         LOG.debug("removeNaptFlowsFromActiveSwitchInternetVpn : Remove NAPT flows from Active switch Internet Vpn");
-        BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
+        Uint64 cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
 
         //Remove the NAPT PFIB TABLE entry
-        long vpnId = -1;
+        Uint32 vpnId = NatConstants.INVALID_ID;
         if (vpnName != null) {
             // ie called from disassociate vpn case
             LOG.debug("removeNaptFlowsFromActiveSwitchInternetVpn : This is disassociate nw with vpn case "
@@ -2182,19 +2236,19 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public void removeFlowsFromNonActiveSwitches(long routerId, String routerName,
-            BigInteger naptSwitchDpnId, TypedReadWriteTransaction<Configuration> removeFlowInvTx)
+    public void removeFlowsFromNonActiveSwitches(Uint32 routerId, String routerName,
+            Uint64 naptSwitchDpnId, TypedReadWriteTransaction<Configuration> removeFlowInvTx)
             throws ExecutionException, InterruptedException {
         LOG.debug("removeFlowsFromNonActiveSwitches : Remove NAPT related flows from non active switches");
 
         // Remove the flows from the other switches which points to the primary and secondary switches
         // for the flows related the router ID.
-        List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
+        List<Uint64> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
         if (allSwitchList.isEmpty()) {
             LOG.error("removeFlowsFromNonActiveSwitches : Unable to get the swithces for the router {}", routerName);
             return;
         }
-        for (BigInteger dpnId : allSwitchList) {
+        for (Uint64 dpnId : allSwitchList) {
             if (!naptSwitchDpnId.equals(dpnId)) {
                 LOG.info("removeFlowsFromNonActiveSwitches : Handle Ordinary switch");
 
@@ -2208,13 +2262,13 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                 mdsalManager.removeFlow(removeFlowInvTx, preSnatFlowEntity);
 
                 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
-                long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
+                Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
                     NatUtil.getGroupIdKey(routerName));
                 if (groupId != NatConstants.INVALID_ID) {
                     LOG.info(
                         "removeFlowsFromNonActiveSwitches : Remove the group {} for the non active switch with "
                             + "the DPN ID {} and router ID {}", groupId, dpnId, routerId);
-                    mdsalManager.removeGroup(removeFlowInvTx, dpnId, groupId);
+                    mdsalManager.removeGroup(removeFlowInvTx, dpnId, groupId.longValue());
                 } else {
                     LOG.error("removeFlowsFromNonActiveSwitches: Unable to obtained groupID for router:{}", routerName);
                 }
@@ -2222,7 +2276,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, @Nullable Uuid networkUuid,
+    public void clrRtsFromBgpAndDelFibTs(final Uint64 dpnId, Uint32 routerId, @Nullable Uuid networkUuid,
                                          @NonNull Collection<String> externalIps, @Nullable String vpnName,
                                          String extGwMacAddress, TypedReadWriteTransaction<Configuration> confTx)
             throws ExecutionException, InterruptedException {
@@ -2254,11 +2308,12 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         //Remove custom FIB routes
         //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
         for (String extIp : externalIps) {
+            extIp = NatUtil.validateAndAddNetworkMask(extIp);
             clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName, networkUuid, extGwMacAddress, confTx);
         }
     }
 
-    protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName,
+    protected void clrRtsFromBgpAndDelFibTs(final Uint64 dpnId, Uint32 routerId, String extIp, final String vpnName,
                                             final Uuid networkUuid, String extGwMacAddress,
                                             TypedReadWriteTransaction<Configuration> removeFlowInvTx)
             throws ExecutionException, InterruptedException {
@@ -2267,8 +2322,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                 removeFlowInvTx);
     }
 
-    protected void delFibTsAndReverseTraffic(final BigInteger dpnId, String routerName, long routerId, String extIp,
-                                             String vpnName, Uuid extNetworkId, long tempLabel,
+    protected void delFibTsAndReverseTraffic(final Uint64 dpnId, String routerName, Uint32 routerId, String extIp,
+                                             String vpnName, Uuid extNetworkId, Uint32 tempLabel,
                                              String gwMacAddress, boolean switchOver,
                                              TypedReadWriteTransaction<Configuration> removeFlowInvTx)
             throws ExecutionException, InterruptedException {
@@ -2291,13 +2346,14 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             );
             return;
         }
-        if (tempLabel < 0) {
+        if (tempLabel.longValue() < 0) {
             LOG.error("delFibTsAndReverseTraffic : Label not found for externalIp {} with router id {}",
                     extIp, routerId);
             return;
         }
-        final long label = tempLabel;
+        final Uint32 label = tempLabel;
         final String externalIp = NatUtil.validateAndAddNetworkMask(extIp);
+        RemoveFibEntryInput input = null;
         if (extNwProvType == ProviderTypes.FLAT || extNwProvType == ProviderTypes.VLAN) {
             LOG.debug("delFibTsAndReverseTraffic : Using extSubnetId as vpnName for FLAT/VLAN use-cases");
             Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
@@ -2312,9 +2368,19 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             }
         }
         final String externalVpn = vpnName;
-        RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(externalVpn)
+        if (label != null && label.toJava() <= 0) {
+            LOG.error("delFibTsAndReverseTraffic : Label not found for externalIp {} with router id {}",
+                extIp, routerId);
+            input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
+                .setSourceDpid(dpnId).setIpAddress(externalIp)
+                .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.ExternalFixedIP).build();
+        } else {
+            input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
                 .setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label)
                 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.ExternalFixedIP).build();
+            removeTunnelTableEntry(dpnId, label, removeFlowInvTx);
+            removeLFibTableEntry(dpnId, label, removeFlowInvTx);
+        }
         ListenableFuture<RpcResult<RemoveFibEntryOutput>> future = fibService.removeFibEntry(input);
 
         removeTunnelTableEntry(dpnId, label, removeFlowInvTx);
@@ -2327,11 +2393,20 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             ListenableFuture<RpcResult<RemoveVpnLabelOutput>> labelFuture =
                 Futures.transformAsync(future, result -> {
                     //Release label
-                    if (result.isSuccessful()) {
+                    if (result.isSuccessful() && label != null && label.toJava() > 0) {
                         NatUtil.removePreDnatToSnatTableEntry(removeFlowInvTx, mdsalManager, dpnId);
                         RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder()
                             .setVpnName(externalVpn).setIpPrefix(externalIp).build();
-                        return vpnService.removeVpnLabel(labelInput);
+                        Future<RpcResult<RemoveVpnLabelOutput>> labelFuture1 = vpnService.removeVpnLabel(labelInput);
+                        if (labelFuture1.get() == null || !labelFuture1.get().isSuccessful()) {
+                            String errMsg = String.format(
+                                    "ExternalRoutersListener: RPC call to remove VPN label "
+                                            + "on dpn %s for prefix %s failed for vpn %s - %s",
+                                    dpnId, externalIp, result.getErrors());
+                            LOG.error(errMsg);
+                            return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+                        }
+                        return JdkFutureAdapters.listenInPoolThread(labelFuture1);
                     } else {
                         String errMsg =
                             String.format("RPC call to remove custom FIB entries on dpn %s for "
@@ -2366,7 +2441,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,
+    private void delFibTsAndReverseTraffic(final Uint64 dpnId, Uint32 routerId, String extIp, final String vpnName,
                                            final Uuid networkUuid, String extGwMacAddress, boolean switchOver,
                                            TypedReadWriteTransaction<Configuration> removeFlowInvTx)
             throws ExecutionException, InterruptedException {
@@ -2397,7 +2472,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             return;
         }
 
-        long tempLabel = NatConstants.INVALID_ID;
+        Uint32 tempLabel = NatConstants.INVALID_ID;
         for (IpMap dbIpMap : dbIpMaps) {
             String dbExternalIp = dbIpMap.getExternalIp();
             LOG.debug("delFibTsAndReverseTraffic : Retrieved dbExternalIp {} for router id {}", dbExternalIp, routerId);
@@ -2415,7 +2490,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             return;
         }
 
-        final long label = tempLabel;
+        final Uint32 label = tempLabel;
         final String externalIp = NatUtil.validateAndAddNetworkMask(extIp);
         RemoveFibEntryInput input = new RemoveFibEntryInputBuilder()
                 .setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp)
@@ -2435,7 +2510,17 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         if (result.isSuccessful()) {
                             RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder()
                                     .setVpnName(vpnName).setIpPrefix(externalIp).build();
-                            return vpnService.removeVpnLabel(labelInput);
+                            Future<RpcResult<RemoveVpnLabelOutput>> labelFuture1 = vpnService
+                                    .removeVpnLabel(labelInput);
+                            if (labelFuture1.get() == null || !labelFuture1.get().isSuccessful()) {
+                                String errMsg = String.format(
+                                        "RPC call to remove VPN label on dpn %s for prefix %s "
+                                                + "failed for vpn %s - %s", dpnId, externalIp, vpnName,
+                                        result.getErrors());
+                                LOG.error(errMsg);
+                                return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+                            }
+                            return JdkFutureAdapters.listenInPoolThread(labelFuture1);
                         } else {
                             String errMsg =
                                     String.format("RPC call to remove custom FIB entries on dpn %s for "
@@ -2470,7 +2555,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid,
+    protected void clearFibTsAndReverseTraffic(final Uint64 dpnId, Uint32 routerId, Uuid networkUuid,
             List<String> externalIps, @Nullable String vpnName, String extGwMacAddress,
             TypedReadWriteTransaction<Configuration> writeFlowInvTx) throws ExecutionException, InterruptedException {
         //Withdraw the corresponding routes from the BGP.
@@ -2510,10 +2595,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         //Inform BGP about the route removal
         LOG.info("clearBgpRoutes : Informing BGP to remove route for externalIP {} of vpn {}", externalIp, vpnName);
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
-        NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, externalIp, vpnName, LOG);
+        NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, externalIp, vpnName);
+        NatUtil.deletePrefixToInterface(dataBroker, NatUtil.getVpnId(dataBroker, vpnName), externalIp);
     }
 
-    private void removeTunnelTableEntry(BigInteger dpnId, long serviceId,
+    private void removeTunnelTableEntry(Uint64 dpnId, Uint32 serviceId,
             TypedReadWriteTransaction<Configuration> writeFlowInvTx) throws ExecutionException, InterruptedException {
         LOG.info("removeTunnelTableEntry : called with DpnId = {} and label = {}", dpnId, serviceId);
         mdsalManager.removeFlow(writeFlowInvTx, dpnId,
@@ -2521,7 +2607,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         LOG.debug("removeTunnelTableEntry : dpID {} : label : {} removed successfully", dpnId, serviceId);
     }
 
-    private void removeLFibTableEntry(BigInteger dpnId, long serviceId,
+    private void removeLFibTableEntry(Uint64 dpnId, Uint32 serviceId,
             TypedReadWriteTransaction<Configuration> writeFlowInvTx) throws ExecutionException, InterruptedException {
         String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
         LOG.debug("removeLFibTableEntry : with flow ref {}", flowRef);
@@ -2536,11 +2622,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
      * @param routerId - router id
      * @param bgpVpnName BGP VPN name
      */
-    public void changeLocalVpnIdToBgpVpnId(String routerName, long routerId, String bgpVpnName,
+    public void changeLocalVpnIdToBgpVpnId(String routerName, Uint32 routerId, String extNetwork, String bgpVpnName,
             TypedWriteTransaction<Configuration> writeFlowInvTx, ProviderTypes extNwProvType) {
         LOG.debug("changeLocalVpnIdToBgpVpnId : Router associated to BGP VPN");
         if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
-            long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
+            Uint32 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
 
             LOG.debug("changeLocalVpnIdToBgpVpnId : BGP VPN ID value {} ", bgpVpnId);
 
@@ -2558,9 +2644,9 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                 addDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, bgpVpnId, writeFlowInvTx);
 
                 // Get the group ID
-                BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
-                installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true, writeFlowInvTx,
-                        extNwProvType);
+                Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
+                installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, new Uuid(extNetwork),
+                    true, writeFlowInvTx, extNwProvType);
             }
         }
     }
@@ -2572,11 +2658,11 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
      * @param routerId - router id
      * @param bgpVpnName BGP VPN name
      */
-    public void changeBgpVpnIdToLocalVpnId(String routerName, long routerId, String bgpVpnName,
+    public void changeBgpVpnIdToLocalVpnId(String routerName, Uint32 routerId, String bgpVpnName, String extNetwork,
             TypedWriteTransaction<Configuration> writeFlowInvTx, ProviderTypes extNwProvType) {
         LOG.debug("changeBgpVpnIdToLocalVpnId : Router dissociated from BGP VPN");
         if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
-            long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
+            Uint32 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
             LOG.debug("changeBgpVpnIdToLocalVpnId : BGP VPN ID value {} ", bgpVpnId);
 
             // Get the allocated Primary NAPT Switch for this router
@@ -2586,9 +2672,9 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             addDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, NatConstants.INVALID_ID, writeFlowInvTx);
 
             // Get the group ID
-            BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
-            installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true,
-                    writeFlowInvTx, extNwProvType);
+            Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
+            installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId,
+                new Uuid(extNetwork), true, writeFlowInvTx, extNwProvType);
         }
     }
 
@@ -2607,28 +2693,29 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId,
-        long routerId, boolean isSnatCfgd, TypedWriteTransaction<Configuration> confTx, ProviderTypes extNwProvType) {
+    public void installFlowsWithUpdatedVpnId(Uint64 primarySwitchId, String routerName, Uint32 bgpVpnId,
+                                             Uint32 routerId, Uuid extNwUuid, boolean isSnatCfgd,
+                                             TypedWriteTransaction<Configuration> confTx, ProviderTypes extNwProvType) {
 
-        long changedVpnId = bgpVpnId;
+        Uint32 changedVpnId = bgpVpnId;
         String idType = "BGP VPN";
         if (bgpVpnId == NatConstants.INVALID_ID) {
             changedVpnId = routerId;
             idType = "router";
         }
 
-        List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
+        List<Uint64> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
         if (switches.isEmpty()) {
             LOG.error("installFlowsWithUpdatedVpnId : No switches found for router {}", routerName);
             return;
         }
-        for (BigInteger dpnId : switches) {
+        for (Uint64 dpnId : switches) {
             // Update the BGP VPN ID in the SNAT miss entry to group
             if (!dpnId.equals(primarySwitchId)) {
                 LOG.debug("installFlowsWithUpdatedVpnId : Install group in non NAPT switch {}", dpnId);
                 List<BucketInfo> bucketInfoForNonNaptSwitches =
                     getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName, routerId);
-                long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
+                Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
                     NatUtil.getGroupIdKey(routerName));
                 if (groupId != NatConstants.INVALID_ID) {
                     if (!isSnatCfgd) {
@@ -2678,16 +2765,23 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
 
                 LOG.debug("installFlowsWithUpdatedVpnId : Installing SNAT PFIB flow in the primary switch {}",
                         primarySwitchId);
-                Long vpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
-                //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
-                if (vpnId != NatConstants.INVALID_ID) {
-                    installNaptPfibEntry(primarySwitchId, vpnId, confTx);
+                //Get the VPN ID from the ExternalNetworks model
+                Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, extNwUuid);
+                if (vpnUuid != null) {
+                    Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+                    //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table
+                    // matching on the VPN ID.
+                    if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
+                        installNaptPfibEntry(primarySwitchId, vpnId, confTx);
+                    }
+                } else {
+                    LOG.error("NAT Service : vpnUuid is null");
                 }
             }
         }
     }
 
-    public void updateNaptFlowsWithVpnId(BigInteger dpnId, String routerName, long routerId, long bgpVpnId) {
+    public void updateNaptFlowsWithVpnId(Uint64 dpnId, String routerName, Uint32 routerId, Uint32 bgpVpnId) {
         //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
         IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
         if (ipPortMapping == null) {
@@ -2731,7 +2825,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.parseInt(internalPort));
                 SessionAddress externalAddress =
                         naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
-                long internetVpnid = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
+                Uint32 internetVpnid = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
                 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid,
                         routerId, bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress);
                 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid,
@@ -2740,22 +2834,23 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
     }
 
-    public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId,
-                                                          long changedVpnId) {
+    public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(Uint64 dpId, String routerName, Uint32 groupId,
+                                                          Uint32 changedVpnId) {
 
         LOG.debug("buildSnatFlowEntityWithUpdatedVpnId : called for dpId {}, routerName {} groupId {} "
             + "changed VPN ID {}", dpId, routerName, groupId, changedVpnId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<ActionInfo> actionsInfo = new ArrayList<>();
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil,
+        Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil,
                 elanManager, idManager, changedVpnId, routerName);
-        actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
+        actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
         LOG.debug("buildSnatFlowEntityWithUpdatedVpnId : Setting the tunnel to the list of action infos {}",
                 actionsInfo);
-        actionsInfo.add(new ActionGroup(groupId));
+        actionsInfo.add(new ActionGroup(groupId.longValue()));
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionApplyActions(actionsInfo));
         String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
@@ -2767,14 +2862,15 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return flowEntity;
     }
 
-    public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName,
-                                                                        long changedVpnId) {
+    public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(Uint64 dpId, String routerName,
+                                                                        Uint32 changedVpnId) {
 
         LOG.debug("buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch : called for dpId {}, routerName {} "
                 + "changed VPN ID {}", dpId, routerName, changedVpnId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
@@ -2789,8 +2885,10 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     }
 
     // TODO : Replace this with ITM Rpc once its available with full functionality
-    protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName,
-        long routerId, long changedVpnId, TypedWriteTransaction<Configuration> confTx, ProviderTypes extNwProvType) {
+    protected void installTerminatingServiceTblEntryWithUpdatedVpnId(Uint64 dpnId, String routerName,
+                                                                     Uint32 routerId, Uint32 changedVpnId,
+                                                                     TypedWriteTransaction<Configuration> confTx,
+                                                                     ProviderTypes extNwProvType) {
 
         LOG.debug("installTerminatingServiceTblEntryWithUpdatedVpnId : called for switch {}, "
             + "routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
@@ -2799,32 +2897,33 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         mdsalManager.addFlow(confTx, flowEntity);
     }
 
-    private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName,
-            long routerIdLongVal, long changedVpnId, ProviderTypes extNwProvType) {
+    private FlowEntity buildTsFlowEntityWithUpdatedVpnId(Uint64 dpId, String routerName,
+                                                         Uint32 routerIdLongVal, Uint32 changedVpnId,
+                                                         ProviderTypes extNwProvType) {
         LOG.debug("buildTsFlowEntityWithUpdatedVpnId : called for switch {}, routerName {}, BGP VPN ID {}",
             dpId, routerName, changedVpnId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
 
-        BigInteger tunnelId = BigInteger.valueOf(changedVpnId);
+        Uint64 tunnelId = Uint64.valueOf(changedVpnId);
         if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
             tunnelId = natOverVxlanUtil.getRouterVni(routerName, changedVpnId);
         }
         matches.add(new MatchTunnelId(tunnelId));
 
         List<InstructionInfo> instructions = new ArrayList<>();
-        instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId),
+        instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
             MetaDataUtil.METADATA_MASK_VRFID));
         instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
-        BigInteger routerId = BigInteger.valueOf(routerIdLongVal);
-        String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
+        Uint32 routerId = routerIdLongVal;
+        String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
             NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
             NwConstants.COOKIE_TS_TABLE, matches, instructions);
         return flowEntity;
     }
 
-    public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId,
+    public void createOutboundTblEntryWithBgpVpn(Uint64 dpnId, Uint32 routerId, Uint32 changedVpnId,
                                                  TypedWriteTransaction<Configuration> writeFlowInvTx) {
         LOG.debug("createOutboundTblEntryWithBgpVpn : called for dpId {} and routerId {}, BGP VPN ID {}",
             dpnId, routerId, changedVpnId);
@@ -2843,15 +2942,16 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         mdsalManager.addFlow(writeFlowInvTx, icmpDropFlow);
     }
 
-    protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId,
-                                                           long changedVpnId, int protocol) {
+    protected FlowEntity buildOutboundFlowEntityWithBgpVpn(Uint64 dpId, Uint32 routerId,
+                                                           Uint32 changedVpnId, int protocol) {
         LOG.debug("buildOutboundFlowEntityWithBgpVpn : called for dpId {} and routerId {}, BGP VPN ID {}",
             dpId, routerId, changedVpnId);
-        BigInteger cookie = getCookieOutboundFlow(routerId);
+        Uint64 cookie = getCookieOutboundFlow(routerId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
         matches.add(new MatchIpProtocol((short)protocol));
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         List<InstructionInfo> instructions = new ArrayList<>();
         List<ActionInfo> actionsInfos = new ArrayList<>();
@@ -2868,7 +2968,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return flowEntity;
     }
 
-    public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId,
+    public void installNaptPfibEntryWithBgpVpn(Uint64 dpnId, Uint32 segmentId, Uint32 changedVpnId,
                                                TypedWriteTransaction<Configuration> writeFlowInvTx) {
         LOG.debug("installNaptPfibEntryWithBgpVpn : called for dpnId {} and segmentId {} ,BGP VPN ID {}",
             dpnId, segmentId, changedVpnId);
@@ -2876,17 +2976,18 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         mdsalManager.addFlow(writeFlowInvTx, naptPfibFlowEntity);
     }
 
-    public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
+    public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(Uint64 dpId, Uint32 segmentId, Uint32 changedVpnId) {
 
         LOG.debug("buildNaptPfibFlowEntityWithUpdatedVpnId : called for dpId {}, "
             + "segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
-        listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
+        listActionInfo.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
         instructionInfo.add(new InstructionApplyActions(listActionInfo));
 
@@ -2903,13 +3004,13 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         return ExternalRoutersListener.this;
     }
 
-    protected void installNaptPfibEntriesForExternalSubnets(String routerName, BigInteger dpnId,
+    protected void installNaptPfibEntriesForExternalSubnets(String routerName, Uint64 dpnId,
                                                         @Nullable TypedWriteTransaction<Configuration> writeFlowInvTx) {
         Collection<Uuid> externalSubnetIdsForRouter = NatUtil.getExternalSubnetIdsForRouter(dataBroker,
                 routerName);
         for (Uuid externalSubnetId : externalSubnetIdsForRouter) {
-            long subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
-            if (subnetVpnId != -1) {
+            Uint32 subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
+            if (subnetVpnId != NatConstants.INVALID_ID) {
                 LOG.debug("installNaptPfibEntriesForExternalSubnets : called for dpnId {} "
                     + "and vpnId {}", dpnId, subnetVpnId);
                 installNaptPfibEntry(dpnId, subnetVpnId, writeFlowInvTx);