Processing Hwvtep/Ovsdb client only once 86/88586/3
authorChandra Shekar S <chandra.shekar.s@ericsson.com>
Mon, 23 Mar 2020 10:11:17 +0000 (15:41 +0530)
committerChandra Shekar S <chandra.shekar.s@ericsson.com>
Sun, 29 Mar 2020 11:29:08 +0000 (16:59 +0530)
There are chances of same client is getting processed multiple times
and resulting in stale eos entry in one controller.

Due to this stale eos entry in controller1 if the device is getting
connected to controller2 it could not be processed as controller1 still
remains as eos leader for this device.

Ideally controller1 should have released its ownership when the device is
disconnected.

Signed-off-by: Chandra Shekar S <chandra.shekar.s@ericsson.com>
Change-Id: I3b8705d7c18358a1f5be78e5ec3b50055464c23f

hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundConstants.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundProvider.java
library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManagerTest.java

index 864dcaf209bc07000b6051cf5a5570751eeb4723..d8fa25eb46dfc4884a0ae67db043d96fe149c258 100644 (file)
@@ -90,6 +90,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
     private final Map<InstanceIdentifier<Node>, TransactionHistory> controllerTxHistory = new ConcurrentHashMap<>();
     private final Map<InstanceIdentifier<Node>, TransactionHistory> deviceUpdateHistory = new ConcurrentHashMap<>();
     private final OvsdbConnection ovsdbConnectionService;
