Fix several issues with disconecting device 98/50198/18
authorJozef Bacigal <jozef.bacigal@pantheon.tech>
Tue, 10 Jan 2017 15:04:05 +0000 (16:04 +0100)
committerJozef Bacigal <jozef.bacigal@pantheon.tech>
Tue, 4 Apr 2017 07:56:15 +0000 (09:56 +0200)
Change-Id: I29a0b08643fce88599a1d3e76d0f382369127780
Signed-off-by: Jozef Bacigal <jozef.bacigal@pantheon.tech>
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProvider.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChain.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainHolder.java
openflowplugin-api/src/main/yang/openflow-provider-config.yang
openflowplugin-blueprint-config/src/main/resources/initial/openflowplugin.cfg
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderFactoryImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainImpl.java

index ae8be1e9839916599bbff10612d4d5f50787921a..918e0d95844f42604bd52cf9189cebc3c06690e9 100644 (file)
@@ -86,4 +86,7 @@ public interface OpenFlowPluginProvider extends AutoCloseable, BindingService {
 
     void setIsUseSingleLayerSerialization(Boolean useSingleLayerSerialization);
 
+    void updateTtlBeforeDropInContextChainHolder(Long ttlBeforeDrop);
+
+    void updateTtlStepInContextChainHolder(Long ttlStep);
 }
index 43043a58a8a4355f910e874af926db025972f2d3..01862a9b1789f647f19913a1133b119781caa1c0 100644 (file)
@@ -88,4 +88,9 @@ public interface ContextChain extends AutoCloseable {
      * @return device context
      */
     DeviceContext provideDeviceContext();
+
+    /**
+     * Just make the chain state SLEEP
+     */
+    void sleepTheChain();
 }
index 74d85f8a5cbaf68ddbf59110df8ab3b6c4c41357..3aedd34e8a9f385cc4a925936a362f16761b38c9 100644 (file)
@@ -62,4 +62,8 @@ public interface ContextChainHolder extends
      * @param singletonServicesProvider provider
      */
     void addSingletonServicesProvider(final ClusterSingletonServiceProvider singletonServicesProvider);
+
+    void setTtlBeforeDrop(Long ttlBeforeDrop);
+
+    void setTtlStep(Long ttlStep);
 }
index c76765fb0552b244c09b0755ad2760a43ba066ca..2db54f1152dbb727ec4583330b4d9d768eca6e00 100644 (file)
@@ -135,32 +135,28 @@ module openflow-provider-config {
             type boolean;
             default "true";
         }
-        container context-chain-config {
-
-            leaf ttl-before-drop {
-                description "TTL in miliseconds without connection before the context chain shall be dropped";
-                type uint32;
-                default 5000;
-            }
-
-            leaf never-drop-contexts-on {
-                description "if true then context chain will not be droped, otherwise use ttl-before-drop";
-                type boolean;
-                default true;
-            }
+        leaf ttl-before-drop {
+            description "TTL in milliseconds without connection before the context chain shall be dropped";
+            type uint32;
+            default 10000;
+        }
 
-            leaf context-chain-startup-state {
-                description "this will set the default state of context chain after creation";
-                type context-chain-state;
-                default WORKING_SLAVE;
-            }
+        leaf ttl-step {
+            description "TTL step in milliseconds";
+            type uint32;
+            default 1000;
+        }
 
-            leaf number-of-needed-managers {
-                description "chceck number for needed managers";
-                type uint16;
-                default 3;
-            }
+        leaf never-drop-contexts-on {
+            description "if true then context chain will not be dropped, otherwise use ttl-before-drop";
+            type boolean;
+            default false;
+        }
 
+        leaf context-chain-startup-state {
+            description "this will set the default state of context chain after creation";
+            type context-chain-state;
+            default WORKING_SLAVE;
         }
 
     }
index c7056a596db580d628f8665c9f229588eedbd03d..1a66b9794c1b80a58d96ef1e9209600aa4181612 100644 (file)
@@ -34,3 +34,9 @@ basic-timer-delay=3000
 #used in polling the statistics, value is in milliseconds
 maximum-timer-delay=900000
 use-single-layer-serialization=true
