Multiple fixes in various modules 83/42383/2
authorSuraj Ranjan <suraj.ranjan@ericsson.com>
Sat, 23 Jul 2016 07:19:44 +0000 (12:49 +0530)
committerSam Hague <shague@redhat.com>
Sat, 23 Jul 2016 13:17:27 +0000 (13:17 +0000)
This review includes following fixes or changes:

1> BGPManager using the batching infrastructure
to batch and apply VRFEntries to Config DS.
(both bgp advertisement and bgp withdrawals).

2> FibManager using the batching infrastructure
to batch and apply flow rules to Inventory Config DS.

3> VPN Refactoring - Concurrency for VPNInterfaceManager

4> Changed the code in dhcpservice such that we add only
direct and macvtap vnic_type to the neutron port cache.

5> Fix for bgp display commands to work in COMCLI

Change-Id: Ib0c0e8515f61e299fa49ef3d432232ce4f3313d7
Signed-off-by: Suraj Ranjan <suraj.ranjan@ericsson.com>
25 files changed:
vpnservice/bgpmanager/bgpmanager-impl/pom.xml
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpConfigurationManager.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/BgpVrfBatchHandler.java [new file with mode: 0644]
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/VtyshCli.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/oam/BgpCounters.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/thrift/client/BgpRouter.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/thrift/server/BgpThriftService.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpNeutronPortListener.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManager.java
vpnservice/fibmanager/fibmanager-impl/src/test/java/org/opendaylight/netvirt/fibmanager/test/FibManagerTest.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/DpnInVpnListener.java [deleted file]
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatServiceProvider.java
vpnservice/vpnmanager/vpnmanager-api/src/main/yang/odl-l3vpn.yang
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/DpnInVpnChangeListener.java [new file with mode: 0644]
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/RouterInterfaceListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetRouteInterfaceStateChangeListener.java [new file with mode: 0644]
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnConstants.java
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/VpnSubnetRouteHandler.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/test/java/org/opendaylight/netvirt/vpnmanager/test/VpnSubnetRouteHandlerTest.java

