<packaging>bundle</packaging>
<dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
<groupId>org.opendaylight.mdsal</groupId>
<artifactId>mdsal-singleton-common-api</artifactId>
</dependency>
-
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</plugins>
</build>
-
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</connection>
<developerConnection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</developerConnection>
package org.opendaylight.openflowplugin.applications.frm;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationListener;
import org.opendaylight.openflowplugin.applications.frm.impl.FlowNodeConnectorInventoryTranslatorImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
*
* @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
*/
-public interface ForwardingRulesManager extends AutoCloseable {
+public interface ForwardingRulesManager extends ConfigurationListener, AutoCloseable {
void start();
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.applications.frm;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+public enum ForwardingRulesProperty {
+ DISABLE_RECONCILIATION,
+ STALE_MARKING_ENABLED,
+ RECONCILIATION_RETRY_COUNT;
+
+
+ private static final Map<String, ForwardingRulesProperty> KEY_VALUE_MAP;
+
+ /**
+ * Get property type from property key
+ *
+ * @param key the property key
+ * @return the property type
+ */
+ public static ForwardingRulesProperty forValue(final String key) {
+ return KEY_VALUE_MAP.get(key);
+ }
+
+ static {
+ final ForwardingRulesProperty[] values = values();
+ final ImmutableMap.Builder<String, ForwardingRulesProperty> builder = ImmutableMap.builder();
+
+ for (final ForwardingRulesProperty value : values) {
+ builder.put(value.toString(), value);
+ }
+
+ KEY_VALUE_MAP = builder.build();
+ }
+
+ /**
+ * Converts enum name to property key
+ *
+ * @return the property key
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase().replace('_', '-');
+ }
+}
package org.opendaylight.openflowplugin.applications.frm.impl;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
import java.util.Objects;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.openflowplugin.applications.frm.FlowNodeReconciliation;
import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesCommiter;
import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
+import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesProperty;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
private final SalGroupService salGroupService;
private final SalMeterService salMeterService;
private final SalTableService salTableService;
- private final ForwardingRulesManagerConfig forwardingRulesManagerConfig;
private final ClusterSingletonServiceProvider clusterSingletonServiceProvider;
private final NotificationProviderService notificationService;
- private final boolean disableReconciliation;
- private final boolean staleMarkingEnabled;
- private final int reconciliationRetryCount;
-
+ private final AutoCloseable configurationServiceRegistration;
private ForwardingRulesCommiter<Flow> flowListener;
private ForwardingRulesCommiter<Group> groupListener;
private ForwardingRulesCommiter<Meter> meterListener;
private FlowNodeReconciliation nodeListener;
private FlowNodeConnectorInventoryTranslatorImpl flowNodeConnectorInventoryTranslatorImpl;
private DeviceMastershipManager deviceMastershipManager;
+ private boolean disableReconciliation;
+ private boolean staleMarkingEnabled;
+ private int reconciliationRetryCount;
public ForwardingRulesManagerImpl(final DataBroker dataBroker,
final RpcConsumerRegistry rpcRegistry,
final ForwardingRulesManagerConfig config,
final ClusterSingletonServiceProvider clusterSingletonService,
final NotificationProviderService notificationService,
- final boolean disableReconciliation,
- final boolean staleMarkingEnabled,
- final int reconciliationRetryCount) {
+ final ConfigurationService configurationService) {
+ disableReconciliation = config.isDisableReconciliation();
+ staleMarkingEnabled = config.isStaleMarkingEnabled();
+ reconciliationRetryCount = config.getReconciliationRetryCount();
+
+ this.configurationServiceRegistration = configurationService.registerListener(this);
this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
- this.forwardingRulesManagerConfig = Preconditions.checkNotNull(config, "Configuration for FRM cannot be null");
this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonService,
"ClusterSingletonService provider can not be null");
- this.notificationService = Preconditions.checkNotNull(notificationService, "Notification publisher service is" +
+ this.notificationService = Preconditions.checkNotNull(notificationService, "Notification publisher configurationService is" +
" not available");
Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
"RPC SalMeterService not found.");
this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class),
"RPC SalTableService not found.");
-
- this.disableReconciliation = disableReconciliation;
- this.staleMarkingEnabled = staleMarkingEnabled;
- this.reconciliationRetryCount = reconciliationRetryCount;
}
@Override
@Override
public void close() throws Exception {
+ configurationServiceRegistration.close();
+
if (this.flowListener != null) {
this.flowListener.close();
this.flowListener = null;
boolean result = false;
InstanceIdentifier<Node> nodeIid = ident.firstIdentifierOf(Node.class);
final ReadOnlyTransaction transaction = dataService.newReadOnlyTransaction();
- Optional<Node> optionalDataObject;
- CheckedFuture<Optional<Node>, ReadFailedException> future = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid);
+ CheckedFuture<com.google.common.base.Optional<Node>, ReadFailedException> future = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid);
try {
- optionalDataObject = future.checkedGet();
+ com.google.common.base.Optional<Node> optionalDataObject = future.checkedGet();
if (optionalDataObject.isPresent()) {
result = true;
} else {
@Override
public boolean isReconciliationDisabled() {
- return this.disableReconciliation;
+ return disableReconciliation;
}
@Override
public boolean isStaleMarkingEnabled() {
- return this.staleMarkingEnabled;
+ return staleMarkingEnabled;
}
@Override
public int getReconciliationRetryCount() {
- return this.reconciliationRetryCount;
+ return reconciliationRetryCount;
}
@Override
public void setDeviceMastershipManager(final DeviceMastershipManager deviceMastershipManager) {
this.deviceMastershipManager = deviceMastershipManager;
}
-}
+ @Override
+ public void onPropertyChanged(@Nonnull final String propertyName, @Nonnull final String propertyValue) {
+ Optional.ofNullable(ForwardingRulesProperty.forValue(propertyName)).ifPresent(forwardingRulesProperty -> {
+ switch (forwardingRulesProperty) {
+ case DISABLE_RECONCILIATION:
+ disableReconciliation = Boolean.valueOf(propertyValue);
+ break;
+ case STALE_MARKING_ENABLED:
+ staleMarkingEnabled = Boolean.valueOf(propertyValue);
+ break;
+ case RECONCILIATION_RETRY_COUNT:
+ reconciliationRetryCount = Integer.valueOf(propertyValue);
+ break;
+ }
+ });
+ }
+}
<reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
<reference id="notificationService" interface="org.opendaylight.controller.sal.binding.api.NotificationProviderService"/>
<reference id="clusterSingletonService" interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
+ <reference id="configurationService" interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService"/>
<odl:clustered-app-config id="frmConfig"
binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig"/>
- <cm:property-placeholder persistent-id="org.opendaylight.openflowplugin"
- placeholder-prefix="${frm-"
- update-strategy="none">
- <cm:default-properties>
- <!-- Disable switch reconciliation -->
- <cm:property name="disable-reconciliation" value="false"/>
- <!-- Enable stale marking for switch reconciliation -->
- <cm:property name="stale-marking-enabled" value="false"/>
- <!-- Number of retries for switch reconciliation -->
- <cm:property name="reconciliation-retry-count" value="5"/>
- </cm:default-properties>
- </cm:property-placeholder>
-
<bean id="frmManager" class="org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerImpl"
init-method="start" destroy-method="close">
<argument ref="dataBroker"/>
<argument ref="frmConfig"/>
<argument ref="clusterSingletonService"/>
<argument ref="notificationService"/>
- <argument value="${frm-disable-reconciliation}"/>
- <argument value="${frm-stale-marking-enabled}"/>
- <argument value="${frm-reconciliation-retry-count}"/>
-
+ <argument ref="configurationService"/>
</bean>
-</blueprint>
\ No newline at end of file
+</blueprint>
}
container forwarding-rules-manager-config {
+ leaf disable-reconciliation {
+ type boolean;
+ default false;
+ }
+
leaf stale-marking-enabled {
type boolean;
default false;
default 5;
}
}
-}
\ No newline at end of file
+}
rpcProviderRegistryMock,
getConfig(),
clusterSingletonService,
- notificationService, false, false, 5);
+ notificationService,
+ getConfigurationService());
+
forwardingRulesManager.start();
// TODO consider tests rewrite (added because of complicated access)
forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager);
rpcProviderRegistryMock,
getConfig(),
clusterSingletonService,
- notificationService, false, false, 5);
+ notificationService,
+ getConfigurationService());
+
forwardingRulesManager.start();
// TODO consider tests rewrite (added because of complicated access)
forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager);
rpcProviderRegistryMock,
getConfig(),
clusterSingletonService,
- notificationService, false, false, 5);
+ notificationService,
+ getConfigurationService());
+
forwardingRulesManager.start();
// TODO consider tests rewrite (added because of complicated access)
forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager);
rpcProviderRegistryMock,
getConfig(),
clusterSingletonService,
- notificationService, false ,false ,5);
+ notificationService,
+ getConfigurationService());
+
forwardingRulesManager.start();
}
rpcProviderRegistryMock,
getConfig(),
clusterSingletonService,
- notificationService, false, false , 5);
+ notificationService,
+ getConfigurationService());
+
forwardingRulesManager.start();
// TODO consider tests rewrite (added because of complicated access)
forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager);
import java.util.Collections;
import java.util.concurrent.ExecutionException;
+import org.mockito.Mockito;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
assertCommit(writeTx.submit());
}
- public ForwardingRulesManagerConfig getConfig(){
+ public ForwardingRulesManagerConfig getConfig() {
ForwardingRulesManagerConfigBuilder cfgBuilder = new ForwardingRulesManagerConfigBuilder();
+ cfgBuilder.setDisableReconciliation(false);
cfgBuilder.setStaleMarkingEnabled(false);
cfgBuilder.setReconciliationRetryCount(0);
return cfgBuilder.build();
+ }
+
+ public ConfigurationService getConfigurationService() {
+ final ConfigurationService configurationService = Mockito.mock(ConfigurationService.class);
+ final ForwardingRulesManagerConfig config = getConfig();
+
+ Mockito.when(configurationService.registerListener(Mockito.any())).thenReturn(() -> {});
+
+ Mockito.when(configurationService.getProperty(Mockito.eq("disable-reconciliation"), Mockito.any()))
+ .thenReturn(config.isDisableReconciliation());
+ Mockito.when(configurationService.getProperty(Mockito.eq("stale-marking-enabled"), Mockito.any()))
+ .thenReturn(config.isStaleMarkingEnabled());
+
+ Mockito.when(configurationService.getProperty(Mockito.eq("reconciliation-retry-count"), Mockito.any()))
+ .thenReturn(config.getReconciliationRetryCount());
+
+ return configurationService;
}
+
}
+++ /dev/null
-/*
- * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.api.openflow;
-
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import javax.annotation.Nonnull;
-
-/**
- * Manages OpenFlowPlugin configuration.
- */
-public interface OpenFlowPluginConfigurationService {
-
- /**
- * Enum of property keys. All keys from OpenFlowPlugin configuration file are parsed to this enum.
- * Each enum value represents one working configuration key in format
- * ENUM.name().toLowerCase().replace('_', '-'), so for example PropertyType.IS_STATISTICS_POLLING_ON
- * represents 'is-statistics-polling-on' configuration key.
- */
- enum PropertyType {
- /**
- * Is statistics polling on property type.
- */
- IS_STATISTICS_POLLING_ON,
- /**
- * Barrier count limit property type.
- */
- BARRIER_COUNT_LIMIT,
- /**
- * Barrier interval timeout limit property type.
- */
- BARRIER_INTERVAL_TIMEOUT_LIMIT,
- /**
- * Echo reply timeout property type.
- */
- ECHO_REPLY_TIMEOUT,
- /**
- * Enable flow removed notification property type.
- */
- ENABLE_FLOW_REMOVED_NOTIFICATION,
- /**
- * Skip table features property type.
- */
- SKIP_TABLE_FEATURES,
- /**
- * Basic timer delay property type.
- */
- BASIC_TIMER_DELAY,
- /**
- * Maximum timer delay property type.
- */
- MAXIMUM_TIMER_DELAY,
- /**
- * Switch features mandatory property type.
- */
- SWITCH_FEATURES_MANDATORY,
- /**
- * Is statistics rpc enabled property type.
- */
- @Deprecated
- IS_STATISTICS_RPC_ENABLED,
- /**
- * Use single layer serialization property type.
- */
- USE_SINGLE_LAYER_SERIALIZATION,
- /**
- * Rpc requests quota property type.
- */
- RPC_REQUESTS_QUOTA,
- /**
- * Global notification quota property type.
- */
- GLOBAL_NOTIFICATION_QUOTA,
- /**
- * Thread pool min threads property type.
- */
- THREAD_POOL_MIN_THREADS,
- /**
- * Thread pool max threads property type.
- */
- THREAD_POOL_MAX_THREADS,
- /**
- * Thread pool timeout property type.
- */
- THREAD_POOL_TIMEOUT;
-
- private static final Map<String, PropertyType> KEY_VALUE_MAP;
-
- /**
- * Get property type from property key.
- *
- * @param key the property key
- * @return the property type
- */
- public static PropertyType forValue(String key) {
- return KEY_VALUE_MAP.get(key);
- }
-
- static {
- final PropertyType[] values = values();
- final ImmutableMap.Builder<String, PropertyType> builder = ImmutableMap.builder();
-
- for (final PropertyType value : values) {
- builder.put(value.toString(), value);
- }
-
- KEY_VALUE_MAP = builder.build();
- }
-
- /**
- * Converts enum name to property key.
- *
- * @return the property key
- */
- @Override
- public String toString() {
- return this.name().toLowerCase().replace('_', '-');
- }
-
- }
-
- /**
- * Parses key-value pairs of properties read from OpenFlowPlugin configuration file and processes them.
- *
- * @param properties properties
- */
- void update(@Nonnull Map<String,Object> properties);
-
- /**
- * Parse and process single property key-value pair.
- *
- * @see org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService.PropertyType
- * @param key property type
- * @param value property value
- */
- void updateProperty(@Nonnull PropertyType key, @Nonnull Object value);
-
-}
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
-import org.osgi.framework.BundleContext;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
/**
* Factory for creating OpenFlowPluginProvider instances.
*/
public interface OpenFlowPluginProviderFactory {
- OpenFlowPluginProvider newInstance(OpenflowProviderConfig providerConfig,
+ OpenFlowPluginProvider newInstance(ConfigurationService configurationService,
DataBroker dataBroker,
RpcProviderRegistry rpcRegistry,
NotificationPublishService notificationPublishService,
EntityOwnershipService entityOwnershipService,
List<SwitchConnectionProvider> switchConnectionProviders,
- ClusterSingletonServiceProvider singletonServiceProvider,
- BundleContext bundleContext);
+ ClusterSingletonServiceProvider singletonServiceProvider);
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.configuration;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Listens for changes in OpenFlowPlugin configuration.
+ */
+public interface ConfigurationListener {
+
+ /**
+ * Method invoked on configuration property change.
+ *
+ * @param propertyName the property name
+ * @param propertyValue the property value
+ */
+ void onPropertyChanged(@Nonnull String propertyName, @Nonnull String propertyValue);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.configuration;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+/**
+ * Enum of property keys. All keys from OpenFlowPlugin configuration file are parsed to this enum.
+ * Each enum value represents one working configuration key in format
+ * ENUM.name().toLowerCase().replace('_', '-'), so for example ConfigurationProperty.IS_STATISTICS_POLLING_ON
+ * represents 'is-statistics-polling-on' configuration key.
+ */
+public enum ConfigurationProperty {
+ /**
+ * Is statistics polling on property type.
+ */
+ IS_STATISTICS_POLLING_ON,
+ /**
+ * Barrier count limit property type.
+ */
+ BARRIER_COUNT_LIMIT,
+ /**
+ * Barrier interval timeout limit property type.
+ */
+ BARRIER_INTERVAL_TIMEOUT_LIMIT,
+ /**
+ * Echo reply timeout property type.
+ */
+ ECHO_REPLY_TIMEOUT,
+ /**
+ * Enable flow removed notification property type.
+ */
+ ENABLE_FLOW_REMOVED_NOTIFICATION,
+ /**
+ * Skip table features property type.
+ */
+ SKIP_TABLE_FEATURES,
+ /**
+ * Basic timer delay property type.
+ */
+ BASIC_TIMER_DELAY,
+ /**
+ * Maximum timer delay property type.
+ */
+ MAXIMUM_TIMER_DELAY,
+ /**
+ * Switch features mandatory property type.
+ */
+ SWITCH_FEATURES_MANDATORY,
+ /**
+ * Is statistics rpc enabled property type.
+ */
+ @Deprecated
+ IS_STATISTICS_RPC_ENABLED,
+ /**
+ * Use single layer serialization property type.
+ */
+ USE_SINGLE_LAYER_SERIALIZATION,
+ /**
+ * Rpc requests quota property type.
+ */
+ RPC_REQUESTS_QUOTA,
+ /**
+ * Global notification quota property type.
+ */
+ GLOBAL_NOTIFICATION_QUOTA,
+ /**
+ * Thread pool min threads property type.
+ */
+ THREAD_POOL_MIN_THREADS,
+ /**
+ * Thread pool max threads property type.
+ */
+ THREAD_POOL_MAX_THREADS,
+ /**
+ * Thread pool timeout property type.
+ */
+ THREAD_POOL_TIMEOUT;
+
+ private static final Map<String, ConfigurationProperty> KEY_VALUE_MAP;
+
+ /**
+ * Get property type from property key
+ *
+ * @param key the property key
+ * @return the property type
+ */
+ public static ConfigurationProperty forValue(final String key) {
+ return KEY_VALUE_MAP.get(key);
+ }
+
+ static {
+ final ConfigurationProperty[] values = values();
+ final ImmutableMap.Builder<String, ConfigurationProperty> builder = ImmutableMap.builder();
+
+ for (final ConfigurationProperty value : values) {
+ builder.put(value.toString(), value);
+ }
+
+ KEY_VALUE_MAP = builder.build();
+ }
+
+ /**
+ * Converts enum name to property key
+ *
+ * @return the property key
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase().replace('_', '-');
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.configuration;
+
+import java.util.Map;
+import java.util.function.Function;
+import javax.annotation.Nonnull;
+
+/**
+ * Manages OpenFlowPlugin configuration
+ */
+public interface ConfigurationService extends AutoCloseable {
+
+ /**
+ * Update map of properties.
+ *
+ * @param properties properties
+ */
+ void update(@Nonnull Map<String, String> properties);
+
+ /**
+ * Register listener for configuration changes.
+ *
+ * @param listener the listener
+ * @return the auto closeable listener registration
+ */
+ @Nonnull
+ AutoCloseable registerListener(@Nonnull ConfigurationListener listener);
+
+ /**
+ * Get single property from configuration service.
+ *
+ * @param <T> property type
+ * @param key property key
+ * @param transformer property type transformer
+ * @return property property
+ */
+ @Nonnull
+ <T> T getProperty(@Nonnull String key, @Nonnull Function<String, T> transformer);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.openflowplugin.api.openflow.configuration;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Factory for creating ConfigurationService instances.
+ */
+public interface ConfigurationServiceFactory {
+ ConfigurationService newInstance(OpenflowProviderConfig providerConfig,
+ BundleContext bundleContext);
+}
\ No newline at end of file
*/
void setDeviceDisconnectedHandler(DeviceDisconnectedHandler deviceDisconnectedHandler);
- /**
- * Setter for echo reply timeout.
- * @param echoReplyTimeout {@link Long} timeout
- */
- void setEchoReplyTimeout(long echoReplyTimeout);
}
package org.opendaylight.openflowplugin.api.openflow.device;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.Timeout;
import java.util.List;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
*/
TranslatorLibrary oook();
- /**
- * store cancellable timeout handler of currently running barrier task.
- */
- void setCurrentBarrierTimeout(Timeout timeout);
-
- /**
- * Getter.
- * @return cancellable timeout handle of currently running barrier task
- */
- Timeout getBarrierTaskTimeout();
-
void setNotificationPublishService(NotificationPublishService notificationPublishService);
MessageSpy getMessageSpy();
*/
ItemLifeCycleRegistry getItemLifeCycleSourceRegistry();
- void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory);
-
/**
* Setter for sal role service.
* @param salRoleService Role Service
*/
void initialize();
- void setFlowRemovedNotificationOn(boolean value);
-
- boolean isFlowRemovedNotificationOn();
-
- void setGlobalNotificationQuota(long globalNotificationQuota);
-
- void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory);
-
- void setSkipTableFeatures(boolean skipTableFeatures);
-
- void setBarrierCountLimit(int barrierCountLimit);
-
- void setBarrierInterval(long barrierTimeoutLimit);
-
CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(
@Nonnull KeyedInstanceIdentifier<Node, NodeKey> ii);
*/
package org.opendaylight.openflowplugin.api.openflow.lifecycle;
-import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowplugin.api.openflow.OFPManager;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
*/
void destroyContextChain(DeviceInfo deviceInfo);
- /**
- * Provider is needed to register cluster singleton service.
- * @param singletonServicesProvider provider
- */
- void addSingletonServicesProvider(ClusterSingletonServiceProvider singletonServicesProvider);
-
- /**
- * Register EOS listener.
- * @param entityOwnershipService EOS services
- */
- void changeEntityOwnershipService(@Nonnull EntityOwnershipService entityOwnershipService);
-
@Override
void close() throws Exception;
*/
public interface RpcManager extends OFPManager {
- void setStatisticsRpcEnabled(boolean statisticsRpcEnabled);
-
- void setRpcRequestQuota(int rpcRequestQuota);
-
RpcContext createContext(@Nonnull DeviceInfo deviceInfo, @Nonnull DeviceContext deviceContext);
}
@Override
void close();
- void setIsStatisticsPollingOn(boolean isStatisticsPollingOn);
-
- void setBasicTimerDelay(long basicTimerDelay);
-
- void setMaximumTimerDelay(long maximumTimerDelay);
-
StatisticsContext createContext(@Nonnull DeviceContext deviceContext);
}
# #
#############################################################################
+#
# Disable the default switch reconciliation mechanism
+#
# disable-reconciliation=false
+#
# Enable stale marking for switch reconciliation. Once user enable this feature
# forwarding rule manager will keep track of any change to the config data store
# while the switch is disconnected from controller. Once switch reconnect to the
# controller it will apply those changes to the switch and do the reconciliation
# of other configuration as well.
# NOTE: This option will be effective only if disable_reconciliation=false.
+#
# stale-marking-enabled=false
+#
# Number of time forwarding rules manager should retry to reconcile any specific
# configuration.
+#
# reconciliation-retry-count=5
<reference id="legacySwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
odl:type="openflow-switch-connection-provider-legacy-impl"/>
+ <reference id="openflowPluginProviderFactory"
+ interface="org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory"/>
+
+ <reference id="configurationServiceFactory"
+ interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory"/>
+
<odl:clustered-app-config id="openflowProviderConfig"
binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig"/>
- <reference id="openflowPluginProviderFactory"
- interface="org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory"/>
+ <bean id="configurationService"
+ factory-ref="configurationServiceFactory"
+ factory-method="newInstance"
+ destroy-method="close">
+ <argument ref="openflowProviderConfig" />
+ <argument ref="blueprintBundleContext" />
+ <cm:managed-properties persistent-id="org.opendaylight.openflowplugin"
+ update-strategy="component-managed"
+ update-method="update"/>
+ </bean>
+
+ <service ref="configurationService" interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService"/>
- <bean id="openflowPluginProvider" factory-ref="openflowPluginProviderFactory" factory-method="newInstance" destroy-method="close">
- <argument ref="openflowProviderConfig"/>
+ <bean id="openflowPluginProvider"
+ factory-ref="openflowPluginProviderFactory"
+ factory-method="newInstance"
+ destroy-method="close">
+ <argument ref="configurationService"/>
<argument ref="dataBroker"/>
<argument ref="rpcRegistry"/>
<argument ref="notificationPublishService"/>
</list>
</argument>
<argument ref="clusterSingletonServiceProvider"/>
- <argument ref="blueprintBundleContext" />
- <cm:managed-properties persistent-id="org.opendaylight.openflowplugin"
- update-strategy="component-managed"
- update-method="update"/>
</bean>
<service ref="openflowPluginProvider" odl:type="openflow-plugin-provider-impl">
*/
package org.opendaylight.openflowplugin.impl;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService.PropertyType;
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderFactoryImpl.class);
@Override
- public OpenFlowPluginProvider newInstance(final OpenflowProviderConfig providerConfig,
+ public OpenFlowPluginProvider newInstance(final ConfigurationService configurationService,
final DataBroker dataBroker,
final RpcProviderRegistry rpcRegistry,
final NotificationPublishService notificationPublishService,
final EntityOwnershipService entityOwnershipService,
final List<SwitchConnectionProvider> switchConnectionProviders,
- final ClusterSingletonServiceProvider singletonServiceProvider,
- final BundleContext bundleContext) {
-
+ final ClusterSingletonServiceProvider singletonServiceProvider) {
LOG.info("Initializing new OFP southbound.");
-
- final OpenFlowPluginProviderImpl openflowPluginProvider = new OpenFlowPluginProviderImpl(
+ final OpenFlowPluginProvider openflowPluginProvider = new OpenFlowPluginProviderImpl(
+ configurationService,
switchConnectionProviders,
dataBroker,
rpcRegistry,
singletonServiceProvider,
entityOwnershipService);
- LOG.info("Loading configuration from YANG file");
- openflowPluginProvider.updateProperty(PropertyType.RPC_REQUESTS_QUOTA, providerConfig.getRpcRequestsQuota().getValue());
- openflowPluginProvider.updateProperty(PropertyType.GLOBAL_NOTIFICATION_QUOTA, providerConfig.getGlobalNotificationQuota());
- openflowPluginProvider.updateProperty(PropertyType.SWITCH_FEATURES_MANDATORY, providerConfig.isSwitchFeaturesMandatory());
- openflowPluginProvider.updateProperty(PropertyType.ENABLE_FLOW_REMOVED_NOTIFICATION, providerConfig.isEnableFlowRemovedNotification());
- openflowPluginProvider.updateProperty(PropertyType.IS_STATISTICS_RPC_ENABLED, providerConfig.isIsStatisticsRpcEnabled());
- openflowPluginProvider.updateProperty(PropertyType.BARRIER_COUNT_LIMIT, providerConfig.getBarrierCountLimit().getValue());
- openflowPluginProvider.updateProperty(PropertyType.BARRIER_INTERVAL_TIMEOUT_LIMIT, providerConfig.getBarrierIntervalTimeoutLimit().getValue());
- openflowPluginProvider.updateProperty(PropertyType.ECHO_REPLY_TIMEOUT, providerConfig.getEchoReplyTimeout().getValue());
- openflowPluginProvider.updateProperty(PropertyType.IS_STATISTICS_POLLING_ON, providerConfig.isIsStatisticsPollingOn());
- openflowPluginProvider.updateProperty(PropertyType.SKIP_TABLE_FEATURES, providerConfig.isSkipTableFeatures());
- openflowPluginProvider.updateProperty(PropertyType.BASIC_TIMER_DELAY, providerConfig.getBasicTimerDelay().getValue());
- openflowPluginProvider.updateProperty(PropertyType.MAXIMUM_TIMER_DELAY, providerConfig.getMaximumTimerDelay().getValue());
- openflowPluginProvider.updateProperty(PropertyType.USE_SINGLE_LAYER_SERIALIZATION, providerConfig.isUseSingleLayerSerialization());
- openflowPluginProvider.updateProperty(PropertyType.THREAD_POOL_MIN_THREADS, providerConfig.getThreadPoolMinThreads());
- openflowPluginProvider.updateProperty(PropertyType.THREAD_POOL_MAX_THREADS, providerConfig.getThreadPoolMaxThreads().getValue());
- openflowPluginProvider.updateProperty(PropertyType.THREAD_POOL_TIMEOUT, providerConfig.getThreadPoolTimeout());
-
- LOG.info("Loading configuration from properties file");
- Optional.ofNullable(bundleContext.getServiceReference(ConfigurationAdmin.class.getName())).ifPresent(serviceReference -> {
- final ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(serviceReference);
-
- try {
- final Configuration configuration = configurationAdmin.getConfiguration(OFConstants.CONFIG_FILE_ID);
-
- Optional.ofNullable(configuration.getProperties()).ifPresent(properties -> {
- final Enumeration<String> keys = properties.keys();
- final Map<String, Object> mapProperties = new HashMap<>(properties.size());
-
- while (keys.hasMoreElements()) {
- final String key = keys.nextElement();
- final Object value = properties.get(key);
- mapProperties.put(key, value);
- }
-
- openflowPluginProvider.update(mapProperties);
- });
- } catch (IOException e) {
- LOG.debug("Failed to load " + OFConstants.CONFIG_FILE_ID + " configuration file", e);
- }
- });
-
openflowPluginProvider.initialize();
return openflowPluginProvider;
}
package org.opendaylight.openflowplugin.impl;
-import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.lang.management.ManagementFactory;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.management.InstanceAlreadyExistsException;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
-import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService;
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainHolder;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
import org.opendaylight.openflowplugin.extension.api.ExtensionConverterRegistrator;
import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager;
+import org.opendaylight.openflowplugin.impl.configuration.OpenFlowProviderConfigImpl;
import org.opendaylight.openflowplugin.impl.connection.ConnectionManagerImpl;
import org.opendaylight.openflowplugin.impl.device.DeviceManagerImpl;
import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
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.OpenflowProviderConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginConfigurationService, OpenFlowPluginExtensionRegistratorProvider {
+public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginExtensionRegistratorProvider {
private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderImpl.class);
private final ConvertorManager convertorManager;
private final RpcProviderRegistry rpcProviderRegistry;
private final ClusterSingletonServiceProvider singletonServicesProvider;
+ private final OpenflowProviderConfig config;
private final EntityOwnershipService entityOwnershipService;
- private ContextChainHolder contextChainHolder;
- private int rpcRequestsQuota;
- private long globalNotificationQuota;
- private long barrierInterval;
- private int barrierCountLimit;
- private long echoReplyTimeout;
private DeviceManager deviceManager;
private RpcManager rpcManager;
private StatisticsManager statisticsManager;
private ConnectionManager connectionManager;
- private boolean switchFeaturesMandatory;
- private boolean isStatisticsPollingOn;
- private boolean isStatisticsRpcEnabled;
- private boolean isFlowRemovedNotificationOn;
- private boolean skipTableFeatures;
- private long basicTimerDelay;
- private long maximumTimerDelay;
- private boolean useSingleLayerSerialization;
private ThreadPoolExecutor threadPool;
- private int threadPoolMinThreads;
- private int threadPoolMaxThreads;
- private long threadPoolTimeout;
- private boolean initialized = false;
+ private ContextChainHolderImpl contextChainHolder;
public static MessageIntelligenceAgency getMessageIntelligenceAgency() {
return MESSAGE_INTELLIGENCE_AGENCY;
}
- OpenFlowPluginProviderImpl(final List<SwitchConnectionProvider> switchConnectionProviders,
+ OpenFlowPluginProviderImpl(final ConfigurationService configurationService,
+ final List<SwitchConnectionProvider> switchConnectionProviders,
final DataBroker dataBroker,
final RpcProviderRegistry rpcProviderRegistry,
final NotificationPublishService notificationPublishService,
convertorManager = ConvertorManagerFactory.createDefaultManager();
extensionConverterManager = new ExtensionConverterManagerImpl();
deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();
+ config = new OpenFlowProviderConfigImpl(configurationService);
}
private void startSwitchConnections() {
Futures.addCallback(Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> {
// Inject OpenFlowPlugin custom serializers and deserializers into OpenFlowJava
- if (useSingleLayerSerialization) {
+ if (config.isUseSingleLayerSerialization()) {
SerializerInjector.injectSerializers(switchConnectionProvider);
DeserializerInjector.injectDeserializers(switchConnectionProvider);
} else {
private ListenableFuture<List<Boolean>> shutdownSwitchConnections() {
final ListenableFuture<List<Boolean>> listListenableFuture = Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> {
// Revert deserializers to their original state
- if (useSingleLayerSerialization) {
+ if (config.isUseSingleLayerSerialization()) {
DeserializerInjector.revertDeserializers(switchConnectionProvider);
}
@Override
public void initialize() {
+ registerMXBean(MESSAGE_INTELLIGENCE_AGENCY, MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME);
+
// TODO: copied from OpenFlowPluginProvider (Helium) misusesing the old way of distributing extension converters
// TODO: rewrite later!
OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager);
// constructed threads when they are available.
// Threads that have not been used for x seconds are terminated and removed from the cache.
threadPool = new ThreadPoolLoggingExecutor(
- Preconditions.checkNotNull(threadPoolMinThreads),
- Preconditions.checkNotNull(threadPoolMaxThreads),
- Preconditions.checkNotNull(threadPoolTimeout),
+ config.getThreadPoolMinThreads(),
+ config.getThreadPoolMaxThreads().getValue(),
+ config.getThreadPoolTimeout(),
TimeUnit.SECONDS, new SynchronousQueue<>(), POOL_NAME);
-
- contextChainHolder = new ContextChainHolderImpl(hashedWheelTimer, threadPool);
- contextChainHolder.changeEntityOwnershipService(entityOwnershipService);
-
- connectionManager = new ConnectionManagerImpl(threadPool);
- connectionManager.setEchoReplyTimeout(echoReplyTimeout);
-
- registerMXBean(MESSAGE_INTELLIGENCE_AGENCY, MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME);
-
- contextChainHolder.addSingletonServicesProvider(singletonServicesProvider);
-
deviceManager = new DeviceManagerImpl(
+ config,
dataBroker,
getMessageIntelligenceAgency(),
notificationPublishService,
hashedWheelTimer,
convertorManager,
- deviceInitializerProvider,
- useSingleLayerSerialization);
-
- deviceManager.setGlobalNotificationQuota(globalNotificationQuota);
- deviceManager.setSwitchFeaturesMandatory(switchFeaturesMandatory);
- deviceManager.setBarrierInterval(barrierInterval);
- deviceManager.setBarrierCountLimit(barrierCountLimit);
- deviceManager.setFlowRemovedNotificationOn(isFlowRemovedNotificationOn);
- deviceManager.setSkipTableFeatures(skipTableFeatures);
+ deviceInitializerProvider);
+ TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager);
((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
- rpcManager = new RpcManagerImpl(rpcProviderRegistry, extensionConverterManager, convertorManager, notificationPublishService);
- rpcManager.setRpcRequestQuota(rpcRequestsQuota);
-
- statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, hashedWheelTimer, convertorManager);
- statisticsManager.setBasicTimerDelay(basicTimerDelay);
- statisticsManager.setMaximumTimerDelay(maximumTimerDelay);
- statisticsManager.setIsStatisticsPollingOn(isStatisticsPollingOn);
-
- // Device connection handler moved from device manager to context holder
- connectionManager.setDeviceConnectedHandler(contextChainHolder);
-
- /* Termination Phase ordering - OFP Device Context suite */
- connectionManager.setDeviceDisconnectedHandler(contextChainHolder);
+ rpcManager = new RpcManagerImpl(
+ config,
+ rpcProviderRegistry,
+ extensionConverterManager,
+ convertorManager,
+ notificationPublishService);
- rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
+ statisticsManager = new StatisticsManagerImpl(
+ config,
+ rpcProviderRegistry,
+ hashedWheelTimer,
+ convertorManager);
- TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager);
- deviceManager.initialize();
+ contextChainHolder = new ContextChainHolderImpl(
+ hashedWheelTimer,
+ threadPool,
+ singletonServicesProvider,
+ entityOwnershipService);
contextChainHolder.addManager(deviceManager);
contextChainHolder.addManager(statisticsManager);
contextChainHolder.addManager(rpcManager);
- startSwitchConnections();
- initialized = true;
- }
-
-
- @Override
- public void update(@Nonnull final Map<String, Object> properties) {
- properties.forEach((key, value) -> {
- final PropertyType propertyType = PropertyType.forValue(key);
-
- if (Objects.nonNull(propertyType)) {
- updateProperty(propertyType, value);
- }
- });
- }
-
- private void doPropertyUpdate(final PropertyType propertyType,
- final boolean modifiable,
- final Object origValue,
- final Object newValue,
- final Consumer<Object> successCallback) {
- if (initialized) {
- if (Objects.equals(origValue, newValue)) {
- LOG.debug("{} config parameter is already set to {})", propertyType, origValue);
- return;
- } else if (!modifiable) {
- LOG.warn("{} update ({} -> {}) is not allowed after controller start", propertyType, origValue, newValue);
- return;
- }
- }
-
- successCallback.accept(newValue);
- LOG.info("{} config parameter is updated ({} -> {})", propertyType, origValue, newValue);
- }
-
- @Override
- public void updateProperty(@Nonnull final PropertyType key, @Nonnull final Object value) {
- try {
- final String sValue = value.toString();
- final Consumer<Object> successCallback;
- final boolean modifiable;
- final Object oldValue;
- final Object newValue;
-
- switch (key) {
- case RPC_REQUESTS_QUOTA:
- successCallback = (result) -> {
- rpcRequestsQuota = (int) result;
-
- if (initialized) {
- rpcManager.setRpcRequestQuota(rpcRequestsQuota);
- }
- };
-
- oldValue = rpcRequestsQuota;
- newValue = Integer.valueOf(sValue);
- modifiable = true;
- break;
- case SWITCH_FEATURES_MANDATORY:
- successCallback = (result) -> {
- switchFeaturesMandatory = (boolean) result;
-
- if (initialized) {
- deviceManager.setSwitchFeaturesMandatory(switchFeaturesMandatory);
- }
- };
-
- oldValue = switchFeaturesMandatory;
- newValue = Boolean.valueOf(sValue);
- modifiable = true;
- break;
- case GLOBAL_NOTIFICATION_QUOTA:
- successCallback = (result) -> {
- globalNotificationQuota = (long) result;
-
- if (initialized) {
- deviceManager.setGlobalNotificationQuota(globalNotificationQuota);
- }
- };
-
- oldValue = globalNotificationQuota;
- newValue = Long.valueOf(sValue);
- modifiable = true;
- break;
- case IS_STATISTICS_POLLING_ON:
- successCallback = (result) -> {
- isStatisticsPollingOn = (boolean) result;
-
- if (initialized) {
- statisticsManager.setIsStatisticsPollingOn(isStatisticsPollingOn);
- }
- };
-
- oldValue = isStatisticsPollingOn;
- newValue = Boolean.valueOf(sValue);
- modifiable = true;
- break;
- case IS_STATISTICS_RPC_ENABLED:
- successCallback = (result) -> {
- isStatisticsRpcEnabled = (boolean) result;
-
- if (initialized) {
- rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
- }
- };
-
- oldValue = isStatisticsRpcEnabled;
- newValue = Boolean.valueOf(sValue);
- modifiable = true;
- break;
- case BARRIER_INTERVAL_TIMEOUT_LIMIT:
- successCallback = (result) -> {
- barrierInterval = (long) result;
-
- if (initialized) {
- deviceManager.setBarrierInterval(barrierInterval);
- }
- };
-
- oldValue = barrierInterval;
- newValue = Long.valueOf(sValue);
- modifiable = true;
- break;
- case BARRIER_COUNT_LIMIT:
- successCallback = (result) -> {
- barrierCountLimit = (int) result;
-
- if (initialized) {
- deviceManager.setBarrierCountLimit(barrierCountLimit);
- }
- };
-
- oldValue = barrierCountLimit;
- newValue = Integer.valueOf(sValue);
- modifiable = true;
- break;
- case ECHO_REPLY_TIMEOUT:
- successCallback = (result) -> {
- echoReplyTimeout = (long) result;
-
- if (initialized) {
- connectionManager.setEchoReplyTimeout(echoReplyTimeout);
- }
- };
-
- oldValue = echoReplyTimeout;
- newValue = Long.valueOf(sValue);
- modifiable = true;
- break;
- case THREAD_POOL_MIN_THREADS:
- successCallback = (result) -> threadPoolMinThreads = (int) result;
- oldValue = threadPoolMinThreads;
- newValue = Integer.valueOf(sValue);
- modifiable = false;
- break;
- case THREAD_POOL_MAX_THREADS:
- successCallback = (result) -> threadPoolMaxThreads = (int) result;
- oldValue = threadPoolMaxThreads;
- newValue = Integer.valueOf(sValue);
- modifiable = false;
- break;
- case THREAD_POOL_TIMEOUT:
- successCallback = (result) -> threadPoolTimeout = (long) result;
- oldValue = threadPoolTimeout;
- newValue = Long.valueOf(sValue);
- modifiable = false;
- break;
- case ENABLE_FLOW_REMOVED_NOTIFICATION:
- successCallback = (result) -> {
- isFlowRemovedNotificationOn = (boolean) result;
-
- if (initialized) {
- deviceManager.setFlowRemovedNotificationOn(isFlowRemovedNotificationOn);
- }
- };
-
- oldValue = isFlowRemovedNotificationOn;
- newValue = Boolean.valueOf(sValue);
- modifiable = true;
- break;
- case SKIP_TABLE_FEATURES:
- successCallback = (result) -> {
- skipTableFeatures = (boolean) result;
-
- if (initialized) {
- deviceManager.setSkipTableFeatures(skipTableFeatures);
- }
- };
-
- oldValue = skipTableFeatures;
- newValue = Boolean.valueOf(sValue);
- modifiable = true;
- break;
- case BASIC_TIMER_DELAY:
- successCallback = (result) -> {
- basicTimerDelay = (long) result;
-
- if (initialized) {
- statisticsManager.setBasicTimerDelay(basicTimerDelay);
- }
- };
-
- oldValue = basicTimerDelay;
- newValue = Long.valueOf(sValue);
- modifiable = true;
- break;
- case MAXIMUM_TIMER_DELAY:
- successCallback = (result) -> {
- maximumTimerDelay = (long) result;
-
- if (initialized) {
- statisticsManager.setMaximumTimerDelay(maximumTimerDelay);
- }
- };
-
- oldValue = maximumTimerDelay;
- newValue = Long.valueOf(sValue);
- modifiable = true;
- break;
- case USE_SINGLE_LAYER_SERIALIZATION:
- successCallback = (result) -> useSingleLayerSerialization = (boolean) result;
- oldValue = useSingleLayerSerialization;
- newValue = Boolean.valueOf(sValue);
- modifiable = false;
- break;
- default:
- return;
- }
+ connectionManager = new ConnectionManagerImpl(config, threadPool);
+ connectionManager.setDeviceConnectedHandler(contextChainHolder);
+ connectionManager.setDeviceDisconnectedHandler(contextChainHolder);
- doPropertyUpdate(key, modifiable, oldValue, newValue, successCallback);
- } catch (final Exception ex) {
- LOG.warn("Failed to read configuration property '{}={}', error: {}", key, value, ex);
- }
+ deviceManager.initialize();
+ startSwitchConnections();
}
@Override
@Override
public void close() {
- initialized = false;
-
try {
shutdownSwitchConnections().get(10, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.configuration;
+
+import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableMap;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import javax.annotation.Nonnull;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationListener;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConfigurationServiceFactoryImpl implements ConfigurationServiceFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigurationServiceFactory.class);
+
+ @Override
+ public ConfigurationService newInstance(final OpenflowProviderConfig providerConfig, final BundleContext bundleContext) {
+ return new ConfigurationServiceImpl(providerConfig, bundleContext);
+ }
+
+ private static final class ConfigurationServiceImpl implements ConfigurationService {
+ private final Map<String, String> propertyMap = new HashMap<>();
+ private final List<ConfigurationListener> listeners = new ArrayList<>();
+
+ ConfigurationServiceImpl(final OpenflowProviderConfig providerConfig, final BundleContext bundleContext) {
+ LOG.info("Loading properties from '{}' YANG file", OpenflowProviderConfig.QNAME);
+ update(ImmutableMap
+ .<String, String>builder()
+ .put(ConfigurationProperty.RPC_REQUESTS_QUOTA.toString(),
+ providerConfig.getRpcRequestsQuota().getValue().toString())
+ .put(ConfigurationProperty.GLOBAL_NOTIFICATION_QUOTA.toString(),
+ providerConfig.getGlobalNotificationQuota().toString())
+ .put(ConfigurationProperty.SWITCH_FEATURES_MANDATORY.toString(),
+ providerConfig.isSwitchFeaturesMandatory().toString())
+ .put(ConfigurationProperty.ENABLE_FLOW_REMOVED_NOTIFICATION.toString(),
+ providerConfig.isEnableFlowRemovedNotification().toString())
+ .put(ConfigurationProperty.IS_STATISTICS_RPC_ENABLED.toString(),
+ providerConfig.isIsStatisticsRpcEnabled().toString())
+ .put(ConfigurationProperty.BARRIER_COUNT_LIMIT.toString(),
+ providerConfig.getBarrierCountLimit().getValue().toString())
+ .put(ConfigurationProperty.BARRIER_INTERVAL_TIMEOUT_LIMIT.toString(),
+ providerConfig.getBarrierIntervalTimeoutLimit().getValue().toString())
+ .put(ConfigurationProperty.ECHO_REPLY_TIMEOUT.toString(),
+ providerConfig.getEchoReplyTimeout().getValue().toString())
+ .put(ConfigurationProperty.IS_STATISTICS_POLLING_ON.toString(),
+ providerConfig.isIsStatisticsPollingOn().toString())
+ .put(ConfigurationProperty.SKIP_TABLE_FEATURES.toString(),
+ providerConfig.isSkipTableFeatures().toString())
+ .put(ConfigurationProperty.BASIC_TIMER_DELAY.toString(),
+ providerConfig.getBasicTimerDelay().getValue().toString())
+ .put(ConfigurationProperty.MAXIMUM_TIMER_DELAY.toString(),
+ providerConfig.getMaximumTimerDelay().getValue().toString())
+ .put(ConfigurationProperty.USE_SINGLE_LAYER_SERIALIZATION.toString(),
+ providerConfig.isUseSingleLayerSerialization().toString())
+ .put(ConfigurationProperty.THREAD_POOL_MIN_THREADS.toString(),
+ providerConfig.getThreadPoolMinThreads().toString())
+ .put(ConfigurationProperty.THREAD_POOL_MAX_THREADS.toString(),
+ providerConfig.getThreadPoolMaxThreads().getValue().toString())
+ .put(ConfigurationProperty.THREAD_POOL_TIMEOUT.toString(),
+ providerConfig.getThreadPoolTimeout().toString())
+ .build());
+
+ LOG.info("Loading configuration from '{}' configuration file", OFConstants.CONFIG_FILE_ID);
+ Optional.ofNullable(bundleContext.getServiceReference(ConfigurationAdmin.class.getName())).ifPresent(serviceReference -> {
+ final ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(serviceReference);
+
+ try {
+ final Configuration configuration = configurationAdmin.getConfiguration(OFConstants.CONFIG_FILE_ID);
+
+ Optional.ofNullable(configuration.getProperties()).ifPresent(properties -> {
+ final Enumeration<String> keys = properties.keys();
+ final Map<String, String> mapProperties = new HashMap<>(properties.size());
+
+ while (keys.hasMoreElements()) {
+ final String key = keys.nextElement();
+ final String value = properties.get(key).toString();
+ mapProperties.put(key, value);
+ }
+
+ update(mapProperties);
+ });
+ } catch (IOException e) {
+ LOG.debug("Failed to load {} configuration file. Error {}", OFConstants.CONFIG_FILE_ID, e);
+ }
+ });
+ }
+
+ @Override
+ public void update(@Nonnull final Map<String, String> properties) {
+ properties.forEach((propertyName, newValue) -> {
+ final String originalValue = propertyMap.get(propertyName);
+
+ if (Objects.nonNull(originalValue)) {
+ if (originalValue.equals(newValue)) {
+ return;
+ }
+
+ LOG.info("{} configuration property was changed from '{}' to '{}'", propertyName, originalValue, newValue);
+ } else {
+ if (Objects.isNull(newValue)) {
+ return;
+ }
+
+ LOG.info("{} configuration property was changed to '{}'", propertyName, newValue);
+ }
+
+ propertyMap.put(propertyName, newValue);
+ listeners.forEach(listener -> listener.onPropertyChanged(propertyName, newValue));
+ });
+ }
+
+ @Nonnull
+ @Override
+ public <T> T getProperty(@Nonnull final String key, @Nonnull final Function<String, T> transformer) {
+ return transformer.apply(propertyMap.get(key));
+ }
+
+ @Nonnull
+ @Override
+ public AutoCloseable registerListener(@Nonnull final ConfigurationListener listener) {
+ Verify.verify(!listeners.contains(listener));
+ LOG.info("{} was registered as configuration listener to OpenFlowPlugin configuration service", listener);
+ listeners.add(listener);
+ propertyMap.forEach(listener::onPropertyChanged);
+ return () -> listeners.remove(listener);
+ }
+
+ @Override
+ public void close() throws Exception {
+ propertyMap.clear();
+ listeners.clear();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.configuration;
+
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+public class OpenFlowProviderConfigImpl implements OpenflowProviderConfig {
+ private final ConfigurationService service;
+
+ public OpenFlowProviderConfigImpl(final ConfigurationService service) {
+ this.service = service;
+ }
+
+ @Override
+ public NonZeroUint16Type getRpcRequestsQuota() {
+ final Integer property = service.getProperty(
+ ConfigurationProperty.RPC_REQUESTS_QUOTA.toString(),
+ Integer::valueOf);
+
+ return new NonZeroUint16Type(property);
+ }
+
+ @Override
+ public Boolean isSwitchFeaturesMandatory() {
+ return service.getProperty(ConfigurationProperty.SWITCH_FEATURES_MANDATORY.toString(), Boolean::valueOf);
+ }
+
+ @Override
+ public Long getGlobalNotificationQuota() {
+ return service.getProperty(ConfigurationProperty.GLOBAL_NOTIFICATION_QUOTA.toString(), Long::valueOf);
+ }
+
+ @Override
+ public Boolean isIsStatisticsPollingOn() {
+ return service.getProperty(ConfigurationProperty.IS_STATISTICS_POLLING_ON.toString(), Boolean::valueOf);
+ }
+
+ @Override
+ public Boolean isIsStatisticsRpcEnabled() {
+ return service.getProperty(ConfigurationProperty.IS_STATISTICS_RPC_ENABLED.toString(), Boolean::valueOf);
+ }
+
+ @Override
+ public NonZeroUint32Type getBarrierIntervalTimeoutLimit() {
+ final Long property = service.getProperty(
+ ConfigurationProperty.BARRIER_INTERVAL_TIMEOUT_LIMIT.toString(),
+ Long::valueOf);
+
+ return new NonZeroUint32Type(property);
+ }
+
+ @Override
+ public NonZeroUint16Type getBarrierCountLimit() {
+ final Integer property = service.getProperty(
+ ConfigurationProperty.BARRIER_COUNT_LIMIT.toString(),
+ Integer::valueOf);
+
+ return new NonZeroUint16Type(property);
+ }
+
+ @Override
+ public NonZeroUint32Type getEchoReplyTimeout() {
+ final Long property = service.getProperty(
+ ConfigurationProperty.ECHO_REPLY_TIMEOUT.toString(),
+ Long::valueOf);
+
+ return new NonZeroUint32Type(property);
+ }
+
+ @Override
+ public Integer getThreadPoolMinThreads() {
+ return service.getProperty(ConfigurationProperty.THREAD_POOL_MIN_THREADS.toString(), Integer::valueOf);
+ }
+
+ @Override
+ public NonZeroUint16Type getThreadPoolMaxThreads() {
+ final Integer property = service.getProperty(
+ ConfigurationProperty.THREAD_POOL_MAX_THREADS.toString(),
+ Integer::valueOf);
+
+ return new NonZeroUint16Type(property);
+ }
+
+ @Override
+ public Long getThreadPoolTimeout() {
+ return service.getProperty(ConfigurationProperty.THREAD_POOL_TIMEOUT.toString(), Long::valueOf);
+ }
+
+ @Override
+ public Boolean isEnableFlowRemovedNotification() {
+ return service.getProperty(ConfigurationProperty.ENABLE_FLOW_REMOVED_NOTIFICATION.toString(), Boolean::valueOf);
+ }
+
+ @Override
+ public Boolean isSkipTableFeatures() {
+ return service.getProperty(ConfigurationProperty.SKIP_TABLE_FEATURES.toString(), Boolean::valueOf);
+ }
+
+ @Override
+ public NonZeroUint32Type getBasicTimerDelay() {
+ final Long property = service.getProperty(
+ ConfigurationProperty.BASIC_TIMER_DELAY.toString(),
+ Long::valueOf);
+
+ return new NonZeroUint32Type(property);
+ }
+
+ @Override
+ public NonZeroUint32Type getMaximumTimerDelay() {
+ final Long property = service.getProperty(
+ ConfigurationProperty.MAXIMUM_TIMER_DELAY.toString(),
+ Long::valueOf);
+
+ return new NonZeroUint32Type(property);
+ }
+
+ @Override
+ public Boolean isUseSingleLayerSerialization() {
+ return service.getProperty(ConfigurationProperty.USE_SINGLE_LAYER_SERIALIZATION.toString(), Boolean::valueOf);
+ }
+
+ @Override
+ public <E extends Augmentation<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig>> E getAugmentation(java.lang.Class<E> augmentationType) {
+ return null;
+ }
+
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return OpenflowProviderConfig.class;
+ }
+
+}
import org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(ConnectionManagerImpl.class);
private static final boolean BITMAP_NEGOTIATION_ENABLED = true;
private DeviceConnectedHandler deviceConnectedHandler;
- private long echoReplyTimeout = 2000;
+ private final OpenflowProviderConfig config;
private final ThreadPoolExecutor threadPool;
private DeviceDisconnectedHandler deviceDisconnectedHandler;
- public ConnectionManagerImpl(final ThreadPoolExecutor threadPool) {
+ public ConnectionManagerImpl(final OpenflowProviderConfig config, final ThreadPoolExecutor threadPool) {
+ this.config = config;
this.threadPool = threadPool;
}
new OpenflowProtocolListenerInitialImpl(connectionContext, handshakeContext);
connectionAdapter.setMessageListener(ofMessageListener);
- final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(connectionContext, echoReplyTimeout, threadPool);
+ final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(
+ connectionContext, config.getEchoReplyTimeout().getValue(), threadPool);
connectionAdapter.setSystemListener(systemListener);
LOG.trace("connection ballet finished");
}
- /**
- * @param connectionAdapter
- * @param handshakeListener
- * @return
- */
private HandshakeManager createHandshakeManager(final ConnectionAdapter connectionAdapter,
final HandshakeListener handshakeListener) {
HandshakeManagerImpl handshakeManager = new HandshakeManagerImpl(connectionAdapter,
public void setDeviceDisconnectedHandler(final DeviceDisconnectedHandler deviceDisconnectedHandler) {
this.deviceDisconnectedHandler = deviceDisconnectedHandler;
}
-
- @Override
- public void setEchoReplyTimeout(long echoReplyTimeout){
- this.echoReplyTimeout = echoReplyTimeout;
- }
}
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.HashedWheelTimer;
-import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import java.util.Collection;
import java.util.HashSet;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
private static final int LOW_WATERMARK = 1000;
private static final int HIGH_WATERMARK = 2000;
- private final MultipartWriterProvider writerProvider;
-
- private boolean initialized;
- private SalRoleService salRoleService = null;
+ private final MultipartWriterProvider writerProvider;
private final HashedWheelTimer hashedWheelTimer;
- private volatile ConnectionContext primaryConnectionContext;
private final DeviceState deviceState;
private final DataBroker dataBroker;
private final Collection<RequestContext<?>> requestContexts = new HashSet<>();
- private TransactionChainManager transactionChainManager;
- private DeviceFlowRegistry deviceFlowRegistry;
- private DeviceGroupRegistry deviceGroupRegistry;
- private DeviceMeterRegistry deviceMeterRegistry;
- private PacketInRateLimiter packetInLimiter;
private final MessageSpy messageSpy;
private final ItemLifeCycleKeeper flowLifeCycleKeeper;
- private NotificationPublishService notificationPublishService;
- private Timeout barrierTaskTimeout;
private final MessageTranslator<PortGrouping, FlowCapableNodeConnector> portStatusTranslator;
private final MessageTranslator<PacketInMessage, PacketReceived> packetInTranslator;
private final MessageTranslator<FlowRemoved, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved> flowRemovedTranslator;
private final TranslatorLibrary translatorLibrary;
private final ItemLifeCycleRegistry itemLifeCycleSourceRegistry;
- private ExtensionConverterProvider extensionConverterProvider;
- private boolean skipTableFeatures;
- private boolean switchFeaturesMandatory;
- private DeviceInfo deviceInfo;
private final ConvertorExecutor convertorExecutor;
- private volatile ContextState state;
- private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
- private final DeviceManager myManager;
private final DeviceInitializerProvider deviceInitializerProvider;
+ private final PacketInRateLimiter packetInLimiter;
+ private final DeviceInfo deviceInfo;
+ private final boolean skipTableFeatures;
+ private final boolean switchFeaturesMandatory;
+ private final boolean isFlowRemovedNotificationOn;
private final boolean useSingleLayerSerialization;
+ private NotificationPublishService notificationPublishService;
+ private TransactionChainManager transactionChainManager;
+ private DeviceFlowRegistry deviceFlowRegistry;
+ private DeviceGroupRegistry deviceGroupRegistry;
+ private DeviceMeterRegistry deviceMeterRegistry;
+ private ExtensionConverterProvider extensionConverterProvider;
+ private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
+ private SalRoleService salRoleService;
+ private boolean initialized;
private boolean hasState;
private boolean isInitialTransactionSubmitted;
+ private volatile ConnectionContext primaryConnectionContext;
+ private volatile ContextState state;
DeviceContextImpl(
@Nonnull final ConnectionContext primaryConnectionContext,
@Nonnull final DataBroker dataBroker,
@Nonnull final MessageSpy messageSpy,
@Nonnull final TranslatorLibrary translatorLibrary,
- @Nonnull final DeviceManager contextManager,
final ConvertorExecutor convertorExecutor,
final boolean skipTableFeatures,
final HashedWheelTimer hashedWheelTimer,
final boolean useSingleLayerSerialization,
- final DeviceInitializerProvider deviceInitializerProvider) {
+ final DeviceInitializerProvider deviceInitializerProvider,
+ final boolean isFlowRemovedNotificationOn,
+ final boolean switchFeaturesMandatory) {
this.primaryConnectionContext = primaryConnectionContext;
this.deviceInfo = primaryConnectionContext.getDeviceInfo();
this.hashedWheelTimer = hashedWheelTimer;
this.deviceInitializerProvider = deviceInitializerProvider;
- this.myManager = contextManager;
+ this.isFlowRemovedNotificationOn = isFlowRemovedNotificationOn;
+ this.switchFeaturesMandatory = switchFeaturesMandatory;
this.deviceState = new DeviceStateImpl();
this.dataBroker = dataBroker;
this.messageSpy = messageSpy;
final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved flowRemovedNotification =
flowRemovedTranslator.translate(flowRemoved, deviceInfo, null);
- if(myManager.isFlowRemovedNotificationOn()) {
+ if (isFlowRemovedNotificationOn) {
// Trigger off a notification
notificationPublishService.offerNotification(flowRemovedNotification);
- } else if(LOG.isDebugEnabled()) {
- LOG.debug("For nodeId={} isNotificationFlowRemovedOn={}", getDeviceInfo().getLOGValue(), myManager.isFlowRemovedNotificationOn());
}
final ItemLifecycleListener itemLifecycleListener = flowLifeCycleKeeper.getItemLifecycleListener();
return translatorLibrary;
}
- @Override
- public void setCurrentBarrierTimeout(final Timeout timeout) {
- barrierTaskTimeout = timeout;
- }
-
- @Override
- public Timeout getBarrierTaskTimeout() {
- return barrierTaskTimeout;
- }
-
@Override
public void setNotificationPublishService(final NotificationPublishService notificationPublishService) {
this.notificationPublishService = notificationPublishService;
return this.transactionChainManager;
}
- @Override
- public void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory) {
- this.switchFeaturesMandatory = switchFeaturesMandatory;
- }
-
@Override
public ListenableFuture<Void> stopClusterServices() {
return initialized
import com.google.common.util.concurrent.Futures;
import io.netty.util.HashedWheelTimer;
import io.netty.util.internal.ConcurrentSet;
-import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl;
import org.opendaylight.openflowplugin.impl.services.sal.SalRoleServiceImpl;
+import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtil;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProviderKeeper {
private static final Logger LOG = LoggerFactory.getLogger(DeviceManagerImpl.class);
-
- private long globalNotificationQuota;
- private boolean switchFeaturesMandatory;
- private boolean isFlowRemovedNotificationOn;
- private boolean skipTableFeatures;
private static final int SPY_RATE = 10;
+ private final OpenflowProviderConfig config;
private final DataBroker dataBroker;
private final DeviceInitializerProvider deviceInitializerProvider;
private final ConvertorExecutor convertorExecutor;
- private TranslatorLibrary translatorLibrary;
-
private final ConcurrentMap<DeviceInfo, DeviceContext> deviceContexts = new ConcurrentHashMap<>();
private final Set<KeyedInstanceIdentifier<Node, NodeKey>> notificationCreateNodeSend = new ConcurrentSet<>();
-
- private long barrierIntervalNanos;
- private int barrierCountLimit;
-
- private ExtensionConverterProvider extensionConverterProvider;
- private ScheduledThreadPoolExecutor spyPool;
private final NotificationPublishService notificationPublishService;
private final MessageSpy messageSpy;
private final HashedWheelTimer hashedWheelTimer;
- private final boolean useSingleLayerSerialization;
+ private TranslatorLibrary translatorLibrary;
+ private ExtensionConverterProvider extensionConverterProvider;
+ private ScheduledThreadPoolExecutor spyPool;
- public DeviceManagerImpl(@Nonnull final DataBroker dataBroker,
+ public DeviceManagerImpl(@Nonnull final OpenflowProviderConfig config,
+ @Nonnull final DataBroker dataBroker,
@Nonnull final MessageSpy messageSpy,
- @Nullable final NotificationPublishService notificationPublishService,
+ @Nonnull final NotificationPublishService notificationPublishService,
@Nonnull final HashedWheelTimer hashedWheelTimer,
@Nonnull final ConvertorExecutor convertorExecutor,
- @Nonnull final DeviceInitializerProvider deviceInitializerProvider,
- final boolean useSingleLayerSerialization) {
-
+ @Nonnull final DeviceInitializerProvider deviceInitializerProvider) {
+ this.config = config;
this.dataBroker = dataBroker;
this.deviceInitializerProvider = deviceInitializerProvider;
- this.useSingleLayerSerialization = useSingleLayerSerialization;
-
- /* merge empty nodes to oper DS to predict any problems with missing parent for Node */
- final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
- final NodesBuilder nodesBuilder = new NodesBuilder();
- nodesBuilder.setNode(Collections.<Node>emptyList());
- tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodesBuilder.build());
- try {
- tx.submit().get();
- } catch (ExecutionException | InterruptedException e) {
- LOG.error("Creation of node failed.", e);
- throw new IllegalStateException(e);
- }
-
this.convertorExecutor = convertorExecutor;
this.hashedWheelTimer = hashedWheelTimer;
this.spyPool = new ScheduledThreadPoolExecutor(1);
this.notificationPublishService = notificationPublishService;
this.messageSpy = messageSpy;
+ DeviceInitializationUtil.makeEmptyNodes(dataBroker);
}
@Override
}
@Override
- public void setFlowRemovedNotificationOn(boolean isNotificationFlowRemovedOff) {
- this.isFlowRemovedNotificationOn = isNotificationFlowRemovedOff;
- }
-
- @Override
- public boolean isFlowRemovedNotificationOn() {
- return this.isFlowRemovedNotificationOn;
- }
-
- @Override
- public void setGlobalNotificationQuota(final long globalNotificationQuota) {
- this.globalNotificationQuota = globalNotificationQuota;
- }
-
- @Override
- public void setSwitchFeaturesMandatory(final boolean switchFeaturesMandatory) {
- this.switchFeaturesMandatory = switchFeaturesMandatory;
- }
-
- @Override
- public void setSkipTableFeatures(boolean skipTableFeaturesValue) {
- skipTableFeatures = skipTableFeaturesValue;
- }
-
- @Override
- public void setBarrierCountLimit(final int barrierCountLimit) {
- this.barrierCountLimit = barrierCountLimit;
- }
-
- @Override
- public void setBarrierInterval(final long barrierTimeoutLimit) {
- this.barrierIntervalNanos = TimeUnit.MILLISECONDS.toNanos(barrierTimeoutLimit);
- }
-
- @Override
- public CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(@Nonnull final KeyedInstanceIdentifier<Node, NodeKey> ii) {
+ public CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final KeyedInstanceIdentifier<Node, NodeKey> ii) {
final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
delWtx.delete(LogicalDatastoreType.OPERATIONAL, ii);
final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
final OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration =
connectionContext.getConnectionAdapter().registerOutboundQueueHandler(
outboundQueueProvider,
- barrierCountLimit,
- barrierIntervalNanos);
+ config.getBarrierCountLimit().getValue(),
+ TimeUnit.MILLISECONDS.toNanos(config.getBarrierIntervalTimeoutLimit().getValue()));
connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
dataBroker,
messageSpy,
translatorLibrary,
- this,
convertorExecutor,
- skipTableFeatures,
+ config.isSkipTableFeatures(),
hashedWheelTimer,
- useSingleLayerSerialization,
- deviceInitializerProvider);
+ config.isUseSingleLayerSerialization(),
+ deviceInitializerProvider,
+ config.isEnableFlowRemovedNotification(),
+ config.isSwitchFeaturesMandatory());
deviceContext.setSalRoleService(new SalRoleServiceImpl(deviceContext, deviceContext));
- deviceContext.setSwitchFeaturesMandatory(switchFeaturesMandatory);
((ExtensionConverterProviderKeeper) deviceContext).setExtensionConverterProvider(extensionConverterProvider);
deviceContext.setNotificationPublishService(notificationPublishService);
synchronized (deviceContexts) {
final int deviceContextsSize = deviceContexts.size();
if (deviceContextsSize > 0) {
- long freshNotificationLimit = globalNotificationQuota / deviceContextsSize;
+ long freshNotificationLimit = config.getGlobalNotificationQuota() / deviceContextsSize;
if (freshNotificationLimit < 100) {
freshNotificationLimit = 100;
}
DeviceStateUtil.setDeviceStateBasedOnV13Capabilities(deviceState, capabilities);
// First process description reply, write data to DS and write consequent data if successful
- return Futures.transformAsync(
+ return Futures.transformAsync(
requestMultipart(MultipartType.OFPMPDESC, deviceContext),
(AsyncFunction<RpcResult<List<OfHeader>>, Void>) input -> {
translateAndWriteResult(
private static final String ASYNC_SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.AsyncServiceCloseEntityType";
private final Map<DeviceInfo, ContextChain> contextChainMap = Collections.synchronizedMap(new HashMap<>());
+ private final EntityOwnershipListenerRegistration eosListenerRegistration;
+ private final ClusterSingletonServiceProvider singletonServiceProvider;
+ private final ItemScheduler<DeviceInfo, ContextChain> scheduler;
+ private final ExecutorService executorService;
private DeviceManager deviceManager;
private RpcManager rpcManager;
private StatisticsManager statisticsManager;
- private EntityOwnershipListenerRegistration eosListenerRegistration;
- private ClusterSingletonServiceProvider singletonServicesProvider;
- private final ItemScheduler<DeviceInfo, ContextChain> scheduler;
- private final ExecutorService executorService;
- public ContextChainHolderImpl(final HashedWheelTimer timer, final ExecutorService executorService) {
+ public ContextChainHolderImpl(final HashedWheelTimer timer,
+ final ExecutorService executorService,
+ final ClusterSingletonServiceProvider singletonServiceProvider,
+ final EntityOwnershipService entityOwnershipService) {
+ this.singletonServiceProvider = singletonServiceProvider;
+ this.executorService = executorService;
+ this.eosListenerRegistration = Verify.verifyNotNull(entityOwnershipService.registerListener
+ (ASYNC_SERVICE_ENTITY_TYPE, this));
+
this.scheduler = new ItemScheduler<>(
timer,
CHECK_ROLE_MASTER_TIMEOUT,
CHECK_ROLE_MASTER_TOLERANCE,
ContextChain::makeDeviceSlave);
-
- this.executorService = executorService;
}
@Override
scheduler.add(deviceInfo, contextChain);
scheduler.startIfNotRunning();
deviceContext.onPublished();
- contextChain.registerServices(this.singletonServicesProvider);
+ contextChain.registerServices(singletonServiceProvider);
return contextChain;
}
return ConnectionStatus.MAY_CONTINUE;
}
- @Override
- public void addSingletonServicesProvider(final ClusterSingletonServiceProvider singletonServicesProvider) {
- this.singletonServicesProvider = singletonServicesProvider;
- }
-
@Override
public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason, final boolean mandatory) {
LOG.warn("Not able to set MASTER role on device {}, reason: {}", deviceInfo.getLOGValue(), reason);
});
}
- @Override
- public void changeEntityOwnershipService(@Nonnull final EntityOwnershipService entityOwnershipService) {
- if (Objects.nonNull(this.eosListenerRegistration)) {
- LOG.warn("Entity ownership service listener is already registered.");
- } else {
- this.eosListenerRegistration = Verify.verifyNotNull(entityOwnershipService.registerListener
- (ASYNC_SERVICE_ENTITY_TYPE, this));
- }
- }
-
@VisibleForTesting
boolean checkAllManagers() {
return Objects.nonNull(deviceManager) && Objects.nonNull(rpcManager) && Objects.nonNull(statisticsManager);
});
contextChainMap.clear();
-
-
- if (Objects.nonNull(eosListenerRegistration)) {
- eosListenerRegistration.close();
- eosListenerRegistration = null;
- }
+ eosListenerRegistration.close();
}
@Override
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RpcManagerImpl implements RpcManager {
private static final Logger LOG = LoggerFactory.getLogger(RpcManagerImpl.class);
+ private final OpenflowProviderConfig config;
private final RpcProviderRegistry rpcProviderRegistry;
- private int rpcRequestQuota;
private final ConcurrentMap<DeviceInfo, RpcContext> contexts = new ConcurrentHashMap<>();
- private boolean isStatisticsRpcEnabled;
private final ExtensionConverterProvider extensionConverterProvider;
private final ConvertorExecutor convertorExecutor;
private final NotificationPublishService notificationPublishService;
- public RpcManagerImpl(final RpcProviderRegistry rpcProviderRegistry,
+ public RpcManagerImpl(final OpenflowProviderConfig config,
+ final RpcProviderRegistry rpcProviderRegistry,
final ExtensionConverterProvider extensionConverterProvider,
final ConvertorExecutor convertorExecutor,
final NotificationPublishService notificationPublishService) {
+ this.config = config;
this.rpcProviderRegistry = rpcProviderRegistry;
this.extensionConverterProvider = extensionConverterProvider;
this.convertorExecutor = convertorExecutor;
}
}
-
- @Override
- public void setStatisticsRpcEnabled(boolean statisticsRpcEnabled) {
- isStatisticsRpcEnabled = statisticsRpcEnabled;
- }
-
- @Override
- public void setRpcRequestQuota(final int rpcRequestQuota) {
- this.rpcRequestQuota = rpcRequestQuota;
- }
-
public RpcContext createContext(final @Nonnull DeviceInfo deviceInfo, final @Nonnull DeviceContext deviceContext) {
final RpcContextImpl rpcContext = new RpcContextImpl(
rpcProviderRegistry,
- rpcRequestQuota,
+ config.getRpcRequestsQuota().getValue(),
deviceContext,
extensionConverterProvider,
convertorExecutor,
notificationPublishService,
- this.isStatisticsRpcEnabled);
+ config.isIsStatisticsRpcEnabled());
contexts.put(deviceInfo, rpcContext);
return rpcContext;
import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.ChangeStatisticsWorkModeInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutputBuilder;
private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class);
private static final long DEFAULT_STATS_TIMEOUT_SEC = 50L;
+ @Nonnull
+ private final OpenflowProviderConfig config;
private final ConvertorExecutor converterExecutor;
private final ConcurrentMap<DeviceInfo, StatisticsContext> contexts = new ConcurrentHashMap<>();
- private long basicTimerDelay;
private long currentTimerDelay;
- private long maximumTimerDelay; //wait time for next statistics
-
private StatisticsWorkMode workMode = StatisticsWorkMode.COLLECTALL;
private final Semaphore workModeGuard = new Semaphore(1, true);
private boolean isStatisticsPollingOn;
private final HashedWheelTimer hashedWheelTimer;
- public StatisticsManagerImpl(@Nonnull final RpcProviderRegistry rpcProviderRegistry,
+ public StatisticsManagerImpl(@Nonnull final OpenflowProviderConfig config,
+ @Nonnull final RpcProviderRegistry rpcProviderRegistry,
final HashedWheelTimer hashedWheelTimer,
final ConvertorExecutor convertorExecutor) {
+ this.config = config;
+ currentTimerDelay = config.getBasicTimerDelay().getValue();
this.converterExecutor = convertorExecutor;
this.controlServiceRegistration = Preconditions.checkNotNull(rpcProviderRegistry
.addRpcImplementation(StatisticsManagerControlService.class, this));
final long averageStatisticsGatheringTime = timeCounter.getAverageTimeBetweenMarks();
if (averageStatisticsGatheringTime > currentTimerDelay) {
currentTimerDelay *= 2;
- if (currentTimerDelay > maximumTimerDelay) {
- currentTimerDelay = maximumTimerDelay;
+ if (currentTimerDelay > config.getMaximumTimerDelay().getValue()) {
+ currentTimerDelay = config.getMaximumTimerDelay().getValue();
}
} else {
- if (currentTimerDelay > basicTimerDelay) {
+ if (currentTimerDelay > config.getBasicTimerDelay().getValue()) {
currentTimerDelay /= 2;
} else {
- currentTimerDelay = basicTimerDelay;
+ currentTimerDelay = config.getBasicTimerDelay().getValue();
}
}
}
}
}
- @Override
- public void setIsStatisticsPollingOn(boolean isStatisticsPollingOn){
- this.isStatisticsPollingOn = isStatisticsPollingOn;
- }
-
@Override
public StatisticsContext createContext(@Nonnull final DeviceContext deviceContext) {
LOG.debug("Statistics context removed for node {}", deviceInfo.getLOGValue());
}
}
-
- @Override
- public void setBasicTimerDelay(final long basicTimerDelay) {
- this.basicTimerDelay = basicTimerDelay;
- this.currentTimerDelay = basicTimerDelay;
- }
-
- @Override
- public void setMaximumTimerDelay(final long maximumTimerDelay) {
- this.maximumTimerDelay = maximumTimerDelay;
- }
}
package org.opendaylight.openflowplugin.impl.util;
import java.net.InetSocketAddress;
+import java.util.Collections;
import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
}
/**
- * Create specified number of empty tables on device
+ * Merge empty nodes to operational DS to predict any problems with missing parent for node.
+ *
+ * @param dataBroker the data broker
+ */
+ public static void makeEmptyNodes(final DataBroker dataBroker) {
+ final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+
+ try {
+ tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), new NodesBuilder()
+ .setNode(Collections.emptyList())
+ .build());
+ tx.submit().get();
+ } catch (ExecutionException | InterruptedException e) {
+ LOG.error("Creation of node failed.", e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Create specified number of empty tables on device.
* FIXME: remove after ovs table features fix
- * @param txFacade transaction facade
+ *
+ * @param txFacade transaction facade
* @param deviceInfo device info
* @param nrOfTables number of tables
*/
}
/**
- * Retrieve ip address from connection
- * @param connectionContext connection context
+ * Retrieve ip address from connection.
+ *
+ * @param connectionContext connection context
* @param instanceIdentifier instance identifier
* @return ip address
*/
}
/**
- * Retrieve port number from connection
- * @param connectionContext connection context
+ * Retrieve port number from connection.
+ *
+ * @param connectionContext connection context
* @param instanceIdentifier instance identifier
* @return port number
*/
}
/**
- * Retrieve switch features from connection
+ * Retrieve switch features from connection.
+ *
* @param connectionContext connection context
* @return switch features
*/
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
<bean id="ofPluginProviderFactory" class="org.opendaylight.openflowplugin.impl.OpenFlowPluginProviderFactoryImpl"/>
+ <service ref="ofPluginProviderFactory" interface="org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory"/>
- <service ref="ofPluginProviderFactory" interface="org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory"
- odl:type="default"/>
-
+ <bean id="configurationServiceFactory" class="org.opendaylight.openflowplugin.impl.configuration.ConfigurationServiceFactoryImpl"/>
+ <service ref="configurationServiceFactory" interface="org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory"/>
</blueprint>
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
-import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService.PropertyType;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.StatisticsManagerControlService;
@RunWith(MockitoJUnitRunner.class)
@Mock
ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+ @Mock
+ ConfigurationService configurationService;
+
private static final int RPC_REQUESTS_QUOTA = 500;
private static final long GLOBAL_NOTIFICATION_QUOTA = 131072;
private static final int THREAD_POOL_MIN_THREADS = 1;
private static final int THREAD_POOL_MAX_THREADS = 32000;
private static final long THREAD_POOL_TIMEOUT = 60;
+ private static final long BASIC_TIMER_DELAY = 1L;
+ private static final boolean USE_SINGLE_LAYER_SERIALIZATION = false;
private OpenFlowPluginProviderImpl provider;
when(entityOwnershipService.registerListener(any(), any())).thenReturn(entityOwnershipListenerRegistration);
when(rpcProviderRegistry.addRpcImplementation(eq(StatisticsManagerControlService.class), any())).thenReturn(controlServiceRegistration);
when(switchConnectionProvider.startup()).thenReturn(Futures.immediateCheckedFuture(null));
+ when(configurationService.getProperty(eq(ConfigurationProperty.USE_SINGLE_LAYER_SERIALIZATION.toString()), any())).thenReturn(USE_SINGLE_LAYER_SERIALIZATION);
+ when(configurationService.getProperty(eq(ConfigurationProperty.THREAD_POOL_MIN_THREADS.toString()), any())).thenReturn(THREAD_POOL_MIN_THREADS);
+ when(configurationService.getProperty(eq(ConfigurationProperty.THREAD_POOL_MAX_THREADS.toString()), any())).thenReturn(THREAD_POOL_MAX_THREADS);
+ when(configurationService.getProperty(eq(ConfigurationProperty.THREAD_POOL_TIMEOUT.toString()), any())).thenReturn(THREAD_POOL_TIMEOUT);
+ when(configurationService.getProperty(eq(ConfigurationProperty.RPC_REQUESTS_QUOTA.toString()), any())).thenReturn(RPC_REQUESTS_QUOTA);
+ when(configurationService.getProperty(eq(ConfigurationProperty.GLOBAL_NOTIFICATION_QUOTA.toString()), any())).thenReturn(GLOBAL_NOTIFICATION_QUOTA);
+ when(configurationService.getProperty(eq(ConfigurationProperty.BASIC_TIMER_DELAY.toString()), any())).thenReturn(BASIC_TIMER_DELAY);
provider = new OpenFlowPluginProviderImpl(
+ configurationService,
Lists.newArrayList(switchConnectionProvider),
dataBroker,
rpcProviderRegistry,
notificationPublishService,
clusterSingletonServiceProvider,
entityOwnershipService);
-
- provider.updateProperty(PropertyType.THREAD_POOL_MIN_THREADS, THREAD_POOL_MIN_THREADS);
- provider.updateProperty(PropertyType.THREAD_POOL_MAX_THREADS, THREAD_POOL_MAX_THREADS);
- provider.updateProperty(PropertyType.THREAD_POOL_TIMEOUT, THREAD_POOL_TIMEOUT);
- provider.updateProperty(PropertyType.RPC_REQUESTS_QUOTA, RPC_REQUESTS_QUOTA);
- provider.updateProperty(PropertyType.GLOBAL_NOTIFICATION_QUOTA, GLOBAL_NOTIFICATION_QUOTA);
- }
-
- @After
- public void tearDown() throws Exception {
-
}
@Test
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
@Captor
private ArgumentCaptor<OpenflowProtocolListener> ofpListenerAC;
- private final static int ECHO_REPLY_TIMEOUT = 500;
+ private final static long ECHO_REPLY_TIMEOUT = 500;
/**
* before each test method
60L, TimeUnit.SECONDS,
new SynchronousQueue<>(), "ofppool");
- connectionManagerImpl = new ConnectionManagerImpl(threadPool);
- connectionManagerImpl.setEchoReplyTimeout(ECHO_REPLY_TIMEOUT);
+ connectionManagerImpl = new ConnectionManagerImpl(new OpenflowProviderConfigBuilder()
+ .setEchoReplyTimeout(new NonZeroUint32Type(ECHO_REPLY_TIMEOUT))
+ .build(), threadPool);
+
connectionManagerImpl.setDeviceConnectedHandler(deviceConnectedHandler);
final InetSocketAddress deviceAddress = InetSocketAddress.createUnresolved("yahoo", 42);
Mockito.when(connection.getRemoteAddress()).thenReturn(deviceAddress);
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import io.netty.util.HashedWheelTimer;
-import io.netty.util.Timeout;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.InOrder;
-import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
-import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Mock
TranslatorLibrary translatorLibrary;
@Mock
- Registration registration;
- @Mock
MessageTranslator messageTranslatorPacketReceived;
@Mock
MessageTranslator messageTranslatorFlowCapableNodeConnector;
@Mock
private DeviceInfo deviceInfo;
@Mock
- private DeviceManager deviceManager;
- @Mock
private ConvertorExecutor convertorExecutor;
@Mock
private MessageSpy messageSpy;
- private InOrder inOrderDevState;
-
private final AtomicLong atomicLong = new AtomicLong(0);
private DeviceContext deviceContextSpy;
dataBroker,
messageSpy,
translatorLibrary,
- deviceManager,
convertorExecutor,
false, timer, false,
- DeviceInitializerProviderFactory.createDefaultProvider());
+ DeviceInitializerProviderFactory.createDefaultProvider(),
+ true, false);
((DeviceContextImpl) deviceContext).lazyTransactionManagerInitialization();
deviceContextSpy = Mockito.spy(deviceContext);
assertEquals(translatorLibrary, pickedTranslatorLibrary);
}
- @Test
- public void testBarrierFieldSetGet() {
- final Timeout mockedTimeout = mock(Timeout.class);
- deviceContext.setCurrentBarrierTimeout(mockedTimeout);
- final Timeout pickedBarrierTimeout = deviceContext.getBarrierTaskTimeout();
- assertEquals(mockedTimeout, pickedBarrierTimeout);
- }
-
@Test
public void testGetMessageSpy() {
final MessageSpy pickedMessageSpy = deviceContext.getMessageSpy();
.child(Table.class, new TableKey((short) 0))
.child(Flow.class, new FlowKey(new FlowId("ut-ofp:f456")));
- Mockito.when(deviceManager.isFlowRemovedNotificationOn()).thenReturn(true);
-
deviceContext.setNotificationPublishService(mockedNotificationPublishService);
deviceContext.processFlowRemovedMessage(flowRemovedBld.build());
Mockito.verify(itemLifecycleListener).onRemoved(flowToBeRemovedPath);
-
- Mockito.when(deviceManager.isFlowRemovedNotificationOn()).thenReturn(false);
- deviceContext.processFlowRemovedMessage(flowRemovedBld.build());
-
- Mockito.verify(mockedNotificationPublishService).offerNotification(Matchers.any(Notification.class));
}
@Test
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder;
@RunWith(MockitoJUnitRunner.class)
public class DeviceManagerImplTest {
private static final long TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA = 2000L;
private static final int barrierCountLimit = 25600;
- private static final int barrierIntervalNanos = 500;
+ private static final long barrierIntervalNanos = 500;
private static final NodeId DUMMY_NODE_ID = new NodeId("dummyNodeId");
@Mock
when(mockedWriteTransaction.submit()).thenReturn(mockedFuture);
final DeviceManagerImpl deviceManager = new DeviceManagerImpl(
+ new OpenflowProviderConfigBuilder()
+ .setBarrierCountLimit(new NonZeroUint16Type(barrierCountLimit))
+ .setBarrierIntervalTimeoutLimit(new NonZeroUint32Type(barrierIntervalNanos))
+ .setGlobalNotificationQuota(TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA)
+ .setSwitchFeaturesMandatory(false)
+ .setEnableFlowRemovedNotification(true)
+ .setSkipTableFeatures(false)
+ .build(),
mockedDataBroker,
messageIntelligenceAgency,
null,
new HashedWheelTimer(),
convertorExecutor,
- DeviceInitializerProviderFactory.createDefaultProvider(),
- false);
-
- deviceManager.setBarrierCountLimit(barrierCountLimit);
- deviceManager.setBarrierInterval(barrierIntervalNanos);
- deviceManager.setGlobalNotificationQuota(TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA);
- deviceManager.setSwitchFeaturesMandatory(false);
- deviceManager.setFlowRemovedNotificationOn(true);
- deviceManager.setSkipTableFeatures(false);
+ DeviceInitializerProviderFactory.createDefaultProvider());
return deviceManager;
}
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
private ExecutorService executorService;
@Mock
private ClusterSingletonServiceRegistration clusterSingletonServiceRegistration;
+ @Mock
+ private EntityOwnershipService entityOwnershipService;
+ @Mock
+ private EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
private ContextChainHolderImpl contextChainHolder;
Mockito.when(singletonServicesProvider.registerClusterSingletonService(Mockito.any()))
.thenReturn(clusterSingletonServiceRegistration);
- contextChainHolder = new ContextChainHolderImpl(timer, executorService);
+ Mockito.when(entityOwnershipService.registerListener(Mockito.any(), Mockito.any()))
+ .thenReturn(entityOwnershipListenerRegistration);
+
+ contextChainHolder = new ContextChainHolderImpl(timer, executorService, singletonServicesProvider, entityOwnershipService);
contextChainHolder.addManager(statisticsManager);
contextChainHolder.addManager(rpcManager);
contextChainHolder.addManager(deviceManager);
- contextChainHolder.addSingletonServicesProvider(singletonServicesProvider);
}
@Test
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
@Before
public void setUp() {
final NodeKey nodeKey = new NodeKey(nodeId);
- rpcManager = new RpcManagerImpl(rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService);
- rpcManager.setRpcRequestQuota(QUOTA_VALUE);
+ rpcManager = new RpcManagerImpl(new OpenflowProviderConfigBuilder()
+ .setRpcRequestsQuota(new NonZeroUint16Type(QUOTA_VALUE))
+ .build(), rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService);
GetFeaturesOutput featuresOutput = new GetFeaturesOutputBuilder()
.setVersion(OFConstants.OFP_VERSION_1_3)
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.ChangeStatisticsWorkModeInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.StatisticsManagerControlService;
final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
final long basicTimerDelay = 3000L;
final long maximumTimerDelay = 900000L;
- statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, new HashedWheelTimer(),
+
+ statisticsManager = new StatisticsManagerImpl(
+ new OpenflowProviderConfigBuilder()
+ .setBasicTimerDelay(new NonZeroUint32Type(basicTimerDelay))
+ .setMaximumTimerDelay(new NonZeroUint32Type(maximumTimerDelay))
+ .setIsStatisticsPollingOn(false)
+ .build(), rpcProviderRegistry, new HashedWheelTimer(),
convertorManager);
- statisticsManager.setBasicTimerDelay(basicTimerDelay);
- statisticsManager.setMaximumTimerDelay(maximumTimerDelay);
- statisticsManager.setIsStatisticsPollingOn(false);
}
private static Map<DeviceInfo, StatisticsContext> getContextsMap(final StatisticsManagerImpl statisticsManager)