+    private final Map<OvsdbClient, OvsdbClient> alreadyProcessedClients = new ConcurrentHashMap<>();
 
     public HwvtepConnectionManager(final DataBroker db, final TransactionInvoker txInvoker,
                     final EntityOwnershipService entityOwnershipService, final OvsdbConnection ovsdbConnectionService) {
@@ -116,6 +117,16 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
 
     @Override
     public void connected(final OvsdbClient externalClient) {
+        if (alreadyProcessedClients.containsKey(externalClient)) {
+            LOG.info("Hwvtep Library already connected {} from {}:{} to {}:{} to this, hence skipping the processing",
+                    externalClient.getConnectionInfo().getType(),
+                    externalClient.getConnectionInfo().getRemoteAddress(),
+                    externalClient.getConnectionInfo().getRemotePort(),
+                    externalClient.getConnectionInfo().getLocalAddress(),
+                    externalClient.getConnectionInfo().getLocalPort());
+            return;
+        }
+        alreadyProcessedClients.put(externalClient, externalClient);
         HwvtepConnectionInstance hwClient = null;
         try {
             List<String> databases = externalClient.getDatabases().get(DB_FETCH_TIMEOUT, TimeUnit.MILLISECONDS);
@@ -143,6 +154,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
     @Override
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void disconnected(final OvsdbClient client) {
+        alreadyProcessedClients.remove(client);
         HwvtepConnectionInstance hwvtepConnectionInstance = null;
         try {
             LOG.info("Library disconnected {} from {}:{} to {}:{}. Cleaning up the operational data store",
index 328945cf29bdce0c2940c8f4c03c0c1da4a9bc38..1bf1c0c756b1de1afb4c0d5bd51d88b642a13386 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 public interface HwvtepSouthboundConstants {
     TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri("hwvtep:1"));
     Integer DEFAULT_OVSDB_PORT = 6640;
+    long PORT_OPEN_MAX_DELAY_IN_MINS = 5;
     String IID_OTHER_CONFIG_KEY = "opendaylight-iid";
     String UUID = "uuid";
     ImmutableBiMap<Class<? extends EncapsulationTypeBase>,String> ENCAPS_TYPE_MAP
index 3330c8e997949c6bb27e73958a5bedfe626a1eb8..15446d83f9e77fafa48d81e10d3a0b5def605f76 100644 (file)
@@ -140,6 +140,12 @@ public class HwvtepSouthboundProvider implements ClusteredDataTreeChangeListener
 
         LOG.trace("Registering listener for path {}", treeId);
         operTopologyRegistration = dataBroker.registerDataTreeChangeListener(treeId, this);
+        Scheduler.getScheduledExecutorService().schedule(() -> {
+            if (!registered.get()) {
+                openOvsdbPort();
+                LOG.error("Timed out to get eos notification opening the port now");
+            }
+        }, HwvtepSouthboundConstants.PORT_OPEN_MAX_DELAY_IN_MINS, TimeUnit.MINUTES);
     }
 
     private void registerConfigListenerPostUpgrade() {
@@ -223,11 +229,7 @@ public class HwvtepSouthboundProvider implements ClusteredDataTreeChangeListener
 
     @Override
     public void onDataTreeChanged(final Collection<DataTreeModification<Topology>> collection) {
-        if (!registered.getAndSet(true)) {
-            LOG.info("Starting the ovsdb port");
-            ovsdbConnection.registerConnectionListener(cm);
-            ovsdbConnection.startOvsdbManager();
-        }
+        openOvsdbPort();
 
         if (operTopologyRegistration != null) {
             operTopologyRegistration.close();
@@ -235,6 +237,14 @@ public class HwvtepSouthboundProvider implements ClusteredDataTreeChangeListener
         }
     }
 
+    private void openOvsdbPort() {
+        if (!registered.getAndSet(true)) {
+            LOG.info("Starting the ovsdb port");
+            ovsdbConnection.registerConnectionListener(cm);
+            ovsdbConnection.startOvsdbManager();
+        }
+    }
+
     public void setShardStatusCheckRetryCount(int retryCount) {
         this.shardStatusCheckRetryCount = retryCount;
     }
index 675dee291a7112f5ccefdeb3e3bf91aa80ccffc6..cd76a00fb0e18695a75ba0d2a5435afa7e90bfe3 100644 (file)
@@ -284,8 +284,12 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
     @Override
     public void registerConnectionListener(final OvsdbConnectionListener listener) {
         LOG.info("registerConnectionListener: registering {}", listener.getClass().getSimpleName());
-        CONNECTION_LISTENERS.add(listener);
-        notifyAlreadyExistingConnectionsToListener(listener);
+        if (CONNECTION_LISTENERS.add(listener)) {
+            LOG.info("registerConnectionListener: registered {} notifying exisitng connections",
+                    listener.getClass().getSimpleName());
+            //notify only the first time if called multiple times
+            notifyAlreadyExistingConnectionsToListener(listener);
+        }
     }
 
     private void notifyAlreadyExistingConnectionsToListener(final OvsdbConnectionListener listener) {
index 296216ec9cc3a858303f8843597a6e1b98fd8054..b020a8bf3dd581b813f13dcb041fdb19e030b8db 100644 (file)
@@ -76,6 +76,7 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
 
     private final DataBroker db;
     private final TransactionInvoker txInvoker;
+    private final Map<OvsdbClient, OvsdbClient> alreadyProcessedClients = new ConcurrentHashMap<>();
     private final Map<ConnectionInfo,InstanceIdentifier<Node>> instanceIdentifiers =
             new ConcurrentHashMap<>();
     private final Map<InstanceIdentifier<Node>, OvsdbConnectionInstance> nodeIdVsConnectionInstance =
@@ -106,6 +107,18 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
 
     @Override
     public void connected(final OvsdbClient externalClient) {
+        if (alreadyProcessedClients.containsKey(externalClient)) {
+            LOG.info("OvsdbConnectionManager Library already connected {} from {}:{} to {}:{} "
+                            + "to this, hence skipping the processing",
+                    externalClient.getConnectionInfo().getType(),
+                    externalClient.getConnectionInfo().getRemoteAddress(),
+                    externalClient.getConnectionInfo().getRemotePort(),
+                    externalClient.getConnectionInfo().getLocalAddress(),
+                    externalClient.getConnectionInfo().getLocalPort());
+            return;
+        }
+        alreadyProcessedClients.put(externalClient, externalClient);
+
         LOG.info("Library connected {} from {}:{} to {}:{}",
                 externalClient.getConnectionInfo().getType(),
                 externalClient.getConnectionInfo().getRemoteAddress(),
@@ -161,6 +174,7 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
 
     @Override
     public void disconnected(final OvsdbClient client) {
+        alreadyProcessedClients.remove(client);
         LOG.info("Library disconnected {} from {}:{} to {}:{}. Cleaning up the operational data store",
                 client.getConnectionInfo().getType(),
                 client.getConnectionInfo().getRemoteAddress(),
index 53754cce5be3b458092cf9955314f9dc6be873ee..2b6b9d421933c8a8179f5d7db2d610f74a10f256 100644 (file)
@@ -88,6 +88,7 @@ public class OvsdbConnectionManagerTest {
         field(OvsdbConnectionManager.class, "entityOwnershipService").set(ovsdbConnManager, entityOwnershipService);
         field(OvsdbConnectionManager.class, "reconciliationManager").set(ovsdbConnManager, reconciliationManager);
         field(OvsdbConnectionManager.class, "ovsdbConnection").set(ovsdbConnManager, ovsdbConnection);
+        field(OvsdbConnectionManager.class, "alreadyProcessedClients").set(ovsdbConnManager, new HashMap());
         entityConnectionMap = new ConcurrentHashMap<>();
 
         OvsdbConnectionInfo info = mock(OvsdbConnectionInfo.class);