Multiple fixes in different module 76/41776/10
authorSuraj Ranjan <suraj.ranjan@ericsson.com>
Wed, 13 Jul 2016 16:06:40 +0000 (21:36 +0530)
committerSam Hague <shague@redhat.com>
Sat, 16 Jul 2016 16:12:50 +0000 (12:12 -0400)
This commit includes following changes and bug fixes:

  - Additional check when handling operational ds of vpn interface
  - Performance Issue: Association/Dissociation of router takes
    huge time.
  - All Internal VPN(ROUTER) Ip's not coming on deletion of L3VPN
  - NextHop for SubnetRoute not re-programmed in DCGW after a DPN
    disconnect.
  - NextHop for Subnet route not re-programmed on DC-GW.
  - Some of VM entries and Invisible IPs of VM are not in FIB
  - Fixed disassociate of floating ip
  - New Invisible IP is not reachable from
    DC/DC-GW after reboot

Change-Id: I3b0e6cc1fc9f8396d93b5391efaaefcac4b8eabd
Signed-off-by: Suraj Ranjan <suraj.ranjan@ericsson.com>
Signed-off-by: Sam Hague <shague@redhat.com>
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManager.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java
vpnservice/vpnmanager/vpnmanager-api/src/main/yang/odl-l3vpn.yang
vpnservice/vpnmanager/vpnmanager-impl/pom.xml
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/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 9fdec88be115c10e3dc0e0ab620d993828e9ec63..096924c76d2705f030a68b147f28f9e060d77d23 100644 (file)
@@ -27,7 +27,6 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataCh
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
-import org.opendaylight.genius.itm.globals.ITMConstants;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.ActionType;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
@@ -39,12 +38,10 @@ import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RdToElanOp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroute;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
@@ -269,10 +266,8 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
               NwConstants.TABLE_MISS_PRIORITY, "Subnet Route Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
 
       if (addOrRemove == NwConstants.ADD_FLOW) {
-          LOG.debug("Invoking MDSAL to install SubnetRoute Table Miss Entries for DPN" + dpnId);
           mdsalManager.installFlow(flowEntity);
       } else {
-          LOG.debug("Invoking MDSAL to remove SubnetRoute Table Miss Entries for DPN " + dpnId);
           mdsalManager.removeFlow(flowEntity);
       }
   }
@@ -333,7 +328,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
       createTerminatingServiceActions(dpId, (int)label, actionsInfos);
 
-      LOG.debug("Terminating service Entry for dpID {} : label : {} egress : {} installed successfully {}",
+      LOG.debug("Terminating service Entry for dpID {} : label : {} egress : {} installed successfully",
               dpId, label, groupId);
   }
 
@@ -368,7 +363,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                                            5, String.format("%s:%d","TST Flow Entry ",label), 0, 0,
                                            COOKIE_TUNNEL.add(BigInteger.valueOf(label)), mkMatches, null);
     mdsalManager.removeFlow(flowEntity);
-    LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpId, label);
+    LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully",dpId, label);
   }
 
   public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
@@ -447,7 +442,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                                     final long vpnId, final VrfTablesKey vrfTableKey,
                                     final VrfEntry vrfEntry) {
     String rd = vrfTableKey.getRouteDistinguisher();
-    LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
+    LOG.debug("createremotefibentry: adding route {} for rd {}", vrfEntry.getDestPrefix(), rd);
     /********************************************/
     String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
     if(tunnelInterface == null) {
@@ -507,7 +502,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     }
 **/
       makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW);
