Merge "Bug 7846: ensure switch reconnection succeed in case of connection errors...
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / device / DeviceManagerImpl.java
index c7ec6d66b907562deb7c1f185fcf273e9c3cb66f..0f3d5f3ef1d866fa449e0f43df9d0ab5bdf70758 100644 (file)
@@ -17,6 +17,7 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.TimerTask;
+import java.math.BigInteger;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Objects;
@@ -169,14 +170,24 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
          * in {@link org.opendaylight.openflowplugin.impl.connection.org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl}
          * If context already exist we are in state closing process (connection flapping) and we should not propagate connection close
          */
-         if (deviceContexts.containsKey(deviceInfo)) {
-             DeviceContext deviceContext = deviceContexts.get(deviceInfo);
-             LOG.warn("Node {} already connected disconnecting device. Rejecting connection", deviceInfo.getLOGValue());
-             if (!deviceContext.getState().equals(OFPContext.CONTEXT_STATE.TERMINATION)) {
+         DeviceContext current = deviceContexts.get(deviceInfo);
+         if (current != null) {
+             LOG.warn("New connection received from the already connected Node {}. Disconnecting both the connection " +
+                      "to add the switch back gracefully.", deviceInfo.getLOGValue());
+             if (!current.getState().equals(OFPContext.CONTEXT_STATE.TERMINATION)) {
                  LOG.warn("Node {} context state not in TERMINATION state.",
                          connectionContext.getDeviceInfo().getLOGValue());
+                 //Lets disconnect the existing connection as well and ask switch to connect fresh.
+                 //This will re-add the node properly
+                 current.getPrimaryConnectionContext().closeConnection(true);
                  return ConnectionStatus.ALREADY_CONNECTED;
              } else {
+                 // Device context already exist with a terminated connection. Reject the connection to receive fresh
+                 // connection and properly add the device.
+                 LOG.debug("Old connection from {} is terminated but still exist in device context." +
+                         "Rejecting new connection and cleaning up the old connection.", deviceInfo.getLOGValue());
+                 deviceContexts.remove(deviceInfo);
+                 current.getPrimaryConnectionContext().closeConnection(true);
                  return ConnectionStatus.CLOSING;
              }
          }
@@ -308,7 +319,12 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
             return;
         }
 
-        if (!connectionContext.equals(deviceCtx.getPrimaryConnectionContext())) {
+        if (connectionContext.getFeatures() != null
+                && connectionContext.getFeatures().getAuxiliaryId() != null
+                && connectionContext.getFeatures().getAuxiliaryId() > 0
+                && deviceCtx.getAuxiliaryConnectionContexts(new BigInteger(String.valueOf(
+                connectionContext.getFeatures().getAuxiliaryId().intValue()))) != null) {
+
             LOG.debug("Node {} disconnected, but not primary connection.", connectionContext.getDeviceInfo().getLOGValue());
             // Connection is not PrimaryConnection so try to remove from Auxiliary Connections
             deviceCtx.removeAuxiliaryConnectionContext(connectionContext);