+#TTL in milliseconds without connection before the context chain shall be dropped
+ttl-before-drop=10000
+#TTL step in milliseconds
+ttl-step=1000
+#if true then context chain will not be dropped, otherwise use ttl-before-drop
+never-drop-contexts-on=false
index c68bfe0bd54085551f6ce2dfd73c3f5e3867fab5..f1a28a5c0301eaacc2f0f10b6df4414114425336 100644 (file)
@@ -65,6 +65,8 @@ public class OpenFlowPluginProviderFactoryImpl implements OpenFlowPluginProvider
         openflowPluginProvider.setBasicTimerDelay(providerConfig.getBasicTimerDelay().getValue());
         openflowPluginProvider.setMaximumTimerDelay(providerConfig.getMaximumTimerDelay().getValue());
         openflowPluginProvider.setIsUseSingleLayerSerialization(providerConfig.isUseSingleLayerSerialization());
+        openflowPluginProvider.updateTtlBeforeDropInContextChainHolder(providerConfig.getTtlBeforeDrop());
+        openflowPluginProvider.updateTtlStepInContextChainHolder(providerConfig.getTtlStep());
 
         openflowPluginProvider.initialize();
 
@@ -79,7 +81,11 @@ public class OpenFlowPluginProviderFactoryImpl implements OpenFlowPluginProvider
                 "ThreadPoolTimeout:{}, " +
                 "NotificationFlowRemovedOff:{}, " +
                 "BasicTimerDelay:{}, "+
-                "MaximumTimerDelay:{} ",
+                "MaximumTimerDelay:{} " +
+                "NotificationFlowRemovedOff:{}" +
+                "TTL before drop:{}" +
+                "Never drop connection:{}" +
+                "TTL step:{}",
                 providerConfig.isIsStatisticsPollingOn(),
                 providerConfig.isSwitchFeaturesMandatory(),
                 providerConfig.getBarrierCountLimit().getValue(),
@@ -90,7 +96,10 @@ public class OpenFlowPluginProviderFactoryImpl implements OpenFlowPluginProvider
                 providerConfig.getThreadPoolTimeout(),
                 providerConfig.isEnableFlowRemovedNotification(),
                 providerConfig.getBasicTimerDelay().getValue(),
-                providerConfig.getMaximumTimerDelay().getValue());
+                providerConfig.getMaximumTimerDelay().getValue(),
+                providerConfig.getTtlBeforeDrop(),
+                providerConfig.isNeverDropContextsOn(),
+                providerConfig.getTtlStep());
 
         return openflowPluginProvider;
     }
index b9dcedf675db8c829c9a41529e65d19947f85960..c3f476154a1bf72f8186c726d5da00797457d848 100644 (file)
@@ -61,7 +61,6 @@ import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConve
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.openflow.provider.config.ContextChainConfigBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import io.netty.util.HashedWheelTimer;
@@ -129,7 +128,7 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
                 new SynchronousQueue<>(), POOL_NAME);
         deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();          
         convertorManager = ConvertorManagerFactory.createDefaultManager();
-        contextChainHolder = new ContextChainHolderImpl(new ContextChainConfigBuilder().build(), hashedWheelTimer);
+        contextChainHolder = new ContextChainHolderImpl(hashedWheelTimer);
     }
 
     @Override
@@ -365,6 +364,14 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
         if(statisticsManager != null && props.containsKey("maximum-timer-delay")){
             statisticsManager.setMaximumTimerDelay(Long.valueOf(props.get("maximum-timer-delay").toString()));
         }