-      LOG.debug("Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
+      LOG.debug("Successfully added fib entry for prefix {} in vpn {} ", vrfEntry.getDestPrefix(), vpnId);
   }
 
   private void delIntfFromDpnToVpnList(long vpnId, BigInteger dpnId, String intfName, String rd) {
@@ -544,6 +539,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
          - prefix to interface entry
          - vpn interface op DS
      */
+      LOG.debug("Cleanup of prefix {} in VPN {}", vrfEntry.getDestPrefix(), vpnId);
       Prefixes prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
       Extraroute extraRoute = null;
       if (prefixInfo == null) {
@@ -551,36 +547,57 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
           if(extraRoute != null) {
               prefixInfo = getPrefixToInterface(vpnId, extraRoute.getNexthopIp() + "/32");
               //clean up the vpn to extra route entry in DS
-              FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
+              //FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnToExtrarouteIdentifier(rd,
+                //      vrfEntry.getDestPrefix()));
           }
       }
       if (prefixInfo == null) {
-          LOG.debug("Cleanup VPN Data Failed as unable to find prefix Info for " + vrfEntry.getDestPrefix());
+          LOG.debug("Cleanup VPN Data Failed as unable to find prefix Info for prefix {}" , vrfEntry.getDestPrefix());
           return; //Don't have any info for this prefix (shouldn't happen); need to return
       }
       String ifName = prefixInfo.getVpnInterfaceName();
-      Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
-      int numAdj = 0;
-      if (optAdjacencies.isPresent()) {
-          numAdj = optAdjacencies.get().getAdjacency().size();
-      }
-      LOG.trace("cleanUpOpDataForFib: remove adjacency for prefix: {} {}", vpnId, vrfEntry.getDestPrefix());
-      //remove adjacency corr to prefix
-      if (numAdj > 1) {
-        FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                         FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
-      }
+      synchronized (ifName.intern()) {
+          Optional<VpnInterface> optvpnInterface = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnInterfaceIdentifier(ifName));
+          if (optvpnInterface.isPresent()) {
+              long associatedVpnId = FibUtil.getVpnId(broker, optvpnInterface.get().getVpnInstanceName());
+              if (vpnId != associatedVpnId) {
+                  LOG.warn("Prefixes {} are associated with different vpn instance with id : {} rather than {}",
+                          vrfEntry.getDestPrefix(), associatedVpnId, vpnId);
+                  LOG.trace("Releasing prefix label - rd {}, prefix {}", rd, vrfEntry.getDestPrefix());
+                  FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
+                          FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
+                  LOG.warn("Not proceeding with Cleanup op data for prefix {}", vrfEntry.getDestPrefix());
+                  return;
+              } else {
+                  LOG.debug("Processing cleanup of prefix {} associated with vpn {}", vrfEntry.getDestPrefix(), associatedVpnId);
+              }
+          }
+          if (extraRoute != null) {
+              FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
+          }
+          Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
+          int numAdj = 0;
+          if (optAdjacencies.isPresent()) {
+              numAdj = optAdjacencies.get().getAdjacency().size();
+          }
 
-      if ((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
-          //clean up the vpn interface from DpnToVpn list
-          LOG.trace("Clean up vpn interface {} from dpn {} to vpn {} list.", ifName, prefixInfo.getDpnId(), rd);
-          FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                         FibUtil.getVpnInterfaceIdentifier(ifName));
-      }
+          //remove adjacency corr to prefix
+          if (numAdj > 1) {
+              LOG.trace("cleanUpOpDataForFib: remove adjacency for prefix: {} {}", vpnId, vrfEntry.getDestPrefix());
+              FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                      FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+          }
 
-      FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
-         FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
+          if ((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
+              //clean up the vpn interface from DpnToVpn list
+              LOG.trace("Clean up vpn interface {} from dpn {} to vpn {} list.", ifName, prefixInfo.getDpnId(), rd);
+              FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                      FibUtil.getVpnInterfaceIdentifier(ifName));
+          }
 
+          FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
+                  FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
+      }
   }
 
   private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier,
@@ -664,12 +681,16 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     String values[] = vrfEntry.getDestPrefix().split("/");
     String ipAddress = values[0];
     int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
-    LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
+    if (addOrRemove == NwConstants.ADD_FLOW) {
+        LOG.debug("Adding route to DPN {} for rd {} prefix {} ", dpId, rd, vrfEntry.getDestPrefix());
+    } else {
+        LOG.debug("Removing route from DPN {} for rd {} prefix {}", dpId, rd, vrfEntry.getDestPrefix());
+    }
     InetAddress destPrefix = null;
     try {
       destPrefix = InetAddress.getByName(ipAddress);
     } catch (UnknownHostException e) {
-      LOG.error("UnknowHostException in addRoute. Failed  to add Route for ipPrefix {}", vrfEntry.getDestPrefix());
+      LOG.error("Failed to get destPrefix for prefix {} ", vrfEntry.getDestPrefix(), e);
       return;
     }
 
@@ -801,8 +822,6 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                 makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
                 makeLFibTableEntry(dpnId, vrfEntry.getLabel(), null,
                         vrfEntry.getNextHopAddress(),NwConstants.DEL_FLOW);
-                FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
-                        FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
                 LOG.trace("cleanUpDpnForVpn: Released subnetroute label {} for rd {} prefix {}", vrfEntry.getLabel(), rd,
                         vrfEntry.getDestPrefix());
                 continue;
index d264e9c94ba1a50bf34c07f9d3e97c022c151431..d2803c51fce8e3fa7621dafb66d1b7289a87ab18 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
@@ -125,6 +126,32 @@ public class FibUtil {
         }
     }
 
