Upstreaming changes in Netvirt 48/42548/2
authorSuraj Ranjan <suraj.ranjan@ericsson.com>
Tue, 26 Jul 2016 09:08:22 +0000 (14:38 +0530)
committerSuraj Ranjan <suraj.ranjan@ericsson.com>
Tue, 26 Jul 2016 09:54:57 +0000 (15:24 +0530)
(Dependent on https://git.opendaylight.org/gerrit/#/c/42540/)

This commit includes VPN Engine Concurrency Fixes also some SNAT and DNAT
regression issues.

1. We have made multiple fixes here for safe concurrency.

2. We have moved all helper methods that deal with VRFEntry
resource into FibManager from VPNManager.

3. We have gracefully handled deletion of bgpvpn regardless of
how many ever external routes are available in such vpn.

4. We have fixed NATService to directly use FibManager to
program SNAT/DNAT VRFEntries.

5. As of this review, all local VM routes WILL NOT be batched for
write into VRFEntry Config DataStore.

6. All the external routes imported from BGP, WILL BE batched and
written to VRFEntry Config DataStore.

Change-Id: I3109516e8d163f2b61ba49acc463b85b09bbaf85
Signed-off-by: Suraj Ranjan <suraj.ranjan@ericsson.com>
33 files changed:
vpnservice/bgpmanager/bgpmanager-api/pom.xml
vpnservice/bgpmanager/bgpmanager-api/src/main/java/org.opendaylight.netvirt.bgpmanager.api/IBgpManager.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpConfigurationManager.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpManager.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpUtil.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/FibDSWriter.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/commands/Network.java
vpnservice/bgpmanager/bgpmanager-impl/src/test/java/org/opendaylight/netvirt/bgpmanager/test/BgpManagerTest.java
vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java
vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/RouteOrigin.java [moved from vpnservice/bgpmanager/bgpmanager-api/src/main/java/org.opendaylight.netvirt.bgpmanager.api/RouteOrigin.java with 97% similarity]
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManager.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerProvider.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java
vpnservice/fibmanager/fibmanager-impl/src/test/java/org/opendaylight/netvirt/fibmanager/test/FibManagerTest.java
vpnservice/natservice/natservice-api/src/main/yang/odl-nat.yang
vpnservice/natservice/natservice-impl/pom.xml
vpnservice/natservice/natservice-impl/src/main/config/default-config.xml
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalRoutersListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/FloatingIPListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatServiceProvider.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/VpnFloatingIpHandler.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/natservice/impl/rev160111/NATServiceModule.java
vpnservice/natservice/natservice-impl/src/main/yang/natservice-impl.yang
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/DpnInVpnChangeListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/TunnelInterfaceStateListener.java [new file with mode: 0644]
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnserviceProvider.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkListener.java

index 74c9b71309949f75d1d63e105b9141b7e927de6b..fe64fd829d6aea1cd4a25085dbfcf2be168edf6c 100644 (file)
@@ -20,6 +20,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <artifactId>bgpmanager-api</artifactId>
   <version>${vpnservices.version}</version>
   <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.netvirt</groupId>
+      <artifactId>fibmanager-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netvirt</groupId>
+      <artifactId>fibmanager-api</artifactId>
+      <version>0.3.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
 
   <properties>
     <maven.javadoc.skip>true</maven.javadoc.skip>
index 986cdf69920e138b4226a9f80335c24abdae7413..bcd207a110f70f475362d3d1ba249d31fb3bd3bc 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netvirt.bgpmanager.api;
 
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import java.util.Collection;
 import java.util.List;
 
@@ -33,7 +34,7 @@ public interface IBgpManager {
      *
      * @param rd
      * @param prefix
-     * @param nextHopList
+     * @param nextHop
      * @param vpnLabel
      */
     public void addPrefix(String rd, String prefix, List<String> nextHopList, int vpnLabel, RouteOrigin origin) throws Exception;
index ac3f086f71a16802efa9f375e7e0ced73c418bf7..9ef6c2b9ed75fe3d140c833b2b7fdfcc47da0f55 100644 (file)
@@ -18,7 +18,6 @@ import java.net.NetworkInterface;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.*;
 import org.opendaylight.netvirt.bgpmanager.thrift.client.*;
@@ -32,6 +31,7 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.utils.clustering.EntityOwnerUtils;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.*;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.*;
index 72835c449f4a77360b3a2a3eed96f6477f11ee86..94728237dc435817f0acc23f77722536f1f1833c 100644 (file)
@@ -19,7 +19,6 @@ import com.google.common.base.*;
 import com.google.common.base.Optional;
 import org.apache.thrift.TException;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.bgpmanager.commands.Commands;
 import org.opendaylight.netvirt.bgpmanager.oam.*;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
@@ -29,6 +28,7 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
index bca33c6300e862bbce6b9777e362652f8ea89636..e1612b54afacd2e80939b693f8e2398d4019c5e8 100644 (file)
@@ -45,7 +45,7 @@ public class BgpUtil {
     public static Integer batchInterval;
     private static int txChainAttempts = 0;
 
-    private static BlockingQueue<ActionableResource> bgpRoutesBufferQ = new LinkedBlockingQueue<>();
+    private static BlockingQueue<ActionableResource> bgpResourcesBufferQ = new LinkedBlockingQueue<>();
 
     // return number of pending Write Transactions with BGP-Util (no read)
     public static int getGetPendingWrTransaction() {
@@ -64,7 +64,7 @@ public class BgpUtil {
 
     static void registerWithBatchManager(ResourceHandler resourceHandler) {
         ResourceBatchingManager resBatchingManager = ResourceBatchingManager.getInstance();
-        resBatchingManager.registerBatchableResource("BGP-VRFENTRY", bgpRoutesBufferQ, resourceHandler);
+        resBatchingManager.registerBatchableResource("BGP-RESOURCES", bgpResourcesBufferQ, resourceHandler);
     }
 
     static <T extends DataObject> void update(DataBroker broker, final LogicalDatastoreType datastoreType,
@@ -73,7 +73,7 @@ public class BgpUtil {
         actResource.setAction(ActionableResource.UPDATE);
         actResource.setInstanceIdentifier(path);
         actResource.setInstance(data);
-        bgpRoutesBufferQ.add(actResource);
+        bgpResourcesBufferQ.add(actResource);
     }
 
     public static <T extends DataObject> void write(DataBroker broker, final LogicalDatastoreType datastoreType,
@@ -82,7 +82,7 @@ public class BgpUtil {
         actResource.setAction(ActionableResource.CREATE);
         actResource.setInstanceIdentifier(path);
         actResource.setInstance(data);
-        bgpRoutesBufferQ.add(actResource);
+        bgpResourcesBufferQ.add(actResource);
     }
 
     static <T extends DataObject> void delete(DataBroker broker, final LogicalDatastoreType datastoreType,
@@ -91,7 +91,7 @@ public class BgpUtil {
         actResource.setAction(ActionableResource.DELETE);
         actResource.setInstanceIdentifier(path);
         actResource.setInstance(null);
-        bgpRoutesBufferQ.add(actResource);
+        bgpResourcesBufferQ.add(actResource);
     }
 
 
index 58a96472c53a37e2dc01fac3882bdcec2be5ec8a..c142f46e39674036b191940583a739d062b6d00c 100644 (file)
@@ -8,9 +8,9 @@
 
 package org.opendaylight.netvirt.bgpmanager;
 
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
index 2c952f9116bd52e2a8449072e8499f5ca5aebadb..ffc256e111f0d81f02c89cce62402c5f5cda4a71 100644 (file)
@@ -11,8 +11,8 @@ package org.opendaylight.netvirt.bgpmanager.commands;
 import org.apache.karaf.shell.commands.*;
 import org.apache.karaf.shell.console.OsgiCommandSupport;
 import org.opendaylight.netvirt.bgpmanager.BgpManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
index 20a9310b5d692f879383220897d42eb6aa0bc9a9..49c8d3f38986ee7344c69b84a60c64846f745f33 100644 (file)
@@ -16,9 +16,9 @@ import org.junit.runner.RunWith;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.netvirt.bgpmanager.BgpUtil;
 import org.opendaylight.netvirt.bgpmanager.FibDSWriter;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 
 import static org.junit.Assert.assertEquals;
 
index 51c3c38198f7c137002c5659610d36a9302670b9..a2f19174a1d1f693c1c16c0cd8f507f3e34b85bd 100644 (file)
@@ -8,6 +8,9 @@
 
 package org.opendaylight.netvirt.fibmanager.api;
 
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+
 import java.math.BigInteger;
 import java.util.List;
 
@@ -34,4 +37,10 @@ public interface IFibManager {
                            String rd, String destPrefix,
                            String localNextHopIp,
                            String remoteNextHopIP);
+
+
+    void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
+                             int label, RouteOrigin origin, WriteTransaction writeConfigTxn);
+    void removeOrUpdateFibEntry(DataBroker broker, String rd, String prefix, String nextHopToRemove, WriteTransaction writeConfigTxn);
+    void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn);
 }
similarity index 97%
rename from vpnservice/bgpmanager/bgpmanager-api/src/main/java/org.opendaylight.netvirt.bgpmanager.api/RouteOrigin.java
rename to vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/RouteOrigin.java
index c410676e12050e8c515aa49f40ba011a4b66f1d8..a1bc94bffdabc8f1321c8a098af29c1bcdf632ce 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.netvirt.bgpmanager.api;
+package org.opendaylight.netvirt.fibmanager.api;
 
   /* Usage:
    * RouteOrigin origin = RouteOrigin.value("b");
index 1eadba9c914b2ee290aeb6d5303c21c976ed93f0..e5d8b5e37c734bbe8b3cc32e45ba5e2a1f9744b9 100644 (file)
@@ -18,8 +18,8 @@ import java.util.List;
 import java.util.concurrent.*;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
@@ -27,12 +27,13 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.utils.batching.ActionableResource;
 import org.opendaylight.genius.utils.batching.ActionableResourceImpl;
 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
 import org.opendaylight.genius.utils.batching.ResourceHandler;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
@@ -92,7 +93,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
@@ -1222,8 +1222,8 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
       }
   }
 
-  private void checkCleanUpOpDataForFib(Prefixes prefixInfo, Long vpnId, String rd,
-                                        final VrfEntry vrfEntry, Extraroute extraRoute) {
+  private void checkCleanUpOpDataForFib(final Prefixes prefixInfo, final Long vpnId, final String rd,
+                                        final VrfEntry vrfEntry, final Extraroute extraRoute) {
 
       if (prefixInfo == null) {
           LOG.debug("Cleanup VPN Data Failed as unable to find prefix Info for prefix {}", vrfEntry.getDestPrefix());
@@ -1231,9 +1231,35 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
       }
 
       String ifName = prefixInfo.getVpnInterfaceName();
-      synchronized (ifName.intern()) {
+      DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+      dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + ifName,
+              new CleanupVpnInterfaceWorker(prefixInfo, vpnId, rd, vrfEntry, extraRoute));
+  }
+
+  private class CleanupVpnInterfaceWorker implements Callable<List<ListenableFuture<Void>>> {
+      Prefixes prefixInfo;
+      Long vpnId;
+      String rd;
+      VrfEntry vrfEntry;
+      Extraroute extraRoute;
+
+      public CleanupVpnInterfaceWorker(final Prefixes prefixInfo, final Long vpnId, final String rd,
+                                       final VrfEntry vrfEntry, final Extraroute extraRoute) {
+          this.prefixInfo = prefixInfo;
+          this.vpnId = vpnId;
+          this.rd= rd;
+          this.vrfEntry= vrfEntry;
+          this.extraRoute = extraRoute;
+      }
+
+      @Override
+      public List<ListenableFuture<Void>> call() throws Exception {
+          // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+          // to call the respective helpers.
+          String ifName = prefixInfo.getVpnInterfaceName();
+          WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
           Optional<VpnInterface> optvpnInterface = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
-                                                                FibUtil.getVpnInterfaceIdentifier(ifName));
+                  FibUtil.getVpnInterfaceIdentifier(ifName));
           if (optvpnInterface.isPresent()) {
               long associatedVpnId = FibUtil.getVpnId(broker, optvpnInterface.get().getVpnInstanceName());
               if (vpnId != associatedVpnId) {
@@ -1243,18 +1269,18 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                   FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
                           FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
                   LOG.warn("Not proceeding with Cleanup op data for prefix {}", vrfEntry.getDestPrefix());
-                  return;
+                  return null;
               } else {
                   LOG.debug("Processing cleanup of prefix {} associated with vpn {}",
-                            vrfEntry.getDestPrefix(), associatedVpnId);
+                          vrfEntry.getDestPrefix(), associatedVpnId);
               }
           }
           if (extraRoute != null) {
               FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                             FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
+                      FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
           }
           Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
-                                                              FibUtil.getAdjListPath(ifName));
+                  FibUtil.getAdjListPath(ifName));
           int numAdj = 0;
           if (optAdjacencies.isPresent()) {
               numAdj = optAdjacencies.get().getAdjacency().size();
@@ -1263,13 +1289,13 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
           if (numAdj > 1) {
               LOG.trace("cleanUpOpDataForFib: remove adjacency for prefix: {} {}", vpnId, vrfEntry.getDestPrefix());
               FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                             FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+                      FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
           }
           if ((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
               //clean up the vpn interface from DpnToVpn list
               LOG.trace("Clean up vpn interface {} from dpn {} to vpn {} list.", ifName, prefixInfo.getDpnId(), rd);
               FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                             FibUtil.getVpnInterfaceIdentifier(ifName));
+                      FibUtil.getVpnInterfaceIdentifier(ifName));
           }
 
           synchronized (vrfEntry.getLabel().toString().intern()) {
@@ -1281,7 +1307,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                   if (vpnInstanceOpDataEntryOptional.isPresent()) {
                       vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
                   }
-                  boolean lriRemoved = this.deleteLabelRouteInfo(lri, vpnInstanceName);
+                  boolean lriRemoved = deleteLabelRouteInfo(lri, vpnInstanceName);
                   if (lriRemoved) {
                       String parentRd = lri.getParentVpnRd();
                       FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
@@ -1289,6 +1315,14 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                   }
               }
           }
+          CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+          try {
+              futures.get();
+          } catch (InterruptedException | ExecutionException e) {
+              LOG.error("Error cleaning up interface {} on vpn {}", ifName, vpnId);
+              throw new RuntimeException(e.getMessage());
+          }
+          return null;
       }
   }
 
index 84d7f1c3c9a762a971e0d3a8ef52a4c5e5bfa4ea..d126443975e2397a65bf7b22734d704a8cbad76d 100644 (file)
@@ -11,11 +11,13 @@ import java.math.BigInteger;
 import java.util.List;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
@@ -183,4 +185,17 @@ public class FibManagerProvider implements BindingAwareProvider, IFibManager, Au
                                 localNextHopIp, remoteNextHopIp);
   }
 
+  public void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
+                                  int label, RouteOrigin origin, WriteTransaction writeConfigTxn) {
+    FibUtil.addOrUpdateFibEntry(broker, rd, prefix , nextHopList, label, origin, writeConfigTxn);
+  }
+
+  public void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn) {
+    FibUtil.removeFibEntry(broker, rd, prefix, writeConfigTxn);
+  }
+
+  public void removeOrUpdateFibEntry(DataBroker broker, String rd, String prefix, String nextHopToRemove, WriteTransaction writeConfigTxn) {
+    FibUtil.removeOrUpdateFibEntry(broker, rd, prefix, nextHopToRemove, writeConfigTxn);
+  }
+
 }
\ No newline at end of file
index 5554b813e24946900d1b10ad4d6f6c29f12f2c54..9945ed21d3c5adddcbb71fe5da428abb42b5d54c 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.netvirt.fibmanager;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -19,8 +20,15 @@ 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.TransactionCommitFailedException;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
@@ -449,5 +457,135 @@ public class FibUtil {
             throw new RuntimeException(e.getMessage());
         }
     }
+    public static void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
+                                           int label, RouteOrigin origin, WriteTransaction writeConfigTxn) {
+        if (rd == null || rd.isEmpty() ) {
+            LOG.error("Prefix {} not associated with vpn", prefix);
+            return;
+        }
+
+        Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
+
+        for ( String nextHop: nextHopList){
+            if (nextHop == null || nextHop.isEmpty()){
+                LOG.error("nextHop list contains null element");
+                return;
+            }
+        }
+
+        LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHopList, label);
+        try{
+            InstanceIdentifier<VrfEntry> vrfEntryId =
+                    InstanceIdentifier.builder(FibEntries.class)
+                            .child(VrfTables.class, new VrfTablesKey(rd))
+                            .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
+            Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+
+            if (! entry.isPresent()) {
+                VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nextHopList)
+                        .setLabel((long)label).setOrigin(origin.getValue()).build();
+
+                if (writeConfigTxn != null) {
+                    writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
+                } else {
+                    MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+                }
+            } else { // Found in MDSAL database
+                List<String> nh = entry.get().getNextHopAddressList();
+                for (String nextHop : nextHopList) {
+                    if (!nh.contains(nextHop))
+                        nh.add(nextHop);
+                }
+                VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nh)
+                        .setLabel((long) label).setOrigin(origin.getValue()).build();
+
+                if (writeConfigTxn != null) {
+                    writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
+                } else {
+                    MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("addFibEntryToDS: error ", e);
+        }
+    }
+
+    public static void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn) {
+
+        if (rd == null || rd.isEmpty()) {
+            LOG.error("Prefix {} not associated with vpn", prefix);
+            return;
+        }
+        LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
+
+        InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
+                InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
+        InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
+        if (writeConfigTxn != null) {
+            writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+        } else {
+            MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+        }
+    }
+
+    /**
+     * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
+     * last one in the VrfEntry, then the VrfEntry is removed too.
+     *
+     * @param broker dataBroker service reference
+     * @param rd Route-Distinguisher to which the VrfEntry belongs to
+     * @param prefix Destination of the route
+     * @param nextHopToRemove Specific nexthop within the Route to be removed.
+     *           If null or empty, then the whole VrfEntry is removed
+     */
+    public static void removeOrUpdateFibEntry(DataBroker broker, String rd, String prefix, String nextHopToRemove,
+                                              WriteTransaction writeConfigTxn) {
+
+        LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
+
+        // Looking for existing prefix in MDSAL database
+        InstanceIdentifier<VrfEntry> vrfEntryId =
+                InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
+                        .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
+        Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+
+        if ( entry.isPresent() ) {
+            List<String> nhListRead = new ArrayList<>();
+            if ( nextHopToRemove != null && !nextHopToRemove.isEmpty()) {
+                nhListRead = entry.get().getNextHopAddressList();
+                if (nhListRead.contains(nextHopToRemove)) {
+                    nhListRead.remove(nextHopToRemove);
+                }
+            }
+
+            if (nhListRead.isEmpty()) {
+                // Remove the whole entry
+                if (writeConfigTxn != null) {
+                    writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+                } else {
+                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+                }
+                LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
+            } else {
+                // An update must be done, not including the current next hop
+                VrfEntry vrfEntry =
+                        new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
+                                .setKey(new VrfEntryKey(prefix)).build();
+                if (writeConfigTxn != null) {
+                    writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
+                } else {
+                    MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+                }
+                LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
+            }
+        } else {
+            LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
+        }
+    }
+
+
+
+
+
 
 }
index 94bbea795d741b431e4fbcd6c6858a58ae63e273..39e97c4ed3b2392e6f731968dabf6be4aeb3b01f 100644 (file)
@@ -28,7 +28,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.netvirt.fibmanager.FibManager;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
index 99aba348e54d8d361bba2986cbccae29d03f3f73..6d762ab610ece791821ac22e100b40f599e6e33b 100644 (file)
@@ -38,7 +38,7 @@ module odl-nat {
     grouping external-interface-info {
         leaf internal-ip { type string; }
         leaf external-ip { type string; }
-        leaf label { type uint16; config false; }
+        leaf label { type uint32; config false; }
     }
 
     container floating-ip-info {
index c35a072d4b5e0353a3c02b973889056a9f10495d..928cc8aed24585557a58bcfa39f70f6013dfa7bf 100644 (file)
@@ -101,7 +101,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <artifactId>powermock-module-junit4</artifactId>
         <version>${powermock.version}</version>
         <scope>test</scope>
-        </dependency>
+    </dependency>
     </dependencies>
 
     <!--
index 3aaf1c23c30067cff333d7a2438de8206660f178..788d217ba0f38f7f06f2e2a152defb7bd459249b 100644 (file)
@@ -14,6 +14,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:bgpmanager:api?module=bgpmanager-api&amp;revision=2015-04-20</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:fibmanager:api?module=fibmanager-api&amp;revision=2015-05-08</capability>
       <capability>urn:opendaylight:genius:interfacemanager?module=odl-interface&amp;revision=2016-04-06</capability>
   </required-capabilities>
   <configuration>
@@ -35,6 +36,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <type xmlns:bgpmanager="urn:opendaylight:params:xml:ns:yang:bgpmanager:api">bgpmanager:bgpmanager-api</type>
             <name>bgpmanager</name>
           </bgpmanager>
+          <fibmanager>
+            <type xmlns:fibmanager="urn:opendaylight:params:xml:ns:yang:fibmanager:api">fibmanager:fibmanager-api</type>
+            <name>fibmanager</name>
+          </fibmanager>
           <notification-service>
             <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-service</type>
             <name>binding-notification-adapter</name>
index f2d91306b970b534279a5517967ab5a472f79e59..7c4810995238a28cf44fa6a56fe8164985376fe1 100644 (file)
@@ -14,7 +14,8 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
@@ -28,7 +29,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
@@ -68,7 +68,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
@@ -96,7 +95,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -137,6 +135,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
     private NaptEventHandler naptEventHandler;
     private NaptPacketInHandler naptPacketInHandler;
+    private IFibManager fibManager;
 
     public void setNaptEventHandler(NaptEventHandler naptEventHandler) {
         this.naptEventHandler = naptEventHandler;
@@ -188,6 +187,10 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         this.fibService = fibService;
     }
 
+    public void setFibManager(IFibManager fibManager) {
+        this.fibManager = fibManager;
+    }
+
     public ExternalRoutersListener(DataBroker dataBroker )
     {
         super( Routers.class, ExternalRoutersListener.class );
@@ -983,7 +986,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     //Inform BGP
                     String rd = NatUtil.getVpnRd(dataBroker, vpnName);
                     String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
-                    NatUtil.addPrefixToBGP(bgpManager, rd, externalIp, Arrays.asList(nextHopIp), label, log, RouteOrigin.STATIC);
+                    NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
 
                     //Install custom FIB routes
                     List<Instruction> customInstructions = new ArrayList<>();
@@ -1933,7 +1936,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         //Inform BGP about the route removal
         LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
-        NatUtil.removePrefixFromBGP(bgpManager, rd, externalIp, LOG);
+        NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
     }
 
     private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
index 6f761c84092d1b99a13a6361bda5f5e832a10431..c9d2fac24dd89c3464665fe952242b18b7f47727 100644 (file)
@@ -665,7 +665,7 @@ public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> im
         return null;
     }
 
-    void updateOperationalDS(String routerId, String interfaceName, int label, String internalIp, String externalIp) {
+    void updateOperationalDS(String routerId, String interfaceName, long label, String internalIp, String externalIp) {
 
         LOG.info("Updating operational DS for floating ip config : {} with label {}", internalIp, label);
         InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
index 50667e5a788af0c1f2636bdee2747ed22353ac32..bc039aa03062038eb97ddc0dc13f41a1ff86e462 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderCo
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
@@ -51,6 +52,7 @@ public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
     private NAPTSwitchSelector naptSwitchSelector;
     private RouterPortsListener routerPortsListener;
     private IInterfaceManager interfaceManager;
+    private IFibManager fibManager;
 
     public NatServiceProvider(RpcProviderRegistry rpcProviderRegistry) {
         this.rpcProviderRegistry = rpcProviderRegistry;
@@ -69,6 +71,11 @@ public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
         this.bgpManager = bgpManager;
     }
 
+    public void setFibManager(IFibManager fibManager) {
+        LOG.debug("FIB Manager reference initialized");
+        this.fibManager = fibManager;
+    }
+
     public void setInterfaceManager(IInterfaceManager interfaceManager) {
         this.interfaceManager = interfaceManager;
     }
@@ -128,6 +135,7 @@ public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
             VpnFloatingIpHandler handler = new VpnFloatingIpHandler(vpnService, bgpManager, fibService);
             handler.setBroker(dataBroker);
             handler.setMdsalManager(mdsalManager);
+            handler.setFibManager(fibManager);
             handler.setListener(floatingIpListener);
             floatingIpListener.setFloatingIpHandler(handler);
 
@@ -148,6 +156,7 @@ public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
             externalRouterListener.setNaptSwitchSelector(naptSwitchSelector);
             externalRouterListener.setNaptEventHandler(naptEventHandler);
             externalRouterListener.setNaptPacketInHandler(naptPacketInHandler);
+            externalRouterListener.setFibManager(fibManager);
 
             //Instantiate ExternalNetworksChangeListener and set the dataBroker in it.
             externalNetworksChangeListener = new ExternalNetworksChangeListener( dataBroker );
index 49ad793cf86bd3ad741c36aa50211c993b5a77c2..2b01a51952980a1164d789465d5901993091f9a8 100644 (file)
@@ -9,10 +9,7 @@
 package org.opendaylight.netvirt.natservice.internal;
 
 import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -22,7 +19,8 @@ import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
@@ -103,7 +101,6 @@ import org.slf4j.LoggerFactory;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
@@ -649,12 +646,20 @@ public class NatUtil {
         return vpnUuid.getValue();
     }
 
-    public static void addPrefixToBGP(IBgpManager bgpManager, String rd, String prefix, List<String> nextHopIpList,
-                                         long label, Logger log, RouteOrigin origin) {
+    public static void addPrefixToBGP(DataBroker broker,
+                                      IBgpManager bgpManager,
+                                      IFibManager fibManager,
+                                      String rd,
+                                      String prefix,
+                                      String nextHopIp,
+                                      long label,
+                                      Logger log,
+                                      RouteOrigin origin) {
         try {
-            LOG.info("ADD: Adding Fib Entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHopIpList, label);
-            bgpManager.addPrefix(rd, prefix, nextHopIpList, (int)label, origin);
-            LOG.info("ADD: Added Fib Entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHopIpList, label);
+            LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
+            fibManager.addOrUpdateFibEntry(broker, rd, prefix, Arrays.asList(nextHopIp), (int)label, origin, null);
+            bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
+            LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
         } catch(Exception e) {
             log.error("Add prefix failed", e);
         }
@@ -761,11 +766,12 @@ public class NatUtil {
         return 0;
     }
 
-    public static void removePrefixFromBGP(IBgpManager bgpManager, String rd, String prefix, Logger log) {
+    public static void removePrefixFromBGP(DataBroker broker , IBgpManager bgpManager, IFibManager fibManager, String rd, String prefix, Logger log) {
         try {
-            LOG.info("REMOVE: Removing Fib Entry rd {} prefix {}", rd, prefix);
-            bgpManager.deletePrefix(rd, prefix);
-            LOG.info("REMOVE: Removed Fib Entry rd {} prefix {}", rd, prefix);
+            LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
+            fibManager.removeFibEntry(broker, rd, prefix, null);
+            bgpManager.withdrawPrefix(rd, prefix);
+            LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
         } catch(Exception e) {
             log.error("Delete prefix failed", e);
         }
index f3c1f8f44c2f3e8a34a470708379f512fe5d4fec..5b065dbc9a6d664d50dc02792e98daff85036f58 100644 (file)
@@ -24,7 +24,8 @@ import org.opendaylight.genius.mdsalutil.MatchFieldType;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
@@ -57,6 +58,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
     private DataBroker dataBroker;
     private IMdsalApiManager mdsalManager;
     private FloatingIPListener listener;
+    private IFibManager fibManager;
 
     static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
     static final String FLOWID_PREFIX = "NAT.";
@@ -80,6 +82,10 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         this.mdsalManager = mdsalManager;
     }
 
+    void setFibManager(IFibManager fibManager) {
+        this.fibManager = fibManager;
+    }
+
     @Override
     public void onAddFloatingIp(final BigInteger dpnId, final String routerId,
                                 Uuid networkId, final String interfaceName, final String externalIp, final String internalIp) {
@@ -101,13 +107,14 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                     GenerateVpnLabelOutput output = result.getResult();
                     long label = output.getLabel();
                     LOG.debug("Generated label {} for prefix {}", label, externalIp);
-                    listener.updateOperationalDS(routerId, interfaceName, (int)label, internalIp, externalIp);
+                    listener.updateOperationalDS(routerId, interfaceName, label, internalIp, externalIp);
 
                     //Inform BGP
                     String rd = NatUtil.getVpnRd(dataBroker, vpnName);
                     String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
                     LOG.debug("Nexthop ip for prefix {} is {}", externalIp, nextHopIp);
-                    NatUtil.addPrefixToBGP(bgpManager, rd, externalIp + "/32", Arrays.asList(nextHopIp),label, LOG, RouteOrigin.STATIC);
+                    NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp + "/32", nextHopIp,
+                            label, LOG, RouteOrigin.STATIC);
 
                     List<Instruction> instructions = new ArrayList<>();
                     List<ActionInfo> actionsInfos = new ArrayList<>();
@@ -161,7 +168,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         }
         //Remove Prefix from BGP
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
-        removePrefixFromBGP(rd, externalIp + "/32");
+        NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp + "/32", LOG);
 
         //Remove custom FIB routes
         //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
@@ -205,20 +212,10 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         });
     }
 
-    private void removePrefixFromBGP(String rd, String prefix) {
-        try {
-            LOG.info("REMOVE: Removing Fib Entry rd {} prefix {}", rd, prefix);
-            bgpManager.deletePrefix(rd, prefix);
-            LOG.info("REMOVE: Removed Fib Entry rd {} prefix {}", rd, prefix);
-        } catch(Exception e) {
-            LOG.error("Delete prefix failed", e);
-        }
-    }
-
     void cleanupFibEntries(final BigInteger dpnId, final String vpnName, final String externalIp, final long label ) {
         //Remove Prefix from BGP
         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
-        removePrefixFromBGP(rd, externalIp + "/32");
+        NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp + "/32", LOG);
 
         //Remove custom FIB routes
 
index a405894721582b426d43b9dcd1c0d2c156892985..96e4a3e69425e385d5fe84b9b8106632837a0418 100644 (file)
@@ -30,6 +30,7 @@ public class NATServiceModule extends org.opendaylight.yang.gen.v1.urn.opendayli
         provider.setMdsalManager(getMdsalutilDependency());
         provider.setInterfaceManager(getOdlinterfaceDependency());
         provider.setBgpManager(getBgpmanagerDependency());
+        provider.setFibManager(getFibmanagerDependency());
         getBrokerDependency().registerProvider(provider);
         return provider;
     }
index b7c4d90eea932c64df3c1d67b3eb0b58a506971c..d95d817c64b8cfb81166637c0d6aa18385fc31f6 100644 (file)
@@ -8,6 +8,7 @@ module natservice-impl {
     import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28; }
     import odl-mdsalutil { prefix odl-mdsal; revision-date 2016-04-06;}
     import bgpmanager-api { prefix bgpmgr-api; revision-date 2015-04-20;}
+    import fibmanager-api { prefix fibmgr-api; revision-date 2015-05-08;}
     import odl-interface {prefix odlif; revision-date 2016-04-06;}
 
     description
@@ -50,6 +51,14 @@ module natservice-impl {
                     }
                 }
             }
+            container fibmanager {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity fibmgr-api:fibmanager-api;
+                    }
+                }
+            }
             container notification-service {
                 uses config:service-ref {
                     refine type {
index 74a59bc6716203ed44854b15ede4a49446dc3d64..25527b46ea111f09d9d7a0ecd64ced256939467f 100644 (file)
@@ -8,10 +8,12 @@
 package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 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.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.mdsalutil.*;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
@@ -32,6 +34,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 
 public class DpnInVpnChangeListener implements OdlL3vpnListener {
     private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnChangeListener.class);
@@ -51,7 +54,7 @@ public class DpnInVpnChangeListener implements OdlL3vpnListener {
 
         RemoveEventData eventData = notification.getRemoveEventData();
         final String rd = eventData.getRd();
-        String vpnName = eventData.getVpnName();
+        final String vpnName = eventData.getVpnName();
         BigInteger dpnId = eventData.getDpnId();
 
         LOG.trace("Remove Dpn Event notification received for rd {} VpnName {} DpnId {}", rd , vpnName, dpnId);
@@ -66,15 +69,20 @@ public class DpnInVpnChangeListener implements OdlL3vpnListener {
                     final Collection<VpnToDpnList> vpnToDpnList = vpnOpValue.get().getVpnToDpnList();
 
                     DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-                    dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+                    dataStoreCoordinator.enqueueJob("VPN-" + vpnName + "-DPN-" + dpnId.toString() ,
                             new Callable<List<ListenableFuture<Void>>>() {
                                 @Override
                                 public List<ListenableFuture<Void>> call() throws Exception {
                                     WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
                                     deleteDpn(vpnToDpnList , rd , writeTxn);
-                                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                    futures.add(writeTxn.submit());
-                                    return futures;
+                                    CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+                                    try {
+                                        futures.get();
+                                    } catch (InterruptedException | ExecutionException e) {
+                                        LOG.error("Error removing dpnToVpnList for vpn {} ", vpnName);
+                                        throw new RuntimeException(e.getMessage());
+                                    }
+                                    return null;
                                 }
                             });
 
index a3c04fec9b047c45d5a0d8cbffd06047ac3e3211..7f7a292b94337aea4be3408952be591bcacb84b4 100644 (file)
@@ -9,12 +9,14 @@ package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.base.Optional;
 
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
@@ -32,6 +34,7 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 
 public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
@@ -50,7 +53,7 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
     }
 
     public void setIfaceMgrRpcService(OdlInterfaceRpcService interfaceManager) {
-      this.interfaceManager = interfaceManager;
+        this.interfaceManager = interfaceManager;
     }
 
     @Override
@@ -70,7 +73,7 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
     private void registerListener(final DataBroker db) {
         try {
             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                                                                 getWildCardPath(), InterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
+                    getWildCardPath(), InterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
         } catch (final Exception e) {
             LOG.error("Interface DataChange listener registration failed", e);
             throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
@@ -100,11 +103,27 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
                                 new Callable<List<ListenableFuture<Void>>>() {
                                     @Override
                                     public List<ListenableFuture<Void>> call() throws Exception {
-                                        WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-                                        vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeTxn);
-                                        List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                        futures.add(writeTxn.submit());
-                                        return futures;
+                                        WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
+                                        WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+                                        vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false,
+                                                writeConfigTxn, writeOperTxn);
+                                        CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                                        try {
+                                            futures.get();
+                                        } catch (InterruptedException | ExecutionException e) {
+                                            LOG.error("Error adding Oper data for interface {} to vpn {} on dpn {}", interfaceName,
+                                                    vpnInterface.getVpnInstanceName(), dpnId);
+                                            throw new RuntimeException(e.getMessage());
+                                        }
+                                        futures = writeConfigTxn.submit();
+                                        try {
+                                            futures.get();
+                                        } catch (InterruptedException | ExecutionException e) {
+                                            LOG.error("Error adding Config data for interface {} to vpn {} on dpn {}", interfaceName,
+                                                    vpnInterface.getVpnInstanceName(), dpnId);
+                                            throw new RuntimeException(e.getMessage());
+                                        }
+                                        return null;
                                     }
                                 });
                     } else {
@@ -116,11 +135,17 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
                                     new Callable<List<ListenableFuture<Void>>>() {
                                         @Override
                                         public List<ListenableFuture<Void>> call() throws Exception {
-                                            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-                                            handleRouterInterfacesUpEvent(routerName, interfaceName, writeTxn);
-                                            List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                            futures.add(writeTxn.submit());
-                                            return futures;
+                                            WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+                                            handleRouterInterfacesUpEvent(routerName, interfaceName, writeOperTxn);
+                                            CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                                            try {
+                                                futures.get();
+                                            } catch (InterruptedException | ExecutionException e) {
+                                                LOG.error("Error adding as router interface for interface {} to router {} ", interfaceName,
+                                                        routerName);
+                                                throw new RuntimeException(e.getMessage());
+                                            }
+                                            return null;
                                         }
                                     });
                         } else {
@@ -160,7 +185,7 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
                     LOG.debug("Interface {} is not a vpninterface, ignoring.", intrf.getName());
                     return;
                 }
-                VpnInterface vpnInterface = optVpnInterface.get();
+                final VpnInterface vpnInterface = optVpnInterface.get();
                 try {
                     dpId = InterfaceUtils.getDpIdFromInterface(intrf);
                 } catch (Exception e){
@@ -174,16 +199,32 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
                         new Callable<List<ListenableFuture<Void>>>() {
                             @Override
                             public List<ListenableFuture<Void>> call() throws Exception {
-                                WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-                                vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, false, false, writeTxn);
+                                WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+                                WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
+                                vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, false, false,
+                                        writeConfigTxn, writeOperTxn);
                                 RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(broker, interfaceName);
                                 if (routerInterface != null) {
                                     final String routerName = routerInterface.getRouterName();
-                                    handleRouterInterfacesDownEvent(routerName, interfaceName, dpnId, writeTxn);
+                                    handleRouterInterfacesDownEvent(routerName, interfaceName, dpnId, writeOperTxn);
+                                }
+                                CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                                try {
+                                    futures.get();
+                                } catch (InterruptedException | ExecutionException e) {
+                                    LOG.error("Error removing Oper data for interface {} from vpn {} on dpn {}", interfaceName,
+                                            vpnInterface.getVpnInstanceName(), dpnId);
+                                    throw new RuntimeException(e.getMessage());
+                                }
+                                futures = writeConfigTxn.submit();
+                                try {
+                                    futures.get();
+                                } catch (InterruptedException | ExecutionException e) {
+                                    LOG.error("Error removing Config data for interface {} from vpn {} on dpn {}", interfaceName,
+                                            vpnInterface.getVpnInstanceName(), dpnId);
+                                    throw new RuntimeException(e.getMessage());
                                 }
-                                List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                futures.add(writeTxn.submit());
-                                return futures;
+                                return null;
                             }
                         });
             }
