Do not unbox Boolean
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnInterfaceManager.java
index 9c1f6c0e4fa71ae07de5bbb97695115a86afc579..1350a29be4fa542a7501c6beb34ad5afdde495c2 100755 (executable)
@@ -7,6 +7,12 @@
  */
 package org.opendaylight.netvirt.vpnmanager;
 
+import static java.util.Collections.emptyList;
+import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
+import static org.opendaylight.netvirt.vpnmanager.VpnUtil.requireNonNullElse;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterators;
@@ -18,28 +24,33 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import javax.annotation.Nullable;
 import javax.annotation.PostConstruct;
 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.WriteTransaction;
 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.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.Datastore.Operational;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.TransactionAdapter;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.NWUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
@@ -81,6 +92,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
@@ -102,6 +114,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
@@ -199,9 +212,9 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     @Override
     public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
-        LOG.info("add: intfName {} onto vpnName {}",
-                 vpnInterface.getName(),
-                 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
+        LOG.trace("Received VpnInterface add event: vpnInterface={}", vpnInterface);
+        LOG.info("add: intfName {} onto vpnName {}", vpnInterface.getName(),
+                VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
         addVpnInterface(identifier, vpnInterface, null, null);
     }
 
@@ -219,8 +232,9 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
-                             final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
-        for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
+                             final @Nullable List<Adjacency> oldAdjs, final @Nullable List<Adjacency> newAdjs) {
+        for (VpnInstanceNames vpnInterfaceVpnInstance : requireNonNullElse(vpnInterface.getVpnInstanceNames(),
+                Collections.<VpnInstanceNames>emptyList())) {
             String vpnName = vpnInterfaceVpnInstance.getVpnName();
             addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
         }
@@ -228,7 +242,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
                          final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
-        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class);
         final String interfaceName = key.getName();
 
         if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
@@ -252,10 +266,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
-                    final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
-                    final List<Adjacency> newAdjs,
+                    final VpnInterface vpnInterface, final @Nullable List<Adjacency> oldAdjs,
+                    final @Nullable List<Adjacency> newAdjs,
                     final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
-        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class);
         final String interfaceName = key.getName();
         String primaryRd = vpnUtil.getPrimaryRd(vpnName);
         if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
@@ -269,75 +283,77 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
                         // (the inventory tx goes in last)
                         List<ListenableFuture<Void>> futures = new ArrayList<>();
-                        ListenableFuture<Void> confFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
-                            confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
-                                operTx -> futures.add(
-                                        txRunner.callWithNewWriteOnlyTransactionAndSubmit(invTx -> {
+                        ListenableFuture<Void> confFuture =
+                            txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                                confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
+                                    operTx -> futures.add(
+                                        txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, invTx -> {
                                             LOG.info(
-                                                    "addVpnInterface: VPN Interface add event - intfName {} vpnName {}"
+                                                "addVpnInterface: VPN Interface add event - intfName {} vpnName {}"
                                                     + " on dpn {}",
-                                                    vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
+                                                vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
                                             processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false,
-                                                    confTx, operTx, invTx, interfaceState, vpnName);
+                                                confTx, operTx, invTx, interfaceState, vpnName);
                                             if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
                                                 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
-                                                        + " Update for swapping VPN {} case.", interfaceName, vpnName);
+                                                    + " Update for swapping VPN {} case.", interfaceName, vpnName);
                                                 if (newAdjs != null) {
                                                     for (Adjacency adj : newAdjs) {
                                                         if (oldAdjs.contains(adj)) {
                                                             oldAdjs.remove(adj);
                                                         } else {
                                                             if (!isBgpVpnInternetVpn
-                                                                    || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+                                                                || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
                                                                 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier,
-                                                                        primaryRd, adj, dpnId, operTx, confTx);
+                                                                    primaryRd, adj, dpnId, operTx, confTx, invTx);
                                                             }
                                                         }
                                                     }
                                                 }
                                                 for (Adjacency adj : oldAdjs) {
                                                     if (!isBgpVpnInternetVpn
-                                                            || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+                                                        || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
                                                         delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
-                                                                operTx, confTx);
+                                                            operTx, confTx);
                                                     }
                                                 }
                                             }
                                         })))));
                         futures.add(confFuture);
                         Futures.addCallback(confFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"),
-                                MoreExecutors.directExecutor());
+                            MoreExecutors.directExecutor());
                         LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
-                                + " processed successfully", interfaceName, vpnName, dpnId);
+                            + " processed successfully", interfaceName, vpnName, dpnId);
                         return futures;
                     });
                 } catch (NumberFormatException | IllegalStateException e) {
                     LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
-                                    + "interface {}. Interface addition on vpn {} failed", interfaceName,
-                                    vpnName, e);
+                            + "interface {}. Interface addition on vpn {} failed", interfaceName,
+                        vpnName, e);
                     return;
                 }
             } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
                 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
                     () -> {
-                        ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
-                            createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
+                        ListenableFuture<Void> future =
+                            txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
+                                createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
                                     confTx, vpnName);
-                            LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
+                                LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
                                     vpnName, vpnInterface.getDpnId());
-                        });
+                            });
                         ListenableFutures.addErrorLogging(future, LOG,
-                                "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
+                            "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
                         return Collections.singletonList(future);
                     });
             } else {
                 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
-                        + " is not available", interfaceName, vpnName);
+                    + " is not available", interfaceName, vpnName);
             }
         } else {
             LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
-                      + " as vpn is pending delete", interfaceName, vpnName,
-                    vpnInterface.getDpnId());
+                    + " as vpn is pending delete", interfaceName, vpnName,
+                vpnInterface.getDpnId());
         }
     }
 
@@ -346,11 +362,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
     protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
             final int lportTag, boolean isInterfaceUp,
-            WriteTransaction writeConfigTxn,
-            WriteTransaction writeOperTxn,
-            WriteTransaction writeInvTxn,
+            TypedWriteTransaction<Configuration> writeConfigTxn,
+            TypedWriteTransaction<Operational> writeOperTxn,
+            TypedReadWriteTransaction<Configuration> writeInvTxn,
             Interface interfaceState,
-            final String vpnName) {
+            final String vpnName) throws ExecutionException, InterruptedException {
         final String interfaceName = vpnInterface.getName();
         Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(interfaceName,
                 vpnName);
@@ -368,10 +384,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             }
 
             boolean waitForVpnInterfaceOpRemoval = false;
