Create l3vpn & asso with ext-nw failed
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
index d2f37a6559d23d850fefecf17b358af571a62700..b44bef074ad84cc8e000fe5bf66e8f61d6f5e6a0 100644 (file)
@@ -11,7 +11,6 @@ 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.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
 import static org.opendaylight.genius.infra.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;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -19,6 +18,7 @@ import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
+import edu.umd.cs.findbugs.annotations.CheckReturnValue;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -30,31 +30,36 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 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.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.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 java.util.function.Consumer;
 import java.util.stream.Collectors;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
-import org.opendaylight.genius.infra.Datastore;
+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.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.jobcoordinator.JobCoordinator;
-import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
-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.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;
 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
@@ -64,39 +69,38 @@ import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
 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.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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
+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.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.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;
 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;
@@ -130,17 +134,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
 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.RouterInterfacesMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
 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.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;
 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;
@@ -153,12 +155,14 @@ 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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
@@ -168,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.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;
 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;
@@ -188,11 +193,10 @@ import org.slf4j.helpers.MessageFormatter;
 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
-    private static long LOCK_WAIT_TIME = 10L;
+    private static final long LOCK_WAIT_TIME = 10L;
 
     private final DataBroker dataBroker;
     private final ManagedNewTransactionRunner txRunner;
 
     private final DataBroker dataBroker;
     private final ManagedNewTransactionRunner txRunner;
-    private final NotificationPublishService notificationPublishService;
     private final VpnRpcService vpnRpcService;
     private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
     private final IElanService elanService;
     private final VpnRpcService vpnRpcService;
     private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
     private final IElanService elanService;
@@ -204,19 +208,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     private final IVpnManager vpnManager;
     private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
     private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
     private final IVpnManager vpnManager;
     private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
     private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
-    private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
-    private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
+    private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
+    private final NamedLocks<String> interfaceLock = new NamedLocks<>();
 
     @Inject
     public NeutronvpnManager(
 
     @Inject
     public NeutronvpnManager(
-            final DataBroker dataBroker, final NotificationPublishService notiPublishService,
+            final DataBroker dataBroker,
             final VpnRpcService vpnRpcSrv, final IElanService elanService,
             final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
             final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
             final VpnRpcService vpnRpcSrv, final IElanService elanService,
             final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
             final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
-            final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
+            final JobCoordinator jobCoordinator,
+            final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
         this.dataBroker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.dataBroker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
-        notificationPublishService = notiPublishService;
         vpnRpcService = vpnRpcSrv;
         this.elanService = elanService;
         floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
         vpnRpcService = vpnRpcSrv;
         this.elanService = elanService;
         floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
@@ -236,15 +240,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.info("{} close", getClass().getSimpleName());
     }
 
         LOG.info("{} close", getClass().getSimpleName());
     }
 
-    private void configureFeatures() {
+    private void configureFeatures() throws TransactionCommitFailedException {
         InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
                         Neutron.class).child(Features.class).child(
                         Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
         Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
         try {
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
         InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
                         Neutron.class).child(Features.class).child(
                         Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
         Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
         try {
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
-        } catch (TransactionCommitFailedException e) {
-            LOG.warn("Error configuring feature {}", feature, e);
+        } catch (OptimisticLockFailedException e) {
+            LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
+        }
+        InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
+                Neutron.class).child(Features.class).child(
+                Feature.class, new FeatureKey(BgpvpnVni.class)).build();
+        Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
+        try {
+            SingleTransactionDataBroker.syncWrite(
+                    dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
+        } catch (OptimisticLockFailedException e) {
+            LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
         }
     }
 
         }
     }
 
@@ -255,11 +269,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
-                                       NetworkAttributes.NetworkType networkType, long segmentationId) {
+                                       NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
+                                        boolean isExternalNw) {
         try {
             InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
         try {
             InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
-            synchronized (subnetId.getValue().intern()) {
-                LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
+            final ReentrantLock lock = lockForUuid(subnetId);
+            lock.lock();
+            try {
+                LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
                 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
                         LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
                 if (sn.isPresent()) {
                 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
                         LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
                 if (sn.isPresent()) {
@@ -269,13 +286,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
                 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
                         .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
                 }
                 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
                         .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
-                        .setNetworkType(networkType).setSegmentationId(segmentationId);
+                        .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
                 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
                     subnetId.getValue());
                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
                         subnetMapIdentifier, subnetmapBuilder.build());
                 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
                     subnetId.getValue());
                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
                         subnetMapIdentifier, subnetmapBuilder.build());
+            } 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
             LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
         }
         // check if there are ports to update for already created Subnetmap node
@@ -288,206 +307,218 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
         }
     }
 
-    protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
-        Subnetmap subnetmap = null;
-        SubnetmapBuilder builder = null;
+    @Nullable
+    protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
+            @Nullable Uuid internetvpnId) {
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
                 .build();
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
                 .build();
+        final ReentrantLock lock = lockForUuid(subnetId);
+        lock.lock();
         try {
         try {
-            synchronized (subnetId.getValue().intern()) {
-                Optional<Subnetmap> sn =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                id);
-                if (sn.isPresent()) {
-                    builder = new SubnetmapBuilder(sn.get());
-                    LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
-                } else {
-                    LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
-                    return null;
-                }
-                if (routerId != null) {
-                    builder.setRouterId(routerId);
-                }
-                if (vpnId != null) {
-                    builder.setVpnId(vpnId);
-                }
+            Optional<Subnetmap> sn =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+            if (!sn.isPresent()) {
+                LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
+                return null;
+            }
+            LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
+            SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+            if (routerId != null) {
+                builder.setRouterId(routerId);
+            }
+            if (vpnId != null) {
+                builder.setVpnId(vpnId);
+            }
+            if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
                 builder.setInternetVpnId(internetvpnId);
                 builder.setInternetVpnId(internetvpnId);
-
-                subnetmap = builder.build();
-                LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
-                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
             }
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
+            Subnetmap subnetmap = builder.build();
+            LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
+            SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+            return subnetmap;
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
             LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
             LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
+            return null;
+        } finally {
+            lock.unlock();
         }
         }
-        return subnetmap;
     }
 
     }
 
-    protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
-                                               Uuid routerInterfacePortId, String fixedIp,
-                                               String routerIntfMacAddress, Uuid vpnId) {
-        Subnetmap subnetmap = null;
-        SubnetmapBuilder builder = null;
+    protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
+                                               @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
+                                               @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
         InstanceIdentifier<Subnetmap> id =
         InstanceIdentifier<Subnetmap> id =
-            InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+                InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+        final ReentrantLock lock = lockForUuid(subnetId);
+        lock.lock();
         try {
         try {
-            synchronized (subnetId.getValue().intern()) {
-                Optional<Subnetmap> sn =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                id);
-                if (sn.isPresent()) {
-                    builder = new SubnetmapBuilder(sn.get());
-                    LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
-                        subnetId.getValue());
-                } else {
-                    LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
-                        subnetId.getValue());
-                    return;
-                }
-                builder.setRouterId(routerId);
-                builder.setRouterInterfacePortId(routerInterfacePortId);
-                builder.setRouterIntfMacAddress(routerIntfMacAddress);
-                builder.setRouterInterfaceFixedIp(fixedIp);
-                if (vpnId != null) {
-                    builder.setVpnId(vpnId);
-                }
-                subnetmap = builder.build();
-                LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
+            Optional<Subnetmap> sn =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+            if (!sn.isPresent()) {
+                LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
                     subnetId.getValue());
                     subnetId.getValue());
-                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+                return;
             }
             }
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
-            LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
+            LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
+                subnetId.getValue());
+            SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+            builder.setRouterId(routerId);
+            builder.setRouterInterfacePortId(routerInterfacePortId);
+            builder.setRouterIntfMacAddress(routerIntfMacAddress);
+            builder.setRouterInterfaceFixedIp(fixedIp);
+            if (vpnId != null) {
+                builder.setVpnId(vpnId);
+            }
+            Subnetmap subnetmap = builder.build();
+            LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
+                subnetId.getValue());
+            SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
+            LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
                 subnetId.getValue(), e);
                 subnetId.getValue(), e);
+        } finally {
+            lock.unlock();
         }
     }
 
         }
     }
 
-    protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
+    protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
+            @Nullable Uuid directPortId) {
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
                 new SubnetmapKey(subnetId)).build();
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
                 new SubnetmapKey(subnetId)).build();
-        LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
+        LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
+        final ReentrantLock lock = lockForUuid(subnetId);
+        lock.lock();
         try {
         try {
-            synchronized (subnetId.getValue().intern()) {
-                Optional<Subnetmap> sn =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                id);
-                if (sn.isPresent()) {
-                    SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
-                    if (null != portId) {
-                        List<Uuid> portList = builder.getPortList();
-                        if (null == portList) {
-                            portList = new ArrayList<>();
-                        }
-                        portList.add(portId);
-                        builder.setPortList(portList);
-                        LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
-                            subnetId.getValue(), portId.getValue());
+            Optional<Subnetmap> sn =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        id);
+            if (sn.isPresent()) {
+                SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+                if (null != portId) {
+                    List<Uuid> existingPortList = builder.getPortList();
+                    List<Uuid> portList = new ArrayList<>();
+                    if (null != existingPortList) {
+                        portList.addAll(existingPortList);
                     }
                     }
-                    if (null != directPortId) {
-                        List<Uuid> directPortList = builder.getDirectPortList();
-                        if (null == directPortList) {
-                            directPortList = new ArrayList<>();
-                        }
-                        directPortList.add(directPortId);
-                        builder.setDirectPortList(directPortList);
-                        LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
-                                directPortId.getValue());
+                    portList.add(portId);
+                    builder.setPortList(portList);
+                    LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
+                        subnetId.getValue(), portId.getValue());
+                }
+                if (null != directPortId) {
+                    List<Uuid> existingDirectPortList = builder.getDirectPortList();
+                    List<Uuid> directPortList = new ArrayList<>();
+                    if (null != existingDirectPortList) {
+                        directPortList.addAll(existingDirectPortList);
                     }
                     }
-                    subnetmap = builder.build();
-                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
-                            subnetmap);
-                } else {
-                    LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
-                        + "cache ", subnetId.getValue(), portId.getValue());
-                    unprocessedPortsMap.put(portId, subnetId);
+                    directPortList.add(directPortId);
+                    builder.setDirectPortList(directPortList);
+                    LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
+                        directPortId.getValue());
                 }
                 }
+                subnetmap = builder.build();
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
+                    subnetmap);
+            } else {
+                LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
+                        + "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);
             LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
+        } finally {
+            lock.unlock();
         }
         return subnetmap;
     }
 
         }
         return subnetmap;
     }
 
