Bug 3230 - Attempt to use Epoll native transport if available
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / SwitchConnectionProviderImpl.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9
10 package org.opendaylight.openflowjava.protocol.impl.core;
11
12 import com.google.common.util.concurrent.ListenableFuture;
13 import com.google.common.util.concurrent.SettableFuture;
14 import io.netty.channel.EventLoopGroup;
15 import io.netty.channel.epoll.Epoll;
16 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
17 import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
18 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
19 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
20 import org.opendaylight.openflowjava.protocol.api.extensibility.OFGeneralDeserializer;
21 import org.opendaylight.openflowjava.protocol.api.extensibility.OFGeneralSerializer;
22 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
23 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
24 import org.opendaylight.openflowjava.protocol.api.keys.ActionSerializerKey;
25 import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterActionDeserializerKey;
26 import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterDeserializerKey;
27 import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdDeserializerKey;
28 import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdSerializerKey;
29 import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterInstructionDeserializerKey;
30 import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterSerializerKey;
31 import org.opendaylight.openflowjava.protocol.api.keys.InstructionSerializerKey;
32 import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
33 import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
34 import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
35 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
36 import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializationFactory;
37 import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializerRegistryImpl;
38 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
39 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializerRegistryImpl;
40 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.TransportProtocol;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.queue.property.header.QueueProperty;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeatureProperties;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * Exposed class for server handling<br>
54  * C - {@link MatchEntrySerializerKey} parameter representing oxm_class (see specification)<br>
55  * F - {@link MatchEntrySerializerKey} parameter representing oxm_field (see specification)
56  * @author mirehak
57  * @author michal.polkorab
58  */
59 public class SwitchConnectionProviderImpl implements SwitchConnectionProvider, ConnectionInitializer {
60
61     private static final Logger LOGGER = LoggerFactory
62             .getLogger(SwitchConnectionProviderImpl.class);
63     private SwitchConnectionHandler switchConnectionHandler;
64     private ServerFacade serverFacade;
65     private ConnectionConfiguration connConfig;
66     private final SerializationFactory serializationFactory;
67     private final SerializerRegistry serializerRegistry;
68     private final DeserializerRegistry deserializerRegistry;
69     private final DeserializationFactory deserializationFactory;
70     private TcpConnectionInitializer connectionInitializer;
71
72     /** Constructor */
73     public SwitchConnectionProviderImpl() {
74         serializerRegistry = new SerializerRegistryImpl();
75         serializerRegistry.init();
76         serializationFactory = new SerializationFactory();
77         serializationFactory.setSerializerTable(serializerRegistry);
78         deserializerRegistry = new DeserializerRegistryImpl();
79         deserializerRegistry.init();
80         deserializationFactory = new DeserializationFactory();
81         deserializationFactory.setRegistry(deserializerRegistry);
82     }
83
84     @Override
85     public void setConfiguration(final ConnectionConfiguration connConfig) {
86         this.connConfig = connConfig;
87     }
88
89     @Override
90     public void setSwitchConnectionHandler(final SwitchConnectionHandler switchConnectionHandler) {
91         LOGGER.debug("setSwitchConnectionHandler");
92         this.switchConnectionHandler = switchConnectionHandler;
93     }
94
95     @Override
96     public ListenableFuture<Boolean> shutdown() {
97         LOGGER.debug("Shutdown summoned");
98         if(serverFacade == null){
99             LOGGER.warn("Can not shutdown - not configured or started");
100             throw new IllegalStateException("SwitchConnectionProvider is not started or not configured.");
101         }
102         return serverFacade.shutdown();
103     }
104
105     @Override
106     public ListenableFuture<Boolean> startup() {
107         LOGGER.debug("Startup summoned");
108         ListenableFuture<Boolean> result = null;
109         try {
110             serverFacade = createAndConfigureServer();
111             if (switchConnectionHandler == null) {
112                 throw new IllegalStateException("SwitchConnectionHandler is not set");
113             }
114             new Thread(serverFacade).start();
115             result = serverFacade.getIsOnlineFuture();
116         } catch (final Exception e) {
117             final SettableFuture<Boolean> exResult = SettableFuture.create();
118             exResult.setException(e);
119             result = exResult;
120         }
121         return result;
122     }
123
124     /**
125      * @return
126      */
127     private ServerFacade createAndConfigureServer() {
128         LOGGER.debug("Configuring ..");
129         ServerFacade server = null;
130         final ChannelInitializerFactory factory = new ChannelInitializerFactory();
131         factory.setSwitchConnectionHandler(switchConnectionHandler);
132         factory.setSwitchIdleTimeout(connConfig.getSwitchIdleTimeout());
133         factory.setTlsConfig(connConfig.getTlsConfiguration());
134         factory.setSerializationFactory(serializationFactory);
135         factory.setDeserializationFactory(deserializationFactory);
136         factory.setUseBarrier(connConfig.useBarrier());
137         final TransportProtocol transportProtocol = (TransportProtocol) connConfig.getTransferProtocol();
138
139         // Check if Epoll native transport is available.
140         // TODO : Add option to disable Epoll.
141         boolean isEpollEnabled = Epoll.isAvailable();
142
143         if (transportProtocol.equals(TransportProtocol.TCP) || transportProtocol.equals(TransportProtocol.TLS)) {
144             server = new TcpHandler(connConfig.getAddress(), connConfig.getPort());
145             final TcpChannelInitializer channelInitializer = factory.createPublishingChannelInitializer();
146             ((TcpHandler) server).setChannelInitializer(channelInitializer);
147             ((TcpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled);
148
149             final EventLoopGroup workerGroupFromTcpHandler = ((TcpHandler) server).getWorkerGroup();
150             connectionInitializer = new TcpConnectionInitializer(workerGroupFromTcpHandler, isEpollEnabled);
151             connectionInitializer.setChannelInitializer(channelInitializer);
152             connectionInitializer.run();
153         } else if (transportProtocol.equals(TransportProtocol.UDP)){
154             server = new UdpHandler(connConfig.getAddress(), connConfig.getPort());
155             ((UdpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled);
156             ((UdpHandler) server).setChannelInitializer(factory.createUdpChannelInitializer());
157         } else {
158             throw new IllegalStateException("Unknown transport protocol received: " + transportProtocol);
159         }
160         server.setThreadConfig(connConfig.getThreadConfiguration());
161         return server;
162     }
163
164     /**
165      * @return servers
166      */
167     public ServerFacade getServerFacade() {
168         return serverFacade;
169     }
170
171     @Override
172     public void close() throws Exception {
173         shutdown();
174     }
175
176     @Override
177     public boolean unregisterSerializer(final ExperimenterSerializerKey key) {
178         return serializerRegistry.unregisterSerializer((MessageTypeKey<?>) key);
179     }
180
181     @Override
182     public boolean unregisterDeserializer(final ExperimenterDeserializerKey key) {
183         return deserializerRegistry.unregisterDeserializer((MessageCodeKey) key);
184     }
185
186     @Override
187     public void registerActionSerializer(final ActionSerializerKey<?> key,
188             final OFGeneralSerializer serializer) {
189         serializerRegistry.registerSerializer(key, serializer);
190     }
191
192     @Override
193     public void registerActionDeserializer(final ExperimenterActionDeserializerKey key,
194             final OFGeneralDeserializer deserializer) {
195         deserializerRegistry.registerDeserializer(key, deserializer);
196     }
197
198     @Override
199     public void registerInstructionSerializer(final InstructionSerializerKey<?> key,
200             final OFGeneralSerializer serializer) {
201         serializerRegistry.registerSerializer(key, serializer);
202     }
203
204     @Override
205     public void registerInstructionDeserializer(final ExperimenterInstructionDeserializerKey key,
206             final OFGeneralDeserializer deserializer) {
207         deserializerRegistry.registerDeserializer(key, deserializer);
208     }
209
210     @Override
211     public <C extends OxmClassBase, F extends MatchField> void registerMatchEntrySerializer(final MatchEntrySerializerKey<C, F> key,
212             final OFGeneralSerializer serializer) {
213         serializerRegistry.registerSerializer(key, serializer);
214     }
215
216     @Override
217     public void registerMatchEntryDeserializer(final MatchEntryDeserializerKey key,
218             final OFGeneralDeserializer deserializer) {
219         deserializerRegistry.registerDeserializer(key, deserializer);
220     }
221
222     @Override
223     public void registerErrorDeserializer(final ExperimenterIdDeserializerKey key,
224             final OFDeserializer<ErrorMessage> deserializer) {
225         deserializerRegistry.registerDeserializer(key, deserializer);
226     }
227
228     @Override
229     public void registerExperimenterMessageDeserializer(ExperimenterIdDeserializerKey key,
230                                                         OFDeserializer<? extends ExperimenterDataOfChoice> deserializer) {
231         deserializerRegistry.registerDeserializer(key, deserializer);
232     }
233
234     @Override
235     public void registerMultipartReplyMessageDeserializer(ExperimenterIdDeserializerKey key,
236                                                           OFDeserializer<? extends ExperimenterDataOfChoice> deserializer) {
237         deserializerRegistry.registerDeserializer(key, deserializer);
238     }
239
240     @Override
241     public void registerMultipartReplyTFDeserializer(final ExperimenterIdDeserializerKey key,
242             final OFGeneralDeserializer deserializer) {
243         deserializerRegistry.registerDeserializer(key, deserializer);
244     }
245
246     @Override
247     public void registerQueuePropertyDeserializer(final ExperimenterIdDeserializerKey key,
248             final OFDeserializer<QueueProperty> deserializer) {
249         deserializerRegistry.registerDeserializer(key, deserializer);
250     }
251
252     @Override
253     public void registerMeterBandDeserializer(final ExperimenterIdDeserializerKey key,
254             final OFDeserializer<MeterBandExperimenterCase> deserializer) {
255         deserializerRegistry.registerDeserializer(key, deserializer);
256     }
257
258     @Override
259     public void registerExperimenterMessageSerializer(ExperimenterIdSerializerKey<? extends ExperimenterDataOfChoice> key,
260                                                       OFSerializer<? extends ExperimenterDataOfChoice> serializer) {
261         serializerRegistry.registerSerializer(key, serializer);
262     }
263
264     @Override
265     public void registerMultipartRequestSerializer(ExperimenterIdSerializerKey<? extends ExperimenterDataOfChoice> key,
266                                                    OFSerializer<? extends ExperimenterDataOfChoice> serializer) {
267         serializerRegistry.registerSerializer(key, serializer);
268     }
269
270     @Override
271     public void registerMultipartRequestTFSerializer(final ExperimenterIdSerializerKey<TableFeatureProperties> key,
272             final OFGeneralSerializer serializer) {
273         serializerRegistry.registerSerializer(key, serializer);
274     }
275
276     @Override
277     public void registerMeterBandSerializer(final ExperimenterIdSerializerKey<MeterBandExperimenterCase> key,
278             final OFSerializer<MeterBandExperimenterCase> serializer) {
279         serializerRegistry.registerSerializer(key, serializer);
280     }
281
282     @Override
283     public void initiateConnection(final String host, final int port) {
284         connectionInitializer.initiateConnection(host, port);
285     }
286
287     @Override
288     public ConnectionConfiguration getConfiguration() {
289         return this.connConfig;
290     }
291
292 }