IPv6 loopback ip is not displaying in fib entry
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
index 2eecb958fa29feb232c8f3e0040aaeff8b653c44..397e8c644e223c7b2b927be511a79e6237191891 100644 (file)
@@ -9,9 +9,8 @@ package org.opendaylight.netvirt.neutronvpn;
 
 import static java.util.Collections.singletonList;
 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
-import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -31,34 +30,36 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
-import org.opendaylight.genius.infra.Datastore.Configuration;
-import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
-import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
-import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.utils.JvmGlobalLocks;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
+import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
+import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
@@ -72,7 +73,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
@@ -87,21 +87,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.af.config.VpnTargets;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.af.config.VpnTargetsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.af.config.vpntargets.VpnTarget;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.af.config.vpntargets.VpnTargetBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.af.config.vpntargets.VpnTargetKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
@@ -143,6 +142,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
@@ -155,6 +155,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
@@ -171,6 +172,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.att
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
@@ -292,7 +294,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } finally {
                 lock.unlock();
             }
-        } catch (TransactionCommitFailedException | ReadFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
         }
         // check if there are ports to update for already created Subnetmap node
@@ -335,7 +337,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
             return subnetmap;
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
             return null;
         } finally {
@@ -372,7 +374,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
                 subnetId.getValue());
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
                 subnetId.getValue(), e);
         } finally {
@@ -424,7 +426,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         + "cache ", subnetId.getValue(), portId.getValue());
                 unprocessedPortsMap.put(portId, subnetId);
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
         } finally {
             lock.unlock();
@@ -469,7 +471,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
         } finally {
             lock.unlock();
@@ -512,7 +514,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
                     subnetId.getValue(), e);
         } finally {
@@ -546,29 +548,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIdentifier);
             if (!vpnInstanceConfig.isPresent()) {
-                LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
+                LOG.debug("updateVpnInstanceWithRDs: "
+                        + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
                 return;
             }
             VpnInstance vpnInstance = vpnInstanceConfig.get();
             VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
-            if (vpnInstance.getIpv4Family() != null) {
-                Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
-                updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
-            }
-            if (vpnInstance.getIpv6Family() != null) {
-                Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
-                updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
-            }
-            LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
+            updateVpnInstanceBuilder.setRouteDistinguisher(rds);
+            LOG.debug("updateVpnInstanceWithRDs: "
+                    + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
                     updateVpnInstanceBuilder.build());
-        } catch (ReadFailedException | TransactionCommitFailedException ex) {
-            LOG.warn("Error configuring feature ", ex);
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
+            LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
+                    + "the list of RDs: {}", vpnInstanceId, rds, ex);
         }
     }
 
     private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
-                                       VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
+                                       boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
         String vpnName = vpnId.getValue();
         VpnInstanceBuilder builder = null;
         List<VpnTarget> vpnTargetList = new ArrayList<>();
@@ -578,7 +576,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         try {
             optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                 vpnIdentifier);
-        } catch (ReadFailedException e) {
+        } catch (ExecutionException | InterruptedException e) {
             LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
             return;
         }
@@ -589,7 +587,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.debug("updating existing vpninstance node");
         } else {
             builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
-                    .setType(type).setL3vni(l3vni);
+                    .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN);
         }
         if (irt != null && !irt.isEmpty()) {
             if (ert != null && !ert.isEmpty()) {
@@ -623,25 +621,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
 
         VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
-        Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
-        Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
-
         if (rd != null && !rd.isEmpty()) {
-            ipv4vpnBuilder.setRouteDistinguisher(rd);
-            ipv6vpnBuilder.setRouteDistinguisher(rd);
+            builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN);
         }
 
-        if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
-            builder.setIpv4Family(ipv4vpnBuilder.build());
-        }
-        if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
-            builder.setIpv6Family(ipv6vpnBuilder.build());
-        }
-        if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
-            builder.setIpv4Family(ipv4vpnBuilder.build());
-        }
+        builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
         VpnInstance newVpn = builder.build();
-
         try (AcquireResult lock = tryVpnLock(vpnId)) {
             if (!lock.wasAcquired()) {
                 // FIXME: why do we even bother with locking if we do not honor it?!
@@ -703,11 +688,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (router != null) {
                 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
                 List<RouterIds> rtrIds = builder.getRouterIds() != null
-                        ? new ArrayList<>(builder.getRouterIds()) : null;
+                        ? new ArrayList<>(builder.getRouterIds().values()) : null;
                 if (rtrIds == null) {
                     rtrIds = Collections.singletonList(vpnRouterId);
                 } else {
-                    rtrIds.add(vpnRouterId);
+                    //Add vpnRouterId to rtrIds list only if update routerId is not existing in the VpnMap already
+                    for (RouterIds routerId: rtrIds) {
+                        if (!Objects.equals(routerId, vpnRouterId)) {
+                            rtrIds.add(vpnRouterId);
+                        }
+                    }
                 }
                 builder.setRouterIds(rtrIds);
             }
@@ -729,7 +719,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         builder.build());
                 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
         }
     }
@@ -743,14 +733,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             optionalVpnMap =
                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnMapIdentifier);
