2 * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.interfacemanager.listeners;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
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;
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
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.
77 public class InterfaceInventoryStateListener
78 extends AbstractClusteredAsyncDataTreeChangeListener<FlowCapableNodeConnector>
79 implements RecoverableListener {
81 private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
82 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
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;
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(),
132 public void registerListener() {
137 public void deregisterListener() {
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);
154 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
156 LOG.trace("Removing entry for port id {} from map",nodeConnectorId.getValue());
157 portNameCache.remove(nodeConnectorId.getValue());
160 if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
161 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
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());
171 remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
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);
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);
197 if (fcNodeConnectorNew.getReason() == PortReason.Delete
198 || !entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
199 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
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());
210 InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
211 fcNodeConnectorNew, portName);
212 coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
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);
227 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
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)) {
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());
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));
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);
263 LOG.warn("Port number update detected for {}", fcNodeConnectorNew.getName());
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
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");
282 InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
283 fcNodeConnectorNew, portName);
284 coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
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;
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;
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);
316 public String toString() {
317 return "InterfaceStateAddWorker{" + "nodeConnectorId=" + nodeConnectorId + ", fcNodeConnectorNew="
318 + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
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;
328 InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
329 FlowCapableNodeConnector fcNodeConnectorOld,
330 FlowCapableNodeConnector fcNodeConnectorNew,
333 this.fcNodeConnectorOld = fcNodeConnectorOld;
334 this.fcNodeConnectorNew = fcNodeConnectorNew;
335 this.interfaceName = portName;
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);
352 public String toString() {
353 return "InterfaceStateUpdateWorker{" + "key=" + key + ", fcNodeConnectorOld=" + fcNodeConnectorOld
354 + ", fcNodeConnectorNew=" + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
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;
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;
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();
395 List<ListenableFuture<Void>> futures = removeInterfaceStateConfiguration();
397 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(interfaceName);
398 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
399 // Fetch all interfaces on this port and trigger remove worker
401 InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
402 nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorOld,
403 interfaceChildEntry.getChildInterface(), isNetworkEvent, false);
404 coordinator.enqueueJob(interfaceName, interfaceStateRemoveWorker);
409 private List<ListenableFuture<Void>> removeInterfaceStateConfiguration() {
410 List<ListenableFuture<Void>> futures = new ArrayList<>();
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);
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
422 // cases treat the event as DPN disconnect, if old and new ports are same. Else, this is a VM
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,
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);
439 if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
440 // If this interface is a tunnel interface, remove the tunnel ingress flow and stop LLDP
442 interfaceMetaUtils.removeLportTagInterfaceMap(operTx, interfaceName);
443 return Optional.of((InterruptibleCheckedConsumer<TypedReadWriteTransaction<Configuration>,
444 ExecutionException>) confTx -> handleTunnelMonitoringRemoval(confTx, dpId,
446 iface.augmentation(IfTunnel.class)));
448 // remove ingress flow only for northbound configured interfaces
449 // skip this check for non-unique ports(Ex: br-int,br-ex)
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);
457 // Delete the Vpn Interface from DpnToInterface Op DS.
458 InterfaceManagerCommonUtils.deleteDpnToInterface(dpId, interfaceName, operTx);
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());
468 }, MoreExecutors.directExecutor())));
472 private void handleTunnelMonitoringRemoval(TypedReadWriteTransaction<Configuration> tx, Uint64 dpId,
473 String removedInterfaceName, IfTunnel ifTunnel) throws ExecutionException, InterruptedException {
474 interfaceManagerCommonUtils.removeTunnelIngressFlow(tx, ifTunnel, dpId, removedInterfaceName);
476 IfmUtil.unbindService(txRunner, coordinator, removedInterfaceName,
477 FlowBasedServicesUtils.buildDefaultServiceId(removedInterfaceName));
479 alivenessMonitorUtils.stopLLDPMonitoring(ifTunnel, removedInterfaceName);
483 public String toString() {
484 return "InterfaceStateRemoveWorker{" + "nodeConnectorIdNew=" + nodeConnectorIdNew + ", nodeConnectorIdOld="
485 + nodeConnectorIdOld + ", fcNodeConnectorOld=" + fcNodeConnectorOld + ", interfaceName='"
486 + interfaceName + '\'' + '}';
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();
496 return new ArrayList<>();