NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / VxlanGreConntrackBasedSnatService.java
index b936d4c75ba86330fb20d5b3bcd61ef8609cffd5..e2e1c310ae75d18fafdc174a97a773d4bcf3d1a9 100644 (file)
@@ -7,14 +7,14 @@
  */
 package org.opendaylight.netvirt.natservice.internal;
 
-import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
-import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
@@ -39,9 +39,10 @@ import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
-import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.natservice.ha.NatDataUtil;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
@@ -51,9 +52,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatFlags;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,7 +65,7 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
     private static final Logger LOG = LoggerFactory.getLogger(VxlanGreConntrackBasedSnatService.class);
     private final ExternalRoutersListener externalRouterListener;
     private final IElanService elanManager;
-    private final ManagedNewTransactionRunner txRunner;
+    private final NatOverVxlanUtil natOverVxlanUtil;
 
     public VxlanGreConntrackBasedSnatService(DataBroker dataBroker, IMdsalApiManager mdsalManager,
                                              ItmRpcService itmManager, OdlInterfaceRpcService odlInterfaceRpcService,
@@ -70,123 +73,237 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
                                              ExternalRoutersListener externalRouterListener, IElanService elanManager,
                                              IInterfaceManager interfaceManager,
                                              IVpnFootprintService vpnFootprintService,
-                                             IFibManager fibManager) {
+                                             IFibManager fibManager, NatDataUtil natDataUtil,
+                                             DataTreeEventCallbackRegistrar eventCallbacks,
+                                             NatOverVxlanUtil natOverVxlanUtil) {
         super(dataBroker, mdsalManager, itmManager, idManager, naptSwitchSelector, odlInterfaceRpcService,
-                interfaceManager, vpnFootprintService, fibManager);
+                interfaceManager, vpnFootprintService, fibManager, natDataUtil, eventCallbacks);
         this.externalRouterListener = externalRouterListener;
         this.elanManager = elanManager;
-        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+        this.natOverVxlanUtil = natOverVxlanUtil;
     }
 
     @Override
-    public boolean handleSnatAllSwitch(Routers routers, BigInteger primarySwitchId,  int addOrRemove) {
-        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
+    public boolean addSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+        Uint64 primarySwitchId) {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
         LOG.debug("VxlanGreConntrackBasedSnatService: handleSnatAllSwitch ProviderTypes {}", extNwProviderType);
         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
             LOG.debug("handleSnatAllSwitch : Skip FLAT/VLAN provider networks.");
             return true;
         }
-        return super.handleSnatAllSwitch(routers, primarySwitchId, addOrRemove);
+        return super.addSnatAllSwitch(confTx, routers, primarySwitchId);
     }
 
     @Override