@@ -210,16 +251,23 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
                 if (vpnInterface != null) {
                     if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
                         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-                        dataStoreCoordinator.enqueueJob(interfaceName,
+                        dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
                                 new Callable<List<ListenableFuture<Void>>>() {
                                     @Override
                                     public List<ListenableFuture<Void>> call() throws Exception {
-                                        WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+                                        WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
+                                        WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
                                         vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex,
-                                                true, writeTxn);
-                                        List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                        futures.add(writeTxn.submit());
-                                        return futures;
+                                                true, writeConfigTxn, writeOperTxn);
+                                        CheckedFuture<Void, TransactionCommitFailedException> futures = writeConfigTxn.submit();
+                                        try {
+                                            futures.get();
+                                        } catch (InterruptedException | ExecutionException e) {
+                                            LOG.error("Error updating UP for interface {} in vpn {} on dpn {}", interfaceName,
+                                                    vpnInterface.getVpnInstanceName(), dpnId);
+                                            throw new RuntimeException(e.getMessage());
+                                        }
+                                        return null;
                                     }
                                 });
                     } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
@@ -228,11 +276,27 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
                                 new Callable<List<ListenableFuture<Void>>>() {
                                     @Override
                                     public List<ListenableFuture<Void>> call() throws Exception {
-                                        WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-                                        vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, true, false, writeTxn);
-                                        List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                        futures.add(writeTxn.submit());
-                                        return futures;
+                                        WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
+                                        WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+                                        vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, true, false,
+                                                writeConfigTxn, writeOperTxn);
+                                        CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                                        try {
+                                            futures.get();
+                                        } catch (InterruptedException | ExecutionException e) {
+                                            LOG.error("Error updating DOWN for interface {} from vpn {} on dpn {}", interfaceName,
+                                                    vpnInterface.getVpnInstanceName(), dpnId);
+                                            throw new RuntimeException(e.getMessage());
+                                        }
+                                        futures = writeConfigTxn.submit();
+                                        try {
+                                            futures.get();
+                                        } catch (InterruptedException | ExecutionException e) {
+                                            LOG.error("Error updating DOWN for interface {} from vpn {} on dpn {}", interfaceName,
+                                                    vpnInterface.getVpnInstanceName(), dpnId);
+                                            throw new RuntimeException(e.getMessage());
+                                        }
+                                        return null;
                                     }
                                 });
                     }