-    protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
-                                            Uuid vpnId, Uuid portId) {
+    protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
+                                            Uuid vpnId, @Nullable Uuid portId) {
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
                 .build();
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
                 .build();
+        final ReentrantLock lock = lockForUuid(subnetId);
+        lock.lock();
         try {
         try {
-            synchronized (subnetId.getValue().intern()) {
-                Optional<Subnetmap> sn =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                id);
-                if (sn.isPresent()) {
-                    SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
-                    if (routerId != null) {
-                        builder.setRouterId(null);
-                    }
-                    if (networkId != null) {
-                        builder.setNetworkId(null);
-                    }
-                    if (vpnId != null) {
-                        builder.setVpnId(null);
-                    }
-                    builder.setInternetVpnId(null);
-                    if (portId != null && builder.getPortList() != null) {
-                        List<Uuid> portList = builder.getPortList();
-                        portList.remove(portId);
-                        builder.setPortList(portList);
-                    }
-
-                    subnetmap = builder.build();
-                    LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
-                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
-                            subnetmap);
-                } else {
-                    LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
+            Optional<Subnetmap> sn =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        id);
+            if (sn.isPresent()) {
+                SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+                if (routerId != null) {
+                    builder.setRouterId(null);
+                }
+                if (networkId != null) {
+                    builder.setNetworkId(null);
                 }
                 }
+                if (vpnId != null) {
+                    builder.setVpnId(null);
+                }
+                builder.setInternetVpnId(null);
+                if (portId != null && builder.getPortList() != null) {
+                    List<Uuid> portList = new ArrayList<>(builder.getPortList());
+                    portList.remove(portId);
+                    builder.setPortList(portList);
+                }
+
+                subnetmap = builder.build();
+                LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
+                    subnetmap);
+            } 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());
             LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
+        } finally {
+            lock.unlock();
         }
         return subnetmap;
     }
 
         }
         return subnetmap;
     }
 
-    protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
+    @Nullable
+    protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
+            @Nullable Uuid directPortId) {
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
                 new SubnetmapKey(subnetId)).build();
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
                 new SubnetmapKey(subnetId)).build();
+        final ReentrantLock lock = lockForUuid(subnetId);
+        lock.lock();
         try {
         try {
-            synchronized (subnetId.getValue().intern()) {
-                Optional<Subnetmap> sn =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                id);
-                if (sn.isPresent()) {
-                    SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
-                    if (null != portId && null != builder.getPortList()) {
-                        List<Uuid> portList = builder.getPortList();
-                        portList.remove(portId);
-                        builder.setPortList(portList);
-                        LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
-                                subnetId.getValue());
-                    }
-                    if (null != directPortId && null != builder.getDirectPortList()) {
-                        List<Uuid> directPortList = builder.getDirectPortList();
-                        directPortList.remove(directPortId);
-                        builder.setDirectPortList(directPortList);
-                        LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
-                                .getValue(), subnetId.getValue());
-                    }
-                    subnetmap = builder.build();
-                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
-                            subnetmap);
-                } else {
-                    LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
+            Optional<Subnetmap> sn =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        id);
+            if (sn.isPresent()) {
+                SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+                if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
+                    List<Uuid> portList = new ArrayList<>(builder.getPortList());
+                    portList.remove(portId);
+                    builder.setPortList(portList);
+                    LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
+                        subnetId.getValue());
                 }
                 }
+                if (null != directPortId && null != builder.getDirectPortList()
+                        && !builder.getDirectPortList().isEmpty()) {
+                    List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
+                    directPortList.remove(directPortId);
+                    builder.setDirectPortList(directPortList);
+                    LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
+                        .getValue(), subnetId.getValue());
+                }
+                subnetmap = builder.build();
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
+                    subnetmap);
+            } 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);
             LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
                     subnetId.getValue(), e);
+        } finally {
+            lock.unlock();
         }
         return subnetmap;
     }
         }
         return subnetmap;
     }
@@ -498,13 +529,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         InstanceIdentifier<Subnetmap> subnetMapIdentifier =
                 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
         LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
         InstanceIdentifier<Subnetmap> subnetMapIdentifier =
                 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
         LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
+        final ReentrantLock lock = lockForUuid(subnetId);
+        lock.lock();
         try {
         try {
-            synchronized (subnetId.getValue().intern()) {
-                SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                        subnetMapIdentifier);
-            }
+            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
         } catch (TransactionCommitFailedException e) {
             LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
         } catch (TransactionCommitFailedException e) {
             LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
+        } finally {
+            lock.unlock();
         }
     }
 
         }
     }
 
@@ -516,132 +548,124 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIdentifier);
             if (!vpnInstanceConfig.isPresent()) {
                     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);
                 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());
             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,
         }
     }
 
     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<>();
         String vpnName = vpnId.getValue();
         VpnInstanceBuilder builder = null;
         List<VpnTarget> vpnTargetList = new ArrayList<>();
-        boolean isLockAcquired = false;
         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+        Optional<VpnInstance> optionalVpn;
         try {
         try {
-            Optional<VpnInstance> optionalVpn =
-                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                            vpnIdentifier);
-            LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
-            if (optionalVpn.isPresent()) {
-                builder = new VpnInstanceBuilder(optionalVpn.get());
-                LOG.debug("updating existing vpninstance node");
-            } else {
-                builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
-                        .setType(type).setL3vni(l3vni);
-            }
-            if (irt != null && !irt.isEmpty()) {
-                if (ert != null && !ert.isEmpty()) {
-                    List<String> commonRT = new ArrayList<>(irt);
-                    commonRT.retainAll(ert);
-
-                    for (String common : commonRT) {
-                        irt.remove(common);
-                        ert.remove(common);
-                        VpnTarget vpnTarget =
-                                new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
-                                        .setVrfRTType(VpnTarget.VrfRTType.Both).build();
-                        vpnTargetList.add(vpnTarget);
-                    }
-                }
-                for (String importRT : irt) {
-                    VpnTarget vpnTarget =
-                            new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
-                                    .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
-                    vpnTargetList.add(vpnTarget);
-                }
-            }
+            optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                vpnIdentifier);
+        } catch (ExecutionException | InterruptedException e) {
+            LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
+            return;
+        }
 
 
+        LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
+        if (optionalVpn.isPresent()) {
+            builder = new VpnInstanceBuilder(optionalVpn.get());
+            LOG.debug("updating existing vpninstance node");
+        } else {
+            builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
+                    .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN);
+        }
+        if (irt != null && !irt.isEmpty()) {
             if (ert != null && !ert.isEmpty()) {
             if (ert != null && !ert.isEmpty()) {
-                for (String exportRT : ert) {
+                List<String> commonRT = new ArrayList<>(irt);
+                commonRT.retainAll(ert);
+
+                for (String common : commonRT) {
+                    irt.remove(common);
+                    ert.remove(common);
                     VpnTarget vpnTarget =
                     VpnTarget vpnTarget =
-                            new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
-                                    .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+                            new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
+                            .setVrfRTType(VpnTarget.VrfRTType.Both).build();
                     vpnTargetList.add(vpnTarget);
                 }
             }
                     vpnTargetList.add(vpnTarget);
                 }
             }
+            for (String importRT : irt) {
+                VpnTarget vpnTarget =
+                        new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
+                        .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+                vpnTargetList.add(vpnTarget);
+            }
+        }
 
 
-            VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+        if (ert != null && !ert.isEmpty()) {
+            for (String exportRT : ert) {
+                VpnTarget vpnTarget =
+                        new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
+                        .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+                vpnTargetList.add(vpnTarget);
+            }
+        }
 
 
-            Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
-            Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
+        VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+        if (rd != null && !rd.isEmpty()) {
+            builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN);
+        }
 
 
-            if (rd != null && !rd.isEmpty()) {
-                ipv4vpnBuilder.setRouteDistinguisher(rd);
-                ipv6vpnBuilder.setRouteDistinguisher(rd);
+        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?!
+                logTryLockFailure(vpnId);
             }
 
             }
 
-            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());
-            }
-            VpnInstance newVpn = builder.build();
-            isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
             LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
             LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
-            SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
+            try {
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
                     newVpn);
                     newVpn);
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
-            LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
-        } finally {
-            if (isLockAcquired) {
-                vpnLock.unlock(vpnId);
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
             }
         }
     }
 
     private void deleteVpnMapsNode(Uuid vpnId) {
             }
         }
     }
 
     private void deleteVpnMapsNode(Uuid vpnId) {
-        boolean isLockAcquired = false;
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
                 .child(VpnMap.class, new VpnMapKey(vpnId))
                 .build();
         LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
                 .child(VpnMap.class, new VpnMapKey(vpnId))
                 .build();
         LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
-        try {
-            isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
-            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
-        } catch (TransactionCommitFailedException e) {
-            LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
-        } finally {
-            if (isLockAcquired) {
-                vpnLock.unlock(vpnId);
+        try (AcquireResult lock = tryVpnLock(vpnId)) {
+            if (!lock.wasAcquired()) {
+                // FIXME: why do we even bother with locking if we do not honor it?!
+                logTryLockFailure(vpnId);
+            }
+
+            try {
+                SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    vpnMapIdentifier);
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
             }
         }
     }
 
             }
         }
     }
 
-    private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
+    protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
+            @Nullable List<Uuid> networks) {
         VpnMapBuilder builder;
         VpnMapBuilder builder;
-        boolean isLockAcquired = false;
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
                 .child(VpnMap.class, new VpnMapKey(vpnId))
                 .build();
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
                 .child(VpnMap.class, new VpnMapKey(vpnId))
                 .build();
@@ -663,7 +687,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             }
             if (router != null) {
                 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
             }
             if (router != null) {
                 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
-                List<RouterIds> rtrIds = builder.getRouterIds();
+                List<RouterIds> rtrIds = builder.getRouterIds() != null
+                        ? new ArrayList<>(builder.getRouterIds().values()) : null;
                 if (rtrIds == null) {
                     rtrIds = Collections.singletonList(vpnRouterId);
                 } else {
                 if (rtrIds == null) {
                     rtrIds = Collections.singletonList(vpnRouterId);
                 } else {
@@ -672,30 +697,29 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 builder.setRouterIds(rtrIds);
             }
             if (networks != null) {
                 builder.setRouterIds(rtrIds);
             }
             if (networks != null) {
-                List<Uuid> nwList = builder.getNetworkIds();
-                if (nwList == null) {
-                    nwList = new ArrayList<>();
-                }
+                List<Uuid> nwList = builder.getNetworkIds() != null
+                    ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
                 nwList.addAll(networks);
                 builder.setNetworkIds(nwList);
             }
 
                 nwList.addAll(networks);
                 builder.setNetworkIds(nwList);
             }
 
-            isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
-            LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
-            SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
-                    builder.build());
-            LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
-        } catch (ReadFailedException | TransactionCommitFailedException e) {
-            LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
-        } finally {
-            if (isLockAcquired) {
-                vpnLock.unlock(vpnId);
+            try (AcquireResult lock = tryVpnLock(vpnId)) {
+                if (!lock.wasAcquired()) {
+                    // FIXME: why do we even bother with locking if we do not honor it?!
+                    logTryLockFailure(vpnId);
+                }
+
+                LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
+                        builder.build());
+                LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
             }
             }
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
+            LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
         }
     }
 
         }
     }
 