index be5d5442548abfff3a5b9b6e8c45ba6999d14f98..e66c6740a18b54a9c167bb981a922a8771252636 100644 (file)
@@ -30,6 +30,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>bgpmanager-api</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.genius</groupId>
+      <artifactId>mdsalutil-api</artifactId>
+      <version>${genius.version}</version>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>model-bgp</artifactId>
index 234797e4438addc462d6682db9842a2adcdbb6f3..ac3f086f71a16802efa9f375e7e0ced73c418bf7 100644 (file)
@@ -230,6 +230,15 @@ public class BgpConfigurationManager {
         initer.countDown();
 
         bgpConfigurationManager = this;
+        BgpUtil.batchSize = BgpUtil.BATCH_SIZE;
+        if (Integer.getInteger("batch.size") != null) {
+            BgpUtil.batchSize = Integer.getInteger("batch.size");
+        }
+        BgpUtil.batchInterval = BgpUtil.PERIODICITY;
+        if (Integer.getInteger("batch.wait.time") != null) {
+            BgpUtil.batchInterval = Integer.getInteger("batch.wait.time");
+        }
+        BgpUtil.registerWithBatchManager(new BgpVrfBatchHandler());
     }
 
     boolean ignoreClusterDcnEventForFollower() {
@@ -365,7 +374,7 @@ public class BgpConfigurationManager {
 
         protected synchronized void
         add(InstanceIdentifier<AsId> iid, AsId val) {
-            LOG.error("received bgp add asid");
+            LOG.error("received bgp add asid {}",val);
             if (ignoreClusterDcnEventForFollower()) {
                 return;
             }
index 63250e1f261d2af4ec0d0c6061b1ab1d6dea9feb..bca33c6300e862bbce6b9777e362652f8ea89636 100644 (file)
@@ -16,6 +16,10 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.opendaylight.controller.md.sal.binding.api.*;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.*;
+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.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -34,9 +38,15 @@ public class BgpUtil {
     private static final Logger LOG = LoggerFactory.getLogger(BgpUtil.class);
     private static DataBroker  dataBroker;
     private static BindingTransactionChain fibTransact;
+    public static final int PERIODICITY = 500;
     private static AtomicInteger pendingWrTransaction = new AtomicInteger(0);
+    public static final int BATCH_SIZE = 1000;
+    public static Integer batchSize;
+    public static Integer batchInterval;
     private static int txChainAttempts = 0;
 
+    private static BlockingQueue<ActionableResource> bgpRoutesBufferQ = new LinkedBlockingQueue<>();
+
     // return number of pending Write Transactions with BGP-Util (no read)
     public static int getGetPendingWrTransaction() {
         return pendingWrTransaction.get();
@@ -52,83 +62,36 @@ public class BgpUtil {
         return fibTransact;
     }
 
+    static void registerWithBatchManager(ResourceHandler resourceHandler) {
+        ResourceBatchingManager resBatchingManager = ResourceBatchingManager.getInstance();
+        resBatchingManager.registerBatchableResource("BGP-VRFENTRY", bgpRoutesBufferQ, resourceHandler);
+    }
+
     static <T extends DataObject> void update(DataBroker broker, final LogicalDatastoreType datastoreType,
                                               final InstanceIdentifier<T> path, final T data) {
-        threadPool.submit(new MdsalDsTask<>(datastoreType, path, data, TransactionType.UPDATE));
+        ActionableResource actResource = new ActionableResourceImpl(path.toString());
+        actResource.setAction(ActionableResource.UPDATE);
+        actResource.setInstanceIdentifier(path);
+        actResource.setInstance(data);
+        bgpRoutesBufferQ.add(actResource);
     }
 
-
     public static <T extends DataObject> void write(DataBroker broker, final LogicalDatastoreType datastoreType,
                                                     final InstanceIdentifier<T> path, final T data) {
-        threadPool.submit(new MdsalDsTask<>(datastoreType, path, data, TransactionType.WRITE));
+        ActionableResource actResource = new ActionableResourceImpl(path.toString());
+        actResource.setAction(ActionableResource.CREATE);
+        actResource.setInstanceIdentifier(path);
+        actResource.setInstance(data);
+        bgpRoutesBufferQ.add(actResource);
     }
 
     static <T extends DataObject> void delete(DataBroker broker, final LogicalDatastoreType datastoreType,
                                               final InstanceIdentifier<T> path) {
-        threadPool.submit(new MdsalDsTask<>(datastoreType, path, null, TransactionType.DELETE));
-    }
-
-    static enum TransactionType {
-        WRITE, UPDATE, DELETE;
-    }
-
-    static  class MdsalDsTask<T extends DataObject> implements Runnable {
-        LogicalDatastoreType datastoreType;
-        InstanceIdentifier<T> path;
-        T data;
-        TransactionType type;
-
-        public MdsalDsTask(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data, TransactionType type) {
-            this.datastoreType = datastoreType;
-            this.path = path;
-            this.data = data;
-            this.type = type;
-        }
-
-        @Override
-        public void run() {
-            try {
-                LOG.trace("BgpUtil MDSAL task started ");
-                WriteTransaction tx = getTransactionChain().newWriteOnlyTransaction();
-                switch (type) {
-                    case WRITE:
-                        tx.put(datastoreType, path, data, true);
-                        break;
-                    case UPDATE:
-                        tx.merge(datastoreType, path, data, true);
-                        break;
-                    case DELETE:
-                        tx.delete(datastoreType, path);
-                        break;
-                    default:
-                        LOG.error("Invalid Transaction type: {}", type);
-                }
-                pendingWrTransaction.incrementAndGet();
-                addFutureCallback(tx, path, data);
-                LOG.trace("Transaction type: {} submitted", type);
-            } catch (final Exception e) {
-                LOG.error("TxChain transaction submission failed, re-init TxChain", e);
-                initTransactionChain();
-            }
-        }
-    }
-
-
-    static  <T extends DataObject> void addFutureCallback(WriteTransaction tx, final InstanceIdentifier<T> path,
-                                                          final T data) {
-        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(final Void result) {
-                pendingWrTransaction.decrementAndGet();
-                LOG.trace("DataStore entry success data:{} path:{} ", path);
-            }
-
-            @Override
-            public void onFailure(final Throwable t) {
-                pendingWrTransaction.decrementAndGet();
-                LOG.error("DataStore  entry failed data:{} path:{} cause:{} , retry initTransactionChain", data, path, t.getCause());
-           }
-        });
+        ActionableResource actResource = new ActionableResourceImpl(path.toString());
+        actResource.setAction(ActionableResource.DELETE);
+        actResource.setInstanceIdentifier(path);
+        actResource.setInstance(null);
+        bgpRoutesBufferQ.add(actResource);
     }
 
 
diff --git a/vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpVrfBatchHandler.java b/vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpVrfBatchHandler.java
new file mode 100644 (file)
index 0000000..d9f5ee1
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.bgpmanager;
+
+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.genius.utils.batching.ResourceHandler;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class BgpVrfBatchHandler implements ResourceHandler {
+
+    public void update(WriteTransaction tx, LogicalDatastoreType datastoreType,
+                       final InstanceIdentifier identifier, final Object original, final Object update) {
+        if ((update != null) && !(update instanceof DataObject)) {
+            return;
+        }
+        if (datastoreType != getDatastoreType()) {
+            return;
+        }
+        tx.merge(datastoreType, identifier, (DataObject) update, true);
+    }
+
+    public void create(WriteTransaction tx, final LogicalDatastoreType datastoreType,
+                       final InstanceIdentifier identifier, final Object data) {
+        if ((data != null) && !(data instanceof DataObject)) {
+            return;
+        }
+        if (datastoreType != getDatastoreType()) {
+            return;
+        }
+        tx.put(datastoreType, identifier, (DataObject) data, true);
+    }
+
+    public void delete(WriteTransaction tx, final LogicalDatastoreType datastoreType,
+                       final InstanceIdentifier identifier, final Object data) {
+        if ((data != null) && !(data instanceof DataObject)) {
+            return;
+        }
+        if (datastoreType != getDatastoreType()) {
+            return;
+        }
+        tx.delete(datastoreType, identifier);
+    }
+
+    public DataBroker getResourceBroker() {
+        return BgpUtil.getBroker();
+    }
+
+    public int getBatchSize() {
+        return BgpUtil.batchSize;
+    }
+
+    public int getBatchInterval() {
+        return BgpUtil.batchInterval;
+    }
+
+    public LogicalDatastoreType getDatastoreType() {
+        return LogicalDatastoreType.CONFIGURATION;
+    }
+}
+
index b1fc2da563e0b823b04b6b8ea026c85840d6c6bc..7e59e65296eada99ee32b5a2fb18a88c4c72bbd8 100644 (file)
@@ -126,7 +126,7 @@ public class VtyshCli extends OsgiCommandSupport {
         StringBuilder sb = new StringBuilder();
         int ip = 0, ret;
         StringBuilder temp, temp2;
-        char ch, gt = '>';
+        char ch, gt = '>', hashChar = '#';
 
         inputBgpCmd.append("show " + cmd);
 
@@ -187,8 +187,12 @@ public class VtyshCli extends OsgiCommandSupport {
                 socket.close();
                 return;
             }
-            if (ip == (int) gt) {
-                sb.append(gt);
+            if ((ip == (int) gt) || (ip == (int) hashChar)) {
+                if (ip == (int) gt) {
+                    sb.append(gt);
+                } else {
+                    sb.append(hashChar);
+                }
                 break;
             } else if (ip == -1) {
                 System.out.println(sb.toString());
@@ -215,7 +219,7 @@ public class VtyshCli extends OsgiCommandSupport {
                 socket.close();
                 return;
             }
-            if (ip == (int) gt) {
+            if ((ip == (int) gt) || (ip == (int) hashChar)) {
                 break;
             } else if (ip == -1) {
                 System.out.println(sb.toString());
index 75c157099bf6234d3cbac12e57189289fabdc419..019b7d73ee25d1bd06dd4be9ea172b8653f5dd8c 100644 (file)
@@ -157,7 +157,7 @@ public class BgpCounters extends TimerTask {
                 socket.close();
                 return;
             }
-            if (ip == (int)gt) {
+            if (ip == (int)gt || ip == (int)hash) {
                 break;
             } else if (ip == -1) {
                 LOGGER.error(sb.toString());
index 3311f0350ed45d700f3426b46f370772198ceee4..857023afa00887a4502fc8d1e6498aac61ba2dac 100644 (file)
@@ -73,6 +73,7 @@ public class BgpRouter {
         public int[] ints;
         public List<String> irts;
         public List<String> erts;
+        public long asNumber;
         public static final int ignore = 0;
         public BgpOp() {
             strs = new String[3];
@@ -140,8 +141,10 @@ public class BgpRouter {
         switch (op.type) {
             case START:
                 setStartTS(System.currentTimeMillis());
+                LOGGER.debug("startBgp thrift call for AsId {}",op.asNumber);
                 result = bgpClient.startBgp(op.ints[0], op.strs[0],
                         op.ignore, op.ignore, op.ignore, op.ints[1], op.add);
+                LOGGER.debug("Result of startBgp thrift call for AsId {} : {}",op.asNumber,result);
                 startBGPresult = result;
                 break;
             case STOP:
index c22376a60f596ae3dd8e91e353803187123820df..1d16d2dde9eac5357524453732a9f9e38a46494a 100644 (file)
@@ -116,6 +116,7 @@ public class BgpThriftService {
 
         public void onUpdatePushRoute(String rd, String prefix, int plen, String nexthop, int label) {
             try {
+                LOGGER.debug("Update on push route : rd {} prefix {} plen {}",rd,prefix,plen);
                 BgpConfigurationManager.onUpdatePushRoute(rd, prefix, plen, nexthop, label);
             } catch (Throwable e) {
                 LOGGER.error("failed to handle update route ", e);
index a32da0be59b229ce0701a646a0bf8810a4a8cdca..6e830e6cf9e1baba746f48776bd546530bf43592 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataCh
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 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.neutron.binding.rev150712.PortBindingExtension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
@@ -61,24 +62,23 @@ public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBas
     @Override
     protected void remove(InstanceIdentifier<Port> identifier, Port del) {
         LOG.trace("Port removed: {}", del);
-        if(NeutronUtils.isPortVnicTypeNormal(del)) {
-            return;
+        if(isVnicTypeDirectOrMacVtap(del)) {
+            removePort(del);
         }
-        removePort(del);
     }
 
     @Override
     protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
         LOG.trace("Port changed to {}", update);
-        if (NeutronUtils.isPortVnicTypeNormal(update)) {
+        if (!isVnicTypeDirectOrMacVtap(update)) {
             LOG.trace("Port updated is normal {}", update.getUuid());
-            if (!NeutronUtils.isPortVnicTypeNormal(original)) {
-                LOG.trace("Original Port was direct {} so removing flows and cache entry if any", update.getUuid());
+            if (isVnicTypeDirectOrMacVtap(original)) {
+                LOG.trace("Original Port was direct/macvtap {} so removing flows and cache entry if any", update.getUuid());
                 removePort(original);
             }
             return;
         }
-        if (NeutronUtils.isPortVnicTypeNormal(original)) {
+        if (!isVnicTypeDirectOrMacVtap((original))) {
             LOG.trace("Original port was normal and updated is direct. Calling addPort()");
             addPort(update);
             return;
@@ -98,7 +98,7 @@ public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBas
     @Override
     protected void add(InstanceIdentifier<Port> identifier, Port add) {
         LOG.trace("Port added {}", add);
-        if(NeutronUtils.isPortVnicTypeNormal(add)) {
+        if(!isVnicTypeDirectOrMacVtap(add)) {
             LOG.trace("Port is normal {}", add.getUuid());
             return;
         }
@@ -142,4 +142,14 @@ public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBas
         String macAddress = port.getMacAddress().getValue();
         return macAddress;
     }
+
+    private boolean isVnicTypeDirectOrMacVtap(Port port) {
+        PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
+        if(portBinding == null || portBinding.getVnicType() == null) {
+            // By default, VNIC_TYPE is NORMAL
+            return false;
+        }
+        String vnicType = portBinding.getVnicType().trim().toLowerCase();
+        return (vnicType.equals("direct") || vnicType.equals("macvtap"));
+    }
 }
index 3276d85dcf1c87679c092a881432739dc7ef370a..1eadba9c914b2ee290aeb6d5303c21c976ed93f0 100644 (file)
@@ -15,12 +15,10 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.Callable;
+import java.util.concurrent.*;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -30,6 +28,10 @@ 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.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.vpnmanager.api.IVpnManager;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
@@ -113,7 +115,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class FibManager extends AbstractDataChangeListener<VrfEntry> implements AutoCloseable{
+public class FibManager extends AbstractDataChangeListener<VrfEntry> implements AutoCloseable, ResourceHandler {
   private static final Logger LOG = LoggerFactory.getLogger(FibManager.class);
   private static final String FLOWID_PREFIX = "L3.";
   private ListenerRegistration<DataChangeListener> listenerRegistration;
@@ -133,11 +135,30 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   private static final BigInteger CLEAR_METADATA = BigInteger.valueOf(0);
   public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
 
+    private static final int PERIODICITY = 500;
+    private static Integer batchSize;
+    private static Integer batchInterval;
+
+    private static final int BATCH_SIZE = 1000;
+
+    private static BlockingQueue<ActionableResource> vrfEntryBufferQ = new LinkedBlockingQueue<>();
+    private ResourceBatchingManager resourceBatchingManager;
+
 
   public FibManager(final DataBroker db) {
-    super(VrfEntry.class);
-    broker = db;
-    registerListener(db);
+      super(VrfEntry.class);
+      broker = db;
+      registerListener(db);
+      batchSize = Integer.getInteger("batch.size");
+      if (batchSize == null) {
+          batchSize = BATCH_SIZE;
+      }
+      batchInterval = Integer.getInteger("batch.wait.time");
+      if (batchInterval == null) {
+          batchInterval = PERIODICITY;
+      }
+      resourceBatchingManager = ResourceBatchingManager.getInstance();
+      resourceBatchingManager.registerBatchableResource("FIB-VRFENTRY",vrfEntryBufferQ, this);
   }
 
   @Override
@@ -195,6 +216,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
   }
 
+  public DataBroker getResourceBroker() {
+      return broker;
+  }
 
   @Override
   protected void add(final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
@@ -202,10 +226,18 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
       String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
       LOG.info("ADD: Adding Fib Entry rd {} prefix {} nexthop {} label {}",
                rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
-      createFibEntries(identifier, vrfEntry);
+      if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+          createFibEntries(identifier, vrfEntry);
+      } else {
+          ActionableResource actResource = new ActionableResourceImpl(rd.toString() + vrfEntry.getDestPrefix());
+          actResource.setAction(ActionableResource.CREATE);
+          actResource.setInstanceIdentifier(identifier);
+          actResource.setInstance(vrfEntry);
+          vrfEntryBufferQ.add(actResource);
+          leakRouteIfNeeded(identifier, vrfEntry, NwConstants.ADD_FLOW);
+      }
       LOG.info("ADD: Added Fib Entry rd {} prefix {} nexthop {} label {}",
                rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
-      leakRouteIfNeeded(identifier, vrfEntry, NwConstants.ADD_FLOW);
   }
 
   @Override
@@ -214,7 +246,16 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
     LOG.info("REMOVE: Removing Fib Entry rd {} prefix {} nexthop {} label {}",
              rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
-    deleteFibEntries(identifier, vrfEntry);
+    if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+        deleteFibEntries(identifier, vrfEntry);
+    } else {
+        ActionableResource actResource = new ActionableResourceImpl(rd.toString() + vrfEntry.getDestPrefix());
+        actResource.setAction(ActionableResource.DELETE);
+        actResource.setInstanceIdentifier(identifier);
+        actResource.setInstance(vrfEntry);
+        vrfEntryBufferQ.add(actResource);
+        leakRouteIfNeeded(identifier, vrfEntry, NwConstants.DEL_FLOW);
+    }
     LOG.info("REMOVE: Removed Fib Entry rd {} prefix {} nexthop {} label {}",
              rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
     leakRouteIfNeeded(identifier, vrfEntry, NwConstants.DEL_FLOW);
@@ -223,16 +264,54 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   @Override
   protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
     Preconditions.checkNotNull(update, "VrfEntry should not be null or empty.");
-    if (original.getAugmentation(SubnetRoute.class) != null && update.getAugmentation(SubnetRoute.class) == null)
-        return;
     String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
     LOG.info("UPDATE: Updating Fib Entries to rd {} prefix {} nexthop {} label {}",
              rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
-    createFibEntries(identifier, update);
+    if (RouteOrigin.value(update.getOrigin()) != RouteOrigin.BGP) {
+        createFibEntries(identifier, update);
+    } else {
+        ActionableResource actResource = new ActionableResourceImpl(rd.toString() + update.getDestPrefix());
+        actResource.setAction(ActionableResource.UPDATE);
+        actResource.setInstanceIdentifier(identifier);
+        actResource.setInstance(update);
+        actResource.setOldInstance(original);
+        vrfEntryBufferQ.add(actResource);
+    }
     LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} nexthop {} label {}",
              rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
   }
 
+  public void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object vrfEntry) {
+      if (vrfEntry instanceof VrfEntry) {
+          createFibEntries(tx, identifier, (VrfEntry)vrfEntry);
+      }
+  }
+
+  public void delete(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object vrfEntry) {
+      if (vrfEntry instanceof VrfEntry) {
+          deleteFibEntries(tx, identifier, (VrfEntry) vrfEntry);
+      }
+  }
+
+  public void update(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object original,
+                     Object update) {
+      if ((original instanceof VrfEntry) && (update instanceof VrfEntry)) {
+          createFibEntries(tx, identifier, (VrfEntry)update);
+      }
+  }
+
+  public int getBatchSize() {
+      return batchSize;
+  }
+
+  public int getBatchInterval() {
+      return batchInterval;
+  }
+
+  public LogicalDatastoreType getDatastoreType() {
+      return LogicalDatastoreType.CONFIGURATION;
+  }
+
   private void createFibEntries(final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry) {
       final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
 
@@ -256,7 +335,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                           public List<ListenableFuture<Void>> call() throws Exception {
                               WriteTransaction tx = broker.newWriteOnlyTransaction();
                               for (final VpnToDpnList curDpn : vpnToDpnList) {
-                                  installSubnetRouteInFib(curDpn.getDpnId(),elanTag, rd, vpnId.longValue(), vrfEntry, tx);
+                                  if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+                                      installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd, vpnId.longValue(), vrfEntry, tx);
+                                  }
                               }
                               List<ListenableFuture<Void>> futures = new ArrayList<>();
                               futures.add(tx.submit());
@@ -284,7 +365,9 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                           WriteTransaction tx = broker.newWriteOnlyTransaction();
                           for (VpnToDpnList vpnDpn : vpnToDpnList) {
                               if ( !localDpnIdList.contains(vpnDpn.getDpnId())) {
-                                  createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                  if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+                                      createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                  }
                               }
                           }
                           List<ListenableFuture<Void>> futures = new ArrayList<>();
@@ -308,6 +391,30 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
       }
   }
 
+
+  /*
+    Please note that the following createFibEntries will be invoked only for BGP Imported Routes.
+    The invocation of the following method is via create() callback from the MDSAL Batching Infrastructure
+    provided by ResourceBatchingManager
+   */
+  private void createFibEntries(WriteTransaction writeTx, final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry) {
+      final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
+
+      final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+      Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
+      Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + " has null vpnId!");
+
+      final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+      final String rd = vrfTableKey.getRouteDistinguisher();
+      if (vpnToDpnList != null) {
+          for (VpnToDpnList vpnDpn : vpnToDpnList) {
+              if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+                  createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, writeTx);
+              }
+          }
+      }
+  }
+
     /*
      * Returns true if the specified nexthop is the other endpoint in an
      * InterVpnLink, regarding one of the VPN's point of view.
@@ -663,15 +770,6 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
         }
     }
 
-    private Collection<BigInteger> getDpnsForVpn(VpnInstanceOpDataEntry vpnInstance) {
-        Collection<BigInteger> dpns = new HashSet<>();
-        for(VpnToDpnList dpn : vpnInstance.getVpnToDpnList()) {
-            dpns.add(dpn.getDpnId());
-        }
-
-      return dpns;
-  }
-
   private List<BigInteger> createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
     List<BigInteger> returnLocalDpnId = new ArrayList<BigInteger>();
     Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
@@ -881,7 +979,6 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
      */
   public List<BigInteger> deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
       List<BigInteger> returnLocalDpnId = new ArrayList<>();
-      BigInteger localDpnId = BigInteger.ZERO;
       VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
       String localNextHopIP = vrfEntry.getDestPrefix();
 
@@ -1267,13 +1364,25 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
                         if (localDpnIdList.size() <= 0) {
                             for (VpnToDpnList curDpn : vpnToDpnList) {
-                                deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
+                                    if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+                                        deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                    }
+                                } else {
+                                    deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                }
                             }
                         } else {
                             for (BigInteger localDpnId : localDpnIdList) {
                                 for (VpnToDpnList curDpn : vpnToDpnList) {
                                     if (!curDpn.getDpnId().equals(localDpnId)) {
-                                        deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                        if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
+                                            if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+                                                deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                            }
+                                        } else {
+                                            deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+                                        }
                                     }
                                 }
                             }
@@ -1309,6 +1418,30 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
   }
 
+  /*
+    Please note that the following deleteFibEntries will be invoked only for BGP Imported Routes.
+    The invocation of the following method is via delete() callback from the MDSAL Batching Infrastructure
+    provided by ResourceBatchingManager
+   */
+  private void deleteFibEntries(WriteTransaction writeTx, final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
+      final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
+
+      final String rd  = vrfTableKey.getRouteDistinguisher();
+      final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+      if (vpnInstance == null) {
+          LOG.debug("VPN Instance for rd {} is not available from VPN Op Instance Datastore", rd);
+          return;
+      }
+      final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+      if (vpnToDpnList != null) {
+          for (VpnToDpnList curDpn : vpnToDpnList) {
+              if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+                  deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, writeTx);
+              }
+          }
+      }
+  }
+
   public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
                                 final long vpnId, final VrfTablesKey vrfTableKey,
                                 final VrfEntry vrfEntry, WriteTransaction tx) {
@@ -1779,17 +1912,21 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   protected List<String> resolveAdjacency(final BigInteger remoteDpnId, final long vpnId, final VrfEntry vrfEntry,
                                           String rd) {
     List<String> adjacencyList = new ArrayList<>();
+    List<String> prefixIpList = new ArrayList<>();
     LOG.trace("resolveAdjacency called with remotedpid {}, vpnId{}, VrfEntry {}", remoteDpnId, vpnId, vrfEntry);
     try {
-        Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
-        List<String> prefixIpList;
-        if (extra_route == null) {
-            prefixIpList = Arrays.asList(vrfEntry.getDestPrefix());
-        } else {
-            prefixIpList = new ArrayList<>();
-            for (String extraRouteIp : extra_route.getNexthopIpList()) {
-                prefixIpList.add(extraRouteIp + "/32");
+        if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+            Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+            if (extra_route == null) {
+                prefixIpList = Arrays.asList(vrfEntry.getDestPrefix());
+            } else {
+                prefixIpList = new ArrayList<>();
+                for (String extraRouteIp : extra_route.getNexthopIpList()) {
+                    prefixIpList.add(extraRouteIp + "/32");
+                }
             }
+        } else {
+            prefixIpList = Arrays.asList(vrfEntry.getDestPrefix());
         }
 
         for (String prefixIp : prefixIpList) {
index 4a4b099af9b4f5aaf2fa50fdcc89efc5ddd406a7..94bbea795d741b431e4fbcd6c6858a58ae63e273 100644 (file)
@@ -83,6 +83,7 @@ public class FibManagerTest {
   BigInteger Dpn;
   private static final long vpnId = 101L;
   private static final long vpnIntfCnt = 2;
+  private static final Boolean isCleanupComplete = Boolean.FALSE;
 
   private void SetupMocks() {
     Dpn = BigInteger.valueOf(100000L);
@@ -130,6 +131,9 @@ public class FibManagerTest {
           @Override
           public Long getVpnInterfaceCount() { return vpnIntfCnt; }
 
+          @Override
+          public Long getActiveDpnCount () {return 0L;}
+
           @Override
           public List<VpnToDpnList> getVpnToDpnList() {
             List <VpnToDpnList> vpnToDpnLists =  new ArrayList<>();
@@ -152,6 +156,9 @@ public class FibManagerTest {
                 return new VpnToDpnListKey(Dpn);
               }
 
+              @Override
+              public VpnToDpnList.DpnState getDpnState () { return VpnToDpnList.DpnState.Active;}
+
               @Override
               public <E extends Augmentation<VpnToDpnList>> E getAugmentation(
                       Class<E> augmentationType) {
diff --git a/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/DpnInVpnListener.java b/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/DpnInVpnListener.java
deleted file mode 100644 (file)
index 8c81aac..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * 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.natservice.internal;
-
-import java.math.BigInteger;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DpnInVpnListener implements OdlL3vpnListener {
-    private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnListener.class);
-    private DataBroker dataBroker;
-    private SNATDefaultRouteProgrammer defaultRouteProgrammer;
-    private NaptSwitchHA naptSwitchHA;
-    private IMdsalApiManager mdsalManager;
-    private IdManagerService idManager;
-
-    public DpnInVpnListener(DataBroker dataBroker) {
-        this.dataBroker = dataBroker;
-    }
-
-    void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
-        this.defaultRouteProgrammer = defaultRouteProgrammer;
-    }
-
-    void setNaptSwitchHA(NaptSwitchHA switchHA) {
-        naptSwitchHA = switchHA;
-    }
-
-    void setMdsalManager(IMdsalApiManager mdsalManager) {
-        this.mdsalManager = mdsalManager;
-    }
-
-    public void setIdManager(IdManagerService idManager) {
-        this.idManager = idManager;
-    }
-
-    public void onAddDpnEvent(AddDpnEvent notification) {
-/*
-        AddEventData eventData =  notification.getAddEventData();
-        BigInteger dpnId = eventData.getDpnId();
-        String vpnName = eventData.getVpnName();
-        LOG.info("Received add dpn {} in vpn {} event", dpnId, vpnName);
-        String  routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
-        if (routerId != null) {
-            //check router is associated to external network
-            InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
-            Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
-            if (routerData.isPresent()) {
-                Uuid networkId = routerData.get().getNetworkId();
-                if(networkId != null) {
-                    LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
-                    long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
-                    if(vpnId != NatConstants.INVALID_ID) {
-                        //Install default entry in FIB to SNAT table
-                        LOG.debug("Installing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
-                        defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
-                    } else {
-                        LOG.debug("Add DPN Event: Could not read vpnId for vpnName {}", vpnName);
-                    }
-                    if (routerData.get().isEnableSnat()) {
-                        LOG.info("SNAT enabled for router {}", routerId);
-                        handleSNATForDPN(dpnId, routerId);
-                    } else {
-                        LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
-                    }
-                }
-            }
-        }
-*/
-    }
-
-    void handleSNATForDPN(BigInteger dpnId, String routerName) {
-        //Check if primary and secondary switch are selected, If not select the role
-        //Install select group to NAPT switch
-        //Install default miss entry to NAPT switch
-/*
-        BigInteger naptSwitch;
-        try {
-            Long routerId = NatUtil.getVpnId(dataBroker, routerName);
-            if (routerId == NatConstants.INVALID_ID) {
-                LOG.error("Invalid routerId returned for routerName {}",routerName);
-                return;
-            }
-            BigInteger naptId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
-            if (naptId == null || naptId.equals(BigInteger.ZERO)) {
-                LOG.debug("No Naptswitch is selected for router {}", routerName);
-
-                naptSwitch = dpnId;
-                boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
-                if(!naptstatus) {
-                    LOG.error("Failed to update newNaptSwitch {} for routername {}",naptSwitch,routerName);
-                    return;
-                }
-                LOG.debug("Switch {} is elected as NaptSwitch for router {}",dpnId,routerName);
-
-                //installing group
-                List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInPrimarySwitch();
-                naptSwitchHA.installSnatGroupEntry(naptSwitch,bucketInfo,routerName);
-
-                naptSwitchHA.installSnatFlows(routerName,routerId,naptSwitch);
-
-            }  else {
-                LOG.debug("Napt switch with Id {} is already elected for router {}",naptId, routerName);
-                naptSwitch = naptId;
-
-                //installing group
-                List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, routerName, naptSwitch);
-                if (bucketInfo == null) {
-                    LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}",dpnId,routerName,
-                            naptSwitch);
-                    return;
-                }
-                naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
-            }
-            // Install miss entry (table 26) pointing to group
-            long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
-            FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,NatConstants.ADD_FLOW);
-            if (flowEntity == null) {
-                LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}",routerName,dpnId,groupId);
-                return;
-            }
-            LOG.debug("Successfully installed flow for dpnId {} router {} group {}",dpnId,routerName,groupId);
-            mdsalManager.installFlow(flowEntity);
-        } catch (Exception ex) {
-            LOG.error("Exception in handleSNATForDPN method : {}",ex);
-        }
-*/
-    }
-
-    public void onRemoveDpnEvent(RemoveDpnEvent notification) {
-/*
-        RemoveEventData eventData = notification.getRemoveEventData();
-        BigInteger dpnId = eventData.getDpnId();
-        String vpnName = eventData.getVpnName();
-        LOG.info("Received remove dpn {} in vpn {} event", dpnId, vpnName);
-        String  routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
-        if (routerId != null) {
-            //check router is associated to external network
-            InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
-            Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
-            if (routerData.isPresent()) {
-                Uuid networkId = routerData.get().getNetworkId();
-                if(networkId != null) {
-                    LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
-                    long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
-                    if(vpnId != NatConstants.INVALID_ID) {
-                        //Remove default entry in FIB
-                        LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
-                        defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId);
-                    } else {
-                        LOG.debug("Remove DPN Event: Could not read vpnId for vpnName {}", vpnName);
-                    }
-                    if (routerData.get().isEnableSnat()) {
-                        LOG.info("SNAT enabled for router {}", routerId);
-                        removeSNATFromDPN(dpnId,routerId);
-                    } else {
-                        LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId);
-                    }
-                }
-            }
-        }
-*/
-    }
-
-    /*void removeSNATFromDPN(BigInteger dpnId, String routerName) {
-        //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
-        //remove miss entry to NAPT switch
-        //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
-
-        Long routerId = NatUtil.getVpnId(dataBroker, routerName);
-        if (routerId == NatConstants.INVALID_ID) {
-            LOG.error("Invalid routerId returned for routerName {}",routerName);
-            return;
-        }
-        BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
-        if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
-            LOG.debug("No naptSwitch is selected for router {}", routerName);
-            return;
-        }
-        try {
-            boolean naptStatus = naptSwitchHA.isNaptSwitchDown(routerName,dpnId,naptSwitch);
-            if (!naptStatus) {
-                LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
-                        dpnId, routerName);
-            } else {
-                naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName,naptSwitch);
-            }
-        } catch (Exception ex) {
-            LOG.debug("Exception while handling naptSwitch down for router {} : {}",routerName,ex);
-        }
-
-        long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
-        FlowEntity flowEntity = null;
-        try {
-            flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, NatConstants.DEL_FLOW);
-            if (flowEntity == null) {
-                LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",routerName,dpnId,groupId);
-                return;
-            }
-            LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}",flowEntity);
-            mdsalManager.removeFlow(flowEntity);
-
-        } catch (Exception ex) {
-            LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex);
-            return;
-        }
-        LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName);
-
-        //remove group
-        GroupEntity groupEntity = null;
-        try {
-            groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
-                    GroupTypes.GroupAll, null);
-            LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity);
-            mdsalManager.removeGroup(groupEntity);
-        } catch (Exception ex) {
-            LOG.debug("NAT Service : Failed to remove group entity {} : {}",groupEntity,ex);
-            return;
-        }
-        LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}", dpnId, routerName);
-    }*/
-}
\ No newline at end of file
index afb55be518e506209c94663e91cc50d0964edd27..50667e5a788af0c1f2636bdee2747ed22353ac32 100644 (file)
@@ -174,9 +174,6 @@ public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
             interfaceStateEventListener.setNaptManager(naptManager);
 
             SNATDefaultRouteProgrammer defaultRouteProgrammer = new SNATDefaultRouteProgrammer(mdsalManager);
-            DpnInVpnListener dpnInVpnListener = new DpnInVpnListener(dataBroker);
-            dpnInVpnListener.setDefaultProgrammer(defaultRouteProgrammer);
-            notificationService.registerNotificationListener(dpnInVpnListener);
 
             externalRouterListener.setDefaultProgrammer(defaultRouteProgrammer);
 
@@ -192,10 +189,6 @@ public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
 
             natNodeEventListener = new NatNodeEventListener(dataBroker,naptSwitchHA);
 
-            dpnInVpnListener.setNaptSwitchHA(naptSwitchHA);
-            dpnInVpnListener.setMdsalManager(mdsalManager);
-            dpnInVpnListener.setIdManager(idManager);
-
             routerPortsListener = new RouterPortsListener(dataBroker);
 
             RouterDpnChangeListener routerDpnChangeListener = new RouterDpnChangeListener(dataBroker);
index 31e64c87e1495c1d48dbecc35e4f9369995a3be5..32f20599659d5933db35f231bf91929d0318b5d8 100644 (file)
@@ -169,7 +169,28 @@ module odl-l3vpn {
                    key ip-address;
                    leaf ip-address { type string; }
                }
+               leaf dpn-state {
+                       description
+                       "This flag indicates the state of the DPN.
+                       Active state indicates atleast one vpn interface present on that DPN for the vpn.
+                       Inactive state indicates no vpn interface present on that DPN for this vpn.";
+
+                    type enumeration {
+                         enum active {
+                            value "0";
+                            description
+                               "Active state";
+                            }
+                            enum inactive {
+                                value "1";
+                                description
+                                "Inactive state";
+                            }
+                       }
+                       default "active";
+                  }
            }
+           leaf active-dpn-count { type uint32;}
         }
     }
 
diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/DpnInVpnChangeListener.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/DpnInVpnChangeListener.java
new file mode 100644 (file)
index 0000000..74a59bc
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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 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.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.mdsalutil.*;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry
+        .VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class DpnInVpnChangeListener implements OdlL3vpnListener {
+    private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnChangeListener.class);
+    private DataBroker dataBroker;
+    private IMdsalApiManager mdsalManager;
+    private IdManagerService idManager;
+
+    public DpnInVpnChangeListener(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    public void onAddDpnEvent(AddDpnEvent notification) {
+
+    }
+
+    public void onRemoveDpnEvent(RemoveDpnEvent notification) {
+
+        RemoveEventData eventData = notification.getRemoveEventData();
+        final String rd = eventData.getRd();
+        String vpnName = eventData.getVpnName();
+        BigInteger dpnId = eventData.getDpnId();
+
+        LOG.trace("Remove Dpn Event notification received for rd {} VpnName {} DpnId {}", rd , vpnName, dpnId);
+
+        synchronized (vpnName.intern()) {
+            InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+            Optional<VpnInstanceOpDataEntry> vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+
+            if (vpnOpValue.isPresent()) {
+                LOG.trace(" Active Dpn count {} in VpnInstOpData", vpnOpValue.get().getActiveDpnCount());
+                if (vpnOpValue.get().getActiveDpnCount() == 0) {
+                    final Collection<VpnToDpnList> vpnToDpnList = vpnOpValue.get().getVpnToDpnList();
+
+                    DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                    dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+                            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;
+                                }
+                            });
+
+                }
+            }
+        }
+    }
+
+    protected void deleteDpn(Collection<VpnToDpnList> vpnToDpnList, String rd, WriteTransaction writeTxn) {
+        for (final VpnToDpnList curDpn : vpnToDpnList) {
+            InstanceIdentifier<VpnToDpnList> VpnToDpnId = VpnUtil.getVpnToDpnListIdentifier(rd, curDpn.getDpnId());
+            writeTxn.delete(LogicalDatastoreType.OPERATIONAL, VpnToDpnId);
+        }
+    }
+}
+
index 9adccd84d123e536aec36fef37404a11b3bd5896..a3c04fec9b047c45d5a0d8cbffd06047ac3e3211 100644 (file)
@@ -9,10 +9,13 @@ package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.base.Optional;
 
+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.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;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
@@ -26,6 +29,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
 
 public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
@@ -73,37 +79,62 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
 
     @Override
     protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
-      LOG.trace("Received interface {} up event", intrf);
-      try {
-        String interfaceName = intrf.getName();
-        LOG.info("Received port UP event for interface {} ", interfaceName);
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
-            configInterface = InterfaceUtils.getInterface(broker, interfaceName);
-        BigInteger dpnId = BigInteger.ZERO;
-        try{
-            dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
-        }catch(Exception e){
-            LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", intrf.getName(), e);
-            return;
-        }
-        if (configInterface != null) {
-            if (!configInterface.getType().equals(Tunnel.class)) {
-                // We service only VM interfaces and Router interfaces here.
-                // We donot service Tunnel Interfaces here.
-                // Tunnel events are directly serviced
-                // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
-                final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
-                if (vpnInterface != null) {
-                    vpnInterfaceManager.processVpnInterfaceUp(dpnId, interfaceName, intrf.getIfIndex(), false);
-                    vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(intrf);
-                    handleRouterInterfacesUpEvent(interfaceName);
+        LOG.trace("Received interface {} add event", intrf);
+        try {
+            final String interfaceName = intrf.getName();
+            LOG.info("Received interface add event for interface {} ", interfaceName);
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+                    configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+            if (configInterface != null) {
+                if (!configInterface.getType().equals(Tunnel.class)) {
+                    // We service only VM interfaces and Router interfaces here.
+                    // We donot service Tunnel Interfaces here.
+                    // Tunnel events are directly serviced
+                    // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
+                    final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+                    if (vpnInterface != null) {
+                        final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+                        final int ifIndex = intrf.getIfIndex();
+                        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                        dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
+                                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;
+                                    }
+                                });
+                    } else {
+                        RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(broker, interfaceName);
+                        if (routerInterface != null) {
+                            final String routerName = routerInterface.getRouterName();
+                            DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                            dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
+                                    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;
+                                        }
+                                    });
+                        } else {
+                            LOG.info("Unable to process add for interface {} as it is not configured for vpn", interfaceName);
+                        }
+                    }
                 }
-
+            } else {
+                LOG.error("Unable to process add for interface {} ," +
+                        "since Interface ConfigDS entry absent for the same", interfaceName);
             }
+        } catch (Exception e) {
+            LOG.error("Exception caught in Interface Operational State Up event", e);
         }
-      } catch (Exception e) {
-        LOG.error("Exception observed in handling addition for VPN Interface {}. ", intrf.getName(), e);
-      }
     }
 
 
@@ -113,99 +144,111 @@ public class InterfaceStateChangeListener extends AbstractDataChangeListener<Int
 
     @Override
     protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
-      LOG.trace("Received interface {} down event", intrf);
-      try {
-        String interfaceName = intrf.getName();
-        LOG.info("Received port DOWN event for interface {} ", interfaceName);
-        InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
-        Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-        if (!existingVpnInterface.isPresent()) {
-            LOG.error("VPN Interface operational instance not available for interface {}, ignoring interface", interfaceName);
-            return;
-        }
-        if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
-            //withdraw all prefixes in all vpns for this dpn from bgp
-            // FIXME: Blocked until tunnel event[vxlan/gre] support is available
-            // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
-        } else {
-            BigInteger dpId = BigInteger.ZERO;
-            try{
-                dpId = InterfaceUtils.getDpIdFromInterface(intrf);
-            }catch(Exception e){
-                LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
-                dpId = existingVpnInterface.get().getDpnId();
+        LOG.trace("Received interface {} down event", intrf);
+        try {
+            final String interfaceName = intrf.getName();
+            LOG.info("Received port DOWN event for interface {} ", interfaceName);
+            if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+                //withdraw all prefixes in all vpns for this dpn from bgp
+                // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+                // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+            } else {
+                BigInteger dpId = BigInteger.ZERO;
+                InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+                Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+                if (!optVpnInterface.isPresent()) {
+                    LOG.debug("Interface {} is not a vpninterface, ignoring.", intrf.getName());
+                    return;
+                }
+                VpnInterface vpnInterface = optVpnInterface.get();
+                try {
+                    dpId = InterfaceUtils.getDpIdFromInterface(intrf);
+                } catch (Exception e){
+                    LOG.warn("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
+                    dpId = vpnInterface.getDpnId();
+                }
+                final BigInteger dpnId = dpId;
+                final int ifIndex = intrf.getIfIndex();
+                DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
+                        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);
+                                RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(broker, interfaceName);
+                                if (routerInterface != null) {
+                                    final String routerName = routerInterface.getRouterName();
+                                    handleRouterInterfacesDownEvent(routerName, interfaceName, dpnId, writeTxn);
+                                }
+                                List<ListenableFuture<Void>> futures = new ArrayList<>();
+                                futures.add(writeTxn.submit());
+                                return futures;
+                            }
+                        });
             }
-            vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, intrf.getIfIndex(), false, false);
-            vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(intrf);
-            handleRouterInterfacesDownEvent(interfaceName,dpId);
+        } catch (Exception e) {
+            LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
         }
-      } catch (Exception e) {
-        LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
-      }
     }
 
     @Override
     protected void update(InstanceIdentifier<Interface> identifier,
-            Interface original, Interface update) {
-      LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
-      if(original.getOperStatus().equals(Interface.OperStatus.Unknown) || update.getOperStatus().equals(Interface.OperStatus.Unknown)){
-          LOG.debug("Interface state change is from/to UNKNOWN. Ignoring the update event.");
-          return;
-      }
-      String interfaceName = update.getName();
-      BigInteger dpId = InterfaceUtils.getDpIdFromInterface(update);
-      if (update != null) {
-          if (update.getType().equals(Tunnel.class)) {
-            /*
-            // FIXME: Blocked until tunnel event[vxlan/gre] support is available
-            BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
-            if(update.getOperStatus().equals(Interface.OperStatus.Up)) {
-              //advertise all prefixes in all vpns for this dpn to bgp
-              // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
-              vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(update);
-            } else if(update.getOperStatus().equals(Interface.OperStatus.Down)) {
-              //withdraw all prefixes in all vpns for this dpn from bgp
-              // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
-              vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(update);
-            }*/
-          } else {
-              if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
-                  vpnInterfaceManager.processVpnInterfaceUp(dpId, interfaceName, update.getIfIndex(), true);
-                  vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(update);
-              } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
-                  if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
-                      vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, update.getIfIndex(), true,
-                              false);
-                      vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(update);
-                  }
-              }
-          }
-      }
-
+                          Interface original, Interface update) {
+        LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+        final String interfaceName = update.getName();
+        if (original.getOperStatus().equals(Interface.OperStatus.Unknown) ||
+                update.getOperStatus().equals(Interface.OperStatus.Unknown)){
+            LOG.debug("Interface {} state change is from/to UNKNOWN. Ignoring the update event.", interfaceName);
+            return;
+        }
+        final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
+        final int ifIndex = update.getIfIndex();
+        if (update != null) {
+            if (!update.getType().equals(Tunnel.class)) {
+                final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+                if (vpnInterface != null) {
+                    if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+                        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                        dataStoreCoordinator.enqueueJob(interfaceName,
+                                new Callable<List<ListenableFuture<Void>>>() {
+                                    @Override
+                                    public List<ListenableFuture<Void>> call() throws Exception {
+                                        WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+                                        vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex,
+                                                true, writeTxn);
+                                        List<ListenableFuture<Void>> futures = new ArrayList<>();
+                                        futures.add(writeTxn.submit());
+                                        return futures;
+                                    }
+                                });
+                    } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
+                        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                        dataStoreCoordinator.enqueueJob(interfaceName,
+                                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;
+                                    }
+                                });
+                    }
+                }
+            }
+        }
     }
 