@@ -241,14 +305,15 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
         }
     }
 
-    void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeTxn) {
+    void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeOperTxn) {
         LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
-        vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeTxn);
+        vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeOperTxn);
     }
 
-    void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId, WriteTransaction writeTxn) {
+    void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId,
+                                         WriteTransaction writeOperTxn) {
         LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
-        vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeTxn);
+        vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeOperTxn);
     }
 
-}
\ No newline at end of file
+}
diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/TunnelInterfaceStateListener.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/TunnelInterfaceStateListener.java
new file mode 100644 (file)
index 0000000..50dcc91
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.vpnmanager;
+
+import com.google.common.base.Optional;
+import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216.modules.module.configuration.vpnservice.impl.Bgpmanager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class TunnelInterfaceStateListener extends AbstractDataChangeListener<StateTunnelList> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
+    protected enum UpdateRouteAction {
+        ADVERTISE_ROUTE, WITHDRAW_ROUTE
+    }
+    DataBroker broker;
+    private final IBgpManager bgpManager;
+    private IFibManager fibManager;
+    private ItmRpcService itmProvider;
+
+    public TunnelInterfaceStateListener(final DataBroker broker,
+                                        final IBgpManager bgpManager, final IFibManager fibManager) {
+        super(StateTunnelList.class);
+        this.broker = broker;
+        this.fibManager = fibManager;
+        this.bgpManager = bgpManager;
+    }
+
+    public void setITMProvider(ItmRpcService itmProvider) {
+        this.itmProvider = itmProvider;
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
+        LOG.trace("Tunnel deletion---- {}", del);
+        handlePrefixesForDPNs(del, UpdateRouteAction.WITHDRAW_ROUTE);
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original, StateTunnelList update) {
+        LOG.trace("Tunnel updation---- {}", update);
+        LOG.trace("ITM Tunnel {} of type {} state event changed from :{} to :{}",
+                update.getTunnelInterfaceName(),
+                fibManager.getTransportTypeStr(update.getTransportType().toString()),
+                original.isTunnelState(), update.isTunnelState());
+        //withdraw all prefixes in all vpns for this dpn
+        boolean isTunnelUp = update.isTunnelState();
+        handlePrefixesForDPNs(update, isTunnelUp ? UpdateRouteAction.ADVERTISE_ROUTE :
+                UpdateRouteAction.WITHDRAW_ROUTE);
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
+        LOG.trace("Tunnel addition---- {}", add);
+
+        if (!add.isTunnelState()) {
+            LOG.trace("Tunnel {} is not yet UP.",
+                    add.getTunnelInterfaceName());
+            return;
+        } else {
+            LOG.trace("ITM Tunnel ,type {} ,State is UP b/w src: {} and dest: {}",
+                    fibManager.getTransportTypeStr(add.getTransportType().toString()),
+                    add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
+            handlePrefixesForDPNs(add, UpdateRouteAction.ADVERTISE_ROUTE);
+        }
+    }
+
+    private void handlePrefixesForDPNs(StateTunnelList stateTunnelList, UpdateRouteAction action) {
+        BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
+        BigInteger destDpnId;
+        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+        String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
+
+        InstanceIdentifier.InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
+        InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
+        Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
+        long tunTypeVal = 0, vpnId;
+
+        if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
+        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
+        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
+        } else {
+            tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
+        }
+        LOG.trace("tunTypeVal is {}", tunTypeVal);
+
+        long dcgwPresentStatus = VpnConstants.DCGWPresentStatus.Invalid.getValue();
+        if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+            Future<RpcResult<IsDcgwPresentOutput>> result;
+            try {
+                result = itmProvider.isDcgwPresent(new IsDcgwPresentInputBuilder()
+                        .setDcgwIp(destTepIp)
+                        .build());
+                RpcResult<IsDcgwPresentOutput> rpcResult = result.get();
+                if (!rpcResult.isSuccessful()) {
+                    LOG.warn("RPC Call to isDcgwPresent {} returned with Errors {}", destTepIp, rpcResult.getErrors());
+                } else {
+                    dcgwPresentStatus = rpcResult.getResult().getRetVal();
+                }
+            } catch (Exception e) {
+                LOG.warn("Exception {} when querying for isDcgwPresent {}, trace {}", e, destTepIp, e.getStackTrace());
+            }
+        }
+
+        if (vpnInstances.isPresent()) {
+            List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
+            Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
+            LOG.trace("vpnInstIter {}", vpnInstIter);
+            while (vpnInstIter.hasNext()) {
+                VpnInstance vpnInstance = vpnInstIter.next();
+                LOG.trace("vpnInstance {}", vpnInstance);
+                vpnId = VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName());
+                try {
+                    VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
+                    LOG.trace("vpnConfig {}", vpnConfig);
+                    String rd = vpnConfig.getRouteDistinguisher();
+                    if (rd == null || rd.isEmpty()) {
+                        rd = vpnInstance.getVpnInstanceName();
+                        LOG.trace("rd is null or empty. Assigning VpnInstanceName to rd {}", rd);
+                    }
+                    InstanceIdentifier<VpnToDpnList> srcId =
+                            VpnUtil.getVpnToDpnListIdentifier(rd, srcDpnId);
+                    Optional<VpnToDpnList> srcDpnInVpn =
+                            VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, srcId);
+                    if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+                        destDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
+                        InstanceIdentifier<VpnToDpnList> destId =
+                                VpnUtil.getVpnToDpnListIdentifier(rd, destDpnId);
+                        Optional<VpnToDpnList> destDpnInVpn =
+                                VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, destId);
+                        if (!(srcDpnInVpn.isPresent() &&
+                                destDpnInVpn.isPresent())) {
+                            LOG.trace(" srcDpn {} - destDPN {}, do not share the VPN {} with rd {}.",
+                                    srcDpnId, destDpnId, vpnInstance.getVpnInstanceName(), rd);
+                            continue;
+                        }
+                    }
+                    if (srcDpnInVpn.isPresent()) {
+                        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+                                .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
+                                vpnInterfaces = srcDpnInVpn.get().getVpnInterfaces();
+                        for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+                                .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
+                            InstanceIdentifier<VpnInterface> vpnIntfId =
+                                    VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
+                            LOG.trace("vpnInterface {}", vpnInterface);
+                            InstanceIdentifier<Adjacencies> path =
+                                    vpnIntfId.augmentation(Adjacencies.class);
+                            Optional<Adjacencies> adjacencies =
+                                    VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+                            LOG.trace("adjacencies {}", adjacencies);
+                            if (adjacencies.isPresent()) {
+                                List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
+                                Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
+
+                                while (adjacencyIterator.hasNext()) {
+                                    Adjacency adjacency = adjacencyIterator.next();
+                                    try {
+                                        if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
+                                            LOG.info("VPNInterfaceManager : Added Fib Entry rd {} prefix {} nextHop {} label {}",
+                                                    rd, adjacency.getIpAddress(), adjacency.getNextHopIpList(),
+                                                    adjacency.getLabel());
+//                                            vrf = new VrfEntryBuilder().set
+                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+                                                fibManager.handleRemoteRoute(true,
+                                                        new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId()),
+                                                        new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
+                                                        VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()),
+                                                        rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
+                                            }
+                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+                                                fibManager.populateFibOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
+                                            }
+                                        } else if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
+                                            LOG.info("VPNInterfaceManager : Removed Fib entry rd {} prefix {}",
+                                                    rd, adjacency.getIpAddress());
+                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+                                                fibManager.handleRemoteRoute(false, srcDpnId,
+                                                        new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
+                                                        vpnId, rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
+                                            }
+                                            if ((tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) &&
+                                                    (dcgwPresentStatus == VpnConstants.DCGWPresentStatus.Absent.getValue())) {                                                bgpManager.withdrawPrefix(rd, adjacency.getIpAddress());
+                                                fibManager.cleanUpDpnForVpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
+                                            }
+                                        }
+                                    } catch (Exception e) {
+                                        LOG.error("Exception when updating prefix {} in vrf {} to BGP",
+                                                adjacency.getIpAddress(), rd);
+                                    }
+                                }
+                            } else {
+                                LOG.trace("no adjacencies present for path {}.", path);
+                            }
+                        }
+                        // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
+                        //    fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
+                        // }
+                        // Go through all the VrfEntries and withdraw and readvertise the prefixes to BGP for which the nextHop is the SrcTepIp
+                        if ((action == UpdateRouteAction.ADVERTISE_ROUTE) &&
+                                (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
+                            List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(broker, rd);
+                            if (vrfEntries != null) {
+                                for (VrfEntry vrfEntry : vrfEntries) {
+                                    String destPrefix = vrfEntry.getDestPrefix().trim();
+                                    int vpnLabel = vrfEntry.getLabel().intValue();
+                                    List<String> nextHops = vrfEntry.getNextHopAddressList();
+                                    if (nextHops.contains(srcTepIp.trim())) {
+                                        bgpManager.withdrawPrefix(rd, destPrefix);
+                                        bgpManager.advertisePrefix(rd, destPrefix, nextHops, vpnLabel);
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        LOG.trace("dpnInVpn check failed for srcDpnId {}.", srcDpnId);
+                    }
+                } catch (Exception e) {
+                    LOG.error("updatePrefixesForDPN {} in vpn {} failed", 0, vpnInstance.getVpnInstanceName(), e);
+                }
+            }
+        } else {
+            LOG.trace("No vpn instances present.");
+        }
+    }
+}
index c5dd414f6c9c61265aaba08df7f5598e0e312924..53bb5b429d4866aeab52744dcffec1e7b94a1211 100644 (file)
@@ -10,17 +10,14 @@ package org.opendaylight.netvirt.vpnmanager;
 import com.google.common.base.*;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterators;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.*;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-
 import org.opendaylight.controller.md.sal.binding.api.*;
 import org.opendaylight.genius.mdsalutil.*;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