-    private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
-        boolean isLockAcquired = false;
+    private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
                 .child(VpnMap.class, new VpnMapKey(vpnId))
                 .build();
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
                 .child(VpnMap.class, new VpnMapKey(vpnId))
                 .build();
@@ -704,14 +728,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             optionalVpnMap =
                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnMapIdentifier);
             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);
             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 = vpnMap.getRouterIds();
+            List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values());
             if (rtrIds == null) {
                 rtrIds = new ArrayList<>();
             }
             if (rtrIds == null) {
                 rtrIds = new ArrayList<>();
             }
@@ -719,17 +743,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
                     rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
                     vpnMapBuilder.setRouterIds(rtrIds);
                 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
                     rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
                     vpnMapBuilder.setRouterIds(rtrIds);
-                    try {
-                        // remove entire node in case of internal VPN
-                        isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+
+                    try (AcquireResult lock = tryVpnLock(vpnId)) {
+                        if (!lock.wasAcquired()) {
+                            // FIXME: why do we even bother with locking if we do not honor it?!
+                            logTryLockFailure(vpnId);
+                        }
+
                         LOG.debug("removing vpnMaps node: {} ", vpnId);
                         LOG.debug("removing vpnMaps node: {} ", vpnId);
-                        SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                vpnMapIdentifier);
-                    } catch (TransactionCommitFailedException e) {
-                        LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
-                    } finally {
-                        if (isLockAcquired) {
-                            vpnLock.unlock(vpnId);
+                        try {
+                            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                                    vpnMapIdentifier);
+                        } catch (TransactionCommitFailedException e) {
+                            LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
                         }
                     }
                     return;
                         }
                     }
                     return;
@@ -740,7 +766,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
             if (networkIds != null) {
                 }
             }
             if (networkIds != null) {
-                List<Uuid> vpnNw = vpnMap.getNetworkIds();
+                List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
+                        ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
                 vpnNw.removeAll(networkIds);
                 if (vpnNw.isEmpty()) {
                     LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
                 vpnNw.removeAll(networkIds);
                 if (vpnNw.isEmpty()) {
                     LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
@@ -750,16 +777,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
 
                 }
             }
 
-            try {
-                isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+            try (AcquireResult lock = tryVpnLock(vpnId)) {
+                if (!lock.wasAcquired()) {
+                    // FIXME: why do we even bother with locking if we do not honor it?!
+                    logTryLockFailure(vpnId);
+                }
+
                 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
                 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
-                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
-                        vpnMapBuilder.build());
-            } catch (TransactionCommitFailedException e) {
-                LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
-            } finally {
-                if (isLockAcquired) {
-                    vpnLock.unlock(vpnId);
+                try {
+                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        vpnMapIdentifier, vpnMapBuilder.build());
+                } catch (TransactionCommitFailedException e) {
+                    LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
                 }
             }
         } else {
                 }
             }
         } else {
@@ -769,40 +798,43 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     private void deleteVpnInstance(Uuid vpnId) {
     }
 
     private void deleteVpnInstance(Uuid vpnId) {
-        boolean isLockAcquired = false;
         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
                 .child(VpnInstance.class,
                         new VpnInstanceKey(vpnId.getValue()))
                 .build();
         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
                 .child(VpnInstance.class,
                         new VpnInstanceKey(vpnId.getValue()))
                 .build();
-        try {
-            isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+
+        try (AcquireResult lock = tryVpnLock(vpnId)) {
+            if (!lock.wasAcquired()) {
+                // FIXME: why do we even bother with locking if we do not honor it?!
+                logTryLockFailure(vpnId);
+            }
+
             LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
             LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
-            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
-        } catch (TransactionCommitFailedException e) {
-            LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
-        } finally {
-            if (isLockAcquired) {
-                vpnLock.unlock(vpnId);
+            try {
+                SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
             }
         }
     }
 
     protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
             }
         }
     }
 
     protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
-                                                  TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn,
-                                                  Subnetmap sn, VpnInterface vpnIface) {
+                                                  TypedWriteTransaction<Configuration> wrtConfigTxn,
+                                                  @Nullable VpnInterface vpnIface) {
         List<Adjacency> adjList = new ArrayList<>();
         if (vpnIface != null) {
         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);
         }
         String infName = port.getUuid().getValue();
         LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
-        for (FixedIps ip : port.getFixedIps()) {
-            String ipValue = String.valueOf(ip.getIpAddress().getValue());
+        for (FixedIps ip : port.nonnullFixedIps().values()) {
+            String ipValue = ip.getIpAddress().stringValue();
             String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
             String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
-            if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
+            Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
+            if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
+                    snTemp.getSubnetIp(), false)) {
                 continue;
             }
                 continue;
             }
-            Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
             Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
             if (vpnId != null) {
                 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
             Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
             if (vpnId != null) {
                 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
@@ -823,7 +855,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (routerId != null) {
                 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
                 if (rtr != null && rtr.getRoutes() != null) {
             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
                     // 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
@@ -834,23 +866,35 @@ 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,
     }
 
     protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
-                                      TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
+                                      @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
         boolean isRouterInterface = false;
         if (port.getDeviceOwner() != null) {
             isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
         }
         boolean isRouterInterface = false;
         if (port.getDeviceOwner() != null) {
             isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
         }
-        Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
         String infName = port.getUuid().getValue();
         String infName = port.getUuid().getValue();
+        // Handling cluster reboot scenario where VpnInterface already exists in datastore.
+        VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
+        Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
         LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
         LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
-        writeVpnInterfaceToDs(vpnIds, infName, adjs, isRouterInterface, wrtConfigTxn);
+        writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
     }
 
     protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
     }
 
     protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
-                       Port port, Subnetmap sn, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
+                       Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
         String infName = port.getUuid().getValue();
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
         Optional<VpnInterface> optionalVpnInterface = null;
         String infName = port.getUuid().getValue();
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
         Optional<VpnInterface> optionalVpnInterface = null;
@@ -860,7 +904,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             optionalVpnInterface = SingleTransactionDataBroker
                     .syncReadOptional(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, vpnIfIdentifier);
             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;
         }
             LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
             return;
         }
@@ -869,10 +913,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
                 sn != null ? sn.getSubnetIp() : "null");
         }
         LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
                 sn != null ? sn.getSubnetIp() : "null");
-        List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency();
+        Map<AdjacencyKey, Adjacency> keyAdjacencyMap
+                = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
         List<Adjacency> updatedAdjsList = new ArrayList<>();
         boolean isIpFromAnotherSubnet = false;
         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) {
             String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
             if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
                 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
@@ -893,12 +938,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                           String.valueOf(adjString), wrtConfigTxn);
                 }
             } else {
                           String.valueOf(adjString), wrtConfigTxn);
                 }
             } else {
-                if (port.getDeviceOwner()
-                    .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
+                if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
+                        && sn.getRouterId() != null) {
                     Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
                     if (rtr != null && rtr.getRoutes() != null) {
                         List<Routes> extraRoutesToRemove = new ArrayList<>();
                     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);
                             }
                             if (rt.getNexthop().toString().equals(adjString)) {
                                 extraRoutesToRemove.add(rt);
                             }
@@ -913,13 +958,10 @@ 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);
         }
         if (vpnId != null) {
             updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
         }
-        if (internetVpnId != null) {
-            updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
-        }
         if (!isIpFromAnotherSubnet) {
             // no more subnetworks for neutron port
             if (sn != null && sn.getRouterId() != null) {
         if (!isIpFromAnotherSubnet) {
             // no more subnetworks for neutron port
             if (sn != null && sn.getRouterId() != null) {
@@ -934,9 +976,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void deleteVpnInterface(String infName, @Nullable String vpnId,
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void deleteVpnInterface(String infName, @Nullable String vpnId,
-                                      TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
+                                      @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
         if (wrtConfigTxn == null) {
         if (wrtConfigTxn == null) {
-            ListenableFutures.addErrorLogging(
+            LoggingFutures.addErrorLogging(
                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                         tx -> deleteVpnInterface(infName, vpnId, tx)),
                     LOG, "Error deleting VPN interface {} {}", infName, vpnId);
                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                         tx -> deleteVpnInterface(infName, vpnId, tx)),
                     LOG, "Error deleting VPN interface {} {}", infName, vpnId);
@@ -950,7 +992,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             optionalVpnInterface =
                 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIfIdentifier);
             optionalVpnInterface =
                 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIfIdentifier);
-        } catch (ReadFailedException ex) {
+        } catch (ExecutionException | InterruptedException ex) {
             LOG.error("Error during deletion of vpninterface {}", infName, ex);
             return;
         }
             LOG.error("Error during deletion of vpninterface {}", infName, ex);
             return;
         }
@@ -960,17 +1002,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         if (vpnId != null) {
             VpnInterface vpnInterface = optionalVpnInterface.get();
         }
         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())
                     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());
             }
                 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
                         .build());
             }
@@ -979,8 +1023,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         wrtConfigTxn.delete(vpnIfIdentifier);
     }
 
         wrtConfigTxn.delete(vpnIfIdentifier);
     }
 
-    protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
-                                             TypedWriteTransaction<Datastore.Configuration> writeConfigTxn,
+    protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
+                                             TypedWriteTransaction<Configuration> writeConfigTxn,
                                              Subnetmap sm) {
         if (vpnId == null || port == null) {
             return;
                                              Subnetmap sm) {
         if (vpnId == null || port == null) {
             return;
@@ -992,17 +1036,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     .syncReadOptional(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, vpnIfIdentifier);
             if (optionalVpnInterface.isPresent()) {
                     .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())
                 }
                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
-                         .setVpnInstanceNames(listVpn);
+                         .setVpnInstanceNames(keyVpnInstanceNamesMap);
                 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
                 LOG.debug("Updating vpn interface {}", infName);
                 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) {
                 while (adjacencyIter.hasNext()) {
                     Adjacency adjacency = adjacencyIter.next();
                     if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
@@ -1017,7 +1064,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     if (optionalVpnVipToPort.isPresent()) {
                         LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
                              infName, vpnId);
                     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);
                             adjacencyIter.remove();
                         }
                         neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
@@ -1025,13 +1072,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 mipToQuery, infName, vpnId.getValue());
                     }
                 }
                                 mipToQuery, infName, vpnId.getValue());
                     }
                 }