-    void handleRouterInterfacesUpEvent(String interfaceName) {
-        Optional<RouterInterface> optRouterInterface = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
-        if(optRouterInterface.isPresent()) {
-            RouterInterface routerInterface = optRouterInterface.get();
-            String routerName = routerInterface.getRouterName();
-            LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
-            vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName);
-        } else {
-            LOG.debug("No Router interface configured to handle UP event for {}", interfaceName);
-        }
+    void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeTxn) {
+        LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
+        vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeTxn);
     }
 
-    void handleRouterInterfacesDownEvent(String interfaceName,BigInteger dpnId) {
-        Optional<RouterInterface> optRouterInterface = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
-        if(optRouterInterface.isPresent()) {
-            RouterInterface routerInterface = optRouterInterface.get();
-            String routerName = routerInterface.getRouterName();
-            LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
-            vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName,dpnId);
-        } else {
-            LOG.debug("No Router interface configured to handle  DOWN event for {}", interfaceName);
-        }
+    void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId, WriteTransaction writeTxn) {
+        LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
+        vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeTxn);
     }
 
-}
+}
\ No newline at end of file
index 9e6e35f3b219bce0e6fd1a404235125005b72104..19c302f0cf17bff44924618e87c395542b7cc909 100644 (file)
@@ -7,10 +7,13 @@
  */\r
 package org.opendaylight.netvirt.vpnmanager;\r
 \r