+    static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
+            .vpn.id.VpnInstance>
+    getVpnInstanceToVpnIdIdentifier(String vpnName) {
+        return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+                .VpnInstance.class,
+                        new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+                                .VpnInstanceKey(vpnName)).build();
+    }
+
+    static long getVpnId(DataBroker broker, String vpnName) {
+
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+                .VpnInstance> id
+                = getVpnInstanceToVpnIdIdentifier(vpnName);
+        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+                .VpnInstance> vpnInstance
+                = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+        long vpnId = -1;
+        if(vpnInstance.isPresent()) {
+            vpnId = vpnInstance.get().getVpnId();
+        }
+        return vpnId;
+    }
+
     static final FutureCallback<Void> DEFAULT_CALLBACK =
             new FutureCallback<Void>() {
                 public void onSuccess(Void result) {
index a8fbb6635585975927b7d4476a67c8745af66aa1..76dc9af1e38dad2b8c684c2650ab8f4405146cb5 100644 (file)
@@ -159,6 +159,7 @@ module odl-l3vpn {
 
 
     container subnet-op-data {
+        config false;
         list subnet-op-data-entry {
             key subnet-id;
             leaf subnet-id {
@@ -204,6 +205,7 @@ module odl-l3vpn {
     }
 
     container port-op-data {
+        config false;
         list port-op-data-entry {
             key port-id;
             leaf port-id {
@@ -220,27 +222,6 @@ module odl-l3vpn {
         }
     }
 
-    container rd-to-elan-op{
-        list rd-to-elan-op-entry{
-            key "rd subnet-ip";
-            leaf rd {
-                type string;
-            }
-            leaf subnet-ip {
-                type string;
-            }
-            leaf next-hop-ip {
-                type string;
-            }
-            leaf vpn-name {
-                type string;
-            }
-            leaf elan-tag{
-                type uint32;
-            }
-        }
-    }
-
     grouping dpn-in-vpn-event {
             leaf dpn-id { type uint64; }
             leaf vpn-name { type string; }
index 2b23e0987e0a595b5fc7a0f8613b4b7d38c28072..eb16fffe883d82be83b4752347e5b49f6a9b684c 100644 (file)
@@ -75,6 +75,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-broker-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netvirt</groupId>
+      <artifactId>natservice-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
   </dependencies>
 
   <!--
index fff56b1e0e2dc5b88ea13ea5adddae4015582c14..bb5718c38796387e9213518f02784cf5f4297ae9 100644 (file)
@@ -21,8 +21,9 @@ public class VpnConstants {
     public static final BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
     public static final BigInteger COOKIE_L3_BASE = new BigInteger("8000000", 16);
     public static final String FLOWID_PREFIX = "L3.";
-    public static final long MIN_WAIT_TIME_IN_MILLISECONDS = 10000;
+    public static final long MIN_WAIT_TIME_IN_MILLISECONDS = 5000;
     public static final long MAX_WAIT_TIME_IN_MILLISECONDS = 90000;
+    public static final long PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS = 10000;
     public static final int ELAN_GID_MIN = 200000;
     public static final short ELAN_SMAC_TABLE = 50;
     public static final short FIB_TABLE = 21;
index 080598bb5fc0a8eee21f3475f36b7ed254c968f5..cd0ab785fd239c3809e4600160d96715cffe9754 100644 (file)
@@ -93,10 +93,8 @@ import org.slf4j.LoggerFactory;
 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
     private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
-    private ConcurrentMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
     private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
         .setNameFormat("NV-VpnIntfMgr-%d").build();
-    private ExecutorService executorService = Executors.newSingleThreadExecutor(threadFactory);
     private final DataBroker broker;
     private final IBgpManager bgpManager;
     private IFibManager fibManager;
@@ -107,6 +105,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     private OdlArputilService arpManager;
     private NeutronvpnService neuService;
     private VpnSubnetRouteHandler vpnSubnetRouteHandler;
+    private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
     private InterfaceStateChangeListener interfaceListener;
     private VpnInterfaceOpListener vpnInterfaceOpListener;
     private ArpNotificationHandler arpNotificationHandler;
@@ -237,16 +237,85 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
             return;
         }
+        boolean waitForVpnInterfaceOpRemoval = false;
+        int numAdjs = 0;
+        VpnInterface opVpnInterface = null;
         synchronized (interfaceName.intern()) {
-            if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) {
-                LOG.trace("VPN Interface already provisioned , bailing out from here.");
+            opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName());
+            if (opVpnInterface != null ) {
+                String opVpnName = opVpnInterface.getVpnInstanceName();
+                String primaryInterfaceIp = null;
+                if(opVpnName.equals(vpnName)) {
+                    // Please check if the primary VRF Entry does not exist for VPNInterface
+                    // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
+                    // back to back
+                    // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
+                    List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(broker, interfaceName);
+                    if (adjs == null) {
+                        LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained",
+                                interfaceName);
+                        return;
+                    }
+                    numAdjs = adjs.size();
+                    for (Adjacency adj : adjs) {
+                        if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
+                            primaryInterfaceIp = adj.getNextHopIp();
+                            break;
+                        }
+                    }
+                    if (primaryInterfaceIp == null) {
+                        LOG.info("VPN Interface {} addition failed as primary adjacency for this vpn interface could not be obtained",
+                                interfaceName);
+                        return;
+                    }
+                    // Get the rd of the vpn instance
+                    String rd = getRouteDistinguisher(opVpnName);
+                    VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, primaryInterfaceIp);
+                    if (vrf != null) {
+                        LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
+                        return;
+                    }
+                    waitForVpnInterfaceOpRemoval = true;
+                } else {
+                    LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}", interfaceName, vpnName, opVpnName);
+                }
+            }
+            if (!waitForVpnInterfaceOpRemoval) {
+                // Add the VPNInterface and quit
+                bindService(dpId, vpnName, interfaceName, lPortTag);
+                updateDpnDbs(dpId, vpnName, interfaceName, true);
+                processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
                 return;
             }
+        }
+
+        // FIB didn't get a chance yet to clean up this VPNInterface
+        // Let us give it a chance here !
+        LOG.info("VPN Interface {} waiting for FIB to clean up! ", interfaceName);
+        try {
+            Runnable notifyTask = new VpnNotifyTask();
+            vpnIntfMap.put(interfaceName, notifyTask);
+            synchronized (notifyTask) {
+                try {
+                    notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
+                } catch (InterruptedException e) {
+                }
+            }
+        } finally {
+            vpnIntfMap.remove(interfaceName);
+        }
+
+        opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
+        if (opVpnInterface != null) {
+            LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
+            return;
+        }
+        // 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);
         }
-
     }
 
     private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
@@ -513,20 +582,24 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             removeAdjacenciesFromVpn(identifier, vpnInterface);
             LOG.info("Unbinding vpn service from interface {} ", interfaceName);
             unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
+        }
 
-            //wait till DCN for removal of vpn interface in operational DS arrives
+        // 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();
-            synchronized (interfaceName.intern()) {
-                vpnIntfMap.put(interfaceName, notifyTask);
-                synchronized (notifyTask) {
-                    try {
-                        notifyTask.wait(VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS);
-                    } catch (InterruptedException e) {
-                    }
+            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 InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
@@ -567,10 +640,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
                                int lPortTag, boolean isInterfaceStateDown) {
         if (!isInterfaceStateDown) {
-            VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
+            MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
                            InterfaceUtils.buildServiceId(vpnInterfaceName,
-                                                         VpnConstants.L3VPN_SERVICE_IDENTIFIER),
-                           VpnUtil.DEFAULT_CALLBACK);
+                                                         VpnConstants.L3VPN_SERVICE_IDENTIFIER));
         }
         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