-                List<FixedIps> ips = port.getFixedIps();
-                for (FixedIps ip : ips) {
-                    String ipValue = String.valueOf(ip.getIpAddress().getValue());
+                for (FixedIps ip : port.nonnullFixedIps().values()) {
+                    String ipValue = ip.getIpAddress().stringValue();
+                    //skip IPv4 address
+                    if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
+                        continue;
+                    }
                     neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
                             ipValue, writeConfigTxn);
                 }
                     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());
                     }
                     if (sm != null && sm.getRouterId() != null) {
                         removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
                     }
@@ -1042,103 +1092,120 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
             }
             } else {
                 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
             }
-        } catch (ReadFailedException ex) {
+        } catch (ExecutionException | InterruptedException ex) {
             LOG.error("Update of vpninterface {} failed", infName, ex);
         }
     }
 
             LOG.error("Update of vpninterface {} failed", infName, ex);
         }
     }
 
-    protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
+    protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
                                       boolean isSubnetIp,
                                       boolean isSubnetIp,
-                                      TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
+                                      TypedWriteTransaction<Configuration> writeConfigTxn,
+                                      boolean isInternetVpn) {
         if (vpnId == null || port == null) {
             return;
         }
         if (vpnId == null || port == null) {
             return;
         }
-        boolean isLockAcquired = false;
         String infName = port.getUuid().getValue();
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
 
         String infName = port.getUuid().getValue();
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
 
-        try {
-            isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
-            Optional<VpnInterface> optionalVpnInterface =
-                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+        try (AcquireResult lock = tryInterfaceLock(infName)) {
+            if (!lock.wasAcquired()) {
+                // FIXME: why do we even bother with locking if we do not honor it?!
+                logTryLockFailure(infName);
+            }
+
+            try {
+                Optional<VpnInterface> optionalVpnInterface =
+                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIfIdentifier);
                             vpnIfIdentifier);
-            if (optionalVpnInterface.isPresent()) {
-                VpnInstanceNames vpnInstance = VpnHelper
-                    .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
-                List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
-                           .get().getVpnInstanceNames());
-                if (oldVpnId != null
-                    && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
-                    VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
-                }
-                if (vpnId.getValue() != null
-                    && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
-                    listVpn.add(vpnInstance);
-                }
-                VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
-                        .setVpnInstanceNames(listVpn);
-                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();
-                    while (adjacencyIter.hasNext()) {
-                        Adjacency adjacency = adjacencyIter.next();
-                        String mipToQuery = adjacency.getIpAddress().split("/")[0];
-                        InstanceIdentifier<LearntVpnVipToPort> id =
-                            NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
-                        Optional<LearntVpnVipToPort> optionalVpnVipToPort =
-                                SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                if (optionalVpnInterface.isPresent()) {
+                    VpnInstanceNames vpnInstance = VpnHelper
+                            .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
+                    List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface.get()
+                            .getVpnInstanceNames().values());
+                    if (oldVpnId != null
+                            && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
+                        VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
+                    }
+                    if (vpnId.getValue() != null
+                            && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
+                        listVpn.add(vpnInstance);
+                    }
+                    VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
+                            .setVpnInstanceNames(listVpn);
+                    LOG.debug("Updating vpn interface {}", infName);
+                    if (!isBeingAssociated) {
+                        Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
+                        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];
+                            InstanceIdentifier<LearntVpnVipToPort> id =
+                                    NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
+                            Optional<LearntVpnVipToPort> optionalVpnVipToPort =
+                                    SingleTransactionDataBroker.syncReadOptional(dataBroker,
                                         LogicalDatastoreType.OPERATIONAL, id);
                                         LogicalDatastoreType.OPERATIONAL, id);
-                        if (optionalVpnVipToPort.isPresent()) {
-                            LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
-                                + "from VPN {}", infName, vpnId, oldVpnId);
-                            adjacencyIter.remove();
-                            neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
-                            LOG.trace(
-                                    "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
+                            if (optionalVpnVipToPort.isPresent()
+                                    && optionalVpnVipToPort.get().getPortName().equals(infName)) {
+                                LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
+                                        + "from VPN {}", infName, vpnId, oldVpnId);
+                                adjacencyIter.remove();
+                                neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
+                                LOG.trace(
+                                    "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
+                                    mipToQuery, infName, vpnId.getValue());
+                            }
+                            InstanceIdentifier<VpnPortipToPort> build =
+                                    NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
+                            Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
+                                dataBroker, LogicalDatastoreType.OPERATIONAL, build);
+                            if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
+                                neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
+                                LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
                                     mipToQuery, infName, vpnId.getValue());
                                     mipToQuery, infName, vpnId.getValue());
+                            }
                         }
                         }
+                        Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build();
+                        vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
                     }
                     }
-                    Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
-                    vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
-                }
-                List<FixedIps> ips = port.getFixedIps();
-                for (FixedIps ip : ips) {
-                    String ipValue = String.valueOf(ip.getIpAddress().getValue());
-                    if (oldVpnId != null) {
-                        neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
+                    for (FixedIps ip : port.nonnullFixedIps().values()) {
+                        String ipValue = ip.getIpAddress().stringValue();
+                        if (oldVpnId != null) {
+                            neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
                                 ipValue, writeConfigTxn);
                                 ipValue, writeConfigTxn);
-                    }
-                    neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
+                        }
+                        if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
+                                && isInternetVpn == true) {
+                            continue;
+                        }
+
+                        neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
                             .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
                             .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
+                    }
+                    writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
+                } else {
+                    LOG.error("VPN Interface {} not found", infName);
                 }
                 }
-                writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
-            } else {
-                LOG.error("VPN Interface {} not found", infName);
-            }
-        } catch (ReadFailedException ex) {
-            LOG.error("Updation of vpninterface {} failed", infName, ex);
-        } finally {
-            if (isLockAcquired) {
-                interfaceLock.unlock(infName);
+            } catch (ExecutionException | InterruptedException ex) {
+                LOG.error("Updation of vpninterface {} failed", infName, ex);
             }
         }
     }
 
             }
         }
     }
 
-    public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
-                                    List<String> ert, Uuid router, List<Uuid> networks) {
+    public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
+                                    List<String> ertList, Uuid routerId, List<Uuid> networksList) {
 
 
-        IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
+        IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
 
         // Update VPN Instance node
 
         // Update VPN Instance node
-        updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
+        updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
 
         // Update local vpn-subnet DS
 
         // Update local vpn-subnet DS
-        updateVpnMaps(vpn, name, router, tenant, networks);
+        updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
 
 
-        if (router != null) {
-            Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
+        if (routerId != null) {
+            Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
             if (existingVpn != null) {
                 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
                 // if before reboot, router was already associated to VPN, should not proceed associating router to
             if (existingVpn != null) {
                 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
                 // if before reboot, router was already associated to VPN, should not proceed associating router to
@@ -1147,10 +1214,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
                 // RouterInterfacesMap via #createVPNInterface call.
                 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
                 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
                 // RouterInterfacesMap via #createVPNInterface call.
                 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
-                    + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
+                        + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
                 return;
             }
                 return;
             }
-            associateRouterToInternalVpn(vpn, router);
+            associateRouterToInternalVpn(vpnId, routerId);
         }
     }
 
         }
     }
 
@@ -1166,13 +1233,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 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,
      * @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, List<Uuid> networkList,
-                    VpnInstance.Type type, long l3vni) throws Exception {
+                    List<String> ertList,  @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
+                          boolean isL2Vpn, long l3vni) throws Exception {
 
         IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
 
 
         IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
 
@@ -1182,7 +1249,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 ipVersChoices = ipVersChoices.addVersion(vers);
             }
         }
                 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
 
         // Please note that router and networks will be filled into VPNMaps
         // by subsequent calls here to associateRouterToVpn and
@@ -1201,7 +1268,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
             if (!failStrings.isEmpty()) {
                 LOG.error("VPN {} association to networks failed for networks: {}. ",
             List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
             if (!failStrings.isEmpty()) {
                 LOG.error("VPN {} association to networks failed for networks: {}. ",
-                        vpnId.getValue(), failStrings.toString());
+                        vpnId.getValue(), failStrings);
                 throw new Exception(failStrings.toString());
             }
         }
                 throw new Exception(failStrings.toString());
             }
         }
@@ -1242,10 +1309,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 warningcount++;
                 continue;
             }
                 warningcount++;
                 continue;
             }
-            VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
             long l3vni = 0;
             if (vpn.getL3vni() != null) {
             long l3vni = 0;
             if (vpn.getL3vni() != null) {
-                l3vni = vpn.getL3vni();
+                l3vni = vpn.getL3vni().toJava();
             }
 
             List<String> existingRDs = neutronvpnUtils.getExistingRDs();
             }
 
             List<String> existingRDs = neutronvpnUtils.getExistingRDs();
@@ -1270,10 +1336,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 continue;
             }
             if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
                 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
                 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"
                     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"
@@ -1319,19 +1386,27 @@ 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
             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());
                 }
             }
             try {
                 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
                                 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
                     rtrIdsList.add(rtrId.getRouterId());
                 }
             }
             try {
                 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
                                 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
-                        vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
-                        vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
-                createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
-                        vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
-                        vpnInstanceType, l3vni);
+                        vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
+                        vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
+
+                List<String> rdList = vpn.getRouteDistinguisher() != null
+                        ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
+                List<String> importRdList = vpn.getImportRT() != null
+                        ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
+                List<String> exportRdList = vpn.getExportRT() != null
+                        ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
+
+                createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
+                        importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
             } catch (Exception ex) {
             } catch (Exception ex) {
+                LOG.error("VPN Creation exception :", ex);
                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
                         formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
                         ex.getMessage()));
                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
                         formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
                         ex.getMessage()));
@@ -1379,13 +1454,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                                 vpnsIdentifier);
                 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                                 vpnsIdentifier);
                 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
-                    for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
+                    for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) {
                         // eliminating implicitly created (router and VLAN provider external network specific) VPNs
                         // from getL3VPN output
                         // 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);
                         }
                     }
                             vpns.add(vpn);
                         }
                     }
@@ -1405,8 +1477,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 vpnIdentifier);
                 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
                 // getL3VPN output
                                 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(
                     vpns.add(optionalVpn.get());
                 } else {
                     result.set(
@@ -1420,24 +1491,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 // create VpnMaps id
                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
                 List<String> rd = Collections.EMPTY_LIST;
                 // 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<>();
 
                 }
                 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());
                             }
                             if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
                                 ertList.add(vpnTarget.getVrfRTValue());
                             }
@@ -1466,7 +1532,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     VpnMap vpnMap = optionalVpnMap.get();
                     List<Uuid> rtrIds = new ArrayList<>();
                     if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
                     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());
                         }
                     }
                             rtrIds.add(rtrId.getRouterId());
                         }
                     }
@@ -1481,7 +1547,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             opBuilder.setL3vpnInstances(l3vpnList);
             result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
 
             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());
         }
             result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
                     formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
         }