+import com.google.common.util.concurrent.ListenableFuture;\r
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;\r
 import org.opendaylight.genius.mdsalutil.MDSALUtil;\r
 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;\r
@@ -21,6 +24,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.concurrent.Callable;\r
+\r
 public class RouterInterfaceListener extends AbstractDataChangeListener<Interfaces> {\r
     private static final Logger LOG = LoggerFactory.getLogger(RouterInterfaceListener.class);\r
     private ListenerRegistration<DataChangeListener> listenerRegistration;\r
@@ -54,16 +61,26 @@ public class RouterInterfaceListener extends AbstractDataChangeListener<Interfac
     protected void add(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {\r
         LOG.trace("Add event - key: {}, value: {}", identifier, interfaceInfo);\r
         final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();\r
-        String interfaceName = interfaceInfo.getInterfaceId();\r
-\r
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, \r
-                VpnUtil.getRouterInterfaceId(interfaceName), VpnUtil.getRouterInterface(interfaceName, routerId));\r
-\r
+        final String interfaceName = interfaceInfo.getInterfaceId();\r
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =\r
                 InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);\r
         if (interfaceState != null) {\r
-            LOG.debug("Handling interface {} in router {} add scenario", interfaceName, routerId);\r
-            vpnInterfaceManager.addToNeutronRouterDpnsMap(routerId, interfaceName);\r
+            DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();\r
+            dataStoreCoordinator.enqueueJob(interfaceName,\r
+                    new Callable<List<ListenableFuture<Void>>>() {\r
+                        @Override\r
+                        public List<ListenableFuture<Void>> call() throws Exception {\r
+                            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();\r
+                            LOG.debug("Handling interface {} in router {} add scenario", interfaceName, routerId);\r
+                            writeTxn.put(LogicalDatastoreType.CONFIGURATION,\r
+                                    VpnUtil.getRouterInterfaceId(interfaceName),\r
+                                    VpnUtil.getRouterInterface(interfaceName, routerId), true);\r
+                            vpnInterfaceManager.addToNeutronRouterDpnsMap(routerId, interfaceName, writeTxn);\r
+                            List<ListenableFuture<Void>> futures = new ArrayList<>();\r
+                            futures.add(writeTxn.submit());\r
+                            return futures;\r
+                        }\r
+                    });\r
         } else {\r
             LOG.warn("Interface {} not yet operational to handle router interface add event in router {}", interfaceName, routerId);\r
         }\r
@@ -73,8 +90,19 @@ public class RouterInterfaceListener extends AbstractDataChangeListener<Interfac
     protected void remove(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {\r
         LOG.trace("Remove event - key: {}, value: {}", identifier, interfaceInfo);\r
         final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();\r
-        String interfaceName = interfaceInfo.getInterfaceId();\r
-        vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerId, interfaceName);\r
+        final String interfaceName = interfaceInfo.getInterfaceId();\r
+        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();\r
+        dataStoreCoordinator.enqueueJob(interfaceName,\r
+                new Callable<List<ListenableFuture<Void>>>() {\r
+                    @Override\r
+                    public List<ListenableFuture<Void>> call() throws Exception {\r
+                        WriteTransaction writeTxn = broker.newWriteOnlyTransaction();\r
+                        vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerId, interfaceName, writeTxn);\r
+                        List<ListenableFuture<Void>> futures = new ArrayList<>();\r
+                        futures.add(writeTxn.submit());\r
+                        return futures;\r
+                    }\r
+                });\r
     }\r
 \r
     @Override\r
diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetRouteInterfaceStateChangeListener.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetRouteInterfaceStateChangeListener.java
new file mode 100644 (file)
index 0000000..0429a87
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 - 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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.vpnmanager.utilities.InterfaceUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class SubnetRouteInterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    private final DataBroker broker;
+    private VpnInterfaceManager vpnInterfaceManager;
+
+    public SubnetRouteInterfaceStateChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
+        super(Interface.class);
+        broker = db;
+        this.vpnInterfaceManager = vpnInterfaceManager;
+        registerListener(db);
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (final Exception e) {
+                LOG.error("Error when cleaning up DataChangeListener.", e);
+            }
+            listenerRegistration = null;
+        }
+        LOG.info("Interface listener Closed");
+    }
+
+
+    private void registerListener(final DataBroker db) {
+        try {
+            listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                    getWildCardPath(), SubnetRouteInterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
+        } catch (final Exception e) {
+            LOG.error("Interface DataChange listener registration failed", e);
+            throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+        }
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+        LOG.trace("Received interface {} up event", intrf);
+        try {
+            String interfaceName = intrf.getName();
+            LOG.info("Received port UP event for interface {} ", interfaceName);
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+                    configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+            if (configInterface != null) {
+                if (!configInterface.getType().equals(Tunnel.class)) {
+                    BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+                    vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(dpnId, intrf.getName());
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Exception observed in handling addition for VPN Interface {}. ", intrf.getName(), e);
+        }
+    }
+
+
+    private InstanceIdentifier<Interface> getWildCardPath() {
+        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+        LOG.trace("Received interface {} down event", intrf);
+        try {
+            String interfaceName = intrf.getName();
+            BigInteger dpnId = BigInteger.ZERO;
+            LOG.info("Received port DOWN event for interface {} ", interfaceName);
+            if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+                //withdraw all prefixes in all vpns for this dpn from bgp
+                // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+                // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+            } else {
+                try {
+                    dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+                } catch (Exception e){
+                    LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
+                }
+                vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(dpnId, intrf.getName());
+            }
+        } catch (Exception e) {
+            LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
+        }
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<Interface> identifier,
+                          Interface original, Interface update) {
+        LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+        String interfaceName = update.getName();
+        BigInteger dpId = InterfaceUtils.getDpIdFromInterface(update);
+        if (update != null) {
+            if (!update.getType().equals(Tunnel.class)) {
+                if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+                    vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(dpId, update.getName());
+                } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
+                    if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
+                        vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(dpId, update.getName());
+                    }
+                }
+            }
+        }
+    }
+}
index f3c2a986c26f25f25e488964bdd9c2ff5c7f8f57..422d67fc13f117912c75b57a6a578bbf8acacf1a 100644 (file)
@@ -39,4 +39,11 @@ public class VpnConstants {
         ITMTunnelLocType(int id) { this.type = id; }
         public int getValue() { return type; }
     }
+    public enum DCGWPresentStatus {
+        Invalid(0), Present(1), Absent(2);
+
+        private final int status;
+        DCGWPresentStatus(int id) { this.status = id; }
+        public int getValue() { return status; }
+    }
 }
index acdbf84960ead5fc7008c0b22702081138bdecd0..c5dd414f6c9c61265aaba08df7f5598e0e312924 100644 (file)
@@ -11,6 +11,7 @@ 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 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.IFibManager;
@@ -27,11 +28,24 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
 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.TunnelsState;
 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.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
@@ -57,6 +71,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neu
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+        .VpnInstanceOpDataEntryBuilder;
 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.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
@@ -81,10 +98,7 @@ import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
+import java.util.concurrent.*;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
@@ -129,9 +143,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
     private ExecutorService executorService = Executors.newSingleThreadExecutor();
     private InterfaceStateChangeListener interfaceListener;
+    private SubnetRouteInterfaceStateChangeListener subnetRouteInterfaceListener;
     private TunnelInterfaceStateListener tunnelInterfaceStateListener;
     private VpnInterfaceOpListener vpnInterfaceOpListener;
     private ArpNotificationHandler arpNotificationHandler;
+    private DpnInVpnChangeListener dpnInVpnChangeListener;
     private NotificationPublishService notificationPublishService;
     private FibRpcService fibService;
     protected enum UpdateRouteAction {
@@ -151,12 +167,15 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         broker = db;
         this.bgpManager = bgpManager;
         interfaceListener = new InterfaceStateChangeListener(db, this);
+        subnetRouteInterfaceListener = new SubnetRouteInterfaceStateChangeListener(db, this);
         vpnInterfaceOpListener = new VpnInterfaceOpListener();
         arpNotificationHandler = new ArpNotificationHandler(this, broker);
         vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
+        dpnInVpnChangeListener = new DpnInVpnChangeListener(broker);
         tunnelInterfaceStateListener = new TunnelInterfaceStateListener(broker, this);
         notificationService.registerNotificationListener(vpnSubnetRouteHandler);
         notificationService.registerNotificationListener(arpNotificationHandler);
+        notificationService.registerNotificationListener(dpnInVpnChangeListener);
         registerListener(db);
     }
 
@@ -257,29 +276,36 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
         if(interfaceState != null){
-            BigInteger dpnId = BigInteger.ZERO;
             try{
-                dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
+                final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
+                final int ifIndex = interfaceState.getIfIndex();
+                DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                dataStoreCoordinator.enqueueJob("VPNINTERFACE-"+ interfaceName,
+                        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;
+                            }
+                        });
             }catch (Exception e){
                 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
                 return;
             }
-            processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName,
-                                  interfaceState.getIfIndex(), false);
         } else {
             LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
         }
     }
 
-    protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceUp) {
+    protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
+                                         final int lPortTag, boolean isInterfaceUp, WriteTransaction writeTxn) {
 
-        VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
-        if(vpnInterface == null) {
-            LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
-            return;
-        }
+        final String interfaceName = vpnInterface.getName();
         if (!isInterfaceUp) {
-            String vpnName = vpnInterface.getVpnInstanceName();
+            final String vpnName = vpnInterface.getVpnInstanceName();
             LOG.info("Binding vpn service to interface {} ", interfaceName);
             long vpnId = VpnUtil.getVpnId(broker, vpnName);
             if (vpnId == VpnConstants.INVALID_ID) {
@@ -330,10 +356,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 }
                 if (!waitForVpnInterfaceOpRemoval) {
                     // Add the VPNInterface and quit
-                    bindService(dpId, vpnName, interfaceName, lPortTag);
-                    updateDpnDbs(dpId, vpnName, interfaceName, true);
-                    processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
-                        vpnInterface);
+                    DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                    dataStoreCoordinator.enqueueJob((interfaceName + dpId.toString()),
+                            new UpdateDpnToVpnWorker(dpId, vpnName, interfaceName, lPortTag, true));
                     return;
                 }
             }
@@ -361,22 +386,103 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             }
             // VPNInterface got removed, proceed with Add
             synchronized (interfaceName.intern()) {
-                bindService(dpId, vpnName, interfaceName, lPortTag);
-                updateDpnDbs(dpId, vpnName, interfaceName, true);
-                processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
-                                               vpnInterface);
+                DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+                dataStoreCoordinator.enqueueJob((interfaceName + dpId.toString()),
+                        new UpdateDpnToVpnWorker(dpId, vpnName, interfaceName, lPortTag, true));
             }
         } 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);
+                        vpnInterface, writeTxn);
             }
         }
     }
 
-    private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+
+    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) {
         //Read NextHops
         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
@@ -461,21 +567,21 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+    private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add, WriteTransaction writeTxn) {
         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);
+                updateMappingDbs(vpnId, dpId, interfaceName, vpnName, writeTxn);
             else
-                removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
+                removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName, writeTxn);
         }
-
     }
 
-    private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+    private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag,
+                             WriteTransaction writeTxn) {
         int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
 
@@ -490,19 +596,20 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
                                             VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
                                             VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
-        VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                          InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
+        writeTxn.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);
+                vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeTxn);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
-                vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW);
+                vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeTxn);
 
     }
 
-    private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
-                                                VpnInterface intf) {
-        String intfName = intf.getName();
-        synchronized (intfName) {
+    private void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
+                                                WriteTransaction writeTxn) {
+        InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+
+        synchronized (interfaceName) {
             // Read NextHops
             InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
             Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
@@ -512,69 +619,72 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 List<Adjacency> value = new ArrayList<>();
 
                 // Get the rd of the vpn instance
-                String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+                String rd = getRouteDistinguisher(vpnName);
 
                 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
                 if (nextHopIp == null){
-                    LOG.error("NextHop for interface {} is null", intfName);
+                    LOG.error("NextHop for interface {} is null", interfaceName);
                     return;
                 }
-                List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(intf.getVpnInstanceName());
-                LOG.trace("NextHops for interface {} are {}", intfName, nextHops);
+
+                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) ? intf.getVpnInstanceName() : rd, prefix));
+                    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, intfName, intf.getVpnInstanceName());
-                        VpnUtil.syncUpdate(
-                                broker,
+                        LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
+                        writeTxn.merge(
                                 LogicalDatastoreType.OPERATIONAL,
                                 VpnUtil.getPrefixToInterfaceIdentifier(
-                                        VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
-                                VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
+                                        VpnUtil.getVpnId(broker, vpnName), prefix),
+                                VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
                     } else {
                         //Extra route adjacency
-                        // FIXME 4: To be fixed with VPNManager patch
-                        LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), intf.getVpnInstanceName() );
-                        VpnUtil.syncUpdate(
-                                broker,
+                        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 : intf.getVpnInstanceName(), nextHop.getIpAddress()),
-                                VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()));
+                                        (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
+                                VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
                     }
-
                 }
 
                 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
-                VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug, dpnId, Boolean.FALSE);
-                InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
-                VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
-                long vpnId = VpnUtil.getVpnId(broker, intf.getVpnInstanceName());
+
+                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);
+
                 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,
-                                intfName, null,false, rd);
-                        addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label);
+                                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);
+                                VpnUtil.addFibEntryToDS(broker, vpnRd, nextHop.getIpAddress(), nextHopIp, (int) label, RouteOrigin.SELF_IMPORTED, writeTxn);
                             }
                         }
                     } else {
                         // ### add FIB route directly
-                        VpnUtil.addFibEntryToDS(broker, intf.getVpnInstanceName(), nextHop.getIpAddress(), nextHopIp,
-                                                (int) label, RouteOrigin.STATIC);
+                        VpnUtil.addFibEntryToDS(broker, vpnName, nextHop.getIpAddress(), nextHopIp,
+                                (int) label, RouteOrigin.STATIC, writeTxn);
                     }
                 }
             }
@@ -722,7 +832,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
-                             long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
+                             long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow, WriteTransaction writeTxn){
         List<MatchInfo> matches = new ArrayList<MatchInfo>();
         BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
@@ -751,16 +861,42 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
                 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
                 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
-
-        if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
-            LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
-            mdsalManager.installFlow(flowEntity);
+        Flow flow = flowEntity.getFlowBuilder().build();
+        String flowId = flowEntity.getFlowId();
+        FlowKey flowKey = new FlowKey( new FlowId(flowId));
+        Node nodeDpn = buildDpnNode(dpId);
+
+        InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
+
+        if (writeTxn != null) {
+            if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+                LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
+                writeTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
+            } else {
+                LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
+                writeTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+            }
         } else {
-            LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
-            mdsalManager.removeFlow(flowEntity);
+            if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+                LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
+                mdsalManager.installFlow(flowEntity);
+            } else {
+                LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
+                mdsalManager.removeFlow(flowEntity);
+            }
         }
     }
 
+    //TODO: How to handle the below code, its a copy paste from MDSALManager.java
+    private Node buildDpnNode(BigInteger dpnId) {
+        NodeId nodeId = new NodeId("openflow:" + dpnId);
+        Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
+
+        return nodeDpn;
+    }
+
     private String getRouteDistinguisher(String vpnName) {
         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
                                       .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
@@ -774,46 +910,81 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         return rd;
     }
 
-    private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+    private void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName,
+                                  WriteTransaction writeTxn) {
         String routeDistinguisher = getRouteDistinguisher(vpnName);
         String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
-        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
-            vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
-        if (dpnInVpn.isPresent()) {
-            VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
-                    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)), vpnInterface);
-        } else {
-            VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-                                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-                                    VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId, vpnName));
-            VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
-            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 =  new ArrayList<>();
-            vpnInterfaces.add(vpnInterface);
-            VpnUtil.syncWrite(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
+        synchronized (vpnName.intern()) {
+            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
+                    vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+            if (dpnInVpn.isPresent()) {
+                if (writeTxn != null) {
+                    writeTxn.put(LogicalDatastoreType.OPERATIONAL, id.child(
+                            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)), vpnInterface, true);
+                } else {
+                    VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+                            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)), vpnInterface);
+                }
+            } else {
+
+                /*
+                * Increment the active dpn count in VpnInstanceOpData.
+                * ActiveDpnCount will be decremented when all the VpnInt in that Dpn are removed.
+                */
+                InstanceIdentifier<VpnInstanceOpDataEntry> vpnInsOpDataId = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+                Optional<VpnInstanceOpDataEntry> vpnInstOpData = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnInsOpDataId);
+
+                java.lang.Long activeDpnCnt = vpnInstOpData.get().getActiveDpnCount();
+
+                VpnInstanceOpDataEntryBuilder builder =
+                        new VpnInstanceOpDataEntryBuilder(vpnInstOpData.get()).setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).setActiveDpnCount(++activeDpnCnt);
+
+                if (writeTxn != null) {
+                    writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+                            vpnInsOpDataId,
+                            builder.build(), true);
+                } else {
+                    VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+                            vpnInsOpDataId,
+                            builder.build());
+                }
+
+                VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId).setDpnState(VpnToDpnList.DpnState.Active);
+                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 = new ArrayList<>();
+                vpnInterfaces.add(vpnInterface);
+                if (writeTxn != null) {
+                    writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id,
+                            vpnToDpnList.setVpnInterfaces(vpnInterfaces).build(), true);
+                } else {
+                    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
 
+            }
         }
     }
 
