IPv6 CVR North-South Support
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatUtil.java
index eb37c2feaddc1157680828e35febbeb5f0bf5d5b..d9708410cb36eaa96a0588892ca177b2ac5cbed5 100644 (file)
@@ -8,11 +8,16 @@
 
 package org.opendaylight.netvirt.natservice.internal;
 
+import static java.util.Collections.emptyList;
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.math.BigInteger;
 import java.net.InetAddress;
@@ -51,6 +56,7 @@ import org.opendaylight.genius.mdsalutil.GroupEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
@@ -98,6 +104,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
@@ -110,6 +122,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
@@ -118,7 +132,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
@@ -243,6 +256,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -253,6 +270,9 @@ public final class NatUtil {
 
     private static String OF_URI_SEPARATOR = ":";
     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
+    private static final String OTHER_CONFIG_PARAMETERS_DELIMITER = ",";
+    private static final String OTHER_CONFIG_KEY_VALUE_DELIMITER = ":";
+    private static final String PROVIDER_MAPPINGS = "provider_mappings";
 
     private NatUtil() { }
 
@@ -277,7 +297,7 @@ public final class NatUtil {
     /*
         getVpnId() returns the VPN ID from the VPN name
      */
-    public static long getVpnId(DataBroker broker, String vpnName) {
+    public static long getVpnId(DataBroker broker, @Nullable String vpnName) {
         if (vpnName == null) {
             return NatConstants.INVALID_ID;
         }
@@ -364,6 +384,7 @@ public final class NatUtil {
                     .instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
     }
 
+    @Nullable
     static String getVpnInstanceFromVpnIdentifier(DataBroker broker, long vpnId) {
         InstanceIdentifier<VpnIds> id = InstanceIdentifier.builder(VpnIdToVpnInstance.class)
             .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
@@ -390,6 +411,7 @@ public final class NatUtil {
                 + port;
     }
 
+    @Nullable
     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
         String routerName = getRouterName(broker, routerId);
         if (routerName == null) {
@@ -399,6 +421,7 @@ public final class NatUtil {
         return getNetworkIdFromRouterName(broker, routerName);
     }
 
+    @Nullable
     static Uuid getNetworkIdFromRouterName(DataBroker broker, String routerName) {
         if (routerName == null) {
             LOG.error("getNetworkIdFromRouterName - empty routerName received");
@@ -434,6 +457,7 @@ public final class NatUtil {
                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::isEnableSnat).orElse(false);
     }
 
+    @Nullable
     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -450,6 +474,7 @@ public final class NatUtil {
         }
     }
 
+    @Nullable
     public static ProviderTypes getProviderTypefromNetworkId(DataBroker broker, Uuid networkId) {
         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -472,9 +497,10 @@ public final class NatUtil {
         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Networks::getRouterIds).orElse(
-                Collections.emptyList());
+                emptyList());
     }
 
+    @Nullable
     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
         Optional<Routers> routerData =
@@ -495,6 +521,7 @@ public final class NatUtil {
             .child(Networks.class, new NetworksKey(networkId)).build();
     }
 
+    @Nullable
     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
         // convert routerId to Name
         String routerName = getRouterName(broker, routerId);
@@ -505,6 +532,7 @@ public final class NatUtil {
         return getPrimaryNaptfromRouterName(broker, routerName);
     }
 
+    @Nullable
     public static BigInteger getPrimaryNaptfromRouterName(DataBroker broker, String routerName) {
         if (routerName == null) {
             LOG.error("getPrimaryNaptfromRouterName - empty routerName received");
@@ -517,9 +545,8 @@ public final class NatUtil {
     }
 
     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
-        InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
-            .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
-        return rtrNaptSw;
+        return InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class,
+            new RouterToNaptSwitchKey(routerId)).build();
     }
 
     public static Optional<NaptSwitches> getAllPrimaryNaptSwitches(DataBroker broker) {
@@ -527,6 +554,7 @@ public final class NatUtil {
                 LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier());
     }
 
+    @Nullable
     public static String getRouterName(DataBroker broker, Long routerId) {
         return getVpnInstanceFromVpnIdentifier(broker, routerId);
     }
@@ -558,6 +586,7 @@ public final class NatUtil {
             + ((rawIpAddress[2] & 0xFF) << 1 * 8) + (rawIpAddress[3] & 0xFF) & 0xffffffffL;
     }
 
+    @Nullable
     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
         String nextHopIp = null;
         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
@@ -575,8 +604,8 @@ public final class NatUtil {
         return nextHopIp;
     }
 
+    @Nullable
     public static String getVpnRd(DataBroker broker, String vpnName) {
-
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -585,6 +614,7 @@ public final class NatUtil {
                         .VpnInstance::getVrfId).orElse(null);
     }
 
+    @Nullable
     public static String getVpnRd(TypedReadTransaction<Configuration> tx, String vpnName) {
         try {
             return tx.read(getVpnInstanceToVpnIdIdentifier(vpnName)).get().toJavaUtil().map(
@@ -596,6 +626,7 @@ public final class NatUtil {
         }
     }
 
+    @Nullable
     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress,
                                                       String internalPort, NAPTEntryEvent.Protocol protocol) {
         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
@@ -620,12 +651,14 @@ public final class NatUtil {
             .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
     }
 
+    @Nullable
     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                 LogicalDatastoreType.CONFIGURATION, interfaceId).orNull();
     }
 
+    @Nullable
     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
         /*
          * NodeConnectorId is of form 'openflow:dpnid:portnum'
@@ -646,6 +679,7 @@ public final class NatUtil {
         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
     }
 
+    @Nullable
     public static String getRouterIdfromVpnInstance(DataBroker broker, String vpnName) {
         // returns only router, attached to IPv4 networks
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
@@ -682,6 +716,7 @@ public final class NatUtil {
         return null;
     }
 
+    @Nullable
     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
         Preconditions.checkNotNull(routerId, "dissociateRouter: routerId not found!");
         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
@@ -689,18 +724,22 @@ public final class NatUtil {
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                         LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
-            List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
-            for (VpnMap vpnMap: allMaps) {
+            for (VpnMap vpnMap : requireNonNullElse(optionalVpnMaps.get().getVpnMap(),
+                    Collections.<VpnMap>emptyList())) {
                 if (routerId.equals(vpnMap.getVpnId().getValue())) {
                     continue;
                 }
                 List<Uuid> routerIdsList = NeutronUtils.getVpnMapRouterIdsListUuid(vpnMap.getRouterIds());
-                if (routerIdsList == null || routerIdsList.isEmpty()) {
+                if (routerIdsList.isEmpty()) {
                     return null;
                 }
-                //Skip if current VPN is already associated with network
-                if (vpnMap.getNetworkIds() != null) {
-                    continue;
+                // Skip router vpnId fetching from internet BGP-VPN
+                if (vpnMap.getNetworkIds() != null && !vpnMap.getNetworkIds().isEmpty()) {
+                    // We only need to check the first network; if it’s not an external network there’s no
+                    // need to check the rest of the VPN’s network list
+                    if (isExternalNetwork(broker, vpnMap.getNetworkIds().iterator().next())) {
+                        continue;
+                    }
                 }
                 if (routerIdsList.contains(new Uuid(routerId))) {
                     return vpnMap.getVpnId();
@@ -718,6 +757,7 @@ public final class NatUtil {
                 NatConstants.INVALID_ID);
     }
 
+    @Nullable
     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId) {
         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
         if (vpnUuid == null) {
@@ -727,6 +767,7 @@ public final class NatUtil {
         return vpnUuid.getValue();
     }
 
+    @Nullable
     public static String getAssociatedVPN(TypedReadTransaction<Configuration> tx, Uuid networkId) {
         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(tx, networkId);
         if (vpnUuid == null) {
@@ -743,11 +784,10 @@ public final class NatUtil {
                                       IFibManager fibManager,
                                       String vpnName,
                                       String rd,
-                                      Uuid subnetId,
                                       String prefix,
                                       String nextHopIp,
-                                      String parentVpnRd,
-                                      String macAddress,
+                                      @Nullable String parentVpnRd,
+                                      @Nullable String macAddress,
                                       long label,
                                       long l3vni,
                                       RouteOrigin origin,
@@ -762,7 +802,7 @@ public final class NatUtil {
             }
 
             addPrefixToInterface(broker, getVpnId(broker, vpnName), null /*interfaceName*/,prefix, parentVpnRd,
-                    subnetId, dpId, Prefixes.PrefixCue.Nat);
+                dpId, Prefixes.PrefixCue.Nat);
             fibManager.addOrUpdateFibEntry(rd, macAddress, prefix,
                     Collections.singletonList(nextHopIp), VrfEntry.EncapType.Mplsgre, (int)label, l3vni /*l3vni*/,
                     null /*gatewayMacAddress*/, parentVpnRd, origin, null /*writeTxn*/);
@@ -780,8 +820,8 @@ public final class NatUtil {
         }
     }
 
-    static void addPrefixToInterface(DataBroker broker, long vpnId, String interfaceName, String ipPrefix,
-                                     String networkId, Uuid subnetId, BigInteger dpId, Prefixes.PrefixCue prefixCue) {
+    static void addPrefixToInterface(DataBroker broker, long vpnId, @Nullable String interfaceName, String ipPrefix,
+                                     String networkId, BigInteger dpId, Prefixes.PrefixCue prefixCue) {
         InstanceIdentifier<Prefixes> prefixId = InstanceIdentifier.builder(PrefixToInterface.class)
                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
                         .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix
@@ -831,7 +871,7 @@ public final class NatUtil {
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                 LogicalDatastoreType.CONFIGURATION,
                 buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType)).toJavaUtil().map(
-                IntIpProtoType::getPorts).orElse(Collections.emptyList());
+                IntIpProtoType::getPorts).orElse(emptyList());
     }
 
     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId,
@@ -912,6 +952,7 @@ public final class NatUtil {
         }
     }
 