@@ -1500,10 +1566,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
         int failurecount = 0;
         int warningcount = 0;
 
         int failurecount = 0;
         int warningcount = 0;
-        List<Uuid> vpns = input.getId();
+        List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
         for (Uuid vpn : vpns) {
         for (Uuid vpn : vpns) {
-            RpcError error;
-            String msg;
             try {
                 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
                 InstanceIdentifier<VpnInstance> vpnIdentifier =
             try {
                 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
                 InstanceIdentifier<VpnInstance> vpnIdentifier =
@@ -1519,7 +1583,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                             formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
                     warningcount++;
                 }
                             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()));
                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
                         formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
                         ex.getMessage()));
@@ -1574,7 +1638,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 return;
             }
             final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
                 return;
             }
             final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
-            LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
+            LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
             if (isVpnOfTypeL2(vpnInstance)) {
                 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
                         NeutronEvpnUtils.Operation.ADD);
             if (isVpnOfTypeL2(vpnInstance)) {
                 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
                         NeutronEvpnUtils.Operation.ADD);
@@ -1604,112 +1668,121 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
                 final Boolean isRouterInterface = port.getDeviceOwner()
                         .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
                 }
                 final Boolean isRouterInterface = port.getDeviceOwner()
                         .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
-                jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
-                    txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
-                        Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
+                jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
+                    ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                        wrtConfigTxn -> {
+                            Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
                                     vpnIface);
                                     vpnIface);
-                        if (vpnIface == null) {
-                            LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
-                            Set<Uuid> listVpn = new HashSet<>();
-                            if (vpnId != null) {
-                                listVpn.add(vpnId);
-                            }
-                            if (internetId != null) {
-                                listVpn.add(internetId);
-                            }
-                            writeVpnInterfaceToDs(listVpn,
-                                    vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
-                            if (sn.getRouterId() != null) {
-                                addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
-                            }
-                        } else {
-                            LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
-                            if (vpnId != null) {
-                                updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
-                            }
-                            if (internetId != null) {
-                                updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
+                            if (vpnIface == null) {
+                                LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
+                                Set<Uuid> listVpn = new HashSet<>();
+                                if (vpnId != null) {
+                                    listVpn.add(vpnId);
+                                }
+                                if (internetId != null) {
+                                    listVpn.add(internetId);
+                                }
+                                writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
+                                        isRouterInterface, wrtConfigTxn);
+                                if (sn.getRouterId() != null) {
+                                    addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
+                                }
+                            } else {
+                                LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
+                                if (vpnId != null) {
+                                    updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
+                                }
+                                if (internetId != null) {
+                                    updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
+                                }
                             }
                             }
-                        }
-                    }))
-                );
+                        });
+                    LoggingFutures.addErrorLogging(future, LOG,
+                            "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
+                                    + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
+                    return Collections.singletonList(future);
+                });
             }
         }
     }
 
             }
         }
     }
 
-    protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, 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");
         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);
                   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",
         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) {
                 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",
         }
         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)) {
                 return;
             }
         }
         if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
-            neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
+            neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
                     NeutronEvpnUtils.Operation.DELETE);
         }
         boolean subnetVpnAssociation = false;
                     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;
             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 {}",
             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
             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) {
         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);
                 final Port port = neutronvpnUtils.getNeutronPort(portId);
-                jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
-                    () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
-                            CONFIGURATION, tx -> {
+                jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
+                    List<ListenableFuture<Void>> futures = new ArrayList<>();
+                    ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                        CONFIGURATION, tx -> {
                             if (port != null) {
                             if (port != null) {
-                                withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
+                                withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
                             } else {
                             } else {
-                                LOG.warn(
-                                        "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
-                                                + "port is absent in Neutron config DS", portId.getValue(),
-                                        subnet.getValue());
+                                LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
+                                                + " port is absent in Neutron config DS", portId.getValue(),
+                                        subnetId.getValue());
                             }
                             }
-                        })));
+                        });
+                    LoggingFutures.addErrorLogging(future, LOG,
+                            "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
+                                    + " belonging to subnet {} and vpnId {}",
+                            portId.getValue(), subnetId.getValue(), vpnId.getValue());
+                    futures.add(future);
+                    return futures;
+                });
             }
         }
         //update subnet-vpn association
             }
         }
         //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) {
     }
 
     protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
@@ -1732,10 +1805,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
                 if (isBeingAssociated) {
                     updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
             txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
                 if (isBeingAssociated) {
                     updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
-                            sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
+                            sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
                 } else {
                 } else {
-                    removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
-                                        wrtConfigTxn, sm);
+                    removeInternetVpnFromVpnInterface(vpn,
+                            neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
                 }
                 }
             )));
                 }
                 }
             )));
@@ -1752,15 +1825,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         tx -> {
                             if (isBeingAssociated) {
                                 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
                         tx -> {
                             if (isBeingAssociated) {
                                 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
-                                        true, false, tx);
+                                        true, false, tx, true);
                             } else {
                             } else {
-                                removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
+                                removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
                             }
                         })));
             }
         }
     }
 
                             }
                         })));
             }
         }
     }
 
+    @Nullable
     private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
         LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
                 oldVpnId.getValue(), newVpnId.getValue());
     private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
         LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
                 oldVpnId.getValue(), newVpnId.getValue());
@@ -1774,14 +1848,27 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
             return sn;
         }
             LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
             return sn;
         }
-
+        /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
+         * associated with internet BGP-VPN.
+         */
+        if (vpnExtUuid != null) {
+            /* Update V6 Internet default route match with new VPN metadata.
+             * isBeingAssociated = true means oldVpnId is same as routerId
+             * isBeingAssociated = false means newVpnId is same as routerId
+            */
+            if (isBeingAssociated) {
+                neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
+            } else {
+                neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
+            }
+        }
         //Update Router Interface first synchronously.
         //CAUTION:  Please DONOT make the router interface VPN Movement as an asynchronous commit again !
         ListenableFuture<Void> future =
                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                     tx -> updateVpnInterface(newVpnId, oldVpnId,
                         neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
         //Update Router Interface first synchronously.
         //CAUTION:  Please DONOT make the router interface VPN Movement as an asynchronous commit again !
         ListenableFuture<Void> future =
                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                     tx -> updateVpnInterface(newVpnId, oldVpnId,
                         neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
-                        isBeingAssociated, true, tx));
+                        isBeingAssociated, true, tx, false));
         Futures.addCallback(future, new FutureCallback<Void>() {
             @Override
             public void onSuccess(Void result) {
         Futures.addCallback(future, new FutureCallback<Void>() {
             @Override
             public void onSuccess(Void result) {
@@ -1796,7 +1883,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                                     tx -> updateVpnInterface(newVpnId, oldVpnId,
                                             neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
                                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                                     tx -> updateVpnInterface(newVpnId, oldVpnId,
                                             neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
-                                            tx))));
+                                            tx, false))));
                     }
                 }
             }
                     }
                 }
             }
@@ -1819,59 +1906,59 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
     }
 
     protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
-        synchronized (routerId.getValue().intern()) {
-            InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
-            try {
-                Optional<RouterInterfaces> optRouterInterfaces =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                routerInterfacesId);
-                Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
+        final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
+        final ReentrantLock lock = lockForUuid(routerId);
+        lock.lock();
+        try {
+            Optional<RouterInterfaces> optRouterInterfaces =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        routerInterfacesId);
+            Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
                     .setInterfaceId(interfaceName).build();
                     .setInterfaceId(interfaceName).build();
-                if (optRouterInterfaces.isPresent()) {
-                    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);
-                }
-            } catch (ReadFailedException | TransactionCommitFailedException e) {
-                LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
+            if (optRouterInterfaces.isPresent()) {
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
+            } else {
+                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 (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
+            LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
+        } finally {
+            lock.unlock();
         }
     }
 
     protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
         }
     }
 
     protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
-        synchronized (routerId.getValue().intern()) {
-            InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
-            try {
-                Optional<RouterInterfaces> optRouterInterfaces =
-                        SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                routerInterfacesId);
-                Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
+        final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
+        final ReentrantLock lock = lockForUuid(routerId);
+        lock.lock();
+        try {
+            Optional<RouterInterfaces> optRouterInterfaces =
+                    SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        routerInterfacesId);
+            Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
                     .setInterfaceId(interfaceName).build();
                     .setInterfaceId(interfaceName).build();
-                if (optRouterInterfaces.isPresent()) {
-                    RouterInterfaces routerInterfaces = optRouterInterfaces.get();
-                    List<Interfaces> interfaces = routerInterfaces.getInterfaces();
-                    if (interfaces != null && interfaces.remove(routerInterface)) {
-                        if (interfaces.isEmpty()) {
-                            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                    routerInterfacesId);
-                        } else {
-                            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                                    routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
-                        }
+            if (optRouterInterfaces.isPresent()) {
+                RouterInterfaces routerInterfaces = optRouterInterfaces.get();
+                List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values());
+                if (interfaces != null && interfaces.remove(routerInterface)) {
+                    if (interfaces.isEmpty()) {
+                        SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            routerInterfacesId);
+                    } else {
+                        SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
                     }
                 }
                     }
                 }
-            } catch (ReadFailedException | TransactionCommitFailedException e) {
-                LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
             }
             }
+        } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
+            LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
+        } finally {
+            lock.unlock();
         }
     }
 
         }
     }
 
@@ -1887,8 +1974,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
         for (Routes route : interVpnLinkRoutes) {
     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
         for (Routes route : interVpnLinkRoutes) {
-            String nexthop = String.valueOf(route.getNexthop().getValue());
-            String destination = String.valueOf(route.getDestination().getValue());
+            String nexthop = route.getNexthop().stringValue();
+            String destination = route.getDestination().stringValue();
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 AddStaticRouteInput rpcInput =
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 AddStaticRouteInput rpcInput =
@@ -1913,7 +2000,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
-                        String.valueOf(route.getDestination().getValue()), nexthop);
+                        route.getDestination().stringValue(), nexthop);
                 continue;
             }
         }
                 continue;
             }
         }
@@ -1930,8 +2017,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
         for (Routes route : interVpnLinkRoutes) {
     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
         for (Routes route : interVpnLinkRoutes) {
-            String nexthop = String.valueOf(route.getNexthop().getValue());
-            String destination = String.valueOf(route.getDestination().getValue());
+            String nexthop = route.getNexthop().stringValue();
+            String destination = route.getDestination().stringValue();
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 RemoveStaticRouteInput rpcInput =
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 RemoveStaticRouteInput rpcInput =
@@ -1939,12 +2026,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 .setVpnInstanceName(vpnName.getValue())
                                 .build();
 
                                 .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.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
                         vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
-                        String.valueOf(route.getDestination().getValue()), nexthop);
+                        route.getDestination().stringValue(), nexthop);
                 continue;
             }
         }
                 continue;
             }
         }