-    public boolean handleSnat(Routers routers, BigInteger primarySwitchId, BigInteger dpnId,  int addOrRemove) {
+    public boolean removeSnatAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 primarySwitchId) throws ExecutionException, InterruptedException {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
+        LOG.debug("VxlanGreConntrackBasedSnatService: handleSnatAllSwitch ProviderTypes {}", extNwProviderType);
+        if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
+            LOG.debug("handleSnatAllSwitch : Skip FLAT/VLAN provider networks.");
+            return true;
+        }
+        return super.removeSnatAllSwitch(confTx, routers, primarySwitchId);
+    }
+
+    public boolean addCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 primarySwitchId) {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
+        LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouterAllSwitch ProviderTypes {}",
+                extNwProviderType);
+        if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
+            LOG.debug("handleCentralizedRouterAllSwitch : Skip FLAT/VLAN provider networks.");
+            return true;
+        }
+        return super.addCentralizedRouterAllSwitch(confTx, routers, primarySwitchId);
+    }
+
+    public boolean removeCentralizedRouterAllSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 primarySwitchId)  throws ExecutionException, InterruptedException {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
+        LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouterAllSwitch ProviderTypes {}",
+                extNwProviderType);
+        if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
+            LOG.debug("handleCentralizedRouterAllSwitch : Skip FLAT/VLAN provider networks.");
+            return true;
+        }
+        return super.removeCentralizedRouterAllSwitch(confTx, routers, primarySwitchId);
+    }
+
+    public boolean addCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 primarySwitchId, Uint64 dpnId) {
         ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
+        LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouter ProviderTypes {}", extNwProviderType);
+        if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
+            LOG.debug("handleCentralizedRouter : Skip FLAT/VLAN provider networks.");
+            return true;
+        }
+        return super.addCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
+    }
+
+    public boolean removeCentralizedRouter(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 primarySwitchId, Uint64 dpnId)  throws ExecutionException, InterruptedException {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(dataBroker, routers.getNetworkId());
+        LOG.debug("VxlanGreConntrackBasedSnatService: handleCentralizedRouter ProviderTypes {}", extNwProviderType);
+        if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
+            LOG.debug("handleCentralizedRouter : Skip FLAT/VLAN provider networks.");
+            return true;
+        }
+        return super.removeCentralizedRouter(confTx, routers, primarySwitchId, dpnId);
+    }
+
+    @Override
+    public boolean addSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+        Uint64 primarySwitchId, Uint64 dpnId) {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
+        LOG.debug("VxlanGreConntrackBasedSnatService: handleSnat ProviderTypes {}", extNwProviderType);
+        if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
+            LOG.debug("handleSnat : Skip FLAT/VLAN provider networks.");
+            return true;
+        }
+        return super.addSnat(confTx, routers, primarySwitchId, dpnId);
+    }
+
+    @Override
+    public boolean removeSnat(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 primarySwitchId, Uint64 dpnId) throws ExecutionException, InterruptedException {
+        ProviderTypes extNwProviderType = NatUtil.getProviderTypefromNetworkId(confTx, routers.getNetworkId());
         LOG.debug("VxlanGreConntrackBasedSnatService: handleSnat ProviderTypes {}", extNwProviderType);
         if (extNwProviderType == ProviderTypes.FLAT || extNwProviderType == ProviderTypes.VLAN) {
             LOG.debug("handleSnat : Skip FLAT/VLAN provider networks.");
             return true;
         }
-        return super.handleSnat(routers, primarySwitchId, dpnId, addOrRemove);
+        return super.removeSnat(confTx, routers, primarySwitchId, dpnId);
     }
 
     @Override
-    protected void installSnatSpecificEntriesForNaptSwitch(Routers routers, BigInteger dpnId, int addOrRemove) {
+    protected void addSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+        Uint64 dpnId) {
+
         LOG.info("installSnatSpecificEntriesForNaptSwitch for router {}",
-                routers.getRouterName());
+            routers.getRouterName());
         String routerName = routers.getRouterName();
-        Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
         int elanId = NatUtil.getElanInstanceByName(routers.getNetworkId().getValue(), dataBroker)
-                .getElanTag().intValue();
+            .getElanTag().intValue();
         /* Install Outbound NAT entries */
 
-        installSnatMissEntryForPrimrySwch(dpnId, routerId, elanId, addOrRemove);
-        installTerminatingServiceTblEntryForVxlanGre(dpnId, routerName, routerId, elanId, addOrRemove);
+        addSnatMissEntryForPrimrySwch(confTx, dpnId, routerId, elanId);
+        addTerminatingServiceTblEntryForVxlanGre(confTx, dpnId, routerName, routerId, elanId);
         //Long extNetVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, routers.getNetworkId());
         if (vpnUuid == null) {
             LOG.error("installSnatSpecificEntriesForNaptSwitch: Unable to retrieve external vpn_id for "
-                    + "external network {} with routerId {}", routers.getNetworkId(), routerId);
+                + "external network {} with routerId {}", routers.getNetworkId(), routerId);
             return;
         }
