Bug 6779 -After a Cluster Reboot, 10 VPNintfs seen 72/46972/3
authorVivekanandan Narasimhan <n.vivekanandan@ericsson.com>
Wed, 21 Sep 2016 17:01:58 +0000 (22:31 +0530)
committerSam Hague <shague@redhat.com>
Tue, 18 Oct 2016 15:14:43 +0000 (15:14 +0000)
After a Cluster Reboot, only 10 VPN Interfaces are configured
out of 1500 VPN Interfaces.

Upon cluster reboot , VpnInterface add may fail due to
vpnInstance unavailability. VpnInstance creation might lag
VpnInterface add event.

So we have introduced a synchronization mechanism for
VpnInterfaceManager to synchronize with VPNInstance
creation driven by VpnManager.  The same concept applies
to the VpnSubnetRouteHandler engine.

With this fix VpnInterfaceManager/VpnSubnetRouteHandler
will wait for 90 seconds for VpnManager to provide complete
VpnInstance information before proceeding to plumb the
VpnInterfaces/SubnetRoutes that are part of that VPNInstance.

These waits will be removed in Carbon as we refactor and will
build a parent first processing logic around the
VpnInstanceListener.

Change-Id: I912fda5aef4b4c50d897cd293dee6f49c429eea6
Signed-off-by: Vivekanandan Narasimhan <n.vivekanandan@ericsson.com>
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/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/NexthopManager.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NaptEventHandler.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NaptFlowRemovedEventHandler.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnConstants.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInstanceListener.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/VpnSubnetRouteHandler.java

