ifm changes for performance enhancements
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceInventoryStateListener.java
index e8444440179c24ed5868f0922f9dd0b0a364c9d8..472ff9c3eba8946b16e8a18a5b91bb3d8a01a8b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,24 +8,40 @@
 package org.opendaylight.genius.interfacemanager.listeners;
 
 import com.google.common.util.concurrent.ListenableFuture;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
-import org.opendaylight.genius.interfacemanager.IfmUtil;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
 import org.opendaylight.genius.interfacemanager.IfmConstants;
+import org.opendaylight.genius.interfacemanager.IfmUtil;
+import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
+import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
+import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
+import org.opendaylight.genius.interfacemanager.recovery.listeners.RecoverableListener;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateRemoveHelper;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
+import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
@@ -34,33 +50,69 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
 /**
- *
  * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
- * This creates an entry in the interface-state OperDS for every node-connector used.
+ * This creates an entry in the interface-state OperDS for every node-connector
+ * used.
  *
- * NOTE: This class just creates an ifstate entry whose interface-name will be the same as the node-connector portname.
- * If PortName is not unique across DPNs, this implementation can have problems.
+ * <p>
+ * NOTE: This class just creates an ifstate entry whose interface-name will be
+ * the same as the node-connector portname. If PortName is not unique across
+ * DPNs, this implementation can have problems.
  */
-
-public class InterfaceInventoryStateListener extends AsyncDataTreeChangeListenerBase<FlowCapableNodeConnector, InterfaceInventoryStateListener> {
+@Singleton
+public class InterfaceInventoryStateListener
+        extends AsyncClusteredDataTreeChangeListenerBase<FlowCapableNodeConnector, InterfaceInventoryStateListener>
+        implements RecoverableListener {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
-    private DataBroker dataBroker;
-    private IdManagerService idManager;
-    private IMdsalApiManager mdsalApiManager;
-    private AlivenessMonitorService alivenessMonitorService;
+    private final DataBroker dataBroker;
+    private final IdManagerService idManager;
+    private final EntityOwnershipUtils entityOwnershipUtils;
+    private final JobCoordinator coordinator;
+    private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
+    private final AlivenessMonitorUtils alivenessMonitorUtils;
+    private final OvsInterfaceStateUpdateHelper ovsInterfaceStateUpdateHelper;
+    private final OvsInterfaceStateAddHelper ovsInterfaceStateAddHelper;
+    private final InterfaceMetaUtils interfaceMetaUtils;
+    private final PortNameCache portNameCache;
+    private final InterfacemgrProvider interfacemgrProvider;
 
-    public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager,
-                                           final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService) {
+    @Inject
+    public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManagerService,
+            final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService,
+            final EntityOwnershipUtils entityOwnershipUtils, final JobCoordinator coordinator,
+            final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
+            final OvsInterfaceStateAddHelper ovsInterfaceStateAddHelper,
+            final OvsInterfaceStateUpdateHelper ovsInterfaceStateUpdateHelper,
+            final AlivenessMonitorUtils alivenessMonitorUtils,
+            final InterfaceMetaUtils interfaceMetaUtils,
+            final PortNameCache portNameCache,
+            final InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler,
+            final InterfacemgrProvider interfacemgrProvider) {
         super(FlowCapableNodeConnector.class, InterfaceInventoryStateListener.class);
         this.dataBroker = dataBroker;
-        this.idManager = idManager;
-        this.mdsalApiManager = mdsalApiManager;
-        this.alivenessMonitorService = alivenessMonitorService;
+        this.idManager = idManagerService;
+        this.entityOwnershipUtils = entityOwnershipUtils;
+        this.coordinator = coordinator;
+        this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
+        this.alivenessMonitorUtils = alivenessMonitorUtils;
+        this.ovsInterfaceStateUpdateHelper = ovsInterfaceStateUpdateHelper;
+        this.ovsInterfaceStateAddHelper = ovsInterfaceStateAddHelper;
+        this.interfaceMetaUtils = interfaceMetaUtils;
+        this.portNameCache = portNameCache;
+        this.interfacemgrProvider = interfacemgrProvider;
+        registerListener();
+        interfaceServiceRecoveryHandler.addRecoverableListener(this);
+    }
+
+    @Override
+    public void registerListener() {
+        this.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+    }
+
+    @Override
+    public  void deregisterListener() {
+        close();
     }
 
     @Override
@@ -77,59 +129,120 @@ public class InterfaceInventoryStateListener extends AsyncDataTreeChangeListener
     @Override
     protected void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
                           FlowCapableNodeConnector flowCapableNodeConnectorOld) {
-        LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
-        String portName = flowCapableNodeConnectorOld.getName();
-        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        if (interfacemgrProvider.isItmDirectTunnelsEnabled()
+                && interfaceManagerCommonUtils.isTunnelInternal(flowCapableNodeConnectorOld.getName())) {
+            LOG.debug("ITM Direct Tunnels is enabled, ignoring node connector removed for internal tunnel {}",
+                    flowCapableNodeConnectorOld.getName());
+            return;
+        }
 
-        //VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD for same interface from Older DPN
-        Interface ifState = InterfaceManagerCommonUtils.getInterfaceStateFromDS(portName);
-        NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(ifState);
-        if(nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
-            LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
+        if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
+                IfmConstants.INTERFACE_CONFIG_ENTITY)) {
             return;
         }