-        } catch (ReadFailedException e) {
+        } catch (ExecutionException | InterruptedException e) {
             LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
             return;
         }
         if (optionalVpnMap.isPresent()) {
             VpnMap vpnMap = optionalVpnMap.get();
             VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
-            List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
+            List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values());
             if (rtrIds == null) {
                 rtrIds = new ArrayList<>();
             }
@@ -838,11 +828,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                                   @Nullable VpnInterface vpnIface) {
         List<Adjacency> adjList = new ArrayList<>();
         if (vpnIface != null) {
-            adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
+            adjList = new ArrayList<Adjacency>(vpnIface.augmentation(Adjacencies.class).getAdjacency().values());
         }
         String infName = port.getUuid().getValue();
         LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
-        for (FixedIps ip : port.nonnullFixedIps()) {
+        for (FixedIps ip : port.nonnullFixedIps().values()) {
             String ipValue = ip.getIpAddress().stringValue();
             String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
             Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
@@ -870,7 +860,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (routerId != null) {
                 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
                 if (rtr != null && rtr.getRoutes() != null) {
-                    List<Routes> routeList = rtr.getRoutes();
+                    List<Routes> routeList = new ArrayList<Routes>(rtr.getRoutes().values());
                     // create extraroute Adjacence for each ipValue,
                     // because router can have IPv4 and IPv6 subnet ports, or can have
                     // more that one IPv4 subnet port or more than one IPv6 subnet port
@@ -881,7 +871,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
         }
-        return new AdjacenciesBuilder().setAdjacency(adjList).build();
+        return new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(adjList)).build();
+    }
+
+    private Map<AdjacencyKey, Adjacency> getAdjacencyMap(List<Adjacency> adjList) {
+        //convert to set to remove duplicates.
+        Set<Adjacency> adjset = adjList.stream().collect(Collectors.toSet());
+        Map<AdjacencyKey, Adjacency> adjacencyMap = new HashMap<>();
+        for (Adjacency adj : adjset) {
+            adjacencyMap.put(new AdjacencyKey(adj.getIpAddress()), adj);
+        }
+        return adjacencyMap;
     }
 
     protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
@@ -909,7 +909,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             optionalVpnInterface = SingleTransactionDataBroker
                     .syncReadOptional(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, vpnIfIdentifier);
-        } catch (ReadFailedException e) {
+        } catch (ExecutionException | InterruptedException e) {
             LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
             return;
         }
@@ -918,10 +918,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
                 sn != null ? sn.getSubnetIp() : "null");
-        List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
+        Map<AdjacencyKey, Adjacency> keyAdjacencyMap
+                = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
         List<Adjacency> updatedAdjsList = new ArrayList<>();
         boolean isIpFromAnotherSubnet = false;
-        for (Adjacency adj : vpnAdjsList) {
+        for (Adjacency adj : keyAdjacencyMap.values()) {
             String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
             if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
                 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
@@ -947,7 +948,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
                     if (rtr != null && rtr.getRoutes() != null) {
                         List<Routes> extraRoutesToRemove = new ArrayList<>();
-                        for (Routes rt: rtr.getRoutes()) {
+                        for (Routes rt: rtr.getRoutes().values()) {
                             if (rt.getNexthop().toString().equals(adjString)) {
                                 extraRoutesToRemove.add(rt);
                             }
@@ -962,7 +963,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
         }
-        Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
+        Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(updatedAdjsList)).build();
         if (vpnId != null) {
             updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
         }
@@ -982,7 +983,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     protected void deleteVpnInterface(String infName, @Nullable String vpnId,
                                       @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
         if (wrtConfigTxn == null) {
-            ListenableFutures.addErrorLogging(
+            LoggingFutures.addErrorLogging(
                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                         tx -> deleteVpnInterface(infName, vpnId, tx)),
                     LOG, "Error deleting VPN interface {} {}", infName, vpnId);
@@ -996,7 +997,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             optionalVpnInterface =
                 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIfIdentifier);
-        } catch (ReadFailedException ex) {
+        } catch (ExecutionException | InterruptedException ex) {
             LOG.error("Error during deletion of vpninterface {}", infName, ex);
             return;
         }
@@ -1006,17 +1007,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         if (vpnId != null) {
             VpnInterface vpnInterface = optionalVpnInterface.get();
-            List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
-            if (vpnList != null
-                && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
-                VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
-                if (!vpnList.isEmpty()) {
+            Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap = vpnInterface.getVpnInstanceNames();
+            if (keyVpnInstanceNamesMap != null
+                && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId,
+                    new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
+                VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId,
+                        new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
+                if (!keyVpnInstanceNamesMap.isEmpty()) {
                     LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
                             + "List not empty", infName);
                     return;
                 }
                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
-                        .setVpnInstanceNames(vpnList);
+                        .setVpnInstanceNames(keyVpnInstanceNamesMap);
                 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
                         .build());
             }
@@ -1038,17 +1041,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     .syncReadOptional(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, vpnIfIdentifier);
             if (optionalVpnInterface.isPresent()) {
-                List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
-                if (listVpn != null
-                    && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
-                    VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
+                Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap
+                        = optionalVpnInterface.get().getVpnInstanceNames();
+                if (keyVpnInstanceNamesMap != null
+                    && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),
+                        new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
+                    VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(),
+                            new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
                 }
                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
-                         .setVpnInstanceNames(listVpn);
+                         .setVpnInstanceNames(keyVpnInstanceNamesMap);
                 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
                 LOG.debug("Updating vpn interface {}", infName);
-                List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
-                Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
+                Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency() : new HashMap<>();
+                Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
                 while (adjacencyIter.hasNext()) {
                     Adjacency adjacency = adjacencyIter.next();
                     if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
@@ -1063,7 +1069,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     if (optionalVpnVipToPort.isPresent()) {
                         LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
                              infName, vpnId);
-                        if (listVpn == null || listVpn.isEmpty()) {
+                        if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
                             adjacencyIter.remove();
                         }
                         neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
@@ -1071,7 +1077,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 mipToQuery, infName, vpnId.getValue());
                     }
                 }
-                for (FixedIps ip : port.nonnullFixedIps()) {
+                for (FixedIps ip : port.nonnullFixedIps().values()) {
                     String ipValue = ip.getIpAddress().stringValue();
                     //skip IPv4 address
                     if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
@@ -1080,7 +1086,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
                             ipValue, writeConfigTxn);
                 }
-                if (listVpn == null || listVpn.isEmpty()) {
+                if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
                     if (sm != null && sm.getRouterId() != null) {
                         removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
                     }
@@ -1091,7 +1097,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
             }
-        } catch (ReadFailedException ex) {
+        } catch (ExecutionException | InterruptedException ex) {
             LOG.error("Update of vpninterface {} failed", infName, ex);
         }
     }
@@ -1119,8 +1125,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 if (optionalVpnInterface.isPresent()) {
                     VpnInstanceNames vpnInstance = VpnHelper
                             .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
-                    List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
-                            .get().getVpnInstanceNames());
+                    List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface.get()
+                            .getVpnInstanceNames().values());
                     if (oldVpnId != null
                             && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
                         VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
@@ -1134,8 +1140,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     LOG.debug("Updating vpn interface {}", infName);
                     if (!isBeingAssociated) {
                         Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
-                        List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
-                        Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
+                        Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency()
+                                : new HashMap<AdjacencyKey, Adjacency>();
+                        Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
                         while (adjacencyIter.hasNext()) {
                             Adjacency adjacency = adjacencyIter.next();
                             String mipToQuery = adjacency.getIpAddress().split("/")[0];
@@ -1164,10 +1171,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                     mipToQuery, infName, vpnId.getValue());
                             }
                         }