@@ -840,7 +1011,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                 importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route);
                             } 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);
+                                VpnUtil.addFibEntryToDS(broker, vpnRd, prefix, nh, (int)label, RouteOrigin
+                                        .SELF_IMPORTED, null);
                             }
                         }
                     } catch (Exception e) {
@@ -853,42 +1025,87 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
     }
 
-    private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+    private void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName,
+                                      WriteTransaction writeTxn) {
         //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
-        String rd = VpnUtil.getVpnRd(broker, vpnName);
-        InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
-        Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-        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
-                    currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
-            if (vpnInterfaces.remove(currVpnInterface)) {
-                if (vpnInterfaces.isEmpty()) {
-                    List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
-                    if (ipAddresses == null || ipAddresses.isEmpty()) {
-                        LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
-                        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
-                        fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
-                        publishRemoveNotification(dpnId, vpnName, rd);
+        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);
+            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
+                        currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+                if (vpnInterfaces.remove(currVpnInterface)) {
+                    if (vpnInterfaces.isEmpty()) {
+                        List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
+                        if (ipAddresses == null || ipAddresses.isEmpty()) {
+
+                           /*
+                           * Mark the DPN state as Inactive as the Vpnintf list is empty.
+                           * This DPN will be removed in DpnToVpnChangeListner only if its
+                           * inactive and ActiveDpnCount is zero.
+                           */
+                            VpnToDpnListBuilder vpnToDpnList =
+                                    new VpnToDpnListBuilder(dpnInVpn.get())
+                                            .setDpnId(dpnId)
+                                            .setDpnState(VpnToDpnList.DpnState.Inactive)
+                                            .setVpnInterfaces(vpnInterfaces);
+
+                            if (writeTxn != null) {
+                                writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id , vpnToDpnList.build(), true);
+                            } else {
+                                VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnList.build());
+                            }
+
+                            InstanceIdentifier<VpnInstanceOpDataEntry> vpnInstOpDataId = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+                            Optional<VpnInstanceOpDataEntry> vpnInstOpData = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnInstOpDataId);
+
+                            java.lang.Long activeDpnCnt = vpnInstOpData.get().getActiveDpnCount();
+
+                            VpnInstanceOpDataEntryBuilder builder =
+                                    new VpnInstanceOpDataEntryBuilder(vpnInstOpData.get()).setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).setActiveDpnCount(--activeDpnCnt);
+
+                            if (writeTxn != null) {
+                                writeTxn.merge(LogicalDatastoreType.OPERATIONAL, vpnInstOpDataId , builder.build(), true);
+                            } else {
+                                VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vpnInstOpDataId, builder.build());
+                            }
+
+                            LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
+                            fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+                            publishRemoveNotification(dpnId, vpnName, rd);
+                        } else {
+                            LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
+                        }
                     } else {
-                        LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
+                        if (writeTxn != null) {
+                            writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
+                                    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 {
+                            VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+                                    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)), VpnUtil.DEFAULT_CALLBACK);
+                        }
                     }
-                } else {
-                    VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
-                        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)), VpnUtil.DEFAULT_CALLBACK);
                 }
             }
         }
     }
 
-    private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
+    private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeTxn) {
+
         try {
             LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
-            bgpManager.addPrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC);
+            VpnUtil.addFibEntryToDS(broker, rd, prefix, nextHopIp, (int)label, RouteOrigin.STATIC, writeTxn);
+            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);
@@ -904,13 +1121,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
         LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
-        String interfaceName = key.getName();
+        final String interfaceName = key.getName();
 
         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         Optional<VpnInterface> existingVpnInterface = 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()){
+        if (existingVpnInterface.isPresent()){
             BigInteger dpnId = BigInteger.ZERO;
             Boolean dpnIdRetrieved = Boolean.FALSE;
             if(interfaceState != null){
@@ -920,18 +1137,37 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 }catch (Exception e){
                     LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
                 }
+            } else {
+                LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
+                return;
             }
             if(dpnIdRetrieved == Boolean.FALSE){
                 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
                 dpnId = existingVpnInterface.get().getDpnId();
             }
-            processVpnInterfaceDown(dpnId, interfaceName, interfaceState.getIfIndex(), false, true);
+            final int ifIndex = interfaceState.getIfIndex();
+            final BigInteger dpId = dpnId;
+            DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+            dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
+                    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;
+                        }
+                    });
+            //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) {
+    protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown,
+                                           boolean isConfigRemoval, WriteTransaction writeTxn) {
         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         if (!isInterfaceStateDown) {
             synchronized (interfaceName.intern()) {
@@ -940,34 +1176,18 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
                     return;
                 }else{
-                    String vpnName = vpnInterface.getVpnInstanceName();
+                    final String vpnName = vpnInterface.getVpnInstanceName();
                     if(!vpnInterface.isScheduledForRemove()){
-                        VpnUtil.updateVpnInterface(broker, vpnInterface.getName(), vpnInterface.getDpnId(), vpnInterface.getVpnInstanceName(), Boolean.TRUE);
-                        removeAdjacenciesFromVpn(dpId, identifier, vpnInterface);
+                        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);
+                        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;
                     }
                 }
             }
-
-            // FIB didn't get a chance yet to clean up this VPNInterface
-            // Let us give it a chance here !
-            LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
-            try {
-                Runnable notifyTask = new VpnNotifyTask();
-                vpnIntfMap.put(interfaceName, notifyTask);
-                synchronized (notifyTask) {
-                    try {
-                        notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
-                    } catch (InterruptedException e) {
-                    }
-                }
-            } finally {
-                vpnIntfMap.remove(interfaceName);
-            }
         } else {
                 synchronized (interfaceName.intern()) {
                     // Interface is retained in the DPN, but its Link Down.
@@ -984,14 +1204,34 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     }
 
-    private void removeAdjacenciesFromVpn(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+    private void waitForFibToRemoveVpnPrefix(String interfaceName) {
+        // FIB didn't get a chance yet to clean up this VPNInterface
+        // Let us give it a chance here !
+        LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
+        try {
+            Runnable notifyTask = new VpnNotifyTask();
+            vpnIntfMap.put(interfaceName, notifyTask);
+            synchronized (notifyTask) {
+                try {
+                    notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
+                } catch (InterruptedException e) {
+                }
+            }
+        } finally {
+            vpnIntfMap.remove(interfaceName);
+        }
+    }
+
+    private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
+                                          WriteTransaction writeTxn) {
         //Read NextHops
+        InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
 
-        String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
-        LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", intf.getName(),
-                intf.getVpnInstanceName(), rd);
+        String rd = VpnUtil.getVpnRd(broker, vpnName);
+        LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", interfaceName,
+                vpnName, rd);
         if (adjacencies.isPresent()) {
             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
 
@@ -1012,34 +1252,33 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                         // This is a primary adjacency
                         nhList = nextHop.getNextHopIpList();
                     }
-                    if (rd.equals(intf.getVpnInstanceName())) {
+                    if (rd.equals(vpnName)) {
                         //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, intf.getVpnInstanceName(), nextHop.getIpAddress(), nh);
+                            VpnUtil.removeFibEntryFromDS(broker, vpnName, nextHop.getIpAddress(), nh, writeTxn);
                         }
                     } else {
-
-                        List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(intf.getVpnInstanceName());
+                        List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
                         for (String nh : nextHop.getNextHopIpList()) {
                             //IRT: remove routes from other vpns importing it
-                            removePrefixFromBGP(rd, nextHop.getIpAddress(), nh);
+                            removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeTxn);
                             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);
+                                    VpnUtil.removeFibEntryFromDS(broker, vpnRd, nextHop.getIpAddress(), nh, writeTxn);
                                 }
                             }
                         }
                     }
                     String ip = nextHop.getIpAddress().split("/")[0];
                     VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(broker,
-                            intf.getVpnInstanceName(), ip);
+                            vpnName, ip);
                     if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
                         LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
                                 vpnPortipToPort.getPortName(),ip);
-                        VpnUtil.removeVpnPortFixedIpToPort(broker, intf.getVpnInstanceName(), ip);
+                        VpnUtil.removeVpnPortFixedIpToPort(broker, vpnName, ip);
                     }
                 }
             }
@@ -1048,24 +1287,26 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
 
     private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
-                               int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval) {
+                               int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
+                               WriteTransaction writeTxn) {
         if (!isInterfaceStateDown && isConfigRemoval) {
-            MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
+            writeTxn.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);
+                vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeTxn);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
-                vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW);
+                vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeTxn);
     }
 
 
-    private void removePrefixFromBGP(String rd, String prefix, String nextHop) {
-        VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop);
+    private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeTxn) {
+        VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop, writeTxn);
         try {
             LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
+            VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop, writeTxn);
             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) {
@@ -1179,7 +1420,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
-                                                        long elantag, BigInteger dpnId) {
+                                                        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
@@ -1201,12 +1442,16 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
                 setVrfEntry(vrfEntryList).build();
 
-        VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+        if (writeTxn != null) {
+            writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
+        } else {
+            VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+        }
 
         List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
         if (vpnsToImportRoute.size() > 0) {
             VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
-                    .setLabel((long)label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
+                    .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
                     .addAugmentation(SubnetRoute.class, route).build();
             List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
             for (VpnInstance vpnInstance : vpnsToImportRoute) {
@@ -1214,7 +1459,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
                 InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
                 VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
-                VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
+                if (writeTxn != null) {
+                    writeTxn.merge(LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable, true);
+                } else {
+                    VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
+                }
             }
         }
     }
@@ -1237,12 +1486,12 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
-        VpnUtil.removeFibEntryFromDS(broker, rd, prefix, null /* nextHopToRemove */);
+        VpnUtil.removeFibEntryFromDS(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);
+            VpnUtil.removeFibEntryFromDS(broker, importingRd, prefix, null, null);
         }
     }
 
@@ -1380,10 +1629,10 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             VpnUtil.leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
         } else {
             if (rd != null) {
-                addPrefixToBGP(rd, destination, nextHop, label);
+                addPrefixToBGP(rd, destination, nextHop, label, null);
             } else {
                 // ### add FIB route directly
-                VpnUtil.addFibEntryToDS(broker, routerID, destination, nextHop, label, RouteOrigin.STATIC);
+                VpnUtil.addFibEntryToDS(broker, routerID, destination, nextHop, label, RouteOrigin.STATIC, null);
             }
         }
     }
@@ -1400,10 +1649,10 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         }
 
         if (rd != null) {
-            removePrefixFromBGP(rd, destination, nextHop);
+            removePrefixFromBGP(rd, destination, nextHop, null);
         } else {
             // ### add FIB route directly
-            VpnUtil.removeFibEntryFromDS(broker, routerID, destination, nextHop);
+            VpnUtil.removeFibEntryFromDS(broker, routerID, destination, nextHop, null);
         }
     }
 
@@ -1460,18 +1709,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                        VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
                                        VpnUtil.DEFAULT_CALLBACK);
                         synchronized (interfaceName.intern()) {
-                            updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false);
+                            updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false, null);
                         }
                     }
-//                    Long ifCnt = 0L;
-//                    //ifCnt = vpnInstOp.getVpnInterfaceCount();
-//                    LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} Intf count {}",
-//                            interfaceName, rd, vpnName, ifCnt);
-//                    if ((ifCnt != null) && (ifCnt > 0)) {
-//                        VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-//                                VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-//                                VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
-//                    }
                 }
             } else {
                 LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
@@ -1498,30 +1738,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             }
 
             //increment the vpn interface count in Vpn Instance Op Data
-            //Long ifCnt = 0L;
             VpnInstanceOpDataEntry vpnInstOp = null;
-//            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
-//                    updId = VpnUtil.getVpnInstanceToVpnIdIdentifier(update.getVpnInstanceName());
-//            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> updVpnInstance
-//                    = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, updId);
-//
-//            if (updVpnInstance.isPresent()) {
-//                String rd = null;
-//                rd = updVpnInstance.get().getVrfId();
-//
-//                vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
-//
-//                if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
-//                    ifCnt = vpnInstOp.getVpnInterfaceCount();
-//                }
-//
-//                LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in updated Vpn Op Instance {}", interfaceName, rd, ifCnt);
-//
-//                VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-//                        VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-//                        VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
-//            }
-//
             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
@@ -1553,54 +1770,18 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                             }
                         }
                     }
-//                        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-//                                VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
-//                                        prefixToInterface.get().getIpAddress()),
-//                                VpnUtil.DEFAULT_CALLBACK);
                     synchronized (interfaceName.intern()) {
                         for (Prefixes prefix : prefixToInterfaceList) {
-                            updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false);
+                            updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false, null);
                         }
                     }
                 }
             }
             notifyTaskIfRequired(interfaceName);
-//                if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
-//                    ifCnt = vpnInstOp.getVpnInterfaceCount();
-//                } else {
-//                    LOG.debug("VpnInterfaceOpListener update: Vpn interface count not recoverable from original, to handle update for rd {}", rd);
-//                    return;
-//                }
-//                LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in original Vpn Op Instance {}", interfaceName, rd, ifCnt);
-//
-//                if (ifCnt > 0) {
-//                    VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-//                            VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-//                            VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
-//                }
-//            }
         }
 
         @Override
         protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
-            final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
-            String interfaceName = key.getName();
-
-            //increment the vpn interface count in Vpn Instance Op Data
-//            Long ifCnt = 0L;
-//            String rd = getRouteDistinguisher(add.getVpnInstanceName());
-//            if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
-//            VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
-//            if(vpnInstOp != null &&  vpnInstOp.getVpnInterfaceCount() != null) {
-//                ifCnt = vpnInstOp.getVpnInterfaceCount();
-//            }
-
-//            LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
-
-//            VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-//                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-//                    VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
-
 
         }
     }
