89b9d52d55bf51d6abd840a27162397f197fc8e0
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceInventoryStateListener.java
1 /*
2  * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.genius.interfacemanager.listeners;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Objects;
19 import java.util.Optional;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutionException;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.apache.aries.blueprint.annotation.service.Reference;
25 import org.checkerframework.checker.nullness.qual.Nullable;
26 import org.opendaylight.genius.infra.Datastore.Configuration;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
30 import org.opendaylight.genius.interfacemanager.IfmConstants;
31 import org.opendaylight.genius.interfacemanager.IfmUtil;
32 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
33 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
34 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
35 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
36 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
37 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
38 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
39 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
40 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
41 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
42 import org.opendaylight.infrautils.utils.concurrent.Executors;
43 import org.opendaylight.infrautils.utils.function.InterruptibleCheckedConsumer;
44 import org.opendaylight.mdsal.binding.api.DataBroker;
45 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
46 import org.opendaylight.serviceutils.srm.RecoverableListener;
47 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
48 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.opendaylight.yangtools.yang.common.Uint64;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65
66 /**
67  * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
68  * This creates an entry in the interface-state OperDS for every node-connector
69  * used.
70  *
71  * <p>
72  * NOTE: This class just creates an ifstate entry whose interface-name will be
73  * the same as the node-connector portname. If PortName is not unique across
74  * DPNs, this implementation can have problems.
75  */
76 @Singleton
77 public class InterfaceInventoryStateListener
78         extends AbstractClusteredAsyncDataTreeChangeListener<FlowCapableNodeConnector>
79         implements RecoverableListener {
80
81     private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
82     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
83
84     private final DataBroker dataBroker;
85     private final ManagedNewTransactionRunner txRunner;
86     private final IdManagerService idManager;
87     private final EntityOwnershipUtils entityOwnershipUtils;
88     private final JobCoordinator coordinator;
89     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
90     private final AlivenessMonitorUtils alivenessMonitorUtils;
91     private final OvsInterfaceStateUpdateHelper ovsInterfaceStateUpdateHelper;
92     private final OvsInterfaceStateAddHelper ovsInterfaceStateAddHelper;
93     private final InterfaceMetaUtils interfaceMetaUtils;
94     private final PortNameCache portNameCache;
95     private final InterfacemgrProvider interfacemgrProvider;
96
97     @Inject
98     public InterfaceInventoryStateListener(@Reference final DataBroker dataBroker,
99                                            final IdManagerService idManagerService,
100                                            final EntityOwnershipUtils entityOwnershipUtils,
101                                            @Reference final JobCoordinator coordinator,
102                                            final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
103                                            final OvsInterfaceStateAddHelper ovsInterfaceStateAddHelper,
104                                            final OvsInterfaceStateUpdateHelper ovsInterfaceStateUpdateHelper,
105                                            final AlivenessMonitorUtils alivenessMonitorUtils,
106                                            final InterfaceMetaUtils interfaceMetaUtils,
107                                            final PortNameCache portNameCache,
108                                            final InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler,
109                                            @Reference final ServiceRecoveryRegistry serviceRecoveryRegistry,
110                                            final InterfacemgrProvider interfacemgrProvider) {
111         super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
112                         .child(Node.class).child(NodeConnector.class)
113                         .augmentation(FlowCapableNodeConnector.class),
114                 Executors.newSingleThreadExecutor("InterfaceInventoryStateListener", LOG));
115         this.dataBroker = dataBroker;
116         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
117         this.idManager = idManagerService;
118         this.entityOwnershipUtils = entityOwnershipUtils;
119         this.coordinator = coordinator;
120         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
121         this.alivenessMonitorUtils = alivenessMonitorUtils;
122         this.ovsInterfaceStateUpdateHelper = ovsInterfaceStateUpdateHelper;
123         this.ovsInterfaceStateAddHelper = ovsInterfaceStateAddHelper;
124         this.interfaceMetaUtils = interfaceMetaUtils;
125         this.portNameCache = portNameCache;
126         this.interfacemgrProvider = interfacemgrProvider;
127         serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(),
128                 this);
129     }
130
131     @Override
132     public void registerListener() {
133         super.register();
134     }
135
136     @Override
137     public void deregisterListener() {
138         close();
139     }
140
141     @Override
142     public void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
143                           FlowCapableNodeConnector flowCapableNodeConnectorOld) {
144         String interfaceName = flowCapableNodeConnectorOld.getName();
145         EVENT_LOGGER.debug("IFM-InterfaceInventoryState,REMOVE {}", interfaceName);
146         if (interfacemgrProvider.isItmDirectTunnelsEnabled()
147             && InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
148             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName) == null) {
149             LOG.debug("ITM Direct Tunnels is enabled, node connector removed event for"
150                     + " internal tunnel {}", interfaceName);
151             return;
152         }
153
154         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
155                 .getId();
156         LOG.trace("Removing entry for port id {} from map",nodeConnectorId.getValue());
157         portNameCache.remove(nodeConnectorId.getValue());
158
159
160         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
161                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
162             return;
163         }
164
165         LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
166         String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
167             flowCapableNodeConnectorOld.getName());
168         EVENT_LOGGER.debug("IFM-InterfaceInventoryState Entity Owner,REMOVE {},{}", portName,
169                 nodeConnectorId.getValue());
170
171         remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
172     }
173
174     private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
175                         FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNetworkEvent) {
176         InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
177                 nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorNew, portName,
178                 isNetworkEvent, true);
179         coordinator.enqueueJob(portName, portStateRemoveWorker, IfmConstants.JOB_MAX_RETRIES);
180     }
181
182     @Override
183     public void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
184         FlowCapableNodeConnector fcNodeConnectorNew) {
185         String interfaceName = fcNodeConnectorNew.getName();
186         EVENT_LOGGER.debug("IFM-InterfaceInventoryState,UPDATE {},{}", fcNodeConnectorNew.getName(),
187                 fcNodeConnectorNew.getReason());
188         if (interfacemgrProvider.isItmDirectTunnelsEnabled()
189             && InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
190             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName) == null) {
191             LOG.debug("ITM Direct Tunnels is enabled, hence ignoring node connector Update event for"
192                     + " internal tunnel {}", interfaceName);
193             return;
194         }
195
196
197         if (fcNodeConnectorNew.getReason() == PortReason.Delete
198                 || !entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
199                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
200             return;
201         }
202
203         LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
204         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
205         String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
206                 fcNodeConnectorNew.getName());
207         EVENT_LOGGER.debug("IFM-InterfaceInventoryState Entity Owner,UPDATE {},{}", portName,
208                 nodeConnectorId.getValue());
209
210         InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
211             fcNodeConnectorNew, portName);
212         coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
213     }
214
215     @Override
216     public void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
217         String interfaceName = fcNodeConnectorNew.getName();
218         EVENT_LOGGER.debug("IFM-InterfaceInventoryState,ADD {}", interfaceName);
219         if (interfacemgrProvider.isItmDirectTunnelsEnabled()
220             && InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
221             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName) == null) {
222             LOG.debug("ITM Direct Tunnels is enabled, ignoring node connector add for"
223                     + " internal tunnel {}", interfaceName);
224             return;
225         }
226
227         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
228                 .getId();
229         LOG.trace("Adding entry for portid {} portname {} in map", nodeConnectorId.getValue(),
230                 fcNodeConnectorNew.getName());
231         portNameCache.put(nodeConnectorId.getValue(),fcNodeConnectorNew.getName());
232         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
233                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
234             return;
235         }
236
237         LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
238         String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
239             fcNodeConnectorNew.getName());
240         EVENT_LOGGER.debug("IFM-InterfaceInventoryState Entity Owner,ADD {},{}", portName, nodeConnectorId.getValue());
241
242         if (InterfaceManagerCommonUtils.isNovaPort(portName) || InterfaceManagerCommonUtils.isK8SPort(portName)) {
243             NodeConnectorId nodeConnectorIdOld = null;
244             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
245                     .ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = interfaceManagerCommonUtils
246                     .getInterfaceState(interfaceName);
247             if (interfaceState != null) {
248                 List<String> ofportIds = interfaceState.getLowerLayerIf();
249                 nodeConnectorIdOld = new NodeConnectorId(ofportIds.get(0));
250             }
251             if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
252                 Uint64 dpnIdOld = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorIdOld);
253                 Uint64 dpnIdNew = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
254                 if (!Objects.equals(dpnIdOld, dpnIdNew)) {
255                     if (fcNodeConnectorNew.getReason() != PortReason.Add
256                             && interfaceState.getOperStatus()
257                             != Interface.OperStatus.Unknown) {
258                         LOG.error("Dropping Port update event for {}, as DPN id is changed from {} to {}",
259                             fcNodeConnectorNew.getName(), dpnIdOld, dpnIdNew);
260                         return;
261                     }
262                 } else {
263                     LOG.warn("Port number update detected for {}", fcNodeConnectorNew.getName());
264                 }
265                 //VM Migration or Port Number Update: Delete existing interface entry for older DPN
266                 LOG.trace("Removing entry for port id {} from map",nodeConnectorIdOld.getValue());
267                 portNameCache.remove(nodeConnectorIdOld.getValue());
268                 EVENT_LOGGER.debug("IFM-VMMigration,{}", portName);
269                 LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName,
270                     nodeConnectorId, nodeConnectorIdOld);
271                 remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
272                 // Adding a delay of 10sec for VM migration, so applications will have sufficient time
273                 // for processing remove before add
274                 try {
275                     Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
276                 } catch (final InterruptedException e) {
277                     LOG.error("Error while waiting for the vm migration remove events to get processed");
278                 }
279             }
280         }
281
282         InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
283             fcNodeConnectorNew, portName);
284         coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
285     }
286
287
288     private class InterfaceStateAddWorker implements Callable {
289         private final NodeConnectorId nodeConnectorId;
290         private final FlowCapableNodeConnector fcNodeConnectorNew;
291         private final String interfaceName;
292         private final IdManagerService idManager;
293
294         InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
295                                 FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
296             this.nodeConnectorId = nodeConnectorId;
297             this.fcNodeConnectorNew = fcNodeConnectorNew;
298             this.interfaceName = portName;
299             this.idManager = idManager;
300         }
301
302         @Override
303         public Object call() {
304             List<ListenableFuture<Void>> futures = ovsInterfaceStateAddHelper.addState(nodeConnectorId,
305                     interfaceName, fcNodeConnectorNew);
306             List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
307             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
308                 InterfaceStateAddWorker interfaceStateAddWorker = new InterfaceStateAddWorker(idManager,
309                         nodeConnectorId, fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
310                 coordinator.enqueueJob(interfaceName, interfaceStateAddWorker);
311             }
312             return futures;
313         }
314
315         @Override
316         public String toString() {
317             return "InterfaceStateAddWorker{" + "nodeConnectorId=" + nodeConnectorId + ", fcNodeConnectorNew="
318                     + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
319         }
320     }
321
322     private class InterfaceStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
323         private final InstanceIdentifier<FlowCapableNodeConnector> key;
324         private final FlowCapableNodeConnector fcNodeConnectorOld;
325         private final FlowCapableNodeConnector fcNodeConnectorNew;
326         private final String interfaceName;
327
328         InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
329                                    FlowCapableNodeConnector fcNodeConnectorOld,
330                                    FlowCapableNodeConnector fcNodeConnectorNew,
331                                    String portName) {
332             this.key = key;
333             this.fcNodeConnectorOld = fcNodeConnectorOld;
334             this.fcNodeConnectorNew = fcNodeConnectorNew;
335             this.interfaceName = portName;
336         }
337
338         @Override
339         public List<ListenableFuture<Void>> call() {
340             List<ListenableFuture<Void>> futures = ovsInterfaceStateUpdateHelper.updateState(
341                     interfaceName, fcNodeConnectorNew, fcNodeConnectorOld);
342             List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
343             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
344                 InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key,
345                         fcNodeConnectorOld, fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
346                 coordinator.enqueueJob(interfaceName, interfaceStateUpdateWorker);
347             }
348             return futures;
349         }
350
351         @Override
352         public String toString() {
353             return "InterfaceStateUpdateWorker{" + "key=" + key + ", fcNodeConnectorOld=" + fcNodeConnectorOld
354                     + ", fcNodeConnectorNew=" + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
355         }
356     }
357
358     private class InterfaceStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
359         private final NodeConnectorId nodeConnectorIdNew;
360         private NodeConnectorId nodeConnectorIdOld;
361         private final FlowCapableNodeConnector fcNodeConnectorOld;
362         private final String interfaceName;
363         private final IdManagerService idManager;
364         private final boolean isNetworkEvent;
365         private final boolean isParentInterface;
366
367         InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
368                                    NodeConnectorId nodeConnectorIdOld,
369                                    FlowCapableNodeConnector fcNodeConnectorOld, String interfaceName,
370                                    boolean isNetworkEvent,
371                                    boolean isParentInterface) {
372             this.nodeConnectorIdNew = nodeConnectorIdNew;
373             this.nodeConnectorIdOld = nodeConnectorIdOld;
374             this.fcNodeConnectorOld = fcNodeConnectorOld;
375             this.interfaceName = interfaceName;
376             this.idManager = idManager;
377             this.isNetworkEvent = isNetworkEvent;
378             this.isParentInterface = isParentInterface;
379         }
380
381         @Override
382         public List<ListenableFuture<Void>> call() {
383             // VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD
384             // for same interface from Older DPN
385             if (isParentInterface && isNetworkEvent) {
386                 nodeConnectorIdOld = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(interfaceName,
387                         interfaceManagerCommonUtils);
388                 if (nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
389                     LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", interfaceName,
390                             nodeConnectorIdNew, nodeConnectorIdOld);
391                     return Collections.emptyList();
392                 }
393             }
394
395             List<ListenableFuture<Void>> futures = removeInterfaceStateConfiguration();
396
397             List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
398             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
399                 // Fetch all interfaces on this port and trigger remove worker
400                 // for each of them
401                 InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
402                         nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorOld,
403                         interfaceChildEntry.getChildInterface(), isNetworkEvent, false);
404                 coordinator.enqueueJob(interfaceName, interfaceStateRemoveWorker);
405             }
406             return futures;
407         }
408
409         private List<ListenableFuture<Void>> removeInterfaceStateConfiguration() {
410             List<ListenableFuture<Void>> futures = new ArrayList<>();
411
412             //VM Migration: Use old nodeConnectorId to delete the interface entry
413             NodeConnectorId nodeConnectorId = nodeConnectorIdOld != null
414                     && !nodeConnectorIdNew.equals(nodeConnectorIdOld) ? nodeConnectorIdOld : nodeConnectorIdNew;
415             // delete the port entry from interface operational DS
416             Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
417
418             futures.add(txRunner.applyWithNewTransactionChainAndClose(txChain ->
419                 txChain.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
420                     // In a genuine port delete scenario, the reason will be there in the incoming event, for all
421                     // remaining
422                     // cases treat the event as DPN disconnect, if old and new ports are same. Else, this is a VM
423                     // migration
424                     // scenario, and should be treated as port removal.
425                     LOG.debug("Removing interface state information for interface: {}", interfaceName);
426                     if (fcNodeConnectorOld.getReason() != PortReason.Delete
427                         && nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
428                         //Remove event is because of connection lost between controller and switch, or switch shutdown.
429                         // Hence, don't remove the interface but set the status as "unknown"
430                         ovsInterfaceStateUpdateHelper.updateInterfaceStateOnNodeRemove(interfaceName,
431                             fcNodeConnectorOld,
432                             operTx);
433                     } else {
434                         EVENT_LOGGER.debug("IFM-OvsInterfaceState,REMOVE {}", interfaceName);
435                         InterfaceManagerCommonUtils.deleteStateEntry(operTx, interfaceName);
436                         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
437                             .Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
438
439                         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
440                             // If this interface is a tunnel interface, remove the tunnel ingress flow and stop LLDP
441                             // monitoring
442                             interfaceMetaUtils.removeLportTagInterfaceMap(operTx, interfaceName);
443                             return Optional.of((InterruptibleCheckedConsumer<TypedReadWriteTransaction<Configuration>,
444                                 ExecutionException>) confTx -> handleTunnelMonitoringRemoval(confTx, dpId,
445                                 iface.getName(),
446                                 iface.augmentation(IfTunnel.class)));
447                         }
448                         // remove ingress flow only for northbound configured interfaces
449                         // skip this check for non-unique ports(Ex: br-int,br-ex)
450
451                         if (iface != null) {
452                             FlowBasedServicesUtils.removeIngressFlow(interfaceName, dpId, txRunner, futures);
453                             IfmUtil.unbindService(txRunner, coordinator, iface.getName(),
454                                     FlowBasedServicesUtils.buildDefaultServiceId(iface.getName()));
455                             EVENT_LOGGER.debug("IFM-InterfaceState, REMOVE, IngressFlow {}", interfaceName);
456                         }
457                         // Delete the Vpn Interface from DpnToInterface Op DS.
458                         InterfaceManagerCommonUtils.deleteDpnToInterface(dpId, interfaceName, operTx);
459                     }
460                     return Optional.empty();
461                 }).transform((@Nullable Optional<?> optionalJob) -> {
462                     if (optionalJob != null && optionalJob.isPresent()) {
463                         txChain.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
464                             (InterruptibleCheckedConsumer<TypedReadWriteTransaction<Configuration>, ?
465                                 extends Exception>) optionalJob.get());
466                     }
467                     return null;
468                 }, MoreExecutors.directExecutor())));
469             return futures;
470         }
471
472         private void handleTunnelMonitoringRemoval(TypedReadWriteTransaction<Configuration> tx, Uint64 dpId,
473             String removedInterfaceName, IfTunnel ifTunnel) throws ExecutionException, InterruptedException {
474             interfaceManagerCommonUtils.removeTunnelIngressFlow(tx, ifTunnel, dpId, removedInterfaceName);
475
476             IfmUtil.unbindService(txRunner, coordinator, removedInterfaceName,
477                     FlowBasedServicesUtils.buildDefaultServiceId(removedInterfaceName));
478
479             alivenessMonitorUtils.stopLLDPMonitoring(ifTunnel, removedInterfaceName);
480         }
481
482         @Override
483         public String toString() {
484             return "InterfaceStateRemoveWorker{" + "nodeConnectorIdNew=" + nodeConnectorIdNew + ", nodeConnectorIdOld="
485                     + nodeConnectorIdOld + ", fcNodeConnectorOld=" + fcNodeConnectorOld + ", interfaceName='"
486                     + interfaceName + '\'' + '}';
487         }
488     }
489
490     public List<InterfaceChildEntry> getInterfaceChildEntries(String interfaceName) {
491         InterfaceParentEntry interfaceParentEntry =
492                 interfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceName);
493         if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
494             return interfaceParentEntry.getInterfaceChildEntry();
495         }
496         return new ArrayList<>();
497     }
498 }