-            if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
+            if (opVpnInterface != null) {
                 String opVpnName = opVpnInterface.getVpnInstanceName();
                 String primaryInterfaceIp = null;
-                if (opVpnName.equals(vpnName)) {
+                if (Objects.equals(opVpnName, vpnName)) {
                     // Please check if the primary VRF Entry does not exist for VPNInterface
                     // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
                     // back to back
@@ -421,7 +437,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
                         dpId, vpnName);
                 if (interfaceManager.isExternalInterface(interfaceName)) {
-                    processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
+                    processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
                         NwConstants.ADD_FLOW);
                 }
                 return;
@@ -470,8 +486,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
                     + " FIB to clean up", interfaceName, dpId, vpnName);
             if (interfaceManager.isExternalInterface(interfaceName)) {
-                processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId,
-                               lportTag, writeInvTxn, NwConstants.ADD_FLOW);
+                processExternalVpnInterface(interfaceName, vpnName, dpId,
+                               lportTag, NwConstants.ADD_FLOW);
             }
         } else {
             try {
@@ -490,7 +506,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
                     return;
                 }
-                List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
+                List<Adjacency> adjacencies = requireNonNullElse(optAdjacencies.get().getAdjacency(), emptyList());
                 for (Adjacency adjacency : adjacencies) {
                     if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
                         continue;
@@ -500,7 +516,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         continue;
                     }
                     addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
-                            dpId, writeOperTxn, writeConfigTxn);
+                            dpId, writeOperTxn, writeConfigTxn, writeInvTxn);
                 }
             } catch (ReadFailedException e) {
                 LOG.error("processVpnInterfaceUp: Failed to read data store for interface {} vpn {} rd {} dpn {}",
@@ -509,8 +525,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
-    private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
-            int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
+    private void processExternalVpnInterface(String interfaceName, String vpnName, BigInteger dpId,
+        int lportTag, int addOrRemove) {
         Uuid extNetworkId;
         try {
             // vpn instance of ext-net interface is the network-id
@@ -540,7 +556,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     if (addOrRemove == NwConstants.ADD_FLOW) {
                         vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
                                 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
-                                dpId, interfaceName, lportTag, writeInvTxn);
+                                dpId, interfaceName, lportTag);
                     } else {
                         vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
                                 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
@@ -589,7 +605,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     LogicalDatastoreType.OPERATIONAL, path);
             if (adjacencies.isPresent()) {
                 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
-                if (!nextHops.isEmpty()) {
+                if (nextHops != null && !nextHops.isEmpty()) {
                     LOG.debug("advertiseAdjacenciesForVpnToBgp:  NextHops are {} for interface {} on dpn {} for vpn {}"
                             + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
                     VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(rd);
@@ -636,7 +652,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
-                        String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
+                        String vpnName, String interfaceName, TypedWriteTransaction<Configuration> writeConfigTxn,
+                        TypedWriteTransaction<Operational> writeOperTx) {
         //Read NextHops
         InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
         String rd = vpnUtil.getVpnRd(interfaceName);
@@ -665,7 +682,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         if (adjacencies.isPresent()) {
             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
 
-            if (!nextHops.isEmpty()) {
+            if (nextHops != null && !nextHops.isEmpty()) {
                 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
                         nextHops, interfaceName, vpnName, rd);
                 for (Adjacency nextHop : nextHops) {
@@ -681,9 +698,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         } else {
                             // Perform similar operation as interface delete event for extraroutes.
                             String allocatedRd = nextHop.getVrfId();
-                            for (String nh : nextHop.getNextHopIpList()) {
+                            for (String nh : requireNonNullElse(nextHop.getNextHopIpList(),
+                                    Collections.<String>emptyList())) {
                                 deleteExtraRouteFromCurrentAndImportingVpns(
-                                    vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
+                                    vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn,
+                                    writeOperTx);
                             }
                         }
                     } catch (Exception e) {
@@ -698,25 +717,35 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
                                                   String primaryRd, String interfaceName, final long vpnId,
-                                                  WriteTransaction writeConfigTxn,
-                                                  WriteTransaction writeOperTxn,
-                                                  final WriteTransaction writeInvTxn,
-                                                  Interface interfaceState) {
+                                                  TypedWriteTransaction<Configuration> writeConfigTxn,
+                                                  TypedWriteTransaction<Operational> writeOperTxn,
+                                                  TypedReadWriteTransaction<Configuration> writeInvTxn,
+                                                  Interface interfaceState)
+            throws ExecutionException, InterruptedException {
         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         // Read NextHops
-        InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
-        Optional<Adjacencies> adjacencies = Optional.absent();
+        Optional<VpnInterface> vpnInteface = Optional.absent();
         try {
-            adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                    path);
+            vpnInteface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+            LogicalDatastoreType.CONFIGURATION, identifier);
         } catch (ReadFailedException e) {
             LOG.error("processVpnInterfaceAdjacencies: Failed to read data store for interface {} vpn {} rd {}"
                     + "dpn {}", interfaceName, vpnName, primaryRd, dpnId);
         }
-        if (!adjacencies.isPresent()) {
-            addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
-                    null/*gwMac*/, writeOperTxn);
-            return;
+        Uuid intfnetworkUuid = null;
+        NetworkType networkType = null;
+        Long segmentationId = Long.valueOf(-1);
+        Adjacencies adjacencies = null;
+        if (vpnInteface.isPresent()) {
+            intfnetworkUuid = vpnInteface.get().getNetworkId();
+            networkType = vpnInteface.get().getNetworkType();
+            segmentationId = vpnInteface.get().getSegmentationId();
+            adjacencies = vpnInteface.get().augmentation(Adjacencies.class);
+            if (adjacencies == null) {
+                addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
+                        null/*gwMac*/, writeOperTxn);
+                return;
+            }
         }
         // Get the rd of the vpn instance
         String nextHopIp = null;
@@ -739,7 +768,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
         VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
         VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
-        List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+        List<Adjacency> nextHops = (adjacencies != null) ? adjacencies.getAdjacency() : emptyList();
         List<Adjacency> value = new ArrayList<>();
         for (Adjacency nextHop : nextHops) {
             String rd = primaryRd;
@@ -758,12 +787,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
                 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
                         + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
-                writeOperTxn.merge(
-                    LogicalDatastoreType.OPERATIONAL,
-                    VpnUtil.getPrefixToInterfaceIdentifier(
-                        vpnUtil.getVpnId(vpnName), prefix),
-                    VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
-                            prefixCue), true);
+
+                Prefixes prefixes = (intfnetworkUuid != null)
+                    ? VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, intfnetworkUuid ,networkType,
+                            segmentationId, prefixCue) :
+                    VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, prefixCue);
+                writeOperTxn.merge(VpnUtil.getPrefixToInterfaceIdentifier(
+                        vpnUtil.getVpnId(vpnName), prefix), prefixes, true);
                 final Uuid subnetId = nextHop.getSubnetId();
 
                 String gatewayIp = nextHop.getSubnetGatewayIp();
@@ -875,13 +905,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
-                                              long lportTag, String gwMac, WriteTransaction writeOperTxn) {
+                                              long lportTag, String gwMac,
+                                              TypedWriteTransaction<Operational> writeOperTxn) {
         VpnInterfaceOpDataEntry opInterface =
-              VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
+              VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, lportTag, gwMac);
         InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
             .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
-        writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
-                WriteTransaction.CREATE_MISSING_PARENTS);
+        writeOperTxn.put(interfaceId, opInterface, CREATE_MISSING_PARENTS);
         LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
                 interfaceName, dpnId, vpnName);
     }
@@ -890,13 +920,14 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
                                            StateTunnelList stateTunnelList,
-                                           WriteTransaction writeConfigTxn,
-                                           WriteTransaction writeOperTxn) {
+                                           TypedWriteTransaction<Configuration> writeConfigTxn,
+                                           TypedWriteTransaction<Operational> writeOperTxn) {
 
-        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+        String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
         BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
         AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
-        List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
+        List<Adjacency> adjList =
+            adjacencies != null && adjacencies.getAdjacency() != null ? adjacencies.getAdjacency() : emptyList();
         if (adjList.isEmpty()) {
             LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
                     vpnInterface, srcDpnId);
@@ -921,9 +952,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             List<String> nextHopList = adj.getNextHopIpList();
             // If TEP is added , update the nexthop of primary adjacency.
             // Secondary adj nexthop is already pointing to primary adj IP address.
-            if (nextHopList != null && !nextHopList.isEmpty()) {
-                /* everything right already */
-            } else {
+            if (nextHopList == null || nextHopList.isEmpty()) {
                 isNextHopAddReqd = true;
             }
 
@@ -949,7 +978,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
                 // Update the VRF entry with nextHop
                 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
-                        label, true, writeConfigTxn);
+                        label, true, TransactionAdapter.toWriteTransaction(writeConfigTxn));
 
                 //Get the list of VPN's importing this route(prefix) .
                 // Then update the VRF entry with nhList