-        remove(nodeConnectorId, nodeConnectorIdOld, flowCapableNodeConnectorOld, portName, ifState);
+
+        LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
+        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
+            .getId();
+        String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
+            flowCapableNodeConnectorOld.getName());
+
+        remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
+    }
+
+    private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
+                        FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNetworkEvent) {
+        boolean isNodePresent = interfaceManagerCommonUtils.isNodePresent(nodeConnectorIdNew);
+        InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
+                nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorNew, portName, isNodePresent,
+                isNetworkEvent, true);
+        coordinator.enqueueJob(portName, portStateRemoveWorker, IfmConstants.JOB_MAX_RETRIES);
+        LOG.trace("Removing entry for port id {} from map",nodeConnectorIdNew.getValue());
+        portNameCache.remove(nodeConnectorIdNew.getValue());
     }
 
     @Override
     protected void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
                           FlowCapableNodeConnector fcNodeConnectorNew) {
+        if (interfacemgrProvider.isItmDirectTunnelsEnabled()
+                && interfaceManagerCommonUtils.isTunnelInternal(fcNodeConnectorNew.getName())) {
+            LOG.debug("ITM Direct Tunnels is enabled, ignoring node connector Update for internal tunnel {}",
+                    fcNodeConnectorNew.getName());
+            return;
+        }
+
+        if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
+                IfmConstants.INTERFACE_CONFIG_ENTITY)) {
+            return;
+        }
+
         LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
-        String portName = fcNodeConnectorNew.getName();
-        DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
+                fcNodeConnectorNew.getName());
 
         InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
-                fcNodeConnectorNew, portName);
-        coordinator.enqueueJob(portName, portStateUpdateWorker, 3);
+            fcNodeConnectorNew, portName);
+        coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
     }
 
     @Override
     protected void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
+        if (interfacemgrProvider.isItmDirectTunnelsEnabled()
+                && interfaceManagerCommonUtils.isTunnelInternal(fcNodeConnectorNew.getName())) {
+            LOG.debug("ITM Direct Tunnels is enabled, ignoring node connector add for internal tunnel {}",
+                    fcNodeConnectorNew.getName());
+            return;
+        }
+
+        if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
+                IfmConstants.INTERFACE_CONFIG_ENTITY)) {
+            return;
+        }
+
         LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
-        String portName = fcNodeConnectorNew.getName();
-        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
+            .getId();
+        LOG.trace("Adding entry for portid {} portname {} in map", nodeConnectorId.getValue(),
+                fcNodeConnectorNew.getName());
+        portNameCache.put(nodeConnectorId.getValue(),fcNodeConnectorNew.getName());
+        String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
+            fcNodeConnectorNew.getName());
 
-        //VM Migration: Delete existing interface entry for older DPN
-        Interface ifState = InterfaceManagerCommonUtils.getInterfaceStateFromDS(portName);
-        NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(ifState);
-        if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
-            LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
-            remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, ifState);
+        if (InterfaceManagerCommonUtils.isNovaPort(portName) || InterfaceManagerCommonUtils.isK8SPort(portName)) {
+            NodeConnectorId nodeConnectorIdOld =
+                    FlowBasedServicesUtils.getNodeConnectorIdFromInterface(portName, interfaceManagerCommonUtils);
+            if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
+                BigInteger dpnIdOld = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorIdOld);
+                BigInteger dpnIdNew = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
+                if (!Objects.equals(dpnIdOld, dpnIdNew)) {
+                    if (fcNodeConnectorNew.getReason() != PortReason.Add) {
+                        LOG.error("Dropping Port update event for {}, as DPN id is changed from {} to {}",
+                            fcNodeConnectorNew.getName(), dpnIdOld, dpnIdNew);
+                        return;
+                    }
+                } else {
+                    LOG.warn("Port number update detected for {}", fcNodeConnectorNew.getName());
+                }
+                //VM Migration or Port Number Update: Delete existing interface entry for older DPN
+                LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName,
+                    nodeConnectorId, nodeConnectorIdOld);
+                remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
+                // Adding a delay of 10sec for VM migration, so applications will have sufficient time
+                // for processing remove before add
+                try {
+                    Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
+                } catch (final InterruptedException e) {
+                    LOG.error("Error while waiting for the vm migration remove events to get processed");
+                }
+            }
         }
 