-                        Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
+                        Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build();
                         vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
                     }
-                    for (FixedIps ip : port.nonnullFixedIps()) {
+                    for (FixedIps ip : port.nonnullFixedIps().values()) {
                         String ipValue = ip.getIpAddress().stringValue();
                         if (oldVpnId != null) {
                             neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
@@ -1185,7 +1192,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 } else {
                     LOG.error("VPN Interface {} not found", infName);
                 }
-            } catch (ReadFailedException ex) {
+            } catch (ExecutionException | InterruptedException ex) {
                 LOG.error("Updation of vpninterface {} failed", infName, ex);
             }
         }
@@ -1197,7 +1204,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
 
         // Update VPN Instance node
-        updateVpnInstanceNode(vpnId, rdList, irtList, ertList, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
+        updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
 
         // Update local vpn-subnet DS
         updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
@@ -1231,13 +1238,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * @param ertList A list of Export Route Targets
      * @param routerIdsList ist of neutron router Id to associate with created VPN
      * @param networkList UUID of the neutron network the VPN may be associated to
-     * @param type Type of the VPN Instance
+     * @param isL2Vpn True if VPN Instance is of type L2, false if L3
      * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
      * @throws Exception if association of L3VPN failed
      */
     public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
                     List<String> ertList,  @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
-                    VpnInstance.Type type, long l3vni) throws Exception {
+                          boolean isL2Vpn, long l3vni) throws Exception {
 
         IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
 
@@ -1247,7 +1254,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 ipVersChoices = ipVersChoices.addVersion(vers);
             }
         }
-        updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
+        updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
 
         // Please note that router and networks will be filled into VPNMaps
         // by subsequent calls here to associateRouterToVpn and
@@ -1307,7 +1314,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 warningcount++;
                 continue;
             }
-            VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
             long l3vni = 0;
             if (vpn.getL3vni() != null) {
                 l3vni = vpn.getL3vni().toJava();
@@ -1335,10 +1341,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 continue;
             }
             if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
-                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
-                        routerIdsList = vpn.getRouterIds();
+                Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
+                        .neutronvpn.rev150602.vpn.instance.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight
+                        .netvirt.neutronvpn.rev150602.vpn.instance.RouterIds> keyRouterIdsMap = vpn.getRouterIds();
                 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
-                        routerId : routerIdsList) {
+                        routerId : keyRouterIdsMap.values()) {
                     if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
                         errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
                                 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
@@ -1384,7 +1391,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             List<Uuid> rtrIdsList = new ArrayList<>();
             if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
                 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
-                        rtrId : vpn.getRouterIds()) {
+                        rtrId : vpn.getRouterIds().values()) {
                     rtrIdsList.add(rtrId.getRouterId());
                 }
             }
@@ -1402,7 +1409,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
 
                 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