@@ -958,7 +987,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     String vpnRd = vpn.getVrfId();
                     if (vpnRd != null) {
                         fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
-                                srcTepIp, label, true, writeConfigTxn);
+                            srcTepIp, label, true, TransactionAdapter.toWriteTransaction(writeConfigTxn));
                         LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
                                 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
                             vpnInterface.getName(), srcDpnId, vpnName,
@@ -989,8 +1018,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 .addAugmentation(AdjacenciesOp.class, aug).build();
         InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
                 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
-        writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
-                WriteTransaction.CREATE_MISSING_PARENTS);
+        writeOperTxn.put(interfaceId, opInterface, CREATE_MISSING_PARENTS);
         LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
                 vpnInterface.getName(), srcDpnId, vpnName);
 
@@ -1000,15 +1028,15 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
                                               StateTunnelList stateTunnelList,
-                                              WriteTransaction writeConfigTxn,
-                                              WriteTransaction writeOperTxn) {
+                                              TypedWriteTransaction<Configuration> writeConfigTxn,
+                                              TypedWriteTransaction<Operational> writeOperTxn) {
 
         AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
         List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
         String prefix = null;
         long label = 0;
         boolean isNextHopRemoveReqd = false;
-        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+        String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
         BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
         String vpnName = vpnInterface.getVpnInstanceName();
         long vpnId = vpnUtil.getVpnId(vpnName);
@@ -1053,7 +1081,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             vpnId, rd, vpnInterface.getName());
                     // Update the VRF entry with removed nextHop
                     fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
-                            label, false, writeConfigTxn);
+                            label, false, TransactionAdapter.toWriteTransaction(writeConfigTxn));
 
                     //Get the list of VPN's importing this route(prefix) .
                     // Then update the VRF entry with nhList
@@ -1062,7 +1090,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         String vpnRd = vpn.getVrfId();
                         if (vpnRd != null) {
                             fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
-                                    srcTepIp, label, false, writeConfigTxn);
+                                srcTepIp, label, false, TransactionAdapter.toWriteTransaction(writeConfigTxn));
                             LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
                                     + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
                                     nhList, label, vpnInterface.getName(), srcDpnId,
@@ -1093,8 +1121,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     .addAugmentation(AdjacenciesOp.class, aug).build();
             InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
                     VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
-            writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
-                    WriteTransaction.CREATE_MISSING_PARENTS);
+            writeOperTxn.put(interfaceId, opInterface, CREATE_MISSING_PARENTS);
             LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
                          vpnInterface.getName(), srcDpnId, vpnName);
         }
@@ -1140,46 +1167,49 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
             List<VrfEntry> vrfEntries = vpnUtil.getAllVrfEntries(vpn.getVrfId());
             if (vrfEntries != null) {
-                ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
-                    for (VrfEntry vrfEntry : vrfEntries) {
-                        try {
-                            if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
+                ListenableFutures.addErrorLogging(
+                    txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
+                        for (VrfEntry vrfEntry : vrfEntries) {
+                            try {
+                                if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
                                     RouteOrigin.value(vrfEntry.getOrigin()))) {
-                                LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
-                                                + " is not a controller managed non intervpn link route. Ignoring.",
+                                    LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
+                                            + " is not a controller managed non intervpn link route. Ignoring.",
                                         vpn.getVrfId(), vrfEntry.getDestPrefix());
-                                continue;
-                            }
-                            String prefix = vrfEntry.getDestPrefix();
-                            String gwMac = vrfEntry.getGatewayMacAddress();
-                            vrfEntry.getRoutePaths().forEach(routePath -> {
-                                String nh = routePath.getNexthopAddress();
-                                int label = routePath.getLabel().intValue();
-                                if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
-                                        vrfEntry.getOrigin()))) {
-                                    LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
-                                                    + " nexthop {} label {} to vpn {} vpnRd {}",
-                                            vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
-                                    fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
-                                            Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
-                                            0 /*l3vni*/, gwMac,  vpn.getVrfId(), RouteOrigin.SELF_IMPORTED,
-                                            confTx);
-                                } else {
-                                    LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} "
-                                                    + "prefix {} nexthop {} label {} to vpn {} vpnRd {}",
-                                            vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
-                                    SubnetRoute route = vrfEntry.augmentation(SubnetRoute.class);
-                                    importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, vpn.getVrfId(),
-                                            confTx);
+                                    continue;
                                 }
-                            });
-                        } catch (RuntimeException e) {
-                            LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
-                                            + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
+                                String prefix = vrfEntry.getDestPrefix();
+                                String gwMac = vrfEntry.getGatewayMacAddress();
+                                requireNonNullElse(vrfEntry.getRoutePaths(),
+                                    Collections.<RoutePaths>emptyList()).forEach(routePath -> {
+                                        String nh = routePath.getNexthopAddress();
+                                        int label = routePath.getLabel().intValue();
+                                        if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
+                                            vrfEntry.getOrigin()))) {
+                                            LOG.info(
+                                                "handleVpnsExportingRoutesImporting: Importing fib entry rd {}"
+                                                    + " prefix {} nexthop {} label {} to vpn {} vpnRd {}",
+                                                vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
+                                            fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
+                                                Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
+                                                0 /*l3vni*/, gwMac, vpn.getVrfId(), RouteOrigin.SELF_IMPORTED,
+                                                confTx);
+                                        } else {
+                                            LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry"
+                                                    + " rd {} prefix {} nexthop {} label {} to vpn {} vpnRd {}",
+                                                vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
+                                            SubnetRoute route = vrfEntry.augmentation(SubnetRoute.class);
+                                            importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, vpn.getVrfId(),
+                                                confTx);
+                                        }
+                                    });
+                            } catch (RuntimeException e) {
+                                LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
+                                        + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
                                     vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
+                            }
                         }
-                    }
-                }), LOG, "Error handing VPN exporting routes");
+                    }), LOG, "Error handing VPN exporting routes");
             } else {
                 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
                         vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
@@ -1189,9 +1219,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     @Override
     public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
-        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+        LOG.trace("Received VpnInterface remove event: vpnInterface={}", vpnInterface);
+        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class);
         final String interfaceName = key.getName();
-        for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
+        for (VpnInstanceNames vpnInterfaceVpnInstance : requireNonNullElse(vpnInterface.getVpnInstanceNames(),
+                Collections.<VpnInstanceNames>emptyList())) {
             String vpnName = vpnInterfaceVpnInstance.getVpnName();
             removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
         }
@@ -1202,10 +1234,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                 final String interfaceName) {
         if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
             jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
-                ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
-                    deleteFibEntryForRouterInterface(vpnInterface, confTx, vpnName);
-                    LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
-                });
+                ListenableFuture<Void> future =
+                    txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
+                        deleteFibEntryForRouterInterface(vpnInterface, confTx, vpnName);
+                        LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
+                    });
                 ListenableFutures.addErrorLogging(future, LOG, "Error removing call for interface {} on VPN {}",
                         vpnInterface.getName(), vpnName);
                 return Collections.singletonList(future);
@@ -1218,68 +1251,69 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
     private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
