Do not use String.split() in VpnUtil
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnUtil.java
index a8f4cd6fc78982ef57e3cbb7503820771e3fc5f6..35081e1eef7462a285faf6b4a3080bfaf1b76684 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.netvirt.vpnmanager;
 
+import static java.util.Collections.emptyList;
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
 
 import com.google.common.base.Optional;
@@ -31,6 +33,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
@@ -93,6 +96,7 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -150,6 +154,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
@@ -319,6 +324,7 @@ public final class VpnUtil {
                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
     }
 
+    @Nullable
     VpnInterface getVpnInterface(String vpnInterfaceName) {
         InstanceIdentifier<VpnInterface> id = getVpnInterfaceIdentifier(vpnInterfaceName);
         Optional<VpnInterface> vpnInterface = read(LogicalDatastoreType.CONFIGURATION, id);
@@ -374,6 +380,7 @@ public final class VpnUtil {
      * @param rd Route-Distinguisher
      * @return VrfTables that holds the list of VrfEntries of the specified rd
      */
+    @Nullable
     VrfTables getVrfTable(String rd) {
         InstanceIdentifier<VrfTables> id = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class,
                 new VrfTablesKey(rd)).build();
@@ -409,10 +416,14 @@ public final class VpnUtil {
      */
     public List<VrfEntry> getAllVrfEntries(String rd) {
         VrfTables vrfTables = getVrfTable(rd);
-        return vrfTables != null ? vrfTables.getVrfEntry() : new ArrayList<>();
+        if (vrfTables != null && vrfTables.getVrfEntry() != null) {
+            return vrfTables.getVrfEntry();
+        }
+        return emptyList();
     }
 
     //FIXME: Implement caches for DS reads
+    @Nullable
     public VpnInstance getVpnInstance(String vpnInstanceName) {
         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
             new VpnInstanceKey(vpnInstanceName)).build();
@@ -420,28 +431,36 @@ public final class VpnUtil {
         return vpnInstance.isPresent() ? vpnInstance.get() : null;
     }
 
+    @Nonnull
     List<VpnInstanceOpDataEntry> getAllVpnInstanceOpData() {
         InstanceIdentifier<VpnInstanceOpData> id = InstanceIdentifier.builder(VpnInstanceOpData.class).build();
         Optional<VpnInstanceOpData> vpnInstanceOpDataOptional = read(LogicalDatastoreType.OPERATIONAL, id);
-        return vpnInstanceOpDataOptional.isPresent() ?  vpnInstanceOpDataOptional.get().getVpnInstanceOpDataEntry()
-                : Collections.emptyList();
+        return
+            vpnInstanceOpDataOptional.isPresent() && vpnInstanceOpDataOptional.get().getVpnInstanceOpDataEntry() != null
+                ? vpnInstanceOpDataOptional.get().getVpnInstanceOpDataEntry()
+                : emptyList();
     }
 
+    @Nonnull
     List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> getDpnVpnInterfaces(VpnInstance vpnInstance,
                                                                                            BigInteger dpnId) {
         String primaryRd = getPrimaryRd(vpnInstance);
         InstanceIdentifier<VpnToDpnList> dpnToVpnId = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
         Optional<VpnToDpnList> dpnInVpn = read(LogicalDatastoreType.OPERATIONAL, dpnToVpnId);
-        return dpnInVpn.isPresent() ? dpnInVpn.get().getVpnInterfaces() : Collections.emptyList();
+        return dpnInVpn.isPresent() && dpnInVpn.get().getVpnInterfaces() != null ? dpnInVpn.get().getVpnInterfaces()
+            : emptyList();
     }
 
+    @Nonnull
     static List<String> getListOfRdsFromVpnInstance(VpnInstance vpnInstance) {
         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
         LOG.trace("vpnConfig {}", vpnConfig);
-        return vpnConfig.getRouteDistinguisher() != null ? vpnConfig.getRouteDistinguisher() : Collections.emptyList();
+        return vpnConfig.getRouteDistinguisher() != null && vpnConfig.getRouteDistinguisher() != null
+            ? vpnConfig.getRouteDistinguisher() : emptyList();
     }
 
+    @Nullable
     VrfEntry getVrfEntry(String rd, String ipPrefix) {
         VrfTables vrfTable = getVrfTable(rd);
         // TODO: why check VrfTables if we later go for the specific VrfEntry?
@@ -457,13 +476,13 @@ public final class VpnUtil {
         return null;
     }
 
+    @Nullable
     public List<Adjacency> getAdjacenciesForVpnInterfaceFromConfig(String intfName) {
         final InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceIdentifier(intfName);
         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
         Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.CONFIGURATION, path);
         if (adjacencies.isPresent()) {
-            List<Adjacency> nextHops = adjacencies.get().getAdjacency();
-            return nextHops;
+            return adjacencies.get().getAdjacency();
         }
         return null;
     }
@@ -472,6 +491,7 @@ public final class VpnUtil {
         return new RoutesBuilder().setPrefix(ipPrefix).setNexthopIpList(nextHopList).build();
     }
 
+    @Nullable
     String getVpnInterfaceName(BigInteger metadata) throws InterruptedException, ExecutionException {
         GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder();
         BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata);
@@ -608,7 +628,8 @@ public final class VpnUtil {
             ListenableFutures.addErrorLogging(
                     new ManagedNewTransactionRunnerImpl(dataBroker).callWithNewWriteOnlyTransactionAndSubmit(
                                                                             Datastore.CONFIGURATION, tx -> {
-                            for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
+                            for (VrfEntry vrfEntry : requireNonNullElse(vrfTables.getVrfEntry(),
+                                    Collections.<VrfEntry>emptyList())) {
                                 if (origin == RouteOrigin.value(vrfEntry.getOrigin())) {
                                     tx.delete(vpnVrfTableIid.child(VrfEntry.class, vrfEntry.key()));
                                 }
@@ -624,8 +645,8 @@ public final class VpnUtil {
         List<VrfEntry> matches = new ArrayList<>();
         if (vrfTablesOpc.isPresent()) {
             VrfTables vrfTables = vrfTablesOpc.get();
-            for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
-                vrfEntry.getRoutePaths().stream()
+            for (VrfEntry vrfEntry : requireNonNullElse(vrfTables.getVrfEntry(), Collections.<VrfEntry>emptyList())) {
+                requireNonNullElse(vrfEntry.getRoutePaths(), Collections.<RoutePaths>emptyList()).stream()
                         .filter(routePath -> routePath.getNexthopAddress() != null && routePath.getNexthopAddress()
                                 .equals(nexthop)).findFirst().ifPresent(routePath -> matches.add(vrfEntry));
             }
@@ -718,6 +739,7 @@ public final class VpnUtil {
      * @param vpnId Dataplane identifier of the VPN
      * @return the Vpn instance name
      */
+    @Nullable
     String getVpnName(long vpnId) {
 
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn
@@ -737,11 +759,12 @@ public final class VpnUtil {
             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
     }
 
+    @Nullable
     public VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
-        InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
-        return read(LogicalDatastoreType.OPERATIONAL, id).orNull();
+        return read(LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(rd)).orNull();
     }
 
+    @Nullable
     VpnInterface getConfiguredVpnInterface(String interfaceName) {
         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
         Optional<VpnInterface> configuredVpnInterface = read(LogicalDatastoreType.CONFIGURATION, interfaceId);
@@ -776,11 +799,7 @@ public final class VpnUtil {
     }
 
     public static String getIpPrefix(String prefix) {
-        String[] prefixValues = prefix.split("/");
-        if (prefixValues.length == 1) {
-            prefix = NWUtil.toIpPrefix(prefix);
-        }
-        return prefix;
+        return prefix.indexOf('/') != -1 ? prefix : NWUtil.toIpPrefix(prefix);
     }
 
     static final FutureCallback<Void> DEFAULT_CALLBACK =
@@ -833,6 +852,7 @@ public final class VpnUtil {
     }
 
     // interface-index-tag operational container
+    @Nullable
     IfIndexInterface getInterfaceInfoByInterfaceTag(long interfaceTag) {
         InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
         Optional<IfIndexInterface> existingInterfaceInfo = read(LogicalDatastoreType.OPERATIONAL, interfaceId);
@@ -847,6 +867,7 @@ public final class VpnUtil {
             new IfIndexInterfaceKey((int) interfaceTag)).build();
     }
 
+    @Nullable
     ElanTagName getElanInfoByElanTag(long elanTag) {
         InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
         Optional<ElanTagName> existingElanInfo = read(LogicalDatastoreType.OPERATIONAL, elanId);
@@ -893,7 +914,7 @@ public final class VpnUtil {
     }
 
     void scheduleVpnInterfaceForRemoval(String interfaceName, BigInteger dpnId, String vpnInstanceName,
-                                        TypedWriteTransaction<Operational> writeOperTxn) {
+                                        @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
         InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
                 getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnInstanceName);
         VpnInterfaceOpDataEntry interfaceToUpdate =
@@ -933,7 +954,7 @@ public final class VpnUtil {
     }
 
     void removeLearntVpnVipToPort(String vpnName, String fixedIp,
-                                                   TypedWriteTransaction<Operational> writeOperTxn) {
+                                  @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
         synchronized ((vpnName + fixedIp).intern()) {
             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
             if (writeOperTxn != null) {
@@ -947,7 +968,7 @@ public final class VpnUtil {
     }
 
     protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
-                                                     TypedWriteTransaction<Configuration> writeConfigTxn) {
+                                                     @Nullable TypedWriteTransaction<Configuration> writeConfigTxn) {
         synchronized ((vpnName + fixedIp).intern()) {
             InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
             if (writeConfigTxn != null) {
@@ -985,7 +1006,8 @@ public final class VpnUtil {
         return id;
     }
 
-    public void removeLearntVpnVipToPortEvent(String eventId, TypedWriteTransaction<Operational> writeOperTxn) {
+    public void removeLearntVpnVipToPortEvent(String eventId,
+            @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
         InstanceIdentifier<LearntVpnVipToPortEvent> id = buildLearntVpnVipToPortEventIdentifier(eventId);
         if (writeOperTxn != null) {
             writeOperTxn.delete(id);
@@ -1047,6 +1069,7 @@ public final class VpnUtil {
                 new VpnPortipToPortKey(fixedIp, vpnName)).build();
     }
 
+    @Nullable
     public VpnPortipToPort getNeutronPortFromVpnPortFixedIp(String vpnName, String fixedIp) {
         InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
         Optional<VpnPortipToPort> vpnPortipToPortData = read(LogicalDatastoreType.CONFIGURATION, id);
@@ -1056,6 +1079,7 @@ public final class VpnUtil {
         return null;
     }
 
+    @Nullable
     public static VpnPortipToPort getNeutronPortFromVpnPortFixedIp(TypedReadTransaction<Configuration> confTx,
             String vpnName, String fixedIp) {
         InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
@@ -1066,6 +1090,7 @@ public final class VpnUtil {
         }
     }
 
+    @Nullable
     public LearntVpnVipToPort getLearntVpnVipToPort(String vpnName, String fixedIp) {
         InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
         Optional<LearntVpnVipToPort> learntVpnVipToPort = read(LogicalDatastoreType.OPERATIONAL, id);
@@ -1099,27 +1124,64 @@ public final class VpnUtil {
         return result;
     }
 
+    @Nullable
     String getAssociatedExternalRouter(String extIp) {
         InstanceIdentifier<ExtRouters> extRouterInstanceIndentifier =
                 InstanceIdentifier.builder(ExtRouters.class).build();
         Optional<ExtRouters> extRouterData = read(LogicalDatastoreType.CONFIGURATION, extRouterInstanceIndentifier);
-        if (extRouterData.isPresent()) {
-            for (Routers routerData : extRouterData.get().getRouters()) {
-                List<ExternalIps> externalIps = routerData.getExternalIps();
-                for (ExternalIps externalIp : externalIps) {
-                    if (externalIp.getIpAddress().equals(extIp)) {
-                        return routerData.getRouterName();
-                    }
+        if (!extRouterData.isPresent()) {
+            return null;
+        }
+
+        // We need to find the router associated with the src ip of this packet.
+        // This case is either SNAT, in which case the src ip is the same as the
+        // router's external ip, or FIP in which case the src ip is in the router's
+        // external leg's subnet. We first check the SNAT case because it is much
+        // cheaper to do so because it does not require (potentially, there is a
+        // cache) an datastore read of the neutron subnet for each external IP.
+
+        String routerName = null;
+
+        for (Routers routerData : requireNonNullElse(extRouterData.get().getRouters(),
+                Collections.<Routers>emptyList())) {
+            List<ExternalIps> externalIps = requireNonNullElse(routerData.getExternalIps(), emptyList());
+            for (ExternalIps externalIp : externalIps) {
+                if (Objects.equals(externalIp.getIpAddress(), extIp)) {
+                    routerName = routerData.getRouterName();
+                    break;
                 }
             }
         }
-        return null;
+
+        if (routerName != null) {
+            return routerName;
+        }
+
+        for (Routers routerData : requireNonNullElse(extRouterData.get().getRouters(),
+                Collections.<Routers>emptyList())) {
+            List<ExternalIps> externalIps = requireNonNullElse(routerData.getExternalIps(), emptyList());
+            for (ExternalIps externalIp : externalIps) {
+                Subnet neutronSubnet = neutronVpnService.getNeutronSubnet(externalIp.getSubnetId());
+                if (neutronSubnet == null) {
+                    LOG.warn("Failed to retrieve subnet {} referenced by router {}",
+                            externalIp.getSubnetId(), routerData);
+                    continue;
+                }
+                if (NWUtil.isIpAddressInRange(IpAddressBuilder.getDefaultInstance(extIp), neutronSubnet.getCidr())) {
+                    routerName = routerData.getRouterName();
+                    break;
+                }
+            }
+        }
+
+        return routerName;
     }
 
     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
         return InstanceIdentifier.builder(ExtRouters.class).child(Routers.class, new RoutersKey(routerId)).build();
     }
 
+    @Nullable
     Networks getExternalNetwork(Uuid networkId) {
         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
             .child(Networks.class, new NetworksKey(networkId)).build();
@@ -1127,16 +1189,19 @@ public final class VpnUtil {
         return optionalNets.isPresent() ? optionalNets.get() : null;
     }
 
+    @Nullable
     Uuid getExternalNetworkVpnId(Uuid networkId) {
         Networks extNetwork = getExternalNetwork(networkId);
         return extNetwork != null ? extNetwork.getVpnid() : null;
     }
 
+    @Nonnull
     public List<Uuid> getExternalNetworkRouterIds(Uuid networkId) {
         Networks extNetwork = getExternalNetwork(networkId);
-        return extNetwork != null ? extNetwork.getRouterIds() : Collections.emptyList();
+        return extNetwork != null && extNetwork.getRouterIds() != null ? extNetwork.getRouterIds() : emptyList();
     }
 
+    @Nullable
     Routers getExternalRouter(String routerId) {
         InstanceIdentifier<Routers> id = InstanceIdentifier.builder(ExtRouters.class).child(Routers.class,
                 new RoutersKey(routerId)).build();
@@ -1249,7 +1314,7 @@ public final class VpnUtil {
     }
 
     private boolean doesInterfaceAndHiddenIpAddressTypeMatch(InetAddress hiddenIp, FixedIps portIp) {
-        return (hiddenIp instanceof Inet4Address && portIp.getIpAddress().getIpv4Address() != null)
+        return hiddenIp instanceof Inet4Address && portIp.getIpAddress().getIpv4Address() != null
                 || hiddenIp instanceof Inet6Address && portIp.getIpAddress().getIpv6Address() != null;
     }
 
@@ -1310,7 +1375,7 @@ public final class VpnUtil {
         final Optional<Subnet> subnet = read(LogicalDatastoreType.CONFIGURATION, subnetidentifier);
         if (subnet.isPresent()) {
             Class<? extends IpVersionBase> ipVersionBase = subnet.get().getIpVersion();
-            if (ipVersionBase.equals(IpVersionV4.class)) {
+            if (IpVersionV4.class.equals(ipVersionBase)) {
                 Subnetmap subnetmap = getSubnetmapFromItsUuid(subnetUuid);
                 if (subnetmap != null && subnetmap.getRouterInterfaceFixedIp() != null) {
                     LOG.trace("getVpnSubnetGatewayIp: Obtained subnetMap {} for vpn interface",
@@ -1330,6 +1395,7 @@ public final class VpnUtil {
         return gwIpAddress;
     }
 
+    @Nullable
     RouterToNaptSwitch getRouterToNaptSwitch(String routerName) {
         InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class)
                 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
@@ -1343,6 +1409,7 @@ public final class VpnUtil {
 
     }
 
+    @Nullable
     BigInteger getPrimarySwitchForRouter(String routerName) {
         RouterToNaptSwitch routerToNaptSwitch = getRouterToNaptSwitch(routerName);
         return routerToNaptSwitch != null ? routerToNaptSwitch.getPrimarySwitchId() : null;
@@ -1466,7 +1533,7 @@ public final class VpnUtil {
 
     public static List<String> getIpsListFromExternalIps(List<ExternalIps> externalIps) {
         if (externalIps == null) {
-            return Collections.emptyList();
+            return emptyList();
         }
 
         return externalIps.stream().map(ExternalIps::getIpAddress).collect(Collectors.toList());
@@ -1538,6 +1605,7 @@ public final class VpnUtil {
         return isVxLan ? VrfEntryBase.EncapType.Vxlan : VrfEntryBase.EncapType.Mplsgre;
     }
 
+    @Nullable
     org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets
         getExternalSubnet(Uuid subnetId) {
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets
@@ -1549,11 +1617,12 @@ public final class VpnUtil {
         return optionalSubnets.isPresent() ? optionalSubnets.get() : null;
     }
 
+    @Nullable
     public Uuid getSubnetFromExternalRouterByIp(Uuid routerId, String ip) {
         Routers externalRouter = getExternalRouter(routerId.getValue());
         if (externalRouter != null && externalRouter.getExternalIps() != null) {
             for (ExternalIps externalIp : externalRouter.getExternalIps()) {
-                if (externalIp.getIpAddress().equals(ip)) {
+                if (Objects.equals(externalIp.getIpAddress(), ip)) {
                     return externalIp.getSubnetId();
                 }
             }
@@ -1571,28 +1640,25 @@ public final class VpnUtil {
     }
 
     @SuppressWarnings("checkstyle:linelength")
+    @Nullable
     Network getNeutronNetwork(Uuid networkId) {
-        Network network = null;
         LOG.debug("getNeutronNetwork for {}", networkId.getValue());
         InstanceIdentifier<Network> inst = InstanceIdentifier.create(Neutron.class).child(
                 org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks.class).child(
                 Network.class, new NetworkKey(networkId));
-        Optional<Network> net = read(LogicalDatastoreType.CONFIGURATION, inst);
-        if (net.isPresent()) {
-            network = net.get();
-        }
-        return network;
+        return read(LogicalDatastoreType.CONFIGURATION, inst).orNull();
     }
 
-    public static boolean isEligibleForBgp(String rd, String vpnName, BigInteger dpnId, String networkName) {
+    public static boolean isEligibleForBgp(@Nullable String rd, @Nullable String vpnName, @Nullable BigInteger dpnId,
+            @Nullable String networkName) {
         if (rd != null) {
-            if (vpnName != null && rd.equals(vpnName)) {
+            if (rd.equals(vpnName)) {
                 return false;
             }
             if (dpnId != null && rd.equals(dpnId.toString())) {
                 return false;
             }
-            if (networkName != null && rd.equals(networkName)) {
+            if (rd.equals(networkName)) {
                 return false;
             }
             return true;
@@ -1692,14 +1758,10 @@ public final class VpnUtil {
      * @param subnetUuid the subnet's Uuid
      * @return the Subnetmap of Uuid or null if it is not found
      */
+    @Nullable
     public Subnetmap getSubnetmapFromItsUuid(Uuid subnetUuid) {
-        Subnetmap sn = null;
         InstanceIdentifier<Subnetmap> id = buildSubnetmapIdentifier(subnetUuid);
-        Optional<Subnetmap> optionalSn = read(LogicalDatastoreType.CONFIGURATION, id);
-        if (optionalSn.isPresent()) {
-            sn = optionalSn.get();
-        }
-        return sn;
+        return read(LogicalDatastoreType.CONFIGURATION, id).orNull();
     }
 
     boolean isAdjacencyEligibleToVpnInternet(Adjacency adjacency) {
@@ -1725,6 +1787,7 @@ public final class VpnUtil {
         return adjacencyEligible;
     }
 
+    @Nullable
     String getInternetVpnFromVpnInstanceList(List<VpnInstanceNames> vpnInstanceList) {
         for (VpnInstanceNames vpnInstance : vpnInstanceList) {
             String vpnName = vpnInstance.getVpnName();
@@ -1770,7 +1833,6 @@ public final class VpnUtil {
      * @return the IpVersionChoice of the version or IpVersionChoice.UNDEFINED otherwise
      */
     public static IpVersionChoice getIpVersionFromString(String ipAddress) {
-        IpVersionChoice ipchoice = IpVersionChoice.UNDEFINED;
         int indexIpAddress = ipAddress.indexOf('/');
         if (indexIpAddress >= 0) {
             ipAddress = ipAddress.substring(0, indexIpAddress);
@@ -1783,9 +1845,9 @@ public final class VpnUtil {
                 return IpVersionChoice.IPV6;
             }
         } catch (UnknownHostException | SecurityException e) {
-            ipchoice = IpVersionChoice.UNDEFINED;
+            return IpVersionChoice.UNDEFINED;
         }
-        return ipchoice;
+        return IpVersionChoice.UNDEFINED;
     }
 
     ListenableFuture<Void> unsetScheduledToRemoveForVpnInterface(String interfaceName) {
@@ -1869,7 +1931,8 @@ public final class VpnUtil {
             Optional<ElanDpnInterfacesList> dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL,
                     elanDpnInterfaceId);
             if (dpnInElanInterfaces.isPresent()) {
-                List<DpnInterfaces> dpnInterfaces = dpnInElanInterfaces.get().getDpnInterfaces();
+                List<DpnInterfaces> dpnInterfaces =
+                    requireNonNullElse(dpnInElanInterfaces.get().getDpnInterfaces(), emptyList());
                 for (DpnInterfaces dpnInterface : dpnInterfaces) {
                     dpnIdSet.add(dpnInterface.getDpId());
                 }
@@ -1928,6 +1991,7 @@ public final class VpnUtil {
 
     }
 
+    @Nullable
     ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName) {
         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
         return read(LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
@@ -1938,12 +2002,14 @@ public final class VpnUtil {
                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
     }
 
+    @Nullable
     DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) {
         InstanceIdentifier<DpnInterfaces> elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName,
                 dpId);
         return read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId).orNull();
     }
 
+    @Nullable
     String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) {
         DpnInterfaces dpnInterfaces = getElanInterfaceInfoByElanDpn(elanInstanceName, dpnId);
         if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null) {
@@ -1974,12 +2040,14 @@ public final class VpnUtil {
         return isVlan(elanInstance);
     }
 
+    @Nullable
     ElanInstance getElanInstanceByName(String elanInstanceName) {
         InstanceIdentifier<ElanInstance> elanIdentifierId =
                 ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName);
         return read(LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
     }
 
+    @Nullable
     String getVpnNameFromElanIntanceName(String elanInstanceName) {
         Optional<Subnetmaps> subnetMapsData = read(LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
         if (subnetMapsData.isPresent()) {
@@ -2005,7 +2073,7 @@ public final class VpnUtil {
             if (subnetMapList != null && !subnetMapList.isEmpty()) {
                 for (Subnetmap subnet : subnetMapList) {
                     if (subnet.getVpnId() != null && subnet.getVpnId().getValue().equals(vpnName)
-                            && subnet.getNetworkType().equals(NetworkType.VLAN)) {
+                            && NetworkType.VLAN.equals(subnet.getNetworkType())) {
                         if (subnet.getRouterInterfacePortId() == null || subnet.getNetworkId() == null) {
                             LOG.warn("The RouterInterfacePortId or NetworkId is null");
                             continue;
@@ -2021,6 +2089,7 @@ public final class VpnUtil {
         return elanInstanceRouterPortMap;
     }
 
+    @Nullable
     String getRouterPordIdFromElanInstance(String elanInstanceName) {
         Optional<Subnetmaps> subnetMapsData = read(LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
         if (subnetMapsData.isPresent()) {
@@ -2038,7 +2107,7 @@ public final class VpnUtil {
         return null;
     }
 
-    boolean shouldPopulateFibForVlan(String vpnName, String elanInstanceName, BigInteger dpnId) {
+    boolean shouldPopulateFibForVlan(String vpnName, @Nullable String elanInstanceName, BigInteger dpnId) {
         Map<String,String> elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName);
         boolean shouldPopulateFibForVlan = false;
         if (!elanInstanceRouterPortMap.isEmpty()) {
@@ -2193,32 +2262,38 @@ public final class VpnUtil {
            Also the Subnet overlap in a VPN detection logic to be addressed for router-based-l3vpns.
     */
     static boolean areSubnetsOverlapping(String cidr1, String cidr2) {
-        String[] ipaddressValues1 = cidr1.split("/");
-        int address1 = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues1[0]));
-        int cidrPart1 = Integer.parseInt(ipaddressValues1[1]);
-        String[] ipaddressValues2 = cidr2.split("/");
-        int address2 = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues2[0]));
-        int cidrPart2 = Integer.parseInt(ipaddressValues2[1]);
-        int comparedValue = 0;
+        final int slash1 = cidr1.indexOf('/');
+        final int address1 = addressForCidr(cidr1, slash1);
+        final int cidrPart1 = maskForCidr(cidr1, slash1);
+
+        final int slash2 = cidr2.indexOf('/');
+        final int address2 = addressForCidr(cidr2, slash2);
+        final int cidrPart2 = maskForCidr(cidr2, slash2);
+
+        final int comparedValue = cidrPart1 <= cidrPart2 ? compare(address1, cidrPart1, address2)
+                : compare(address2, cidrPart2, address1);
+        return comparedValue == 0;
+    }
+
+    private static int addressForCidr(String cidr, int slash) {
+        return InetAddresses.coerceToInteger(InetAddresses.forString(cidr.substring(0, slash)));
+    }
+
+    private static int maskForCidr(String cidr, int slash) {
+        return Integer.parseInt(cidr.substring(slash + 1));
+    }
+
+    private static int compare(int address, int cidrPart, int address2) {
+        int prefix = address2 & computeNetmask(cidrPart);
+        return address ^ prefix;
+    }
+
+    private static int computeNetmask(int cidrPart) {
         int netmask = 0;
-        if (cidrPart1 <= cidrPart2) {
-            for (int j = 0; j < cidrPart1; ++j) {
-                netmask |= (1 << 31 - j);
-            }
-            int prefix = address2 & netmask;
-            comparedValue = address1 ^ prefix;
-        } else {
-            for (int j = 0; j < cidrPart2; ++j) {
-                netmask |= (1 << 31 - j);
-            }
-            int prefix = address1 & netmask;
-            comparedValue = address2 ^ prefix;
-        }
-        if (comparedValue == 0) {
-            return  true;
-        } else {
-            return false;
+        for (int j = 0; j < cidrPart; ++j) {
+            netmask |= 1 << 31 - j;
         }
+        return netmask;
     }
 
     public static String buildIpMonitorJobKey(String ip, String vpnName) {
@@ -2226,7 +2301,7 @@ public final class VpnUtil {
     }
 
     public List<String> getVpnListForVpnInterface(VpnInterface vpnInter) {
-        return vpnInter.getVpnInstanceNames().stream()
+        return requireNonNullElse(vpnInter.getVpnInstanceNames(), Collections.<VpnInstanceNames>emptyList()).stream()
                 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
     }
 
@@ -2251,4 +2326,18 @@ public final class VpnUtil {
                 }));
         });
     }
+
+    // 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 boolean isDualRouterVpnUpdate(List<String> oldVpnListCopy, List<String> newVpnListCopy) {
+        if (oldVpnListCopy.size() == 2 && newVpnListCopy.size() == 3
+                || oldVpnListCopy.size() == 3 && newVpnListCopy.size() == 2) {
+            return true;
+        }
+        return false;
+    }
 }