@@ -1954,7 +2041,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * Returns true if the specified nexthop is the other endpoint in an
      * InterVpnLink, regarding one of the VPN's point of view.
      */
      * Returns true if the specified nexthop is the other endpoint in an
      * InterVpnLink, regarding one of the VPN's point of view.
      */
-    private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
+    private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
+            InterVpnLink interVpnLink) {
         return
                 interVpnLink != null
                         && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
         return
                 interVpnLink != null
                         && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
@@ -1963,7 +2051,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
     }
 
                         && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
     }
 
-    @Nonnull
+    @NonNull
     protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
         List<Adjacency> adjList = new ArrayList<>();
         Map<String, List<String>> adjMap = new HashMap<>();
     protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
         List<Adjacency> adjList = new ArrayList<>();
         Map<String, List<String>> adjMap = new HashMap<>();
@@ -1971,8 +2059,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
                 LOG.error("Incorrect input received for extra route. {}", route);
             } else {
             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
                 LOG.error("Incorrect input received for extra route. {}", route);
             } else {
-                String nextHop = String.valueOf(route.getNexthop().getValue());
-                String destination = String.valueOf(route.getDestination().getValue());
+                String nextHop = route.getNexthop().stringValue();
+                String destination = route.getDestination().stringValue();
                 if (!nextHop.equals(fixedIp)) {
                     LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
                     continue;
                 if (!nextHop.equals(fixedIp)) {
                     LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
                     continue;
@@ -2004,8 +2092,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
                 LOG.error("Incorrect input received for extra route. {}", route);
             } else {
             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
                 LOG.error("Incorrect input received for extra route. {}", route);
             } else {
-                String nextHop = String.valueOf(route.getNexthop().getValue());
-                String destination = String.valueOf(route.getDestination().getValue());
+                String nextHop = route.getNexthop().stringValue();
+                String destination = route.getDestination().stringValue();
                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
                         nextHop);
                 if (infName != null) {
                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
                         nextHop);
                 if (infName != null) {
@@ -2029,18 +2117,21 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
                             .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
                             .setAdjacencyType(AdjacencyType.ExtraRoute).build();
                         Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
                             .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
                             .setAdjacencyType(AdjacencyType.ExtraRoute).build();
-                        isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
-                        SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+
+                        try (AcquireResult lock = tryInterfaceLock(infName)) {
+                            if (!lock.wasAcquired()) {
+                                // FIXME: why do we even bother with locking if we do not honor it?!
+                                logTryLockFailure(infName);
+                            }
+
+                            SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
                                 path, erAdj);
                                 path, erAdj);
+                        }
                     } catch (TransactionCommitFailedException e) {
                         LOG.error("exception in adding extra route with destination: {}, next hop: {}",
                             destination, nextHop, e);
                     } 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);
                         LOG.error("Exception on reading data-store ", e);
-                    } finally {
-                        if (isLockAcquired) {
-                            interfaceLock.unlock(infName);
-                        }
                     }
                 } else {
                     LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
                     }
                 } else {
                     LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
@@ -2078,39 +2169,32 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         for (Routes route : routeList) {
             // count  the number of nexthops for each same route.getDestingation().getValue()
         }
         for (Routes route : routeList) {
             // count  the number of nexthops for each same route.getDestingation().getValue()
-            String destination = String.valueOf(route.getDestination().getValue());
-            String nextHop = String.valueOf(route.getNexthop().getValue());
-            List<String> nextHopList = new ArrayList();
+            String destination = route.getDestination().stringValue();
+            String nextHop = route.getNexthop().stringValue();
+            List<String> nextHopList = new ArrayList<>();
             nextHopList.add(nextHop);
             nextHopList.add(nextHop);
-            int nbNextHops = 0;
+            int nbNextHops = 1;
             for (Routes routeTmp : routeList) {
             for (Routes routeTmp : routeList) {
-                String routeDest = String.valueOf(routeTmp.getDestination().getValue());
+                String routeDest = routeTmp.getDestination().stringValue();
                 if (!destination.equals(routeDest)) {
                     continue;
                 }
                 if (!destination.equals(routeDest)) {
                     continue;
                 }
-                String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
+                String routeNextH = routeTmp.getNexthop().stringValue();
                 if (nextHop.equals(routeNextH)) {
                     continue;
                 }
                 nbNextHops++;
                 if (nextHop.equals(routeNextH)) {
                     continue;
                 }
                 nbNextHops++;
-                nextHopList.add(new String(routeTmp.getNexthop().getValue()));
+                nextHopList.add(routeTmp.getNexthop().stringValue());
             }
             final List<String> rdList = new ArrayList<>();
             }
             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 (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";
 
             // 1. VPN Instance Name
             String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
 
@@ -2129,7 +2213,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
             // 4. Prefix in question
             detailsAlarm.append(" for prefix: ");
 
             // 4. Prefix in question
             detailsAlarm.append(" for prefix: ");
-            detailsAlarm.append(route.getDestination().getValue());
+            detailsAlarm.append(route.getDestination().stringValue());
 
             // 5. List of NHs for the prefix
             detailsAlarm.append(" for nextHops: ");
 
             // 5. List of NHs for the prefix
             detailsAlarm.append(" for nextHops: ");
@@ -2151,9 +2235,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
         for (Routes route : routeList) {
             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
     protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
         for (Routes route : routeList) {
             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
-                boolean isLockAcquired = false;
-                String nextHop = String.valueOf(route.getNexthop().getValue());
-                String destination = String.valueOf(route.getDestination().getValue());
+                String nextHop = route.getNexthop().stringValue();
+                String destination = route.getDestination().stringValue();
                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
                         nextHop);
                 if (infName == null) {
                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
                         nextHop);
                 if (infName == null) {
@@ -2191,34 +2274,37 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         }
                     }
 
                         }
                     }
 
-                    isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
-                    if (updateNextHops) {
-                        // An update must be done, not including the current next hop
-                        InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
+                    try (AcquireResult lock = tryInterfaceLock(infName)) {
+                        if (!lock.wasAcquired()) {
+                            // FIXME: why do we even bother with locking if we do not honor it?!
+                            logTryLockFailure(infName);
+                        }
+
+                        if (updateNextHops) {
+                            // An update must be done, not including the current next hop
+                            InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
                                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
                                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
-                        Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
-                                .setNextHopIpList(nextHopList)
-                                .withKey(new AdjacencyKey(destination))
-                                .build();
-                        Adjacencies erAdjs =
-                                new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
-                        VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
-                                .addAugmentation(Adjacencies.class, erAdjs).build();
-                        SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
+                                    .setNextHopIpList(nextHopList)
+                                    .withKey(new AdjacencyKey(destination))
+                                    .build();
+                            List<Adjacency> newAdjList = Collections.singletonList(newAdj);
+                            Adjacencies erAdjs =
+                                    new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(newAdjList)).build();
+                            VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
+                                    .addAugmentation(Adjacencies.class, erAdjs).build();
+                            SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
                                 vpnIfIdentifier, vpnIf);
                                 vpnIfIdentifier, vpnIf);
-                    } else {
-                        // Remove the whole route
-                        SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        } else {
+                            // Remove the whole route
+                            SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
                                 adjacencyIdentifier);
                                 adjacencyIdentifier);
-                        LOG.trace("extra route {} deleted successfully", route);
+                            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);
                     LOG.error("exception in deleting extra route with destination {} for interface {}",
                             destination, infName, e);
-                } finally {
-                    if (isLockAcquired) {
-                        interfaceLock.unlock(infName);
-                    }
                 }
             } else {
                 LOG.error("Incorrect input received for extra route: {}", route);
                 }
             } else {
                 LOG.error("Incorrect input received for extra route: {}", route);
@@ -2229,18 +2315,22 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     public void removeVpn(Uuid vpnId) {
         // read VPNMaps
         VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
     public void removeVpn(Uuid vpnId) {
         // read VPNMaps
         VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
-        List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
-        // dissociate router
-        if (routerIdsList != null && !routerIdsList.isEmpty()) {
-            for (RouterIds routerId : routerIdsList) {
-                dissociateRouterFromVpn(vpnId, routerId.getRouterId());
-            }
-            List<Uuid> rtrIdsList = routerIdsList.stream().map(routerId -> routerId.getRouterId())
-                    .collect(Collectors.toList());
-            if (rtrIdsList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
-                // dissociate networks
+        if (vpnMap != null) {
+            Map<RouterIdsKey, RouterIds> keyRouterIdsMap = vpnMap.getRouterIds();
+            List<Uuid> routerUuidList = new ArrayList<>();
+            // dissociate router
+            if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) {
+                for (RouterIds router : keyRouterIdsMap.values()) {
+                    Uuid routerId = router.getRouterId();
+                    routerUuidList.add(routerId);
+                    dissociateRouterFromVpn(vpnId, routerId);
+                }
+            }
+            if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
                 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
             }
                 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
             }
+        } else {
+            LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
         }
         // remove entire vpnMaps node
         deleteVpnMapsNode(vpnId);
         }
         // remove entire vpnMaps node
         deleteVpnMapsNode(vpnId);
@@ -2251,30 +2341,29 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
     }
 
     private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
-        return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
+        return vpnInstance != null && vpnInstance.isL2vpn();
     }
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
         updateVpnMaps(vpnId, null, routerId, null, null);
     }
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
         updateVpnMaps(vpnId, null, routerId, null, null);
-        LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
-        List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
-        for (Uuid subnetId : routerSubnets) {
-            Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
-            if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
-                neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                          NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
+        LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
+        List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        for (Subnetmap sn : subMapList) {
+            IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
+            if (!ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
             }
         }
             }
         }
-
-        try {
-            checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
-            LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
-                    vpnId.getValue());
-        } catch (Exception e) {
-            LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
-                    .getValue(), vpnId.getValue(), e);
+        if (ipVersion != IpVersionChoice.UNDEFINED) {
+            LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ",
+                    ipVersion, vpnId);
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
+        }
+        for (Subnetmap sn : subMapList) {
+            updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
         }
     }
 
         }
     }
 
@@ -2297,31 +2386,23 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
 
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
 
-        List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
-        boolean vpnInstanceIpVersionsRemoved = false;
-        IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
-        for (Uuid subnetId : routerSubnets) {
-            Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
-            if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
-                vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
-                        .getIpVersionFromString(sn.getSubnetIp()));
-                vpnInstanceIpVersionsRemoved = true;
+        clearFromVpnMaps(vpnId, routerId, null);
+        List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        for (Subnetmap sn : subMapList) {
+            IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
+            if (ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
             }
             }
-            LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
-            updateVpnForSubnet(vpnId, routerId, subnetId, false);
+            LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
+                    routerId.getValue());
+            updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
         }
         }