@@ -581,8 +653,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
 
     private void removePrefixFromBGP(String rd, String prefix) {
+        removeFibEntryFromDS(rd, prefix);
         try {
-            bgpManager.deletePrefix(rd, prefix);
+            bgpManager.withdrawPrefix(rd, prefix);
         } catch(Exception e) {
             LOG.error("Delete prefix failed", e);
         }
@@ -713,7 +786,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         InstanceIdentifierBuilder<VrfEntry> idBuilder =
             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
-        VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
+        MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
 
     }
 
@@ -885,17 +958,19 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                                 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
                                         prefixToInterface.get().getIpAddress()),
                                 VpnUtil.DEFAULT_CALLBACK);
-                        updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false);
-                    }
-                    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);
+                        synchronized (interfaceName.intern()) {
+                            updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false);
+                        }
                     }
+//                    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);
@@ -906,6 +981,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         private void notifyTaskIfRequired(String intfName) {
             Runnable notifyTask = vpnIntfMap.remove(intfName);
             if (notifyTask == null) {
+                LOG.trace("VpnInterfaceOpListener update: No Notify Task queued for vpnInterface {}", intfName);
                 return;
             }
             executorService.execute(notifyTask);
@@ -913,6 +989,93 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
         @Override
         protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
+            final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+            String interfaceName = key.getName();
+
+            if (original.getVpnInstanceName().equals(update.getVpnInstanceName())) {
+                return;
+            }
+
+            //increment the vpn interface count in Vpn Instance Op Data
+            //Long ifCnt = 0L;
+            VpnInstanceOpDataEntry vpnInstOp = null;
+//            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
+//                    .vpn.id.VpnInstance>
+//                    updId = VpnUtil.getVpnInstanceToVpnIdIdentifier(update.getVpnInstanceName());
+//            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.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
+                    = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, origId);
+
+            if (origVpnInstance.isPresent()) {
+                String rd = null;
+                rd = origVpnInstance.get().getVrfId();
+
+                vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+                LOG.trace("VpnInterfaceOpListener updated: interface name {} original rd {} original vpnName {}",
+                        interfaceName, rd, original.getVpnInstanceName());
+
+                if (vpnInstOp != null) {
+                    Adjacency adjacency = original.getAugmentation(Adjacencies.class).getAdjacency().get(0);
+                    Optional<Prefixes> prefixToInterface = Optional.absent();
+                    prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+                            VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+                                    VpnUtil.getIpPrefix(adjacency.getIpAddress())));
+                    if (!prefixToInterface.isPresent()) {
+                        prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+                                VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+                                        VpnUtil.getIpPrefix(adjacency.getNextHopIp())));
+                    }
+                    if (prefixToInterface.isPresent()) {
+//                        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+//                                VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+//                                        prefixToInterface.get().getIpAddress()),
+//                                VpnUtil.DEFAULT_CALLBACK);
+                        synchronized (interfaceName.intern()) {
+                            updateDpnDbs(prefixToInterface.get().getDpnId(), original.getVpnInstanceName(), interfaceName, false);
+                        }
+                    }
+                }
+            }
+            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
@@ -921,20 +1084,20 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             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);
-
+//            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);
 
         }
     }
index a882405b1d2ee85841eaca620d981915a57d5fcf..1fde4894af95be87d7edc58b1e9d725977e5f4e5 100644 (file)
@@ -25,6 +25,9 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 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.VpnInstanceOpDataEntryKey;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op
+        .data.entry.VpnToDpnList;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -116,23 +119,98 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         this.vpnInterfaceManager = vpnInterfaceManager;
     }
 