-                                final VpnInterface vpnInterface, final String vpnName,
-                                final String interfaceName, final Interface interfaceState) {
+                                           final VpnInterface vpnInterface, final String vpnName,
+                                           final String interfaceName, final Interface interfaceState) {
         LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
                 vpnName, vpnInterface.getDpnId());
         removeInterfaceFromUnprocessedList(identifier, vpnInterface);
         jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
             () -> {
                 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
-                ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
-                    writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
-                        writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
-                            LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
-                                    interfaceName, vpnName);
-                            BigInteger dpId = BigInteger.ZERO;
-                            int ifIndex = 0;
-                            String gwMacAddress = null;
-                            InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
-                                    VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
-                            Optional<VpnInterfaceOpDataEntry> optVpnInterface = Optional.absent();
-                            try {
-                                optVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
-                                        LogicalDatastoreType.OPERATIONAL, interfaceId);
-                            } catch (ReadFailedException e) {
-                                LOG.error("remove: Failed to read data store for interface {} vpn {}", interfaceName,
-                                        vpnName);
-                                return;
-                            }
-                            if (interfaceState != null) {
+                ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                    writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
+                        writeOperTxn -> futures.add(
+                            txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeInvTxn -> {
+                                LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
+                                        interfaceName, vpnName);
+                                BigInteger dpId;
+                                int ifIndex;
+                                String gwMacAddress;
+                                InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
+                                        VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
+                                Optional<VpnInterfaceOpDataEntry> optVpnInterface;
                                 try {
-                                    dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
-                                } catch (NumberFormatException | IllegalStateException e) {
-                                    LOG.error("remove: Unable to retrieve dpnId from interface operational"
-                                            + " data store for interface {} on dpn {} for vpn {} Fetching"
-                                                    + " from vpn interface op data store. ", interfaceName,
-                                            vpnInterface.getDpnId(), vpnName, e);
-                                    dpId = BigInteger.ZERO;
+                                    optVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                                            LogicalDatastoreType.OPERATIONAL, interfaceId);
+                                } catch (ReadFailedException e) {
+                                    LOG.error("remove: Failed to read data store for interface {} vpn {}",
+                                            interfaceName, vpnName);
+                                    return;
                                 }
-                                ifIndex = interfaceState.getIfIndex();
-                                gwMacAddress = interfaceState.getPhysAddress().getValue();
-                            } else {
-                                LOG.info("remove: Interface state not available for {}. Trying to fetch data"
-                                        + " from vpn interface op.", interfaceName);
-                                if (optVpnInterface.isPresent()) {
-                                    VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
-                                    dpId = vpnOpInterface.getDpnId();
-                                    ifIndex = vpnOpInterface.getLportTag().intValue();
-                                    gwMacAddress = vpnOpInterface.getGatewayMacAddress();
+                                if (interfaceState != null) {
+                                    try {
+                                        dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
+                                    } catch (NumberFormatException | IllegalStateException e) {
+                                        LOG.error("remove: Unable to retrieve dpnId from interface operational"
+                                                        + " data store for interface {} on dpn {} for vpn {} Fetching"
+                                                        + " from vpn interface op data store. ", interfaceName,
+                                                vpnInterface.getDpnId(), vpnName, e);
+                                        dpId = BigInteger.ZERO;
+                                    }
+                                    ifIndex = interfaceState.getIfIndex();
+                                    gwMacAddress = interfaceState.getPhysAddress().getValue();
                                 } else {
-                                    LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
-                                                    + " as interfaceState and vpn interface op is not"
-                                            + " available", interfaceName, vpnName);
-                                    return;
+                                    LOG.info("remove: Interface state not available for {}. Trying to fetch data"
+                                            + " from vpn interface op.", interfaceName);
+                                    if (optVpnInterface.isPresent()) {
+                                        VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
+                                        dpId = vpnOpInterface.getDpnId();
+                                        ifIndex = vpnOpInterface.getLportTag().intValue();
+                                        gwMacAddress = vpnOpInterface.getGatewayMacAddress();
+                                    } else {
+                                        LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
+                                                + " as interfaceState and vpn interface op is not"
+                                                + " available", interfaceName, vpnName);
+                                        return;
+                                    }
                                 }
-                            }
-                            processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
-                                    optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
-                                    writeConfigTxn, writeOperTxn, writeInvTxn);
-                            LOG.info(
-                                    "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
-                                            + "successfully",
-                                    interfaceName, vpnInterface.getDpnId(), vpnName);
-                        })))));
+                                processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
+                                        optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
+                                        writeConfigTxn, writeOperTxn, writeInvTxn);
+                                LOG.info(
+                                        "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
+                                                + "successfully",
+                                        interfaceName, vpnInterface.getDpnId(), vpnName);
+                            })))));
                 futures.add(configFuture);
                 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
                 return futures;
@@ -1292,9 +1326,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                            String gwMac,
                                            VpnInterfaceOpDataEntry vpnOpInterface,
                                            boolean isInterfaceStateDown,
-                                           WriteTransaction writeConfigTxn,
-                                           WriteTransaction writeOperTxn,
-                                           WriteTransaction writeInvTxn) {
+                                           TypedWriteTransaction<Configuration> writeConfigTxn,
+                                           TypedWriteTransaction<Operational> writeOperTxn,
+                                           TypedReadWriteTransaction<Configuration> writeInvTxn)
+            throws ExecutionException, InterruptedException {
         if (vpnOpInterface == null) {
             LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
                     + " as it is not available in operational data store", interfaceName, dpId);
@@ -1305,13 +1340,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                                     interfaceName, vpnName);
         if (!isInterfaceStateDown) {
             final long vpnId = vpnUtil.getVpnId(vpnName);
-            vpnUtil.scheduleVpnInterfaceForRemoval(interfaceName, dpId, vpnName, Boolean.TRUE, null);
+            vpnUtil.scheduleVpnInterfaceForRemoval(interfaceName, dpId, vpnName,  null);
             final boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
             removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
                     vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
             if (interfaceManager.isExternalInterface(interfaceName)) {
-                processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
-                        NwConstants.DEL_FLOW);
+                processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
+                    NwConstants.DEL_FLOW);
             }
             if (!isBgpVpnInternetVpn) {
                 vpnUtil.unbindService(interfaceName, isInterfaceStateDown);
@@ -1321,14 +1356,16 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         } else {
             // Interface is retained in the DPN, but its Link Down.
             // Only withdraw the prefixes for this interface from BGP
-            withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
+            withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
         }
     }
 
     private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
                                           final String vpnName, final long vpnId, String gwMac,
-                                          WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
-                                          final WriteTransaction writeInvTxn) {
+                                          TypedWriteTransaction<Configuration> writeConfigTxn,
+                                          TypedWriteTransaction<Operational> writeOperTxn,
+                                          TypedReadWriteTransaction<Configuration> writeInvTxn)
+            throws ExecutionException, InterruptedException {
         //Read NextHops
         try {
             InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
@@ -1339,7 +1376,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             String primaryRd = vpnUtil.getVpnRd(vpnName);
             LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
                     interfaceName, dpnId, vpnName, primaryRd);
-            if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
+            if (adjacencies.isPresent() && adjacencies.get().getAdjacency() != null
+                    && !adjacencies.get().getAdjacency().isEmpty()) {
                 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
                 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
                         interfaceName, dpnId, vpnName, nextHops);
@@ -1357,19 +1395,19 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         } else {
                             // This is a primary adjacency
                             nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
-                                    : Collections.emptyList();
+                                    : emptyList();
                             removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
                                     interfaceName, writeInvTxn);
                         }
                         if (!nhList.isEmpty()) {
-                            if (rd.equals(vpnName)) {
+                            if (Objects.equals(rd, vpnName)) {
                                 //this is an internal vpn - the rd is assigned to the vpn instance name;
                                 //remove from FIB directly
                                 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
-                                        interfaceName, dpnId, writeConfigTxn));
+                                        interfaceName, dpnId, writeConfigTxn, writeOperTxn));
                             } else {
                                 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
-                                        interfaceName, writeConfigTxn);
+                                        interfaceName, writeConfigTxn, writeOperTxn);
                             }
                         } else {
                             LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
@@ -1399,7 +1437,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
                 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
                         + " Removing it.", interfaceName, vpnName, dpnId);
