/*
* Copyright (c) 2013 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.openflowjava.protocol.impl.core;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFGeneralDeserializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFGeneralSerializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
import org.opendaylight.openflowjava.protocol.api.keys.ActionSerializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterActionDeserializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterDeserializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdDeserializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdMeterSubTypeSerializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdSerializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterInstructionDeserializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterSerializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.InstructionSerializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializationFactory;
import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializerRegistryImpl;
import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
import org.opendaylight.openflowjava.protocol.impl.serialization.SerializerRegistryImpl;
import org.opendaylight.openflowjava.protocol.api.keys.TypeToClassKey;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.TransportProtocol;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Exposed class for server handling
* C - {@link MatchEntrySerializerKey} parameter representing oxm_class (see specification)
* F - {@link MatchEntrySerializerKey} parameter representing oxm_field (see specification)
* @author mirehak
* @author michal.polkorab
*/
public class SwitchConnectionProviderImpl implements SwitchConnectionProvider, ConnectionInitializer {
private static final Logger LOG = LoggerFactory
.getLogger(SwitchConnectionProviderImpl.class);
private SwitchConnectionHandler switchConnectionHandler;
private ServerFacade serverFacade;
private ConnectionConfiguration connConfig;
private final SerializationFactory serializationFactory;
private final SerializerRegistry serializerRegistry;
private final DeserializerRegistry deserializerRegistry;
private final DeserializationFactory deserializationFactory;
private TcpConnectionInitializer connectionInitializer;
/** Constructor */
public SwitchConnectionProviderImpl() {
serializerRegistry = new SerializerRegistryImpl();
serializerRegistry.init();
serializationFactory = new SerializationFactory();
serializationFactory.setSerializerTable(serializerRegistry);
deserializerRegistry = new DeserializerRegistryImpl();
deserializerRegistry.init();
deserializationFactory = new DeserializationFactory();
deserializationFactory.setRegistry(deserializerRegistry);
}
@Override
public void setConfiguration(final ConnectionConfiguration connConfig) {
this.connConfig = connConfig;
}
@Override
public void setSwitchConnectionHandler(final SwitchConnectionHandler switchConnectionHandler) {
LOG.debug("setSwitchConnectionHandler");
this.switchConnectionHandler = switchConnectionHandler;
}
@Override
public ListenableFuture shutdown() {
LOG.debug("Shutdown summoned");
if(serverFacade == null){
LOG.warn("Can not shutdown - not configured or started");
throw new IllegalStateException("SwitchConnectionProvider is not started or not configured.");
}
return serverFacade.shutdown();
}
@Override
public ListenableFuture startup() {
LOG.debug("Startup summoned");
ListenableFuture result = null;
try {
serverFacade = createAndConfigureServer();
if (switchConnectionHandler == null) {
throw new IllegalStateException("SwitchConnectionHandler is not set");
}
new Thread(serverFacade).start();
result = serverFacade.getIsOnlineFuture();
} catch (final Exception e) {
final SettableFuture exResult = SettableFuture.create();
exResult.setException(e);
result = exResult;
}
return result;
}
/**
* @return
*/
private ServerFacade createAndConfigureServer() {
LOG.debug("Configuring ..");
ServerFacade server = null;
final ChannelInitializerFactory factory = new ChannelInitializerFactory();
factory.setSwitchConnectionHandler(switchConnectionHandler);
factory.setSwitchIdleTimeout(connConfig.getSwitchIdleTimeout());
factory.setTlsConfig(connConfig.getTlsConfiguration());
factory.setSerializationFactory(serializationFactory);
factory.setDeserializationFactory(deserializationFactory);
factory.setUseBarrier(connConfig.useBarrier());
final TransportProtocol transportProtocol = (TransportProtocol) connConfig.getTransferProtocol();
// Check if Epoll native transport is available.
// TODO : Add option to disable Epoll.
boolean isEpollEnabled = Epoll.isAvailable();
if (transportProtocol.equals(TransportProtocol.TCP) || transportProtocol.equals(TransportProtocol.TLS)) {
server = new TcpHandler(connConfig.getAddress(), connConfig.getPort());
final TcpChannelInitializer channelInitializer = factory.createPublishingChannelInitializer();
((TcpHandler) server).setChannelInitializer(channelInitializer);
((TcpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled);
final EventLoopGroup workerGroupFromTcpHandler = ((TcpHandler) server).getWorkerGroup();
connectionInitializer = new TcpConnectionInitializer(workerGroupFromTcpHandler, isEpollEnabled);
connectionInitializer.setChannelInitializer(channelInitializer);
connectionInitializer.run();
} else if (transportProtocol.equals(TransportProtocol.UDP)){
server = new UdpHandler(connConfig.getAddress(), connConfig.getPort());
((UdpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled);
((UdpHandler) server).setChannelInitializer(factory.createUdpChannelInitializer());
} else {
throw new IllegalStateException("Unknown transport protocol received: " + transportProtocol);
}
server.setThreadConfig(connConfig.getThreadConfiguration());
return server;
}
/**
* @return servers
*/
public ServerFacade getServerFacade() {
return serverFacade;
}
@Override
public void close() throws Exception {
shutdown();
}
@Override
public boolean unregisterSerializer(final ExperimenterSerializerKey key) {
return serializerRegistry.unregisterSerializer((MessageTypeKey>) key);
}
@Override
public boolean unregisterDeserializer(final ExperimenterDeserializerKey key) {
return deserializerRegistry.unregisterDeserializer((MessageCodeKey) key);
}
@Override
public void registerActionSerializer(final ActionSerializerKey> key,
final OFGeneralSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerActionDeserializer(final ExperimenterActionDeserializerKey key,
final OFGeneralDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerInstructionSerializer(final InstructionSerializerKey> key,
final OFGeneralSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerInstructionDeserializer(final ExperimenterInstructionDeserializerKey key,
final OFGeneralDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerMatchEntrySerializer(final MatchEntrySerializerKey key,
final OFGeneralSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerMatchEntryDeserializer(final MatchEntryDeserializerKey key,
final OFGeneralDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerErrorDeserializer(final ExperimenterIdDeserializerKey key,
final OFDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerExperimenterMessageDeserializer(ExperimenterIdDeserializerKey key,
OFDeserializer extends ExperimenterDataOfChoice> deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerMultipartReplyMessageDeserializer(ExperimenterIdDeserializerKey key,
OFDeserializer extends ExperimenterDataOfChoice> deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerMultipartReplyTFDeserializer(final ExperimenterIdDeserializerKey key,
final OFGeneralDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerQueuePropertyDeserializer(final ExperimenterIdDeserializerKey key,
final OFDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerMeterBandDeserializer(final ExperimenterIdDeserializerKey key,
final OFDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerExperimenterMessageSerializer(ExperimenterIdSerializerKey extends ExperimenterDataOfChoice> key,
OFSerializer extends ExperimenterDataOfChoice> serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerMultipartRequestSerializer(ExperimenterIdSerializerKey extends ExperimenterDataOfChoice> key,
OFSerializer extends ExperimenterDataOfChoice> serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerMultipartRequestTFSerializer(final ExperimenterIdSerializerKey key,
final OFGeneralSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
/**
* @deprecated Since we have used ExperimenterIdMeterSubTypeSerializerKey as MeterBandSerializer's key, in order to avoid
* the occurrence of an error, we should discard this function
*/
@Deprecated
public void registerMeterBandSerializer(final ExperimenterIdSerializerKey key,
final OFSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerMeterBandSerializer(final ExperimenterIdMeterSubTypeSerializerKey key,
final OFSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void initiateConnection(final String host, final int port) {
connectionInitializer.initiateConnection(host, port);
}
@Override
public ConnectionConfiguration getConfiguration() {
return this.connConfig;
}
@Override
public void registerSerializer(MessageTypeKey key, OFGeneralSerializer serializer) {
serializerRegistry.registerSerializer(key, serializer);
}
@Override
public void registerDeserializer(MessageCodeKey key, OFGeneralDeserializer deserializer) {
deserializerRegistry.registerDeserializer(key, deserializer);
}
@Override
public void registerDeserializerMapping(final TypeToClassKey key, final Class> clazz) {
deserializationFactory.registerMapping(key, clazz);
}
@Override
public boolean unregisterDeserializerMapping(final TypeToClassKey key) {
return deserializationFactory.unregisterMapping(key);
}
}