-        Long extNetVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
-        /*//Long extNetVpnId = NatUtil.getAssociatedVPN(dataBroker, routers.getNetworkId(), LOG);
-        if (extNetVpnId == NatConstants.INVALID_ID && addOrRemove == NwConstants.ADD_FLOW) {
+        Uint32 extNetVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+        LOG.info("installSnatSpecificEntriesForNaptSwitch: external network vpn_id {} for router {}",
+            extNetVpnId, routers.getRouterName());
+        List<ExternalIps> externalIps = routers.getExternalIps();
+        addOutboundTblTrackEntryForVxlanGre(confTx, dpnId, routerId, extNetVpnId);
+        addOutboundTblEntryForVxlanGre(confTx, dpnId, routerId, extNetVpnId, externalIps, elanId);
+        addNaptPfibFlowForVxlanGre(confTx, routers, dpnId, extNetVpnId);
+        addNaptPfibEntry(confTx, dpnId, routerId);
+
+        //Install Inbound NAT entries
+        addInboundEntryForVxlanGre(confTx, dpnId, routerId, extNetVpnId, externalIps, elanId);
+        if (externalIps.isEmpty()) {
+            LOG.error("installSnatSpecificEntriesForNaptSwitch: No externalIP present for router {}",
+                routerName);
+            return;
+        }
+        //The logic now handle only one external IP per router, others if present will be ignored.
+        String externalIp = NatUtil.validateAndAddNetworkMask(externalIps.get(0).getIpAddress());
+        externalRouterListener.handleSnatReverseTraffic(confTx, dpnId, routers, routerId, routerName, externalIp);
+    }
+
+    @Override
+    protected void removeSnatSpecificEntriesForNaptSwitch(TypedReadWriteTransaction<Configuration> confTx,
+            Routers routers, Uint64 dpnId) throws ExecutionException, InterruptedException {
+
+        LOG.info("installSnatSpecificEntriesForNaptSwitch for router {}",
+            routers.getRouterName());
+        String routerName = routers.getRouterName();
+        Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
+
+        /* Remove Outbound NAT entries */
+        removeSnatMissEntryForPrimrySwch(confTx, dpnId, routerId);
+        removeTerminatingServiceTblEntryForVxlanGre(confTx, dpnId, routerId);
+        //Long extNetVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
+        Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, routers.getNetworkId());
+        if (vpnUuid == null) {
             LOG.error("installSnatSpecificEntriesForNaptSwitch: Unable to retrieve external vpn_id for "
-                    + "external network {} with routerId {}", routers.getNetworkId(), routerId);
+                + "external network {} with routerId {}", routers.getNetworkId(), routerId);
             return;
-        }*/
+        }
+        Uint32 extNetVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
         LOG.info("installSnatSpecificEntriesForNaptSwitch: external network vpn_id {} for router {}",
-                extNetVpnId, routers.getRouterName());
+            extNetVpnId, routers.getRouterName());
         List<ExternalIps> externalIps = routers.getExternalIps();
-        createOutboundTblTrackEntryForVxlanGre(dpnId, routerId, extNetVpnId, addOrRemove);
-        createOutboundTblEntryForVxlanGre(dpnId, routerId, extNetVpnId, externalIps, elanId, addOrRemove);
-        installNaptPfibFlowForVxlanGre(routers, dpnId, extNetVpnId, addOrRemove);
-        installNaptPfibEntry(dpnId, routerId, addOrRemove);
+        removeOutboundTblTrackEntryForVxlanGre(confTx, dpnId, routerId);
+        removeOutboundTblEntryForVxlanGre(confTx, dpnId, routerId, externalIps);
+        removeNaptPfibFlowForVxlanGre(confTx, routers, dpnId, extNetVpnId);
+        removeNaptPfibEntry(confTx, dpnId, routerId);
 
         //Install Inbound NAT entries
-        installInboundEntryForVxlanGre(dpnId, routerId, extNetVpnId, externalIps, elanId, addOrRemove);
+        removeInboundEntryForVxlanGre(confTx, dpnId, routerId, externalIps);
         if (externalIps.isEmpty()) {
             LOG.error("installSnatSpecificEntriesForNaptSwitch: No externalIP present for router {}",
-                    routerName);
+                routerName);
             return;
         }
         //The logic now handle only one external IP per router, others if present will be ignored.
         String externalIp = NatUtil.validateAndAddNetworkMask(externalIps.get(0).getIpAddress());
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
-            if (addOrRemove == NwConstants.ADD_FLOW) {
-                externalRouterListener.handleSnatReverseTraffic(dpnId, routers, routerId, routerName, externalIp, tx);
-            } else {
-                externalRouterListener.clearFibTsAndReverseTraffic(dpnId, routerId, routers.getNetworkId(),
-                        Collections.singletonList(externalIp), null, routers.getExtGwMacAddress(), tx);
-            }
-        }), LOG, "Error installing SNAT-specific entries for NAPT switch");
+        externalRouterListener.clearFibTsAndReverseTraffic(dpnId, routerId, routers.getNetworkId(),
+            Collections.singletonList(externalIp), null, routers.getExtGwMacAddress(), confTx);
     }
 