-                        importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), vpnInstanceType, l3vni);
+                        importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
             } catch (Exception ex) {
                 LOG.error("VPN Creation exception :", ex);
                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
@@ -1452,13 +1459,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                                 vpnsIdentifier);
                 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
-                    for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
+                    for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) {
                         // eliminating implicitly created (router and VLAN provider external network specific) VPNs
                         // from getL3VPN output
-                        if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
-                            vpns.add(vpn);
-                        }
-                        if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
+                        if (vpn.getRouteDistinguisher() != null) {
                             vpns.add(vpn);
                         }
                     }
@@ -1478,8 +1482,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 vpnIdentifier);
                 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
                 // getL3VPN output
-                if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
-                        || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
+                if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
                     vpns.add(optionalVpn.get());
                 } else {
                     result.set(
@@ -1493,24 +1496,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 // create VpnMaps id
                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
                 List<String> rd = Collections.EMPTY_LIST;
-                if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
-                    rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
-                } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
-                    rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
+                if (vpnInstance.getRouteDistinguisher() != null) {
+                    rd = vpnInstance.getRouteDistinguisher();
                 }
                 List<String> ertList = new ArrayList<>();
                 List<String> irtList = new ArrayList<>();
 
-                if (vpnInstance.getIpv4Family().getVpnTargets() != null
-                        || vpnInstance.getIpv6Family().getVpnTargets() != null) {
-                    List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
-                    if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
-                        vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
-                    } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
-                        vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
+                if (vpnInstance.getVpnTargets() != null) {
+                    Map<VpnTargetKey, VpnTarget> keyVpnTargetMap = Collections.EMPTY_MAP;
+                    if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
+                        keyVpnTargetMap = vpnInstance.getVpnTargets().getVpnTarget();
                     }
-                    if (!vpnTargetList.isEmpty()) {
-                        for (VpnTarget vpnTarget : vpnTargetList) {
+                    if (!keyVpnTargetMap.isEmpty()) {
+                        for (VpnTarget vpnTarget : keyVpnTargetMap.values()) {
                             if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
                                 ertList.add(vpnTarget.getVrfRTValue());
                             }
@@ -1539,7 +1537,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     VpnMap vpnMap = optionalVpnMap.get();
                     List<Uuid> rtrIds = new ArrayList<>();
                     if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
-                        for (RouterIds rtrId : vpnMap.getRouterIds()) {
+                        for (RouterIds rtrId : vpnMap.getRouterIds().values()) {
                             rtrIds.add(rtrId.getRouterId());
                         }
                     }
@@ -1554,7 +1552,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             opBuilder.setL3vpnInstances(l3vpnList);
             result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
 
-        } catch (ReadFailedException ex) {
+        } catch (ExecutionException | InterruptedException ex) {
             result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
                     formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
         }
@@ -1590,7 +1588,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                             formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
                     warningcount++;
                 }
-            } catch (ReadFailedException ex) {
+            } catch (ExecutionException | InterruptedException ex) {
                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
                         formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
                         ex.getMessage()));
@@ -1676,7 +1674,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 final Boolean isRouterInterface = port.getDeviceOwner()
                         .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
                 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
-                    ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                    ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                         wrtConfigTxn -> {
                             Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
                                     vpnIface);
@@ -1704,7 +1702,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 }
                             }
                         });
-                    ListenableFutures.addErrorLogging(future, LOG,
+                    LoggingFutures.addErrorLogging(future, LOG,
                             "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
                                     + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
                     return Collections.singletonList(future);
@@ -1713,86 +1711,83 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
-    protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
+    protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) {
         Preconditions.checkArgument(vpnId != null || internetVpnId != null,
                 "removeSubnetFromVpn: at least one VPN must be not null");
-        LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
+        Uuid subnetId = subnetmap.getId();
+        LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(),
                   vpnId, internetVpnId);
-        Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
-        if (sn == null) {
-            LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
-            return;
-        }
+        LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue());
         VpnMap vpnMap = null;
         VpnInstance vpnInstance = null;
         if (vpnId != null) {
             vpnMap = neutronvpnUtils.getVpnMap(vpnId);
             if (vpnMap == null) {
                 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
-                        vpnId.getValue(), subnet.getValue());
+                        vpnId.getValue(), subnetId.getValue());
                 return;
             }
             vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
         }
         if (internetVpnId == null) {
-            internetVpnId = sn.getInternetVpnId();
+            internetVpnId = subnetmap.getInternetVpnId();
         }
         if (internetVpnId != null) {
             vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
             if (vpnMap == null) {
                 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
                         + " from Internet VPN",
-                        internetVpnId.getValue(), subnet.getValue());
+                        internetVpnId.getValue(), subnetId.getValue());
                 return;
             }
         }
         if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
-            neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
+            neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
                     NeutronEvpnUtils.Operation.DELETE);
         }
         boolean subnetVpnAssociation = false;
-        if (vpnId != null && sn.getVpnId() != null
-            && sn.getVpnId().getValue().equals(vpnId.getValue())) {
+        if (vpnId != null && subnetmap.getVpnId() != null
+            && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) {
             subnetVpnAssociation = true;
-        } else if (internetVpnId != null && sn.getInternetVpnId() != null
-            && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
+        } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null
+            && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
             subnetVpnAssociation = true;
         }
         if (subnetVpnAssociation == false) {
             LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
-                      vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
+                      vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId());
             return;
         }
         // Check if there are ports on this subnet; remove corresponding vpn-interfaces
