Fix: Reconnect updates the tunnel state 05/88205/5
authorApurba Mukherjee <apurba.mukherjee@ericsson.com>
Mon, 23 Sep 2019 06:10:07 +0000 (11:40 +0530)
committerHema Gopalakrishnan <hema.gopalkrishnan@ericsson.com>
Mon, 3 Aug 2020 17:01:48 +0000 (17:01 +0000)
Check if tunnels State has an entry for this interface.
If so, then this Inventory Add is due to the compute re-connection. Then, ONLY update the state
to UP as previously the compute would have disconnected and so the state will be UNKNOWN.

Change-Id: I957c0e5892763bcae43dbd481ad0620b1d193f0f
Signed-off-by: Apurba Mukherjee <apurba.mukherjee@ericsson.com>
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java

index fb0bcdb8a9b0e073e80deab724ec9b929004341b..a701c23705c79d65abaf564cb02134e31d85c5f8 100644 (file)
@@ -159,6 +159,7 @@ public class TunnelInventoryStateListener extends
             LOG.debug("Node Connector Update {} Interface is not a internal tunnel I/f, so no-op", portName);
             return;
         }
+
         if (fcNodeConnectorNew.getReason() == PortReason.Delete || !directTunnelUtils.isEntityOwner()) {
             return;
         }
@@ -177,12 +178,18 @@ public class TunnelInventoryStateListener extends
         LOG.info("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
         EVENT_LOGGER.debug("ITM-TunnelInventoryState,ADD DTCN received for {}", fcNodeConnectorNew.getName());
         String portName = fcNodeConnectorNew.getName();
+
         // Return if its not tunnel port and if its not Internal
         if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && !portName.startsWith("of")) {
             LOG.debug("Node Connector Add {} Interface is not a tunnel I/f, so no-op", portName);
             return;
         }
 
+        if (!directTunnelUtils.isEntityOwner()) {
+            LOG.debug("Not an entity owner.");
+            return;
+        }
+
         NodeConnectorInfo nodeConnectorInfo =
                 new NodeConnectorInfoBuilder().setNodeConnectorId(key).setNodeConnector(fcNodeConnectorNew).build();
 
@@ -220,7 +227,6 @@ public class TunnelInventoryStateListener extends
         } else {
             addTunnelState(nodeConnectorInfo, portName);
         }
-
     }
 
     private void addTunnelState(NodeConnectorInfo nodeConnectorInfo, String portName) {
@@ -241,6 +247,21 @@ public class TunnelInventoryStateListener extends
             }
         }
 
+        // Check if tunnels State has an entry for this interface.
+        // If so, then this Inventory Add is due to compute re-connection. Then, ONLY update the state
+        // to UP as previously the compute would have disconnected and so the state will be UNKNOWN.
+        try {
+            long portNo = tunnelStateCache.getNodeConnectorIdFromInterface(portName);
+            if (portNo != ITMConstants.INVALID_PORT_NO) {
+                coordinator.enqueueJob(portName,
+                        new TunnelInterfaceNodeReconnectWorker(portName), ITMConstants.JOB_MAX_RETRIES);
+                return;
+            }
+        } catch (ReadFailedException e) {
+            LOG.error("Exception occurred in reconnect for portName {}, reason: {}.",
+                     portName, e.getMessage());
+        }
+
         if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && dpnTepStateCache.isInternal(portName)) {
             tunnelEndPtInfo = dpnTepStateCache.getTunnelEndPointInfoFromCache(portName);
             TunnelStateInfoBuilder builder = new TunnelStateInfoBuilder().setNodeConnectorInfo(nodeConnectorInfo);
@@ -480,4 +501,40 @@ public class TunnelInventoryStateListener extends
                     + flowCapableNodeConnector + ", interfaceName='" + interfaceName + '\'' + '}';
         }
     }
+
+    private class TunnelInterfaceNodeReconnectWorker implements Callable<List<? extends ListenableFuture<?>>> {
+        private final String tunnelName;
+
+        TunnelInterfaceNodeReconnectWorker(String tunnelName) {
+            this.tunnelName = tunnelName;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            // If another renderer(for eg : OVS) needs to be supported, check can be performed here
+            // to call the respective helpers.
+            EVENT_LOGGER.debug("ITM-TunnelInventoryState, Compute Re-connected, ADD received for {} ", tunnelName);
+
+            return handleInterfaceStateOnReconnect(tunnelName);
+        }
+
+        @Override
+        public String toString() {
+            return "TunnelInterfaceNodeReconnectWorker{tunnelName=" + tunnelName + '\'' + '}';
+        }
+    }
+
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
+    private List<ListenableFuture<Void>> handleInterfaceStateOnReconnect(String interfaceName) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+        futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
+            DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
+
+            handleInterfaceStateUpdates(tx, dpnTepInfo, true, interfaceName, interfaceName,
+                    Interface.OperStatus.Up);
+        }));
+        return futures;
+    }
 }