openflowPluginProvider.setBasicTimerDelay(providerConfig.getBasicTimerDelay().getValue());
openflowPluginProvider.setMaximumTimerDelay(providerConfig.getMaximumTimerDelay().getValue());
openflowPluginProvider.setIsUseSingleLayerSerialization(providerConfig.isUseSingleLayerSerialization());
+ openflowPluginProvider.updateTtlBeforeDropInContextChainHolder(providerConfig.getTtlBeforeDrop());
+ openflowPluginProvider.updateTtlStepInContextChainHolder(providerConfig.getTtlStep());
openflowPluginProvider.initialize();
"ThreadPoolTimeout:{}, " +
"NotificationFlowRemovedOff:{}, " +
"BasicTimerDelay:{}, "+
- "MaximumTimerDelay:{} ",
+ "MaximumTimerDelay:{} " +
+ "NotificationFlowRemovedOff:{}" +
+ "TTL before drop:{}" +
+ "Never drop connection:{}" +
+ "TTL step:{}",
providerConfig.isIsStatisticsPollingOn(),
providerConfig.isSwitchFeaturesMandatory(),
providerConfig.getBarrierCountLimit().getValue(),
providerConfig.getThreadPoolTimeout(),
providerConfig.isEnableFlowRemovedNotification(),
providerConfig.getBasicTimerDelay().getValue(),
- providerConfig.getMaximumTimerDelay().getValue());
+ providerConfig.getMaximumTimerDelay().getValue(),
+ providerConfig.getTtlBeforeDrop(),
+ providerConfig.isNeverDropContextsOn(),
+ providerConfig.getTtlStep());
return openflowPluginProvider;
}
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;
new SynchronousQueue<>(), POOL_NAME);
deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();
convertorManager = ConvertorManagerFactory.createDefaultManager();
- contextChainHolder = new ContextChainHolderImpl(new ContextChainConfigBuilder().build(), hashedWheelTimer);
+ contextChainHolder = new ContextChainHolderImpl(hashedWheelTimer);
}
@Override
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) {
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
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;
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;
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;
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
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());
} 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());
}
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() {
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)) {
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);
}
}
}
}
}
+