-        List<Uuid> portList = sn.getPortList();
+        List<Uuid> portList = subnetmap.getPortList();
         final Uuid internetId = internetVpnId;
         if (portList != null) {
             for (final Uuid portId : portList) {
-                LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
+                LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue());
                 final Port port = neutronvpnUtils.getNeutronPort(portId);
                 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    List<ListenableFuture<?>> futures = new ArrayList<>();
+                    ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
                         CONFIGURATION, tx -> {
                             if (port != null) {
-                                withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
+                                withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
                             } else {
                                 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
                                                 + " port is absent in Neutron config DS", portId.getValue(),
-                                        subnet.getValue());
+                                        subnetId.getValue());
                             }
                         });
-                    ListenableFutures.addErrorLogging(future, LOG,
+                    LoggingFutures.addErrorLogging(future, LOG,
                             "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
                                     + " belonging to subnet {} and vpnId {}",
-                            portId.getValue(), subnet.getValue(), vpnId.getValue());
+                            portId.getValue(), subnetId.getValue(), vpnId.getValue());
                     futures.add(future);
                     return futures;
                 });
             }
         }
         //update subnet-vpn association
-        removeFromSubnetNode(subnet, null, null, vpnId, null);
+        removeFromSubnetNode(subnetId, null, null, vpnId, null);
     }
 
     protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
@@ -1874,14 +1869,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         //Update Router Interface first synchronously.
         //CAUTION:  Please DONOT make the router interface VPN Movement as an asynchronous commit again !
-        ListenableFuture<Void> future =
+        ListenableFuture<?> future =
                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                     tx -> updateVpnInterface(newVpnId, oldVpnId,
                         neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
                         isBeingAssociated, true, tx, false));
-        Futures.addCallback(future, new FutureCallback<Void>() {
+        Futures.addCallback(future, new FutureCallback<Object>() {
             @Override
-            public void onSuccess(Void result) {
+            public void onSuccess(Object result) {
                 // Check for ports on this subnet and update association of
                 // corresponding vpn-interfaces to external vpn
                 List<Uuid> portList = sn.getPortList();
@@ -1929,15 +1924,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
                     routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
             } else {
-                // TODO Shouldn't we be doing something with builder and interfaces?
-                //          RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
-                //          List<Interfaces> interfaces = new ArrayList<>();
-                //          interfaces.add(routerInterface);
-
-                SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                    routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
+                RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
+                List<Interfaces> interfaces = new ArrayList<>();
+                interfaces.add(routerInterface);
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    routerInterfacesId, builder.setInterfaces(interfaces).build());
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
         } finally {
             lock.unlock();
@@ -1956,7 +1949,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     .setInterfaceId(interfaceName).build();
             if (optRouterInterfaces.isPresent()) {
                 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
-                List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
+                List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values());
                 if (interfaces != null && interfaces.remove(routerInterface)) {
                     if (interfaces.isEmpty()) {
                         SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
@@ -1967,7 +1960,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     }
                 }
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
         } finally {
             lock.unlock();
@@ -2038,7 +2031,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 .setVpnInstanceName(vpnName.getValue())
                                 .build();
 
-                ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
+                LoggingFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
                         vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
             } else {
                 // Any other case is a fault.
@@ -2142,7 +2135,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     } catch (TransactionCommitFailedException e) {
                         LOG.error("exception in adding extra route with destination: {}, next hop: {}",
                             destination, nextHop, e);
-                    } catch (ReadFailedException e) {
+                    } catch (ExecutionException | InterruptedException e) {
                         LOG.error("Exception on reading data-store ", e);
                     }
                 } else {
@@ -2199,21 +2192,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 nextHopList.add(routeTmp.getNexthop().stringValue());
             }
             final List<String> rdList = new ArrayList<>();
-            if (vpnInstance.getIpv4Family() != null
-                    && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
-                vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
+            if (vpnInstance != null
+                    && vpnInstance.getRouteDistinguisher() != null) {
+                vpnInstance.getRouteDistinguisher().forEach(rd -> {
                     if (rd != null) {
                         rdList.add(rd);
                     }
                 });
             }
-            if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
-                vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
-                    if (rd != null && !rdList.contains(rd)) {
-                        rdList.add(rd);
-                    }
-                });
-            }
             // 1. VPN Instance Name
             String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
 
@@ -2307,8 +2293,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                     .setNextHopIpList(nextHopList)
                                     .withKey(new AdjacencyKey(destination))
                                     .build();
+                            List<Adjacency> newAdjList = Collections.singletonList(newAdj);
                             Adjacencies erAdjs =
-                                    new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
+                                    new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(newAdjList)).build();
                             VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
                                     .addAugmentation(Adjacencies.class, erAdjs).build();
                             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
@@ -2320,7 +2307,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                             LOG.trace("extra route {} deleted successfully", route);
                         }
                     }
-                } catch (TransactionCommitFailedException | ReadFailedException e) {
+                } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
                     LOG.error("exception in deleting extra route with destination {} for interface {}",
                             destination, infName, e);
                 }