-        DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
         InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
-                fcNodeConnectorNew, portName);
-        coordinator.enqueueJob(portName, ifStateAddWorker, 3);
+            fcNodeConnectorNew, portName);
+        coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
     }
 
-    private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
-                        FlowCapableNodeConnector fcNodeConnectorNew, String portName, Interface ifState) {
-        DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
-        InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
-                nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorNew, portName, ifState);
-        coordinator.enqueueJob(portName, portStateRemoveWorker, 3);
-    }
 
     private class InterfaceStateAddWorker implements Callable {
         private final NodeConnectorId nodeConnectorId;
@@ -137,9 +250,8 @@ public class InterfaceInventoryStateListener extends AsyncDataTreeChangeListener
         private final String interfaceName;
         private final IdManagerService idManager;
 
-        public InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
-                                       FlowCapableNodeConnector fcNodeConnectorNew,
-                                       String portName) {
+        InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
+                                FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
             this.nodeConnectorId = nodeConnectorId;
             this.fcNodeConnectorNew = fcNodeConnectorNew;
             this.interfaceName = portName;
@@ -147,41 +259,35 @@ public class InterfaceInventoryStateListener extends AsyncDataTreeChangeListener
         }
 
         @Override
-        public Object call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            List<ListenableFuture<Void>> futures = OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, alivenessMonitorService, nodeConnectorId,
+        public Object call() {
+            List<ListenableFuture<Void>> futures = ovsInterfaceStateAddHelper.addState(nodeConnectorId,
                     interfaceName, fcNodeConnectorNew);
-            List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName, nodeConnectorId);
+            List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
-                InterfaceStateAddWorker interfaceStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
-                        fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
-                DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateAddWorker);
+                InterfaceStateAddWorker interfaceStateAddWorker = new InterfaceStateAddWorker(idManager,
+                        nodeConnectorId, fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
+                coordinator.enqueueJob(interfaceName, interfaceStateAddWorker);
             }
             return futures;
         }
 
         @Override
         public String toString() {
-            return "InterfaceStateAddWorker{" +
-                    "nodeConnectorId=" + nodeConnectorId +
-                    ", fcNodeConnectorNew=" + fcNodeConnectorNew +
-                    ", interfaceName='" + interfaceName + '\'' +
-                    '}';
+            return "InterfaceStateAddWorker{" + "nodeConnectorId=" + nodeConnectorId + ", fcNodeConnectorNew="
+                    + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
         }
     }
 
     private class InterfaceStateUpdateWorker implements Callable {
-        private InstanceIdentifier<FlowCapableNodeConnector> key;
+        private final InstanceIdentifier<FlowCapableNodeConnector> key;
         private final FlowCapableNodeConnector fcNodeConnectorOld;
         private final FlowCapableNodeConnector fcNodeConnectorNew;
-        private String interfaceName;
-
+        private final String interfaceName;
 
-        public InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
-                                          FlowCapableNodeConnector fcNodeConnectorOld,
-                                          FlowCapableNodeConnector fcNodeConnectorNew,
-                                          String portName) {
+        InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
+                                   FlowCapableNodeConnector fcNodeConnectorOld,
+                                   FlowCapableNodeConnector fcNodeConnectorNew,
+                                   String portName) {
             this.key = key;
             this.fcNodeConnectorOld = fcNodeConnectorOld;
             this.fcNodeConnectorNew = fcNodeConnectorNew;
@@ -189,94 +295,151 @@ public class InterfaceInventoryStateListener extends AsyncDataTreeChangeListener
         }
 
         @Override
