From 7b63f30a8fb6f192c10803af2949a55a9d5777bf Mon Sep 17 00:00:00 2001 From: Dileep Date: Mon, 28 Mar 2016 07:49:12 -0700 Subject: [PATCH] Bug 3230 - Attempt to use Epoll native transport if available Attempts to use Epoll native transport if available. Uses Epoll.isAvailable() to check availability. Refer : http://netty.io/wiki/native-transports.html Change-Id: I0019a084b0f2410f4cea7d5541fe0e5b49699bec Depends-on: I073093f9a7b28de9890a6842f8bef72d4fdf6872 Signed-off-by: Dileep Ranganathan --- features/pom.xml | 6 + openflow-protocol-impl/pom.xml | 6 + .../core/SwitchConnectionProviderImpl.java | 15 ++- .../impl/core/TcpConnectionInitializer.java | 16 ++- .../protocol/impl/core/TcpHandler.java | 59 ++++++++- .../impl/core/UdpChannelInitializer.java | 6 +- .../protocol/impl/core/UdpHandler.java | 58 ++++++++- .../protocol/impl/core/TcpHandlerTest.java | 115 ++++++++++++++++-- .../SwitchConnectionProviderImplTest.java | 2 +- .../impl/core/connection/UdpHandlerTest.java | 53 +++++++- .../impl/clients/SimpleClientInitializer.java | 6 +- .../clients/UdpSimpleClientInitializer.java | 6 +- 12 files changed, 302 insertions(+), 46 deletions(-) diff --git a/features/pom.xml b/features/pom.xml index 62dc813d..f35b4d8a 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -156,6 +156,12 @@ io.netty netty-transport + + io.netty + netty-transport-native-epoll + + linux-x86_64 + diff --git a/openflow-protocol-impl/pom.xml b/openflow-protocol-impl/pom.xml index a125a931..0c3fc442 100644 --- a/openflow-protocol-impl/pom.xml +++ b/openflow-protocol-impl/pom.xml @@ -150,5 +150,11 @@ org.opendaylight.controller config-api + + io.netty + netty-transport-native-epoll + + linux-x86_64 + diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/SwitchConnectionProviderImpl.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/SwitchConnectionProviderImpl.java index aa79e6a3..411a9b43 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/SwitchConnectionProviderImpl.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/SwitchConnectionProviderImpl.java @@ -11,7 +11,8 @@ 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.nio.NioEventLoopGroup; +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; @@ -134,18 +135,24 @@ public class SwitchConnectionProviderImpl implements SwitchConnectionProvider, C 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()); + ((TcpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled); - final NioEventLoopGroup workerGroupFromTcpHandler = ((TcpHandler) server).getWorkerGroup(); - connectionInitializer = new TcpConnectionInitializer(workerGroupFromTcpHandler); + 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); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpConnectionInitializer.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpConnectionInitializer.java index c4b0937e..c5905d60 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpConnectionInitializer.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpConnectionInitializer.java @@ -2,9 +2,8 @@ package org.opendaylight.openflowjava.protocol.impl.core; import io.netty.bootstrap.Bootstrap; import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; - import org.opendaylight.openflowjava.protocol.api.connection.ThreadConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,21 +27,28 @@ public class TcpConnectionInitializer implements ServerFacade, private TcpChannelInitializer channelInitializer; private Bootstrap b; + private boolean isEpollEnabled; /** * Constructor * @param workerGroup - shared worker group */ - public TcpConnectionInitializer(NioEventLoopGroup workerGroup) { + public TcpConnectionInitializer(EventLoopGroup workerGroup, boolean isEpollEnabled) { Preconditions.checkNotNull(workerGroup, "WorkerGroup can't be null"); this.workerGroup = workerGroup; + this.isEpollEnabled = isEpollEnabled; } @Override public void run() { b = new Bootstrap(); - b.group(workerGroup).channel(NioSocketChannel.class) - .handler(channelInitializer); + if(isEpollEnabled) { + b.group(workerGroup).channel(EpollSocketChannel.class) + .handler(channelInitializer); + } else { + b.group(workerGroup).channel(NioSocketChannel.class) + .handler(channelInitializer); + } } @Override diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandler.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandler.java index ff4bc6a1..00a3fd71 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandler.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandler.java @@ -13,11 +13,17 @@ import io.netty.buffer.PooledByteBufAllocator; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.util.concurrent.GenericFutureListener; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollServerSocketChannel; + import java.net.InetAddress; import java.net.InetSocketAddress; @@ -50,13 +56,15 @@ public class TcpHandler implements ServerFacade { private int port; private String address; private final InetAddress startupAddress; - private NioEventLoopGroup workerGroup; - private NioEventLoopGroup bossGroup; + private EventLoopGroup workerGroup; + private EventLoopGroup bossGroup; private final SettableFuture isOnlineFuture; private ThreadConfiguration threadConfig; private TcpChannelInitializer channelInitializer; + private Class socketChannelClass; + /** * Constructor of TCPHandler that listens on selected port. * @@ -90,13 +98,13 @@ public class TcpHandler implements ServerFacade { * Any other setting means netty will measure the time it spent selecting * and spend roughly proportional time executing tasks. */ - workerGroup.setIoRatio(100); + //workerGroup.setIoRatio(100); final ChannelFuture f; try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) + .channel(socketChannelClass) .handler(new LoggingHandler(LogLevel.DEBUG)) .childHandler(channelInitializer) .option(ChannelOption.SO_BACKLOG, 128) @@ -202,7 +210,21 @@ public class TcpHandler implements ServerFacade { * Initiate event loop groups * @param threadConfiguration number of threads to be created, if not specified in threadConfig */ - public void initiateEventLoopGroups(ThreadConfiguration threadConfiguration) { + public void initiateEventLoopGroups(ThreadConfiguration threadConfiguration, boolean isEpollEnabled) { + + if(isEpollEnabled) { + initiateEpollEventLoopGroups(threadConfiguration); + } else { + initiateNioEventLoopGroups(threadConfiguration); + } + } + + /** + * Initiate Nio event loop groups + * @param threadConfiguration number of threads to be created, if not specified in threadConfig + */ + public void initiateNioEventLoopGroups(ThreadConfiguration threadConfiguration) { + socketChannelClass = NioServerSocketChannel.class; if (threadConfiguration != null) { bossGroup = new NioEventLoopGroup(threadConfiguration.getBossThreadCount()); workerGroup = new NioEventLoopGroup(threadConfiguration.getWorkerThreadCount()); @@ -210,12 +232,37 @@ public class TcpHandler implements ServerFacade { bossGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup(); } + ((NioEventLoopGroup)workerGroup).setIoRatio(100); + } + + /** + * Initiate Epoll event loop groups with Nio as fall back + * @param threadConfiguration + */ + protected void initiateEpollEventLoopGroups(ThreadConfiguration threadConfiguration) { + try { + socketChannelClass = EpollServerSocketChannel.class; + if (threadConfiguration != null) { + bossGroup = new EpollEventLoopGroup(threadConfiguration.getBossThreadCount()); + workerGroup = new EpollEventLoopGroup(threadConfiguration.getWorkerThreadCount()); + } else { + bossGroup = new EpollEventLoopGroup(); + workerGroup = new EpollEventLoopGroup(); + } + ((EpollEventLoopGroup)workerGroup).setIoRatio(100); + return; + } catch (Throwable ex) { + LOGGER.debug("Epoll initiation failed"); + } + + //Fallback mechanism + initiateNioEventLoopGroups(threadConfiguration); } /** * @return workerGroup */ - public NioEventLoopGroup getWorkerGroup() { + public EventLoopGroup getWorkerGroup() { return workerGroup; } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpChannelInitializer.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpChannelInitializer.java index ba1650e5..ccb8b06c 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpChannelInitializer.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpChannelInitializer.java @@ -8,16 +8,16 @@ package org.opendaylight.openflowjava.protocol.impl.core; -import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.channel.socket.DatagramChannel; /** * @author michal.polkorab * */ -public class UdpChannelInitializer extends ProtocolChannelInitializer { +public class UdpChannelInitializer extends ProtocolChannelInitializer { @Override - protected void initChannel(NioDatagramChannel ch) throws Exception { + protected void initChannel(DatagramChannel ch) throws Exception { ch.pipeline().addLast(PipelineHandlers.OF_DATAGRAMPACKET_HANDLER.name(), new OFDatagramPacketHandler(getSwitchConnectionHandler())); OFDatagramPacketDecoder ofDatagramPacketDecoder = new OFDatagramPacketDecoder(); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpHandler.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpHandler.java index 3e6e384e..9339ba16 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpHandler.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/UdpHandler.java @@ -12,7 +12,10 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollDatagramChannel; +import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.util.concurrent.GenericFutureListener; @@ -41,6 +44,7 @@ public final class UdpHandler implements ServerFacade { private final SettableFuture isOnlineFuture; private UdpChannelInitializer channelInitializer; private ThreadConfiguration threadConfig; + private Class datagramChannelClass; /** * Constructor of UdpHandler that listens on selected port. @@ -64,16 +68,11 @@ public final class UdpHandler implements ServerFacade { @Override public void run() { - if (threadConfig != null) { - group = new NioEventLoopGroup(threadConfig.getWorkerThreadCount()); - } else { - group = new NioEventLoopGroup(); - } final ChannelFuture f; try { Bootstrap b = new Bootstrap(); b.group(group) - .channel(NioDatagramChannel.class) + .channel(datagramChannelClass) .option(ChannelOption.SO_BROADCAST, false) .handler(channelInitializer); @@ -146,4 +145,51 @@ public final class UdpHandler implements ServerFacade { public void setThreadConfig(ThreadConfiguration threadConfig) { this.threadConfig = threadConfig; } + + /** + * Initiate event loop groups + * @param threadConfiguration number of threads to be created, if not specified in threadConfig + */ + public void initiateEventLoopGroups(ThreadConfiguration threadConfiguration, boolean isEpollEnabled) { + + if(isEpollEnabled) { + initiateEpollEventLoopGroups(threadConfiguration); + } else { + initiateNioEventLoopGroups(threadConfiguration); + } + } + + /** + * Initiate Nio event loop groups + * @param threadConfiguration number of threads to be created, if not specified in threadConfig + */ + public void initiateNioEventLoopGroups(ThreadConfiguration threadConfiguration) { + datagramChannelClass = NioDatagramChannel.class; + if (threadConfiguration != null) { + group = new NioEventLoopGroup(threadConfiguration.getWorkerThreadCount()); + } else { + group = new NioEventLoopGroup(); + } + } + + /** + * Initiate Epoll event loop groups with Nio as fall back + * @param threadConfiguration + */ + protected void initiateEpollEventLoopGroups(ThreadConfiguration threadConfiguration) { + try { + datagramChannelClass = EpollDatagramChannel.class; + if (threadConfiguration != null) { + group = new EpollEventLoopGroup(threadConfiguration.getWorkerThreadCount()); + } else { + group = new EpollEventLoopGroup(); + } + return; + } catch (Throwable ex) { + LOGGER.debug("Epoll initiation failed"); + } + + //Fallback mechanism + initiateNioEventLoopGroups(threadConfiguration); + } } \ No newline at end of file diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandlerTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandlerTest.java index 6d103355..6faad908 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandlerTest.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/TcpHandlerTest.java @@ -18,6 +18,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.util.concurrent.ExecutionException; +import io.netty.channel.unix.Errors; import org.junit.Assert; import org.junit.Test; import org.mockito.Mock; @@ -62,7 +63,25 @@ public class TcpHandlerTest { tcpHandler = new TcpHandler(null, 0); tcpHandler.setChannelInitializer(mockChannelInitializer); - assertEquals("failed to start server", true, startupServer()) ; + assertEquals("failed to start server", true, startupServer(false)) ; + assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ; + shutdownServer(); + } + + /** + * Test run with null address set on Epoll native transport + * @throws IOException + * @throws InterruptedException + * @throws ExecutionException + */ + @Test + public void testRunWithNullAddressOnEpoll() throws IOException, InterruptedException, ExecutionException { + + tcpHandler = new TcpHandler(null, 0); + tcpHandler.setChannelInitializer(mockChannelInitializer); + + //Use Epoll native transport + assertEquals("failed to start server", true, startupServer(true)) ; assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ; shutdownServer(); } @@ -79,11 +98,29 @@ public class TcpHandlerTest { tcpHandler = new TcpHandler(serverAddress, 0); tcpHandler.setChannelInitializer(mockChannelInitializer); - assertEquals("failed to start server", true, startupServer()) ; + assertEquals("failed to start server", true, startupServer(false)) ; assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ; shutdownServer(); } + /** + * Test run with address set on Epoll native transport + * @throws IOException + * @throws InterruptedException + * @throws ExecutionException + */ + @Test + public void testRunWithAddressOnEpoll() throws IOException, InterruptedException, ExecutionException { + + tcpHandler = new TcpHandler(serverAddress, 0); + tcpHandler.setChannelInitializer(mockChannelInitializer); + + //Use Epoll native transport + assertEquals("failed to start server", true, startupServer(true)); + assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())); + shutdownServer(); + } + /** * Test run with encryption * @throws InterruptedException @@ -91,17 +128,40 @@ public class TcpHandlerTest { * @throws ExecutionException */ @Test - public void testRunWithEncryption () throws InterruptedException, IOException, ExecutionException { + public void testRunWithEncryption() throws InterruptedException, IOException, ExecutionException { int serverPort = 28001; tcpHandler = new TcpHandler(serverAddress, serverPort); tcpHandler.setChannelInitializer(mockChannelInitializer); - assertEquals( "failed to start server", true, startupServer()) ; - assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections() ); - assertEquals( "wrong port", serverPort, tcpHandler.getPort() ); - assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress()) ; + assertEquals( "failed to start server", true, startupServer(false)); + assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections()); + assertEquals( "wrong port", serverPort, tcpHandler.getPort()); + assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress()); - assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ; + assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())); + + shutdownServer(); + } + + /** + * Test run with encryption on Epoll native transport + * @throws InterruptedException + * @throws IOException + * @throws ExecutionException + */ + @Test + public void testRunWithEncryptionOnEpoll() throws InterruptedException, IOException, ExecutionException { + int serverPort = 28001; + tcpHandler = new TcpHandler(serverAddress, serverPort); + tcpHandler.setChannelInitializer(mockChannelInitializer); + + //Use Epoll native transport + assertEquals( "failed to start server", true, startupServer(true)); + assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections()); + assertEquals( "wrong port", serverPort, tcpHandler.getPort()); + assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress()); + + assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())); shutdownServer(); } @@ -123,7 +183,7 @@ public class TcpHandlerTest { try { tcpHandler = new TcpHandler(serverAddress, serverPort); tcpHandler.setChannelInitializer(mockChannelInitializer); - tcpHandler.initiateEventLoopGroups(null); + tcpHandler.initiateEventLoopGroups(null, false); tcpHandler.run(); } catch (Exception e) { if (e instanceof BindException) { @@ -134,6 +194,35 @@ public class TcpHandlerTest { Assert.assertTrue("Expected BindException has not been thrown", exceptionThrown == true); } + /** + * Test run on already used port + * @throws IOException + */ + @Test + public void testSocketAlreadyInUseOnEpoll() throws IOException { + int serverPort = 28001; + Socket firstBinder = new Socket(); + boolean exceptionThrown = false; + try { + firstBinder.bind(new InetSocketAddress(serverAddress, serverPort)); + } catch (Exception e) { + Assert.fail("Test precondition failed - not able to bind socket to port " + serverPort); + } + try { + tcpHandler = new TcpHandler(serverAddress, serverPort); + tcpHandler.setChannelInitializer(mockChannelInitializer); + //Use Epoll native transport + tcpHandler.initiateEventLoopGroups(null, true); + tcpHandler.run(); + } catch (Exception e) { + if (e instanceof BindException || e instanceof Errors.NativeIoException) { + exceptionThrown = true; + } + } + firstBinder.close(); + Assert.assertTrue("Expected BindException has not been thrown", exceptionThrown == true); + } + /** * Trigger the server shutdown and wait 2 seconds for completion */ @@ -149,9 +238,13 @@ public class TcpHandlerTest { * @throws IOException * @throws ExecutionException */ - private Boolean startupServer() throws InterruptedException, IOException, ExecutionException { + private Boolean startupServer(boolean isEpollEnabled) throws InterruptedException, IOException, ExecutionException { ListenableFuture online = tcpHandler.getIsOnlineFuture(); - tcpHandler.initiateEventLoopGroups(null); + /** + * Test EPoll based native transport if isEpollEnabled is true. + * Else use Nio based transport. + */ + tcpHandler.initiateEventLoopGroups(null, isEpollEnabled); (new Thread(tcpHandler)).start(); int retry = 0; while (online.isDone() != true && retry++ < 20) { diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/SwitchConnectionProviderImplTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/SwitchConnectionProviderImplTest.java index 491e18de..17559515 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/SwitchConnectionProviderImplTest.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/SwitchConnectionProviderImplTest.java @@ -161,7 +161,7 @@ public class SwitchConnectionProviderImplTest { } catch (InterruptedException | ExecutionException | TimeoutException e) { Assert.fail(); } - } + } /** * Tests correct provider shutdown diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/UdpHandlerTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/UdpHandlerTest.java index 0dd9ce3b..ff36181f 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/UdpHandlerTest.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/connection/UdpHandlerTest.java @@ -47,7 +47,27 @@ public class UdpHandlerTest { public void testWithEmptyAddress() throws InterruptedException, ExecutionException, IOException { udpHandler = new UdpHandler(null, 0); udpHandler.setChannelInitializer(udpChannelInitializerMock); - Assert.assertTrue("Wrong - start server", startupServer()); + Assert.assertTrue("Wrong - start server", startupServer(false)); + try { + Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue()); + } catch (TimeoutException e) { + Assert.fail("Wrong - getIsOnlineFuture timed out"); + } + Assert.assertFalse("Wrong - port has been set to zero", udpHandler.getPort() == 0); + shutdownServer(); + } + + /** + * Test to create UdpHandler with empty address and zero port on Epoll native transport + * @throws InterruptedException + * @throws ExecutionException + * @throws IOException + */ + @Test + public void testWithEmptyAddressOnEpoll() throws InterruptedException, ExecutionException, IOException { + udpHandler = new UdpHandler(null, 0); + udpHandler.setChannelInitializer(udpChannelInitializerMock); + Assert.assertTrue("Wrong - start server", startupServer(true)); try { Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue()); } catch (TimeoutException e) { @@ -68,7 +88,7 @@ public class UdpHandlerTest { int port = 9874; udpHandler = new UdpHandler(InetAddress.getLocalHost(), port); udpHandler.setChannelInitializer(udpChannelInitializerMock); - Assert.assertTrue("Wrong - start server", startupServer()); + Assert.assertTrue("Wrong - start server", startupServer(false)); try { Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue()); } catch (TimeoutException e) { @@ -78,9 +98,34 @@ public class UdpHandlerTest { shutdownServer(); } - private Boolean startupServer() throws InterruptedException, IOException, ExecutionException { - ListenableFuture online = udpHandler.getIsOnlineFuture(); + /** + * Test to create UdpHandler with fill address and given port on Epoll native transport + * @throws InterruptedException + * @throws ExecutionException + * @throws IOException + */ + @Test + public void testWithAddressAndPortOnEpoll() throws InterruptedException, ExecutionException, IOException{ + int port = 9874; + udpHandler = new UdpHandler(InetAddress.getLocalHost(), port); + udpHandler.setChannelInitializer(udpChannelInitializerMock); + Assert.assertTrue("Wrong - start server", startupServer(true)); + try { + Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue()); + } catch (TimeoutException e) { + Assert.fail("Wrong - getIsOnlineFuture timed out"); + } + Assert.assertEquals("Wrong - bad port number has been set", port, udpHandler.getPort()); + shutdownServer(); + } + private Boolean startupServer(boolean isEpollEnabled) throws InterruptedException, IOException, ExecutionException { + ListenableFuture online = udpHandler.getIsOnlineFuture(); + /** + * Test EPoll based native transport if isEpollEnabled is true. + * Else use Nio based transport. + */ + udpHandler.initiateEventLoopGroups(null, isEpollEnabled); (new Thread(udpHandler)).start(); int retry = 0; while (online.isDone() != true && retry++ < 20) { diff --git a/simple-client/src/main/java/org/opendaylight/openflowjava/protocol/impl/clients/SimpleClientInitializer.java b/simple-client/src/main/java/org/opendaylight/openflowjava/protocol/impl/clients/SimpleClientInitializer.java index a2fe3a11..98a6e1ff 100644 --- a/simple-client/src/main/java/org/opendaylight/openflowjava/protocol/impl/clients/SimpleClientInitializer.java +++ b/simple-client/src/main/java/org/opendaylight/openflowjava/protocol/impl/clients/SimpleClientInitializer.java @@ -11,7 +11,7 @@ package org.opendaylight.openflowjava.protocol.impl.clients; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.channel.socket.SocketChannel; import io.netty.handler.ssl.SslHandler; import javax.net.ssl.SSLEngine; @@ -22,7 +22,7 @@ import com.google.common.util.concurrent.SettableFuture; * * @author michal.polkorab */ -public class SimpleClientInitializer extends ChannelInitializer { +public class SimpleClientInitializer extends ChannelInitializer { private SettableFuture isOnlineFuture; private boolean secured; @@ -38,7 +38,7 @@ public class SimpleClientInitializer extends ChannelInitializer { +public class UdpSimpleClientInitializer extends ChannelInitializer { private SettableFuture isOnlineFuture; private ScenarioHandler scenarioHandler; @@ -32,7 +32,7 @@ public class UdpSimpleClientInitializer extends ChannelInitializer