@@ -2334,11 +2321,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         // read VPNMaps
         VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
         if (vpnMap != null) {
-            List<RouterIds> routerIdsList = vpnMap.getRouterIds();
+            Map<RouterIdsKey, RouterIds> keyRouterIdsMap = vpnMap.getRouterIds();
             List<Uuid> routerUuidList = new ArrayList<>();
             // dissociate router
-            if (routerIdsList != null && !routerIdsList.isEmpty()) {
-                for (RouterIds router : routerIdsList) {
+            if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) {
+                for (RouterIds router : keyRouterIdsMap.values()) {
                     Uuid routerId = router.getRouterId();
                     routerUuidList.add(routerId);
                     dissociateRouterFromVpn(vpnId, routerId);
@@ -2359,7 +2346,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
-        return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
+        return vpnInstance != null && vpnInstance.isL2vpn();
     }
 
     // TODO Clean up the exception handling
@@ -2376,7 +2363,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             }
         }
         if (ipVersion != IpVersionChoice.UNDEFINED) {
-            LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
+            LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ",
                     ipVersion, vpnId);
             neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
         }
@@ -2417,7 +2404,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
         }
         if (ipVersion != IpVersionChoice.UNDEFINED) {
-            LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
+            LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ",
                     ipVersion, vpnId);
             neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
                     false);
@@ -2435,6 +2422,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
         List<String> failedNwList = new ArrayList<>();
         HashSet<Uuid> passedNwList = new HashSet<>();
+        ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
         boolean isExternalNetwork = false;
         if (networkList.isEmpty()) {
             LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
@@ -2458,6 +2446,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 return failedNwList;
             }
             Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+            boolean isIpFamilyUpdated = false;
+            IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
             for (Uuid nw : networkList) {
                 Network network = neutronvpnUtils.getNeutronNetwork(nw);
                 if (network == null) {
@@ -2482,15 +2472,26 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                                    + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
                     continue;
                 }
-                if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
-                    LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
-                            nw.getValue(), vpnId.getValue());
-                    failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
-                            nw.getValue(), vpnId.getValue()));
-                    continue;
-                }
-                if (NeutronvpnUtils.getIsExternal(network)) {
+                /* Handle association of external network(s) to Internet BGP-VPN use case outside of the
+                 * networkList iteration
+                 */
+                if (neutronvpnUtils.getIsExternal(network)) {
+                    extNwMap.put(nw, network);
                     isExternalNetwork = true;
+                    //Check whether router-gw is set with external network before external network to BGPVPN association
+                    List<Uuid> routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw);
+                    if (!routerList.isEmpty()) {
+                        for (Uuid routerId : routerList) {
+                            //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance
+                            if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
+                                ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6);
+                                LOG.debug("associateNetworksToVpn: External network {} is already associated with "
+                                        + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 "
+                                        + "address family type in Internet VPN Instance {}", network, routerId, vpnId);
+                                break;
+                            }
+                        }
+                    }
                 }
                 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
                 if (subnetmapList == null || subnetmapList.isEmpty()) {
@@ -2500,17 +2501,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
                     continue;
                 }
-                IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
                 for (Subnetmap subnetmap : subnetmapList) {
                     IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
                     if (!ipVersion.isIpVersionChosen(ipVers)) {
                         ipVersion = ipVersion.addVersion(ipVers);
                     }
                 }
-                if (ipVersion != IpVersionChoice.UNDEFINED) {
-                    LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
+                //Update vpnInstance for IP address family
+                if (ipVersion != IpVersionChoice.UNDEFINED && !isIpFamilyUpdated) {
+                    LOG.debug("associateNetworksToVpn: Updating vpnInstance with ip address family {}"
                             + " for VPN {} ", ipVersion, vpnId);
                     neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
+                    isIpFamilyUpdated = true;
                 }
                 for (Subnetmap subnetmap : subnetmapList) {
                     Uuid subnetId = subnetmap.getId();
@@ -2532,8 +2534,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     }
                 }
                 passedNwList.add(nw);
+                //Handle association of external network(s) to Internet BGP-VPN Instance use case
+                if (!extNwMap.isEmpty() || extNwMap != null) {
+                    for (Network extNw : extNwMap.values()) {
+                        if (!associateExtNetworkToVpn(vpnId, extNw, vpnInstance.getBgpvpnType())) {
+                            LOG.error("associateNetworksToVpn: Failed to associate Provider External Network {} with "
+                                    + "VPN {}", extNw, vpnId.getValue());
+                            failedNwList.add(String.format("Failed to associate Provider External Network %s with "
+                                            + "VPN %s", extNw, vpnId.getValue()));
+                            continue;
+                        }
+                    }
+                }
             }
-        } catch (ReadFailedException e) {
+        } catch (ExecutionException | InterruptedException e) {
             LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
                     networkList, e);
             failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
@@ -2547,18 +2561,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return failedNwList;
     }
 
-    private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
+    private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet,
+                                             VpnInstance.BgpvpnType bgpVpnType) {
         if (!addExternalNetworkToVpn(extNet, vpnId)) {
             return false;
         }
-        VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
-        if (vpnOpDataEntry == null) {
-            LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
-            return false;
-        }
-        if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
-            LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
-            neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
+        if (!bgpVpnType.equals(VpnInstance.BgpvpnType.InternetBGPVPN)) {
+            LOG.info("associateExtNetworkToVpn: External network {} is associated to VPN {}."
+                            + "Hence set vpnInstance type to {} from {} ", extNet.key().getUuid().getValue(),
+                    vpnId.getValue(), VpnInstance.BgpvpnType.InternetBGPVPN.getName(),
+                    VpnInstance.BgpvpnType.BGPVPN.getName());
+            neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.InternetBGPVPN, vpnId);
         }
         //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
         List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