@@ -1626,6 +1807,23 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             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();
@@ -1694,9 +1892,6 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                                         rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
                                             }
                                             if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-                                                bgpManager.advertisePrefix( rd, adjacency.getIpAddress(),
-                                                                            adjacency.getNextHopIpList(),
-                                                                            adjacency.getLabel().intValue());
                                                 fibManager.populateFibOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
                                             }
                                         }
@@ -1708,7 +1903,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                                                 new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
                                                                 vpnId, rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
                                             }
-                                            if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+                                            if ((tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) &&
+                                                    (dcgwPresentStatus == VpnConstants.DCGWPresentStatus.Absent.getValue())) {
                                                 bgpManager.withdrawPrefix(rd, adjacency.getIpAddress());
                                                 fibManager.cleanUpDpnForVpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
                                             }
@@ -1726,6 +1922,22 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                         // 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);
                     }
@@ -1785,7 +1997,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
     }
 
-    protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
+    protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeTxn) {
         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);
@@ -1797,22 +2009,22 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 .OPERATIONAL, routerDpnListIdentifier);
         RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
         if (optionalRouterDpnList.isPresent()) {
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
-                    RouterInterfaces.class,  new RouterInterfacesKey(vpnInterfaceName)), routerInterface);
+            writeTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+                    RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
         } else {
-            MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-                    getRouterId(routerName),
-                    new RouterDpnListBuilder().setRouterId(routerName).build());
-            //VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
+            RouterDpnListBuilder builder = new RouterDpnListBuilder();
+            builder.setRouterId(routerName);
             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
             List<RouterInterfaces> routerInterfaces =  new ArrayList<>();
             routerInterfaces.add(routerInterface);
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier,
-                    dpnVpnList.setRouterInterfaces(routerInterfaces).build());
+            builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
+            writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+                    getRouterId(routerName),
+                    new RouterDpnListBuilder().setRouterId(routerName).build(), true);
         }
     }
 
-    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
+    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeTxn) {
         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);
@@ -1827,17 +2039,27 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
                 if (routerInterfaces.isEmpty()) {
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+                    if (writeTxn != null) {
+                        writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+                    } else {
+                        MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+                    }
                 } else {
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
-                            RouterInterfaces.class,
-                            new RouterInterfacesKey(vpnInterfaceName)));
+                    if (writeTxn != null) {
+                        writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+                                RouterInterfaces.class,
+                                new RouterInterfacesKey(vpnInterfaceName)));
+                    } else {
+                        MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+                                RouterInterfaces.class,
+                                new RouterInterfacesKey(vpnInterfaceName)));
+                    }
                 }
             }
         }
     }
 
-    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,BigInteger dpId) {
+    protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId, WriteTransaction writeTxn) {
         if(dpId.equals(BigInteger.ZERO)) {
             LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
             return;
@@ -1848,12 +2070,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         if (optionalRouterDpnList.isPresent()) {
             List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
             RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
-
             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
                 if (routerInterfaces.isEmpty()) {
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+                    writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
                 } else {
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+                    writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
                             RouterInterfaces.class,
                             new RouterInterfacesKey(vpnInterfaceName)));
                 }
index 381095172cdfa739cb35753eef927c4c72cabe72..d34b3fed03d13c8d2c9b5c145843a758649c82e4 100644 (file)
@@ -11,9 +11,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.*;
 
-import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.*;
 
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
@@ -51,8 +51,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
 
 public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
@@ -155,20 +153,6 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                     Thread.sleep(timeout);
                 } catch (java.lang.InterruptedException e) {
                 }
-//                Runnable notifyTask = new VpnNotifyTask();
-//                synchronized (rd.intern()) {
-//                    try {
-//                        vpnOpMap.put(rd, notifyTask);
-//                        synchronized (notifyTask) {
-//                            try {
-//                                notifyTask.wait(timeout);
-//                            } catch (InterruptedException e) {
-//                            }
-//                        }
-//                    } finally {
-//                        vpnOpMap.remove(rd);
-//                    }
-//                }
 
                 // Check current interface count
                 vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
@@ -222,81 +206,162 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         }
         LOG.info("Returned out of waiting for  Op Data removal for rd {}, vpnname {}", rd, vpnName);
     }
-
-
     @Override
     protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
         LOG.trace("Remove VPN event key: {}, value: {}", identifier, del);
-        String vpnName = del.getVpnInstanceName();
-        String rd = del.getIpv4Family().getRouteDistinguisher();
-        long vpnId = VpnUtil.getVpnId(broker, vpnName);
+        final String vpnName = del.getVpnInstanceName();
+        final String rd = del.getIpv4Family().getRouteDistinguisher();
+        final long vpnId = VpnUtil.getVpnId(broker, vpnName);
+        Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
 
         //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
-        Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
-        if ((rd != null) && (!rd.isEmpty())) {
-            vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
-                    VpnUtil.getVpnInstanceOpDataIdentifier(rd));
-        } else {
-            vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
-                    VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
+        try {
+            if ((rd != null) && (!rd.isEmpty())) {
+                vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+                        VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+            } else {
+                vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+                        VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
+            }
+        } catch (Exception e) {
+            LOG.error("Exception when attempting to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName, e);
+            return;
         }
 
-        if ((rd != null)  && (!rd.isEmpty())) {
-            waitForOpRemoval(rd, vpnName);
-        } else {
-            waitForOpRemoval(vpnName, vpnName);
+        if (vpnOpValue == null || !vpnOpValue.isPresent()) {
+            LOG.error("Unable to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName);
+            return;
         }
 
-        // Clean up VpnInstanceToVpnId from Config DS
-        VpnUtil.removeVpnIdToVpnInstance(broker, vpnId);
-        VpnUtil.removeVpnInstanceToVpnId(broker, vpnName);
-        LOG.trace("Removed vpnIdentifier for  rd{} vpnname {}", rd, vpnName);
-        if (rd != null) {
-            synchronized (rd.intern()) {
-                try {
-                    bgpManager.deleteVrf(rd);
-                } catch (Exception e) {
-                    LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
-                }
-            }
+        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+        dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+                new DeleteVpnInstanceWorker(idManager, broker, del));
+    }
 
-            // Clean up VPNExtraRoutes Operational DS
-            VpnUtil.removeVpnExtraRouteForVpn(broker, rd);
+    private class DeleteVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
+        IdManagerService idManager;
+        DataBroker broker;
+        VpnInstance vpnInstance;
+
+        public DeleteVpnInstanceWorker(IdManagerService idManager,
+                                       DataBroker broker,
+                                       VpnInstance value) {
+            this.idManager = idManager;
+            this.broker = broker;
+            this.vpnInstance = value;
+        }
 
-            // Clean up VPNInstanceOpDataEntry
-            VpnUtil.removeVpnOpInstance(broker, rd);
-        } else {
-            // Clean up FIB Entries Config DS
-            synchronized (vpnName.intern()) {
-                VpnUtil.removeVrfTableForVpn(broker, vpnName);
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            final String vpnName = vpnInstance.getVpnInstanceName();
+            final String rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
+            final long vpnId = VpnUtil.getVpnId(broker, vpnName);
+            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+            if ((rd != null) && (!rd.isEmpty())) {
+                waitForOpRemoval(rd, vpnName);
+            } else {
+                waitForOpRemoval(vpnName, vpnName);
             }
 
-            // Clean up VPNExtraRoutes Operational DS
-            VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName);
+            // Clean up VpnInstanceToVpnId from Config DS
+            VpnUtil.removeVpnIdToVpnInstance(broker, vpnId, writeTxn);
+            VpnUtil.removeVpnInstanceToVpnId(broker, vpnName, writeTxn);
+
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            futures.add(writeTxn.submit());
+            LOG.trace("Removed vpnIdentifier for  rd{} vpnname {}", rd, vpnName);
+            if (rd != null) {
+                synchronized (rd.intern()) {
+                    try {
+                        bgpManager.deleteVrf(rd);
+                    } catch (Exception e) {
+                        LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
+                    }
+                }
 
-            // Clean up VPNInstanceOpDataEntry
-            VpnUtil.removeVpnOpInstance(broker, vpnName);
-        }
+                // Clean up VPNExtraRoutes Operational DS
+                VpnUtil.removeVpnExtraRouteForVpn(broker, rd, null);
+
+                // Clean up VPNInstanceOpDataEntry
+                VpnUtil.removeVpnOpInstance(broker, rd, null);
+            } else {
+                // Clean up FIB Entries Config DS
+                synchronized (vpnName.intern()) {
+                    VpnUtil.removeVrfTableForVpn(broker, vpnName, null);
+                }
+                // Clean up VPNExtraRoutes Operational DS
+                VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, null);
+
+                // Clean up VPNInstanceOpDataEntry
+                VpnUtil.removeVpnOpInstance(broker, vpnName, null);
+            }
+            // Clean up PrefixToInterface Operational DS
+            VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId, null);
 
-        // Clean up PrefixToInterface Operational DS
-        VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId);
+            // Clean up L3NextHop Operational DS
+            VpnUtil.removeL3nexthopForVpnId(broker, vpnId, null);
 
-        // Clean up L3NextHop Operational DS
-        VpnUtil.removeL3nexthopForVpnId(broker, vpnId);
+            // Release the ID used for this VPN back to IdManager
+            VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
 
-        // Release the ID used for this VPN back to IdManager
-        VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
+            return futures;
+        }
     }
 
     @Override
     protected void update(InstanceIdentifier<VpnInstance> identifier,
-            VpnInstance original, VpnInstance update) {
+                          VpnInstance original, VpnInstance update) {
         LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
     }
 
     @Override
-    protected void add(InstanceIdentifier<VpnInstance> identifier, VpnInstance value) {
+    protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
         LOG.trace("Add VPN event key: {}, value: {}", identifier, value);
+        final VpnAfConfig config = value.getIpv4Family();
+        final String rd = config.getRouteDistinguisher();
+        final String vpnName = value.getVpnInstanceName();
+
+        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+        dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+                new AddVpnInstanceWorker(idManager, vpnInterfaceManager, broker, value));
+    }
+
+    private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
+        IdManagerService idManager;
+        VpnInterfaceManager vpnInterfaceManager;
+        VpnInstance vpnInstance;
+        DataBroker broker;
+
+        public AddVpnInstanceWorker(IdManagerService idManager,
+                                    VpnInterfaceManager vpnInterfaceManager,
+                                    DataBroker broker,
+                                    VpnInstance value) {
+            this.idManager = idManager;
+            this.vpnInterfaceManager = vpnInterfaceManager;
+            this.broker = broker;
+            this.vpnInstance = value;
+        }
+
+        @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.
+            final VpnAfConfig config = vpnInstance.getIpv4Family();
+            final String rd = config.getRouteDistinguisher();
+            WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+            addVpnInstance(vpnInstance, writeTxn);
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            futures.add(writeTxn.submit());
+            ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+            if (rd != null) {
+                Futures.addCallback(listenableFuture,
+                        new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
+            }
+            return futures;
+        }
+    }
+
+    private void addVpnInstance(VpnInstance value, WriteTransaction writeTxn) {
         VpnAfConfig config = value.getIpv4Family();
         String rd = config.getRouteDistinguisher();
         String vpnInstanceName = value.getVpnInstanceName();
@@ -304,19 +369,30 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
         LOG.trace("VPN instance to ID generated.");
         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
-            vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
-                                                                                                    : vpnInstanceName);
+                vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
+                : vpnInstanceName);
 
-        syncWrite(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
-                  vpnInstanceToVpnId, DEFAULT_CALLBACK);
+        if (writeTxn != null) {
+            writeTxn.put(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+                    vpnInstanceToVpnId, true);
+        } else {
+            syncWrite(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+                    vpnInstanceToVpnId, DEFAULT_CALLBACK);
+        }
 
-        VpnIds
+        org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
                 vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
-                (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/) ;
+                (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/);
 
-        syncWrite(LogicalDatastoreType.CONFIGURATION,
-                VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
-                vpnIdToVpnInstance, DEFAULT_CALLBACK);
+        if (writeTxn != null) {
+            writeTxn.put(LogicalDatastoreType.CONFIGURATION,
+                    VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
+                    vpnIdToVpnInstance, true);
+        } else {
+            syncWrite(LogicalDatastoreType.CONFIGURATION,
+                    VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
+                    vpnIdToVpnInstance, DEFAULT_CALLBACK);
+        }
 
         IFibManager fibManager = vpnInterfaceManager.getFibManager();
         try {
@@ -336,62 +412,93 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
             LOG.error(e.getMessage());
         }
 
-        if(rd == null) {
+        if (rd == null) {
             VpnInstanceOpDataEntryBuilder builder =
-                new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
-                                                   .setVpnInstanceName(vpnInstanceName)
-                                                   .setVpnInterfaceCount(0L);
-            syncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
-                      builder.build(), DEFAULT_CALLBACK);
-
+                    new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
+                            .setVpnInstanceName(vpnInstanceName)
+                            .setVpnInterfaceCount(0L).setActiveDpnCount(0L);
+            if (writeTxn != null) {
+                writeTxn.merge(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
+                        builder.build(), true);
+            } else {
+                syncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
+                        builder.build(), DEFAULT_CALLBACK);
+            }
         } else {
             VpnInstanceOpDataEntryBuilder builder =
-                new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName)
-                                                   .setVpnInterfaceCount(0L);
-            syncWrite(LogicalDatastoreType.OPERATIONAL,
-                      VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-                      builder.build(), DEFAULT_CALLBACK);
+                    new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName)
+                            .setVpnInterfaceCount(0L).setActiveDpnCount(0L);
 