@@ -86,7 +83,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
@@ -150,9 +146,6 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     private DpnInVpnChangeListener dpnInVpnChangeListener;
     private NotificationPublishService notificationPublishService;
     private FibRpcService fibService;
-    protected enum UpdateRouteAction {
-        ADVERTISE_ROUTE, WITHDRAW_ROUTE
-    }
 
     /**
      * Responsible for listening to data change related to VPN Interface
@@ -172,7 +165,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         arpNotificationHandler = new ArpNotificationHandler(this, broker);
         vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
         dpnInVpnChangeListener = new DpnInVpnChangeListener(broker);
-        tunnelInterfaceStateListener = new TunnelInterfaceStateListener(broker, this);
+        tunnelInterfaceStateListener = new TunnelInterfaceStateListener(broker, bgpManager, fibManager);
         notificationService.registerNotificationListener(vpnSubnetRouteHandler);
         notificationService.registerNotificationListener(arpNotificationHandler);
         notificationService.registerNotificationListener(dpnInVpnChangeListener);
@@ -188,11 +181,6 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         interfaceListener.setIfaceMgrRpcService(ifMgrRpcService);
     }
 
-    public void setITMProvider(ItmRpcService itmProvider) {
-        this.itmProvider = itmProvider;
-    }
-
-
     public void setFibManager(IFibManager fibManager) {
         this.fibManager = fibManager;
     }
@@ -249,7 +237,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
                     getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
             opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                                                                   getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
+                    getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
             tunnelInterfaceStateListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
                     getTunnelInterfaceStateListenerPath(), tunnelInterfaceStateListener, DataChangeScope.SUBTREE);
         } catch (final Exception e) {
@@ -264,17 +252,17 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
         return InstanceIdentifier.create(InterfacesState.class)
-            .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
     }
 
     @Override
     public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
         LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
-        String interfaceName = key.getName();
+        final String interfaceName = key.getName();
 
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
-            InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+                InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
         if(interfaceState != null){
             try{
                 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
@@ -284,11 +272,26 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                         new Callable<List<ListenableFuture<Void>>>() {
                             @Override
                             public List<ListenableFuture<Void>> call() throws Exception {
-                                WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-                                processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeTxn);
-                                List<ListenableFuture<Void>> futures = new ArrayList<>();
-                                futures.add(writeTxn.submit());
-                                return futures;
+                                WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
+                                WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+                                processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeConfigTxn, writeOperTxn);
+                                CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                                try {
+                                    futures.get();
+                                } catch (InterruptedException | ExecutionException e) {
+                                    LOG.error("Error adding oper data for interface {} to vpn {} on dpn {}", interfaceName,
+                                            vpnInterface.getVpnInstanceName(), dpnId);
+                                    throw new RuntimeException(e.getMessage());
+                                }
+                                futures = writeConfigTxn.submit();
+                                try {
+                                    futures.get();
+                                } catch (InterruptedException | ExecutionException e) {
+                                    LOG.error("Error adding config data for interface {} to vpn {} on dpn {}", interfaceName,
+                                            vpnInterface.getVpnInstanceName(), dpnId);
+                                    throw new RuntimeException(e.getMessage());
+                                }
+                                return null;
                             }
                         });
             }catch (Exception e){
@@ -301,7 +304,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
-                                         final int lPortTag, boolean isInterfaceUp, WriteTransaction writeTxn) {
+                                         final int lPortTag, boolean isInterfaceUp,
+                                         WriteTransaction writeConfigTxn,
+                                         WriteTransaction writeOperTxn) {
 
         final String interfaceName = vpnInterface.getName();
         if (!isInterfaceUp) {
@@ -313,54 +318,50 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 return;
             }
             boolean waitForVpnInterfaceOpRemoval = false;
-            int numAdjs = 0;
-            VpnInterface opVpnInterface = null;
-            synchronized (interfaceName.intern()) {
-                opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName());
-                if (opVpnInterface != null ) {
-                    String opVpnName = opVpnInterface.getVpnInstanceName();
-                    String primaryInterfaceIp = null;
-                    if(opVpnName.equals(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
-                        // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
-                        List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(broker, interfaceName);
-                        if (adjs == null) {
-                            LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
-                            return;
-                        }
-                        numAdjs = adjs.size();
-                        for (Adjacency adj : adjs) {
-                            if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
-                                primaryInterfaceIp = adj.getIpAddress();
-                                break;
-                            }
-                        }
-                        if (primaryInterfaceIp == null) {
-                            LOG.info("VPN Interface {} addition failed as primary adjacency for this vpn interface could not be obtained", interfaceName);
-                            return;
+            VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName());
+            if (opVpnInterface != null ) {
+                String opVpnName = opVpnInterface.getVpnInstanceName();
+                String primaryInterfaceIp = null;
+                if(opVpnName.equals(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
+                    // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
+                    List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(broker, interfaceName);
+                    if (adjs == null) {
+                        LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
+                        return;
+                    }
+                    for (Adjacency adj : adjs) {
+                        if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
+                            primaryInterfaceIp = adj.getIpAddress();
+                            break;
                         }
-                        // Get the rd of the vpn instance
-                        String rd = getRouteDistinguisher(opVpnName);
-                        VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, primaryInterfaceIp);
-                            if (vrf != null) {
-                                LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
-                                return;
-                            }
-                        waitForVpnInterfaceOpRemoval = true;
-                    } else {
-                        LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
-                             interfaceName, vpnName, opVpnName);
                     }
+                    if (primaryInterfaceIp == null) {
+                        LOG.info("VPN Interface {} addition failed as primary adjacency "
+                                + "for this vpn interface could not be obtained", interfaceName);
+                        return;
+                    }
+                    // Get the rd of the vpn instance
+                    String rd = getRouteDistinguisher(opVpnName);
+                    VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, primaryInterfaceIp);
+                    if (vrf != null) {
+                        LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
+                        return;
+                    }
+                    waitForVpnInterfaceOpRemoval = true;
+                } else {
+                    LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
+                            interfaceName, vpnName, opVpnName);
                 }
-                if (!waitForVpnInterfaceOpRemoval) {
-                    // Add the VPNInterface and quit
-                    DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-                    dataStoreCoordinator.enqueueJob((interfaceName + dpId.toString()),
-                            new UpdateDpnToVpnWorker(dpId, vpnName, interfaceName, lPortTag, true));
-                    return;
-                }
+            }
+            if (!waitForVpnInterfaceOpRemoval) {
+                // Add the VPNInterface and quit
+                updateDpnDbs(dpId, vpnName, interfaceName, true /* add */);
+                bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn);
+                processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
+                return;
             }
 
             // FIB didn't get a chance yet to clean up this VPNInterface
@@ -385,104 +386,100 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 return;
             }
             // VPNInterface got removed, proceed with Add