@@ -2600,6 +2613,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
         List<String> failedNwList = new ArrayList<>();
         HashSet<Uuid> passedNwList = new HashSet<>();
+        ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
         if (networkList.isEmpty()) {
             LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
             failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
@@ -2634,20 +2649,36 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 vpnId.getValue()));
                 continue;
             }
-            if (NeutronvpnUtils.getIsExternal(network)) {
-                if (disassociateExtNetworkFromVpn(vpnId, network)) {
-                    passedNwList.add(nw);
-                } else {
-                    LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
-                              nw.getValue(), vpnId.getValue());
-                    failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
-                                                   vpnId.getValue()));
-                    continue;
+            /* Handle disassociation of external network(s) from Internet BGP-VPN use case outside of the
+             * networkList iteration
+             */
+            if (neutronvpnUtils.getIsExternal(network)) {
+                extNwMap.put(nw, network);
+                //Handle external-Nw to BGPVPN Disassociation and still ext-router is being set with external-Nw
+                List<Uuid> routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw);
+                if (!routerList.isEmpty()) {
+                    for (Uuid routerId : routerList) {
+                        //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance
+                        if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
+                            ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6);
+                            LOG.debug("dissociateNetworksFromVpn: External network {} is still associated with "
+                                    + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 "
+                                    + "address family type in Internet VPN Instance {}", network, routerId, vpnId);
+                            break;
+                        }
+                    }
                 }
             }
-            IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
             for (Uuid subnet : networkSubnets) {
                 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
+                if (subnetmap == null) {
+                    failedNwList.add(String.format("subnetmap %s not found for network %s",
+                            subnet.getValue(), nw.getValue()));
+                    LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
+                            + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
+                            vpnId.getValue());
+                    continue;
+                }
                 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
                 if (!ipVersion.isIpVersionChosen(ipVers)) {
                     ipVersion = ipVersion.addVersion(ipVers);
@@ -2655,7 +2686,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 if (!NeutronvpnUtils.getIsExternal(network)) {
                     LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
                             vpnId.getValue());
-                    removeSubnetFromVpn(vpnId, subnet, null);
+                    removeSubnetFromVpn(vpnId, subnetmap, null);
                     Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
                     vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
                             vpnId.getValue());
@@ -2663,11 +2694,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
             if (ipVersion != IpVersionChoice.UNDEFINED) {
-                LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
+                LOG.debug("dissociateNetworksFromVpn: Updating vpnInstance with ip address family {}"
                         + " for VPN {}", ipVersion, vpnId);
                 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
             }
         }
+        //Handle disassociation of external network(s) from Internet BGP-VPN Instance use case
+        if (!extNwMap.isEmpty() || extNwMap != null) {
+            for (Network extNw : extNwMap.values()) {
+                if (disassociateExtNetworkFromVpn(vpnId, extNw)) {
+                    passedNwList.add(extNw.getUuid());
+                } else {
+                    LOG.error("dissociateNetworksFromVpn: Failed to withdraw External Provider Network {} from VPN {}",
+                            extNw, vpnId.getValue());
+                    failedNwList.add(String.format("Failed to withdraw External Provider Network %s from VPN %s",
+                            extNw, vpnId.getValue()));
+                    continue;
+                }
+            }
+        }
         clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
         LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
                 passedNwList, vpnId.getValue());
@@ -2691,10 +2736,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
         }
-        //Set VPN Type is BGPVPNExternal from BGPVPNInternet
-        LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
-                VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
-        neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
+        ///Set VPN Type is BGPVPN from InternetBGPVPN
+        LOG.info("disassociateExtNetworkFromVpn: Set BGP-VPN type with {} for VPN {} and update IPv6 address family. "
+                        + "Since external network is disassociated from VPN {}",
+                VpnInstance.BgpvpnType.BGPVPN, extNet, vpnId.getValue());
+        neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.BGPVPN, vpnId);
         IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
         for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
@@ -2777,13 +2823,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("associateRouter {}", input);
         StringBuilder returnMsg = new StringBuilder();
         Uuid vpnId = input.getVpnId();
-        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
-                routerIds = input.getRouterIds();
-        Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
+        Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter
+                .input.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
+                .associaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
+        Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!");
         Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
         Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