-            List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+            if (writeTxn != null) {
+                writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+                        VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                        builder.build(), true);
+            } else {
+                syncWrite(LogicalDatastoreType.OPERATIONAL,
+                        VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                        builder.build(), DEFAULT_CALLBACK);
+            }
+        }
+    }
 
-            List<String> ertList = new ArrayList<String>();
-            List<String> irtList = new ArrayList<String>();
 
-            for (VpnTarget vpnTarget : vpnTargetList) {
-                if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
-                    ertList.add(vpnTarget.getVrfRTValue());
-                }
-                if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
-                    irtList.add(vpnTarget.getVrfRTValue());
-                }
-                if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
-                    ertList.add(vpnTarget.getVrfRTValue());
-                    irtList.add(vpnTarget.getVrfRTValue());
-                }
-            }
+    private class AddBgpVrfWorker implements FutureCallback<List<Void>> {
+        VpnAfConfig config;
+        String vpnName;
 
-            try {
-                bgpManager.addVrf(rd, irtList, ertList);
-            } catch(Exception e) {
-                LOG.error("Exception when adding VRF to BGP", e);
-            }
+        public AddBgpVrfWorker(VpnAfConfig config, String vpnName)  {
+            this.config = config;
+            this.vpnName = vpnName;
         }
-        //Try to add up vpn Interfaces if already in Operational Datastore
-        InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
-        Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, vpnInterfacesId);
-
-        if(optionalVpnInterfaces.isPresent()) {
-            List<VpnInterface> vpnInterfaces = optionalVpnInterfaces.get().getVpnInterface();
-            for(VpnInterface vpnInterface : vpnInterfaces) {
-                if(vpnInterface.getVpnInstanceName().equals(vpnInstanceName)) {
-                    LOG.debug("VpnInterface {} will be added from VPN {}", vpnInterface.getName(), vpnInstanceName);
-                    vpnInterfaceManager.add(
-                                VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
 
+        /**
+         * @param voids
+         * This implies that all the future instances have returned success. -- TODO: Confirm this
+         */
+        @Override
+        public void onSuccess(List<Void> voids) {
+            String rd = config.getRouteDistinguisher();
+            if (rd != null) {
+                List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+
+                List<String> ertList = new ArrayList<String>();
+                List<String> irtList = new ArrayList<String>();
+
+                for (VpnTarget vpnTarget : vpnTargetList) {
+                    if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+                        ertList.add(vpnTarget.getVrfRTValue());
+                    }
+                    if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+                        irtList.add(vpnTarget.getVrfRTValue());
+                    }
+                    if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+                        ertList.add(vpnTarget.getVrfRTValue());
+                        irtList.add(vpnTarget.getVrfRTValue());
+                    }
+                }
+
+                try {
+                    bgpManager.addVrf(rd, irtList, ertList);
+                } catch (Exception e) {
+                    LOG.error("Exception when adding VRF to BGP", e);
+                    return;
                 }
+                vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
             }
         }
-        vpnInterfaceManager.handleVpnsExportingRoutes(vpnInstanceName, rd);
+        /**
+         *
+         * @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());
+        }
     }
 
     public boolean isVPNConfigured() {
index 303e9137c544d5de22a83b5d95bdb5eaee459231..5bada7e936698ea2a412f9bb4fcaddde294a46ed 100644 (file)
@@ -136,7 +136,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);
+            VpnUtil.addFibEntryToDS(dataBroker, vpnRd, destination, nexthop, label.intValue(), RouteOrigin.STATIC , null);
         } else {
             vpnInterfaceMgr.addExtraRoute(destination, nexthop, vpnRd, null /*routerId */, label.intValue(),
                                           null /* intfName */);
@@ -193,7 +193,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);
+            VpnUtil.removeFibEntryFromDS(dataBroker,  vpnRd, destination, nexthop, null);
         } else {
             vpnInterfaceMgr.delExtraRoute(destination, nexthop, vpnRd, null /*routerId*/, null /*intfName*/);
         }
index 33fa34ce29405df3557523714f9ce06818571d2f..796057cd56cb130e8464eb8c3035090e09d9b9a9 100644 (file)
@@ -468,21 +468,19 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
         }
     }
 
-    public void onInterfaceUp(Interface intfState) {
-
-        logger.info("onInterfaceUp: Port " + intfState.getName());
+    public void onInterfaceUp(BigInteger dpnId, String intfName) {
+        logger.info("onInterfaceUp: Port " + intfName);
         //TODO(vivek): Change this to use more granularized lock at subnetId level
         synchronized (this) {
             SubnetToDpn subDpn = null;
-            String intfName = intfState.getName();
             PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
             if (portOpEntry == null) {
-                logger.info("onInterfaceUp: Port " + intfState.getName()  + "is part of a subnet not in VPN, ignoring");
+                logger.info("onInterfaceUp: Port " + intfName  + "is part of a subnet not in VPN, ignoring");
                 return;
             }
-            BigInteger dpnId = portOpEntry.getDpnId();
-            if (dpnId  == null) {
-                dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+
+            if ((dpnId == null) || (dpnId == BigInteger.ZERO)) {
+                dpnId = portOpEntry.getDpnId();
                 if (dpnId == null) {
                     logger.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
                     return;
@@ -542,28 +540,23 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
         }
     }
 
-    public void onInterfaceDown(Interface intfState) {
-        logger.info("onInterfaceDown: Port " + intfState.getName());
+    public void onInterfaceDown(final BigInteger dpnId, final String interfaceName) {
+        logger.info("onInterfaceDown: Port " + interfaceName);
         //TODO(vivek): Change this to use more granularized lock at subnetId level
         synchronized (this) {
-            String intfName = intfState.getName();
-            PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
+            PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(interfaceName);
             if (portOpEntry == null) {
-                logger.info("onInterfaceDown: Port " + intfState.getName()  + "is part of a subnet not in VPN, ignoring");
+                logger.info("onInterfaceDown: Port " + interfaceName  + "is part of a subnet not in VPN, ignoring");
                 return;
             }
-            BigInteger dpnId = portOpEntry.getDpnId();
-            if (dpnId  == null) {
-                dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
-                if (dpnId == null) {
-                    logger.error("onInterfaceDown: Unable to determine the DPNID for port " + intfName);
-                    return;
-                }
+            if ((dpnId  == null) ||(dpnId == BigInteger.ZERO)) {
+                logger.error("onInterfaceDown: Unable to determine the DPNID for port " + interfaceName);
+                return;
             }
             Uuid subnetId = portOpEntry.getSubnetId();
             try {
                 logger.debug("onInterfaceDown: Updating the SubnetOpDataEntry node for subnet: " +  subnetId.getValue());
-                boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, intfName);
+                boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, interfaceName);
                 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
                         child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
                 Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
@@ -585,7 +578,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                 if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
                     // select another NhDpnId
                     if (last) {
-                        logger.debug("onInterfaceDown: Last active port " + intfState.getName() + " on the subnet: " +  subnetId.getValue());
+                        logger.debug("onInterfaceDown: Last active port " + interfaceName + " on the subnet: " +  subnetId.getValue());
                         // last port on this DPN, so we need to swap the NHDpnId
                         subDpnList = subOpBuilder.getSubnetToDpn();
                         if (subDpnList.isEmpty()) {
@@ -621,7 +614,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                 }
                 subOpEntry = subOpBuilder.build();
                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
-                logger.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + intfName);
+                logger.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + interfaceName);
             } catch (Exception ex) {
                 logger.error("Creation of SubnetOpDataEntry for subnet " +
                         subnetId.getValue() + " failed {}" + ex);
@@ -646,7 +639,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
         Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
         String nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, nhDpnId);
         if(nexthopIp != null)
-            vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId);
+            vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId , null);
         else
             logger.info("Unable to get nextHop ip address for nextHop DPN {}. Abort adding subnet route to FIB table.", nhDpnId);
     }
index 32f0c72a7e070bf6d331ae67ecaa608850d515b8..295c8a9df78526b71b53ea2c8007d00df0d29833 100644 (file)
@@ -478,21 +478,30 @@ public class VpnUtil {
      * @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) {
+    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 vrfEntry = getVrfEntry(broker, rd, prefix);
+            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
-                VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
-                        vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry);
+                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))
@@ -501,7 +510,11 @@ public class VpnUtil {
                 currentVrfEntries.add(vrfEntry);
                 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(
                         currentVrfEntries).build();
-                VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+                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);
         }
@@ -518,7 +531,8 @@ public class VpnUtil {
      * @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) {
+    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);
 
@@ -540,15 +554,24 @@ public class VpnUtil {
 
                 if (nhListRead.isEmpty()) {
                     // Remove the whole entry
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+                    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();
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-                    MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, 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);
                 }
             }
@@ -612,6 +635,14 @@ public class VpnUtil {
                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
     }
 
+    static RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
+        Optional<RouterInterface> optRouterInterface = read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
+        if(optRouterInterface.isPresent()) {
+            return optRouterInterface.get();
+        }
+        return null;
+    }
+
     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
                 getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) {
         return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsBuilder()
@@ -974,73 +1005,106 @@ public class VpnUtil {
         // DPN has gone down (and the VpnToDpnMap has been removed in a different Thread)
     }
 
-    public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId) {
+    public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
         try {
             // Clean up PrefixToInterface Operational DS
-            delete(broker, LogicalDatastoreType.OPERATIONAL,
-                    InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(PrefixToInterface.class).child(
+                                VpnIds.class, new VpnIdsKey(vpnId)).build());
+            } else {
+                delete(broker, LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during cleanup of PrefixToInterface for VPN ID {}", vpnId, e);
         }
     }
 
-    public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName) {
+    public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
         try {
             // Clean up VPNExtraRoutes Operational DS
-            delete(broker, LogicalDatastoreType.OPERATIONAL,
-                    InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build());
+            } else {
+                delete(broker, LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during cleanup of VPNToExtraRoute for VPN {}", vpnName, e);
         }
     }
 
-    public static void removeVpnOpInstance(DataBroker broker, String vpnName) {
+    public static void removeVpnOpInstance(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
         try {
             // Clean up VPNInstanceOpDataEntry
-            delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName));
+            } else {
+                delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during cleanup of VPNInstanceOpDataEntry for VPN {}", vpnName, e);
         }
     }
 
-    public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName) {
+    public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
         try {
-            delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName));
+            } else {
+                delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during clean up of VpnInstanceToVpnId for VPN {}", vpnName, e);
         }
     }
 
-    public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId) {
+    public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
         try {
-            delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId));
+            } else {
+                delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during clean up of VpnIdToVpnInstance for VPNID {}", vpnId, e);
         }
     }
 
-    public static void removeVrfTableForVpn(DataBroker broker, String vpnName) {
+    public static void removeVrfTableForVpn(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
         // Clean up FIB Entries Config DS
         try {
-            delete(broker, LogicalDatastoreType.CONFIGURATION,
-                    InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
+                        InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build());
+            } else {
+                delete(broker, LogicalDatastoreType.CONFIGURATION,
+                        InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during clean up of VrfTable from FIB for VPN {}", vpnName, e);
         }
     }
 
-    public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId) {
+    public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
         try {
             // Clean up L3NextHop Operational DS
-            delete(broker, LogicalDatastoreType.OPERATIONAL,
-                    InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
-                    DEFAULT_CALLBACK);
+            if (writeTxn != null) {
+                writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build());
+            } else {
+                delete(broker, LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
+                        DEFAULT_CALLBACK);
+            }
         } catch (Exception e) {
             LOG.error("Exception during cleanup of L3NextHop for VPN ID {}", vpnId, e);
         }
@@ -1268,11 +1332,14 @@ public class VpnUtil {
         return result;
     }
 
-    public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId, String vpnInstanceName, Boolean isScheduledToRemove){
+    public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId,
+                                          String vpnInstanceName, Boolean isScheduledToRemove,
+                                          WriteTransaction writeTxn){
         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
         VpnInterface interfaceToUpdate = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName)).setName(interfaceName)
                 .setDpnId(dpnId).setVpnInstanceName(vpnInstanceName).setScheduledForRemove(isScheduledToRemove).build();
-        VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
+        writeTxn.merge(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate, true);
+        //VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
     }
 
     protected static void createVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
index de46e61ae77e15f890cbde3b23667aca5027c4e3..061da52417f23565b11d54257b36904cf6e16057 100644 (file)
@@ -338,7 +338,7 @@ public class VpnSubnetRouteHandlerTest {
     @Test
     public void testOnInterfaceUp() {
 
-        vpnSubnetRouteHandler.onInterfaceUp(stateInterface);
+        vpnSubnetRouteHandler.onInterfaceUp(dpId, interfaceName);
 
         verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, instPortOp, portOp, true);
         verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
@@ -348,7 +348,7 @@ public class VpnSubnetRouteHandlerTest {
     @Test
     public void testOnInterfaceDown() {
 
-        vpnSubnetRouteHandler.onInterfaceDown(stateInterface);
+        vpnSubnetRouteHandler.onInterfaceDown(dpId, interfaceName);
 
         verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, dpnOpId);
         verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);