-            synchronized (interfaceName.intern()) {
-                DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-                dataStoreCoordinator.enqueueJob((interfaceName + dpId.toString()),
-                        new UpdateDpnToVpnWorker(dpId, vpnName, interfaceName, lPortTag, true));
-            }
+            updateDpnDbs(dpId, vpnName, interfaceName, true /* add */);
+            bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn);
+            processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
         } else {
-            synchronized (interfaceName.intern()) {
-                // Interface is retained in the DPN, but its Link Up.
-                // Advertise prefixes again for this interface to BGP
-                advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
-                        vpnInterface, writeTxn);
-            }
-        }
-    }
-
-
-    private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
-        BigInteger dpnId;
-        String vpnName;
-        String interfaceName;
-        boolean addToDpn;
-        int lPortTag;
-
-        public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
-                                    int lPortTag, boolean addToDpn) {
-            this.dpnId= dpnId;
-            this.vpnName = vpnName;
-            this.interfaceName = interfaceName;
-            this.lPortTag = lPortTag;
-            this.addToDpn = addToDpn;
-        }
-
-        @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-            updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            futures.add(writeTxn.submit());
-            ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
-            Futures.addCallback(listenableFuture,
-                    new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
-            return futures;
-        }
-    }
-
-
-    /**
-     * JobCallback class is used as a future callback for
-     * main and rollback workers to handle success and failure.
-     */
-    private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
-        BigInteger dpnId;
-        String vpnName;
-        String interfaceName;
-        boolean addToDpn;
-        int lPortTag;
-
-        public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
-                                      int lPortTag, boolean addToDpn) {
-            this.dpnId= dpnId;
-            this.vpnName = vpnName;
-            this.interfaceName = interfaceName;
-            this.lPortTag = lPortTag;
-            this.addToDpn = addToDpn;
-        }
-
-        /**
-         * @param voids
-         * This implies that all the future instances have returned success. -- TODO: Confirm this
-         */
-        @Override
-        public void onSuccess(List<Void> voids) {
-            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-            bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
-            processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
-            writeTxn.submit();
-        }
-
-        /**
-         *
-         * @param throwable
-         * This method is used to handle failure callbacks.
-         * If more retry needed, the retrycount is decremented and mainworker is executed again.
-         * After retries completed, rollbackworker is executed.
-         * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
-         */
-
-        @Override
-        public void onFailure(Throwable throwable) {
-            LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
-        }
-    }
+            // Interface is retained in the DPN, but its Link Up.
+            // Advertise prefixes again for this interface to BGP
+            advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
+                    vpnInterface);
+        }
+    }
+
+
+//    private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
+//        BigInteger dpnId;
+//        String vpnName;
+//        String interfaceName;
+//        boolean addToDpn;
+//        int lPortTag;
+//
+//        public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
+//                                    int lPortTag, boolean addToDpn) {
+//            this.dpnId= dpnId;
+//            this.vpnName = vpnName;
+//            this.interfaceName = interfaceName;
+//            this.lPortTag = lPortTag;
+//            this.addToDpn = addToDpn;
+//        }
+//
+//        @Override
+//        public List<ListenableFuture<Void>> call() throws Exception {
+//            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+//            // to call the respective helpers.
+//            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+//            updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
+//            List<ListenableFuture<Void>> futures = new ArrayList<>();
+//            futures.add(writeTxn.submit());
+//            ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+//            Futures.addCallback(listenableFuture,
+//                    new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
+//            return futures;
+//        }
+//    }
+//
+//
+//    /**
+//     * JobCallback class is used as a future callback for
+//     * main and rollback workers to handle success and failure.
+//     */
+//    private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
+//        BigInteger dpnId;
+//        String vpnName;
+//        String interfaceName;
+//        boolean addToDpn;
+//        int lPortTag;
+//
+//        public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
+//                                      int lPortTag, boolean addToDpn) {
+//            this.dpnId= dpnId;
+//            this.vpnName = vpnName;
+//            this.interfaceName = interfaceName;
+//            this.lPortTag = lPortTag;
+//            this.addToDpn = addToDpn;
+//        }
+//
+//        /**
+//         * @param voids
+//         * This implies that all the future instances have returned success. -- TODO: Confirm this
+//         */
+//        @Override
+//        public void onSuccess(List<Void> voids) {
+//            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+//            bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
+//            processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
+//            writeTxn.submit();
+//        }
+//
+//        /**
+//         *
+//         * @param throwable
+//         * This method is used to handle failure callbacks.
+//         * If more retry needed, the retrycount is decremented and mainworker is executed again.
+//         * After retries completed, rollbackworker is executed.
+//         * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+//         */
+//
+//        @Override
+//        public void onFailure(Throwable throwable) {
+//            LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
+//        }
+//    }
 
 
     private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
-                                                 VpnInterface intf, WriteTransaction writeTxn) {
+                                                 VpnInterface intf) {
         //Read NextHops
         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
@@ -567,21 +564,21 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add, WriteTransaction writeTxn) {
+    private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
         long vpnId = VpnUtil.getVpnId(broker, vpnName);
         if (dpId == null) {
             dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
         }
         if(!dpId.equals(BigInteger.ZERO)) {
             if(add)
-                updateMappingDbs(vpnId, dpId, interfaceName, vpnName, writeTxn);
+                updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
             else
-                removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName, writeTxn);
+                removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
         }
     }
 
     private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag,
-                             WriteTransaction writeTxn) {
+                             WriteTransaction writeConfigTxn) {
         int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
 
@@ -592,100 +589,98 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
 
         BoundServices
-            serviceInfo =
-            InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
-                                            VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
-                                            VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
-        writeTxn.put(LogicalDatastoreType.CONFIGURATION,
+                serviceInfo =
+                InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
+                        VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
+                        VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
+        writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
                 InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo, true);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
-                vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeTxn);
+                vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeConfigTxn);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
-                vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeTxn);
+                vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeConfigTxn);
 
     }
 
     private void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
-                                                WriteTransaction writeTxn) {
+                                                WriteTransaction writeConfigTxn,
+                                                WriteTransaction writeOperTxn) {
         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+        // Read NextHops
+        InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+        Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
 
-        synchronized (interfaceName) {
-            // Read NextHops
-            InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
-            Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
-
-            if (adjacencies.isPresent()) {
-                List<Adjacency> nextHops = adjacencies.get().getAdjacency();
-                List<Adjacency> value = new ArrayList<>();
-
-                // Get the rd of the vpn instance
-                String rd = getRouteDistinguisher(vpnName);
+        if (adjacencies.isPresent()) {
+            List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+            List<Adjacency> value = new ArrayList<>();
 
-                String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
-                if (nextHopIp == null){
-                    LOG.error("NextHop for interface {} is null", interfaceName);
-                    return;
-                }
+            // Get the rd of the vpn instance
+            String rd = getRouteDistinguisher(vpnName);
 
-                List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
+            String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+            if (nextHopIp == null){
+                LOG.error("NextHop for interface {} is null", interfaceName);
+                return;
+            }
 
-                LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
-                for (Adjacency nextHop : nextHops) {
-                    String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
-                    long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
-                            VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
-                                    : rd, prefix));
-                    List<String> adjNextHop = nextHop.getNextHopIpList();
-                    value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
-                            (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
-                            .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
-
-                    if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
-                        LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
-                        writeTxn.merge(
-                                LogicalDatastoreType.OPERATIONAL,
-                                VpnUtil.getPrefixToInterfaceIdentifier(
-                                        VpnUtil.getVpnId(broker, vpnName), prefix),
-                                VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
-                    } else {
-                        //Extra route adjacency
-                        LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
-                        writeTxn.merge(
-                                LogicalDatastoreType.OPERATIONAL,
-                                VpnUtil.getVpnToExtrarouteIdentifier(
-                                        (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
-                                VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
-                    }
+            List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
+
+            LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
+            for (Adjacency nextHop : nextHops) {
+                String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
+                long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                        VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
+                                : rd, prefix));
+                List<String> adjNextHop = nextHop.getNextHopIpList();
+                value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
+                        (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
+                        .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+
+                if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
+                    LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
+                    writeOperTxn.merge(
+                            LogicalDatastoreType.OPERATIONAL,
+                            VpnUtil.getPrefixToInterfaceIdentifier(
+                                    VpnUtil.getVpnId(broker, vpnName), prefix),
+                            VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
+                } else {
+                    //Extra route adjacency
+                    LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
+                    writeOperTxn.merge(
+                            LogicalDatastoreType.OPERATIONAL,
+                            VpnUtil.getVpnToExtrarouteIdentifier(
+                                    (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
+                            VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
                 }
+            }
 
-                Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
+            Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
 
-                VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
-                InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
-                writeTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
-                long vpnId = VpnUtil.getVpnId(broker, vpnName);
+            VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
+            InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+            writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
+            long vpnId = VpnUtil.getVpnId(broker, vpnName);
 
-                for (Adjacency nextHop : aug.getAdjacency()) {
-                    long label = nextHop.getLabel();
-                    List<String> nextHopList = new ArrayList<>(nextHop.getNextHopIpList());
-                    if (rd != null) {
-
-                        addToLabelMapper(label, dpnId, nextHop.getIpAddress(), nextHopList, vpnId,
-                                interfaceName, null,false, rd);
-                        addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeTxn);
-                        //TODO: ERT - check for VPNs importing my route
-                        for (VpnInstance vpn : vpnsToImportRoute) {
-                            String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
-                            if (vpnRd != null) {
-                                LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
-                                VpnUtil.addFibEntryToDS(broker, vpnRd, nextHop.getIpAddress(), nextHopIp, (int) label, RouteOrigin.SELF_IMPORTED, writeTxn);
-                            }
+            for (Adjacency nextHop : aug.getAdjacency()) {
+                long label = nextHop.getLabel();
+                List<String> nextHopList = new ArrayList<>(nextHop.getNextHopIpList());
+                if (rd != null) {
+                    addToLabelMapper(label, dpnId, nextHop.getIpAddress(), nextHopList, vpnId,
+                            interfaceName, null,false, rd, writeOperTxn);
+                    addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeConfigTxn);
+                    //TODO: ERT - check for VPNs importing my route
+                    for (VpnInstance vpn : vpnsToImportRoute) {
+                        String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
+                        if (vpnRd != null) {
+                            LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
+                            fibManager.addOrUpdateFibEntry(broker, vpnRd, nextHop.getIpAddress(), Arrays.asList(nextHopIp), (int) label,
+                                    RouteOrigin.SELF_IMPORTED, writeConfigTxn);
                         }
-                    } else {
-                        // ### add FIB route directly
-                        VpnUtil.addFibEntryToDS(broker, vpnName, nextHop.getIpAddress(), nextHopIp,
-                                (int) label, RouteOrigin.STATIC, writeTxn);
                     }
+                } else {
+                    // ### add FIB route directly
+                    fibManager.addOrUpdateFibEntry(broker, vpnName, nextHop.getIpAddress(), Arrays.asList(nextHopIp),
+                            (int) label, RouteOrigin.STATIC, writeConfigTxn);
                 }
             }
         }
@@ -832,7 +827,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
-                             long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow, WriteTransaction writeTxn){
+                             long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow,
+                             WriteTransaction writeConfigTxn){
         List<MatchInfo> matches = new ArrayList<MatchInfo>();
         BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
@@ -856,11 +852,12 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
         // Install the flow entry in L3_INTERFACE_TABLE
         String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
-                    NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
+                NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
         FlowEntity flowEntity;
         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
                 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
                 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
+
         Flow flow = flowEntity.getFlowBuilder().build();
         String flowId = flowEntity.getFlowId();
         FlowKey flowKey = new FlowKey( new FlowId(flowId));
@@ -870,13 +867,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
                 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
 
-        if (writeTxn != null) {
+        if (writeConfigTxn != null) {
             if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
                 LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
-                writeTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
+                writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
             } else {
                 LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
-                writeTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+                writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
             }
         } else {
             if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
@@ -899,7 +896,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     private String getRouteDistinguisher(String vpnName) {
         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
-                                      .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+                .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
         Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
         String rd = "";
         if(vpnInstance.isPresent()) {
@@ -910,15 +907,15 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         return rd;
     }
 
-    private void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName,
-                                  WriteTransaction writeTxn) {
+    private void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
         String routeDistinguisher = getRouteDistinguisher(vpnName);
         String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
         synchronized (vpnName.intern()) {
+            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
             InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
             Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-            org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op
-                    .data.entry.vpn.to.dpn.list.VpnInterfaces
+            org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
+                    .entry.vpn.to.dpn.list.VpnInterfaces
                     vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
 
             if (dpnInVpn.isPresent()) {
@@ -968,33 +965,28 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id,
                             vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
                 }
-                /**
-                 * FIXME: DC Gateway tunnel should be built dynamically
-                 //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
-                 //if tunnel to DC GW does not exist, create it
-                 //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
-                 String dcGW = bgpManager.getDCGwIP();
-                 if(dcGW != null && !dcGW.isEmpty())
-                 {
-                 LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
-                 itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
-                 }*/
                 fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
                 publishAddNotification(dpnId, vpnName, rd);
                 //TODO: IRT - import local routes to vpn. check for the VPNs exporting the routes
                 //FIXME: do we need to handle here. since already routes are imported to this vpn
 
             }
+            CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+            try {
+                futures.get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
+                throw new RuntimeException(e.getMessage());
+            }
         }
     }
 
     void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
         List<VpnInstance> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
-        long vpnId = VpnUtil.getVpnId(broker, vpnName);
         for (VpnInstance vpn : vpnsToExportRoute) {
             String rd = vpn.getIpv4Family().getRouteDistinguisher();
-            long exportingVpnId = VpnUtil.getVpnId(broker, vpn.getVpnInstanceName());
             List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(broker, vpn.getIpv4Family().getRouteDistinguisher());
+            WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
             if (vrfEntries != null) {
                 for (VrfEntry vrfEntry : vrfEntries) {
                     try {
@@ -1008,35 +1000,36 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                         for (String nh : nextHops) {
                             if (route != null) {
                                 LOG.info("Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
-                                importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route);
+                                importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route, writeConfigTxn);
                             } else {
                                 LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
-                                VpnUtil.addFibEntryToDS(broker, vpnRd, prefix, nh, (int)label, RouteOrigin
-                                        .SELF_IMPORTED, null);
+                                fibManager.addOrUpdateFibEntry(broker, vpnRd, prefix, Arrays.asList(nh), (int)label,
+                                        RouteOrigin.SELF_IMPORTED, writeConfigTxn);
                             }
                         }
                     } catch (Exception e) {
                         LOG.error("Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} to vpn {}", vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpn.getVpnInstanceName(), vpnName);
                     }
                 }
+                writeConfigTxn.submit();
             } else {
                 LOG.info("No vrf entries to import from vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getIpv4Family().getRouteDistinguisher());
             }
         }
     }
 
-    private void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName,
-                                      WriteTransaction writeTxn) {
+    private void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
         //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
         synchronized (vpnName.intern()) {
             String rd = VpnUtil.getVpnRd(broker, vpnName);
             InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
             Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
             if (dpnInVpn.isPresent()) {
                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
                         .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
-                org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
-                        .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+                org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op
+                        .data.entry.vpn.to.dpn.list.VpnInterfaces
                         currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
 
                 if (vpnInterfaces.remove(currVpnInterface)) {
@@ -1056,9 +1049,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                             .setVpnInterfaces(vpnInterfaces);
 
                             if (writeTxn != null) {
-                                writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id , vpnToDpnList.build(), true);
+                                writeTxn.put(LogicalDatastoreType.OPERATIONAL, id , vpnToDpnList.build(), true);
                             } else {
-                                VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnList.build());
+                                VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnList.build());
                             }
 
                             InstanceIdentifier<VpnInstanceOpDataEntry> vpnInstOpDataId = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
@@ -1084,8 +1077,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     } else {
                         if (writeTxn != null) {
                             writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
-                                    org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op
-                                            .data
+                                    org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
                                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
                                     new VpnInterfacesKey(intfName)));
                         } else {
@@ -1097,14 +1089,20 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     }
                 }
             }
+            CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+            try {
+                futures.get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
+                throw new RuntimeException(e.getMessage());
+            }
         }
     }
 
-    private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeTxn) {
-
+    private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeConfigTxn) {
         try {
             LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
-            VpnUtil.addFibEntryToDS(broker, rd, prefix, nextHopIp, (int)label, RouteOrigin.STATIC, writeTxn);
+            fibManager.addOrUpdateFibEntry(broker, rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC, writeConfigTxn);
             bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
             LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
         } catch(Exception e) {
@@ -1124,10 +1122,10 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         final String interfaceName = key.getName();
 
         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
-        Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+        final Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
-            InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
-        if (existingVpnInterface.isPresent()){
+                InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+        if (optVpnInterface.isPresent()){
             BigInteger dpnId = BigInteger.ZERO;
             Boolean dpnIdRetrieved = Boolean.FALSE;
             if(interfaceState != null){
@@ -1141,9 +1139,10 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
                 return;
             }
+            final VpnInterface vpnOpInterface = optVpnInterface.get();
             if(dpnIdRetrieved == Boolean.FALSE){
                 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
-                dpnId = existingVpnInterface.get().getDpnId();
+                dpnId = vpnOpInterface.getDpnId();
             }
             final int ifIndex = interfaceState.getIfIndex();
             final BigInteger dpId = dpnId;
@@ -1152,56 +1151,66 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     new Callable<List<ListenableFuture<Void>>>() {
                         @Override
                         public List<ListenableFuture<Void>> call() throws Exception {
-                            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
-                            processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeTxn);
-                            List<ListenableFuture<Void>> futures = new ArrayList<>();
-                            futures.add(writeTxn.submit());
-                            waitForFibToRemoveVpnPrefix(interfaceName);
-                            return futures;
+                            WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
+                            WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+
+                            processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeConfigTxn, writeOperTxn);
+                            CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                            try {
+                                futures.get();
+                            } catch (InterruptedException | ExecutionException e) {
+                                LOG.error("Error removing interface {} from vpn {} on dpn {}", interfaceName,
+                                        vpnOpInterface.getVpnInstanceName(), dpId);
+                                throw new RuntimeException(e.getMessage());
+                            }
+                            futures = writeConfigTxn.submit();
+                            try {
+                                futures.get();
+                            } catch (InterruptedException | ExecutionException e) {
+                                LOG.error("Error removing interface {} from vpn {} on dpn {}", interfaceName,
+                                        vpnOpInterface.getVpnInstanceName(), dpId);
+                                throw new RuntimeException(e.getMessage());
+                            }
+                            return null;
                         }
                     });
-            //processVpnInterfaceDown(dpnId, interfaceName, interfaceState.getIfIndex(), false, true);
+
         }else{
             LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
         }
     }
 
     protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown,