-                .RouterIds routerId : routerIds) {
+                .RouterIds routerId : keyRouterIdsMap.values()) {
             VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
             Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
             if (vpnMap != null) {
@@ -2834,7 +2881,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             List<String> fixedIPList = new ArrayList<>();
             Port port = neutronvpnUtils.getNeutronPort(portId);
             if (port != null) {
-                for (FixedIps ip : port.nonnullFixedIps()) {
+                for (FixedIps ip : port.nonnullFixedIps().values()) {
                     fixedIPList.add(ip.getIpAddress().stringValue());
                 }
             } else {
@@ -2919,15 +2966,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("dissociateRouter {}", input);
         StringBuilder returnMsg = new StringBuilder();
         Uuid vpnId = input.getVpnId();
-        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
-                .RouterIds> routerIdList = input.getRouterIds();
+        Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
+                .RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
+                .dissociaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
         String routerIdsString = "";
-        Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
+        Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!");
         Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
-        Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
+        Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!");
         if (neutronvpnUtils.getVpnMap(vpnId) != null) {
             for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
-                    .RouterIds routerId : routerIdList) {
+                    .RouterIds routerId : keyRouterIdsMap.values()) {
                 try {
                     if (routerId != null) {
                         routerIdsString += routerId.getRouterId() + ", ";
@@ -2977,13 +3025,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (vpnId != null) {
             // remove existing external vpn interfaces
             for (Uuid subnetId : routerSubnetIds) {
-                removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
+                Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
+                if (subnetmap != null) {
+                    removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
+                } else {
+                    LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
+                            subnetId, routerId.getValue());
+                }
             }
             clearFromVpnMaps(vpnId, routerId, null);
         } else {
             // remove existing internal vpn interfaces
             for (Uuid subnetId : routerSubnetIds) {
-                removeSubnetFromVpn(routerId, subnetId, internetVpnId);
+                Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
+                if (subnetmap != null) {
+                    removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
+                } else {
+                    LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
+                            subnetId, routerId.getValue());
+                }
             }
         }
         // delete entire vpnMaps node for internal VPN
@@ -3031,9 +3091,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
      *
      * @return a List of String to be printed on screen
-     * @throws ReadFailedException if there was a problem reading from the data store
+     * @throws ExecutionException or InterruptedException   if there was a problem reading from the data store
      */
-    public List<String> showNeutronPortsCLI() throws ReadFailedException {
+    public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
         List<String> result = new ArrayList<>();
         result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length",
             "IP Address"));
@@ -3042,11 +3102,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
         Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
         if (ports.isPresent() && ports.get().getPort() != null) {
-            for (Port port : ports.get().nonnullPort()) {
-                List<FixedIps> fixedIPs = port.getFixedIps();
-                if (fixedIPs != null && !fixedIPs.isEmpty()) {
+            for (Port port : ports.get().nonnullPort().values()) {
+                Map<FixedIpsKey, FixedIps> keyFixedIpsMap = port.getFixedIps();
+                if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) {
                     List<String> ipList = new ArrayList<>();
-                    for (FixedIps fixedIp : fixedIPs) {
+                    for (FixedIps fixedIp : keyFixedIpsMap.values()) {
                         IpAddress ipAddress = fixedIp.getIpAddress();
                         if (ipAddress.getIpv4Address() != null) {
                             ipList.add(ipAddress.getIpv4Address().getValue());
@@ -3149,7 +3209,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return;
         }
 
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+        LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
             for (String elanInterface : extElanInterfaces) {
                 createExternalVpnInterface(extNetId, elanInterface, tx);
             }
@@ -3164,7 +3224,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("No external ports attached for external network {}", extNetId.getValue());
             return;
         }
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+        LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
             for (String elanInterface : extElanInterfaces) {
                 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
                         .buildVpnInterfaceIdentifier(elanInterface);
@@ -3190,7 +3250,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return;
         }
         if (wrtConfigTxn == null) {
-            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+            LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
                 "Error writing VPN interface");
             return;
@@ -3238,7 +3298,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         if (wrtConfigTxn == null) {
             LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
-            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+            LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
                 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
             }), LOG, "Error updating VPN interface with adjacencies");
             return;
@@ -3266,7 +3326,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
                     if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
                         List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
-                                optionalVpnInterface.get().getVpnInstanceNames());
+                                optionalVpnInterface.get().getVpnInstanceNames().values());
                         if (listVpnInstances.isEmpty()
                                 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
                             VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
@@ -3284,7 +3344,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     LOG.info("Updating vpn interface {} with new adjacencies", infName);
                     wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
                 }
-            } catch (IllegalStateException | ReadFailedException ex) {
+            } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
                 // FIXME: why are we catching IllegalStateException here?
                 LOG.error("Update of vpninterface {} failed", infName, ex);
             }
@@ -3339,7 +3399,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
                                                   networks);
             return true;
-        } catch (TransactionCommitFailedException | ReadFailedException ex) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
             LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
                       extNetId.getValue(), ex);
         }
@@ -3368,7 +3428,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     extNetId.getValue());
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
             return true;
-        } catch (TransactionCommitFailedException | ReadFailedException ex) {
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
             LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
                     extNetId.getValue(), ex);
         }
@@ -3379,10 +3439,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         Optional<String> existingVpnName = Optional.of(primaryRd);
         Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
         try {
-            vpnInstanceOpDataOptional = SingleTransactionDataBroker
-                .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
+            vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
                     neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
-        } catch (ReadFailedException e) {
+        } catch (ExecutionException | InterruptedException e) {
             LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
                     primaryRd, e);
             /*Read failed. We don't know if a VPN exists or not.
@@ -3392,7 +3451,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (vpnInstanceOpDataOptional.isPresent()) {
             existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
         } else {
-            existingVpnName = Optional.absent();
+            existingVpnName = Optional.empty();
         }
         return existingVpnName;
     }