+    @Nullable
     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                 LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId)).orNull();
@@ -924,12 +965,11 @@ public final class NatUtil {
 
     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
         .natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
-        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
-            .intext.ip.map.IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
+        return InstanceIdentifier.builder(IntextIpMap.class)
             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map
                 .IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
-                .intext.ip.map.IpMappingKey(routerId)).build();
-        return idBuilder;
+                .intext.ip.map.IpMappingKey(routerId))
+            .build();
     }
 
     @Nonnull
@@ -941,8 +981,7 @@ public final class NatUtil {
         // Ensure there are no duplicates
         Collection<String> externalIps = new HashSet<>();
         if (ipMappingOptional.isPresent()) {
-            List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
-            for (IpMap ipMap : ipMaps) {
+            for (IpMap ipMap : requireNonNullElse(ipMappingOptional.get().getIpMap(), Collections.<IpMap>emptyList())) {
                 externalIps.add(ipMap.getExternalIp());
             }
         }
@@ -956,7 +995,7 @@ public final class NatUtil {
             return NatUtil.getIpsListFromExternalIps(routerData.getExternalIps());
         }
 
-        return Collections.emptyList();
+        return emptyList();
     }
 
     @Nonnull
@@ -967,14 +1006,14 @@ public final class NatUtil {
                         LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
         Map<String, Long> externalIpsLabel = new HashMap<>();
         if (ipMappingOptional.isPresent()) {
-            List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
-            for (IpMap ipMap : ipMaps) {
+            for (IpMap ipMap : requireNonNullElse(ipMappingOptional.get().getIpMap(), Collections.<IpMap>emptyList())) {
                 externalIpsLabel.put(ipMap.getExternalIp(), ipMap.getLabel());
             }
         }
         return externalIpsLabel;
     }
 
+    @Nullable
     public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId) {
         String leastLoadedExternalIp = null;
         InstanceIdentifier<ExternalCounters> id =
@@ -984,9 +1023,9 @@ public final class NatUtil {
             MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
         if (externalCountersData.isPresent()) {
             ExternalCounters externalCounter = externalCountersData.get();
-            List<ExternalIpCounter> externalIpCounterList = externalCounter.getExternalIpCounter();
             short countOfLstLoadExtIp = 32767;
-            for (ExternalIpCounter externalIpCounter : externalIpCounterList) {
+            for (ExternalIpCounter externalIpCounter : requireNonNullElse(externalCounter.getExternalIpCounter(),
+                    Collections.<ExternalIpCounter>emptyList())) {
                 String curExternalIp = externalIpCounter.getExternalIp();
                 short countOfCurExtIp = externalIpCounter.getCounter();
                 if (countOfCurExtIp < countOfLstLoadExtIp) {
@@ -999,6 +1038,7 @@ public final class NatUtil {
     }
 
     @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
+    @Nullable
     public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId) {
         String subnetIP = getSubnetIp(dataBroker, subnetId);
         if (subnetIP != null) {
@@ -1008,6 +1048,7 @@ public final class NatUtil {
         return null;
     }
 
+    @Nonnull
     public static String[] getSubnetIpAndPrefix(String subnetString) {
         String[] subnetSplit = subnetString.split("/");
         String subnetIp = subnetSplit[0];
@@ -1018,6 +1059,7 @@ public final class NatUtil {
         return new String[] {subnetIp, subnetPrefix};
     }
 
+    @Nullable
     public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId) {
         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
             .builder(Subnetmaps.class)
@@ -1025,7 +1067,6 @@ public final class NatUtil {
             .build();
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                 LogicalDatastoreType.CONFIGURATION, subnetmapId).toJavaUtil().map(Subnetmap::getSubnetIp).orElse(null);
-
     }
 
     public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr) {
@@ -1047,8 +1088,8 @@ public final class NatUtil {
                         LogicalDatastoreType.OPERATIONAL, id);
         List<BigInteger> dpns = new ArrayList<>();
         if (routerDpnListData.isPresent()) {
-            List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
-            for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
+            for (DpnVpninterfacesList dpnVpnInterface : requireNonNullElse(
+                    routerDpnListData.get().getDpnVpninterfacesList(), Collections.<DpnVpninterfacesList>emptyList())) {
                 dpns.add(dpnVpnInterface.getDpnId());
             }
         }
@@ -1064,6 +1105,7 @@ public final class NatUtil {
         return bgpVpnId;
     }
 
+    @Nullable
     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
         .RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -1137,7 +1179,8 @@ public final class NatUtil {
         if (optionalDpnRoutersList.isPresent()) {
             RoutersList routersList = new RoutersListBuilder().withKey(new RoutersListKey(routerName))
                     .setRouter(routerName).build();
-            List<RoutersList> routersListFromDs = optionalDpnRoutersList.get().getRoutersList();
+            List<RoutersList> routersListFromDs = requireNonNullElse(optionalDpnRoutersList.get().getRoutersList(),
+                emptyList());
             if (!routersListFromDs.contains(routersList)) {
                 LOG.debug("addToDpnRoutersMap : Router {} not present for the DPN {}"
                         + " in the ODL-L3VPN : DPNRouters map", routerName, dpId);
@@ -1345,7 +1388,7 @@ public final class NatUtil {
     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
                                                                 ItmRpcService itmRpcService,
                                                                 IInterfaceManager interfaceManager,
-                                                                String ifName, Long tunnelKey, int pos,
+                                                                String ifName, @Nullable Long tunnelKey, int pos,
                                                                 boolean internalTunnelInterface) {
         LOG.debug("getEgressActionsForInterface : called for interface {}", ifName);
         GetEgressActionsForInterfaceInputBuilder egressActionsIfmBuilder =
@@ -1358,7 +1401,7 @@ public final class NatUtil {
         } //init builders, ITM/IFM rpc can be called based on type of interface
 
         try {
-            List<Action> actions = Collections.emptyList();
+            List<Action> actions = emptyList();
             if (interfaceManager.isItmDirectTunnelsEnabled() && internalTunnelInterface) {
                 RpcResult<GetEgressActionsForTunnelOutput> rpcResult =
                         itmRpcService.getEgressActionsForTunnel(egressActionsItmBuilder.build()).get();
@@ -1379,7 +1422,7 @@ public final class NatUtil {
                 }
             }
             List<ActionInfo> listActionInfo = new ArrayList<>();
-            for (Action action : actions) {
+            for (Action action : requireNonNullElse(actions, Collections.<Action>emptyList())) {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
                     actionClass = action.getAction();
                 if (actionClass instanceof OutputActionCase) {
@@ -1408,9 +1451,10 @@ public final class NatUtil {
             LOG.error("Exception when egress actions for interface {}", ifName, e);
         }
         LOG.error("Error when getting egress actions for interface {}", ifName);
-        return Collections.emptyList();
+        return emptyList();
     }
 
+    @Nullable
     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker, IpAddress targetIP) {
         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
     }
@@ -1427,14 +1471,14 @@ public final class NatUtil {
 
         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
             LOG.error("getNeutronPorts : No neutron ports found");
-            return Collections.emptyList();
+            return emptyList();
         }
 
         return portsOptional.get().getPort();
     }
 
-    public static Port getNeutronPortForIp(DataBroker broker,
-                                           IpAddress targetIP, String deviceType) {
+    @Nullable
+    public static Port getNeutronPortForIp(DataBroker broker, IpAddress targetIP, String deviceType) {
         List<Port> ports = getNeutronPorts(
             broker);
 
@@ -1451,12 +1495,13 @@ public final class NatUtil {
         return null;
     }
 
+    @Nullable
     public static Uuid getSubnetIdForFloatingIp(Port port, IpAddress targetIP) {
         if (port == null) {
             LOG.error("getSubnetIdForFloatingIp : port is null");
             return null;
         }
-        for (FixedIps ip : port.getFixedIps()) {
+        for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
             if (Objects.equals(ip.getIpAddress(), targetIP)) {
                 return ip.getSubnetId();
             }
@@ -1465,6 +1510,7 @@ public final class NatUtil {
         return null;
     }
 
+    @Nullable
     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
             .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
@@ -1478,9 +1524,10 @@ public final class NatUtil {
             .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(NetworkMap::getSubnetIdList).orElse(
-                Collections.emptyList());
+                emptyList());
     }
 
+    @Nullable
     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
         if (subnetId == null) {
             LOG.error("getSubnetGwMac : subnetID is null");
@@ -1551,6 +1598,7 @@ public final class NatUtil {
             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
     }
 
+    @Nullable
     protected static String getFloatingIpPortMacFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -1558,6 +1606,7 @@ public final class NatUtil {
                 FloatingIpIdToPortMapping::getFloatingIpPortMacAddress).orElse(null);
     }
 
+    @Nullable
     protected static String getFloatingIpPortMacFromFloatingIpId(TypedReadTransaction<Configuration> confTx,
         Uuid floatingIpId) {
         try {
@@ -1569,6 +1618,7 @@ public final class NatUtil {
         }
     }
 
+    @Nullable
     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -1593,6 +1643,7 @@ public final class NatUtil {
             FloatingIpIdToPortMappingKey(floatingIpId)).build();
     }
 
+    @Nullable
     static Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
         InstanceIdentifier<Interface> ifStateId =
             buildStateInterfaceId(interfaceName);
@@ -1607,10 +1658,10 @@ public final class NatUtil {
                 .child(Interface.class,
                     new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
                         .interfaces.state.InterfaceKey(interfaceName));
-        InstanceIdentifier<Interface> id = idBuilder.build();
-        return id;
+        return idBuilder.build();
     }
 
+    @Nullable
     public static Routers getRoutersFromConfigDS(DataBroker dataBroker, String routerName) {
         InstanceIdentifier<Routers> routerIdentifier = NatUtil.buildRouterIdentifier(routerName);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
@@ -1637,6 +1688,7 @@ public final class NatUtil {
         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, buildRouterIdentifier(routerId), rtrs);
     }
 
+    @Nullable
     static FlowEntity buildDefaultNATFlowEntityForExternalSubnet(BigInteger dpId, long vpnId, String subnetId,
             IdManagerService idManager) {
         InetAddress defaultIP = null;
@@ -1659,12 +1711,12 @@ public final class NatUtil {
         actionsInfo.add(new ActionGroup(groupId));
         String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
         instructions.add(new InstructionApplyActions(actionsInfo));
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
+        return MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
-        return flowEntity;
     }
 
+    @Nullable
     static String getExtGwMacAddFromRouterId(DataBroker broker, long routerId) {
         String routerName = getRouterName(broker, routerId);
         if (routerName == null) {
@@ -1674,6 +1726,7 @@ public final class NatUtil {
         return getExtGwMacAddFromRouterName(broker, routerName);
     }
 
+    @Nullable
     static String getExtGwMacAddFromRouterName(DataBroker broker, String routerName) {
         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -1698,6 +1751,7 @@ public final class NatUtil {
         return routerInstanceIdentifier;
     }
 
+    @Nullable
     public static String getNeutronRouterNamebyUuid(DataBroker broker, Uuid routerUuid) {
         InstanceIdentifier<Router> neutronRouterIdentifier = NatUtil.buildNeutronRouterIdentifier(routerUuid);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -1710,7 +1764,7 @@ public final class NatUtil {
         InstanceIdentifier<RouterPorts> routerPortsIdentifier = getRouterPortsId(routerUuid.getValue());
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                 LogicalDatastoreType.CONFIGURATION,
-                routerPortsIdentifier).toJavaUtil().map(RouterPorts::getPorts).orElse(Collections.emptyList());
+                routerPortsIdentifier).toJavaUtil().map(RouterPorts::getPorts).orElse(emptyList());
     }
 
     @Nonnull
@@ -1720,13 +1774,14 @@ public final class NatUtil {
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                         LogicalDatastoreType.CONFIGURATION, externalNwIdentifier);
         if (externalNwData.isPresent()) {
-            for (Networks externalNw : externalNwData.get().getNetworks()) {
+            for (Networks externalNw : requireNonNullElse(externalNwData.get().getNetworks(),
+                    Collections.<Networks>emptyList())) {
                 if (externalNw.getVpnid() != null && externalNw.getVpnid().equals(vpnUuid)) {
-                    return externalNw.getRouterIds();
+                    return requireNonNullElse(externalNw.getRouterIds(), emptyList());
                 }
             }
         }
-        return Collections.emptyList();
+        return emptyList();
     }
 
     public static boolean isIpInSubnet(String ipAddress, String start, String end) {
@@ -1743,7 +1798,7 @@ public final class NatUtil {
     }
 
     @Nonnull
-    public static Collection<Uuid> getExternalSubnetIdsFromExternalIps(List<ExternalIps> externalIps) {
+    public static Collection<Uuid> getExternalSubnetIdsFromExternalIps(@Nullable List<ExternalIps> externalIps) {
         if (externalIps == null) {
             return Collections.emptySet();
         }
@@ -1752,7 +1807,7 @@ public final class NatUtil {
     }
 
     @Nonnull
-    public static Collection<Uuid> getExternalSubnetIdsForRouter(DataBroker dataBroker, String routerName) {
+    public static Collection<Uuid> getExternalSubnetIdsForRouter(DataBroker dataBroker, @Nullable String routerName) {
         if (routerName == null) {
             LOG.error("getExternalSubnetIdsForRouter : empty routerName received");
             return Collections.emptySet();
@@ -1840,10 +1895,10 @@ public final class NatUtil {
         return NatConstants.INVALID_ID;
     }
 
+    @Nullable
     protected static Uuid getExternalSubnetForRouterExternalIp(String externalIpAddress, Routers router) {
         externalIpAddress = validateAndAddNetworkMask(externalIpAddress);
-        List<ExternalIps> externalIps = router.getExternalIps();
-        for (ExternalIps extIp : externalIps) {
+        for (ExternalIps extIp : requireNonNullElse(router.getExternalIps(), Collections.<ExternalIps>emptyList())) {
             String extIpString = validateAndAddNetworkMask(extIp.getIpAddress());
             if (extIpString.equals(externalIpAddress)) {
                 return extIp.getSubnetId();
@@ -1866,13 +1921,14 @@ public final class NatUtil {
     @Nonnull
     static List<String> getIpsListFromExternalIps(@Nullable List<ExternalIps> externalIps) {
         if (externalIps == null) {
-            return Collections.emptyList();
+            return emptyList();
         }
 
         return externalIps.stream().map(ExternalIps::getIpAddress).collect(Collectors.toList());
     }
 
     // elan-instances config container
+    @Nullable
     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
@@ -1894,11 +1950,12 @@ public final class NatUtil {
                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
     }
 
-    public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, IElanService elanManager,
-            IdManagerService idManager, long routerId, String routerName) {
+    public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, NatOverVxlanUtil natOverVxlanUtil,
+                                                       IElanService elanManager, IdManagerService idManager,
+                                                       long routerId, String routerName) {
         if (elanManager.isOpenStackVniSemanticsEnforced()) {
             // Router VNI will be set as tun_id if OpenStackSemantics is enabled
-            return NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId).longValue();
+            return natOverVxlanUtil.getRouterVni(routerName, routerId).longValue();
         } else {
             return NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
         }
@@ -1938,7 +1995,7 @@ public final class NatUtil {
                 + NwConstants.FLOWID_SEPARATOR + uniqueId;
     }
 
-    public static Boolean isFloatingIpPresentForDpn(DataBroker dataBroker, BigInteger dpnId, String rd,
+    public static boolean isFloatingIpPresentForDpn(DataBroker dataBroker, BigInteger dpnId, String rd,
                                                     String vpnName, String externalIp,
                                                     Boolean isMoreThanOneFipCheckOnDpn) {
         InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
@@ -1951,31 +2008,31 @@ public final class NatUtil {
                 if (ipAddressList != null && !ipAddressList.isEmpty()) {
                     int floatingIpPresentCount = 0;
                     for (IpAddresses ipAddress: ipAddressList) {
-                        if (!ipAddress.getIpAddress().equals(externalIp)
+                        if (!Objects.equals(ipAddress.getIpAddress(), externalIp)
                                 && IpAddresses.IpAddressSource.FloatingIP.equals(ipAddress.getIpAddressSource())) {
                             floatingIpPresentCount++;
                             //Add tunnel table check
                             if (isMoreThanOneFipCheckOnDpn && floatingIpPresentCount > 1) {
-                                return Boolean.TRUE;
+                                return true;
                             }
                             //Remove tunnel table check
                             if (!isMoreThanOneFipCheckOnDpn) {
-                                return Boolean.TRUE;
+                                return true;
                             }
                         }
                     }
                 } else {
                     LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list does not contain any floating IP for DPN {}",
                            dpnId);
-                    return Boolean.FALSE;
+                    return false;
                 }
             } catch (NullPointerException e) {
                 LOG.error("isFloatingIpPresentForDpn: Exception occurred on getting external IP address from "
                         + "vpn-to-dpn-list on Dpn {}", dpnId, e);
-                return Boolean.FALSE;
+                return false;
             }
         }
-        return Boolean.FALSE;
+        return false;
     }
 
     private static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
@@ -2001,12 +2058,13 @@ public final class NatUtil {
         return vpnName;
     }
 
-    public static String getPrimaryRd(VpnInstance vpnInstance) {
-        List<String> rds = null;
-        if (vpnInstance != null) {
-            rds = getListOfRdsFromVpnInstance(vpnInstance);
+    @Nullable
+    public static String getPrimaryRd(@Nullable VpnInstance vpnInstance) {
+        if (vpnInstance == null) {
+            return null;
         }
-        return rds == null || rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
+        List<String> rds = getListOfRdsFromVpnInstance(vpnInstance);
+        return rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
     }
 
     public static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
@@ -2042,6 +2100,7 @@ public final class NatUtil {
         new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
     }
 
+    @Nullable
     public static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
         InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(rd);
         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
@@ -2060,9 +2119,7 @@ public final class NatUtil {
                     String sharedRouterName = routerUuid.getValue();
                     if (!routerName.equals(sharedRouterName)) {
                         BigInteger switchDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
-                        if (switchDpnId == null) {
-                            continue;
-                        } else if (switchDpnId.equals(dpnId)) {
+                        if (switchDpnId != null && switchDpnId.equals(dpnId)) {
                             LOG.debug("checkForRoutersWithSameExtNetAndNaptSwitch: external-network {} is "
                                     + "associated with other active router {} on NAPT switch {}", networkId,
                                     sharedRouterName, switchDpnId);
@@ -2079,15 +2136,13 @@ public final class NatUtil {
                                                                         String routerName, BigInteger dpnId) {
         List<Uuid> routerUuidList = getOptionalExternalSubnets(broker, externalSubnetId).toJavaUtil()
             .map(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
-                .subnets.Subnets::getRouterIds).orElse(Collections.emptyList());
-        if (routerUuidList != null && !routerUuidList.isEmpty()) {
+                .subnets.Subnets::getRouterIds).orElse(emptyList());
+        if (!routerUuidList.isEmpty()) {
             for (Uuid routerUuid : routerUuidList) {
                 String sharedRouterName = routerUuid.getValue();
                 if (!routerName.equals(sharedRouterName)) {
                     BigInteger switchDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
-                    if (switchDpnId == null) {
-                        continue;
-                    } else if (switchDpnId.equals(dpnId)) {
+                    if (switchDpnId != null && switchDpnId.equals(dpnId)) {
                         LOG.debug("checkForRoutersWithSameExtSubnetAndNaptSwitch: external-subnetwork {} is "
                                   + "associated with other active router {} on NAPT switch {}", externalSubnetId,
                             sharedRouterName, switchDpnId);
@@ -2105,7 +2160,7 @@ public final class NatUtil {
             List<ExternalIps> externalIps = router.getExternalIps();
             List<String> externalIpsSting = new ArrayList<>();
 
-            if (externalIps.isEmpty()) {
+            if (externalIps == null || externalIps.isEmpty()) {
                 LOG.error("installRouterGwFlows: setupRouterGwFlows no externalIP present");
                 return;
             }
@@ -2185,7 +2240,7 @@ public final class NatUtil {
             GroupEntity groupEntity = null;
             try {
                 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
-                    GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
+                    GroupTypes.GroupAll, emptyList() /*listBucketInfo*/);
                 LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
                 mdsalManager.removeGroup(groupEntity);
             } catch (Exception ex) {
@@ -2340,17 +2395,16 @@ public final class NatUtil {
         return extRouterInstanceIndentifier;
     }
 
+    @Nullable
     public static LearntVpnVipToPortData getLearntVpnVipToPortData(DataBroker dataBroker) {
-        InstanceIdentifier<LearntVpnVipToPortData> learntVpnVipToPortDataId = getLearntVpnVipToPortDataId();
-        LearntVpnVipToPortData learntVpnVipToPortData = null;
         try {
-            learntVpnVipToPortData = SingleTransactionDataBroker.syncRead(dataBroker,
-                    LogicalDatastoreType.OPERATIONAL, learntVpnVipToPortDataId);
+            return SingleTransactionDataBroker.syncRead(dataBroker,
+                    LogicalDatastoreType.OPERATIONAL, getLearntVpnVipToPortDataId());
         }
         catch (ReadFailedException e) {
             LOG.warn("Failed to read LearntVpnVipToPortData with error {}", e.getMessage());
+            return null;
         }
-        return learntVpnVipToPortData;
     }
 
     public static InstanceIdentifier<LearntVpnVipToPortData> getLearntVpnVipToPortDataId() {
@@ -2367,7 +2421,8 @@ public final class NatUtil {
     }
 
     public static InstanceIdentifier<Group> getGroupInstanceId(BigInteger dpnId, long groupId) {
-        return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId)))
+        return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight
+                .inventory.rev130819.nodes.Node.class, new NodeKey(new NodeId("openflow:" + dpnId)))
                 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
     }
 
@@ -2392,9 +2447,10 @@ public final class NatUtil {
     public static boolean getSwitchStatus(DataBroker broker, BigInteger switchId) {
         NodeId nodeId = new NodeId("openflow:" + switchId);
         LOG.debug("getSwitchStatus : Querying switch with dpnId {} is up/down", nodeId);
-        InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
-            .child(Node.class, new NodeKey(nodeId)).build();
-        Optional<Node> nodeOptional =
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeInstanceId
+            = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight
+                    .inventory.rev130819.nodes.Node.class, new NodeKey(nodeId)).build();
+        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeOptional =
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                         LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
         if (nodeOptional.isPresent()) {
@@ -2404,4 +2460,198 @@ public final class NatUtil {
         LOG.debug("getSwitchStatus : Switch {} is down", nodeId);
         return false;
     }
+
+    public static boolean isExternalNetwork(DataBroker broker, Uuid networkId) {
+        InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
+        Optional<Networks> networkData =
+                SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
+                        broker, LogicalDatastoreType.CONFIGURATION, id);
+        return networkData.isPresent();
+    }
+
+    @Nullable
+    public static String getElanInstancePhysicalNetwok(String elanInstanceName, DataBroker broker) {
+        ElanInstance elanInstance =  getElanInstanceByName(elanInstanceName, broker);
+        if (null != elanInstance) {
+            return elanInstance.getPhysicalNetworkName();
+        }
+        return null;
+
+    }
+
+    public static Map<String, String> getOpenvswitchOtherConfigMap(BigInteger dpnId, DataBroker dataBroker) {
+        String otherConfigVal = getProviderMappings(dpnId, dataBroker);
+        return getMultiValueMap(otherConfigVal);
+    }
+
+    public static Map<String, String> getMultiValueMap(String multiKeyValueStr) {
+        if (Strings.isNullOrEmpty(multiKeyValueStr)) {
+            return Collections.emptyMap();
+        }
+
+        Map<String, String> valueMap = new HashMap<>();
+        Splitter splitter = Splitter.on(OTHER_CONFIG_PARAMETERS_DELIMITER);
+        for (String keyValue : splitter.split(multiKeyValueStr)) {
+            String[] split = keyValue.split(OTHER_CONFIG_KEY_VALUE_DELIMITER, 2);
+            if (split.length == 2) {
+                valueMap.put(split[0], split[1]);
+            }
+        }
+
+        return valueMap;
+    }
+
+    public static Optional<Node> getBridgeRefInfo(BigInteger dpnId, DataBroker dataBroker) {
+        InstanceIdentifier<BridgeRefEntry> bridgeRefInfoPath = InstanceIdentifier.create(BridgeRefInfo.class)
+                .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId));
+
+        Optional<BridgeRefEntry> bridgeRefEntry =
+                SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+                        LogicalDatastoreType.OPERATIONAL, bridgeRefInfoPath);
+        if (!bridgeRefEntry.isPresent()) {
+            LOG.info("getBridgeRefInfo : bridgeRefEntry is not present for {}", dpnId);
+            return Optional.absent();
+        }
+
+        InstanceIdentifier<Node> nodeId =
+                bridgeRefEntry.get().getBridgeReference().getValue().firstIdentifierOf(Node.class);
+
+        return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+                LogicalDatastoreType.OPERATIONAL, nodeId);
+    }
+
+    @Nullable
+    public static String getProviderMappings(BigInteger dpId, DataBroker dataBroker) {
+        return getBridgeRefInfo(dpId, dataBroker).toJavaUtil().map(node -> getOpenvswitchOtherConfigs(node,
+                PROVIDER_MAPPINGS, dataBroker)).orElse(null);
+    }
+
+    @Nullable
+    public static String getOpenvswitchOtherConfigs(Node node, String key, DataBroker dataBroker) {
+        OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
+        if (ovsdbNode == null) {
+            Optional<Node> nodeFromReadOvsdbNode = readOvsdbNode(node, dataBroker);
+            if (nodeFromReadOvsdbNode.isPresent()) {
+                ovsdbNode = nodeFromReadOvsdbNode.get().augmentation(OvsdbNodeAugmentation.class);
+            }
+        }
+
+        if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
+            for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
+                if (Objects.equals(openvswitchOtherConfigs.getOtherConfigKey(), key)) {
+                    return openvswitchOtherConfigs.getOtherConfigValue();
+                }
+            }
+        }
+        LOG.info("getOpenvswitchOtherConfigs : OtherConfigs is not present for ovsdbNode {}", node.getNodeId());
+        return null;
+    }
+
+    @Nonnull
+    public static Optional<Node> readOvsdbNode(Node bridgeNode, DataBroker dataBroker) {
+        OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
+        if (bridgeAugmentation != null) {
+            InstanceIdentifier<Node> ovsdbNodeIid =
+                    (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
+            return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+                    LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
+        }
+        return Optional.absent();
+
+    }
+
+    @Nullable
+    public static OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
+        if (node == null) {
+            return null;
+        }
+        return node.augmentation(OvsdbBridgeAugmentation.class);
+    }
+
+    // Use Objects.requireNonNullElse instead with JDK9+
+    @Nonnull
+    public static <T> T requireNonNullElse(@Nullable T obj, @Nonnull T defaultObj) {
+        return obj != null ? obj : requireNonNull(defaultObj);
+    }
+
+    public static String getDefaultFibRouteToSNATForSubnetJobKey(String subnetName, BigInteger dpnId) {
+        return NatConstants.NAT_DJC_PREFIX + subnetName + dpnId;
+    }
+
+    public static ExternalSubnets getExternalSubnets(DataBroker dataBroker) {
+        InstanceIdentifier<ExternalSubnets> subnetsIdentifier =
+                InstanceIdentifier.builder(ExternalSubnets.class)
+                .build();
+        try {
+            Optional<ExternalSubnets> optionalExternalSubnets  = SingleTransactionDataBroker
+                    .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
+            if (optionalExternalSubnets.isPresent()) {
+                return optionalExternalSubnets.get();
+            }
+        } catch (ReadFailedException e) {
+            LOG.error("Failed to read the subnets from the datastore.");
+        }
+        return null;
+
+    }
+
+    public static void addFlow(TypedWriteTransaction<Configuration> confTx, IMdsalApiManager mdsalManager,
+            BigInteger dpId, short tableId, String flowId, int priority, String flowName, BigInteger cookie,
+            List<? extends MatchInfoBase> matches, List<InstructionInfo> instructions) {
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
+                NatConstants.DEFAULT_IDLE_TIMEOUT, NatConstants.DEFAULT_IDLE_TIMEOUT, cookie, matches,
+                instructions);
+        LOG.trace("syncFlow : Installing DpnId {}, flowId {}", dpId, flowId);
+        mdsalManager.addFlow(confTx, flowEntity);
+    }
+
+    public static void removeFlow(TypedReadWriteTransaction<Configuration> confTx, IMdsalApiManager mdsalManager,
+            BigInteger dpId, short tableId, String flowId) throws ExecutionException, InterruptedException {
+        LOG.trace("syncFlow : Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
+        mdsalManager.removeFlow(confTx, dpId, flowId, tableId);
+    }
+
+    public static String getIpv6FlowRef(BigInteger dpnId, short tableId, long routerID) {
+        return new StringBuilder().append(NatConstants.IPV6_FLOWID_PREFIX).append(dpnId).append(NatConstants
+                .FLOWID_SEPARATOR).append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
+    }
+
+    public static String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId,
+                                                ItmRpcService itmManager) {
+        Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+        RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
+        try {
+            Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager
+                    .getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId)
+                            .setDestinationDpid(dstDpId).setTunnelType(tunType).build());
+            rpcResult = result.get();
+            if (!rpcResult.isSuccessful()) {
+                tunType = TunnelTypeGre.class ;
+                result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
+                        .setSourceDpid(srcDpId)
+                        .setDestinationDpid(dstDpId)
+                        .setTunnelType(tunType)
+                        .build());
+                rpcResult = result.get();
+                if (!rpcResult.isSuccessful()) {
+                    LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
+                            rpcResult.getErrors());
+                } else {
+                    return rpcResult.getResult().getInterfaceName();
+                }
+                LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
+                        rpcResult.getErrors());
+            } else {
+                return rpcResult.getResult().getInterfaceName();
+            }
+        } catch (InterruptedException | ExecutionException | NullPointerException e) {
+            LOG.error("getTunnelInterfaceName : Exception when getting tunnel interface Id for tunnel "
+                    + "between {} and {}", srcDpId, dstDpId);
+        }
+        return null;
+    }
+
+    public static String getIpv6JobKey(String routerName) {
+        return "Ipv6." + routerName;
+    }
 }