diff --git a/lib/netty-3.10.0.Final.jar b/lib/netty-3.10.0.Final.jar deleted file mode 100644 index 5f8aa2e2eb08d43a1a8c90c13bafcec5fdd11d63..0000000000000000000000000000000000000000 Binary files a/lib/netty-3.10.0.Final.jar and /dev/null differ diff --git a/lib/netty-all-4.0.31.Final.jar b/lib/netty-all-4.0.31.Final.jar new file mode 100644 index 0000000000000000000000000000000000000000..ef9477a323af6de76bd1a0b4cda9c4da0e72860d Binary files /dev/null and b/lib/netty-all-4.0.31.Final.jar differ diff --git a/lib/openflowj-0.9.0-SNAPSHOT-sources.jar b/lib/openflowj-0.9.0-SNAPSHOT-sources.jar deleted file mode 100644 index abdf436f91750e82a1e50f3376105bf590526477..0000000000000000000000000000000000000000 Binary files a/lib/openflowj-0.9.0-SNAPSHOT-sources.jar and /dev/null differ diff --git a/lib/openflowj-0.9.0-SNAPSHOT-javadoc.jar b/lib/openflowj-2.0.0-SNAPSHOT-javadoc.jar similarity index 53% rename from lib/openflowj-0.9.0-SNAPSHOT-javadoc.jar rename to lib/openflowj-2.0.0-SNAPSHOT-javadoc.jar index 3b2cd87c8da1a2ba622894c2241b4321b59e6ce2..c914cdc2c508df534c5cbc0b0b68255b1691a3b1 100644 Binary files a/lib/openflowj-0.9.0-SNAPSHOT-javadoc.jar and b/lib/openflowj-2.0.0-SNAPSHOT-javadoc.jar differ diff --git a/lib/openflowj-2.0.0-SNAPSHOT-sources.jar b/lib/openflowj-2.0.0-SNAPSHOT-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..9702a84e6e38fdae39d6a01d8ffd651eea589ca7 Binary files /dev/null and b/lib/openflowj-2.0.0-SNAPSHOT-sources.jar differ diff --git a/lib/openflowj-0.9.0-SNAPSHOT.jar b/lib/openflowj-2.0.0-SNAPSHOT.jar similarity index 70% rename from lib/openflowj-0.9.0-SNAPSHOT.jar rename to lib/openflowj-2.0.0-SNAPSHOT.jar index 2a2140a0038065ee1bc875723a42ae9b9cf8ece0..54a8ef28d0e28207ac2101ccc8f24bb752f25062 100644 Binary files a/lib/openflowj-0.9.0-SNAPSHOT.jar and b/lib/openflowj-2.0.0-SNAPSHOT.jar differ diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java index c91e55fc1720c5e36307cfb108084fe9f156da0e..ee182ef53b82014b5d737f9cf35996e9aa9abcf5 100644 --- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java +++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java @@ -23,9 +23,7 @@ import java.util.Map; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.packet.Ethernet; - -import org.jboss.netty.util.Timer; - +import io.netty.util.Timer; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.HARole; import net.floodlightcontroller.core.IHAListener; @@ -36,10 +34,12 @@ import net.floodlightcontroller.core.RoleInfo; import net.floodlightcontroller.core.internal.RoleManager; import net.floodlightcontroller.core.internal.Controller.IUpdate; import net.floodlightcontroller.core.internal.Controller.ModuleLoaderState; - import net.floodlightcontroller.core.FloodlightContextStore; + import org.projectfloodlight.openflow.protocol.OFMessage; import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.TransportPort; /** * The interface exposed by the core bundle that allows you to interact * with connected switches. @@ -115,16 +115,16 @@ public interface IFloodlightProviderService extends public String getControllerId(); /** - * Gets the controller hostname - * @return the controller hostname + * Gets the controller addresses + * @return the controller addresses */ - public String getOFHostname(); + public Set<IPv4Address> getOFAddresses(); /** * Gets the controller's openflow port * @return the controller's openflow port */ - public int getOFPort(); + public TransportPort getOFPort(); /** * Set the role of the controller diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java index 4cc47498d8534a5cce3f24e78243f4cac7313394..9e51dd1f46124c8e8633c31df8d737c654f51054 100644 --- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java +++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java @@ -40,6 +40,7 @@ import org.projectfloodlight.openflow.types.U64; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.ListenableFuture; +import net.floodlightcontroller.core.internal.OFConnection; import net.floodlightcontroller.core.internal.TableFeatures; import net.floodlightcontroller.core.web.serializers.IOFSwitchSerializer; diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 51c0dbc3232cff0944cf67771aad68fe1f6cfd1b..4e27cb95fa3b07a23f81ce77c5f066cb7d713881 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -22,6 +22,7 @@ import java.lang.management.RuntimeMXBean; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -34,9 +35,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.LinkedBlockingQueue; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timer; - +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import net.floodlightcontroller.core.ControllerId; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.HAListenerTypeMarker; @@ -66,6 +66,8 @@ import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFType; import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.TransportPort; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; @@ -129,8 +131,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis private IShutdownService shutdownService; // Configuration options - protected int openFlowPort = 6653; // new registered OF port number - private String openFlowHostname = null; + private static TransportPort openFlowPort = TransportPort.of(6653); // new registered OF port number + private static Set<IPv4Address> openFlowAddresses = new HashSet<IPv4Address>(); protected int workerThreads = 0; // The id for this controller node. Should be unique for each controller @@ -513,11 +515,12 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } @Override - public String getOFHostname() { - return openFlowHostname; + public Set<IPv4Address> getOFAddresses() { + return Collections.unmodifiableSet(openFlowAddresses); } + @Override - public int getOFPort() { + public TransportPort getOFPort() { return openFlowPort; } @@ -677,22 +680,33 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } private void setConfigParams(Map<String, String> configParams) throws FloodlightModuleException { - String ofPort = configParams.get("openflowPort"); + String ofPort = configParams.get("openFlowPort"); if (!Strings.isNullOrEmpty(ofPort)) { try { - this.openFlowPort = Integer.parseInt(ofPort); - } catch (NumberFormatException e) { - log.error("invalid openflow port specifier", e); - throw new FloodlightModuleException("invalid port specifier in cofig"); + openFlowPort = TransportPort.of(Integer.parseInt(ofPort)); + } catch (Exception e) { + log.error("Invalid OpenFlow port {}, {}", ofPort, e); + throw new FloodlightModuleException("Invalid OpenFlow port of " + ofPort + " in config"); } - log.debug("OpenFlow port set to {}", this.openFlowPort); } + log.info("OpenFlow port set to {}", openFlowPort); - String threads = configParams.get("workerthreads"); + String threads = configParams.get("workerThreads"); if (!Strings.isNullOrEmpty(threads)) { this.workerThreads = Integer.parseInt(threads); } - log.debug("Number of worker threads set to {}", this.workerThreads); + log.info("Number of worker threads set to {}", this.workerThreads); + + String addresses = configParams.get("openFlowAddresses"); + if (!Strings.isNullOrEmpty(ofPort)) { + try { + openFlowAddresses = Collections.singleton(IPv4Address.of(addresses)); //TODO support list of addresses for multi-honed controllers + } catch (Exception e) { + log.error("Invalid OpenFlow address {}, {}", addresses, e); + throw new FloodlightModuleException("Invalid OpenFlow address of " + addresses + " in config"); + } + log.info("OpenFlow addresses set to {}", openFlowAddresses); + } } /** diff --git a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java index de5b99255c8e2968a7d914b50dc7c0115f330d4c..d14e88d78e91a28fbe37e773cf5c684d4bda51f3 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java +++ b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java @@ -1,11 +1,9 @@ package net.floodlightcontroller.core.internal; import net.floodlightcontroller.core.IOFSwitchBackend; -import net.floodlightcontroller.core.OFConnectionCounters; import net.floodlightcontroller.debugcounter.IDebugCounter; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", diff --git a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java b/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java index 89ef68109bdc715eb2c16ea3f59f6c2c7b33fc67..2bf6a7c919072e5f6da9fa42cc85b00856b422bb 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java @@ -19,22 +19,18 @@ package net.floodlightcontroller.core.internal; import java.util.concurrent.TimeUnit; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.channel.SimpleChannelUpstreamHandler; -import org.jboss.netty.util.Timeout; -import org.jboss.netty.util.Timer; -import org.jboss.netty.util.TimerTask; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; /** * Trigger a timeout if a switch fails to complete handshake soon enough */ -public class HandshakeTimeoutHandler - extends SimpleChannelUpstreamHandler { +public class HandshakeTimeoutHandler extends ChannelInboundHandlerAdapter { - static final HandshakeTimeoutException EXCEPTION = - new HandshakeTimeoutException(); + static final HandshakeTimeoutException EXCEPTION = new HandshakeTimeoutException(); final OFChannelHandler handshakeHandler; final Timer timer; @@ -52,22 +48,20 @@ public class HandshakeTimeoutHandler } @Override - public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) - throws Exception { + public void channelActive(ChannelHandlerContext ctx) throws Exception { if (timeoutNanos > 0) { - timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx), - timeoutNanos, TimeUnit.NANOSECONDS); + timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx), timeoutNanos, TimeUnit.NANOSECONDS); } - ctx.sendUpstream(e); + super.channelActive(ctx); } @Override - public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) - throws Exception { + public void channelInactive(ChannelHandlerContext ctx) throws Exception { if (timeout != null) { timeout.cancel(); timeout = null; } + super.channelInactive(ctx); } private final class HandshakeTimeoutTask implements TimerTask { @@ -84,11 +78,11 @@ public class HandshakeTimeoutHandler return; } - if (!ctx.getChannel().isOpen()) { + if (!ctx.channel().isOpen()) { return; } if (!handshakeHandler.isSwitchHandshakeComplete()) - Channels.fireExceptionCaught(ctx, EXCEPTION); + ctx.fireExceptionCaught(EXCEPTION); } } -} +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java index b6bb90358f88b8c2fa38c6c478c2e8d9cbec64ac..04c68118d54f7e844e8e7988489e3277ee66c51f 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java +++ b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java @@ -11,7 +11,6 @@ import javax.annotation.Nonnull; import net.floodlightcontroller.core.IOFConnectionBackend; import net.floodlightcontroller.core.IOFSwitchBackend; import net.floodlightcontroller.core.IOFSwitchDriver; -import net.floodlightcontroller.core.OFSwitch; import net.floodlightcontroller.core.SwitchDescription; import org.projectfloodlight.openflow.protocol.OFFactory; diff --git a/src/main/java/net/floodlightcontroller/core/NullConnection.java b/src/main/java/net/floodlightcontroller/core/internal/NullConnection.java similarity index 92% rename from src/main/java/net/floodlightcontroller/core/NullConnection.java rename to src/main/java/net/floodlightcontroller/core/internal/NullConnection.java index 34f225e1343a1f32953f786a61555cf053438f8d..2db236e45f64a6e475e4729d3e0653604f6d918a 100644 --- a/src/main/java/net/floodlightcontroller/core/NullConnection.java +++ b/src/main/java/net/floodlightcontroller/core/internal/NullConnection.java @@ -1,10 +1,12 @@ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; import java.net.SocketAddress; import java.util.List; import java.util.Date; -import net.floodlightcontroller.core.internal.IOFConnectionListener; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFMessageWriter; +import net.floodlightcontroller.core.SwitchDisconnectedException; import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFFactory; diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java index 7d45c1ee862f08dea0111bed7a63c37d94caf15e..0611648a5252cd623f1ade599777b3a9151c0067 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java @@ -10,25 +10,19 @@ import java.util.concurrent.RejectedExecutionException; import javax.annotation.Nonnull; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.channel.ExceptionEvent; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; -import org.jboss.netty.handler.timeout.IdleStateEvent; -import org.jboss.netty.handler.timeout.IdleStateHandler; -import org.jboss.netty.handler.timeout.ReadTimeoutException; -import org.jboss.netty.util.Timer; - +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.handler.timeout.ReadTimeoutException; +import io.netty.util.AttributeKey; +import io.netty.util.Timer; import net.floodlightcontroller.core.IOFConnectionBackend; -import net.floodlightcontroller.core.OFConnection; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandler; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandshakeTimeout; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineIdleReadTimeout; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineIdleWriteTimeout; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineHandler; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineHandshakeTimeout; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineIdleReadTimeout; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineIdleWriteTimeout; import net.floodlightcontroller.debugcounter.IDebugCounterService; import org.projectfloodlight.openflow.exceptions.OFParseError; @@ -62,10 +56,12 @@ import com.google.common.base.Preconditions; * messages to the higher orders of control. * @author Jason Parraga <Jason.Parraga@Bigswitch.com> */ -class OFChannelHandler extends IdleStateAwareChannelHandler { +class OFChannelHandler extends SimpleChannelInboundHandler<Iterable<OFMessage>> { private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class); + public static final AttributeKey<OFChannelInfo> ATTR_CHANNEL_INFO = AttributeKey.valueOf("channelInfo"); + private final ChannelPipeline pipeline; private final INewOFConnectionListener newConnectionListener; private final SwitchManagerCounters counters; @@ -83,10 +79,10 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { * We will count down */ private long handshakeTransactionIds = 0x00FFFFFFFFL; - - private volatile long echoSendTime; - private volatile long featuresLatency; - + + private volatile long echoSendTime; + private volatile long featuresLatency; + /** * Default implementation for message handlers in any OFChannelState. * @@ -336,11 +332,11 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { /* Lookup highest, common supported OpenFlow version */ commonVersion = computeOFVersionFromBitmap(bitmaps); if (commonVersion == null) { - log.error("Could not negotiate common OpenFlow version for {} with greatest version bitmap algorithm.", channel.getRemoteAddress()); + log.error("Could not negotiate common OpenFlow version for {} with greatest version bitmap algorithm.", channel.remoteAddress()); channel.disconnect(); return; } else { - log.info("Negotiated OpenFlow version of {} for {} with greatest version bitmap algorithm.", commonVersion.toString(), channel.getRemoteAddress()); + log.info("Negotiated OpenFlow version of {} for {} with greatest version bitmap algorithm.", commonVersion.toString(), channel.remoteAddress()); factory = OFFactories.getFactory(commonVersion); OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class); decoder.setVersion(commonVersion); @@ -348,16 +344,16 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { } /* If there's not a bitmap present, choose the lower of the two supported versions. */ else if (theirVersion.compareTo(factory.getVersion()) < 0) { - log.info("Negotiated down to switch OpenFlow version of {} for {} using lesser hello header algorithm.", theirVersion.toString(), channel.getRemoteAddress()); + log.info("Negotiated down to switch OpenFlow version of {} for {} using lesser hello header algorithm.", theirVersion.toString(), channel.remoteAddress()); factory = OFFactories.getFactory(theirVersion); OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class); decoder.setVersion(theirVersion); } /* else The controller's version is < or = the switch's, so keep original controller factory. */ else if (theirVersion.equals(factory.getVersion())) { - log.info("Negotiated equal OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.getRemoteAddress()); + log.info("Negotiated equal OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.remoteAddress()); } else { - log.info("Negotiated down to controller OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.getRemoteAddress()); + log.info("Negotiated down to controller OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.remoteAddress()); } setState(new WaitFeaturesReplyState()); @@ -382,7 +378,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { void processOFFeaturesReply(OFFeaturesReply m) throws IOException { featuresReply = m; - + featuresLatency = (System.currentTimeMillis() - featuresLatency) / 2; // Mark handshake as completed @@ -409,7 +405,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { * we are. */ if (m.getVersion().equals(factory.getVersion())) { - log.warn("Ignoring second hello from {} in state {}. Might be a Brocade.", channel.getRemoteAddress(), state.toString()); + log.warn("Ignoring second hello from {} in state {}. Might be a Brocade.", channel.remoteAddress(), state.toString()); } else { super.processOFHello(m); /* Versions don't match as they should; abort */ } @@ -417,7 +413,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { @Override void processOFPortStatus(OFPortStatus m) { - log.warn("Ignoring PORT_STATUS message from {} during OpenFlow channel establishment. Ports will be explicitly queried in a later state.", channel.getRemoteAddress()); + log.warn("Ignoring PORT_STATUS message from {} during OpenFlow channel establishment. Ports will be explicitly queried in a later state.", channel.remoteAddress()); } @Override @@ -429,7 +425,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { @Override void processOFMessage(OFMessage m) throws IOException { if (m.getType().equals(OFType.PACKET_IN)) { - log.warn("Ignoring PACKET_IN message from {} during OpenFlow channel establishment.", channel.getRemoteAddress()); + log.warn("Ignoring PACKET_IN message from {} during OpenFlow channel establishment.", channel.remoteAddress()); } else { super.processOFMessage(m); } @@ -453,11 +449,11 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { setSwitchHandshakeTimeout(); // Handle non 1.3 connections - if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){ + if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){ connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, OFAuxId.MAIN, debugCounters, timer); } // Handle 1.3 connections - else{ + else { connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, featuresReply.getAuxiliaryId(), debugCounters, timer); // If this is an aux connection, we set a longer echo idle time @@ -465,10 +461,10 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { setAuxChannelIdle(); } } - + connection.updateLatency(U64.of(featuresLatency)); echoSendTime = 0; - + // Notify the connection broker notifyConnectionOpened(connection); } @@ -588,21 +584,18 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { } @Override - public void channelConnected(ChannelHandlerContext ctx, - ChannelStateEvent e) throws Exception { + public void channelActive(ChannelHandlerContext ctx) throws Exception { log.debug("channelConnected on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this))); counters.switchConnected.increment(); - channel = e.getChannel(); - log.info("New switch connection from {}", - channel.getRemoteAddress()); + channel = ctx.channel(); + log.info("New switch connection from {}", channel.remoteAddress()); setState(new WaitHelloState()); } @Override - public void channelDisconnected(ChannelHandlerContext ctx, - ChannelStateEvent e) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { // Only handle cleanup connection is even known - if(this.connection != null){ + if (this.connection != null) { // Alert the connection object that the channel has been disconnected this.connection.disconnected(); // Punt the cleanup to the Switch Manager @@ -612,19 +605,19 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { } @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (e.getCause() instanceof ReadTimeoutException) { + if (cause instanceof ReadTimeoutException) { if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) { log.error("Disconnecting switch {} due to read timeout on main cxn.", getConnectionInfoString()); - ctx.getChannel().close(); + ctx.channel().close(); } else { if (featuresReply.getAuxiliaryId().equals(OFAuxId.MAIN)) { log.error("Disconnecting switch {} due to read timeout on main cxn.", getConnectionInfoString()); - ctx.getChannel().close(); + ctx.channel().close(); } else { // We only don't disconnect on aux connections log.warn("Switch {} encountered read timeout on aux cxn.", @@ -634,95 +627,84 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { // Increment counters counters.switchDisconnectReadTimeout.increment(); - } else if (e.getCause() instanceof HandshakeTimeoutException) { + } else if (cause instanceof HandshakeTimeoutException) { log.error("Disconnecting switch {}: failed to complete handshake. Channel handshake complete : {}", getConnectionInfoString(), this.state.channelHandshakeComplete); counters.switchDisconnectHandshakeTimeout.increment(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof ClosedChannelException) { + ctx.channel().close(); + } else if (cause instanceof ClosedChannelException) { log.debug("Channel for sw {} already closed", getConnectionInfoString()); - } else if (e.getCause() instanceof IOException) { + } else if (cause instanceof IOException) { log.error("Disconnecting switch {} due to IO Error: {}", - getConnectionInfoString(), e.getCause().getMessage()); + getConnectionInfoString(), cause.getMessage()); if (log.isDebugEnabled()) { // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); + log.debug("StackTrace for previous Exception: ", cause); } counters.switchDisconnectIOError.increment(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof SwitchStateException) { + ctx.channel().close(); + } else if (cause instanceof SwitchStateException) { log.error("Disconnecting switch {} due to switch state error: {}", - getConnectionInfoString(), e.getCause().getMessage()); + getConnectionInfoString(), cause.getMessage()); if (log.isDebugEnabled()) { // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); + log.debug("StackTrace for previous Exception: ", cause); } counters.switchDisconnectSwitchStateException.increment(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof OFAuxException) { + ctx.channel().close(); + } else if (cause instanceof OFAuxException) { log.error("Disconnecting switch {} due to OF Aux error: {}", - getConnectionInfoString(), e.getCause().getMessage()); + getConnectionInfoString(), cause.getMessage()); if (log.isDebugEnabled()) { // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); + log.debug("StackTrace for previous Exception: ", cause); } counters.switchDisconnectSwitchStateException.increment(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof OFParseError) { + ctx.channel().close(); + } else if (cause instanceof OFParseError) { log.error("Disconnecting switch " + getConnectionInfoString() + " due to message parse failure", - e.getCause()); + cause); counters.switchDisconnectParseError.increment(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof RejectedExecutionException) { + ctx.channel().close(); + } else if (cause instanceof RejectedExecutionException) { log.warn("Could not process message: queue full"); counters.rejectedExecutionException.increment(); - } else if (e.getCause() instanceof IllegalArgumentException) { - log.error("Illegal argument exception with switch {}. {}", getConnectionInfoString(), e.getCause()); + } else if (cause instanceof IllegalArgumentException) { + log.error("Illegal argument exception with switch {}. {}", getConnectionInfoString(), cause); counters.switchSslConfigurationError.increment(); - ctx.getChannel().close(); + ctx.channel().close(); } else { log.error("Error while processing message from switch " + getConnectionInfoString() - + "state " + this.state, e.getCause()); + + "state " + this.state, cause); counters.switchDisconnectOtherException.increment(); - ctx.getChannel().close(); + ctx.channel().close(); } } @Override - public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) - throws Exception { - + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { log.debug("channelIdle on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this))); - OFChannelHandler handler = ctx.getPipeline().get(OFChannelHandler.class); + OFChannelHandler handler = ctx.pipeline().get(OFChannelHandler.class); handler.sendEchoRequest(); } @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) - throws Exception { - if (e.getMessage() instanceof List) { - @SuppressWarnings("unchecked") - List<OFMessage> msglist = (List<OFMessage>)e.getMessage(); - for (OFMessage ofm : msglist) { - try { - // Do the actual packet processing - state.processOFMessage(ofm); - } - catch (Exception ex) { - // We are the last handler in the stream, so run the - // exception through the channel again by passing in - // ctx.getChannel(). - Channels.fireExceptionCaught(ctx.getChannel(), ex); - } + public void channelRead0(ChannelHandlerContext ctx, Iterable<OFMessage> msgList) throws Exception { + for (OFMessage ofm : msgList) { + try { + // Do the actual packet processing + state.processOFMessage(ofm); + } + catch (Exception ex) { + // We are the last handler in the stream, so run the + // exception through the channel again by passing in + // ctx.getChannel(). + ctx.fireExceptionCaught(ex); } - } - else { - Channels.fireExceptionCaught(ctx.getChannel(), - new AssertionError("Message received from channel is not a list")); } } @@ -731,9 +713,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { * This is specifically for aux channels. */ private void setAuxChannelIdle() { - IdleStateHandler idleHandler = new IdleStateHandler( - this.timer, PipelineIdleReadTimeout.AUX, PipelineIdleWriteTimeout.AUX, 0); @@ -765,10 +745,10 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { private String getConnectionInfoString() { String channelString; - if (channel == null || channel.getRemoteAddress() == null) { + if (channel == null || channel.remoteAddress() == null) { channelString = "?"; } else { - channelString = channel.getRemoteAddress().toString(); + channelString = channel.remoteAddress().toString(); if(channelString.startsWith("/")) channelString = channelString.substring(1); } @@ -807,7 +787,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { OFFeaturesRequest m = factory.buildFeaturesRequest() .setXid(handshakeTransactionIds--) .build(); - channel.write(Collections.singletonList(m)); + write(m); } /** @@ -830,8 +810,8 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { OFHello m = builder.setXid(handshakeTransactionIds--) .build(); - - channel.write(Collections.singletonList(m)); + + write(m); log.debug("Send hello: {}", m); } @@ -841,7 +821,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { .build(); /* Record for latency calculation */ echoSendTime = System.currentTimeMillis(); - channel.write(Collections.singletonList(request)); + write(request); } private void sendEchoReply(OFEchoRequest request) { @@ -849,7 +829,11 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { .setXid(request.getXid()) .setData(request.getData()) .build(); - channel.write(Collections.singletonList(reply)); + write(reply); + } + + private void write(OFMessage m) { + channel.writeAndFlush(Collections.singletonList(m)); } OFChannelState getStateForTesting() { diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelInfo.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..e4a347e18dafccc9a90f90d48c6e287f1908da02 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelInfo.java @@ -0,0 +1,59 @@ +package net.floodlightcontroller.core.internal; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +import javax.annotation.Nonnull; + +import io.netty.channel.Channel; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPAddress; +import org.projectfloodlight.openflow.types.OFAuxId; + +import com.google.common.base.Preconditions; + +/** Basic information that {@link OFChannelHandler} attaches to the + * netty channel via {@link Channel#setAttachment(Object)}, mainly + * for the purpose of being able to log the connection information. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class OFChannelInfo { + private final DatapathId id; + private final OFAuxId auxId; + private final IPAddress<?> address; + private final int port; + + public OFChannelInfo(@Nonnull DatapathId id, @Nonnull OFAuxId auxId, @Nonnull SocketAddress address) { + Preconditions.checkNotNull(id, "id should not be null"); + Preconditions.checkNotNull(auxId, "auxId should not be null"); + Preconditions.checkNotNull(address, "address should not be null"); + + this.id = id; + this.auxId = auxId; + InetSocketAddress socketAddress = (InetSocketAddress) address; + this.address = IPAddress.of(socketAddress.getHostString()); + this.port = socketAddress.getPort(); + } + + public DatapathId getId() { + return id; + } + + public OFAuxId getAuxId() { + return auxId; + } + + public IPAddress<?> getAddress() { + return address; + } + + public int getPort() { + return port; + } + + @Override + public String toString() { + return id + "/" + auxId + "@" + address + ":" + port; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelInitializer.java similarity index 54% rename from src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java rename to src/main/java/net/floodlightcontroller/core/internal/OFChannelInitializer.java index 11827d02fb50a490c7661179bab38e9b2b46292a..3b3709c2e288c5e3fbd31911c7f6248cded12185 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelInitializer.java @@ -21,7 +21,6 @@ import java.io.FileInputStream; import java.security.KeyStore; import java.util.List; -import javax.annotation.Nonnull; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; @@ -29,85 +28,64 @@ import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.handler.ssl.SslHandler; -import org.jboss.netty.handler.timeout.IdleStateHandler; -import org.jboss.netty.handler.timeout.ReadTimeoutHandler; -import org.jboss.netty.util.ExternalResourceReleasable; -import org.jboss.netty.util.Timer; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.types.U32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.floodlightcontroller.core.internal.IOFSwitchManager; +import net.floodlightcontroller.core.internal.HandshakeTimeoutHandler; +import net.floodlightcontroller.core.internal.INewOFConnectionListener; +import net.floodlightcontroller.core.internal.OFChannelHandler; import net.floodlightcontroller.debugcounter.IDebugCounterService; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.util.Timer; /** * Creates a ChannelPipeline for a server-side openflow channel - * @author readams, sovietaced + * @author readams, sovietaced, rizard, andi-bigswitch */ -public class OpenflowPipelineFactory -implements ChannelPipelineFactory, ExternalResourceReleasable { - private static final Logger log = LoggerFactory.getLogger(OpenflowPipelineFactory.class); - protected IOFSwitchManager switchManager; - protected INewOFConnectionListener connectionListener; - protected Timer timer; - protected IdleStateHandler idleHandler; - protected ReadTimeoutHandler readTimeoutHandler; - protected IDebugCounterService debugCounters; +public class OFChannelInitializer extends ChannelInitializer<Channel> { + private static final Logger log = LoggerFactory.getLogger(OFChannelInitializer.class); + + private IOFSwitchManager switchManager; + private INewOFConnectionListener connectionListener; + private Timer timer; + private IDebugCounterService debugCounters; private String keyStore; private String keyStorePassword; private OFFactory defaultFactory; private List<U32> ofBitmaps; - private void init(IOFSwitchManager switchManager, Timer timer, + public OFChannelInitializer(IOFSwitchManager switchManager, INewOFConnectionListener connectionListener, IDebugCounterService debugCounters, - @Nonnull List<U32> ofBitmaps, - @Nonnull OFFactory defaultFactory) { + Timer timer, + List<U32> ofBitmaps, + OFFactory defaultFactory, + String keyStore, + String keyStorePassword) { + super(); this.switchManager = switchManager; this.connectionListener = connectionListener; this.timer = timer; this.debugCounters = debugCounters; this.defaultFactory = defaultFactory; this.ofBitmaps = ofBitmaps; - this.idleHandler = new IdleStateHandler( - timer, - PipelineIdleReadTimeout.MAIN, - PipelineIdleWriteTimeout.MAIN, - 0); - this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30); - } - - public OpenflowPipelineFactory(IOFSwitchManager switchManager, Timer timer, - INewOFConnectionListener connectionListener, - IDebugCounterService debugCounters, - @Nonnull List<U32> ofBitmaps, - @Nonnull OFFactory defaultFactory) { - super(); - init(switchManager,timer, connectionListener, debugCounters, ofBitmaps, defaultFactory); - this.keyStore = null; - this.keyStorePassword = null; - } - - public OpenflowPipelineFactory(IOFSwitchManager switchManager, Timer timer, - INewOFConnectionListener connectionListener, - IDebugCounterService debugCounters, - @Nonnull List<U32> ofBitmaps, - @Nonnull OFFactory defaultFactory, - @Nonnull String keyStore, @Nonnull String keyStorePassword) { - super(); - init(switchManager,timer, connectionListener, debugCounters, ofBitmaps, defaultFactory); this.keyStore = keyStore; this.keyStorePassword = keyStorePassword; } @Override - public ChannelPipeline getPipeline() throws Exception { - ChannelPipeline pipeline = Channels.pipeline(); - OFChannelHandler handler = new OFChannelHandler(switchManager, + protected void initChannel(Channel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + OFChannelHandler handler = new OFChannelHandler( + switchManager, connectionListener, pipeline, debugCounters, @@ -153,61 +131,57 @@ implements ChannelPipelineFactory, ExternalResourceReleasable { throw e; /* If we wanted secure but didn't get it, we should bail. */ } } - - /* SSL handler will have been added first if we're using it. */ + pipeline.addLast(PipelineHandler.OF_MESSAGE_DECODER, new OFMessageDecoder()); pipeline.addLast(PipelineHandler.OF_MESSAGE_ENCODER, new OFMessageEncoder()); - pipeline.addLast(PipelineHandler.MAIN_IDLE, idleHandler); - pipeline.addLast(PipelineHandler.READ_TIMEOUT, readTimeoutHandler); + pipeline.addLast(PipelineHandler.MAIN_IDLE, + new IdleStateHandler(PipelineIdleReadTimeout.MAIN, + PipelineIdleWriteTimeout.MAIN, + 0)); + pipeline.addLast(PipelineHandler.READ_TIMEOUT, new ReadTimeoutHandler(30)); pipeline.addLast(PipelineHandler.CHANNEL_HANDSHAKE_TIMEOUT, new HandshakeTimeoutHandler( handler, timer, PipelineHandshakeTimeout.CHANNEL)); - pipeline.addLast(PipelineHandler.CHANNEL_HANDLER, handler); - return pipeline; - } - @Override - public void releaseExternalResources() { - timer.stop(); + pipeline.addLast(PipelineHandler.CHANNEL_HANDLER, handler); } public static class PipelineHandler { - final static String CHANNEL_HANDSHAKE_TIMEOUT = "channelhandshaketimeout"; - final static String SWITCH_HANDSHAKE_TIMEOUT = "switchhandshaketimeout"; - final static String CHANNEL_HANDLER = "channelhandler"; - final static String MAIN_IDLE = "mainidle"; - final static String AUX_IDLE = "auxidle"; - final static String OF_MESSAGE_DECODER = "ofmessagedecoder"; - final static String OF_MESSAGE_ENCODER = "ofmessageencoder"; - final static String READ_TIMEOUT = "readtimeout"; - final static String SSL_TLS_ENCODER_DECODER = "ofsecurechannelencoderdecoder"; - } + public final static String CHANNEL_HANDSHAKE_TIMEOUT = "channelhandshaketimeout"; + public final static String SWITCH_HANDSHAKE_TIMEOUT = "switchhandshaketimeout"; + public final static String CHANNEL_HANDLER = "channelhandler"; + public final static String MAIN_IDLE = "mainidle"; + public final static String AUX_IDLE = "auxidle"; + public final static String OF_MESSAGE_DECODER = "ofmessagedecoder"; + public final static String OF_MESSAGE_ENCODER = "ofmessageencoder"; + public final static String READ_TIMEOUT = "readtimeout"; + public final static String SSL_TLS_ENCODER_DECODER = "ofsecurechannelencoderdecoder"; } /** * Timeouts for parts of the handshake, in seconds */ - public static class PipelineHandshakeTimeout { - final static int CHANNEL = 10; - final static int SWITCH = 30; - } - - /** - * Timeouts for writes on connections, in seconds - */ - public static class PipelineIdleWriteTimeout { - final static int MAIN = 2; - final static int AUX = 15; - } - - /** - * Timeouts for reads on connections, in seconds - */ - public static class PipelineIdleReadTimeout { - final static int MAIN = 3 * PipelineIdleWriteTimeout.MAIN; - final static int AUX = 3 * PipelineIdleWriteTimeout.AUX; - } -} + public static class PipelineHandshakeTimeout { + final static int CHANNEL = 10; + public final static int SWITCH = 30; + } + + /** + * Timeouts for writes on connections, in seconds + */ + public static class PipelineIdleWriteTimeout { + final static int MAIN = 2; + public final static int AUX = 15; + } + + /** + * Timeouts for reads on connections, in seconds + */ + public static class PipelineIdleReadTimeout { + final static int MAIN = 3 * PipelineIdleWriteTimeout.MAIN; + public final static int AUX = 3 * PipelineIdleWriteTimeout.AUX; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/OFConnection.java b/src/main/java/net/floodlightcontroller/core/internal/OFConnection.java similarity index 95% rename from src/main/java/net/floodlightcontroller/core/OFConnection.java rename to src/main/java/net/floodlightcontroller/core/internal/OFConnection.java index c72c618c6d2073cd1738baa0d35c7a3c95a3b5e6..791ced36bf710eb2a59f2d2def57a1f68f5539a7 100644 --- a/src/main/java/net/floodlightcontroller/core/OFConnection.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFConnection.java @@ -15,7 +15,7 @@ * under the License. **/ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; import java.net.SocketAddress; import java.util.ArrayList; @@ -29,15 +29,18 @@ import java.util.concurrent.TimeoutException; import javax.annotation.Nonnull; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.util.Timeout; -import org.jboss.netty.util.Timer; -import org.jboss.netty.util.TimerTask; +import io.netty.channel.Channel; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; import java.util.Date; -import net.floodlightcontroller.core.internal.Controller; -import net.floodlightcontroller.core.internal.IOFConnectionListener; +import net.floodlightcontroller.core.Deliverable; +import net.floodlightcontroller.core.DeliverableListenableFuture; +import net.floodlightcontroller.core.IOFConnection; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.SwitchDisconnectedException; import net.floodlightcontroller.debugcounter.IDebugCounterService; import org.projectfloodlight.openflow.protocol.OFErrorMsg; @@ -164,7 +167,7 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{ logger.trace("{}: send {}", this, m); counters.updateWriteStats(m); } - this.channel.write(msglist); + this.channel.writeAndFlush(msglist); } // Notifies the connection object that the channel has been disconnected @@ -188,7 +191,7 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{ @Override public String toString() { - String channelString = (channel != null) ? String.valueOf(channel.getRemoteAddress()): "?"; + String channelString = (channel != null) ? String.valueOf(channel.remoteAddress()): "?"; return "OFConnection [" + getDatapathId() + "(" + getAuxId() + ")" + "@" + channelString + "]"; } @@ -279,7 +282,7 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{ @Override public boolean isConnected() { - return channel.isConnected(); + return channel.isActive(); } @Override @@ -293,12 +296,12 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{ @Override public SocketAddress getRemoteInetAddress() { - return channel.getRemoteAddress(); + return channel.remoteAddress(); } @Override public SocketAddress getLocalInetAddress() { - return channel.getLocalAddress(); + return channel.localAddress(); } public boolean deliverResponse(OFMessage m) { diff --git a/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java b/src/main/java/net/floodlightcontroller/core/internal/OFConnectionCounters.java similarity index 99% rename from src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java rename to src/main/java/net/floodlightcontroller/core/internal/OFConnectionCounters.java index aef32b24d9743be5bf8528d3c02714cfdf425eb4..b92ab9ed71a031376f0805b0723c55ea6dcd7570 100644 --- a/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFConnectionCounters.java @@ -1,6 +1,5 @@ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; -import net.floodlightcontroller.core.internal.OFSwitchManager; import net.floodlightcontroller.debugcounter.IDebugCounter; import net.floodlightcontroller.debugcounter.IDebugCounterService; diff --git a/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java b/src/main/java/net/floodlightcontroller/core/internal/OFErrorMsgException.java similarity index 95% rename from src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java rename to src/main/java/net/floodlightcontroller/core/internal/OFErrorMsgException.java index f990f0a451052dfac060673e5bca7b20d6e802ad..bdb526153ac5cc2ce6b9ebf7d0aac2d6d4bfc276 100644 --- a/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFErrorMsgException.java @@ -1,4 +1,4 @@ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; import org.projectfloodlight.openflow.protocol.OFErrorMsg; import org.projectfloodlight.openflow.protocol.OFRequest; diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java index 12faa3be6b49a43d70a8d8fbffec769184524b77..40e6434baeef2c7538437f02ca674b70894f1487 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java @@ -1,29 +1,30 @@ /** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* Licensed under the Apache License, Version 2.0 (the "License"); you may -* not use this file except in compliance with the License. You may obtain -* a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -**/ + * Copyright 2011, Big Switch Networks, Inc. + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + **/ package net.floodlightcontroller.core.internal; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.frame.FrameDecoder; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFMessage; @@ -33,49 +34,71 @@ import org.projectfloodlight.openflow.protocol.OFVersion; /** * Decode an openflow message from a channel, for use in a netty pipeline. * - * @author readams + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> */ -public class OFMessageDecoder extends FrameDecoder { +public class OFMessageDecoder extends ByteToMessageDecoder { + + private OFMessageReader<OFMessage> reader; - private OFMessageReader<OFMessage> reader; + public OFMessageDecoder() { + setReader(); + } - public OFMessageDecoder() { - reader = OFFactories.getGenericReader(); - } + public OFMessageDecoder(OFVersion version) { + setVersion(version); + setReader(); + } - public OFMessageDecoder(OFVersion version) { - setVersion(version); - } + private void setReader() { + reader = OFFactories.getGenericReader(); + } - public void setVersion(OFVersion version) { - OFFactory factory = OFFactories.getFactory(version); - this.reader = factory.getReader(); - } + public void setVersion(OFVersion version) { + OFFactory factory = OFFactories.getFactory(version); + this.reader = factory.getReader(); + } - @Override - protected Object decode(ChannelHandlerContext ctx, Channel channel, - ChannelBuffer buffer) throws Exception { - if (!channel.isConnected()) { - // In testing, I see decode being called AFTER decode last. - // This check avoids that from reading corrupted frames - return null; - } + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { + if (!ctx.channel().isActive()) { + // In testing, I see decode being called AFTER decode last. + // This check avoids that from reading corrupted frames + return; + } - List<OFMessage> messageList = new ArrayList<OFMessage>(); - for (;;) { - OFMessage message = reader.readFrom(buffer); - if (message == null) - break; - messageList.add(message); - } - return messageList.isEmpty() ? null : messageList; - } + // Note(andiw): netty4 adds support for more efficient handling of lists messages in the + // pipeline itself. + // Instead of constructing a list of messages here, we could also just add the individual + // messages to the "out" list provided by netty. This would require changing all the handlers + // in the pipeline to accept "OFMessage" instead of "Iterable<OFMessage>". Probably + // a good idea, but left for a future cleanup. - @Override - protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, - ChannelBuffer buffer) throws Exception { - // This is not strictly needed at this time. It is used to detect - // connection reset detection from netty (for debug) - return null; - } -} + OFMessage singleMessage = null; + List<OFMessage> list = null; + boolean first = true; + for (;;) { + OFMessage message = reader.readFrom(in); + if (message == null) { + break; + } + if (first) { + // first message read + singleMessage = message; + first = false; + } else { + // more messages read, use the list + if (list == null) { + list = new ArrayList<>(); + list.add(singleMessage); + singleMessage = null; + } + list.add(message); + } + } + if (list != null) { + out.add(list); + } else if (singleMessage != null) { + out.add(Collections.singletonList(singleMessage)); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java index 4d6912ad69a9246da975063127fca3b8d97fe0b0..09ca7bd4441b89150d1417c508080243cd98765f 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java @@ -17,33 +17,24 @@ package net.floodlightcontroller.core.internal; -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; import org.projectfloodlight.openflow.protocol.OFMessage; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + + /** - * Encode an openflow message for output into a ChannelBuffer, for use in a + * Encode an iterable of openflow messages for output into a ByteBuf, for use in a * netty pipeline - * @author readams + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> */ -public class OFMessageEncoder extends OneToOneEncoder { - +public class OFMessageEncoder extends MessageToByteEncoder<Iterable<OFMessage>> { @Override - protected Object encode(ChannelHandlerContext ctx, Channel channel, - Object msg) throws Exception { - if (!(msg instanceof Iterable)) - return msg; - - @SuppressWarnings("unchecked") - Iterable<OFMessage> msgList = (Iterable<OFMessage>)msg; - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + protected void encode(ChannelHandlerContext ctx, Iterable<OFMessage> msgList, ByteBuf out) throws Exception { for (OFMessage ofm : msgList) { - ofm.writeTo(buf); + ofm.writeTo(out); } - return buf; } -} +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitch.java similarity index 98% rename from src/main/java/net/floodlightcontroller/core/OFSwitch.java rename to src/main/java/net/floodlightcontroller/core/internal/OFSwitch.java index 1b72fef170fd0a8b3b5827dd1ce39bc747dad533..1c95a2bfe2ff9e84fde91d75daa025d826b095e8 100644 --- a/src/main/java/net/floodlightcontroller/core/OFSwitch.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitch.java @@ -15,7 +15,7 @@ * under the License. **/ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -37,8 +37,18 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.annotation.Nonnull; -import net.floodlightcontroller.core.internal.IOFSwitchManager; -import net.floodlightcontroller.core.internal.TableFeatures; +import net.floodlightcontroller.core.IOFConnection; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.LogicalOFMessageCategory; +import net.floodlightcontroller.core.PortChangeEvent; +import net.floodlightcontroller.core.PortChangeType; +import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted; +import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted; +import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted; +import net.floodlightcontroller.core.IOFSwitch.SwitchStatus; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.core.util.URIUtil; diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java index ddfd008720a6853262905afeb7072cf91c99c3f5..9652f4ac64d60b1e5f31bb2e31b1023fd12120c7 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java @@ -2,9 +2,9 @@ package net.floodlightcontroller.core.internal; import java.util.concurrent.TimeUnit; -import org.jboss.netty.util.Timeout; -import org.jboss.netty.util.Timer; -import org.jboss.netty.util.TimerTask; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState; import org.projectfloodlight.openflow.protocol.OFMessage; diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java index b6bed6556164633f3e169f377d2dc6c3276f7963..b17eec619fd6a67c10f55aea8bca85e2e414925a 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java @@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; -import org.jboss.netty.util.Timer; +import io.netty.util.Timer; import net.floodlightcontroller.core.HARole; import net.floodlightcontroller.core.IOFConnection; diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java index dbf9cc2449c9cfe77cf562296071662f5f478c61..e0f30158c5862a0a48813744d965e70de1204660 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java @@ -1,6 +1,7 @@ package net.floodlightcontroller.core.internal; import java.io.IOException; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Arrays; @@ -16,13 +17,6 @@ import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Executors; - -import org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.group.ChannelGroup; -import org.jboss.netty.channel.group.DefaultChannelGroup; -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.HAListenerTypeMarker; @@ -60,6 +54,7 @@ import org.projectfloodlight.openflow.protocol.OFMessage; import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.OFAuxId; import org.projectfloodlight.openflow.types.TableId; import org.projectfloodlight.openflow.types.U32; @@ -80,6 +75,13 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelOption; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.util.concurrent.GlobalEventExecutor; + /** * The Switch Manager class contains most of the code involved with dealing * with switches. The Switch manager keeps track of the switches known to the controller, @@ -102,7 +104,6 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen private static String keyStorePassword; private static String keyStore; - private static boolean useSsl = false; protected static boolean clearTablesOnInitialConnectAsMaster = false; protected static boolean clearTablesOnEachTransitionToMaster = false; @@ -112,7 +113,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen protected static List<U32> ofBitmaps; protected static OFFactory defaultFactory; - + private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers; private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches; private ConcurrentHashMap<DatapathId, IOFSwitch> syncedSwitches; @@ -129,9 +130,13 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen protected Set<IOFSwitchListener> switchListeners; // Module Dependencies - IFloodlightProviderService floodlightProvider; - IDebugEventService debugEventService; - IDebugCounterService debugCounterService; + private IFloodlightProviderService floodlightProvider; + private IDebugEventService debugEventService; + private IDebugCounterService debugCounterService; + + private NioEventLoopGroup bossGroup; + private NioEventLoopGroup workerGroup; + private DefaultChannelGroup cg; /** IHAListener Implementation **/ @Override @@ -181,7 +186,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); oldSw.disconnect(); } - + /* * Set some other config options for this switch. */ @@ -480,7 +485,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, SwitchDescription description, OFFactory factory, DatapathId datapathId) { - + return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId); } @@ -488,7 +493,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) { floodlightProvider.handleMessage(sw, m, bContext); } - + @Override public void handleOutgoingMessage(IOFSwitch sw, OFMessage m) { floodlightProvider.handleOutgoingMessage(sw, m); @@ -653,7 +658,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen driverRegistry = new NaiveSwitchDriverRegistry(this); this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); - + /* TODO @Ryan try { this.storeClient = this.syncService.getStoreClient( @@ -685,13 +690,11 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen ) ) { log.warn("SSL disabled. Using unsecure connections between Floodlight and switches."); - OFSwitchManager.useSsl = false; OFSwitchManager.keyStore = null; OFSwitchManager.keyStorePassword = null; } else { log.info("SSL enabled. Using secure connections between Floodlight and switches."); log.info("SSL keystore path: {}, password: {}", path, (pass == null ? "" : pass)); - OFSwitchManager.useSsl = true; OFSwitchManager.keyStore = path; OFSwitchManager.keyStorePassword = (pass == null ? "" : pass); } @@ -762,7 +765,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen maxPerDpid = configParams.get("maxTableToReceiveTableMissFlowPerDpid"); } forwardToControllerFlowsUpToTableByDpid = jsonToSwitchTableIdMap(maxPerDpid); - + /* * Get config to determine what versions of OpenFlow we will * support. The versions will determine the hello's header @@ -809,7 +812,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen defaultFactory = computeInitialFactory(ofVersions); ofBitmaps = computeOurVersionBitmaps(ofVersions); } - + /** * Find the max version supplied in the supported * versions list and use it as the default, which @@ -845,7 +848,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen */ return OFFactories.getFactory(highest); } - + /** * Based on the list of OFVersions provided as input (or from Loxi), * create a list of bitmaps for use in version negotiation during a @@ -862,7 +865,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen if (ofVersions == null || ofVersions.isEmpty()) { throw new IllegalStateException("OpenFlow version list should never be null or empty at this point. Make sure it's set in the OFSwitchManager."); } - + int pos = 1; /* initial bitmap in list */ int size = 32; /* size of a U32 */ int tempBitmap = 0; /* maintain the current bitmap we're working on */ @@ -978,45 +981,51 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen */ public void bootstrapNetty() { try { - final ServerBootstrap bootstrap = createServerBootStrap(); - - bootstrap.setOption("reuseAddr", true); - bootstrap.setOption("child.keepAlive", true); - bootstrap.setOption("child.tcpNoDelay", true); - bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); - - ChannelPipelineFactory pfact = useSsl ? new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService, ofBitmaps, defaultFactory, keyStore, keyStorePassword) : - new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService, ofBitmaps, defaultFactory); + bossGroup = new NioEventLoopGroup(); + workerGroup = new NioEventLoopGroup(); + + ServerBootstrap bootstrap = new ServerBootstrap() + .group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_REUSEADDR, true) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.TCP_NODELAY, true) + .option(ChannelOption.SO_SNDBUF, Controller.SEND_BUFFER_SIZE); + + + OFChannelInitializer initializer = new OFChannelInitializer( + this, + this, + debugCounterService, + floodlightProvider.getTimer(), + ofBitmaps, + defaultFactory, + keyStore, + keyStorePassword); + + bootstrap.childHandler(initializer); + + cg = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + + Set<InetSocketAddress> addrs = new HashSet<InetSocketAddress>(); + if (floodlightProvider.getOFAddresses().isEmpty()) { + cg.add(bootstrap.bind(addrs.iterator().next()).channel()); + } else { + for (IPv4Address ip : floodlightProvider.getOFAddresses()) { + addrs.add(new InetSocketAddress(InetAddress.getByAddress(ip.getBytes()), floodlightProvider.getOFPort().getPort())); + } + } - bootstrap.setPipelineFactory(pfact); - InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort()); - final ChannelGroup cg = new DefaultChannelGroup(); - cg.add(bootstrap.bind(sa)); + for (InetSocketAddress sa : addrs) { + cg.add(bootstrap.bind(sa).channel()); + log.info("Listening for switch connections on {}", sa); + } - log.info("Listening for switch connections on {}", sa); } catch (Exception e) { throw new RuntimeException(e); } } - /** - * Helper that bootstrapNetty. - * @return - */ - private ServerBootstrap createServerBootStrap() { - if (floodlightProvider.getWorkerThreads() == 0) { - return new ServerBootstrap( - new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool())); - } else { - return new ServerBootstrap( - new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads())); - } - } - /** * Performs startup related actions for logical OF message categories. * Setting the categories list to immutable ensures that unsupported operation diff --git a/src/main/java/net/floodlightcontroller/core/util/NettyUtils.java b/src/main/java/net/floodlightcontroller/core/util/NettyUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..88e5a1b9e927f6fbb7c730c3427f6f08ad265c99 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/util/NettyUtils.java @@ -0,0 +1,105 @@ +package net.floodlightcontroller.core.util; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.EventLoopGroup; +import io.netty.util.concurrent.Future; + +/** Collection of static utilitiy functions for netty. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class NettyUtils { + private static final Logger logger = LoggerFactory.getLogger(NettyUtils.class); + + private static final long SHUTDOWN_TIMEOUT = 20; + private static final TimeUnit SHUTDOWN_TIMEOUT_UNIT = TimeUnit.SECONDS; + + private NettyUtils() {} + + /** + * Shuts down an event group gracefully and waits for the corresponding Future to complete. Logs + * any exceptions. + * + * TODO: may want to force a shutdown if the graceful shutdown fails + * + * @param name - name of the even group to be shut down (for logging) + * @param group to be shut down + * @throws InterruptedException - if the thread is interrupted while shutting down + */ + public static void shutdownAndWait(String name, EventLoopGroup group) throws InterruptedException { + try { + logger.debug("Shutting down {}", name); + Future<?> shutdownFuture = group.shutdownGracefully(); + shutdownFuture.get(SHUTDOWN_TIMEOUT, SHUTDOWN_TIMEOUT_UNIT); + logger.debug("Done shutting down {}", name); + } catch (ExecutionException e) { + /*** + * @id NETTYUTIL4001 + * @desc A netty event loop group failed to shutdown + * @action #support if encountered repeatedly + * @param name the name of the event loop group + * @param e the exception + */ + logger.warn("NETTYUTIL4001: Error during shutdown of {}: {}", name, e); + } catch (TimeoutException e) { + /*** + * @id NETTYUTIL4002 + * @desc A netty event loop group failed to shutdown + * @action #support if encountered repeatedly + * @param name the name of the event loop group + * @param e the exception + */ + logger.warn("NETTYUTIL4002: Graceful shutdown of {} timed out: {}", name, e); + } + } + + /** Wait for the supplied set of futures to complete. Logs any exceptions occur. + * + * @param name name of futures to wait on for logging + * @param shutdownFutures futures to wait on + * @throws InterruptedException if process is interrupted + */ + public static void waitOrLog(String name, Future<?>... shutdownFutures) + throws InterruptedException { + logger.debug("Shutting down {}", name); + long limit = System.nanoTime() + SHUTDOWN_TIMEOUT_UNIT.toNanos(SHUTDOWN_TIMEOUT); + + for(Future<?> f: shutdownFutures) { + try { + long wait = limit - System.nanoTime(); + if(wait > 0) { + f.get(wait, TimeUnit.NANOSECONDS); + logger.debug("Done shutting down {}", name); + } else { + throw new TimeoutException("timed out waiting for shutdown"); + } + } catch (ExecutionException e) { + /*** + * @id NETTYUTIL4003 + * @desc An error was encountered waiting for completion of future. + * @action #support if encountered repeatedly + * @param name the name of the future + * @param e the exception + */ + logger.warn("Error during completion of {}: {}", name, e); + } catch (TimeoutException e) { + /*** + * @id NETTYUTIL4004 + * @desc A timeout was encountered waiting for completion of future. + * @action #support if encountered repeatedly + * @param name the name of the future + * @param e the exception + */ + logger.warn("Graceful shutdown of {} timed out: {}", name, e); + break; + } + + } + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java index 3481e974505c4bcdfe50801a60a40848796c6ecd..0c6a520e3161a05f6589f09b1e152ebf78ff5b9c 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java @@ -409,7 +409,7 @@ public class StatsReplySerializer extends JsonSerializer<StatsReply> { jGen.writeStringField("version", meterConfigReply.getVersion().toString()); //return the enum name jGen.writeFieldName("meterConfig"); jGen.writeStartArray(); - for(OFMeterBand band : meterConfigReply.getEntries()) { + for (OFMeterBand band : meterConfigReply.getEntries()) { jGen.writeStartObject(); short type = (short)band.getType(); jGen.writeNumberField("bandType",type); diff --git a/src/test/java/net/floodlightcontroller/core/internal/MockOFSwitchImpl.java b/src/test/java/net/floodlightcontroller/core/internal/MockOFSwitchImpl.java index 846f4f7b82ad89a557f6b30aaf0b1ddacd6f1675..0fcbc88c19b217e6d67141acc9f44b5f093c8046 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/MockOFSwitchImpl.java +++ b/src/test/java/net/floodlightcontroller/core/internal/MockOFSwitchImpl.java @@ -7,7 +7,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import org.easymock.EasyMock; -import net.floodlightcontroller.core.OFSwitch; import org.projectfloodlight.openflow.protocol.OFCapabilities; import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFStatsReply; diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java index 96147b02eb52b4323be4f804ffad6014c552809b..2460b3a7687c93ba64c32af6779ea7517847e031 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer10Test.java @@ -24,22 +24,20 @@ import org.easymock.Capture; import org.easymock.CaptureType; import org.easymock.EasyMock; import org.hamcrest.CoreMatchers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.ExceptionEvent; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timer; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; + import org.junit.After; import org.junit.Before; import org.junit.Test; import net.floodlightcontroller.core.IOFConnectionBackend; -import net.floodlightcontroller.core.OFConnectionCounters; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandler; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandshakeTimeout; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineHandler; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineHandshakeTimeout; import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl; import net.floodlightcontroller.debugcounter.IDebugCounterService; @@ -67,6 +65,7 @@ import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.U32; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; @@ -78,13 +77,10 @@ public class OFChannelHandlerVer10Test { private Channel channel; private Timer timer; private ChannelHandlerContext ctx; - private MessageEvent messageEvent; - private ChannelStateEvent channelStateEvent; private ChannelPipeline pipeline; - // FIXME:LOJI: Currently only use OF 1.0 private final OFFactory factory = OFFactories.getFactory(OFVersion.OF_10); - private Capture<ExceptionEvent> exceptionEventCapture; + private Capture<Throwable> exceptionEventCapture; private Capture<List<OFMessage>> writeCapture; private OFPortDesc portDesc; @@ -121,11 +117,9 @@ public class OFChannelHandlerVer10Test { newFeaturesReply = new Capture<OFFeaturesReply>(); ctx = createMock(ChannelHandlerContext.class); - channelStateEvent = createMock(ChannelStateEvent.class); channel = createMock(Channel.class); timer = new HashedWheelTimer(); - messageEvent = createMock(MessageEvent.class); - exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL); + exceptionEventCapture = new Capture<Throwable>(CaptureType.ALL); pipeline = createMock(ChannelPipeline.class); writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL); seenXids = null; @@ -150,16 +144,14 @@ public class OFChannelHandlerVer10Test { replay(switchManager); // Mock ctx and channelStateEvent - expect(ctx.getChannel()).andReturn(channel).anyTimes(); - expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes(); - replay(ctx, channelStateEvent); + expect(ctx.channel()).andReturn(channel).anyTimes(); + expect(ctx.fireExceptionCaught(capture(exceptionEventCapture))).andReturn(ctx).anyTimes(); + replay(ctx); /* Setup an exception event capture on the channel. Right now * we only expect exception events to be send up the channel. * However, it's easy to extend to other events if we need it */ - pipeline.sendUpstream(capture(exceptionEventCapture)); - expectLastCall().anyTimes(); expect(pipeline.get(OFMessageDecoder.class)).andReturn(new OFMessageDecoder()).anyTimes(); replay(pipeline); } @@ -168,40 +160,26 @@ public class OFChannelHandlerVer10Test { public void tearDown() { /* ensure no exception was thrown */ if (exceptionEventCapture.hasCaptured()) { - Throwable ex = exceptionEventCapture.getValue().getCause(); + Throwable ex = exceptionEventCapture.getValue(); ex.printStackTrace(); - throw new AssertionError("Unexpected exception: " + - ex.getClass().getName() + "(" + ex + ")"); + Throwables.propagate(ex); } assertFalse("Unexpected messages have been captured", writeCapture.hasCaptured()); // verify all mocks. verify(channel); - verify(messageEvent); verify(switchManager); verify(ctx); - verify(channelStateEvent); verify(pipeline); } /** Reset the channel mock and set basic method call expectations */ void resetChannel() { reset(channel); - expect(channel.getPipeline()).andReturn(pipeline).anyTimes(); - expect(channel.getRemoteAddress()).andReturn(InetSocketAddress.createUnresolved("1.1.1.1", 80)).anyTimes(); - } - - - /** reset, setup, and replay the messageEvent mock for the given - * messages - */ - void setupMessageEvent(List<OFMessage> messages) { - reset(messageEvent); - expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce(); - replay(messageEvent); + expect(channel.pipeline()).andReturn(pipeline).anyTimes(); + expect(channel.remoteAddress()).andReturn(InetSocketAddress.createUnresolved("1.1.1.1", 80)).anyTimes(); } - /** reset, setup, and replay the messageEvent mock for the given * messages, mock controller send message to channel handler * @@ -209,7 +187,6 @@ public class OFChannelHandlerVer10Test { */ void sendMessageToHandlerWithControllerReset(List<OFMessage> messages) throws Exception { - sendMessageToHandlerNoControllerReset(messages); } @@ -220,9 +197,7 @@ public class OFChannelHandlerVer10Test { */ void sendMessageToHandlerNoControllerReset(List<OFMessage> messages) throws Exception { - setupMessageEvent(messages); - - handler.messageReceived(ctx, messageEvent); + handler.channelRead(ctx, messages); } /** @@ -256,7 +231,7 @@ public class OFChannelHandlerVer10Test { Class<? extends Throwable> expectedExceptionClass) { assertTrue("Excpected exception not thrown", exceptionEventCapture.hasCaptured()); - Throwable caughtEx = exceptionEventCapture.getValue().getCause(); + Throwable caughtEx = exceptionEventCapture.getValue(); assertEquals(expectedExceptionClass, caughtEx.getClass()); exceptionEventCapture.reset(); } @@ -277,16 +252,21 @@ public class OFChannelHandlerVer10Test { seenXids.add(xid); } } - + + @Test + public void testNullMsg() throws Exception { + reset(ctx); + expect(ctx.fireChannelRead(null)).andReturn(ctx).once(); + replay(ctx, channel); + + // null message is not passed to the handler + handler.channelRead(ctx, null); + verify(channel, ctx); + } @Test public void testInitState() throws Exception { - // Message event needs to be list - expect(messageEvent.getMessage()).andReturn(null); - replay(channel, messageEvent); - handler.messageReceived(ctx, messageEvent); - verify(channel, messageEvent); - verifyExceptionCaptured(AssertionError.class); + replay(channel); // We don't expect to receive /any/ messages in init state since // channelConnected moves us to a different state @@ -302,13 +282,10 @@ public class OFChannelHandlerVer10Test { public void moveToWaitHello() throws Exception { resetChannel(); - channel.write(capture(writeCapture)); - expectLastCall().andReturn(null).once(); + expect(channel.writeAndFlush(capture(writeCapture))).andReturn(null).once(); replay(channel); - // replay unused mocks - replay(messageEvent); - handler.channelConnected(ctx, channelStateEvent); + handler.channelActive(ctx); List<OFMessage> msgs = getMessagesFromCapture(); assertEquals(1, msgs.size()); @@ -327,8 +304,7 @@ public class OFChannelHandlerVer10Test { moveToWaitHello(); resetChannel(); - channel.write(capture(writeCapture)); - expectLastCall().andReturn(null).atLeastOnce(); + expect(channel.writeAndFlush(capture(writeCapture))).andReturn(null).atLeastOnce(); replay(channel); OFMessage hello = factory.buildHello().build(); @@ -387,8 +363,7 @@ public class OFChannelHandlerVer10Test { newConnection.getValue().setListener(connectionListener); resetChannel(); - channel.write(capture(writeCapture)); - expectLastCall().andReturn(null).atLeastOnce(); + expect(channel.writeAndFlush(capture(writeCapture))).andReturn(null).atLeastOnce(); replay(channel); // Send echo request. expect reply diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java index 9b9b6ce897bf00c210326fed7d49e315500e11eb..6764bdef866c9d61dd65628e8ca0eb9413cfc9a7 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerVer13Test.java @@ -24,22 +24,20 @@ import org.easymock.Capture; import org.easymock.CaptureType; import org.easymock.EasyMock; import org.hamcrest.CoreMatchers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.ExceptionEvent; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timer; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; + import org.junit.After; import org.junit.Before; import org.junit.Test; import net.floodlightcontroller.core.IOFConnectionBackend; -import net.floodlightcontroller.core.OFConnectionCounters; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandler; -import net.floodlightcontroller.core.internal.OpenflowPipelineFactory.PipelineHandshakeTimeout; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineHandler; +import net.floodlightcontroller.core.internal.OFChannelInitializer.PipelineHandshakeTimeout; import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl; import net.floodlightcontroller.debugcounter.IDebugCounterService; @@ -68,6 +66,7 @@ import org.projectfloodlight.openflow.types.OFAuxId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.U32; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; @@ -82,12 +81,10 @@ public class OFChannelHandlerVer13Test { private Channel channel; private Timer timer; private ChannelHandlerContext ctx; - private MessageEvent messageEvent; - private ChannelStateEvent channelStateEvent; private ChannelPipeline pipeline; private final OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); - private Capture<ExceptionEvent> exceptionEventCapture; + private Capture<Throwable> exceptionEventCapture; private Capture<List<OFMessage>> writeCapture; private OFFeaturesReply featuresReply; @@ -123,11 +120,9 @@ public class OFChannelHandlerVer13Test { newFeaturesReply = new Capture<OFFeaturesReply>(); ctx = createMock(ChannelHandlerContext.class); - channelStateEvent = createMock(ChannelStateEvent.class); channel = createMock(Channel.class); timer = new HashedWheelTimer(); - messageEvent = createMock(MessageEvent.class); - exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL); + exceptionEventCapture = new Capture<Throwable>(CaptureType.ALL); pipeline = createMock(ChannelPipeline.class); writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL); seenXids = null; @@ -154,16 +149,14 @@ public class OFChannelHandlerVer13Test { replay(switchManager); // Mock ctx and channelStateEvent - expect(ctx.getChannel()).andReturn(channel).anyTimes(); - expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes(); - replay(ctx, channelStateEvent); + expect(ctx.channel()).andReturn(channel).anyTimes(); + expect(ctx.fireExceptionCaught(capture(exceptionEventCapture))).andReturn(ctx).anyTimes(); + replay(ctx); /* Setup an exception event capture on the channel. Right now * we only expect exception events to be send up the channel. * However, it's easy to extend to other events if we need it */ - pipeline.sendUpstream(capture(exceptionEventCapture)); - expectLastCall().anyTimes(); expect(pipeline.get(OFMessageDecoder.class)).andReturn(new OFMessageDecoder()).anyTimes(); replay(pipeline); } @@ -172,40 +165,26 @@ public class OFChannelHandlerVer13Test { public void tearDown() { /* ensure no exception was thrown */ if (exceptionEventCapture.hasCaptured()) { - Throwable ex = exceptionEventCapture.getValue().getCause(); + Throwable ex = exceptionEventCapture.getValue(); ex.printStackTrace(); - throw new AssertionError("Unexpected exception: " + - ex.getClass().getName() + "(" + ex + ")"); + Throwables.propagate(ex); } assertFalse("Unexpected messages have been captured", writeCapture.hasCaptured()); // verify all mocks. verify(channel); - verify(messageEvent); verify(switchManager); verify(ctx); - verify(channelStateEvent); verify(pipeline); } /** Reset the channel mock and set basic method call expectations */ void resetChannel() { reset(channel); - expect(channel.getPipeline()).andReturn(pipeline).anyTimes(); - expect(channel.getRemoteAddress()).andReturn(null).anyTimes(); + expect(channel.pipeline()).andReturn(pipeline).anyTimes(); + expect(channel.remoteAddress()).andReturn(null).anyTimes(); } - - /** reset, setup, and replay the messageEvent mock for the given - * messages - */ - void setupMessageEvent(List<OFMessage> messages) { - reset(messageEvent); - expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce(); - replay(messageEvent); - } - - /** reset, setup, and replay the messageEvent mock for the given * messages, mock controller send message to channel handler * @@ -213,7 +192,6 @@ public class OFChannelHandlerVer13Test { */ void sendMessageToHandlerWithControllerReset(List<OFMessage> messages) throws Exception { - sendMessageToHandlerNoControllerReset(messages); } @@ -224,9 +202,7 @@ public class OFChannelHandlerVer13Test { */ void sendMessageToHandlerNoControllerReset(List<OFMessage> messages) throws Exception { - setupMessageEvent(messages); - - handler.messageReceived(ctx, messageEvent); + handler.channelRead(ctx, messages); } /** @@ -256,11 +232,9 @@ public class OFChannelHandlerVer13Test { * expectedExceptionClass. * Resets the capture */ - void verifyExceptionCaptured( - Class<? extends Throwable> expectedExceptionClass) { - assertTrue("Excpected exception not thrown", - exceptionEventCapture.hasCaptured()); - Throwable caughtEx = exceptionEventCapture.getValue().getCause(); + void verifyExceptionCaptured(Class<? extends Throwable> expectedExceptionClass) { + assertTrue("Excpected exception not thrown", exceptionEventCapture.hasCaptured()); + Throwable caughtEx = exceptionEventCapture.getValue(); assertEquals(expectedExceptionClass, caughtEx.getClass()); exceptionEventCapture.reset(); } @@ -282,15 +256,20 @@ public class OFChannelHandlerVer13Test { } } + @Test + public void testNullMsg() throws Exception { + reset(ctx); + expect(ctx.fireChannelRead(null)).andReturn(ctx).once(); + replay(ctx, channel); + + // null message is not passed to the handler + handler.channelRead(ctx, null); + verify(channel, ctx); + } @Test public void testInitState() throws Exception { - // Message event needs to be list - expect(messageEvent.getMessage()).andReturn(null); - replay(channel, messageEvent); - handler.messageReceived(ctx, messageEvent); - verify(channel, messageEvent); - verifyExceptionCaptured(AssertionError.class); + replay(channel); // We don't expect to receive /any/ messages in init state since // channelConnected moves us to a different state @@ -305,13 +284,10 @@ public class OFChannelHandlerVer13Test { @Test public void moveToWaitHello() throws Exception { resetChannel(); - channel.write(capture(writeCapture)); - expectLastCall().andReturn(null).once(); + expect(channel.writeAndFlush(capture(writeCapture))).andReturn(null).once(); replay(channel); - // replay unused mocks - replay(messageEvent); - handler.channelConnected(ctx, channelStateEvent); + handler.channelActive(ctx); List<OFMessage> msgs = getMessagesFromCapture(); assertEquals(1, msgs.size()); @@ -328,8 +304,7 @@ public class OFChannelHandlerVer13Test { public void moveToWaitFeaturesReply() throws Exception { moveToWaitHello(); resetChannel(); - channel.write(capture(writeCapture)); - expectLastCall().andReturn(null).atLeastOnce(); + expect(channel.writeAndFlush(capture(writeCapture))).andReturn(null).once(); replay(channel); OFMessage hello = factory.buildHello().build(); @@ -388,8 +363,7 @@ public class OFChannelHandlerVer13Test { newConnection.getValue().setListener(connectionListener); resetChannel(); - channel.write(capture(writeCapture)); - expectLastCall().andReturn(null).atLeastOnce(); + expect(channel.writeAndFlush(capture(writeCapture))).andReturn(null).once(); replay(channel); // Send echo request. expect reply diff --git a/src/test/java/net/floodlightcontroller/core/OFConnectionTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFConnectionTest.java similarity index 94% rename from src/test/java/net/floodlightcontroller/core/OFConnectionTest.java rename to src/test/java/net/floodlightcontroller/core/internal/OFConnectionTest.java index d65788b36a3cff928e09301fdeb1362f3f78121d..24d39515c6b8dd9d93208959632e7fe1da1249d7 100644 --- a/src/test/java/net/floodlightcontroller/core/OFConnectionTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFConnectionTest.java @@ -1,4 +1,4 @@ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.expect; @@ -13,12 +13,18 @@ import org.easymock.Capture; import org.easymock.EasyMock; import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timer; + +import io.netty.channel.Channel; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; + import org.junit.Before; import org.junit.Test; +import net.floodlightcontroller.core.SwitchDisconnectedException; +import net.floodlightcontroller.core.internal.OFConnection; +import net.floodlightcontroller.core.internal.OFConnectionCounters; +import net.floodlightcontroller.core.internal.OFErrorMsgException; import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl; import net.floodlightcontroller.debugcounter.IDebugCounterService; @@ -142,9 +148,9 @@ public class OFConnectionTest { } private Capture<List<OFMessage>> prepareChannelForWriteList() { - EasyMock.expect(channel.isConnected()).andReturn(Boolean.TRUE).anyTimes(); + EasyMock.expect(channel.isActive()).andReturn(Boolean.TRUE).anyTimes(); Capture<List<OFMessage>> cMsgList = new Capture<>(); - expect(channel.write(capture(cMsgList))).andReturn(null).once(); + expect(channel.writeAndFlush(capture(cMsgList))).andReturn(null).once(); replay(channel); return cMsgList; } @@ -181,7 +187,7 @@ public class OFConnectionTest { @Test(timeout = 5000) public void testWriteRequestNotConnectedFailure() throws InterruptedException, ExecutionException { - EasyMock.expect(channel.isConnected()).andReturn(Boolean.FALSE).anyTimes(); + EasyMock.expect(channel.isActive()).andReturn(Boolean.FALSE).anyTimes(); replay(channel); OFEchoRequest echoRequest = factory.echoRequest(new byte[] {}); diff --git a/src/test/java/net/floodlightcontroller/core/OFSwitchBaseTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchBaseTest.java similarity index 98% rename from src/test/java/net/floodlightcontroller/core/OFSwitchBaseTest.java rename to src/test/java/net/floodlightcontroller/core/internal/OFSwitchBaseTest.java index 24db287af6da5c28214280f1a240991dafc27e55..8fefbfbf162c7dd51533f23b4e51ff36f229a627 100644 --- a/src/test/java/net/floodlightcontroller/core/OFSwitchBaseTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchBaseTest.java @@ -14,7 +14,7 @@ * under the License. **/ -package net.floodlightcontroller.core; +package net.floodlightcontroller.core.internal; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; @@ -41,7 +41,17 @@ import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.LogicalOFMessageCategory; +import net.floodlightcontroller.core.PortChangeEvent; +import net.floodlightcontroller.core.PortChangeType; +import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted; +import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted; +import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted; import net.floodlightcontroller.core.internal.IOFSwitchManager; +import net.floodlightcontroller.core.internal.OFSwitch; import net.floodlightcontroller.core.internal.SwitchManagerCounters; import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl; import net.floodlightcontroller.debugcounter.IDebugCounterService; diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java index 675873a5eeac46c7e8db6cef30e31ea02680fd08..23cc4f12e661dc4043e9a85509464201179470e3 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java @@ -27,9 +27,9 @@ import java.util.concurrent.TimeUnit; import org.easymock.EasyMock; import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; -import org.jboss.netty.util.Timeout; -import org.jboss.netty.util.Timer; -import org.jboss.netty.util.TimerTask; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer10Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer10Test.java index be752d0246f9075751fae5d2f321a7ee4af85ac7..d940ed4d55ee6da5e922d871a8319a6ce2437457 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer10Test.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer10Test.java @@ -16,11 +16,12 @@ import java.util.EnumSet; import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; import org.junit.Test; + import net.floodlightcontroller.core.IOFSwitchBackend; -import net.floodlightcontroller.core.OFConnection; import net.floodlightcontroller.core.SwitchDescription; import net.floodlightcontroller.core.internal.OFSwitchAppHandshakePlugin.PluginResultType; import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState; + import org.projectfloodlight.openflow.protocol.OFActionType; import org.projectfloodlight.openflow.protocol.OFCapabilities; import org.projectfloodlight.openflow.protocol.OFControllerRole; diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java index 9cb4c82167651f09f48588bc085e460103220e23..7f8393f65b704c26e3b865c93a2518494439e7f3 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java @@ -18,7 +18,6 @@ import org.hamcrest.Matchers; import org.junit.Test; import net.floodlightcontroller.core.IOFSwitchBackend; -import net.floodlightcontroller.core.OFConnection; import net.floodlightcontroller.core.SwitchDescription; import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState; import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitTableFeaturesReplyState; diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java index 62d43ab96a1305cb89e0df40ae14df5ee9f89fd2..6f5312ae2670344d91791bd4b87292a4ee5078e1 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java @@ -35,7 +35,7 @@ import static org.junit.Assert.fail; import java.util.List; -import org.jboss.netty.util.Timer; +import io.netty.util.Timer; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -50,8 +50,6 @@ import net.floodlightcontroller.core.IOFSwitchListener; import net.floodlightcontroller.core.IShutdownListener; import net.floodlightcontroller.core.IShutdownService; import net.floodlightcontroller.core.LogicalOFMessageCategory; -import net.floodlightcontroller.core.NullConnection; -import net.floodlightcontroller.core.OFSwitch; import net.floodlightcontroller.core.PortChangeType; import net.floodlightcontroller.core.SwitchDescription; import net.floodlightcontroller.core.module.FloodlightModuleContext; diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchTest.java index b5ca01ed6884656e520c40ccd5cc284e88eae5f9..4ddef9978888e2c77763e9fb95a9362453cf9656 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchTest.java @@ -29,12 +29,13 @@ import java.util.List; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; + import net.floodlightcontroller.core.IOFSwitchBackend; -import net.floodlightcontroller.core.OFSwitch; import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted; import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted; import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted; import net.floodlightcontroller.core.util.URIUtil; + import org.projectfloodlight.openflow.protocol.OFBsnControllerConnection; import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionState; import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply; diff --git a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java index f5f89350abb048234cd368bc773f45187ff98f05..adab6d540995123d559b59b84e0bdc879ef621a2 100644 --- a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java +++ b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java @@ -35,8 +35,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.jboss.netty.util.Timer; - +import io.netty.util.Timer; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.HAListenerTypeMarker; import net.floodlightcontroller.core.HARole; @@ -59,6 +58,8 @@ import net.floodlightcontroller.core.util.ListenerDispatcher; import org.projectfloodlight.openflow.protocol.OFMessage; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.TransportPort; import net.floodlightcontroller.packet.Ethernet; @@ -74,8 +75,8 @@ public class MockFloodlightProvider implements IFloodlightModule, IFloodlightPro protected ConcurrentMap<OFType, ListenerDispatcher<OFType,IOFMessageListener>> listeners; protected ListenerDispatcher<HAListenerTypeMarker, IHAListener> haListeners; private HARole role; - private final String openFlowHostname = "127.0.0.1"; - private final int openFlowPort = 6653; + private final Set<IPv4Address> openFlowHostname = Collections.singleton(IPv4Address.of("127.0.0.1")); + private final TransportPort openFlowPort = TransportPort.of(6653); private final boolean useAsyncUpdates; private volatile ExecutorService executorService; private volatile Future<?> mostRecentUpdateFuture; @@ -378,12 +379,12 @@ public class MockFloodlightProvider implements IFloodlightModule, IFloodlightPro } @Override - public String getOFHostname() { + public Set<IPv4Address> getOFAddresses() { return openFlowHostname; } @Override - public int getOFPort() { + public TransportPort getOFPort() { return openFlowPort; } diff --git a/src/test/java/net/floodlightcontroller/debugcounter/OFConnectionCountersTest.java b/src/test/java/net/floodlightcontroller/debugcounter/OFConnectionCountersTest.java index c82eb132c050eef6b9acedc0cde5936dd2545154..46984522e60e9af43a471a42e8cc5c6f759c3deb 100644 --- a/src/test/java/net/floodlightcontroller/debugcounter/OFConnectionCountersTest.java +++ b/src/test/java/net/floodlightcontroller/debugcounter/OFConnectionCountersTest.java @@ -7,7 +7,7 @@ import java.util.ArrayList; import org.junit.Before; import org.junit.Test; -import net.floodlightcontroller.core.OFConnectionCounters; +import net.floodlightcontroller.core.internal.OFConnectionCounters; import org.projectfloodlight.openflow.protocol.OFAsyncGetReply; import org.projectfloodlight.openflow.protocol.OFAsyncGetRequest; diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java index c4005b32aaec719cfd0f4f43732bacc941f75bb3..119b7acf8dcba7ca15ca9d5bf89a92ce798c5483 100644 --- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java +++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java @@ -28,8 +28,8 @@ import java.util.Set; import net.floodlightcontroller.core.IOFConnection; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.LogicalOFMessageCategory; -import net.floodlightcontroller.core.OFConnection; import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.core.internal.OFConnection; import net.floodlightcontroller.core.internal.TableFeatures; import org.projectfloodlight.openflow.protocol.OFActionType;