+        if (props.containsKey("ttl-before-drop")) {
+            contextChainHolder.setTtlBeforeDrop(Long.valueOf(props.get("ttl-before-drop").toString()));
+        }
+
+        if (props.containsKey("ttl-step")) {
+            contextChainHolder.setTtlStep(Long.valueOf(props.get("ttl-step").toString()));
+        }
+
     }
 
     private static void registerMXBean(final MessageIntelligenceAgency messageIntelligenceAgency) {
@@ -418,4 +425,15 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
     public void setIsUseSingleLayerSerialization(Boolean useSingleLayerSerialization) {
         this.useSingleLayerSerialization = useSingleLayerSerialization;
     }
-}
+
+    @Override
+    public void updateTtlBeforeDropInContextChainHolder(final Long ttlBeforeDrop) {
+        this.contextChainHolder.setTtlBeforeDrop(ttlBeforeDrop);
+    }
+
+    @Override
+    public void updateTtlStepInContextChainHolder(final Long ttlStep) {
+        this.contextChainHolder.setTtlStep(ttlStep);
+    }
+
+}
\ No newline at end of file
index fb6059638f007feef6c83cef79c644e83c9c3bcc..0db24e7598fa7babea89b9de88c14c98077e8f6e 100644 (file)
@@ -12,7 +12,6 @@ import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timeout;
-import io.netty.util.Timer;
 import io.netty.util.TimerTask;
 import java.util.Map;
 import java.util.Objects;