-                writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
+                writeOperTxn.delete(identifier);
             }
         } catch (ReadFailedException e) {
             LOG.error("removeAdjacenciesFromVpn: Failed to read data store for interface {} dpn {} vpn {}",
@@ -1408,11 +1446,26 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
-                                                                   String interfaceName, BigInteger dpnId,
-                                                                   WriteTransaction writeConfigTxn) {
+                                                            String interfaceName, BigInteger dpnId,
+                                                            TypedWriteTransaction<Configuration> writeConfigTxn,
+                                                            TypedWriteTransaction<Operational> writeOperTx) {
         return (nh) -> {
-            fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
-                    writeConfigTxn);
+            String primaryRd = vpnUtil.getVpnRd(vpnName);
+            String prefix = nextHop.getIpAddress();
+            String vpnNamePrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
+            LOG.info("remove adjacencies for nexthop {} vpnName {} interfaceName {} dpnId {}",
+                    nextHop, vpnName, interfaceName, dpnId);
+            synchronized (vpnNamePrefixKey.intern()) {
+                if (vpnUtil.removeOrUpdateDSForExtraRoute(vpnName, primaryRd, dpnId.toString(), interfaceName,
+                        prefix, nextHop.getNextHopIpList().get(0), nh, writeOperTx)) {
+                    //If extra-route is present behind at least one VM, then do not remove or update
+                    //fib entry for route-path representing that CSS nexthop, just update vpntoextraroute and
+                    //prefixtointerface DS
+                    return;
+                }
+                fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
+                        writeConfigTxn);
+            }
             LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
                             + " nexthop {} for interface {} on dpn {} for internal vpn {}",
                     vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
@@ -1421,13 +1474,14 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
                                            BigInteger dpnId, String rd, String interfaceName,
-                                           WriteTransaction writeConfigTxn) {
+                                           TypedWriteTransaction<Configuration> writeConfigTxn,
+                                           TypedWriteTransaction<Operational> writeOperTx) {
         List<VpnInstanceOpDataEntry> vpnsToImportRoute =
                 vpnUtil.getVpnsImportingMyRoute(vpnName);
         nhList.forEach((nh) -> {
             //IRT: remove routes from other vpns importing it
-            vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
-                    nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
+            vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
+                    nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
             for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
                 String vpnRd = vpn.getVrfId();
                 if (vpnRd != null) {
@@ -1444,7 +1498,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
                                                  int lportTag, String gwMac, String interfaceName,
-                                                 WriteTransaction writeInvTxn) {
+                                                 TypedReadWriteTransaction<Configuration> writeInvTxn)
+            throws ExecutionException, InterruptedException {
         final Uuid subnetId = nextHop.getSubnetId();
         if (nextHop.getSubnetGatewayMacAddress() == null) {
             // A valid mac-address was not available for this subnet-gateway-ip
@@ -1466,7 +1521,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
                             + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
                     vpnName);
-            nhList = Collections.emptyList();
+            nhList = emptyList();
         } else {
             nhList = Collections.singletonList(nextHopIp);
         }
@@ -1488,164 +1543,276 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     @Override
     protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
         final VpnInterface update) {
-        LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
-                update.getDpnId(), original.getVpnInstanceNames(),
-                update.getVpnInstanceNames());
+        LOG.trace("Received VpnInterface update event: original={}, update={}", original, update);
+        LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}", update.getName(),
+                update.getDpnId(), original.getVpnInstanceNames(), update.getVpnInstanceNames());
         final String vpnInterfaceName = update.getName();
         final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