-
-        if (vpnInstanceIpVersionsRemoved) {
-            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
-        }
-        clearFromVpnMaps(vpnId, routerId, null);
-        try {
-            checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
-            LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
-                    vpnId.getValue());
-        } catch (Exception e) {
-            LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
-                    .getValue(), vpnId.getValue(), e);
+        if (ipVersion != IpVersionChoice.UNDEFINED) {
+            LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ",
+                    ipVersion, vpnId);
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
+                    false);
         }
     }
 
         }
     }
 
@@ -2332,10 +2413,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * @param networkList List list of network Ids (Uuid), which will be associated.
      * @return list of formatted strings with detailed error messages.
      */
      * @param networkList List list of network Ids (Uuid), which will be associated.
      * @return list of formatted strings with detailed error messages.
      */
-    @Nonnull
-    protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
+    @NonNull
+    protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
         List<String> failedNwList = new ArrayList<>();
         HashSet<Uuid> passedNwList = new HashSet<>();
         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());
             failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
         if (networkList.isEmpty()) {
             LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
             failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
@@ -2358,6 +2441,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 return failedNwList;
             }
             Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
                 return failedNwList;
             }
             Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+            boolean isIpFamilyUpdated = false;
             for (Uuid nw : networkList) {
                 Network network = neutronvpnUtils.getNeutronNetwork(nw);
                 if (network == null) {
             for (Uuid nw : networkList) {
                 Network network = neutronvpnUtils.getNeutronNetwork(nw);
                 if (network == null) {
@@ -2382,12 +2466,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                                    + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
                     continue;
                 }
                                                    + "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;
+                /* 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);
+                }
+                if (NeutronvpnUtils.getIsExternal(network)) {
+                    isExternalNetwork = true;
                 }
                 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
                 if (subnetmapList == null || subnetmapList.isEmpty()) {
                 }
                 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
                 if (subnetmapList == null || subnetmapList.isEmpty()) {
@@ -2397,6 +2483,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
                     continue;
                 }
                 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);
+                    }
+                }
+                //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();
                     Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
                 for (Subnetmap subnetmap : subnetmapList) {
                     Uuid subnetId = subnetmap.getId();
                     Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
@@ -2407,11 +2507,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
                         continue;
                     }
                                 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
                         continue;
                     }
-                    if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(subnetmap, vpnId)) {
-                        neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                                NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()), true);
-                    }
-                    if (!neutronvpnUtils.getIsExternal(network)) {
+                    if (!NeutronvpnUtils.getIsExternal(network)) {
                         LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
                                 vpnId.getValue());
                         addSubnetToVpn(vpnId, subnetId, null);
                         LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
                                 vpnId.getValue());
                         addSubnetToVpn(vpnId, subnetId, null);
@@ -2421,43 +2517,70 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     }
                 }
                 passedNwList.add(nw);
                     }
                 }
                 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(),
                     networkList, 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(),
                     networkList, e));
         }
-        updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
-        LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
+        //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
+        if (!isExternalNetwork) {
+            updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
+        }
+        LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
         return failedNwList;
     }
 
         return failedNwList;
     }
 
-    private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
-        VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
-        if (vpnOpDataEntry == null) {
-            LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
-            return false;
-        }
+    private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet,
+                                             VpnInstance.BgpvpnType bgpVpnType) {
         if (!addExternalNetworkToVpn(extNet, vpnId)) {
             return false;
         }
         if (!addExternalNetworkToVpn(extNet, vpnId)) {
             return false;
         }
-        if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
-            LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
-            neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
-        }
-        for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
+        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());
+        updateVpnMaps(vpnId, null, null, null, extNwList);
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
             if (sm == null) {
                 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
                 continue;
             }
             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
             if (sm == null) {
                 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
                 continue;
             }
-            updateVpnInternetForSubnet(sm, vpnId, true);
-            if (!vpnOpDataEntry.isIpv6Configured()
-                    && NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6) {
-                LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
-                neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
+            IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
+            if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
+                continue;
+            }
+            if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
+                updateVpnInternetForSubnet(sm, vpnId, true);
             }
             }
+            if (!ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
+            }
+        }
+        if (ipVersion != IpVersionChoice.UNDEFINED) {
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
+            LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
+            neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
         }
         return true;
     }
         }
         return true;
     }
@@ -2469,10 +2592,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * @param networkList List list of network Ids (Uuid), which will be disassociated.
      * @return list of formatted strings with detailed error messages.
      */
      * @param networkList List list of network Ids (Uuid), which will be disassociated.
      * @return list of formatted strings with detailed error messages.
      */
-    @Nonnull
-    protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
+    @NonNull
+    protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
         List<String> failedNwList = new ArrayList<>();
         HashSet<Uuid> passedNwList = new HashSet<>();
         List<String> failedNwList = new ArrayList<>();
         HashSet<Uuid> passedNwList = new HashSet<>();
+        ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
         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",
         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",
@@ -2487,7 +2611,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             }
             Network network = neutronvpnUtils.getNeutronNetwork(nw);
             if (network == null) {
             }
             Network network = neutronvpnUtils.getNeutronNetwork(nw);
             if (network == null) {
-                LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
+                LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
                 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
                         nw.getValue()));
                 continue;
                 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
                         nw.getValue()));
                 continue;
@@ -2507,48 +2631,72 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 vpnId.getValue()));
                 continue;
             }
                                 vpnId.getValue()));
                 continue;
             }
-            if (NeutronvpnUtils.getIsExternal(network)) {
-                if (disassociateExtNetworkFromVpn(vpnId, network)) {
-                    passedNwList.add(nw);
-                    continue;
-                } 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);
             }
             }
-            Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+            IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
             for (Uuid subnet : networkSubnets) {
                 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
             for (Uuid subnet : networkSubnets) {
                 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
-                if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(subnetmap, vpnId)) {
-                    IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
-                    IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
-                    neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                        ipVersionsToRemove.addVersion(ipVersion), false);
+                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);
+                }
+                if (!NeutronvpnUtils.getIsExternal(network)) {
+                    LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
+                            vpnId.getValue());
+                    removeSubnetFromVpn(vpnId, subnetmap, null);
+                    Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+                    vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
+                            vpnId.getValue());
+                    passedNwList.add(nw);
+                }
+            }
+            if (ipVersion != IpVersionChoice.UNDEFINED) {
+                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;
                 }
                 }
-                LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
-                          vpnId.getValue());
-                removeSubnetFromVpn(vpnId, subnet, null);
-                vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
-                        vpnId.getValue());
-                passedNwList.add(nw);
             }
         }
         clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
             }
         }
         clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
-        LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
-                vpnId.getValue());
+        LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
+                passedNwList, vpnId.getValue());
         return failedNwList;
     }
 
         return failedNwList;
     }
 
-    private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
+    private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
         if (!removeExternalNetworkFromVpn(extNet)) {
             return false;
         }
         // check, if there is another Provider Networks associated with given VPN
         List<Uuid> vpnNets = getNetworksForVpn(vpnId);
         if (vpnNets != null) {
         if (!removeExternalNetworkFromVpn(extNet)) {
             return false;
         }
         // check, if there is another Provider Networks associated with given VPN
         List<Uuid> vpnNets = getNetworksForVpn(vpnId);
         if (vpnNets != null) {
+            //Remove currently disassociated network from the list
+            vpnNets.remove(extNet.getUuid());
             for (Uuid netId : vpnNets) {
                 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
                     LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
             for (Uuid netId : vpnNets) {
                 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
                     LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
@@ -2557,20 +2705,35 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
         }
                 }
             }
         }
-        LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
-                VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
-        neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
-        for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
+        ///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);
             if (sm == null) {
                 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
                 continue;
             }
             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
             if (sm == null) {
                 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
                 continue;
             }
-            updateVpnInternetForSubnet(sm, vpnId, false);
+            IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
+            if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
+                continue;
+            }
+            if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
+                updateVpnInternetForSubnet(sm, vpnId, false);
+            }
+            if (!ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
+            }
+        }
+        if (ipVersion != IpVersionChoice.UNDEFINED) {
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
+            LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
+                    vpnId.getValue());
+            neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
         }
         }
-        neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
-        LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
-        neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
         return true;
     }
 
         return true;
     }
 
@@ -2590,7 +2753,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         try {
             if (neutronvpnUtils.getVpnMap(vpnId) != null) {
                 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
         try {
             if (neutronvpnUtils.getVpnMap(vpnId) != null) {
                 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
-                        input.getNetworkId().toString());
+                        input.getNetworkId());
                 List<Uuid> netIds = input.getNetworkId();
                 if (netIds != null && !netIds.isEmpty()) {
                     List<String> failed = associateNetworksToVpn(vpnId, netIds);
                 List<Uuid> netIds = input.getNetworkId();
                 if (netIds != null && !netIds.isEmpty()) {
                     List<String> failed = associateNetworksToVpn(vpnId, netIds);
@@ -2610,6 +2773,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
             }
         } catch (Exception ex) {
                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
             }
         } catch (Exception ex) {
+            LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
             result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
                     formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
                             input.getVpnId().getValue(), ex.getMessage(), ex)).build());
             result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
                     formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
                             input.getVpnId().getValue(), ex.getMessage(), ex)).build());