-    protected void createOutboundTblTrackEntryForVxlanGre(BigInteger dpnId, Long routerId, Long extNetVpnId,
-                                               int addOrRemove) {
+    protected void addOutboundTblTrackEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId,
+                                                       Uint32 routerId, Uint32 extNetVpnId) {
         LOG.info("createOutboundTblTrackEntryForVxlanGre: Install Outbound tracking table flow on dpId {} for "
                 + "routerId {}", dpnId, routerId);
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
         matches.add(new NxMatchCtState(SNAT_CT_STATE, SNAT_CT_STATE_MASK));
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
-                    .getVpnIdMetadata(extNetVpnId));
-            listActionInfo.add(actionSetFieldMeta);
-        }
+        ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(
+                MetaDataUtil.getVpnIdMetadata(extNetVpnId.longValue()));
+        listActionInfo.add(actionSetFieldMeta);
         ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
         listActionInfo.add(new ActionNxResubmit(NwConstants.NAPT_PFIB_TABLE));
         instructionInfo.add(new InstructionApplyActions(listActionInfo));
 
-        String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
-        flowRef += "trkest";
-        syncFlow(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef,
-                NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo, addOrRemove);
+        String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
+        NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
+                NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
+
+    }
+
+    protected void removeOutboundTblTrackEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx,
+            Uint64 dpnId, Uint32 routerId) throws ExecutionException, InterruptedException {
+        LOG.info("createOutboundTblTrackEntryForVxlanGre: Install Outbound tracking table flow on dpId {} for "
+            + "routerId {}", dpnId, routerId);
+
+        String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId) + "trkest";
+        NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
 
     }
 
-    protected void createOutboundTblEntryForVxlanGre(BigInteger dpnId, long routerId, Long extNetVpnId,
-                                                     List<ExternalIps> externalIps, int elanId, int addOrRemove) {
+    protected void addOutboundTblEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId,
+                                                  Uint32 routerId, Uint32 extNetVpnId, List<ExternalIps> externalIps,
+                                                  int elanId) {
         LOG.info("createOutboundTblEntryForVxlanGre: Install Outbound table flow on dpId {} for routerId {}", dpnId,
                 routerId);
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
         matches.add(new NxMatchCtState(TRACKED_NEW_CT_STATE, TRACKED_NEW_CT_MASK));
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
         if (externalIps.isEmpty()) {
             LOG.error("createOutboundTblEntryForVxlanGre: No externalIP present for routerId {}",
                     routerId);
@@ -195,17 +312,14 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
         //The logic now handle only one external IP per router, others if present will be ignored.
         String externalIp = externalIps.get(0).getIpAddress();
         List<ActionInfo> actionsInfos = new ArrayList<>();
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
-                    .getVpnIdMetadata(extNetVpnId));
-            actionsInfos.add(actionSetFieldMeta);
-        }
+        ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
+                .getVpnIdMetadata(extNetVpnId.longValue()));
+        actionsInfos.add(actionSetFieldMeta);
         List<ActionNxConntrack.NxCtAction> ctActionsListCommit = new ArrayList<>();
         int rangePresent = NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue();
         int flags = NxActionNatFlags.NXNATFSRC.getIntValue();
         ActionNxConntrack.NxCtAction nxCtActionCommit = new ActionNxConntrack.NxNat(0, flags, rangePresent,
-                new IpPrefixOrAddress(externalIp.toCharArray()).getIpAddress(),
-                null,0, 0);
+            IpPrefixOrAddressBuilder.getDefaultInstance(externalIp).getIpAddress(), null,0, 0);
         ctActionsListCommit.add(nxCtActionCommit);
         int ctCommitFlag = 1;
         ActionNxConntrack actionNxConntrackSubmit = new ActionNxConntrack(ctCommitFlag, 0, elanId,
@@ -214,32 +328,54 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionApplyActions(actionsInfos));
         String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