-                                           boolean isConfigRemoval, WriteTransaction writeTxn) {
+                                           boolean isConfigRemoval, WriteTransaction writeConfigTxn, WriteTransaction writeOperTxn) {
         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         if (!isInterfaceStateDown) {
-            synchronized (interfaceName.intern()) {
-                VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
-                if(vpnInterface == null){
-                    LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
-                    return;
+            VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
+            if(vpnInterface == null){
+                LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
+                return;
+            }else{
+                final String vpnName = vpnInterface.getVpnInstanceName();
+                if(!vpnInterface.isScheduledForRemove()){
+                    VpnUtil.scheduleVpnInterfaceForRemoval(broker, interfaceName, dpId, vpnName, Boolean.TRUE, writeOperTxn);
+                    removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeConfigTxn);
+                    LOG.info("Unbinding vpn service from interface {} ", interfaceName);
+                    unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeConfigTxn);
                 }else{
-                    final String vpnName = vpnInterface.getVpnInstanceName();
-                    if(!vpnInterface.isScheduledForRemove()){
-                        VpnUtil.updateVpnInterface(broker, interfaceName, dpId, vpnName, Boolean.TRUE, writeTxn);
-                        removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeTxn);
-                        LOG.info("Unbinding vpn service from interface {} ", interfaceName);
-                        unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeTxn);
-                    }else{
-                        LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
-                        return;
-                    }
+                    LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
+                    return;
                 }
             }
         } else {
-                synchronized (interfaceName.intern()) {
-                    // Interface is retained in the DPN, but its Link Down.
-                    // Only withdraw the prefixes for this interface from BGP
-                    VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
-                    if(vpnInterface == null){
-                        LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
-                        return;
-                    }else {
-                        withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
-                    }
-                }
+            // Interface is retained in the DPN, but its Link Down.
+            // Only withdraw the prefixes for this interface from BGP
+            VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
+            if(vpnInterface == null){
+                LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
+                return;
+            }else {
+                withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
+            }
         }
-
     }
 
     private void waitForFibToRemoveVpnPrefix(String interfaceName) {
@@ -1223,7 +1232,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
-                                          WriteTransaction writeTxn) {
+                                          WriteTransaction writeConfigTxn) {
         //Read NextHops
         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
@@ -1256,18 +1265,18 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                         //this is an internal vpn - the rd is assigned to the vpn instance name;
                         //remove from FIB directly
                         for(String nh : nhList) {
-                            VpnUtil.removeFibEntryFromDS(broker, vpnName, nextHop.getIpAddress(), nh, writeTxn);
+                            fibManager.removeOrUpdateFibEntry(broker, vpnName, nextHop.getIpAddress(), nh, writeConfigTxn);
                         }
                     } else {
                         List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
                         for (String nh : nextHop.getNextHopIpList()) {
                             //IRT: remove routes from other vpns importing it
-                            removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeTxn);
+                            removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
                             for (VpnInstance vpn : vpnsToImportRoute) {
                                 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
                                 if (vpnRd != null) {
                                     LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
-                                    VpnUtil.removeFibEntryFromDS(broker, vpnRd, nextHop.getIpAddress(), nh, writeTxn);
+                                    fibManager.removeOrUpdateFibEntry(broker, vpnRd, nextHop.getIpAddress(), nh, writeConfigTxn);
                                 }
                             }
                         }
@@ -1288,25 +1297,24 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
                                int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
-                               WriteTransaction writeTxn) {
+                               WriteTransaction writeConfigTxn) {
         if (!isInterfaceStateDown && isConfigRemoval) {
-            writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
+            writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION,
                     InterfaceUtils.buildServiceId(vpnInterfaceName,
                             VpnConstants.L3VPN_SERVICE_IDENTIFIER));
         }
         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
-                vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeTxn);
+                vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeConfigTxn);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
-                vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeTxn);
+                vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeConfigTxn);
     }
 
 
-    private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeTxn) {
-        VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop, writeTxn);
+    private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeConfigTxn) {
         try {
             LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
-            VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop, writeTxn);
+            fibManager.removeOrUpdateFibEntry(broker, rd, prefix, nextHop, writeConfigTxn);
             bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
             LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
         } catch(Exception e) {
@@ -1331,6 +1339,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         //handles switching between <internal VPN - external VPN>
         if (!oldVpnName.equals(newVpnName)) {
             remove(identifier, original);
+            waitForFibToRemoveVpnPrefix(update.getName());
             add(identifier, update);
         }
         //handle both addition and removal of adjacencies
@@ -1350,7 +1359,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, PhysAddress targetMac,String srcInterface){
+    public void processArpRequest(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
+                                          .IpAddress srcIP, PhysAddress srcMac, org.opendaylight.yang.gen.v1.urn.ietf
+            .params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP, PhysAddress targetMac, String srcInterface){
         //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
         SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
                 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
@@ -1377,13 +1388,14 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         StringBuilder errorText = new StringBuilder();
         for(RpcError error : errors) {
             errorText.append(",").append(error.getErrorType()).append("-")
-                     .append(error.getMessage());
+                    .append(error.getMessage());
         }
         return errorText.toString();
     }
 
     private void addToLabelMapper(Long label, BigInteger dpnId, String prefix, List<String> nextHopIpList, Long vpnId,
-                                  String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd) {
+                                  String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd,
+                                  WriteTransaction writeOperTxn) {
         Preconditions.checkNotNull(label, "label cannot be null or empty!");
         Preconditions.checkNotNull(prefix, "prefix cannot be null or empty!");
         Preconditions.checkNotNull(vpnId, "vpnId cannot be null or empty!");
@@ -1413,7 +1425,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             }
             LabelRouteInfo lri = lriBuilder.build();
             LOG.trace("Adding route info to label map: {}", lri);
-            VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
+            if (writeOperTxn != null) {
+                writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, lriIid, lri, true);
+            } else {
+                VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
+            }
         } else {
             LOG.trace("Can't add entry to label map for lable {},dpnId is null", label);
         }
@@ -1421,18 +1437,17 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
                                                         long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
-
         SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
         RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
         VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
-                                                 .setLabel((long)label).setOrigin(origin.getValue())
-                                                 .addAugmentation(SubnetRoute.class, route).build();
+                .setLabel((long)label).setOrigin(origin.getValue())
+                .addAugmentation(SubnetRoute.class, route).build();
 
         LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
 
         //TODO: What should be parentVpnId? Get it from RD?
         long vpnId = VpnUtil.getVpnId(broker, vpnName);
-        addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd);
+        addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd, null);
         List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
 
         InstanceIdentifierBuilder<VrfTables> idBuilder =
@@ -1469,7 +1484,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
-                                                        SubnetRoute route) {
+                                                        SubnetRoute route, WriteTransaction writeConfigTxn) {
 
         RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
         VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
@@ -1482,30 +1497,23 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
                 setVrfEntry(vrfEntryList).build();
-        VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+        if (writeConfigTxn != null) {
+            writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
+        } else {
+            VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+        }
     }
 
     public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
-        VpnUtil.removeFibEntryFromDS(broker, rd, prefix, null /* nextHopToRemove */, null);
+        fibManager.removeOrUpdateFibEntry(broker, rd, prefix, null /* nextHopToRemove */, null);
         List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
         for (VpnInstance vpnInstance : vpnsToImportRoute) {
             String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
             LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
-            VpnUtil.removeFibEntryFromDS(broker, importingRd, prefix, null, null);
+            fibManager.removeOrUpdateFibEntry(broker, importingRd, prefix, null /* nextHopToRemove */, null);
         }
     }
 
-    public synchronized void removeVrfFromDS(String rd) {
-        LOG.debug("Removing vrf table for rd {}", rd);
-
-        InstanceIdentifierBuilder<VrfTables> idBuilder =
-                InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
-        InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
-
-        VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
-
-    }
-
     protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
 
         Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
@@ -1528,19 +1536,18 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 adjacencies = new ArrayList<>();
             }
 
-
             adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIpList(adj.getNextHopIpList())
                     .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+
             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
+
             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
             for (String nh : adj.getNextHopIpList()) {
                 addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
-                              currVpnIntf.getName());
+                        currVpnIntf.getName());
             }
-
         }
-
     }
 
     protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
@@ -1565,14 +1572,14 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
                             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
                             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
-                                                                              currVpnIntf.getVpnInstanceName(),
-                                                                              aug, dpnId, currVpnIntf.isScheduledForRemove());
+                                    currVpnIntf.getVpnInstanceName(),
+                                    aug, dpnId, currVpnIntf.isScheduledForRemove());
 
                             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
 
                             for (String nh : adj.getNextHopIpList()) {
                                 delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
-                                              currVpnIntf.getName());
+                                        currVpnIntf.getName());
                             }
                             break;
                         }
@@ -1589,10 +1596,10 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
         //add extra route to vpn mapping; advertise with nexthop as tunnel ip
         VpnUtil.syncUpdate(
-            broker,
-            LogicalDatastoreType.OPERATIONAL,
-            VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
-            VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
+                broker,
+                LogicalDatastoreType.OPERATIONAL,
+                VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
+                VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
 
         BigInteger dpnId = null;
         if (intfName != null && !intfName.isEmpty()) {
@@ -1600,14 +1607,14 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
             if (nextHopIp == null || nextHopIp.isEmpty()) {
                 LOG.error("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
-                          intfName, destination);
+                        intfName, destination);
                 return;
             }
             nextHop = nextHopIp;
         }
         List<String> nextHopIpList = Arrays.asList(nextHop);
         addToLabelMapper((long)label, dpnId, destination, nextHopIpList, VpnUtil.getVpnId(broker, routerID),
-                intfName, null, false, rd);
+                intfName, null, false, rd, null);
 
         // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
         // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
@@ -1620,19 +1627,19 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             // This is like leaking one of the Vpn2 routes towards Vpn1
             boolean nexthopIsVpn2 = ( interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nextHop) );
             String srcVpnUuid = (nexthopIsVpn2) ? interVpnLink.getSecondEndpoint().getVpnUuid().getValue()
-                                                : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
+                    : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
             String dstVpnUuid = (nexthopIsVpn2) ? interVpnLink.getFirstEndpoint().getVpnUuid().getValue()
-                                                : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
+                    : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
             String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
             long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
-                                                VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
+                    VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
             VpnUtil.leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
         } else {
             if (rd != null) {
                 addPrefixToBGP(rd, destination, nextHop, label, null);
             } else {
                 // ### add FIB route directly
-                VpnUtil.addFibEntryToDS(broker, routerID, destination, nextHop, label, RouteOrigin.STATIC, null);
+                fibManager.addOrUpdateFibEntry(broker, routerID, destination, Arrays.asList(nextHop), label, RouteOrigin.STATIC, null);
             }
         }
     }