@@ -2628,13 +2792,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("associateRouter {}", input);
         StringBuilder returnMsg = new StringBuilder();
         Uuid vpnId = input.getVpnId();
         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
         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) {
             VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
             Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
             if (vpnMap != null) {
@@ -2685,9 +2850,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             List<String> fixedIPList = new ArrayList<>();
             Port port = neutronvpnUtils.getNeutronPort(portId);
             if (port != null) {
             List<String> fixedIPList = new ArrayList<>();
             Port port = neutronvpnUtils.getNeutronPort(portId);
             if (port != null) {
-                List<FixedIps> fixedIPs = port.getFixedIps();
-                for (FixedIps ip : fixedIPs) {
-                    fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
+                for (FixedIps ip : port.nonnullFixedIps().values()) {
+                    fixedIPList.add(ip.getIpAddress().stringValue());
                 }
             } else {
                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
                 }
             } else {
                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
@@ -2729,7 +2893,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         try {
             if (neutronvpnUtils.getVpnMap(vpnId) != null) {
                 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
         try {
             if (neutronvpnUtils.getVpnMap(vpnId) != null) {
                 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
-                        input.getNetworkId().toString());
+                        input.getNetworkId());
                 List<Uuid> netIds = input.getNetworkId();
                 if (netIds != null && !netIds.isEmpty()) {
                     List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
                 List<Uuid> netIds = input.getNetworkId();
                 if (netIds != null && !netIds.isEmpty()) {
                     List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
@@ -2771,15 +2935,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("dissociateRouter {}", input);
         StringBuilder returnMsg = new StringBuilder();
         Uuid vpnId = input.getVpnId();
         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 = "";
         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(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
         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() + ", ";
                 try {
                     if (routerId != null) {
                         routerIdsString += routerId.getRouterId() + ", ";
@@ -2829,13 +2994,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (vpnId != null) {
             // remove existing external vpn interfaces
             for (Uuid subnetId : routerSubnetIds) {
         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) {
             }
             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
             }
         }
         // delete entire vpnMaps node for internal VPN
@@ -2849,6 +3026,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return neutronvpnUtils.getNeutronSubnet(subnetId);
     }
 
         return neutronvpnUtils.getNeutronSubnet(subnetId);
     }
 
+    @Nullable
     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
         Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
         if (null != sn) {
     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
         Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
         if (null != sn) {
@@ -2882,9 +3060,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
      * 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"));
         List<String> result = new ArrayList<>();
         result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length",
             "IP Address"));
@@ -2893,11 +3071,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
         Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
         if (ports.isPresent() && ports.get().getPort() != null) {
 
         Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
         if (ports.isPresent() && ports.get().getPort() != null) {
-            for (Port port : ports.get().getPort()) {
-                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<>();
                     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());
                         IpAddress ipAddress = fixedIp.getIpAddress();
                         if (ipAddress.getIpv4Address() != null) {
                             ipList.add(ipAddress.getIpv4Address().getValue());
@@ -2947,9 +3125,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             result.add("");
             result.add("------------------------------------------------------------------------------------");
             result.add("");
             result.add("");
             result.add("------------------------------------------------------------------------------------");
             result.add("");
-            List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
-            for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
-                    .rev150602.VpnInstance vpn : vpnList) {
+            for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
+                    rpcResult.getResult().nonnullL3vpnInstances()) {
                 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
                         : "\"                 " + "                  \"";
                 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
                 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
                         : "\"                 " + "                  \"";
                 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
@@ -3001,7 +3178,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return;
         }
 
             return;
         }
 
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
+        LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
             for (String elanInterface : extElanInterfaces) {
                 createExternalVpnInterface(extNetId, elanInterface, tx);
             }
             for (String elanInterface : extElanInterfaces) {
                 createExternalVpnInterface(extNetId, elanInterface, tx);
             }
@@ -3016,7 +3193,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("No external ports attached for external network {}", extNetId.getValue());
             return;
         }
             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);
             for (String elanInterface : extElanInterfaces) {
                 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
                         .buildVpnInterfaceIdentifier(elanInterface);
@@ -3027,22 +3204,23 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     private void createExternalVpnInterface(Uuid vpnId, String infName,
     }
 
     private void createExternalVpnInterface(Uuid vpnId, String infName,
-                                            TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
-        writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null,
+                                            TypedWriteTransaction<Configuration> wrtConfigTxn) {
+        writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
                 false /* not a router iface */, wrtConfigTxn);
     }
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
                 false /* not a router iface */, wrtConfigTxn);
     }
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
-            Boolean isRouterInterface, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
+    private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
+            @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
+            TypedWriteTransaction<Configuration> wrtConfigTxn) {
         if (vpnIdList.isEmpty() || infName == null) {
         if (vpnIdList.isEmpty() || infName == null) {
-            LOG.error("vpn id or interface is null");
+            LOG.error("vpnid is empty or interface({}) is null", infName);
             return;
         }
         if (wrtConfigTxn == null) {
             return;
         }
         if (wrtConfigTxn == null) {
-            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-                tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, isRouterInterface, tx)), LOG,
+            LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
                 "Error writing VPN interface");
             return;
         }
                 "Error writing VPN interface");
             return;
         }
@@ -3058,6 +3236,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 .setName(infName)
                 .setVpnInstanceNames(vpnIdListStruct)
                 .setRouterInterface(isRouterInterface);
                 .setName(infName)
                 .setVpnInstanceNames(vpnIdListStruct)
                 .setRouterInterface(isRouterInterface);
+        LOG.info("Network Id is {}", networkUuid);
+        if (networkUuid != null) {
+            Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
+            ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
+            NetworkAttributes.NetworkType networkType = providerType != null
+                    ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
+            String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
+            vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
+                .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
+        }
+
         if (adjacencies != null) {
             vpnb.addAugmentation(Adjacencies.class, adjacencies);
         }
         if (adjacencies != null) {
             vpnb.addAugmentation(Adjacencies.class, adjacencies);
         }
@@ -3071,62 +3260,62 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
     }
 
     private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
-                                                   TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
+                                                   TypedWriteTransaction<Configuration> wrtConfigTxn) {
         if (vpnId == null || infName == null) {
             LOG.error("vpn id or interface is null");
             return;
         }
         if (wrtConfigTxn == null) {
             LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
         if (vpnId == null || infName == null) {
             LOG.error("vpn id or interface is null");
             return;
         }
         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;
         }
 
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
                 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
             }), LOG, "Error updating VPN interface with adjacencies");
             return;
         }
 
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
-        boolean isLockAcquired = false;
-        try {
-            isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
-            Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
-                    .syncReadOptional(dataBroker, LogicalDatastoreType
-                    .CONFIGURATION, vpnIfIdentifier);
-            if (optionalVpnInterface.isPresent()) {
-                VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
-                LOG.debug("Updating vpn interface {} with new adjacencies", infName);
 
 
-                if (adjacencies == null) {
-                    if (isLockAcquired) {
-                        interfaceLock.unlock(infName);
+        try (AcquireResult lock = tryInterfaceLock(infName)) {
+            if (!lock.wasAcquired()) {
+                // FIXME: why do we even bother with locking if we do not honor it?!
+                logTryLockFailure(infName);
+            }
+
+            try {
+                Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
+                        .syncReadOptional(dataBroker, LogicalDatastoreType
+                            .CONFIGURATION, vpnIfIdentifier);
+                if (optionalVpnInterface.isPresent()) {
+                    VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
+                    LOG.debug("Updating vpn interface {} with new adjacencies", infName);
+
+                    if (adjacencies == null) {
+                        return;
                     }
                     }
-                    return;
-                }
-                vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
-                if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
-                    List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
-                        optionalVpnInterface.get().getVpnInstanceNames());
-                    if (listVpnInstances.isEmpty() || !VpnHelper
-                        .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
+                    vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
+                    if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
+                        List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
+                                optionalVpnInterface.get().getVpnInstanceNames().values());
+                        if (listVpnInstances.isEmpty()
+                                || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
+                            VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
+                                AssociatedSubnetType.V4AndV6Subnets);
+                            listVpnInstances.add(vpnInstance);
+                            vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
+                        }
+                    } else {
                         VpnInstanceNames vpnInstance = VpnHelper
                         VpnInstanceNames vpnInstance = VpnHelper
-                             .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
+                                .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
+                        List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
                         listVpnInstances.add(vpnInstance);
                         vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
                     }
                         listVpnInstances.add(vpnInstance);
                         vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
                     }
-                } else {
-                    VpnInstanceNames vpnInstance = VpnHelper
-                         .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
-                    List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
-                    listVpnInstances.add(vpnInstance);
-                    vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
+                    LOG.info("Updating vpn interface {} with new adjacencies", infName);
+                    wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
                 }
                 }
-                LOG.info("Updating vpn interface {} with new adjacencies", infName);
-                wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
-            }
-        } catch (IllegalStateException | ReadFailedException ex) {
-            LOG.error("Update of vpninterface {} failed", infName, ex);
-        } finally {
-            if (isLockAcquired) {
-                interfaceLock.unlock(infName);
+            } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
+                // FIXME: why are we catching IllegalStateException here?
+                LOG.error("Update of vpninterface {} failed", infName, ex);
             }
         }
     }
             }
         }
     }
@@ -3137,22 +3326,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return help.toString();
     }
 
         return help.toString();
     }
 
-    private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
-            InterruptedException {
-        RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
-                .setVpnId(vpnId).build();
-        LOG.info("publishing notification upon association of router to VPN");
-        notificationPublishService.putNotification(routerAssociatedToVpn);
-    }
-
-    private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
-            InterruptedException {
-        RouterDisassociatedFromVpn routerDisassociatedFromVpn =
-            new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
-        LOG.info("publishing notification upon disassociation of router from VPN");
-        notificationPublishService.putNotification(routerDisassociatedFromVpn);
-    }
-
     protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
         floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
     }
     protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
         floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
     }
@@ -3195,7 +3368,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
                                                   networks);
             return true;
             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);
         }
             LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
                       extNetId.getValue(), ex);
         }
@@ -3224,7 +3397,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     extNetId.getValue());
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
             return true;
                     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);
         }
             LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
                     extNetId.getValue(), ex);
         }
@@ -3235,10 +3408,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         Optional<String> existingVpnName = Optional.of(primaryRd);
         Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
         try {
         Optional<String> existingVpnName = Optional.of(primaryRd);
         Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
         try {
-            vpnInstanceOpDataOptional = SingleTransactionDataBroker
-                .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
+            vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
                     neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
                     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.
             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.
@@ -3248,26 +3420,72 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (vpnInstanceOpDataOptional.isPresent()) {
             existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
         } else {
         if (vpnInstanceOpDataOptional.isPresent()) {
             existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
         } else {
-            existingVpnName = Optional.absent();
+            existingVpnName = Optional.empty();
         }
         return existingVpnName;
     }
 
         }
         return existingVpnName;
     }
 
-    private String formatAndLog(Consumer<String> logger, String template, Object arg) {
+    private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
         return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
     }
 
         return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
     }
 
-    private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
+    private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
         return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
     }
 
         return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
     }
 
-    private String formatAndLog(Consumer<String> logger, String template, Object... args) {
+    private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
         return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
     }
 
         return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
     }
 
-    private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
+    private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
         String message = tuple.getMessage();
         logger.accept(message);
         return message;
     }
         String message = tuple.getMessage();
         logger.accept(message);
         return message;
     }
+
+    protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
+                                                  @NonNull Subnetmap subnetMap) {
+        updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
+        neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
+        if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
+            LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
+                    subnetMap.getId().getValue(), internetVpnId.getValue());
+        }
+    }
+
+    protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
+                                                     @NonNull Subnetmap subnetMap) {
+        updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
+        neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
+    }
+
+    protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
+        if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
+            LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
+                            + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
+                    internetVpnId.getValue(), routerId.getValue());
+            neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
+                    ? true : false);
+        }
+    }
+
+    @CheckReturnValue
+    private AcquireResult tryInterfaceLock(final String infName) {
+        return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+    }
+
+    @CheckReturnValue
+    private AcquireResult tryVpnLock(final Uuid vpnId) {
+        return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+    }
+
+    private static ReentrantLock lockForUuid(Uuid uuid) {
+        // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
+        return JvmGlobalLocks.getLockForString(uuid.getValue());
+    }
+
+    private static void logTryLockFailure(Object objectId) {
+        LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());
+    }
 }
 }