index fd4842e13c7d0c1509a193d6628579bd92ea4b95..0b323c0edcbdef30ccca0636d4bc67ee93d9dbca 100644 (file)
@@ -1863,8 +1863,7 @@ public class BgpConfigurationManager {
         Vrfs dto = new VrfsBuilder().setRd(rd)
                 .setImportRts(irts)
                 .setExportRts(erts).build();
-
-        asyncWrite(iid, dto);
+        BgpUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
     }
 
     public synchronized void stopConfig() {
index b3bbb2211a00d3ec8f0432042ca90a2608f6551e..2599e0a6c792dbd2f26bc3ada9979635a6cdbe0f 100644 (file)
@@ -13,7 +13,9 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
@@ -111,6 +113,19 @@ public class BgpUtil {
         return Optional.absent();
     }
 
+    public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+                                                        InstanceIdentifier<T> path, T data) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.put(datastoreType, path, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
     public static void setBroker(final DataBroker broker) {
         BgpUtil.dataBroker = broker;
         initTransactionChain();
index c98aa4e6d40e5322c4a16c62a1d0bdce44e3ce0c..e16543552405596b898560dc02041b85480642a5 100644 (file)
@@ -289,6 +289,10 @@ public class NexthopManager implements AutoCloseable {
     public long createLocalNextHop(long vpnId, BigInteger dpnId,
                                    String ifName, String ipAddress) {
         long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
+        if (groupId == 0) {
+            LOG.error("Unable to allocate groupId for vpnId {} , prefix {}", vpnId, ipAddress);
+            return groupId;
+        }
         String nextHopLockStr = new String(vpnId + ipAddress);
         synchronized (nextHopLockStr.intern()) {
             VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
index d7c82ee0e11a757b96b12070335813bd940fa7cf..7c5af194363c45aa94251e4b033603f9f42fd814 100644 (file)
@@ -782,11 +782,16 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         if (localNextHopInfo != null) {
             final BigInteger dpnId = localNextHopInfo.getDpnId();
             if (!isVpnPresentInDpn(rd, dpnId)) {
+                LOG.error("The vpnName with vpnId {} rd {} is not available on dpn {}", vpnId, rd, dpnId.toString());
                 return BigInteger.ZERO;
             }
 
             final long groupId = nextHopManager.createLocalNextHop(parentVpnId, dpnId, localNextHopInfo.getVpnInterfaceName(), localNextHopIP);
-
+            if (groupId == 0) {
+                LOG.error("Unable to create Group for local prefix {} on rd {} for vpninterface {} on Node {}",
+                        vrfEntry.getDestPrefix(), rd, localNextHopInfo.getVpnInterfaceName(), dpnId.toString());
+                return BigInteger.ZERO;
+            }
             List<ActionInfo> actionsInfos =
                     Arrays.asList(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
             final List<InstructionInfo> instructions =
index 42190c36d500e905e644f018ceaea1446c5f0e69..d8b64e37878d85e968fd4e7a04db38a8e15cd6d3 100644 (file)
@@ -103,6 +103,10 @@ public class NaptEventHandler {
             LOG.debug("NAT Service : BGP VPN ID {}", bgpVpnId);
             String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
             String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
+            if (routerName == null) {
+                LOG.error("NAT Service: Unable to find router for VpnName {}", vpnName);
+                return;
+            }
             routerId = NatUtil.getVpnId(dataBroker, routerName);
             LOG.debug("NAT Service : Router ID {}", routerId);
             dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
index 5649a3273a088bbd50d83819b60926c5d466f296..26870769fc1706dbaf30c3a9d5a0765604f6cd18 100644 (file)
@@ -132,6 +132,10 @@ public class NaptFlowRemovedEventHandler implements SalFlowListener{
                 LOG.debug("NaptFlowRemovedEventHandler : BGP VPN ID {}", bgpVpnId);
                 String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
                 String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
+                if (routerName == null) {
+                    LOG.error("NAT Service: Unable to find router for VpnName {}", vpnName);
+                    return;
+                }
                 routerId = NatUtil.getVpnId(dataBroker, routerName);
                 LOG.debug("NaptFlowRemovedEventHandler : Router ID {}", routerId);
                 ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId, internalIpv4HostAddress, internalPortNumber.toString(), protocol);
index b54b8e87ce4c386ba6cc8782faab5e71a96302c3..23f64df80a5cde9db218b42bab71c7d7f90468b3 100644 (file)
@@ -650,7 +650,10 @@ public class NatUtil {
         Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
                 vpnMapIdentifier);
         if (optionalVpnMap.isPresent()) {
-            return optionalVpnMap.get().getRouterId().getValue();
+            Uuid routerId = optionalVpnMap.get().getRouterId();
+            if (routerId != null) {
+                return routerId.getValue();
+            }
         }
         return null;
     }
index cebdcd6def443e45569827c79309b9e475c37780..6d2d694cff74adcb76dc1e8dca39722f1b5a6723 100644 (file)
@@ -23,6 +23,8 @@ public class VpnConstants {
     public static final long MIN_WAIT_TIME_IN_MILLISECONDS = 10000;
     public static final long MAX_WAIT_TIME_IN_MILLISECONDS = 180000;
     public static final long PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS = 50000;
+    public static final long PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS = 90000;
+    public static final long PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS = 180000;
     public static final int ELAN_GID_MIN = 200000;
     public static final int INVALID_LABEL = 0;
 
index 030a6c3fc9223afa93e7e7e28af2d8a13f96b881..ee246982a0f7db8654fab6b31bb15e2582b7cf3d 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
@@ -60,9 +61,7 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
     private final IdManagerService idManager;
     private final VpnInterfaceManager vpnInterfaceManager;
     private final IFibManager fibManager;
-    private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
-            .setNameFormat("NV-VpnMgr-%d").build();
-    private ExecutorService executorService = Executors.newSingleThreadExecutor(threadFactory);
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
     private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
 
     public VpnInstanceListener(final DataBroker dataBroker, final IBgpManager bgpManager,
@@ -92,15 +91,6 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
         return VpnInstanceListener.this;
     }
 
-    void notifyTaskIfRequired(String vpnName) {
-        Runnable notifyTask = vpnOpMap.remove(vpnName);
-        if (notifyTask == null) {
-            LOG.trace("VpnInstanceListener update: No Notify Task queued for vpnName {}", vpnName);
-            return;
-        }
-        executorService.execute(notifyTask);
-    }
-
     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
         //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
@@ -356,10 +346,8 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
             List<ListenableFuture<Void>> futures = new ArrayList<>();
             futures.add(writeConfigTxn.submit());
             ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
-            if (rd != null) {
-                Futures.addCallback(listenableFuture,
-                        new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
-            }
+            Futures.addCallback(listenableFuture,
+                    new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
             return futures;
         }
     }
@@ -372,10 +360,11 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
 
         long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
         if (vpnId == 0) {
+            LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
             LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
             return;
         }
-        LOG.trace("VPN instance to ID generated.");
+        LOG.info("VPN Id {} generated for VpnInstanceName {}", vpnId, vpnInstanceName);
         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);
@@ -405,19 +394,17 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
 
         try {
             String cachedTransType = fibManager.getConfTransType();
-            LOG.trace("Value for confTransportType is " + cachedTransType);
             if (cachedTransType.equals("Invalid")) {
                 try {
                     fibManager.setConfTransType("L3VPN", "VXLAN");
                 } catch (Exception e) {
-                    LOG.trace("Exception caught setting the cached value for transportType");
-                    LOG.error(e.getMessage());
+                    LOG.error("Exception caught setting the L3VPN tunnel transportType", e);
                 }
             } else {
-                LOG.trace(":cached val is neither unset/invalid. NO-op.");
+                LOG.trace("Configured tunnel transport type for L3VPN as {}", cachedTransType);
             }
         } catch (Exception e) {
-            LOG.error(e.getMessage());
+            LOG.error("Error when trying to retrieve tunnel transport type for L3VPN ", e);
         }
 
         if (rd == null) {
@@ -464,6 +451,7 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
                         builder.build(), TransactionUtil.DEFAULT_CALLBACK);
             }
         }
+        LOG.info("VpnInstanceOpData populated successfully for vpn {} rd {}", vpnInstanceName, rd);
     }
 
 
@@ -508,7 +496,11 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
                     LOG.error("Exception when adding VRF to BGP", e);
                     return;
                 }
-                vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+                notifyTaskIfRequired(vpnName, vpnInterfaceManager.getvpnInstanceToIdSynchronizerMap());
+                notifyTaskIfRequired(vpnName, vpnInterfaceManager.getvpnInstanceOpDataSynchronizerMap());
+                if (rd != null) {
+                    vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+                }
             }
         }
         /**
@@ -551,4 +543,21 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
         }
         return null;
     }
+
+    private void notifyTaskIfRequired(String vpnName,
+                                      ConcurrentHashMap<String, List<Runnable>> vpnInstanceMap) {
+        synchronized (vpnInstanceMap) {
+            List<Runnable> notifieeList = vpnInstanceMap.remove(vpnName);
+            if (notifieeList == null) {
+                LOG.trace(" No notify tasks found for vpnName {}", vpnName);
+                return;
+            }
+            Iterator<Runnable> notifieeIter = notifieeList.iterator();
+            while (notifieeIter.hasNext()) {
+                Runnable notifyTask = notifieeIter.next();
+                executorService.execute(notifyTask);
+                notifieeIter.remove();
+            }
+        }
+    }
 }
index fcce10d37c205b7d0e7bc2d06046f46d87ab4372..0efecd35e5a6260ac1112c9187a1f89c0c3dd50d 100644 (file)
@@ -146,8 +146,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     private final OdlArputilService arpManager;
     private final OdlInterfaceRpcService ifaceMgrRpcService;
     private final NotificationPublishService notificationPublishService;
-    private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
-    private final ExecutorService executorService = Executors.newSingleThreadExecutor();
+    private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
+    private ConcurrentHashMap<String, List<Runnable>> vpnInstanceToIdSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
+    private ConcurrentHashMap<String, List<Runnable>> vpnInstanceOpDataSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
 
     public VpnInterfaceManager(final DataBroker dataBroker,
                                final IBgpManager bgpManager,
@@ -183,6 +185,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         return VpnInterfaceManager.this;
     }
 
+    public ConcurrentHashMap<String, List<Runnable>> getvpnInstanceToIdSynchronizerMap() {
+        return vpnInstanceToIdSynchronizerMap;
+    }
+
+    public ConcurrentHashMap<String, List<Runnable>> getvpnInstanceOpDataSynchronizerMap() {
+        return vpnInstanceOpDataSynchronizerMap;
+    }
 
     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
         return InstanceIdentifier.create(InterfacesState.class)
@@ -223,7 +232,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 return;
             }
         } else {
-            LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
+            LOG.error("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
         }
     }
 
@@ -239,9 +248,38 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             LOG.info("Binding vpn service to interface {} ", interfaceName);
             long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
             if (vpnId == VpnConstants.INVALID_ID) {
-                LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
-                return;
+                waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInstanceToIdSynchronizerMap);
+                vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+                if (vpnId == VpnConstants.INVALID_ID) {
+                    LOG.error("VpnInstance to VPNId mapping not yet available for VpnName {} processing vpninterface {} " +
+                            ", bailing out now.", vpnName, interfaceName);
+                    return;
+                }
+            } else {
+                // Incase of cluster reboot , VpnId would be available already as its a configDS fetch.
+                // However VpnInstanceOpData will be repopulated, so if its not available
+                // wait for 180 seconds and retry.
+                // TODO:  This wait to be removed by making vpnManager the central engine in carbon
+                String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
+                VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
+                if (vpnInstanceOpDataEntry == null) {
+                    LOG.debug("VpnInstanceOpData not yet populated for vpn {} rd {}", vpnName, vpnRd);
+                    int retry = 2;
+                    while (retry > 0) {
+                        waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInstanceOpDataSynchronizerMap);
+                        vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
+                        if (vpnInstanceOpDataEntry != null) {
+                            break;
+                        }
+                        retry--;
+                        if (retry <= 0) {
+                            LOG.error("VpnInstanceOpData not populated even after second retry for vpn {} rd {} vpninterface {}, bailing out ", vpnName, vpnRd, interfaceName);
+                            return;
+                        }
+                    }
+                }
             }
+
             boolean waitForVpnInterfaceOpRemoval = false;
             VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, vpnInterface.getName());
             if (opVpnInterface != null ) {
@@ -1713,11 +1751,36 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
-    void notifyTaskIfRequired(String intfName) {
-        Runnable notifyTask = vpnIntfMap.remove(intfName);
-        if (notifyTask == null) {
-            return;
+    //TODO(vivek) This waiting business to be removed in carbon
+    public void waitForVpnInstance(String vpnName, long wait_time,
+                                       ConcurrentHashMap<String, List<Runnable>> vpnInstanceMap) {
+        List<Runnable> notifieeList = null;
+        Runnable notifyTask = new VpnNotifyTask();
+        try {
+            synchronized (vpnInstanceMap) {
+                notifieeList = vpnInstanceMap.get(vpnName);
+                if (notifieeList == null) {
+                    notifieeList = new ArrayList<Runnable>();
+                    vpnInstanceMap.put(vpnName, notifieeList);
+                }
+                notifieeList.add(notifyTask);
+            }
+            synchronized (notifyTask) {
+                try {
+                    notifyTask.wait(wait_time);
+                } catch (InterruptedException e) {
+                }
+            }
+        } finally {
+            synchronized (vpnInstanceMap) {
+                notifieeList = vpnInstanceMap.get(vpnName);
+                if (notifieeList != null) {
+                    notifieeList.remove(notifyTask);
+                    if (notifieeList.isEmpty()) {
+                        vpnInstanceMap.remove(vpnName);
+                    }
+                }
+            }
         }
-        executorService.execute(notifyTask);
     }
 }
index 83e74632c212be010484148b647838cdc9225e15..69dd0bd9383b222d8ec957fcc2f25e16b22755b7 100644 (file)
@@ -91,6 +91,16 @@ public class VpnSubnetRouteHandler implements NeutronvpnListener {
         Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
 
         logger.info("onSubnetAddedToVpn: Subnet " + subnetId.getValue() + " being added to vpn");
+        long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+        if (vpnId == VpnConstants.INVALID_ID) {
+            vpnInterfaceManager.waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInterfaceManager.getvpnInstanceToIdSynchronizerMap());
+            vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+            if (vpnId == VpnConstants.INVALID_ID) {
+                logger.error("onSubnetAddedToVpn: VpnInstance to VPNId mapping not yet available for VpnName {} processing subnet {} with IP {} " +
+                        ", bailing out now.", vpnName, subnetId, subnetIp);
+                return;
+            }
+        }
         //TODO(vivek): Change this to use more granularized lock at subnetId level
         try {
             VpnUtil.lockSubnet(lockManager, subnetId.getValue());