-        syncFlow(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,  NatConstants.SNAT_NEW_FLOW_PRIORITY,
-                flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions, addOrRemove);
+        NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
+                NatConstants.SNAT_NEW_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
+    }
+
+    protected void removeOutboundTblEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId,
+                                                     Uint32 routerId, List<ExternalIps> externalIps)
+            throws ExecutionException, InterruptedException {
+        LOG.info("createOutboundTblEntryForVxlanGre: Install Outbound table flow on dpId {} for routerId {}", dpnId,
+            routerId);
+        if (externalIps.isEmpty()) {
+            LOG.error("createOutboundTblEntryForVxlanGre: No externalIP present for routerId {}",
+                routerId);
+            return;
+        }
+        //The logic now handle only one external IP per router, others if present will be ignored.
+        String flowRef = getFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
+        NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef);
     }
 
-    protected void installNaptPfibFlowForVxlanGre(Routers routers, BigInteger dpnId, Long extNetVpnId,
-                                                  int addOrRemove) {
+    protected void addNaptPfibFlowForVxlanGre(TypedWriteTransaction<Configuration> confTx, Routers routers,
+        Uint64 dpnId, Uint32 extNetVpnId) {
         LOG.info("installNaptPfibFlowForVxlanGre: Install Napt preFibFlow on dpId {} with matching extNetVpnId {} "
                 + "for router {}", dpnId, extNetVpnId, routers.getRouterName());
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNetVpnId),
-                    MetaDataUtil.METADATA_MASK_VRFID));
-        }
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNetVpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
         ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
         ArrayList<InstructionInfo> instructions = new ArrayList<>();
-        listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
+        listActionInfo.add(new ActionNxLoadInPort(Uint64.ZERO));
         listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
         instructions.add(new InstructionApplyActions(listActionInfo));
         String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, extNetVpnId);
-        syncFlow(dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef, NatConstants.SNAT_TRK_FLOW_PRIORITY,
-                flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions, addOrRemove);
+        NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef,
+                NatConstants.SNAT_TRK_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
     }
 
-    protected void installInboundEntryForVxlanGre(BigInteger dpnId, long routerId, Long extNeVpnId,
-                                                  List<ExternalIps> externalIps, int elanId, int addOrRemove) {
+    protected void removeNaptPfibFlowForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Routers routers,
+            Uint64 dpnId, Uint32 extNetVpnId) throws ExecutionException, InterruptedException {
+        LOG.info("installNaptPfibFlowForVxlanGre: Install Napt preFibFlow on dpId {} with matching extNetVpnId {} "
+            + "for router {}", dpnId, extNetVpnId, routers.getRouterName());
+        String flowRef = getFlowRef(dpnId, NwConstants.NAPT_PFIB_TABLE, extNetVpnId);
+        NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.NAPT_PFIB_TABLE, flowRef);
+    }
+
+    protected void addInboundEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId,
+                                              Uint32 routerId, Uint32 extNeVpnId, List<ExternalIps> externalIps,
+                                              int elanId) {
         LOG.info("installInboundEntryForVxlanGre:  Install Inbound table entry on dpId {} for routerId {}",
                 dpnId, routerId);
         List<MatchInfoBase> matches = new ArrayList<>();
@@ -251,15 +387,13 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
         }
         String externalIp = externalIps.get(0).getIpAddress();
         matches.add(new MatchIpv4Destination(externalIp,"32"));
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNeVpnId),
-                    MetaDataUtil.METADATA_MASK_VRFID));
-        }
+        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(extNeVpnId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
         List<ActionInfo> actionsInfos = new ArrayList<>();
         List<ActionNxConntrack.NxCtAction> ctActionsList = new ArrayList<>();
         ActionNxConntrack.NxCtAction nxCtAction = new ActionNxConntrack.NxNat(0, 0, 0,null, null,0, 0);
         ActionSetFieldMeta actionSetFieldMeta = new ActionSetFieldMeta(MetaDataUtil
-                .getVpnIdMetadata(routerId));
+                .getVpnIdMetadata(routerId.longValue()));
         actionsInfos.add(actionSetFieldMeta);
         ctActionsList.add(nxCtAction);
         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(0, 0, elanId, NwConstants
@@ -269,20 +403,35 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionApplyActions(actionsInfos));
         String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