-        public Object call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            List<ListenableFuture<Void>> futures = OvsInterfaceStateUpdateHelper.updateState(key, alivenessMonitorService, dataBroker, interfaceName,
-                    fcNodeConnectorNew, fcNodeConnectorOld);
-            NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
-            List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName, nodeConnectorId);
+        public Object call() {
+            List<ListenableFuture<Void>> futures = ovsInterfaceStateUpdateHelper.updateState(
+                    interfaceName, fcNodeConnectorNew, fcNodeConnectorOld);
+            List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
-                InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
-                        fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
-                DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateUpdateWorker);
+                InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key,
+                        fcNodeConnectorOld, fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
+                coordinator.enqueueJob(interfaceName, interfaceStateUpdateWorker);
             }
             return futures;
         }
 
         @Override
         public String toString() {
-            return "InterfaceStateUpdateWorker{" +
-                    "key=" + key +
-                    ", fcNodeConnectorOld=" + fcNodeConnectorOld +
-                    ", fcNodeConnectorNew=" + fcNodeConnectorNew +
-                    ", interfaceName='" + interfaceName + '\'' +
-                    '}';
+            return "InterfaceStateUpdateWorker{" + "key=" + key + ", fcNodeConnectorOld=" + fcNodeConnectorOld
+                    + ", fcNodeConnectorNew=" + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
         }
     }
 
     private class InterfaceStateRemoveWorker implements Callable {
         private final NodeConnectorId nodeConnectorIdNew;
-        private final NodeConnectorId nodeConnectorIdOld;
+        private NodeConnectorId nodeConnectorIdOld;
         FlowCapableNodeConnector fcNodeConnectorOld;
         private final String interfaceName;
         private final IdManagerService idManager;
-        private final Interface ifState;
+        private final boolean isNodePresent;
+        private final boolean isNetworkEvent;
+        private final boolean isParentInterface;
 
-        public InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
-                                          NodeConnectorId nodeConnectorIdOld,
-                                          FlowCapableNodeConnector fcNodeConnectorOld,
-                                          String portName,Interface ifState) {
+        InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
+                                   NodeConnectorId nodeConnectorIdOld,
+                                   FlowCapableNodeConnector fcNodeConnectorOld, String interfaceName,
+                                   boolean isNodePresent, boolean isNetworkEvent,
+                                   boolean isParentInterface) {
             this.nodeConnectorIdNew = nodeConnectorIdNew;
             this.nodeConnectorIdOld = nodeConnectorIdOld;
             this.fcNodeConnectorOld = fcNodeConnectorOld;
-            this.interfaceName = portName;
+            this.interfaceName = interfaceName;
             this.idManager = idManager;
-            this.ifState = ifState;
+            this.isNodePresent = isNodePresent;
+            this.isNetworkEvent = isNetworkEvent;
+            this.isParentInterface = isParentInterface;
         }
 
         @Override
-        public Object call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            List<ListenableFuture<Void>> futures = OvsInterfaceStateRemoveHelper.removeInterfaceStateConfiguration(idManager, mdsalApiManager, alivenessMonitorService,
-                    nodeConnectorIdNew, nodeConnectorIdOld, dataBroker, interfaceName, fcNodeConnectorOld, ifState);
+        public Object call() {
+            List<ListenableFuture<Void>> futures = null;
+            // VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD
+            // for same interface from Older DPN
+            if (isParentInterface && isNetworkEvent) {
+                nodeConnectorIdOld = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(interfaceName,
+                        interfaceManagerCommonUtils);
+                if (nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
+                    LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", interfaceName,
+                            nodeConnectorIdNew, nodeConnectorIdOld);
+                    return futures;
+                }
+            }
+
+            futures = removeInterfaceStateConfiguration();
 
-            List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName, nodeConnectorIdNew);
+            List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
-                // Fetch all interfaces on this port and trigger remove worker for each of them
+                // Fetch all interfaces on this port and trigger remove worker
+                // for each of them
                 InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
-                        nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorOld, interfaceChildEntry.getChildInterface(),
-                        InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceChildEntry.getChildInterface(), dataBroker));
-                DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateRemoveWorker);
+                        nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorOld,
+                        interfaceChildEntry.getChildInterface(), isNodePresent, isNetworkEvent, false);
+                coordinator.enqueueJob(interfaceName, interfaceStateRemoveWorker);
             }
             return futures;
         }
 