@@ -1652,27 +1659,54 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             removePrefixFromBGP(rd, destination, nextHop, null);
         } else {
             // ### add FIB route directly
-            VpnUtil.removeFibEntryFromDS(broker, routerID, destination, nextHop, null);
+            fibManager.removeOrUpdateFibEntry(broker, routerID, destination, nextHop, null);
         }
     }
 
-    class VpnInterfaceOpListener extends AbstractDataChangeListener<VpnInterface> {
+    class VpnInterfaceOpListener extends org.opendaylight.genius.mdsalutil.AbstractDataChangeListener<VpnInterface> {
 
         public VpnInterfaceOpListener() {
             super(VpnInterface.class);
         }
 
         @Override
-        protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
+        protected void remove(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface del) {
+            final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+            final String interfaceName = key.getName();
+            final String vpnName = del.getVpnInstanceName();
+            DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+            dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
+                    new Callable<List<ListenableFuture<Void>>>() {
+                        @Override
+                        public List<ListenableFuture<Void>> call() throws Exception {
+                            WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+                            postProcessVpnInterfaceRemoval(identifier, del, writeOperTxn);
+                            CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
+                            try {
+                                futures.get();
+                            } catch (InterruptedException | ExecutionException e) {
+                                LOG.error("Error handling removal of oper data for interface {} from vpn {}", interfaceName,
+                                        vpnName);
+                                throw new RuntimeException(e.getMessage());
+                            }
+                            return null;
+                        }
+                    });
+        }
+
+        private void postProcessVpnInterfaceRemoval(InstanceIdentifier<VpnInterface> identifier, VpnInterface del,
+                                                    WriteTransaction writeOperTxn) {
             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
             String interfaceName = key.getName();
             String vpnName = del.getVpnInstanceName();
 
             LOG.trace("VpnInterfaceOpListener removed: interface name {} vpnName {}", interfaceName, vpnName);
             //decrement the vpn interface count in Vpn Instance Op Data
-            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
+                    .vpn.id.VpnInstance>
                     id = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
-            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+                    .VpnInstance> vpnInstance
                     = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
 
             if (vpnInstance.isPresent()) {
@@ -1698,19 +1732,22 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     if (prefixToInterface.isEmpty()) {
                         for (String nh : adjacency.getNextHopIpList()) {
                             prefix = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
-                                     VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
-                                                                           VpnUtil.getIpPrefix(nh)));
+                                    VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+                                            VpnUtil.getIpPrefix(nh)));
                             if (prefix.isPresent())
                                 prefixToInterface.add(prefix.get());
                         }
                     }
                     for (Prefixes pref : prefixToInterface) {
-                        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                                       VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
-                                       VpnUtil.DEFAULT_CALLBACK);
-                        synchronized (interfaceName.intern()) {
-                            updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false, null);
+                        if (writeOperTxn != null) {
+                            writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL,
+                                    VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()));
+                        } else {
+                            VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                                    VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
+                                    VpnUtil.DEFAULT_CALLBACK);
                         }
+                        updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false /* delete */);
                     }
                 }
             } else {
@@ -1729,19 +1766,39 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
 
         @Override
-        protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
+        protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
+                              final VpnInterface update) {
             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
-            String interfaceName = key.getName();
+            final String interfaceName = key.getName();
 
             if (original.getVpnInstanceName().equals(update.getVpnInstanceName())) {
                 return;
             }
 
+            final String vpnName = update.getVpnInstanceName();
+            DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+            dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
+                    new Callable<List<ListenableFuture<Void>>>() {
+                        @Override
+                        public List<ListenableFuture<Void>> call() throws Exception {
+                            postProcessVpnInterfaceUpdate(identifier, original, update);
+                            return null;
+                        }
+                    });
+        }
+
+        private void postProcessVpnInterfaceUpdate(InstanceIdentifier<VpnInterface> identifier, VpnInterface original,
+                                                   VpnInterface update) {
+            final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+            String interfaceName = key.getName();
+
             //increment the vpn interface count in Vpn Instance Op Data
             VpnInstanceOpDataEntry vpnInstOp = null;
-            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
+                    .vpn.id.VpnInstance>
                     origId = VpnUtil.getVpnInstanceToVpnIdIdentifier(original.getVpnInstanceName());
-            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> origVpnInstance
+            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+                    .VpnInstance> origVpnInstance
                     = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, origId);
 
             if (origVpnInstance.isPresent()) {
@@ -1763,17 +1820,15 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     } else {
                         for (String adj : adjacency.getNextHopIpList()) {
                             prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
-                                          VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
-                                          VpnUtil.getIpPrefix(adj)));
+                                    VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+                                            VpnUtil.getIpPrefix(adj)));
                             if (prefixToInterface.isPresent()) {
                                 prefixToInterfaceList.add(prefixToInterface.get());
                             }
                         }
                     }
-                    synchronized (interfaceName.intern()) {
-                        for (Prefixes prefix : prefixToInterfaceList) {
-                            updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false, null);
-                        }
+                    for (Prefixes prefix : prefixToInterfaceList) {
+                        updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false /* delete */);
                     }
                 }
             }
@@ -1782,171 +1837,6 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
         @Override
         protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
-
-        }
-    }
-
-    protected void handlePrefixesForDPNs(StateTunnelList stateTunnelList, UpdateRouteAction action) {
-        BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
-        BigInteger destDpnId;
-        String srcTepIp =  String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
-        String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
-
-        InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
-        InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
-        Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
-        long tunTypeVal = 0, vpnId;
-
-        if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
-        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
-        } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class){
-            tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
-        } else {
-            tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
-        }
-        LOG.trace("tunTypeVal is {}", tunTypeVal);
-        long dcgwPresentStatus = VpnConstants.DCGWPresentStatus.Invalid.getValue();
-        if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-            Future<RpcResult<IsDcgwPresentOutput>> result;
-            try {
-                result = itmProvider.isDcgwPresent(new IsDcgwPresentInputBuilder()
-                        .setDcgwIp(destTepIp)
-                        .build());
-                RpcResult<IsDcgwPresentOutput> rpcResult = result.get();
-                if (!rpcResult.isSuccessful()) {
-                    LOG.warn("RPC Call to isDcgwPresent {} returned with Errors {}", destTepIp, rpcResult.getErrors());
-                } else {
-                    dcgwPresentStatus = rpcResult.getResult().getRetVal();
-                }
-            } catch (Exception e) {
-                LOG.warn("Exception {} when querying for isDcgwPresent {}, trace {}", e, destTepIp, e.getStackTrace());
-            }
-        }
-
-        if (vpnInstances.isPresent()) {
-            List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
-            Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
-            LOG.trace("vpnInstIter {}", vpnInstIter);
-            while (vpnInstIter.hasNext()) {
-                VpnInstance vpnInstance = vpnInstIter.next();
-                LOG.trace("vpnInstance {}", vpnInstance);
-                vpnId = VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName());
-                try {
-                    VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
-                    LOG.trace("vpnConfig {}", vpnConfig);
-                    String rd = vpnConfig.getRouteDistinguisher();
-                    if (rd == null || rd.isEmpty()) {
-                        rd = vpnInstance.getVpnInstanceName();
-                        LOG.trace("rd is null or empty. Assigning VpnInstanceName to rd {}", rd);
-                    }
-                    InstanceIdentifier<VpnToDpnList> srcId =
-                        VpnUtil.getVpnToDpnListIdentifier(rd, srcDpnId);
-                    Optional<VpnToDpnList> srcDpnInVpn =
-                            VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, srcId);
-                    if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                        destDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
-                        InstanceIdentifier<VpnToDpnList> destId =
-                                VpnUtil.getVpnToDpnListIdentifier(rd, destDpnId);
-                        Optional<VpnToDpnList> destDpnInVpn =
-                                VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, destId);
-                        if (!(srcDpnInVpn.isPresent() &&
-                                destDpnInVpn.isPresent())) {
-                            LOG.trace(" srcDpn {} - destDPN {}, do not share the VPN {} with rd {}.",
-                                    srcDpnId, destDpnId, vpnInstance.getVpnInstanceName(), rd);
-                            continue;
-                        }
-                    }
-                    if (srcDpnInVpn.isPresent()) {
-                        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
-                                .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
-                            vpnInterfaces = srcDpnInVpn.get().getVpnInterfaces();
-                        for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
-                                .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
-                            InstanceIdentifier<VpnInterface> vpnIntfId =
-                                VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
-                            LOG.trace("vpnInterface {}", vpnInterface);
-                            InstanceIdentifier<Adjacencies> path =
-                                vpnIntfId.augmentation(Adjacencies.class);
-                            Optional<Adjacencies> adjacencies =
-                                VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
-                            LOG.trace("adjacencies {}", adjacencies);
-                            if (adjacencies.isPresent()) {
-                                List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
-                                Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
-
-                                while (adjacencyIterator.hasNext()) {
-                                    Adjacency adjacency = adjacencyIterator.next();
-                                    try {
-                                        if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
-                                            LOG.info("VPNInterfaceManager : Added Fib Entry rd {} prefix {} nextHop {} label {}",
-                                                     rd, adjacency.getIpAddress(), adjacency.getNextHopIpList(),
-                                                     adjacency.getLabel());
-//                                            vrf = new VrfEntryBuilder().set
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                                                fibManager.handleRemoteRoute(true,
-                                                        new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId()),
-                                                        new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
-                                                        VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()),
-                                                        rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
-                                            }
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-                                                fibManager.populateFibOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
-                                            }
-                                        }
-                                        else if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
-                                            LOG.info("VPNInterfaceManager : Removed Fib entry rd {} prefix {}",
-                                                     rd, adjacency.getIpAddress());
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                                                fibManager.handleRemoteRoute(false, srcDpnId,
-                                                                new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
-                                                                vpnId, rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
-                                            }
-                                            if ((tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) &&
-                                                    (dcgwPresentStatus == VpnConstants.DCGWPresentStatus.Absent.getValue())) {
-                                                bgpManager.withdrawPrefix(rd, adjacency.getIpAddress());
-                                                fibManager.cleanUpDpnForVpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
-                                            }
-                                        }
-                                    } catch (Exception e) {
-                                        LOG.error("Exception when updating prefix {} in vrf {} to BGP",
-                                            adjacency.getIpAddress(), rd);
-                                    }
-                                }
-                            } else {
-                                LOG.trace("no adjacencies present for path {}.", path);
-                            }
-
-                        }
-                        // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
-                        //    fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
-                        // }
-                        // Go through all the VrfEntries and withdraw and readvertise the prefixes to BGP for which the nextHop is the SrcTepIp
-                        if ((action == UpdateRouteAction.ADVERTISE_ROUTE) &&
-                                (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
-                            List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(broker, rd);
-                            if (vrfEntries != null) {
-                                for (VrfEntry vrfEntry : vrfEntries) {
-                                    String destPrefix = vrfEntry.getDestPrefix().trim();
-                                    int vpnLabel = vrfEntry.getLabel().intValue();
-                                    List<String> nextHops = vrfEntry.getNextHopAddressList();
-                                    if (nextHops.contains(srcTepIp.trim())) {
-                                        bgpManager.withdrawPrefix(rd, destPrefix);
-                                        bgpManager.advertisePrefix(rd, destPrefix, nextHops, vpnLabel);
-                                    }
-                                }
-                            }
-                        }
-                    } else {
-                        LOG.trace("dpnInVpn check failed for srcDpnId {}.", srcDpnId);
-                    }
-                } catch (Exception e) {
-                    LOG.error("updatePrefixesForDPN {} in vpn {} failed", 0, vpnInstance.getVpnInstanceName(), e);
-                }
-            }
-        } else {
-            LOG.trace("No vpn instances present.");
         }
     }
 
@@ -1988,16 +1878,16 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
         return InstanceIdentifier.builder(NeutronRouterDpns.class)
-            .child(RouterDpnList.class, new RouterDpnListKey(routerName))
-            .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
+                .child(RouterDpnList.class, new RouterDpnListKey(routerName))
+                .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
     }
 
     InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
         return InstanceIdentifier.builder(NeutronRouterDpns.class)
-            .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
+                .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
     }
 
-    protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeTxn) {
+    protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
         BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
         if(dpId.equals(BigInteger.ZERO)) {
             LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
@@ -2009,7 +1899,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 .OPERATIONAL, routerDpnListIdentifier);
         RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
         if (optionalRouterDpnList.isPresent()) {
-            writeTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+            writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
                     RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
         } else {
             RouterDpnListBuilder builder = new RouterDpnListBuilder();
@@ -2018,13 +1908,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             List<RouterInterfaces> routerInterfaces =  new ArrayList<>();
             routerInterfaces.add(routerInterface);
             builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
-            writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+            writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
                     getRouterId(routerName),
-                    new RouterDpnListBuilder().setRouterId(routerName).build(), true);
+                    builder.build(), true);
         }
     }
 