-    private void waitForOpRemoval(String id, long timeout) {
+    private void waitForOpRemoval(String rd, String vpnName) {
         //wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is zero
-        Runnable notifyTask = new VpnNotifyTask();
-        synchronized (id.intern()) {
-            try {
-                vpnOpMap.put(id, notifyTask);
-                synchronized (notifyTask) {
-                    try {
-                        notifyTask.wait(timeout);
-                    } catch (InterruptedException e) {
+        //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
+        VpnInstanceOpDataEntry vpnOpEntry = null;
+        Long intfCount = 0L;
+        Long currentIntfCount = 0L;
+        long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
+        Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
+        vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+                VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+
+        if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
+            vpnOpEntry = vpnOpValue.get();
+            List<VpnToDpnList> dpnToVpns = vpnOpEntry.getVpnToDpnList();
+            if (dpnToVpns != null) {
+                for (VpnToDpnList dpn : dpnToVpns) {
+                    if (dpn.getVpnInterfaces() != null) {
+                        intfCount = intfCount + dpn.getVpnInterfaces().size();
                     }
                 }
-            } finally {
-                vpnOpMap.remove(id);
             }
-        }
+            //intfCount = vpnOpEntry.getVpnInterfaceCount();
+            while (true) {
+                if (intfCount > 0) {
+                    // Minimum wait time of 5 seconds for one VPN Interface clearance (inclusive of full trace on)
+                    timeout = intfCount * VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
+                    // Maximum wait time of 90 seconds for all VPN Interfaces clearance (inclusive of full trace on)
+                    if (timeout > VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS) {
+                        timeout = VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS;
+                    }
+                    LOG.info("VPNInstance removal count of interface at {} for for rd {}, vpnname {}",
+                            intfCount, rd, vpnName);
+                }
+                LOG.info("VPNInstance removal thread waiting for {} seconds for rd {}, vpnname {}",
+                        (timeout / 1000), rd, vpnName);
 
+                try {
+                    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,
+                        VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+                if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
+                    vpnOpEntry = vpnOpValue.get();
+                    dpnToVpns = vpnOpEntry.getVpnToDpnList();
+                    currentIntfCount = 0L;
+                    if (dpnToVpns != null) {
+                        for (VpnToDpnList dpn : dpnToVpns) {
+                            if (dpn.getVpnInterfaces() != null) {
+                                currentIntfCount = currentIntfCount + dpn.getVpnInterfaces().size();
+                            }
+                        }
+                    }
+                    //currentIntfCount = vpnOpEntry.getVpnInterfaceCount();
+                    if ((currentIntfCount == 0) || (currentIntfCount >= intfCount)) {
+                        // Either the FibManager completed its job to cleanup all vpnInterfaces in VPN
+                        // OR
+                        // There is no progress by FibManager in removing all the interfaces even after good time!
+                        // In either case, let us quit and take our chances.
+                        //TODO(vpnteam): L3VPN refactoring to take care of this case.
+                        LOG.info("VPNInstance bailing out of wait loop as currentIntfCount is {} for for rd {}, vpnname {}",
+                                currentIntfCount, rd, vpnName);
+                        break;
+                    } else {
+                        // There is some progress by FibManager, so let us give it some more time!
+                        intfCount = currentIntfCount;
+                    }
+                } else {
+                    // There is no VPNOPEntry.  Something else happened on the system !
+                    // So let us quit and take our chances.
+                    //TODO(vpnteam): L3VPN refactoring to take care of this case.
+                    break;
+                }
+            }
+        }
+        LOG.info("Returned out of waiting for  Op Data removal for rd {}, vpnname {}", rd, vpnName);
     }
 
     @Override
@@ -152,33 +230,10 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                     VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
         }
 
-        if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
-            VpnInstanceOpDataEntry vpnOpEntry = null;
-            long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
-            Long intfCount = 0L;
-
-            vpnOpEntry = vpnOpValue.get();
-            intfCount = vpnOpEntry.getVpnInterfaceCount();
-            if (intfCount != null && intfCount > 0) {
-                // Minimum wait time of 10 seconds for one VPN Interface clearance (inclusive of full trace on)
-                timeout = intfCount * 10000;
-                // Maximum wait time of 90 seconds for all VPN Interfaces clearance (inclusive of full trace on)
-                if (timeout > VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS) {
-                    timeout = VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS;
-                }
-                LOG.trace("VPNInstance removal count of interface at {} for for rd {}, vpnname {}",
-                        intfCount, rd, vpnName);
-            }
-            LOG.trace("VPNInstance removal thread waiting for {} seconds for rd {}, vpnname {}",
-                    (timeout/1000), rd, vpnName);
-
-            if ((rd != null)  && (!rd.isEmpty())) {
-                waitForOpRemoval(rd, timeout);
-            } else {
-                waitForOpRemoval(vpnName, timeout);
-            }
-
-            LOG.trace("Returned out of waiting for  Op Data removal for rd {}, vpnname {}", rd, vpnName);
+        if ((rd != null)  && (!rd.isEmpty())) {
+            waitForOpRemoval(rd, vpnName);
+        } else {
+            waitForOpRemoval(vpnName, vpnName);
         }
         // Clean up VpnInstanceToVpnId from Config DS
         VpnUtil.removeVpnInstanceToVpnId(broker, vpnName);
@@ -249,7 +304,6 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
                     fibManager.setConfTransType("L3VPN", "VXLAN");
                     LOG.trace("setting it to vxlan now");
                 } catch (Exception e) {
-                    LOG.trace("Exception caught setting the cached value for transportType");
                     LOG.error(e.getMessage());
                 }
             } else {
@@ -499,23 +553,26 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
             final VpnInstanceOpDataEntryKey key = identifier.firstKeyOf(VpnInstanceOpDataEntry.class, VpnInstanceOpDataEntryKey.class);
             String vpnName = key.getVrfId();
 
-            LOG.trace("VpnInstanceOpListener update: vpn name {} interface count in Old VpnOp Instance {} in New VpnOp Instance {}" ,
-                            vpnName, original.getVpnInterfaceCount(), update.getVpnInterfaceCount() );
-
-            //if((original.getVpnToDpnList().size() != update.getVpnToDpnList().size()) && (update.getVpnToDpnList().size() == 0)) {
-            if((original.getVpnInterfaceCount() != update.getVpnInterfaceCount()) && (update.getVpnInterfaceCount() == 0)) {
-                notifyTaskIfRequired(vpnName);
-            }
-        }
-
-        private void notifyTaskIfRequired(String vpnName) {
-            Runnable notifyTask = vpnOpMap.remove(vpnName);
-            if (notifyTask == null) {
-                LOG.trace("VpnInstanceOpListener update: No Notify Task queued for vpnName {}", vpnName);
-                return;
-            }
-            executorService.execute(notifyTask);
-        }
+//            LOG.trace("VpnInstanceOpListener update: vpn name {} interface count in Old VpnOp Instance {} in New " +
+//                    "VpnOp Instance {}" ,
+//                            vpnName, original.getVpnInterfaceCount(), update.getVpnInterfaceCount() );
+//
+//            //if((original.getVpnToDpnList().size() != update.getVpnToDpnList().size()) && (update.getVpnToDpnList()
+// .size() == 0)) {
+//            if((original.getVpnInterfaceCount() != update.getVpnInterfaceCount()) && (update.getVpnInterfaceCount()
+//                    == 0)) {
+//                notifyTaskIfRequired(vpnName);
+//           }
+       }
+
+//        private void notifyTaskIfRequired(String vpnName) {
+//            Runnable notifyTask = vpnOpMap.remove(vpnName);
+//            if (notifyTask == null) {
+//                LOG.trace("VpnInstanceOpListener update: No Notify Task queued for vpnName {}", vpnName);
+//                return;
+//            }
+//            executorService.execute(notifyTask);
+//        }
 
         @Override
         protected void add(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry add) {
index 877b5200ea313c15600b0896b0b5d73f93985e17..e21f529fcea8bb111c514d94a5c11600fbf4dd1e 100644 (file)
@@ -22,13 +22,9 @@ import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
 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.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
@@ -38,6 +34,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 import java.math.BigInteger;
@@ -84,10 +83,29 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
         Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
         Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
 
-        logger.info("onSubnetAddedToVpn: Subnet" + subnetId.getValue() + " being added to vpn");
+        logger.info("onSubnetAddedToVpn: Subnet " + subnetId.getValue() + " being added to vpn");
         //TODO(vivek): Change this to use more granularized lock at subnetId level
         synchronized (this) {
             try {
+                Subnetmap subMap = null;
+
+                // Please check if subnetId belongs to an External Network
+                InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).
+                        child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+                Optional<Subnetmap> sm = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subMapid);
+                if (!sm.isPresent()) {
+                    logger.error("onSubnetAddedToVpn: Unable to retrieve subnetmap entry for subnet : " + subnetId);
+                    return;
+                }
+                subMap = sm.get();
+                InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class).
+                        child(Networks.class, new NetworksKey(subMap.getNetworkId())).build();
+                Optional<Networks> optionalNets = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
+                if (optionalNets.isPresent()) {
+                    logger.info("onSubnetAddedToVpn: subnet {} is an external subnet on external network {}, so ignoring this for SubnetRoute",
+                            subnetId.getValue(), subMap.getNetworkId().getValue());
+                    return;
+                }
                 //Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
                 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
                         child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