+        private List<ListenableFuture<Void>> removeInterfaceStateConfiguration() {
+            LOG.debug("Removing interface state information for interface: {} {}", interfaceName, isNodePresent);
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            WriteTransaction defaultOperationalShardTransaction = dataBroker.newWriteOnlyTransaction();
+
+            //VM Migration: Use old nodeConnectorId to delete the interface entry
+            NodeConnectorId nodeConnectorId = nodeConnectorIdOld != null
+                    && !nodeConnectorIdNew.equals(nodeConnectorIdOld) ? nodeConnectorIdOld : nodeConnectorIdNew;
+            // delete the port entry from interface operational DS
+            BigInteger dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
+
+            //VM Migration: Update the interface state to unknown only if remove event received for same switch
+            if (!isNodePresent && nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
+                //Remove event is because of connection lost between controller and switch, or switch shutdown.
+                // Hence, don't remove the interface but set the status as "unknown"
+                ovsInterfaceStateUpdateHelper.updateInterfaceStateOnNodeRemove(interfaceName, fcNodeConnectorOld,
+                        defaultOperationalShardTransaction);
+            } else {
+                InterfaceManagerCommonUtils.deleteStateEntry(interfaceName, defaultOperationalShardTransaction);
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
+                    .Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
+
+                if (iface != null) {
+                    // If this interface is a tunnel interface, remove the tunnel ingress flow and stop LLDP monitoring
+                    if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
+                        interfaceMetaUtils.removeLportTagInterfaceMap(defaultOperationalShardTransaction,
+                                interfaceName);
+                        handleTunnelMonitoringRemoval(dpId, iface.getName(), iface.getAugmentation(IfTunnel.class),
+                                defaultOperationalShardTransaction, futures);
+                        return futures;
+                    }
+                }
+                // remove ingress flow only for northbound configured interfaces
+                // skip this check for non-unique ports(Ex: br-int,br-ex)
+                if (iface != null || !interfaceName.contains(fcNodeConnectorOld.getName())) {
+                    FlowBasedServicesUtils.removeIngressFlow(interfaceName, dpId, dataBroker, futures);
+                }
+
+                // Delete the Vpn Interface from DpnToInterface Op DS.
+                interfaceManagerCommonUtils.deleteDpnToInterface(dpId, interfaceName,
+                        defaultOperationalShardTransaction);
+            }
+            futures.add(defaultOperationalShardTransaction.submit());
+            return futures;
+        }
+
+        private void handleTunnelMonitoringRemoval(BigInteger dpId, String removedInterfaceName,
+                                                   IfTunnel ifTunnel, WriteTransaction transaction,
+                                                   List<ListenableFuture<Void>> futures) {
+            interfaceManagerCommonUtils.removeTunnelIngressFlow(ifTunnel, dpId, removedInterfaceName);
+
+            IfmUtil.unbindService(dataBroker, coordinator, removedInterfaceName,
+                    FlowBasedServicesUtils.buildDefaultServiceId(removedInterfaceName));
+
+            futures.add(transaction.submit());
+            alivenessMonitorUtils.stopLLDPMonitoring(ifTunnel, removedInterfaceName);
+        }
+
         @Override
         public String toString() {
-            return "InterfaceStateRemoveWorker{" +
-                    "nodeConnectorIdNew=" + nodeConnectorIdNew +
-                    ", nodeConnectorIdOld=" + nodeConnectorIdOld +
-                    ", fcNodeConnectorOld=" + fcNodeConnectorOld +
-                    ", interfaceName='" + interfaceName + '\'' +
-                    '}';
+            return "InterfaceStateRemoveWorker{" + "nodeConnectorIdNew=" + nodeConnectorIdNew + ", nodeConnectorIdOld="
+                    + nodeConnectorIdOld + ", fcNodeConnectorOld=" + fcNodeConnectorOld + ", interfaceName='"
+                    + interfaceName + '\'' + '}';
         }
     }
 
-    public static List<InterfaceChildEntry> getInterfaceChildEntries(DataBroker dataBroker, String interfaceName, NodeConnectorId nodeConnectorId) {
+    public List<InterfaceChildEntry> getInterfaceChildEntries(String interfaceName) {
         InterfaceParentEntry interfaceParentEntry =
-                InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceName, dataBroker);
-        if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
-            return interfaceParentEntry.getInterfaceChildEntry();
-        }
-        StringBuilder parentInterface = new StringBuilder(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
-        parentInterface.append(IfmConstants.OF_URI_SEPARATOR);
-        parentInterface.append(interfaceName);
-        interfaceParentEntry = InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(parentInterface.toString(), dataBroker);
+                interfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceName);
         if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
             return interfaceParentEntry.getInterfaceChildEntry();
         }
         return new ArrayList<>();
     }
-}
\ No newline at end of file
+}