2 * Copyright (c) 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.itm.itmdirecttunnels.listeners;
10 import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 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.ConcurrentHashMap;
22 import java.util.concurrent.ConcurrentMap;
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
25 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
26 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
27 import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache;
28 import org.opendaylight.genius.itm.cache.TunnelStateCache;
29 import org.opendaylight.genius.itm.cache.UnprocessedNodeConnectorCache;
30 import org.opendaylight.genius.itm.cache.UnprocessedNodeConnectorEndPointCache;
31 import org.opendaylight.genius.itm.cache.UnprocessedOFNodeConnectorCache;
32 import org.opendaylight.genius.itm.globals.ITMConstants;
33 import org.opendaylight.genius.itm.impl.ItmUtils;
34 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
35 import org.opendaylight.genius.itm.itmdirecttunnels.workers.OfPortStateAddWorker;
36 import org.opendaylight.genius.itm.itmdirecttunnels.workers.OfPortStateAddWorkerForNodeConnector;
37 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorker;
38 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorkerForNodeConnector;
39 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
40 import org.opendaylight.genius.itm.utils.NodeConnectorInfo;
41 import org.opendaylight.genius.itm.utils.NodeConnectorInfoBuilder;
42 import org.opendaylight.genius.itm.utils.TunnelEndPointInfo;
43 import org.opendaylight.genius.itm.utils.TunnelStateInfo;
44 import org.opendaylight.genius.itm.utils.TunnelStateInfoBuilder;
45 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
46 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
47 import org.opendaylight.mdsal.binding.api.DataBroker;
48 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
49 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
50 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
51 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
52 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
53 import org.opendaylight.mdsal.common.api.ReadFailedException;
54 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredSyncDataTreeChangeListener;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.Uint64;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
73 * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
74 * This creates an entry in the tunnels-state OperDS for every node-connector used.
76 public class TunnelInventoryStateListener extends
77 AbstractClusteredSyncDataTreeChangeListener<FlowCapableNodeConnector> {
79 private static final Logger LOG = LoggerFactory.getLogger(TunnelInventoryStateListener.class);
80 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
82 private final JobCoordinator coordinator;
83 private final ManagedNewTransactionRunner txRunner;
84 private final TunnelStateCache tunnelStateCache;
85 private final DpnTepStateCache dpnTepStateCache;
86 private final DPNTEPsInfoCache dpntePsInfoCache;
87 private final UnprocessedNodeConnectorCache unprocessedNCCache;
88 private final UnprocessedNodeConnectorEndPointCache unprocessedNodeConnectorEndPointCache;
89 private final DirectTunnelUtils directTunnelUtils;
90 private final ConcurrentMap<String, NodeConnectorInfo> meshedMap = new ConcurrentHashMap<>();
91 private final UnprocessedOFNodeConnectorCache unprocessedOFNCCache;
92 private final OfDpnTepConfigCache ofDpnTepConfigCache;
93 private final IInterfaceManager interfaceManager;
95 public TunnelInventoryStateListener(final DataBroker dataBroker,
96 final JobCoordinator coordinator,
97 final TunnelStateCache tunnelStateCache,
98 final DpnTepStateCache dpnTepStateCache,
99 final DPNTEPsInfoCache dpntePsInfoCache,
100 final UnprocessedNodeConnectorCache unprocessedNCCache,
101 final UnprocessedNodeConnectorEndPointCache
102 unprocessedNodeConnectorEndPointCache,
103 final DirectTunnelUtils directTunnelUtils,
104 UnprocessedOFNodeConnectorCache unprocessedOFNCCache,
105 final OfDpnTepConfigCache ofDpnTepConfigCache,
106 final IInterfaceManager interfaceManager) {
107 super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class).child(Node.class)
108 .child(NodeConnector.class).augmentation(FlowCapableNodeConnector.class));
109 this.coordinator = coordinator;
110 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
111 this.tunnelStateCache = tunnelStateCache;
112 this.dpnTepStateCache = dpnTepStateCache;
113 this.dpntePsInfoCache = dpntePsInfoCache;
114 this.unprocessedNCCache = unprocessedNCCache;
115 this.unprocessedNodeConnectorEndPointCache = unprocessedNodeConnectorEndPointCache;
116 this.directTunnelUtils = directTunnelUtils;
117 this.unprocessedOFNCCache = unprocessedOFNCCache;
118 this.ofDpnTepConfigCache = ofDpnTepConfigCache;
119 this.interfaceManager = interfaceManager;
124 public void remove(@NonNull InstanceIdentifier<FlowCapableNodeConnector> key,
125 @NonNull FlowCapableNodeConnector flowCapableNodeConnector) {
126 String portName = flowCapableNodeConnector.getName();
127 LOG.debug("InterfaceInventoryState Remove for {}", portName);
128 EVENT_LOGGER.debug("ITM-TunnelInventoryState,REMOVE DTCN received for {}",
129 flowCapableNodeConnector.getName());
130 // ITM Direct Tunnels Return if its not tunnel port and if its not Internal
131 if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && !portName.startsWith("of")) {
132 LOG.debug("Node Connector Remove - {} Interface is not a tunnel I/f, so no-op", portName);
136 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName)
137 && !tunnelStateCache.isInternalBasedOnState(portName)) {
138 LOG.debug("Node Connector Remove {} Interface is not a internal tunnel I/f, so no-op", portName);
141 } catch (ReadFailedException e) {
142 LOG.error("Tunnel {} is not present in operational DS ", portName);
146 if (!directTunnelUtils.isEntityOwner()) {
149 LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnector);
150 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
151 remove(nodeConnectorId, flowCapableNodeConnector, portName);
154 private void remove(NodeConnectorId nodeConnectorId,
155 FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
156 LOG.debug("TunnelInventoryState REMOVE for {}", portName);
157 LOG.debug("InterfaceInventoryState REMOVE for {}", portName);
158 EVENT_LOGGER.debug("ITM-TunnelInventoryState Entity Owner, REMOVE {} {}", nodeConnectorId.getValue(),
160 TunnelInterfaceStateRemoveWorker portStateRemoveWorker = new TunnelInterfaceStateRemoveWorker(nodeConnectorId,
161 fcNodeConnectorNew, portName);
162 coordinator.enqueueJob(portName, portStateRemoveWorker, ITMConstants.JOB_MAX_RETRIES);
166 public void update(@NonNull InstanceIdentifier<FlowCapableNodeConnector> key,
167 @NonNull FlowCapableNodeConnector fcNodeConnectorOld,
168 @NonNull FlowCapableNodeConnector fcNodeConnectorNew) {
169 EVENT_LOGGER.debug("ITM-TunnelInventoryState,UPDATE DTCN received for {}", fcNodeConnectorOld.getName());
170 String portName = fcNodeConnectorNew.getName();
171 if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && !portName.startsWith("of")) {
172 LOG.debug("Node Connector Update - {} Interface is not a tunnel I/f, so no-op", portName);
174 } else if (!dpnTepStateCache.isInternal(portName)) {
175 LOG.debug("Node Connector Update {} Interface is not a internal tunnel I/f, so no-op", portName);
179 if (fcNodeConnectorNew.getReason() == PortReason.Delete || !directTunnelUtils.isEntityOwner()) {
182 LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
184 TunnelInterfaceStateUpdateWorker portStateUpdateWorker =
185 new TunnelInterfaceStateUpdateWorker(key, fcNodeConnectorOld, fcNodeConnectorNew, portName);
186 EVENT_LOGGER.debug("ITM-TunnelInventoryState Entity Owner, UPDATE {} {} Reason {}",
187 fcNodeConnectorNew.getName(), portName, fcNodeConnectorNew.getReason());
188 coordinator.enqueueJob(portName, portStateUpdateWorker, ITMConstants.JOB_MAX_RETRIES);
192 public void add(@NonNull InstanceIdentifier<FlowCapableNodeConnector> key,
193 @NonNull FlowCapableNodeConnector fcNodeConnectorNew) {
194 LOG.info("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
195 EVENT_LOGGER.debug("ITM-TunnelInventoryState,ADD DTCN received for {}", fcNodeConnectorNew.getName());
196 String portName = fcNodeConnectorNew.getName();
198 // Return if its not tunnel port and if its not Internal
199 if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && !portName.startsWith("of")) {
200 LOG.debug("Node Connector Add {} Interface is not a tunnel I/f, so no-op", portName);
204 if (!directTunnelUtils.isEntityOwner()) {
205 LOG.debug("Not an entity owner.");
209 //Optional<OfDpnTep> dpnTepOptional = Optional.ofNullable(null);
210 NodeConnectorInfo nodeConnectorInfo =
211 new NodeConnectorInfoBuilder().setNodeConnectorId(key).setNodeConnector(fcNodeConnectorNew).build();
213 if (portName.startsWith("of") && interfaceManager.isItmOfTunnelsEnabled()) {
214 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
216 Uint64 srcDpn = DirectTunnelUtils.getDpnFromNodeConnectorId(nodeConnectorId);
218 OfDpnTep dpntep = null;
219 try (Acquired lock = directTunnelUtils.lockTunnel(portName)) {
221 Optional<OfDpnTep> dpnTepOptional = ofDpnTepConfigCache.get(srcDpn.toJava());
222 if (!dpnTepOptional.isPresent()) {
223 // Park the notification
224 LOG.debug("Unable to process the NodeConnector ADD event for {} as Config not available."
225 + "Hence parking it", portName);
226 unprocessedOFNCCache.add(portName, nodeConnectorInfo);
229 dpntep = dpnTepOptional.get();
231 } catch (ReadFailedException e) {
232 LOG.error("unable to get ofDpnTepConfigCache");
236 if (dpntep != null) {
237 OfPortStateAddWorkerForNodeConnector ifOfStateAddWorker =
238 new OfPortStateAddWorkerForNodeConnector(new OfPortStateAddWorker(directTunnelUtils,
239 dpntep, txRunner), nodeConnectorInfo);
240 EVENT_LOGGER.debug("ITM-Of-tepInventoryState Entity Owner,ADD {} {}",
241 nodeConnectorId.getValue(), portName);
242 coordinator.enqueueJob(portName, ifOfStateAddWorker, ITMConstants.JOB_MAX_RETRIES);
245 addTunnelState(nodeConnectorInfo, portName);
249 private void addTunnelState(NodeConnectorInfo nodeConnectorInfo, String portName) {
251 TunnelStateInfo tunnelStateInfo = null;
252 TunnelEndPointInfo tunnelEndPtInfo = null;
253 try (Acquired lock = directTunnelUtils.lockTunnel(portName)) {
254 if (!dpnTepStateCache.isConfigAvailable(portName)) {
255 // Park the notification
256 LOG.debug("Unable to process the NodeConnector ADD event for {} as Config not available."
257 + "Hence parking it", portName);
258 unprocessedNCCache.add(portName,
259 new TunnelStateInfoBuilder().setNodeConnectorInfo(nodeConnectorInfo).build());
261 } else if (!dpnTepStateCache.isInternal(portName)) {
262 LOG.debug("{} Interface is not a internal tunnel I/f, so no-op", portName);
267 // Check if tunnels State has an entry for this interface.
268 // If so, then this Inventory Add is due to compute re-connection. Then, ONLY update the state
269 // to UP as previously the compute would have disconnected and so the state will be UNKNOWN.
271 long portNo = tunnelStateCache.getNodeConnectorIdFromInterface(portName);
272 if (portNo != ITMConstants.INVALID_PORT_NO) {
273 coordinator.enqueueJob(portName,
274 new TunnelInterfaceNodeReconnectWorker(portName), ITMConstants.JOB_MAX_RETRIES);
277 } catch (ReadFailedException e) {
278 LOG.error("Exception occurred in reconnect for portName {}, reason: {}.",
279 portName, e.getMessage());
282 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && dpnTepStateCache.isInternal(portName)) {
283 tunnelEndPtInfo = dpnTepStateCache.getTunnelEndPointInfoFromCache(portName);
284 TunnelStateInfoBuilder builder = new TunnelStateInfoBuilder().setNodeConnectorInfo(nodeConnectorInfo);
285 dpntePsInfoCache.getDPNTepFromDPNId(Uint64.valueOf(tunnelEndPtInfo.getSrcEndPointInfo()))
286 .ifPresent(builder::setSrcDpnTepsInfo);
287 dpntePsInfoCache.getDPNTepFromDPNId(Uint64.valueOf(tunnelEndPtInfo.getDstEndPointInfo()))
288 .ifPresent(builder::setDstDpnTepsInfo);
289 tunnelStateInfo = builder.setTunnelEndPointInfo(tunnelEndPtInfo)
290 .setDpnTepInterfaceInfo(dpnTepStateCache.getTunnelFromCache(portName)).build();
292 if (tunnelStateInfo.getSrcDpnTepsInfo() == null) {
293 try (Acquired lock = directTunnelUtils.lockTunnel(tunnelEndPtInfo.getSrcEndPointInfo())) {
294 LOG.debug("Source DPNTepsInfo is null for tunnel {}. Hence Parking with key {}",
295 portName, tunnelEndPtInfo.getSrcEndPointInfo());
296 unprocessedNodeConnectorEndPointCache.add(tunnelEndPtInfo.getSrcEndPointInfo(), tunnelStateInfo);
299 if (tunnelStateInfo.getDstDpnTepsInfo() == null) {
300 try (Acquired lock = directTunnelUtils.lockTunnel(tunnelEndPtInfo.getDstEndPointInfo())) {
301 LOG.debug("Destination DPNTepsInfo is null for tunnel {}. Hence Parking with key {}",
302 portName, tunnelEndPtInfo.getDstEndPointInfo());
303 unprocessedNodeConnectorEndPointCache.add(tunnelEndPtInfo.getDstEndPointInfo(), tunnelStateInfo);
308 if (tunnelEndPtInfo != null && tunnelStateInfo.getSrcDpnTepsInfo() != null
309 && tunnelStateInfo.getDstDpnTepsInfo() != null) {
310 EVENT_LOGGER.debug("ITM-TunnelInventoryState Entity Owner,ADD {}", portName);
311 coordinator.enqueueJob(portName,
312 new TunnelStateAddWorkerForNodeConnector(new TunnelStateAddWorker(directTunnelUtils, txRunner),
313 tunnelStateInfo), ITMConstants.JOB_MAX_RETRIES);
317 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
318 justification = "https://github.com/spotbugs/spotbugs/issues/811")
319 private List<? extends ListenableFuture<?>> updateState(String interfaceName,
320 FlowCapableNodeConnector flowCapableNodeConnectorNew,
321 FlowCapableNodeConnector flowCapableNodeConnectorOld) {
322 LOG.debug("Updating interface state for port: {}", interfaceName);
324 // Hardware updates can be ignored
325 Interface.OperStatus operStatusNew = getOpState(flowCapableNodeConnectorNew);
326 MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
328 Interface.OperStatus operStatusOld = getOpState(flowCapableNodeConnectorOld);
329 MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
331 boolean opstateModified = false;
332 boolean hardwareAddressModified = false;
333 if (!operStatusNew.equals(operStatusOld)) {
334 opstateModified = true;
336 if (!Objects.equals(macAddressNew, macAddressOld)) {
337 hardwareAddressModified = true;
340 if (!opstateModified && !hardwareAddressModified) {
341 LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
342 return Collections.emptyList();
345 DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
347 // For monitoring enabled tunnels, skip opstate updation
348 if (!modifyTunnelOpState(dpnTepInfo, opstateModified)) {
349 LOG.debug("skipping Tunnel-state update for monitoring enabled tunnel interface {}", interfaceName);
350 opstateModified = false;
353 if (!opstateModified && !hardwareAddressModified) {
354 LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
355 return Collections.emptyList();
357 if (opstateModified) {
358 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
359 // modify the attributes in interface operational DS
360 handleInterfaceStateUpdates(tx, dpnTepInfo, true, interfaceName, flowCapableNodeConnectorNew.getName(),
362 EVENT_LOGGER.debug("ITM-TunnelInventoryState, UPDATE {} CHGED {} completed", interfaceName,
363 operStatusNew.getName());
366 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
367 // modify the attributes in interface operational DS
368 handleInterfaceStateUpdates(tx, dpnTepInfo, false, interfaceName,
369 flowCapableNodeConnectorNew.getName(), operStatusNew);
370 EVENT_LOGGER.debug("ITM-TunnelInventoryState, UPDATE {} completed", interfaceName);
375 private void updateInterfaceStateOnNodeRemove(TypedWriteTransaction<Operational> tx, String interfaceName,
376 FlowCapableNodeConnector flowCapableNodeConnector) {
377 LOG.debug("Updating interface oper-status to UNKNOWN for : {}", interfaceName);
378 DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
380 handleInterfaceStateUpdates(tx, dpnTepInfo, true, interfaceName, flowCapableNodeConnector.getName(),
381 Interface.OperStatus.Unknown);
384 private Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) {
385 return flowCapableNodeConnector.getState().isLive()
386 && !flowCapableNodeConnector.getConfiguration().isPORTDOWN()
387 ? Interface.OperStatus.Up : Interface.OperStatus.Down;
390 private void handleInterfaceStateUpdates(TypedWriteTransaction<Operational> tx,
391 DpnTepInterfaceInfo dpnTepInfo,
392 boolean opStateModified, String interfaceName, String portName,
393 Interface.OperStatus opState) {
394 if (dpnTepInfo == null && !portName.startsWith("of") && !interfaceName.equals(portName)) {
397 LOG.debug("updating interface state entry for {}", interfaceName);
398 InstanceIdentifier<StateTunnelList> tnlStateId = ItmUtils.buildStateTunnelListId(
399 new StateTunnelListKey(interfaceName));
400 StateTunnelListBuilder stateTnlBuilder = new StateTunnelListBuilder();
401 stateTnlBuilder.withKey(new StateTunnelListKey(interfaceName));
402 if (modifyOpState(dpnTepInfo, opStateModified)) {
403 LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
404 boolean tunnelState = opState.equals(Interface.OperStatus.Up);
405 stateTnlBuilder.setTunnelState(tunnelState);
406 stateTnlBuilder.setOperState(DirectTunnelUtils.convertInterfaceToTunnelOperState(opState));
408 tx.merge(tnlStateId, stateTnlBuilder.build());
411 private boolean modifyOpState(DpnTepInterfaceInfo dpnTepInterfaceInfo, boolean opStateModified) {
412 return opStateModified && dpnTepInterfaceInfo != null;
415 private boolean modifyTunnelOpState(DpnTepInterfaceInfo dpnTepInterfaceInfo, boolean opStateModified) {
416 return !dpnTepInterfaceInfo.isMonitoringEnabled() && modifyOpState(dpnTepInterfaceInfo, opStateModified);
419 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
420 justification = "https://github.com/spotbugs/spotbugs/issues/811")
421 private List<? extends ListenableFuture<?>> removeInterfaceStateConfiguration(NodeConnectorId nodeConnectorId,
422 String interfaceName,
423 FlowCapableNodeConnector
424 flowCapableNodeConnector) {
427 List<ListenableFuture<?>> futures = new ArrayList<>();
428 Uint64 dpId = DirectTunnelUtils.getDpnFromNodeConnectorId(nodeConnectorId);
429 // In a genuine port delete scenario, the reason will be there in the incoming event, for all remaining
430 // cases treat the event as DPN disconnect, if old and new ports are same. Else, this is a VM migration
431 // scenario, and should be treated as port removal.
432 if (flowCapableNodeConnector.getReason() != PortReason.Delete) {
433 //Remove event is because of connection lost between controller and switch, or switch shutdown.
434 // Hence, dont remove the interface but set the status as "unknown"
436 if (interfaceName.startsWith("of")) {
437 LOG.debug("Received remove state for dpid {}", dpId.intValue());
438 for (Map.Entry<String, NodeConnectorInfo> entry : meshedMap.entrySet()) {
439 if (!dpId.toString().equals(entry.getKey())) {
440 String fwdTunnel = dpnTepStateCache.getDpnTepInterface(dpId, Uint64.valueOf(entry.getKey()))
442 LOG.debug("Fwd Tunnel name for {} : {} is {}", dpId.intValue(), entry.getKey(), fwdTunnel);
443 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
444 tx -> updateInterfaceStateOnNodeRemove(tx, fwdTunnel, flowCapableNodeConnector)));
445 String bwdTunnel = dpnTepStateCache.getDpnTepInterface(Uint64.valueOf(entry.getKey()), dpId)
447 LOG.debug("Bwd Tunnel name for {} : {} is {}", entry.getKey(), dpId.intValue(), bwdTunnel);
448 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
449 tx -> updateInterfaceStateOnNodeRemove(tx, bwdTunnel,
450 entry.getValue().getNodeConnector())));
454 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
455 tx -> updateInterfaceStateOnNodeRemove(tx, interfaceName, flowCapableNodeConnector)));
458 LOG.debug("removing interface state for interface: {}", interfaceName);
459 EVENT_LOGGER.debug("ITM-TunnelInventoryState,REMOVE Table 0 flow for {} completed", interfaceName);
460 // removing interfaces are already done in delete worker
461 meshedMap.remove(dpId.toString());
466 private class TunnelInterfaceStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
467 private final InstanceIdentifier<FlowCapableNodeConnector> key;
468 private final FlowCapableNodeConnector fcNodeConnectorOld;
469 private final FlowCapableNodeConnector fcNodeConnectorNew;
470 private final String interfaceName;
472 TunnelInterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
473 FlowCapableNodeConnector fcNodeConnectorOld,
474 FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
476 this.fcNodeConnectorOld = fcNodeConnectorOld;
477 this.fcNodeConnectorNew = fcNodeConnectorNew;
478 this.interfaceName = portName;
482 public List<? extends ListenableFuture<?>> call() {
483 // If another renderer(for eg : OVS) needs to be supported, check can be performed here
484 // to call the respective helpers.
485 return updateState(interfaceName, fcNodeConnectorNew, fcNodeConnectorOld);
489 public String toString() {
490 return "TunnelInterfaceStateUpdateWorker{key=" + key + ", fcNodeConnectorOld=" + fcNodeConnectorOld
491 + ", fcNodeConnectorNew=" + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
495 private class TunnelInterfaceStateRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
496 private final NodeConnectorId nodeConnectorId;
497 private final FlowCapableNodeConnector flowCapableNodeConnector;
498 private final String interfaceName;
500 TunnelInterfaceStateRemoveWorker(NodeConnectorId nodeConnectorId,
501 FlowCapableNodeConnector flowCapableNodeConnector,
502 String interfaceName) {
503 this.nodeConnectorId = nodeConnectorId;
504 this.flowCapableNodeConnector = flowCapableNodeConnector;
505 this.interfaceName = interfaceName;
509 public List<? extends ListenableFuture<?>> call() {
510 // If another renderer(for eg : OVS) needs to be supported, check can be performed here
511 // to call the respective helpers.
512 return removeInterfaceStateConfiguration(nodeConnectorId, interfaceName, flowCapableNodeConnector);
516 public String toString() {
517 return "TunnelInterfaceStateRemoveWorker{nodeConnectorId=" + nodeConnectorId + ", fcNodeConnector"
518 + flowCapableNodeConnector + ", interfaceName='" + interfaceName + '\'' + '}';
522 private class TunnelInterfaceNodeReconnectWorker implements Callable<List<? extends ListenableFuture<?>>> {
523 private final String tunnelName;
525 TunnelInterfaceNodeReconnectWorker(String tunnelName) {
526 this.tunnelName = tunnelName;
530 public List<? extends ListenableFuture<?>> call() throws Exception {
531 // If another renderer(for eg : OVS) needs to be supported, check can be performed here
532 // to call the respective helpers.
533 EVENT_LOGGER.debug("ITM-TunnelInventoryState, Compute Re-connected, ADD received for {} ", tunnelName);
535 return handleInterfaceStateOnReconnect(tunnelName);
539 public String toString() {
540 return "TunnelInterfaceNodeReconnectWorker{tunnelName=" + tunnelName + '\'' + '}';
544 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
545 justification = "https://github.com/spotbugs/spotbugs/issues/811")
546 private List<? extends ListenableFuture<?>> handleInterfaceStateOnReconnect(String interfaceName) {
547 List<ListenableFuture<?>> futures = new ArrayList<>();
549 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
550 DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
552 handleInterfaceStateUpdates(tx, dpnTepInfo, true, interfaceName, interfaceName,
553 Interface.OperStatus.Up);