--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.openflowjava.protocol.impl.core;
+
+import static java.util.Objects.requireNonNull;
+
+import java.net.InetAddress;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
+import org.opendaylight.openflowjava.protocol.api.connection.ThreadConfiguration;
+import org.opendaylight.openflowjava.protocol.api.connection.TlsConfiguration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.KeystoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.TransportProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506._switch.connection.config.Threads;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506._switch.connection.config.Tls;
+
+final class ConnectionConfigurationImpl implements ConnectionConfiguration {
+ private final SwitchConnectionConfig config;
+ private final InetAddress address;
+
+ ConnectionConfigurationImpl(final SwitchConnectionConfig config) {
+ this.config = requireNonNull(config);
+ final var addr = config.getAddress();
+ address = addr != null ? IetfInetUtil.inetAddressFor(addr) : null;
+ }
+
+ @Override
+ public InetAddress getAddress() {
+ return address;
+ }
+
+ @Override
+ public int getPort() {
+ return config.getPort().toJava();
+ }
+
+ @Override
+ public Object getTransferProtocol() {
+ return config.getTransportProtocol();
+ }
+
+ @Override
+ public int getChannelOutboundQueueSize() {
+ return config.getChannelOutboundQueueSize().toJava();
+ }
+
+ @Override
+ public TlsConfiguration getTlsConfiguration() {
+ final Tls tlsConfig = config.getTls();
+ if (tlsConfig == null || !TransportProtocol.TLS.equals(getTransferProtocol())) {
+ return null;
+ }
+
+ return new TlsConfiguration() {
+ @Override
+ public KeystoreType getTlsTruststoreType() {
+ return requireNonNull(tlsConfig.getTruststoreType());
+ }
+
+ @Override
+ public String getTlsTruststore() {
+ return requireNonNull(tlsConfig.getTruststore());
+ }
+
+ @Override
+ public KeystoreType getTlsKeystoreType() {
+ return requireNonNull(tlsConfig.getKeystoreType());
+ }
+
+ @Override
+ public String getTlsKeystore() {
+ return requireNonNull(tlsConfig.getKeystore());
+ }
+
+ @Override
+ public org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType
+ getTlsKeystorePathType() {
+ return requireNonNull(tlsConfig.getKeystorePathType());
+ }
+
+ @Override
+ public org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType
+ getTlsTruststorePathType() {
+ return requireNonNull(tlsConfig.getTruststorePathType());
+ }
+
+ @Override
+ public String getKeystorePassword() {
+ return requireNonNull(tlsConfig.getKeystorePassword());
+ }
+
+ @Override
+ public String getCertificatePassword() {
+ return requireNonNull(tlsConfig.getCertificatePassword());
+ }
+
+ @Override
+ public String getTruststorePassword() {
+ return requireNonNull(tlsConfig.getTruststorePassword());
+ }
+
+ @Override
+ public List<String> getCipherSuites() {
+ return tlsConfig.getCipherSuites();
+ }
+ };
+ }
+
+ @Override
+ public long getSwitchIdleTimeout() {
+ return config.getSwitchIdleTimeout().toJava();
+ }
+
+ @Override
+ public Object getSslContext() {
+ return null;
+ }
+
+ @Override
+ public ThreadConfiguration getThreadConfiguration() {
+ final Threads threads = config.getThreads();
+ if (threads == null) {
+ return null;
+ }
+
+ return new ThreadConfiguration() {
+ @Override
+ public int getWorkerThreadCount() {
+ return threads.getWorkerThreads().toJava();
+ }
+
+ @Override
+ public int getBossThreadCount() {
+ return threads.getBossThreads().toJava();
+ }
+ };
+ }
+
+ @Override
+ public boolean useBarrier() {
+ return config.getUseBarrier();
+ }
+
+ @Override
+ public boolean isGroupAddModEnabled() {
+ return config.getGroupAddModEnabled();
+ }
+}
\ No newline at end of file
import static java.util.Objects.requireNonNull;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.infrautils.diagstatus.DiagStatusService;
-import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
-import org.opendaylight.openflowjava.protocol.api.connection.ThreadConfiguration;
-import org.opendaylight.openflowjava.protocol.api.connection.TlsConfiguration;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderFactory;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.KeystoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.TransportProtocol;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506._switch.connection.config.Threads;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506._switch.connection.config.Tls;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
public SwitchConnectionProvider newInstance(final SwitchConnectionConfig config) {
return new SwitchConnectionProviderImpl(diagStatus, new ConnectionConfigurationImpl(config));
}
-
- private static class ConnectionConfigurationImpl implements ConnectionConfiguration {
- private final SwitchConnectionConfig config;
- private InetAddress address;
-
- ConnectionConfigurationImpl(final SwitchConnectionConfig config) {
- this.config = config;
-
- try {
- address = getInetAddress(config.getAddress());
- } catch (UnknownHostException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public InetAddress getAddress() {
- return address;
- }
-
- @Override
- public int getPort() {
- return config.getPort().toJava();
- }
-
- @Override
- public Object getTransferProtocol() {
- return config.getTransportProtocol();
- }
-
- @Override
- public int getChannelOutboundQueueSize() {
- return config.getChannelOutboundQueueSize().toJava();
- }
-
- @Override
- public TlsConfiguration getTlsConfiguration() {
- final Tls tlsConfig = config.getTls();
- if (tlsConfig == null || !TransportProtocol.TLS.equals(getTransferProtocol())) {
- return null;
- }
-
- return new TlsConfiguration() {
- @Override
- public KeystoreType getTlsTruststoreType() {
- return requireNonNull(tlsConfig.getTruststoreType());
- }
-
- @Override
- public String getTlsTruststore() {
- return requireNonNull(tlsConfig.getTruststore());
- }
-
- @Override
- public KeystoreType getTlsKeystoreType() {
- return requireNonNull(tlsConfig.getKeystoreType());
- }
-
- @Override
- public String getTlsKeystore() {
- return requireNonNull(tlsConfig.getKeystore());
- }
-
- @Override
- public org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType
- getTlsKeystorePathType() {
- return requireNonNull(tlsConfig.getKeystorePathType());
- }
-
- @Override
- public org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType
- getTlsTruststorePathType() {
- return requireNonNull(tlsConfig.getTruststorePathType());
- }
-
- @Override
- public String getKeystorePassword() {
- return requireNonNull(tlsConfig.getKeystorePassword());
- }
-
- @Override
- public String getCertificatePassword() {
- return requireNonNull(tlsConfig.getCertificatePassword());
- }
-
- @Override
- public String getTruststorePassword() {
- return requireNonNull(tlsConfig.getTruststorePassword());
- }
-
- @Override
- public List<String> getCipherSuites() {
- return tlsConfig.getCipherSuites();
- }
- };
- }
-
- @Override
- public long getSwitchIdleTimeout() {
- return config.getSwitchIdleTimeout().toJava();
- }
-
- @Override
- public Object getSslContext() {
- return null;
- }
-
- @Override
- public ThreadConfiguration getThreadConfiguration() {
- final Threads threads = config.getThreads();
- if (threads == null) {
- return null;
- }
-
- return new ThreadConfiguration() {
- @Override
- public int getWorkerThreadCount() {
- return threads.getWorkerThreads().toJava();
- }
-
- @Override
- public int getBossThreadCount() {
- return threads.getBossThreads().toJava();
- }
- };
- }
-
- @Override
- public boolean useBarrier() {
- return config.getUseBarrier();
- }
-
- @Override
- public boolean isGroupAddModEnabled() {
- return config.getGroupAddModEnabled();
- }
-
- private static InetAddress getInetAddress(final IpAddress address) throws UnknownHostException {
- if (address != null) {
- if (address.getIpv4Address() != null) {
- return InetAddress.getByName(address.getIpv4Address().getValue());
- } else if (address.getIpv6Address() != null) {
- return InetAddress.getByName(address.getIpv6Address().getValue());
- }
- }
- return null;
- }
- }
}
import com.google.common.util.concurrent.MoreExecutors;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
+import java.util.Map;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.infrautils.diagstatus.DiagStatusService;
import org.opendaylight.infrautils.diagstatus.ServiceDescriptor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.queue.property.header.QueueProperty;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeatureProperties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author mirehak
* @author michal.polkorab
*/
+@Component(service = SwitchConnectionProvider.class, factory = SwitchConnectionProviderImpl.FACTORY_NAME)
public class SwitchConnectionProviderImpl implements SwitchConnectionProvider, ConnectionInitializer {
private static final Logger LOG = LoggerFactory.getLogger(SwitchConnectionProviderImpl.class);
+
private static final String THREAD_NAME_PREFIX = "OFP-SwitchConnectionProvider-Udp/TcpHandler";
private static final String OPENFLOW_JAVA_SERVICE_NAME_PREFIX = "OPENFLOW_SERVER";
+ // OSGi DS Component Factory name
+ public static final String FACTORY_NAME =
+ "org.opendaylight.openflowjava.protocol.impl.core.SwitchConnectionProviderImpl";
+ public static final String PROP_CONFIG = ".config";
+
private SwitchConnectionHandler switchConnectionHandler;
private ServerFacade serverFacade;
private final ConnectionConfiguration connConfig;
deserializationFactory = new DeserializationFactory(deserializerRegistry);
}
+ @Activate
+ public SwitchConnectionProviderImpl(@Reference final DiagStatusService diagStatus,
+ final Map<String, Object> props) {
+ this(diagStatus, new ConnectionConfigurationImpl((SwitchConnectionConfig) props.get(PROP_CONFIG)));
+ }
+
+ @Deactivate
+ void deactivate() {
+ diagReg.close();
+ }
+
// ID based, on configuration, used for diagstatus serviceIdentifier (ServiceDescriptor moduleServiceName)
private static String createConnectionSuffix(final @Nullable ConnectionConfiguration config) {
return config == null ? "-null-config" : "_" + config.getPort();
<url>https://wiki.opendaylight.org/view/Openflow_Protocol_Library:Main</url>
<tag>HEAD</tag>
</scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jdt</groupId>
+ <artifactId>org.eclipse.jdt.annotation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-common-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.openflowjava</groupId>
+ <artifactId>openflow-protocol-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.openflowjava</groupId>
+ <artifactId>openflow-protocol-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.openflowjava</groupId>
+ <artifactId>openflow-protocol-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>concepts</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.framework</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.component</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.component.annotations</artifactId>
+ </dependency>
+ </dependencies>
+
<build>
<plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <DynamicImport-Package>*</DynamicImport-Package>
- </instructions>
- </configuration>
- </plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.openflowjava.mdsal;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.util.List;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.KeystoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.TransportProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506._switch.connection.config.TlsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint16;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A component responsible for populating default (factory) configuration.
+ */
+@Component(service = { })
+public final class OSGiFactorySwitchConnectionConfiguration {
+ private static final Logger LOG = LoggerFactory.getLogger(OSGiFactorySwitchConnectionConfiguration.class);
+
+ @Activate
+ public OSGiFactorySwitchConnectionConfiguration(@Reference final DataBroker dataBroker) {
+ // Common for both cases
+ final var builder = new SwitchConnectionConfigBuilder()
+ .setTransportProtocol(TransportProtocol.TCP)
+ .setGroupAddModEnabled(Boolean.FALSE)
+ .setChannelOutboundQueueSize(Uint16.valueOf(1024))
+ .setTls(new TlsBuilder()
+ .setKeystore("configuration/ssl/ctl.jks")
+ .setKeystoreType(KeystoreType.JKS)
+ .setKeystorePathType(PathType.PATH)
+ .setKeystorePassword("opendaylight")
+ .setTruststore("configuration/ssl/truststore.jks")
+ .setTruststoreType(KeystoreType.JKS)
+ .setTruststorePathType(PathType.PATH)
+ .setTruststorePassword("opendaylight")
+ .setCertificatePassword("opendaylight")
+ .setCipherSuites(List.of())
+ .build());
+
+ // Create OF switch connection provider on port 6653 (default)
+ writeIfNotPresent(dataBroker, builder
+ .setInstanceName("openflow-switch-connection-provider-default-impl")
+ .setPort(Uint16.valueOf(6653))
+ .build());
+ // Create OF switch connection provider on port 6633 (legacy)
+ writeIfNotPresent(dataBroker, builder
+ .setInstanceName("openflow-switch-connection-provider-legacy-impl")
+ .setPort(Uint16.valueOf(6633))
+ .build());
+ }
+
+ private static void writeIfNotPresent(final DataBroker dataBroker, final SwitchConnectionConfig config) {
+ final var instanceName = config.getInstanceName();
+ LOG.info("Checking presence of configuration for {}", instanceName);
+
+ final var sw = Stopwatch.createStarted();
+ final var iid = InstanceIdentifier.builder(SwitchConnectionConfig.class, config.key()).build();
+ final var tx = dataBroker.newReadWriteTransaction();
+ tx.exists(LogicalDatastoreType.CONFIGURATION, iid).addCallback(new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(final Boolean result) {
+ LOG.debug("Presence of configuration for {} ascertained in {}", instanceName, sw);
+ if (result) {
+ LOG.info("Configuration for {} already present", instanceName);
+ tx.cancel();
+ return;
+ }
+
+ tx.put(LogicalDatastoreType.CONFIGURATION, iid, config);
+ tx.commit().addCallback(new FutureCallback<CommitInfo>() {
+ @Override
+ public void onSuccess(final CommitInfo result) {
+ LOG.info("Configuration for {} set to factory-default", instanceName);
+ }
+
+ @Override
+ public void onFailure(final Throwable cause) {
+ LOG.warn("Failed to set configuration for {} set to factory-default", instanceName, cause);
+ }
+ }, MoreExecutors.directExecutor());
+ }
+
+ @Override
+ public void onFailure(final Throwable cause) {
+ LOG.warn("Failed to ascertain presence of configuration for {} after {}", instanceName, sw, cause);
+ tx.cancel();
+ }
+ }, MoreExecutors.directExecutor());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, 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.openflowjava.mdsal;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.openflowjava.protocol.impl.core.SwitchConnectionProviderImpl;
+import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A component exposing {@link SwitchConnectionProvider} into OSGi service registry based on MD-SAL's configuration
+ * data store contents of {@link SwitchConnectionConfig}.
+ */
+@Component(service = { })
+public final class OSGiSwitchConnectionProviders implements DataTreeChangeListener<SwitchConnectionConfig> {
+ private static final Logger LOG = LoggerFactory.getLogger(OSGiSwitchConnectionProviders.class);
+
+ private final Map<String, ComponentInstance<SwitchConnectionProvider>> instances = new HashMap<>();
+ private final ComponentFactory<SwitchConnectionProvider> providerFactory;
+ private final Registration reg;
+
+ @Activate
+ public OSGiSwitchConnectionProviders(@Reference final DataBroker dataBroker,
+ @Reference(target = "(component.factory=" + SwitchConnectionProviderImpl.FACTORY_NAME + ")")
+ final ComponentFactory<SwitchConnectionProvider> providerFactory) {
+ this.providerFactory = requireNonNull(providerFactory);
+ reg = dataBroker.registerTreeChangeListener(DataTreeIdentifier.of(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(SwitchConnectionConfig.class)), this);
+ LOG.info("MD-SAL configuration-based SwitchConnectionProviders started");
+ }
+
+ @Deactivate
+ synchronized void deactivate() {
+ LOG.info("MD-SAL configuration-based SwitchConnectionProviders stopping");
+ reg.close();
+ instances.forEach((key, instance) -> instance.dispose());
+ instances.clear();
+ LOG.info("MD-SAL configuration-based SwitchConnectionProviders stopped");
+ }
+
+ @Override
+ public synchronized void onDataTreeChanged(final List<DataTreeModification<SwitchConnectionConfig>> changes) {
+ final var apply = new HashMap<String, SwitchConnectionConfig>();
+
+ for (var change : changes) {
+ final var root = change.getRootNode();
+ switch (root.modificationType()) {
+ case DELETE -> apply.put(root.dataBefore().getInstanceName(), null);
+ case SUBTREE_MODIFIED, WRITE -> {
+ final var after = root.dataAfter();
+ apply.put(after.getInstanceName(), after);
+ }
+ default -> LOG.warn("Ignoring unhandled root {}", root);
+ }
+ }
+
+ LOG.debug("Applying {} changes", apply.size());
+ apply.entrySet().stream()
+ .sorted(Comparator.comparing(Entry::getKey))
+ .forEach(entry -> {
+ final var type = entry.getKey();
+ final var prev = instances.remove(type);
+ if (prev != null) {
+ LOG.info("Stopping instance of type '{}'", type);
+ prev.dispose();
+ }
+
+ final var config = entry.getValue();
+ if (config != null) {
+ LOG.info("Starting instance of type '{}'", type);
+ instances.put(type, providerFactory.newInstance(FrameworkUtil.asDictionary(props(type, config))));
+ }
+ });
+ }
+
+ @Override
+ public void onInitialData() {
+ LOG.debug("No configuration is present");
+ }
+
+ private static Map<String, Object> props(final String type, final @Nullable SwitchConnectionConfig config) {
+ return config != null ? Map.of("type", type, SwitchConnectionProviderImpl.PROP_CONFIG, config)
+ : Map.of("type", type);
+ }
+}
+++ /dev/null
-<?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">
- <reference id="switchConnectionProviderFactory" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderFactory"/>
- <!-- Create OF switch connection provider on port 6653 (default) -->
- <odl:clustered-app-config id="defaultSwitchConnConfig" default-config-file-name="default-openflow-connection-config.xml"
- binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig"
- list-key-value="openflow-switch-connection-provider-default-impl">
- </odl:clustered-app-config>
- <bean id="defaultSwitchConnProvider" factory-ref="switchConnectionProviderFactory" factory-method="newInstance">
- <argument ref="defaultSwitchConnConfig"/>
- </bean>
- <service ref="defaultSwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
- odl:type="openflow-switch-connection-provider-default-impl"/>
-
- <!-- Create OF switch connection provider on port 6633 (legacy) -->
- <odl:clustered-app-config id="legacySwitchConnConfig" default-config-file-name="legacy-openflow-connection-config.xml"
- binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig"
- list-key-value="openflow-switch-connection-provider-legacy-impl">
- </odl:clustered-app-config>
- <bean id="legacySwitchConnProvider" factory-ref="switchConnectionProviderFactory" factory-method="newInstance">
- <argument ref="legacySwitchConnConfig"/>
- </bean>
- <service ref="legacySwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
- odl:type="openflow-switch-connection-provider-legacy-impl"/>
-</blueprint>