-    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeTxn) {
+    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
         BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
         if(dpId.equals(BigInteger.ZERO)) {
             LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
@@ -2039,14 +1929,14 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
                 if (routerInterfaces.isEmpty()) {
-                    if (writeTxn != null) {
-                        writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+                    if (writeOperTxn != null) {
+                        writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
                     } else {
                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
                     }
                 } else {
-                    if (writeTxn != null) {
-                        writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+                    if (writeOperTxn != null) {
+                        writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
                                 RouterInterfaces.class,
                                 new RouterInterfacesKey(vpnInterfaceName)));
                     } else {
@@ -2059,7 +1949,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId, WriteTransaction writeTxn) {
+    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
+                                                  WriteTransaction writeOperTxn) {
         if(dpId.equals(BigInteger.ZERO)) {
             LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
             return;
@@ -2072,9 +1963,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
                 if (routerInterfaces.isEmpty()) {
-                    writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+                    writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
                 } else {
-                    writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+                    writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
                             RouterInterfaces.class,
                             new RouterInterfacesKey(vpnInterfaceName)));
                 }
@@ -2082,7 +1973,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    public void addMIPAdjacency(String vpnName,String vpnInterface, IpAddress prefix){
+    public void addMIPAdjacency(String vpnName,String vpnInterface, org.opendaylight.yang.gen.v1.urn.ietf.params.xml
+            .ns.yang.ietf.inet.types.rev130715.IpAddress prefix){
 
         LOG.trace("Adding {} adjacency to VPN Interface {} ",prefix,vpnInterface);
         InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
@@ -2122,7 +2014,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     }
 
-    public void removeMIPAdjacency(String vpnName, String vpnInterface, IpAddress prefix) {
+    public void removeMIPAdjacency(String vpnName, String vpnInterface, org.opendaylight.yang.gen.v1.urn.ietf.params
+            .xml.ns.yang.ietf.inet.types.rev130715.IpAddress prefix) {
         String ip = VpnUtil.getIpPrefix(prefix.getIpv4Address().getValue());
         LOG.trace("Removing {} adjacency from Old VPN Interface {} ",ip,vpnInterface);
         InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
@@ -2138,47 +2031,4 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             LOG.trace("Successfully Deleted Adjacency into VpnInterface {}", vpnInterface);
         }
     }
-
-    class TunnelInterfaceStateListener extends AbstractDataChangeListener<StateTunnelList>  {
-        public TunnelInterfaceStateListener(final DataBroker db, VpnInterfaceManager vpnIfMgr) {
-            super(StateTunnelList.class);
-        }
-
-
-        @Override
-        protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
-            LOG.trace("Tunnel deletion---- {}", del);
-            handlePrefixesForDPNs(del, UpdateRouteAction.WITHDRAW_ROUTE);
-        }
-
-        @Override
-        protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original, StateTunnelList update) {
-            LOG.trace("Tunnel updation---- {}", update);
-            LOG.trace("ITM Tunnel {} of type {} state event changed from :{} to :{}",
-                    update.getTunnelInterfaceName(),
-                    fibManager.getTransportTypeStr(update.getTransportType().toString()),
-                    original.isTunnelState(), update.isTunnelState());
-                //withdraw all prefixes in all vpns for this dpn
-            boolean isTunnelUp = update.isTunnelState();
-                handlePrefixesForDPNs(update,isTunnelUp ?  UpdateRouteAction.ADVERTISE_ROUTE :
-                                                            UpdateRouteAction.WITHDRAW_ROUTE);
-        }
-
-        @Override
-        protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
-            LOG.trace("Tunnel addition---- {}", add);
-
-            if(!add.isTunnelState()) {
-                LOG.trace(  "Tunnel {} is not yet UP.",
-                            add.getTunnelInterfaceName());
-                return;
-            } else {
-                LOG.trace("ITM Tunnel ,type {} ,State is UP b/w src: {} and dest: {}",
-                        fibManager.getTransportTypeStr(add.getTransportType().toString()),
-                        add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
-                handlePrefixesForDPNs(add, UpdateRouteAction.ADVERTISE_ROUTE);
-            }
-        }
-    }
-
 }
index d34b3fed03d13c8d2c9b5c145843a758649c82e4..f2a2a234ad543a76fc92441365ff22fa6dd28b74 100644 (file)
@@ -168,33 +168,31 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                             }
                         }
                     }
-                    //currentIntfCount = vpnOpEntry.getVpnInterfaceCount();
                     if ((currentIntfCount == 0) || (currentIntfCount >= intfCount)) {
                         // Either the FibManager completed its job to cleanup all vpnInterfaces in VPN
                         // OR
                         // There is no progress by FibManager in removing all the interfaces even after good time!
                         // In either case, let us quit and take our chances.
                         //TODO(vpnteam): L3VPN refactoring to take care of this case.
-                        if (retryCount > 0) {
-                            retryCount--;
-                            LOG.info("Retrying clearing vpn with vpnname {} rd {} since currentIntfCount {} ", vpnName, rd, currentIntfCount);
-                            if (currentIntfCount > 0L){
-                                LOG.info("Current interface count for vpn {} and rd {} is not zero and so retrying ...", vpnName, rd);
-                                intfCount = currentIntfCount;
+                        if ((dpnToVpns == null) || dpnToVpns.size() <= 0) {
+                            LOG.info("VPN Instance vpn {} rd {} ready for removal, exiting wait loop", vpnName, rd);
+                            break;
+                        } else {
+                            if (retryCount > 0) {
+                                retryCount--;
+                                LOG.info("Retrying clearing vpn with vpnname {} rd {} since current interface count {} ", vpnName, rd, currentIntfCount);
+                                if (currentIntfCount > 0) {
+                                    intfCount = currentIntfCount;
+                                } else {
+                                    LOG.info("Current interface count is zero, but instance Op for vpn {} and rd {} not cleared yet. Waiting for 5 more seconds.", vpnName, rd);
+                                    intfCount = 1L;
+                                }
                             } else {
-                                LOG.info("Current interface count is zero but instance Op for vpn {} and rd {} not cleared yet. Waiting for 5 more seconds.", vpnName, rd);
-                                intfCount = 1L;
+                                LOG.info("VPNInstance bailing out of wait loop as current interface count is {} and max retries exceeded for for vpnName {}, rd {}",
+                                        currentIntfCount, vpnName, rd);
+                                break;
                             }
-                        } else {
-                            LOG.info("VPNInstance bailing out of wait loop as currentIntfCount is {} and max retries exceeded for for rd {}, vpnname {}",
-                                    currentIntfCount, rd, vpnName);
-                            break;
                         }
-                    } else {
-                        // There is some progress by FibManager, so let us give it some more time!
-                        intfCount = currentIntfCount;
-                        retryCount = 1;
-                        LOG.info("current interface count {} for vpn {} and rd {} showing progress, waiting for it to drive to 0.", currentIntfCount, vpnName, rd);
                     }
                 } else {
                     // There is no VPNOPEntry.  Something else happened on the system !
index 5bada7e936698ea2a412f9bb4fcaddde294a46ed..980352a7b0ee4d05773cb032524affea7e726c3d 100644 (file)
@@ -9,7 +9,8 @@ package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.util.concurrent.SettableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
@@ -21,6 +22,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.concurrent.Future;
 
@@ -30,11 +32,13 @@ public class VpnRpcServiceImpl implements VpnRpcService {
     private IdManagerService idManager;
     private VpnInterfaceManager vpnInterfaceMgr;
     private DataBroker dataBroker;
+    private IFibManager fibManager;
 
     public VpnRpcServiceImpl(IdManagerService idManager, VpnInterfaceManager vpnIfaceMgr, DataBroker dataBroker) {
         this.idManager = idManager;
         this.vpnInterfaceMgr = vpnIfaceMgr;
         this.dataBroker = dataBroker;
+        this.fibManager = fibManager;
     }
 
     /**
@@ -136,7 +140,7 @@ public class VpnRpcServiceImpl implements VpnRpcService {
         InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
         if ( interVpnLink != null ) {
             // A static route pointing to an InterVpnLink endpoint: just write the VrfEntry
-            VpnUtil.addFibEntryToDS(dataBroker, vpnRd, destination, nexthop, label.intValue(), RouteOrigin.STATIC , null);
+            fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, destination, Arrays.asList(nexthop), label.intValue(), RouteOrigin.STATIC, null);
         } else {
             vpnInterfaceMgr.addExtraRoute(destination, nexthop, vpnRd, null /*routerId */, label.intValue(),
                                           null /* intfName */);
@@ -193,7 +197,7 @@ public class VpnRpcServiceImpl implements VpnRpcService {
         InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
         if ( interVpnLink != null ) {
             // A static route pointing to an InterVpnLink endpoint: just remove the VrfEntry from DS
-            VpnUtil.removeFibEntryFromDS(dataBroker,  vpnRd, destination, nexthop, null);
+            fibManager.removeOrUpdateFibEntry(dataBroker,  vpnRd, destination, nexthop, null);
         } else {
             vpnInterfaceMgr.delExtraRoute(destination, nexthop, vpnRd, null /*routerId*/, null /*intfName*/);
         }
index 295c8a9df78526b71b53ea2c8007d00df0d29833..02141cf8dfc60115b0cfc082d0a5139e61116f54 100644 (file)
@@ -29,7 +29,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
@@ -467,126 +467,12 @@ public class VpnUtil {
         return rd;
     }
 
-    /**
-     * Writes in MDSAL a new VrfEntry for a VPN specified by its Route-Distinguisher. It performs a merge,
-     * that is, if the VrfEntry exists the nexthop is added the VrfEntry nexthop list. If the entry does not
-     * exist, it is created.
-     *
-     * @param broker dataBroker service reference
-     * @param rd Route-distinguisher of the VPN
-     * @param prefix Destination of the route. This, together with the RD, identifies the VrfEntry
-     * @param nextHop Nexthop of the route
-     * @param label Label of the route
-     */
-    public static void addFibEntryToDS(DataBroker broker, String rd, String prefix, String nextHop, int label,
-                                       RouteOrigin origin,
-                                       WriteTransaction writeTxn) {
-        Preconditions.checkNotNull(rd, "RD cannot be null");
-        VrfEntry vrfEntry = null;
-
-        LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
-        synchronized (rd.intern()) {
-            InstanceIdentifier<VrfTables> vrfTableId =
-                    InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
-            vrfEntry = getVrfEntry(broker, rd, prefix);
-            if (vrfEntry != null) {
-                List<String> nextHopList = vrfEntry.getNextHopAddressList();
-                nextHopList.add(nextHop);
-                VrfEntryBuilder builder = new VrfEntryBuilder(vrfEntry).setNextHopAddressList(nextHopList);
-                VrfEntry newVrfEntry = builder.build();
-                // Just update the VrfEntry
-                if (writeTxn != null) {
-                    writeTxn.merge(LogicalDatastoreType.CONFIGURATION,
-                            vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry, true);
-                } else {
-                    VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
-                            vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry);
-                }
-            } else {
-                List<VrfEntry> currentVrfEntries = new ArrayList<VrfEntry>();
-                VrfEntryBuilder builder = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
-                        .setLabel((long) label).setOrigin(origin.getValue());
-                vrfEntry = builder.build();
-                currentVrfEntries.add(vrfEntry);
-                VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(
-                        currentVrfEntries).build();
-                if (writeTxn != null) {
-                    writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
-                } else {
-                    VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
-                }
-            }
-            LOG.info("ADD: Added Fib Entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHop, label);
-        }
-
-    }
-
-    /**
-     * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
-     * last one in the VrfEntry, then the VrfEntry is removed too.
-     *
-     * @param broker dataBroker service reference
-     * @param rd Route-Distinguisher to which the VrfEntry belongs to
-     * @param prefix Destination of the route
-     * @param nextHopToRemove Specific nexthop within the Route to be removed.
-     *           If null or empty, then the whole VrfEntry is removed
-     */
-    public static void removeFibEntryFromDS(DataBroker broker, String rd, String prefix, String nextHopToRemove,
-                                            WriteTransaction writeTxn) {
-
-        LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
-
-        // Looking for existing prefix in MDSAL database
-        InstanceIdentifier<VrfEntry> vrfEntryId =
-            InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
-                                                        .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
-        Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-
-        if ( entry.isPresent() ) {
-            synchronized (rd.intern()) {
-                List<String> nhListRead = new ArrayList<>();
-                if ( nextHopToRemove != null && !nextHopToRemove.isEmpty()) {
-                    nhListRead = entry.get().getNextHopAddressList();
-                    if (nhListRead.contains(nextHopToRemove)) {
-                        nhListRead.remove(nextHopToRemove);
-                    }
-                }
-
-                if (nhListRead.isEmpty()) {
-                    // Remove the whole entry
-                    if (writeTxn != null) {
-                        writeTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-                    } else {
-                        MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-                    }
-                    LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
-                } else {
-                    // An update must be done, not including the current next hop
-                    VrfEntry vrfEntry =
-                            new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
-                                    .setKey(new VrfEntryKey(prefix)).build();
-                    if (writeTxn != null) {
-                        writeTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-                        writeTxn.put(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
-                    } else {
-                        MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-                        MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
-                    }
-                    LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
-                }
-            }
-        } else {
-            LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
-        }
-    }
-
-
     /**
      * Remove from MDSAL all those VrfEntries in a VPN that have an specific RouteOrigin
      *
      * @param broker dataBroker service reference
      * @param rd     Route Distinguisher
-     * @param origin Origin of the Routes to be removed (see {@link org.opendaylight.netvirt.bgpmanager.api.RouteOrigin})
+     * @param origin Origin of the Routes to be removed (see {@link RouteOrigin})
      */
     public static void removeVrfEntriesByOrigin(DataBroker broker, String rd, RouteOrigin origin) {
         InstanceIdentifier<VrfTables> vpnVrfTableIid =
@@ -1332,14 +1218,17 @@ public class VpnUtil {
         return result;
     }
 
-    public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId,
-                                          String vpnInstanceName, Boolean isScheduledToRemove,
-                                          WriteTransaction writeTxn){
+    public static void scheduleVpnInterfaceForRemoval(DataBroker broker,String interfaceName, BigInteger dpnId,
+                                                      String vpnInstanceName, Boolean isScheduledToRemove,
+                                                      WriteTransaction writeOperTxn){
         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         VpnInterface interfaceToUpdate = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName)).setName(interfaceName)
                 .setDpnId(dpnId).setVpnInstanceName(vpnInstanceName).setScheduledForRemove(isScheduledToRemove).build();
-        writeTxn.merge(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate, true);
-        //VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
+        if (writeOperTxn != null) {
+            writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate, true);
+        } else {
+            VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
+        }
     }
 
     protected static void createVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
index 38642878c9a74b918425ad56dac206785d107fd0..cf685590bed7164a796903839599e95c18304a7e 100644 (file)
@@ -62,6 +62,7 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager, Au
     private InterVpnLinkListener interVpnLinkListener;
     private DataBroker dataBroker;
     private InterVpnLinkNodeListener interVpnLinkNodeListener;
+    private TunnelInterfaceStateListener tunIntfStateListener;
 
 
     @Override
@@ -72,9 +73,10 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager, Au
             vpnManager = new VpnManager(dataBroker, bgpManager);
             vpnManager.setIdManager(idManager);
             vpnInterfaceManager = new VpnInterfaceManager(dataBroker, bgpManager, notificationService);
+            tunIntfStateListener = new TunnelInterfaceStateListener(dataBroker, bgpManager, fibManager);
             vpnInterfaceManager.setMdsalManager(mdsalManager);
             vpnInterfaceManager.setIfaceMgrRpcService(odlInterfaceRpcService);
-            vpnInterfaceManager.setITMProvider(itmProvider);
+            tunIntfStateListener.setITMProvider(itmProvider);
             vpnInterfaceManager.setIdManager(idManager);
             vpnInterfaceManager.setArpManager(arpManager);
             vpnInterfaceManager.setNeutronvpnManager(neuService);
index a41480542d8218ab23457180bc2de448a61ebfd7..47afcad74eecba137b0d5bdeaf02da225a3bc54b 100644 (file)
@@ -24,7 +24,7 @@ import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
-import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;