+        LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
+        //handles switching between <internal VPN - external VPN>
+        jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            if (handleVpnInstanceUpdateForVpnInterface(identifier, original, update, futures)) {
+                LOG.info("update: handled Instance update for VPNInterface {} on dpn {} from oldVpn(s) {} "
+                                + "to newVpn(s) {}",
+                        original.getName(), dpnId,
+                        VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
+                        VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
+                return emptyList();
+            }
+            updateVpnInstanceAdjChange(original, update, vpnInterfaceName, futures);
+            return futures;
+        });
+    }
+
+    private boolean handleVpnInstanceUpdateForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
+                                                           VpnInterface original, VpnInterface update,
+                                                           List<ListenableFuture<Void>> futures) {
+        boolean isVpnInstanceUpdate = false;
+        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class);
+        final String interfaceName = key.getName();
+        List<String> oldVpnList = VpnUtil.getVpnListForVpnInterface(original);
+        List<String> oldVpnListCopy = new ArrayList<>();
+        oldVpnListCopy.addAll(oldVpnList);
+        List<String> newVpnList = VpnUtil.getVpnListForVpnInterface(update);
+        List<String> newVpnListCopy = new ArrayList<>();
+        newVpnListCopy.addAll(newVpnList);
+
+        oldVpnList.removeAll(newVpnList);
+        newVpnList.removeAll(oldVpnListCopy);
+        //This block will execute only on if there is a change in the VPN Instance.
+        if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
+            /*
+             * Internet BGP-VPN Instance update with single router:
+             * ====================================================
+             * In this case single VPN Interface will be part of maximum 2 VPN Instance only.
+             *     1st VPN Instance : router VPN or external BGP-VPN.
+             *     2nd VPN Instance : Internet BGP-VPN(router-gw update/delete) for public network access.
+             *
+             * VPN Instance UPDATE:
+             * oldVpnList = 0 and newVpnList = 1 (Internet BGP-VPN)
+             * oldVpnList = 1 and newVpnList = 0 (Internet BGP-VPN)
+             *
+             * External BGP-VPN Instance update with single router:
+             * ====================================================
+             * In this case single VPN interface will be part of maximum 1 VPN Instance only.
+             *
+             * Updated VPN Instance will be always either internal router VPN to
+             * external BGP-VPN or external BGP-VPN to internal router VPN swap.
+             *
+             * VPN Instance UPDATE:
+             * oldVpnList = 1 and newVpnList = 1 (router VPN to Ext-BGPVPN)
+             * oldVpnList = 1 and newVpnList = 1 (Ext-BGPVPN to router VPN)
+             *
+             * Dual Router VPN Instance Update:
+             * ================================
+             * In this case single VPN interface will be part of maximum 3 VPN Instance only.
+             *
+             * 1st VPN Instance : router VPN or external BGP-VPN-1.
+             * 2nd VPN Instance : router VPN or external BGP-VPN-2.
+             * 3rd VPN Instance : Internet BGP-VPN(router-gw update/delete) for public network access.
+             *
+             * Dual Router --> Associated with common external BGP-VPN Instance.
+             * 1st router and 2nd router are getting associated with single External BGP-VPN
+             * 1) add 1st router to external bgpvpn --> oldVpnList=1, newVpnList=1;
+             * 2) add 2nd router to the same external bgpvpn --> oldVpnList=1, newVpnList=0
+             * In this case, we need to call removeVpnInterfaceCall() followed by addVpnInterfaceCall()
+             *
+             *
+             */
+            isVpnInstanceUpdate = true;
+            if (VpnUtil.isDualRouterVpnUpdate(oldVpnListCopy, newVpnListCopy)) {
+                if ((oldVpnListCopy.size() == 2 || oldVpnListCopy.size() == 3)
+                        && (oldVpnList.size() == 1 && newVpnList.size() == 0)) {
+                    //Identify the external BGP-VPN Instance and pass that value as newVpnList
+                    List<String> externalBgpVpnList = new ArrayList<>();
+                    for (String newVpnName : newVpnListCopy) {
+                        String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
+                        VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(primaryRd);
+                        if (vpnInstanceOpDataEntry.getBgpvpnType() == VpnInstanceOpDataEntry
+                                .BgpvpnType.BGPVPNExternal) {
+                            externalBgpVpnList.add(newVpnName);
+                            break;
+                        }
+                    }
+                    //This call will execute removeVpnInterfaceCall() followed by addVpnInterfaceCall()
+                    updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList,
+                            externalBgpVpnList, oldVpnListCopy, futures);
+
+                } else if ((oldVpnListCopy.size() == 2 || oldVpnListCopy.size() == 3)
+                        && (oldVpnList.size() == 0 && newVpnList.size() == 1)) {
+                    //Identify the router VPN Instance and pass that value as oldVpnList
+                    List<String> routerVpnList = new ArrayList<>();
+                    for (String newVpnName : newVpnListCopy) {
+                        String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
+                        VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(primaryRd);
+                        if (vpnInstanceOpDataEntry.getBgpvpnType() == VpnInstanceOpDataEntry
+                                .BgpvpnType.VPN) {
+                            routerVpnList.add(newVpnName);
+                            break;
+                        }
+                    }
+                    //This call will execute removeVpnInterfaceCall() followed by addVpnInterfaceCall()
+                    updateVpnInstanceChange(identifier, interfaceName, original, update, routerVpnList,
+                            newVpnList, oldVpnListCopy, futures);
+
+                } else {
+                    //Handle remaining use cases.
+                    updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList, newVpnList,
+                            oldVpnListCopy, futures);
+                }
+            } else {
+                updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList, newVpnList,
+                        oldVpnListCopy, futures);
+            }
+        }
+        return isVpnInstanceUpdate;
+    }
+
+    private void updateVpnInstanceChange(InstanceIdentifier<VpnInterface> identifier, String interfaceName,
+                                         VpnInterface original, VpnInterface update, List<String> oldVpnList,
+                                         List<String> newVpnList, List<String> oldVpnListCopy,
+                                         List<ListenableFuture<Void>> futures) {
+        final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
+        final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
+                ? origAdjs.getAdjacency() : new ArrayList<>();
+        final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
+        final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
+                ? updateAdjs.getAdjacency() : new ArrayList<>();
+
+        boolean isOldVpnRemoveCallExecuted = false;
+        for (String oldVpnName : oldVpnList) {
+            LOG.info("updateVpnInstanceChange: VPN Interface update event - intfName {} "
+                    + "remove from vpnName {} ", interfaceName, oldVpnName);
+            removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
+            LOG.info("updateVpnInstanceChange: Processed Remove for update on VPNInterface"
+                            + " {} upon VPN update from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName,
+                    newVpnList);
+            isOldVpnRemoveCallExecuted = true;
+        }
+        //Wait for previous interface bindings to be removed
+        if (isOldVpnRemoveCallExecuted && !newVpnList.isEmpty()) {
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                //Ignore
+            }
+        }
+        for (String newVpnName : newVpnList) {
+            String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
+            if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
+                LOG.info("updateVpnInstanceChange: VPN Interface update event - intfName {} "
+                        + "onto vpnName {} ", interfaceName, newVpnName);
+                addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
+                LOG.info("updateVpnInstanceChange: Processed Add for update on VPNInterface {}"
+                                + "from oldVpn(s) {} to newVpn {} ",
+                        interfaceName, oldVpnListCopy, newVpnName);
+                /* This block will execute only if V6 subnet is associated with internet BGP-VPN.
+                 * Use Case:
+                 *     In Dual stack network, first V4 subnet only attached to router and router is associated
+                 *     with internet BGP-VPN(router-gw). At this point VPN interface is having only router vpn instance.
+                 *     Later V6 subnet is added to router, at this point existing VPN interface will get updated
+                 *     with Internet BGP-VPN instance(Note: Internet BGP-VPN Instance update in vpn interface
+                 *     is applicable for only on V6 subnet is added to router). newVpnList = Contains only Internet
+                 *     BGP-VPN Instance. So we required V6 primary adjacency info needs to be populated onto
+                 *     router VPN as well as Internet BGP-VPN.
+                 *
+                 *     addVpnInterfaceCall() --> It will create V6 Adj onto Internet BGP-VPN only.
+                 *     updateVpnInstanceAdjChange() --> This method call is needed for second primary V6 Adj
+                 *                                       update in existing router VPN instance.
+                 */
+                if (vpnUtil.isBgpVpnInternet(newVpnName)) {
+                    LOG.info("updateVpnInstanceChange: VPN Interface {} with new Adjacency {} in existing "
+                            + "VPN instance {}", interfaceName, newAdjs, original.getVpnInstanceNames());
+                    updateVpnInstanceAdjChange(original, update, interfaceName, futures);
+                }
+            }
+        }
+    }
+
+    private List<ListenableFuture<Void>> updateVpnInstanceAdjChange(VpnInterface original, VpnInterface update,
+                                                                    String vpnInterfaceName,
+                                                                    List<ListenableFuture<Void>> futures) {
         final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
         final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
-            != null ? origAdjs.getAdjacency() : new ArrayList<>();
+                != null ? origAdjs.getAdjacency() : new ArrayList<>();
         final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
         final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
-            != null ? updateAdjs.getAdjacency() : new ArrayList<>();
+                != null ? updateAdjs.getAdjacency() : new ArrayList<>();
 
-        LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
-        //handles switching between <internal VPN - external VPN>
-        if (handleVpnSwapForVpnInterface(identifier, original, update)) {
-            LOG.info("update: handled VPNInterface {} on dpn {} update"
-                     + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
-                     original.getName(), dpnId,
-                     VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
-                     VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
-            return;
-        }
-        for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
+        final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
+        for (VpnInstanceNames vpnInterfaceVpnInstance : requireNonNullElse(update.getVpnInstanceNames(),
+                Collections.<VpnInstanceNames>emptyList())) {
             String newVpnName = vpnInterfaceVpnInstance.getVpnName();
             List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
             List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
             String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
             if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
-                jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
-                    // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
-                        futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(operTx -> {
-                            InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
-                                    VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
-                            LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
-                                    update.getName(), newVpnName);
-                            //handle both addition and removal of adjacencies
-                            //currently, new adjacency may be an extra route
-                            boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
-                            if (!oldAdjs.equals(newAdjs)) {
-                                for (Adjacency adj : copyNewAdjs) {
-                                    if (copyOldAdjs.contains(adj)) {
-                                        copyOldAdjs.remove(adj);
-                                    } else {
-                                        // add new adjacency - right now only extra route will hit this path
-                                        if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
-                                            addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
-                                                    dpnId, operTx, confTx);
-                                        }
-                                        LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
-                                                + " vpn interface {} on vpn {} dpnId {}",
-                                                adj.getIpAddress(), adj.getNextHopIpList(),
-                                                adj.getLabel(), adj.getSubnetId(), update.getName(),
-                                                newVpnName, dpnId);
+                // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
+                futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
+                    futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
+                        InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
+                                VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
+                        LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
+                                update.getName(), newVpnName);
+                        //handle both addition and removal of adjacencies
+                        //currently, new adjacency may be an extra route
+                        boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
+                        if (!oldAdjs.equals(newAdjs)) {
+                            for (Adjacency adj : copyNewAdjs) {
+                                if (copyOldAdjs.contains(adj)) {
+                                    copyOldAdjs.remove(adj);
+                                } else {
+                                    // add new adjacency
+                                    if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+                                        addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
+                                                dpnId, operTx, confTx, confTx);
                                     }
+                                    LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
+                                                    + " vpn interface {} on vpn {} dpnId {}",
+                                            adj.getIpAddress(), adj.getNextHopIpList(),
+                                            adj.getLabel(), adj.getSubnetId(), update.getName(),
+                                            newVpnName, dpnId);
                                 }
-                                for (Adjacency adj : copyOldAdjs) {
-                                    if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
-                                        if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
-                                                && !adj.isPhysNetworkFunc()) {
-                                            delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
-                                                    operTx, confTx);
-                                            Optional<VpnInterfaceOpDataEntry> optVpnInterface = operTx.read(
-                                                    LogicalDatastoreType.OPERATIONAL, vpnInterfaceOpIdentifier).get();
-                                            if (optVpnInterface.isPresent()) {
-                                                VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry = optVpnInterface.get();
-                                                long vpnId = vpnUtil.getVpnId(newVpnName);
-                                                vpnUtil.removePrefixToInterfaceAdj(adj, vpnId,
-                                                        vpnInterfaceOpDataEntry, operTx);
-                                            } else {
-                                                LOG.info("update: Vpninterface {} not present in Operational",
-                                                        vpnInterfaceName);
-                                            }
-                                            //remove FIB entry
-                                            String vpnRd = vpnUtil.getVpnRd(newVpnName);
-                                            LOG.debug("update: remove prefix {} from the FIB and BGP entry "
-                                                    + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
-                                            //remove BGP entry
-                                            fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
-                                            if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
-                                                bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
-                                            }
-                                        } else {
-                                            delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
-                                                    operTx, confTx);
+                            }
+                            for (Adjacency adj : copyOldAdjs) {
+                                if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+                                    if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
+                                            && !adj.isPhysNetworkFunc()) {
+                                        delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
+                                                operTx, confTx);
+                                        //remove FIB entry
+                                        String vpnRd = vpnUtil.getVpnRd(newVpnName);
+                                        LOG.debug("update: remove prefix {} from the FIB and BGP entry "
+                                                + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
+                                        //remove BGP entry
+                                        fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
+                                        if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
+                                            bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
                                         }