@@ -121,14 +139,6 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                 subOpBuilder.setElanTag(elanTag);
 
                 // First recover set of ports available in this subnet
-                InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).
-                        child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
-                Optional<Subnetmap> sm = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subMapid);
-                if (!sm.isPresent()) {
-                    logger.error("onSubnetAddedToVpn: Unable to retrieve subnetmap entry for subnet : " + subnetId);
-                    return;
-                }
-                Subnetmap subMap = sm.get();
                 List<Uuid> portList = subMap.getPortList();
                 if (portList != null) {
                     for (Uuid port: portList) {
@@ -210,7 +220,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
         if (!notification.isExternalVpn()) {
             return;
         }
-        logger.info("onSubnetDeletedFromVpn: Subnet" + subnetId.getValue() + " being removed to vpn");
+        logger.info("onSubnetDeletedFromVpn: Subnet " + subnetId.getValue() + " being removed to vpn");
         //TODO(vivek): Change this to use more granularized lock at subnetId level
         synchronized (this) {
             try {
@@ -267,7 +277,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                 String subnetIp = subOpBuilder.getSubnetCidr();
                 BigInteger nhDpnId = subOpBuilder.getNhDpnId();
                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
-                logger.trace("Removed subnetopdataentry successfully to CONFIG Datastore");
+                logger.info("onSubnetDeletedFromVpn: Removed subnetopdataentry for subnet {} successfully from Datastore", subnetId.getValue());
                 try {
                     //Withdraw the routes for all the interfaces on this subnet
                     //Remove subnet route entry from FIB
@@ -376,13 +386,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                     try {
                         // Write the Subnet Route Entry to FIB
                         // Advertise BGP Route here and set route_adv_state to DONE
-                        int label = 0;
-                        VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, subnetIp);
-                        if (vrf != null) {
-                            label = (vrf.getLabel()).intValue();
-                        } else {
-                            label = getLabel(rd, subnetIp);
-                        }
+                        int label = getLabel(rd, subnetIp);
                         addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                         advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                         subOpBuilder.setRouteAdvState(TaskState.Done);
@@ -466,13 +470,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                                 // Best effort Withdrawal of route from BGP for this subnet
                                 // Advertise the new NexthopIP to BGP for this subnet
                                 //withdrawSubnetRoutefromBgp(rd, subnetIp);
-                                int label = 0;
-                                VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, subnetIp);
-                                if (vrf != null) {
-                                    label = (vrf.getLabel()).intValue();
-                                } else {
-                                    label = getLabel(rd, subnetIp);
-                                }
+                                int label = getLabel(rd, subnetIp);
                                 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                                 advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                                 subOpBuilder.setRouteAdvState(TaskState.Done);
@@ -550,13 +548,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                     try {
                         // Write the Subnet Route Entry to FIB
                         // Advertise BGP Route here and set route_adv_state to DONE
-                        int label = 0;
-                        VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, subnetIp);
-                        if (vrf != null) {
-                            label = (vrf.getLabel()).intValue();
-                        } else {
-                            label = getLabel(rd, subnetIp);
-                        }
+                        int label = getLabel(rd, subnetIp);
                         addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                         advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                         subOpBuilder.setRouteAdvState(TaskState.Done);
@@ -641,13 +633,7 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
                             try {
                                 // Best effort Withdrawal of route from BGP for this subnet
                                 //withdrawSubnetRoutefromBgp(rd, subnetIp);
-                                int label = 0;
-                                VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, subnetIp);
-                                if (vrf != null) {
-                                    label = (vrf.getLabel()).intValue();
-                                } else {
-                                    label = getLabel(rd, subnetIp);
-                                }
+                                int label = getLabel(rd, subnetIp);
                                 addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                                 advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
                                 subOpBuilder.setRouteAdvState(TaskState.Done);
@@ -710,6 +696,9 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
             throw new Exception("Unable to obtain endpointIp address for DPNId " + nhDpnId);
         }
         try {
+            // BGPManager (inside ODL) requires a withdraw followed by advertise
+            // due to bugs with ClusterDataChangeListener used by BGPManager.
+            bgpManager.withdrawPrefix(rd, subnetIp);
             bgpManager.advertisePrefix(rd, subnetIp, nexthopIp, label);
         } catch (Exception e) {
             logger.error("Subnet route not advertised for rd " + rd + " failed ", e);
index 1b0cdaf8714f7d58679ed82c0a86e1d6f1bcc543..93a895eaa6bac78b5da0a591c724f29a6ff75a39 100644 (file)
@@ -133,6 +133,18 @@ public class VpnUtil {
                  new ExtrarouteKey(ipPrefix)).build();
     }
 
+    static List<Adjacency> getAdjacenciesForVpnInterfaceFromConfig(DataBroker broker, String intfName) {
+        final InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceIdentifier(intfName);
+        InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+        Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
+
+        if (adjacencies.isPresent()) {
+            List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+            return nextHops;
+        }
+        return null;
+    }
+
     static Extraroute getVpnToExtraroute(String ipPrefix, String nextHop) {
         return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIp(nextHop).build();
     }
index c07122f91a2fa78a5650598245a9bd77952d411d..7e9623fa860ea307660008d3793a32ec43d2cd91 100644 (file)
@@ -41,15 +41,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeCon
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpDataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RdToElanOp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.TaskState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
@@ -87,6 +83,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -112,7 +112,6 @@ public class VpnSubnetRouteHandlerTest {
     SubnetUpdatedInVpn subnetUpdatedInVpn = null;
     SubnetDeletedFromVpn subnetDeletedFromVpn = null;
     SubnetToDpn subnetToDpn = null;
-    RdToElanOpEntry rdToElanOpEntry = null;
     String subnetIp = "10.1.1.24";
     String routeDistinguisher = "100:1";
     String nexthopIp = null;
@@ -141,6 +140,7 @@ public class VpnSubnetRouteHandlerTest {
     String idKey = null;
     AllocateIdOutput allocateIdOutput = null;
     AllocateIdInput allocateIdInput = null;
+    Networks networks = null;
     org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance vpnInstnce;
 
     InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
@@ -157,8 +157,6 @@ public class VpnSubnetRouteHandlerTest {
     InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new
             SubnetmapKey(subnetId)).build();
     InstanceIdentifier<PortOpData> portOpIdentifr = InstanceIdentifier.builder(PortOpData.class).build();
-    InstanceIdentifier<RdToElanOpEntry> rdIdentifier = InstanceIdentifier.builder(RdToElanOp.class).
-            child(RdToElanOpEntry.class, new RdToElanOpEntryKey(interfaceName, subnetIp)).build();
     InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
             .VpnInstance> instVpnInstance = getVpnInstanceToVpnIdIdentifier(interfaceName);
     InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.
@@ -166,6 +164,8 @@ public class VpnSubnetRouteHandlerTest {
             .yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance.class,
             new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances
                     .VpnInstanceKey(interfaceName)).build();
+    InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class).
+            child(Networks.class, new NetworksKey(portId)).build();
 
     @Mock DataBroker dataBroker;
     @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
@@ -185,11 +185,11 @@ public class VpnSubnetRouteHandlerTest {
     Optional<PortOpDataEntry> optionalPortOp;
     Optional<PortOpData> optionalPtOp;
     Optional<Subnetmap> optionalSubnetMap;
-    Optional<RdToElanOpEntry> optionalRd;
     Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
             optionalVpnInstnce;
     Optional<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance>
             vpnInstanceOptional;
+    Optional<Networks> optionalNetworks;
 
     @Before
     public void setUp() throws Exception {
@@ -212,12 +212,10 @@ public class VpnSubnetRouteHandlerTest {
         optionalPortOp = Optional.of(portOp);
         optionalPtOp = Optional.of(portOpData);
         optionalSubnetMap = Optional.of(subnetmap);
-        optionalRd = Optional.of(rdToElanOpEntry);
         optionalVpnInstnce = Optional.of(vpnInstance);
         vpnInstanceOptional = Optional.of(vpnInstnce);
+        optionalNetworks = Optional.of(networks);
 
-        doReturn(Futures.immediateCheckedFuture(optionalRd)).when(mockReadTx).read(LogicalDatastoreType.OPERATIONAL,
-                rdIdentifier);
         doReturn(Futures.immediateCheckedFuture(optionalIfState)).when(mockReadTx).read(LogicalDatastoreType
                 .OPERATIONAL, ifStateId);
         doReturn(Futures.immediateCheckedFuture(optionalSubs)).when(mockReadTx).read(LogicalDatastoreType
@@ -238,6 +236,8 @@ public class VpnSubnetRouteHandlerTest {
                 .CONFIGURATION, instVpnInstance);
         doReturn(Futures.immediateCheckedFuture(vpnInstanceOptional)).when(mockReadTx).read(LogicalDatastoreType
                 .CONFIGURATION,vpnInstanceIdentifier);
+        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(LogicalDatastoreType
+                .CONFIGURATION,netsIdentifier);
         doReturn(idOutputOptional).when(idManager).allocateId(allocateIdInput);
     }
 
@@ -290,7 +290,7 @@ public class VpnSubnetRouteHandlerTest {
                 .setSubnetIp(subnetIp).setVpnName(interfaceName).setElanTag(elanTag).build();
         subnetOp = new SubnetOpDataEntryBuilder().setElanTag(elanTag).setNhDpnId(dpId).setSubnetCidr(subnetIp)
                 .setSubnetId(subnetId).setKey(new SubnetOpDataEntryKey(subnetId)).setVpnName(interfaceName)
-                .setVrfId(routeDistinguisher).setSubnetToDpn(subToDpn).setRouteAdvState(TaskState.Pending).build();
+                .setVrfId(routeDistinguisher).setSubnetToDpn(subToDpn).setRouteAdvState(TaskState.Done).build();
         vpnInstance = new VpnInstanceBuilder().setVpnId(elanTag).setVpnInstanceName(interfaceName).setVrfId
                 (interfaceName).setKey(new VpnInstanceKey(interfaceName)).build();
         subnetmap = new SubnetmapBuilder().setSubnetIp(subnetIp).setId(subnetId).setNetworkId(portId).setKey(new
@@ -302,14 +302,12 @@ public class VpnSubnetRouteHandlerTest {
         tunlEndPts = new TunnelEndPointsBuilder().setInterfaceName(interfaceName).setVLANID(10).setIpAddress
                 (ipAddress).build();
         tunnelEndPoints.add(tunlEndPts);
-        rdToElanOpEntry = new RdToElanOpEntryBuilder().setElanTag(elanTag).setRd(interfaceName).setVpnName
-                (interfaceName).setNextHopIp(nexthopIp)
-                .setKey(new RdToElanOpEntryKey(interfaceName, subnetIp)).setSubnetIp(subnetIp).build();
         ipv4Family = new Ipv4FamilyBuilder().setRouteDistinguisher(routeDistinguisher).build();
         vpnInstnce = new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances
                 .VpnInstanceBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn
                 .rev140815.vpn.instances.VpnInstanceKey(interfaceName)).setVpnInstanceName(interfaceName)
                 .setIpv4Family(ipv4Family).build();
+        networks = new NetworksBuilder().setId(portId).setKey(new NetworksKey(portId)).build();
         doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
         doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
         doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();