-        syncFlow(dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef, NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
-                NwConstants.COOKIE_SNAT_TABLE, matches, instructions, addOrRemove);
+        NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef,
+                NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
+    }
+
+    protected void removeInboundEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId,
+                                                 Uint32 routerId, List<ExternalIps> externalIps)
+            throws ExecutionException, InterruptedException {
+        LOG.info("removeInboundEntryForVxlanGre: remove Inbound table entry on dpId {} for routerId {}",
+            dpnId, routerId);
+        if (externalIps.isEmpty()) {
+            LOG.error("removeInboundEntryForVxlanGre : createInboundTblEntry no externalIP present for routerId {}",
+                routerId);
+            return;
+        }
+
+        String flowRef = getFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId);
+        NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.INBOUND_NAPT_TABLE, flowRef);
     }
 
-    protected void installTerminatingServiceTblEntryForVxlanGre(BigInteger dpnId, String routerName,
-            Long  routerId, int elanId, int addOrRemove) {
+    protected void addTerminatingServiceTblEntryForVxlanGre(TypedWriteTransaction<Configuration> confTx,
+        Uint64 dpnId, String routerName, Uint32 routerId, int elanId) {
         LOG.info("installTerminatingServiceTblEntryForVxlanGre : creating entry for"
                 + "Terminating Service Table for switch {}, routerId {}", dpnId, routerId);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
 
-        BigInteger tunnelId = BigInteger.valueOf(routerId);
+        Uint64 tunnelId = Uint64.valueOf(routerId);
         if (elanManager.isOpenStackVniSemanticsEnforced()) {
-            tunnelId = NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId);
+            tunnelId = natOverVxlanUtil.getRouterVni(routerName, routerId);
         }
         matches.add(new MatchTunnelId(tunnelId));
 
@@ -298,55 +447,86 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
         actionsInfos.add(actionNxConntrack);
         List<InstructionInfo> instructions = new ArrayList<>();
         instructions.add(new InstructionApplyActions(actionsInfos));
-        String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
-        syncFlow(dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef, NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef,
-                 NwConstants.COOKIE_SNAT_TABLE, matches, instructions, addOrRemove);
+        String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
+        NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
+                NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
 
     }
 