@@ -37,7 +36,6 @@ import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.ContextChainState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.openflow.provider.config.ContextChainConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,6 +47,8 @@ public class ContextChainHolderImpl implements ContextChainHolder {
     private static final String CONTEXT_CREATED_FOR_CONNECTION = " context created for connection: {}";
     private static final String SINGLETON_SERVICE_PROVIDER_WAS_NOT_SET_YET
             = "Singleton service provider was not set yet.";
+    private static final long DEFAULT_TTL_STEP = 1000L;
+    private static final long DEFAULT_TTL_BEFORE_DROP = 5000L;
 
     private DeviceManager deviceManager;
     private RpcManager rpcManager;
@@ -56,15 +56,17 @@ public class ContextChainHolderImpl implements ContextChainHolder {
     private ConcurrentHashMap<DeviceInfo, ContextChain> contextChainMap = new ConcurrentHashMap<>();
     private ConcurrentHashMap<DeviceInfo, ContextChain> sleepingChains = new ConcurrentHashMap<>();
     private ConcurrentHashMap<DeviceInfo, Long> timeToLive = new ConcurrentHashMap<>();
-    private final ContextChainConfig config;
     private ClusterSingletonServiceProvider singletonServicesProvider;
     private boolean timerIsRunning;
     private final HashedWheelTimer timer;
+    private Long ttlBeforeDrop;
+    private Long ttlStep;
 
-    public ContextChainHolderImpl(final ContextChainConfig config, final HashedWheelTimer timer) {
-        this.config = config;
+    public ContextChainHolderImpl(final HashedWheelTimer timer) {
         this.timerIsRunning = false;
         this.timer = timer;
+        this.ttlBeforeDrop = DEFAULT_TTL_BEFORE_DROP;
+        this.ttlStep = DEFAULT_TTL_STEP;
     }
 
     @Override
@@ -138,6 +140,7 @@ public class ContextChainHolderImpl implements ContextChainHolder {
         if (Objects.nonNull(chain)) {
             chain.close();
             try {
+                LOG.info("Removing device: {} from DS", deviceInfo);
                 deviceManager.removeDeviceFromOperationalDS(deviceInfo).checkedGet(5L, TimeUnit.SECONDS);
             } catch (TimeoutException | TransactionCommitFailedException e) {
                 LOG.warn("Not able to remove device {} from DS", deviceInfo.getLOGValue());
@@ -245,14 +248,25 @@ public class ContextChainHolderImpl implements ContextChainHolder {
             } else {
                 Futures.addCallback(chain.connectionDropped(),
                         new StartStopChainCallback(chain.provideDeviceContext(), true));
+                chain.sleepTheChain();
                 addToSleepingChainsMap(connectionContext.getDeviceInfo(), chain);
             }
         }
     }
 
+    @Override
+    public void setTtlBeforeDrop(final Long ttlBeforeDrop) {
+        this.ttlBeforeDrop = ttlBeforeDrop;
+    }
+
+    @Override
+    public void setTtlStep(final Long ttlStep) {
+        this.ttlStep = ttlStep;
+    }
+
     private void addToSleepingChainsMap(@Nonnull final DeviceInfo deviceInfo, final ContextChain contextChain) {
-        sleepingChains.putIfAbsent(deviceInfo, contextChain);
-        timeToLive.putIfAbsent(deviceInfo, config.getTtlBeforeDrop());
+        sleepingChains.put(deviceInfo, contextChain);
+        timeToLive.put(deviceInfo, this.ttlBeforeDrop);
         if (LOG.isDebugEnabled()) {
             LOG.debug("Put context chain on mattress to sleep for device {}", deviceInfo.getLOGValue());
         }
@@ -274,7 +288,7 @@ public class ContextChainHolderImpl implements ContextChainHolder {
         if (LOG.isDebugEnabled()) {
             LOG.debug("There is at least one context chains sleeping, starting timer.");
         }
-        timer.newTimeout(new SleepingChainsTimerTask(), 1000, TimeUnit.MILLISECONDS);
+        timer.newTimeout(new SleepingChainsTimerTask(), this.ttlStep, TimeUnit.MILLISECONDS);
     }
 
     private void stopTimer() {
@@ -292,8 +306,13 @@ public class ContextChainHolderImpl implements ContextChainHolder {
                 LOG.debug("Context chain holder timer tick. There are {} context chains sleeping.",
                         sleepingChains.size());
             }
+            if (timeToLive.isEmpty()) {
+                LOG.warn("TTL map is empty but not sleeping chains map. Providing clean up.");
+                sleepingChains.clear();
+            }
             for (Map.Entry<DeviceInfo, Long> deviceInfoLongEntry : timeToLive.entrySet()) {
-                Long newValue = deviceInfoLongEntry.getValue() - 1000;
+                Long newValue = deviceInfoLongEntry.getValue() - this.ttlStep;
+                deviceInfoLongEntry.setValue(newValue);
                 DeviceInfo deviceInfo = deviceInfoLongEntry.getKey();
                 ContextChain chain = sleepingChains.get(deviceInfo);
                 if (Objects.isNull(chain)) {
@@ -303,18 +322,25 @@ public class ContextChainHolderImpl implements ContextChainHolder {
                     timeToLive.remove(deviceInfo);
                     continue;
                 }
-                if ((newValue <= 0) && (chain.getContextChainState().equals(ContextChainState.SLEEPING))) {
+                if (!ContextChainState.SLEEPING.equals(chain.getContextChainState())) {
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("There is timer registered for device: {} " +
+                                        "but device is in state: {} Removing from timer.",
+                                deviceInfo.getLOGValue(),
+                                chain.getContextChainState().getName());
+                    }
+                    timeToLive.remove(deviceInfo);
+                }
+                if (newValue <= 0) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Dear device: {} your time to wake up is up. Its time to destroy you.",
                                 deviceInfo.getLOGValue());
                     }
                     destroyContextChain(deviceInfo);
-                    continue;
                 }
-                deviceInfoLongEntry.setValue(newValue);
             }
             if (!timeToLive.isEmpty()) {
-                timer.newTimeout(new SleepingChainsTimerTask(), 1000, TimeUnit.MILLISECONDS);
+                timer.newTimeout(new SleepingChainsTimerTask(), this.ttlStep, TimeUnit.MILLISECONDS);
             }
         }
     }
@@ -357,3 +383,4 @@ public class ContextChainHolderImpl implements ContextChainHolder {
     }
 
 }
+
index 82303f0bed5b5556432c751b06c2afc1419e581c..2658663c595d56473c6e58159a4e1608a9599b0e 100644 (file)
@@ -160,4 +160,9 @@ public class ContextChainImpl implements ContextChain {
     public DeviceContext provideDeviceContext() {
         return this.deviceContext;
     }
+
+    @Override
+    public void sleepTheChain() {
+        this.contextChainState = ContextChainState.SLEEPING;
+    }
 }