+                                    } else {
+                                        delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
+                                                operTx, confTx);
                                     }
-                                    LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
-                                                    + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
-                                                    .getNextHopIpList(),
-                                            adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
                                 }
+                                LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
+                                                + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
+                                                .getNextHopIpList(),
+                                        adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
                             }
-                        }));
+                        }
                     }));
-                    for (ListenableFuture<Void> future : futures) {
-                        ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
-                                update.getName(), update.getVpnInstanceNames());
-                    }
-                    return futures;
-                });
+                }));
+                for (ListenableFuture<Void> future : futures) {
+                    ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
+                            update.getName(), update.getVpnInstanceNames());
+                }
             } else {
                 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
                         + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
             }
         }
-    }
-
-    private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
-                                                 VpnInterface original, VpnInterface update) {
-        boolean isSwap = Boolean.FALSE;
-        final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
-        final String interfaceName = key.getName();
-        List<String> oldVpnList = original.getVpnInstanceNames().stream()
-            .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
-        List<String> oldVpnListCopy = new ArrayList<>();
-        oldVpnListCopy.addAll(oldVpnList);
-        List<String> newVpnList = update.getVpnInstanceNames().stream()
-            .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
-        oldVpnList.removeAll(newVpnList);
-        newVpnList.removeAll(oldVpnListCopy);
-        if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
-            for (String oldVpnName: oldVpnList) {
-                isSwap = Boolean.TRUE;
-                LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
-                        + " running config-driven swap removal", interfaceName, oldVpnName);
-                removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
-                LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
-                        + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
-            }
-            //Wait for previous interface bindings to be removed
-            try {
-                Thread.sleep(2000);
-            } catch (InterruptedException e) {
-                //Ignore
-            }
-            for (String newVpnName: newVpnList) {
-                String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
-                isSwap = Boolean.TRUE;
-                if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
-                    LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
-                            + "running config-driven swap addition", interfaceName, newVpnName);
-                    final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
-                    final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
-                            ? origAdjs.getAdjacency() : new ArrayList<>();
-                    final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
-                    final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
-                            ? updateAdjs.getAdjacency() : new ArrayList<>();
-
-                    addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
-                    LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
-                                    + "from oldVpn(s) {} to newVpn {} upon VPN swap",
-                            interfaceName, oldVpnListCopy, newVpnName);
-                }
-            }
-        }
-        return isSwap;
+        return futures;
     }
 
     private void updateLabelMapper(Long label, List<String> nextHopIpList) {
@@ -1675,7 +1842,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
-        SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
+        SubnetRoute route, String parentVpnRd, TypedWriteTransaction<Configuration> writeConfigTxn) {
 
         RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
         VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
@@ -1686,7 +1853,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
         if (writeConfigTxn != null) {
-            writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
+            writeConfigTxn.merge(vrfTableId, vrfTableNew, CREATE_MISSING_PARENTS);
         } else {
             vpnUtil.syncUpdate(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
         }
@@ -1695,8 +1862,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
-                                           Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
-                                           WriteTransaction writeConfigTxn) {
+                                           Adjacency adj, BigInteger dpnId,
+                                           TypedWriteTransaction<Operational> writeOperTxn,
+                                           TypedWriteTransaction<Configuration> writeConfigTxn,
+                                           TypedReadWriteTransaction<Configuration> writeInvTxn)
+            throws ExecutionException, InterruptedException {
         String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
         String configVpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
         try {
@@ -1714,12 +1884,9 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
                 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L :  vpnInstanceOpData.getL3vni();
                 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
-                List<Adjacency> adjacencies;
-                if (optAdjacencies.isPresent()) {
-                    adjacencies = optAdjacencies.get().getAdjacency();
-                } else {
-                    // This code will be hit in case of first PNF adjacency
-                    adjacencies = new ArrayList<>();
+                List<Adjacency> adjacencies = new ArrayList<>();
+                if (optAdjacencies.isPresent() && optAdjacencies.get().getAdjacency() != null) {
+                    adjacencies.addAll(optAdjacencies.get().getAdjacency());
                 }
                 long vpnId = vpnUtil.getVpnId(vpnName);
                 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
@@ -1734,7 +1901,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     if (interfaceState != null) {
                         processVpnInterfaceAdjacencies(dpnId, currVpnIntf.getLportTag().intValue(), vpnName, primaryRd,
                                 currVpnIntf.getName(),
-                                vpnId, writeConfigTxn, writeOperTxn, null, interfaceState);
+                                vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
                     }
                 }
                 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()
@@ -1786,16 +1953,26 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
                             currVpnIntf.getName(), vpnName);
 
+                    InstanceIdentifier<VpnInterface> vpnIfaceConfigidentifier = VpnUtil
+                            .getVpnInterfaceIdentifier(currVpnIntf.getName());
+                    Optional<VpnInterface> vpnIntefaceConfig = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                            LogicalDatastoreType.CONFIGURATION, vpnIfaceConfigidentifier);
+                    Prefixes pnfPrefix = VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
+                            Prefixes.PrefixCue.PhysNetFunc);
+                    if (vpnIntefaceConfig.isPresent()) {
+                        pnfPrefix = VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
+                                vpnIntefaceConfig.get().getNetworkId(), vpnIntefaceConfig.get().getNetworkType(),
+                                vpnIntefaceConfig.get().getSegmentationId(), Prefixes.PrefixCue.PhysNetFunc);
+                    }
+
                     String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
 
                     writeOperTxn.merge(
-                            LogicalDatastoreType.OPERATIONAL,
                             VpnUtil.getPrefixToInterfaceIdentifier(vpnUtil.getVpnId(adj.getSubnetId().getValue()),
-                                    prefix), VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(),
-                                    prefix, adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
+                                    prefix), pnfPrefix, true);
 
                     fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