-    protected void installSnatMissEntry(BigInteger dpnId, Long routerId, String routerName, BigInteger primarySwitchId,
-            int addOrRemove) {
-        LOG.debug("installSnatMissEntry : Installing SNAT miss entry in switch {}", dpnId);
+    protected void removeTerminatingServiceTblEntryForVxlanGre(TypedReadWriteTransaction<Configuration> confTx,
+            Uint64 dpnId, Uint32 routerId) throws ExecutionException, InterruptedException {
+        LOG.info("removeTerminatingServiceTblEntryForVxlanGre : removing entry for"
+            + "Terminating Service Table for switch {}, routerId {}", dpnId, routerId);
+
+        String flowRef = getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
+        NatUtil.removeFlow(confTx, mdsalManager, dpnId,  NwConstants.INTERNAL_TUNNEL_TABLE, flowRef);
+
+    }
+
+    @Override
+    protected void addSnatMissEntry(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId, Uint32 routerId,
+        String routerName, Uint64 primarySwitchId) {
+        LOG.debug("addSnatMissEntry : Installing SNAT miss entry in switch {}", dpnId);
         List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
-        String ifNamePrimary = getTunnelInterfaceName(dpnId, primarySwitchId);
+        String ifNamePrimary = NatUtil.getTunnelInterfaceName(dpnId, primarySwitchId, itmManager);
         List<BucketInfo> listBucketInfo = new ArrayList<>();
         if (ifNamePrimary != null) {
-            LOG.debug("installSnatMissEntry : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
+            LOG.debug("addSnatMissEntry : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
             listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
                     interfaceManager, ifNamePrimary, routerId, true);
         }
         BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
         listBucketInfo.add(0, bucketPrimary);
-        LOG.debug("installSnatMissEntry : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId,
+        LOG.debug("addSnatMissEntry : addSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId,
                 listBucketInfo.get(0));
         // Install the select group
-        long groupId = createGroupId(getGroupIdKey(routerName));
-        GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll,
-                listBucketInfo);
-        LOG.debug("installSnatMissEntry : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
-        mdsalManager.installGroup(groupEntity);
-        // Install miss entry pointing to group
-        LOG.debug("installSnatMissEntry : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}",
+        Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, getGroupIdKey(routerName));
+        if (groupId != NatConstants.INVALID_ID) {
+            GroupEntity groupEntity = MDSALUtil
+                .buildGroupEntity(dpnId, groupId.longValue(), routerName, GroupTypes.GroupAll,
+                    listBucketInfo);
+            LOG.debug("addSnatMissEntry : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
+            mdsalManager.addGroup(confTx, groupEntity);
+            // Install miss entry pointing to group
+            LOG.debug(
+                "addSnatMissEntry : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}",
                 dpnId, routerName, groupId);
-        List<MatchInfo> matches = new ArrayList<>();
-        matches.add(new MatchEthernetType(0x0800L));
-        matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
+            List<MatchInfo> matches = new ArrayList<>();
+            matches.add(new MatchEthernetType(0x0800L));
+            matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
+                MetaDataUtil.METADATA_MASK_VRFID));
 
-        List<ActionInfo> actionsInfo = new ArrayList<>();
+            List<ActionInfo> actionsInfo = new ArrayList<>();
 
-        BigInteger tunnelId = BigInteger.valueOf(routerId);
-        if (elanManager.isOpenStackVniSemanticsEnforced()) {
-            tunnelId = NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId);
+            Uint64 tunnelId = Uint64.valueOf(routerId);
+            if (elanManager.isOpenStackVniSemanticsEnforced()) {
+                tunnelId = natOverVxlanUtil.getRouterVni(routerName, routerId);
+            }
+
+            actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
+            LOG.debug("addSnatMissEntry : Setting the tunnel to the list of action infos {}",
+                actionsInfo);
+            actionsInfo.add(new ActionGroup(groupId.longValue()));
+            List<InstructionInfo> instructions = new ArrayList<>();
+            instructions.add(new InstructionApplyActions(actionsInfo));
+            String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
+            NatUtil.addFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef,
+                NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, NwConstants.COOKIE_SNAT_TABLE,
+                matches,
+                instructions);
+        } else {
+            LOG.error("installSnatMissEntry: Unable to get groupId for router:{}", routerName);
         }
+    }
+
+    @Override
+    protected void removeSnatMissEntry(TypedReadWriteTransaction<Configuration> confTx, Uint64 dpnId,
+                                       Uint32 routerId, String routerName)
+            throws ExecutionException, InterruptedException {
+        LOG.debug("installSnatMissEntry : Removing SNAT miss entry in switch {}", dpnId);
 
-        actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
-        LOG.debug("AbstractSnatService : Setting the tunnel to the list of action infos {}", actionsInfo);
-        actionsInfo.add(new ActionGroup(groupId));
-        List<InstructionInfo> instructions = new ArrayList<>();
-        instructions.add(new InstructionApplyActions(actionsInfo));
         String flowRef = getFlowRef(dpnId, NwConstants.PSNAT_TABLE, routerId);
-        syncFlow(dpnId, NwConstants.PSNAT_TABLE, flowRef,  NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef,
-                NwConstants.COOKIE_SNAT_TABLE, matches, instructions, addOrRemove);
+        NatUtil.removeFlow(confTx, mdsalManager, dpnId, NwConstants.PSNAT_TABLE, flowRef);
     }
 
 }