-                            adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */,
+                            adj.getIpAddress(), emptyList(), null /* EncapType */, 0 /* label */,
                             0 /*l3vni*/, null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
 
                     input.setRd(adj.getVrfId());
@@ -1807,10 +1984,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
                 VpnInterfaceOpDataEntry newVpnIntf =
                         VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
-                                aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
+                                aug, dpnId, currVpnIntf.getLportTag(),
                                 currVpnIntf.getGatewayMacAddress());
 
-                writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
+                writeOperTxn.merge(identifier, newVpnIntf, CREATE_MISSING_PARENTS);
             }
         } catch (ReadFailedException e) {
             LOG.error("addNewAdjToVpnInterface: Failed to read data store for interface {} dpn {} vpn {} rd {} ip "
@@ -1818,13 +1995,15 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
+    @Nullable
     private String getParentVpnRdForExternalSubnet(Adjacency adj) {
         Subnets subnets = vpnUtil.getExternalSubnet(adj.getSubnetId());
         return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
     }
 
     protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
-            BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
+                                            BigInteger dpnId, TypedWriteTransaction<Operational> writeOperTxn,
+                                            TypedWriteTransaction<Configuration> writeConfigTxn) {
         String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
         String vpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
         try {
@@ -1838,26 +2017,16 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 if (optAdjacencies.isPresent()) {
                     List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
 
-                    if (!adjacencies.isEmpty()) {
+                    if (adjacencies != null && !adjacencies.isEmpty()) {
                         LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
-                        Iterator<Adjacency> adjIt = adjacencies.iterator();
-                        while (adjIt.hasNext()) {
-                            Adjacency adjElem = adjIt.next();
-                            if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
-                                String rd = adjElem.getVrfId();
-                                adjIt.remove();
-                                AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
-                                VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
-                                        .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
-                                                currVpnIntf.getVpnInstanceName(), aug, dpnId,
-                                                currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
-                                                currVpnIntf.getGatewayMacAddress());
-                                writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
+                        for (Adjacency adjacency : adjacencies) {
+                            if (Objects.equals(adjacency.getIpAddress(), adj.getIpAddress())) {
+                                String rd = adjacency.getVrfId();
                                 if (adj.getNextHopIpList() != null) {
                                     for (String nh : adj.getNextHopIpList()) {
                                         deleteExtraRouteFromCurrentAndImportingVpns(
                                                 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
-                                                currVpnIntf.getName(), writeConfigTxn);
+                                                currVpnIntf.getName(), writeConfigTxn, writeOperTxn);
                                     }
                                 } else if (adj.isPhysNetworkFunc()) {
                                     LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
@@ -1884,13 +2053,15 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
-        String rd, String intfName, WriteTransaction writeConfigTxn) {
-        vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
+                                    String rd, String intfName, TypedWriteTransaction<Configuration> writeConfigTxn,
+                                    TypedWriteTransaction<Operational> writeOperTx) {
+        vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn, writeOperTx);
         List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
         for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
             String vpnRd = vpn.getVrfId();
             if (vpnRd != null) {
-                vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
+                vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn,
+                        writeOperTx);
             }
         }
     }
@@ -1907,7 +2078,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
-                                                    WriteTransaction writeConfigTxn, String vpnName) {
+                                                TypedWriteTransaction<Configuration> writeConfigTxn, String vpnName) {
         if (vpnInterface == null) {
             return;
         }
@@ -1942,11 +2113,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
-                                                    WriteTransaction writeConfigTxn, String vpnName) {
+            TypedWriteTransaction<Configuration> writeConfigTxn, String vpnName) {
         Adjacencies adjs = vpnInterface.augmentation(Adjacencies.class);
         String rd = vpnUtil.getVpnRd(vpnName);
         if (adjs != null) {
-            List<Adjacency> adjsList = adjs.getAdjacency();
+            List<Adjacency> adjsList = requireNonNullElse(adjs.getAdjacency(), emptyList());
             for (Adjacency adj : adjsList) {
                 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
                     String primaryInterfaceIp = adj.getIpAddress();
@@ -1964,19 +2135,12 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
-        if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
-            LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
-                  vpnName, intefaceData.vpnInterface.getName());
-            return;
-        }
-        final VpnInterfaceKey key = intefaceData.identifier
-               .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+        final VpnInterfaceKey key = intefaceData.identifier.firstKeyOf(VpnInterface.class);
         final String interfaceName = key.getName();
         InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
                  .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
         addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
                   intefaceData.identifier, vpnName);
-        return;
     }
 
     private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
@@ -2128,8 +2292,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
                         return;
                     }
-                    List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
-                            .augmentation(AdjacenciesOp.class).getAdjacency();
+                    List<Adjacency> operationVpnAdjacencies = requireNonNullElse(vpnInterfaceOptional.get()
+                            .augmentation(AdjacenciesOp.class).getAdjacency(), emptyList());
                     // Due to insufficient rds,  some of the extra route wont get processed when it is added.
                     // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
                     // in operational DS. These unprocessed adjacencies will be handled below.
@@ -2138,7 +2302,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     configVpnAdjacencies.stream()
                         .filter(adjacency -> operationVpnAdjacencies.stream()
                                 .noneMatch(operationalAdjacency ->
-                                        operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
+                                    Objects.equals(operationalAdjacency.getIpAddress(), adjacency.getIpAddress())))
                         .forEach(adjacency -> {
                             LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
                             jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
@@ -2147,14 +2311,16 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                     // if the oper tx goes in
                                     if (vpnUtil.isAdjacencyEligibleToVpn(adjacency, vpnName)) {
                                         List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                        futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx ->
-                                            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
-                                                confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId,
-                                                    primaryRd, adjacency, vpnInterfaceOptional.get()
-                                                        .getDpnId(), confTx, operTx)))));
+                                        futures.add(
+                                            txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx ->
+                                                futures.add(
+                                                    txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                                                        confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId,
+                                                            primaryRd, adjacency, vpnInterfaceOptional.get()
+                                                                .getDpnId(), operTx, confTx, confTx)))));
                                         return futures;
                                     } else {
-                                        return Collections.emptyList();
+                                        return emptyList();
                                     }
                                 });
                         });