diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-22 10:02:05 -0800 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-22 10:02:05 -0800 |
commit | 77ce3be7567bd01c66d8ee88a93b485666723501 (patch) | |
tree | 283e7f39a501750bbd705fbb91645b20198900f1 /framework/src/onos/openflow/ctl | |
parent | 00e6500d0813dcbccaaa741ef38cc1eae6d11e07 (diff) |
Removed patch path since changes have been merged upstream to a different path. Updated README with directions.
Change-Id: Ie419abd2d3d3ef7315de9f607dcd757a78190995
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/openflow/ctl')
23 files changed, 0 insertions, 4756 deletions
diff --git a/framework/src/onos/openflow/ctl/pom.xml b/framework/src/onos/openflow/ctl/pom.xml deleted file mode 100644 index 56d48550..00000000 --- a/framework/src/onos/openflow/ctl/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ -<!-- - ~ Copyright 2014 Open Networking Laboratory - ~ - ~ 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. - --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onosproject</groupId> - <artifactId>onos-of</artifactId> - <version>1.4.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <artifactId>onos-of-ctl</artifactId> - <packaging>bundle</packaging> - - <description>ONOS OpenFlow controller subsystem API</description> - - <dependencies> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-api</artifactId> - </dependency> - <dependency> - <groupId>io.netty</groupId> - <artifactId>netty</artifactId> - </dependency> - <dependency> - <groupId>org.apache.felix</groupId> - <artifactId>org.apache.felix.scr.annotations</artifactId> - </dependency> - <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.compendium</artifactId> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-scr-plugin</artifactId> - </plugin> - <plugin> - <groupId>org.onosproject</groupId> - <artifactId>onos-maven-plugin</artifactId> - </plugin> - </plugins> - </build> - -</project> diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java deleted file mode 100644 index d9848be5..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -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 org.onlab.util.ItemNotFoundException; -import org.onosproject.net.DeviceId; -import org.onosproject.net.driver.DefaultDriverData; -import org.onosproject.net.driver.DefaultDriverHandler; -import org.onosproject.net.driver.Driver; -import org.onosproject.net.driver.DriverService; -import org.onosproject.openflow.controller.Dpid; -import org.onosproject.openflow.controller.driver.OpenFlowAgent; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; -import org.projectfloodlight.openflow.protocol.OFDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFFactories; -import org.projectfloodlight.openflow.protocol.OFFactory; -import org.projectfloodlight.openflow.protocol.OFVersion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.TrustManagerFactory; -import java.io.FileInputStream; -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.net.InetSocketAddress; -import java.security.KeyStore; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.onlab.util.Tools.get; -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.net.DeviceId.deviceId; -import static org.onosproject.openflow.controller.Dpid.uri; - - -/** - * The main controller class. Handles all setup and network listeners - * - Distributed ownership control of switch through IControllerRegistryService - */ -public class Controller { - - protected static final Logger log = LoggerFactory.getLogger(Controller.class); - - protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13); - protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10); - private static final boolean TLS_DISABLED = false; - private static final short MIN_KS_LENGTH = 6; - - protected HashMap<String, String> controllerNodeIPsCache; - - private ChannelGroup cg; - - // Configuration options - protected List<Integer> openFlowPorts = ImmutableList.of(6633, 6653); - protected int workerThreads = 16; - - // Start time of the controller - protected long systemStartTime; - - private OpenFlowAgent agent; - - private NioServerSocketChannelFactory execFactory; - - protected String ksLocation; - protected String tsLocation; - protected char[] ksPwd; - protected char[] tsPwd; - protected SSLEngine serverSSLEngine; - - // Perf. related configuration - protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; - private DriverService driverService; - private boolean enableOFTLS = TLS_DISABLED; - - // *************** - // Getters/Setters - // *************** - - public OFFactory getOFMessageFactory10() { - return FACTORY10; - } - - - public OFFactory getOFMessageFactory13() { - return FACTORY13; - } - - // ************** - // Initialization - // ************** - - /** - * Tell controller that we're ready to accept switches loop. - */ - public void run() { - - 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 = - new OpenflowPipelineFactory(this, null, serverSSLEngine); - bootstrap.setPipelineFactory(pfact); - cg = new DefaultChannelGroup(); - openFlowPorts.forEach(port -> { - InetSocketAddress sa = new InetSocketAddress(port); - cg.add(bootstrap.bind(sa)); - log.info("Listening for switch connections on {}", sa); - }); - - } catch (Exception e) { - throw new RuntimeException(e); - } - - } - - private ServerBootstrap createServerBootStrap() { - - if (workerThreads == 0) { - execFactory = new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")), - Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d"))); - return new ServerBootstrap(execFactory); - } else { - execFactory = new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")), - Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")), workerThreads); - return new ServerBootstrap(execFactory); - } - } - - public void setConfigParams(Dictionary<?, ?> properties) { - String ports = get(properties, "openflowPorts"); - if (!Strings.isNullOrEmpty(ports)) { - this.openFlowPorts = Stream.of(ports.split(",")) - .map(s -> Integer.parseInt(s)) - .collect(Collectors.toList()); - } - log.debug("OpenFlow ports set to {}", this.openFlowPorts); - - String threads = get(properties, "workerThreads"); - if (!Strings.isNullOrEmpty(threads)) { - this.workerThreads = Integer.parseInt(threads); - } - log.debug("Number of worker threads set to {}", this.workerThreads); - } - - /** - * Initialize internal data structures. - */ - public void init() { - // These data structures are initialized here because other - // module's startUp() might be called before ours - this.controllerNodeIPsCache = new HashMap<>(); - - this.systemStartTime = System.currentTimeMillis(); - - try { - getTLSParameters(); - if (enableOFTLS) { - initSSL(); - } - } catch (Exception ex) { - log.error("SSL init failed: {}", ex.getMessage()); - } - - } - - private void getTLSParameters() { - String tempString = System.getProperty("enableOFTLS"); - enableOFTLS = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString); - log.info("OpenFlow Security is {}", enableOFTLS ? "enabled" : "disabled"); - if (enableOFTLS) { - ksLocation = System.getProperty("javax.net.ssl.keyStore"); - if (Strings.isNullOrEmpty(ksLocation)) { - enableOFTLS = TLS_DISABLED; - return; - } - tsLocation = System.getProperty("javax.net.ssl.trustStore"); - if (Strings.isNullOrEmpty(tsLocation)) { - enableOFTLS = TLS_DISABLED; - return; - } - ksPwd = System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(); - if (MIN_KS_LENGTH > ksPwd.length) { - enableOFTLS = TLS_DISABLED; - return; - } - tsPwd = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray(); - if (MIN_KS_LENGTH > tsPwd.length) { - enableOFTLS = TLS_DISABLED; - return; - } - } - } - - private void initSSL() throws Exception { - - TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - KeyStore ts = KeyStore.getInstance("JKS"); - ts.load(new FileInputStream(tsLocation), tsPwd); - tmFactory.init(ts); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(ksLocation), ksPwd); - kmf.init(ks, ksPwd); - - SSLContext serverContext = SSLContext.getInstance("TLS"); - serverContext.init(kmf.getKeyManagers(), tmFactory.getTrustManagers(), null); - - serverSSLEngine = serverContext.createSSLEngine(); - - serverSSLEngine.setNeedClientAuth(true); - serverSSLEngine.setUseClientMode(false); - serverSSLEngine.setEnabledProtocols(serverSSLEngine.getSupportedProtocols()); - serverSSLEngine.setEnabledCipherSuites(serverSSLEngine.getSupportedCipherSuites()); - serverSSLEngine.setEnableSessionCreation(true); - } - - // ************** - // Utility methods - // ************** - - public Map<String, Long> getMemory() { - Map<String, Long> m = new HashMap<>(); - Runtime runtime = Runtime.getRuntime(); - m.put("total", runtime.totalMemory()); - m.put("free", runtime.freeMemory()); - return m; - } - - - public Long getSystemUptime() { - RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); - return rb.getUptime(); - } - - public long getSystemStartTime() { - return (this.systemStartTime); - } - - /** - * Forward to the driver-manager to get an IOFSwitch instance. - * - * @param dpid data path id - * @param desc switch description - * @param ofv OpenFlow version - * @return switch instance - */ - protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid, - OFDescStatsReply desc, - OFVersion ofv) { - Dpid dpidObj = new Dpid(dpid); - - Driver driver; - try { - driver = driverService.getDriver(DeviceId.deviceId(Dpid.uri(dpidObj))); - } catch (ItemNotFoundException e) { - driver = driverService.getDriver(desc.getMfrDesc(), desc.getHwDesc(), desc.getSwDesc()); - } - - if (driver != null && driver.hasBehaviour(OpenFlowSwitchDriver.class)) { - Dpid did = new Dpid(dpid); - DefaultDriverHandler handler = - new DefaultDriverHandler(new DefaultDriverData(driver, deviceId(uri(did)))); - OpenFlowSwitchDriver ofSwitchDriver = - driver.createBehaviour(handler, OpenFlowSwitchDriver.class); - ofSwitchDriver.init(did, desc, ofv); - ofSwitchDriver.setAgent(agent); - ofSwitchDriver.setRoleHandler(new RoleManager(ofSwitchDriver)); - log.info("OpenFlow handshaker found for device {}: {}", dpid, ofSwitchDriver); - return ofSwitchDriver; - } - log.error("No OpenFlow driver for {} : {}", dpid, desc); - return null; - - } - - public void start(OpenFlowAgent ag, DriverService driverService) { - log.info("Starting OpenFlow IO"); - this.agent = ag; - this.driverService = driverService; - this.init(); - this.run(); - } - - - public void stop() { - log.info("Stopping OpenFlow IO"); - cg.close(); - execFactory.shutdown(); - } - -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/HandshakeTimeoutException.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/HandshakeTimeoutException.java deleted file mode 100644 index bbe307be..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/HandshakeTimeoutException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -/** - * Exception is thrown when the handshake fails to complete. - * before a specified time - * - */ -public class HandshakeTimeoutException extends Exception { - - private static final long serialVersionUID = 6859880268940337312L; - -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/HandshakeTimeoutHandler.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/HandshakeTimeoutHandler.java deleted file mode 100644 index fbbe3428..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/HandshakeTimeoutHandler.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -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; - -/** - * Trigger a timeout if a switch fails to complete handshake soon enough. - */ -public class HandshakeTimeoutHandler - extends SimpleChannelUpstreamHandler { - static final HandshakeTimeoutException EXCEPTION = - new HandshakeTimeoutException(); - - final OFChannelHandler channelHandler; - final Timer timer; - final long timeoutNanos; - volatile Timeout timeout; - - public HandshakeTimeoutHandler(OFChannelHandler channelHandler, - Timer timer, - long timeoutSeconds) { - super(); - this.channelHandler = channelHandler; - this.timer = timer; - this.timeoutNanos = TimeUnit.SECONDS.toNanos(timeoutSeconds); - - } - - @Override - public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) - throws Exception { - if (timeoutNanos > 0) { - timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx), - timeoutNanos, TimeUnit.NANOSECONDS); - } - ctx.sendUpstream(e); - } - - @Override - public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) - throws Exception { - if (timeout != null) { - timeout.cancel(); - timeout = null; - } - } - - private final class HandshakeTimeoutTask implements TimerTask { - - private final ChannelHandlerContext ctx; - - HandshakeTimeoutTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run(Timeout t) throws Exception { - if (t.isCancelled()) { - return; - } - - if (!ctx.getChannel().isOpen()) { - return; - } - if (!channelHandler.isHandshakeComplete()) { - Channels.fireExceptionCaught(ctx, EXCEPTION); - } - } - } -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java deleted file mode 100644 index ff92b77e..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java +++ /dev/null @@ -1,1320 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * 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. - */ - -//CHECKSTYLE:OFF -package org.onosproject.openflow.controller.impl; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.RejectedExecutionException; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelStateEvent; -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.ReadTimeoutException; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; -import org.onosproject.openflow.controller.driver.SwitchStateException; -import org.projectfloodlight.openflow.exceptions.OFParseError; -import org.projectfloodlight.openflow.protocol.OFAsyncGetReply; -import org.projectfloodlight.openflow.protocol.OFBadRequestCode; -import org.projectfloodlight.openflow.protocol.OFBarrierReply; -import org.projectfloodlight.openflow.protocol.OFBarrierRequest; -import org.projectfloodlight.openflow.protocol.OFDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFDescStatsRequest; -import org.projectfloodlight.openflow.protocol.OFEchoReply; -import org.projectfloodlight.openflow.protocol.OFEchoRequest; -import org.projectfloodlight.openflow.protocol.OFErrorMsg; -import org.projectfloodlight.openflow.protocol.OFErrorType; -import org.projectfloodlight.openflow.protocol.OFExperimenter; -import org.projectfloodlight.openflow.protocol.OFFactory; -import org.projectfloodlight.openflow.protocol.OFFeaturesReply; -import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode; -import org.projectfloodlight.openflow.protocol.OFFlowRemoved; -import org.projectfloodlight.openflow.protocol.OFGetConfigReply; -import org.projectfloodlight.openflow.protocol.OFGetConfigRequest; -import org.projectfloodlight.openflow.protocol.OFHello; -import org.projectfloodlight.openflow.protocol.OFHelloElem; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFPacketIn; -import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFPortDescStatsRequest; -import org.projectfloodlight.openflow.protocol.OFPortStatus; -import org.projectfloodlight.openflow.protocol.OFQueueGetConfigReply; -import org.projectfloodlight.openflow.protocol.OFRoleReply; -import org.projectfloodlight.openflow.protocol.OFSetConfig; -import org.projectfloodlight.openflow.protocol.OFStatsReply; -import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; -import org.projectfloodlight.openflow.protocol.OFStatsType; -import org.projectfloodlight.openflow.protocol.OFType; -import org.projectfloodlight.openflow.protocol.OFVersion; -import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg; -import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg; -import org.projectfloodlight.openflow.types.U32; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Channel handler deals with the switch connection and dispatches - * switch messages to the appropriate locations. - */ -class OFChannelHandler extends IdleStateAwareChannelHandler { - private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class); - - private static final String RESET_BY_PEER = "Connection reset by peer"; - private static final String BROKEN_PIPE = "Broken pipe"; - - private final Controller controller; - private OpenFlowSwitchDriver sw; - private long thisdpid; // channelHandler cached value of connected switch id - private Channel channel; - // State needs to be volatile because the HandshakeTimeoutHandler - // needs to check if the handshake is complete - private volatile ChannelState state; - - // When a switch with a duplicate dpid is found (i.e we already have a - // connected switch with the same dpid), the new switch is immediately - // disconnected. At that point netty callsback channelDisconnected() which - // proceeds to cleaup switch state - we need to ensure that it does not cleanup - // switch state for the older (still connected) switch - private volatile Boolean duplicateDpidFound; - - // Temporary storage for switch-features and port-description - private OFFeaturesReply featuresReply; - private List<OFPortDescStatsReply> portDescReplies; - //private OFPortDescStatsReply portDescReply; - // a concurrent ArrayList to temporarily store port status messages - // before we are ready to deal with them - private final CopyOnWriteArrayList<OFPortStatus> pendingPortStatusMsg; - - //Indicates the openflow version used by this switch - protected OFVersion ofVersion; - protected OFFactory factory13; - protected OFFactory factory10; - - /** transaction Ids to use during handshake. Since only one thread - * calls into an OFChannelHandler instance, we don't need atomic. - * We will count down - */ - private int handshakeTransactionIds = -1; - - /** - * Create a new unconnected OFChannelHandler. - * @param controller parent controller - */ - OFChannelHandler(Controller controller) { - this.controller = controller; - this.state = ChannelState.INIT; - this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>(); - this.portDescReplies = new ArrayList<OFPortDescStatsReply>(); - factory13 = controller.getOFMessageFactory13(); - factory10 = controller.getOFMessageFactory10(); - duplicateDpidFound = Boolean.FALSE; - } - - - - // XXX S consider if necessary - public void disconnectSwitch() { - sw.disconnectSwitch(); - } - - - - //************************* - // Channel State Machine - //************************* - - /** - * The state machine for handling the switch/channel state. All state - * transitions should happen from within the state machine (and not from other - * parts of the code) - */ - enum ChannelState { - /** - * Initial state before channel is connected. - */ - INIT(false) { - @Override - void processOFMessage(OFChannelHandler h, OFMessage m) - throws IOException, SwitchStateException { - illegalMessageReceived(h, m); - } - - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) - throws IOException { - // need to implement since its abstract but it will never - // be called - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - unhandledMessageReceived(h, m); - } - }, - - /** - * We send a OF 1.3 HELLO to the switch and wait for a Hello from the switch. - * Once we receive the reply, we decide on OF 1.3 or 1.0 switch - no other - * protocol version is accepted. - * We send an OFFeaturesRequest depending on the protocol version selected - * Next state is WAIT_FEATURES_REPLY - */ - WAIT_HELLO(false) { - @Override - void processOFHello(OFChannelHandler h, OFHello m) - throws IOException { - // TODO We could check for the optional bitmap, but for now - // we are just checking the version number. - if (m.getVersion().getWireVersion() >= OFVersion.OF_13.getWireVersion()) { - log.debug("Received {} Hello from {} - switching to OF " - + "version 1.3", m.getVersion(), - h.channel.getRemoteAddress()); - h.sendHandshakeHelloMessage(); - h.ofVersion = OFVersion.OF_13; - } else if (m.getVersion().getWireVersion() >= OFVersion.OF_10.getWireVersion()) { - log.debug("Received {} Hello from {} - switching to OF " - + "version 1.0", m.getVersion(), - h.channel.getRemoteAddress()); - OFHello hi = - h.factory10.buildHello() - .setXid(h.handshakeTransactionIds--) - .build(); - h.channel.write(Collections.singletonList(hi)); - h.ofVersion = OFVersion.OF_10; - } else { - log.error("Received Hello of version {} from switch at {}. " - + "This controller works with OF1.0 and OF1.3 " - + "switches. Disconnecting switch ...", - m.getVersion(), h.channel.getRemoteAddress()); - h.channel.disconnect(); - return; - } - h.sendHandshakeFeaturesRequestMessage(); - h.setState(WAIT_FEATURES_REPLY); - } - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException, SwitchStateException { - illegalMessageReceived(h, m); - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatsReply m) - throws IOException, SwitchStateException { - illegalMessageReceived(h, m); - } - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - unhandledMessageReceived(h, m); - } - }, - - - /** - * We are waiting for a features reply message. Once we receive it, the - * behavior depends on whether this is a 1.0 or 1.3 switch. For 1.0, - * we send a SetConfig request, barrier, and GetConfig request and the - * next state is WAIT_CONFIG_REPLY. For 1.3, we send a Port description - * request and the next state is WAIT_PORT_DESC_REPLY. - */ - WAIT_FEATURES_REPLY(false) { - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - h.thisdpid = m.getDatapathId().getLong(); - log.debug("Received features reply for switch at {} with dpid {}", - h.getSwitchInfoString(), h.thisdpid); - - h.featuresReply = m; //temp store - if (h.ofVersion == OFVersion.OF_10) { - h.sendHandshakeSetConfig(); - h.setState(WAIT_CONFIG_REPLY); - } else { - //version is 1.3, must get switchport information - h.sendHandshakeOFPortDescRequest(); - h.setState(WAIT_PORT_DESC_REPLY); - } - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatsReply m) - throws IOException, SwitchStateException { - illegalMessageReceived(h, m); - } - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - h.pendingPortStatusMsg.add(m); - } - }, - - /** - * We are waiting for a description of the 1.3 switch ports. - * Once received, we send a SetConfig request - * Next State is WAIT_CONFIG_REPLY - */ - WAIT_PORT_DESC_REPLY(false) { - - @Override - void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m) - throws SwitchStateException { - // Read port description - if (m.getStatsType() != OFStatsType.PORT_DESC) { - log.warn("Expecting port description stats but received stats " - + "type {} from {}. Ignoring ...", m.getStatsType(), - h.channel.getRemoteAddress()); - return; - } - if (m.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - log.debug("Stats reply indicates more stats from sw {} for " - + "port description", - h.getSwitchInfoString()); - h.portDescReplies.add((OFPortDescStatsReply)m); - return; - } - else { - h.portDescReplies.add((OFPortDescStatsReply)m); - } - //h.portDescReply = (OFPortDescStatsReply) m; // temp store - log.info("Received port desc reply for switch at {}", - h.getSwitchInfoString()); - try { - h.sendHandshakeSetConfig(); - } catch (IOException e) { - log.error("Unable to send setConfig after PortDescReply. " - + "Error: {}", e.getMessage()); - } - h.setState(WAIT_CONFIG_REPLY); - } - - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) - throws IOException, SwitchStateException { - logErrorDisconnect(h, m); - - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException, SwitchStateException { - h.pendingPortStatusMsg.add(m); - - } - }, - - /** - * We are waiting for a config reply message. Once we receive it - * we send a DescriptionStatsRequest to the switch. - * Next state: WAIT_DESCRIPTION_STAT_REPLY - */ - WAIT_CONFIG_REPLY(false) { - @Override - void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m) - throws IOException { - if (m.getMissSendLen() == 0xffff) { - log.trace("Config Reply from switch {} confirms " - + "miss length set to 0xffff", - h.getSwitchInfoString()); - } else { - // FIXME: we can't really deal with switches that don't send - // full packets. Shouldn't we drop the connection here? - log.warn("Config Reply from switch {} has" - + "miss length set to {}", - h.getSwitchInfoString(), - m.getMissSendLen()); - } - h.sendHandshakeDescriptionStatsRequest(); - h.setState(WAIT_DESCRIPTION_STAT_REPLY); - } - - @Override - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) { - // do nothing; - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException, SwitchStateException { - illegalMessageReceived(h, m); - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatsReply m) - throws IOException, SwitchStateException { - log.error("Received multipart(stats) message sub-type {}", - m.getStatsType()); - illegalMessageReceived(h, m); - } - - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - h.pendingPortStatusMsg.add(m); - } - }, - - - /** - * We are waiting for a OFDescriptionStat message from the switch. - * Once we receive any stat message we try to parse it. If it's not - * a description stats message we disconnect. If its the expected - * description stats message, we: - * - use the switch driver to bind the switch and get an IOFSwitch instance - * - setup the IOFSwitch instance - * - add switch controller and send the initial role - * request to the switch. - * Next state: WAIT_INITIAL_ROLE - * In the typical case, where switches support role request messages - * the next state is where we expect the role reply message. - * In the special case that where the switch does not support any kind - * of role request messages, we don't send a role message, but we do - * request mastership from the registry service. This controller - * should become master once we hear back from the registry service. - * All following states will have a h.sw instance! - */ - WAIT_DESCRIPTION_STAT_REPLY(false) { - @Override - void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m) - throws SwitchStateException { - // Read description, if it has been updated - if (m.getStatsType() != OFStatsType.DESC) { - log.warn("Expecting Description stats but received stats " - + "type {} from {}. Ignoring ...", m.getStatsType(), - h.channel.getRemoteAddress()); - return; - } - OFDescStatsReply drep = (OFDescStatsReply) m; - log.info("Received switch description reply {} from switch at {}", - drep, h.channel.getRemoteAddress()); - // Here is where we differentiate between different kinds of switches - h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion); - - h.sw.setOFVersion(h.ofVersion); - h.sw.setFeaturesReply(h.featuresReply); - //h.sw.setPortDescReply(h.portDescReply); - h.sw.setPortDescReplies(h.portDescReplies); - h.sw.setConnected(true); - h.sw.setChannel(h.channel); -// boolean success = h.sw.connectSwitch(); -// -// if (!success) { -// disconnectDuplicate(h); -// return; -// } - // set switch information - - - - log.debug("Switch {} bound to class {}, description {}", - h.sw, h.sw.getClass(), drep); - //Put switch in EQUAL mode until we hear back from the global registry - //log.debug("Setting new switch {} to EQUAL and sending Role request", - // h.sw.getStringId()); - //h.sw.activateEqualSwitch(); - //h.setSwitchRole(RoleState.EQUAL); - - h.sw.startDriverHandshake(); - if (h.sw.isDriverHandshakeComplete()) { - if (!h.sw.connectSwitch()) { - disconnectDuplicate(h); - } - handlePendingPortStatusMessages(h); - h.setState(ACTIVE); - } else { - h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE); - } - - } - - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException, SwitchStateException { - illegalMessageReceived(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - h.pendingPortStatusMsg.add(m); - } - }, - - - /** - * We are waiting for the respective switch driver to complete its - * configuration. Notice that we do not consider this to be part of the main - * switch-controller handshake. But we do consider it as a step that comes - * before we declare the switch as available to the controller. - * Next State: depends on the role of this controller for this switch - either - * MASTER or EQUAL. - */ - WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(true) { - - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) - throws IOException { - // will never be called. We override processOFMessage - } - - - - @Override - void processOFMessage(OFChannelHandler h, OFMessage m) - throws IOException, SwitchStateException { - - if (h.sw.isDriverHandshakeComplete()) { - moveToActive(h); - h.state.processOFMessage(h, m); - return; - - } - - if (m.getType() == OFType.ECHO_REQUEST) { - processOFEchoRequest(h, (OFEchoRequest) m); - } else if (m.getType() == OFType.ECHO_REPLY) { - processOFEchoReply(h, (OFEchoReply) m); - } else if (m.getType() == OFType.ROLE_REPLY) { - h.sw.handleRole(m); - } else if (m.getType() == OFType.ERROR) { - if (!h.sw.handleRoleError((OFErrorMsg)m)) { - h.sw.processDriverHandshakeMessage(m); - if (h.sw.isDriverHandshakeComplete()) { - moveToActive(h); - } - } - } else { - if (m.getType() == OFType.EXPERIMENTER && - ((OFExperimenter) m).getExperimenter() == - RoleManager.NICIRA_EXPERIMENTER) { - h.sw.handleNiciraRole(m); - } else { - h.sw.processDriverHandshakeMessage(m); - if (h.sw.isDriverHandshakeComplete()) { - moveToActive(h); - } - } - } - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException, SwitchStateException { - h.pendingPortStatusMsg.add(m); - } - - private void moveToActive(OFChannelHandler h) { - boolean success = h.sw.connectSwitch(); - handlePendingPortStatusMessages(h); - h.setState(ACTIVE); - if (!success) { - disconnectDuplicate(h); - } - } - - }, - - - /** - * This controller is in MASTER role for this switch. We enter this state - * after requesting and winning control from the global registry. - * The main handshake as well as the switch-driver sub-handshake - * is complete at this point. - * // XXX S reconsider below - * In the (near) future we may deterministically assign controllers to - * switches at startup. - * We only leave this state if the switch disconnects or - * if we send a role request for SLAVE /and/ receive the role reply for - * SLAVE. - */ - ACTIVE(true) { - @Override - void processOFError(OFChannelHandler h, OFErrorMsg m) - throws IOException, SwitchStateException { - // if we get here, then the error message is for something else - if (m.getErrType() == OFErrorType.BAD_REQUEST && - ((OFBadRequestErrorMsg) m).getCode() == - OFBadRequestCode.EPERM) { - // We are the master controller and the switch returned - // a permission error. This is a likely indicator that - // the switch thinks we are slave. Reassert our - // role - // FIXME: this could be really bad during role transitions - // if two controllers are master (even if its only for - // a brief period). We might need to see if these errors - // persist before we reassert - - h.sw.reassertRole(); - } else if (m.getErrType() == OFErrorType.FLOW_MOD_FAILED && - ((OFFlowModFailedErrorMsg) m).getCode() == - OFFlowModFailedCode.ALL_TABLES_FULL) { - h.sw.setTableFull(true); - } else { - logError(h, m); - } - h.dispatchMessage(m); - } - - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatsReply m) { - if (m.getStatsType().equals(OFStatsType.PORT_DESC)) { - h.sw.setPortDescReply((OFPortDescStatsReply) m); - } - h.dispatchMessage(m); - } - - @Override - void processOFExperimenter(OFChannelHandler h, OFExperimenter m) - throws SwitchStateException { - h.sw.handleNiciraRole(m); - } - - @Override - void processOFRoleReply(OFChannelHandler h, OFRoleReply m) - throws SwitchStateException { - h.sw.handleRole(m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws SwitchStateException { - handlePortStatusMessage(h, m, true); - //h.dispatchMessage(m); - } - - @Override - void processOFPacketIn(OFChannelHandler h, OFPacketIn m) { -// OFPacketOut out = -// h.sw.factory().buildPacketOut() -// .setXid(m.getXid()) -// .setBufferId(m.getBufferId()).build(); -// h.sw.sendMsg(out); - h.dispatchMessage(m); - } - - @Override - void processOFFlowRemoved(OFChannelHandler h, - OFFlowRemoved m) { - h.dispatchMessage(m); - } - - @Override - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) { - h.dispatchMessage(m); - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) { - h.sw.setFeaturesReply(m); - h.dispatchMessage(m); - } - - }; - - private final boolean handshakeComplete; - ChannelState(boolean handshakeComplete) { - this.handshakeComplete = handshakeComplete; - } - - /** - * Is this a state in which the handshake has completed? - * @return true if the handshake is complete - */ - public boolean isHandshakeComplete() { - return handshakeComplete; - } - - /** - * Get a string specifying the switch connection, state, and - * message received. To be used as message for SwitchStateException - * or log messages - * @param h The channel handler (to get switch information_ - * @param m The OFMessage that has just been received - * @param details A string giving more details about the exact nature - * of the problem. - * @return display string - */ - // needs to be protected because enum members are actually subclasses - protected String getSwitchStateMessage(OFChannelHandler h, - OFMessage m, - String details) { - return String.format("Switch: [%s], State: [%s], received: [%s]" - + ", details: %s", - h.getSwitchInfoString(), - this.toString(), - m.getType().toString(), - details); - } - - /** - * We have an OFMessage we didn't expect given the current state and - * we want to treat this as an error. - * We currently throw an exception that will terminate the connection - * However, we could be more forgiving - * @param h the channel handler that received the message - * @param m the message - * @throws SwitchStateException we always throw the exception - */ - // needs to be protected because enum members are actually subclasses - protected void illegalMessageReceived(OFChannelHandler h, OFMessage m) - throws SwitchStateException { - String msg = getSwitchStateMessage(h, m, - "Switch should never send this message in the current state"); - throw new SwitchStateException(msg); - - } - - /** - * We have an OFMessage we didn't expect given the current state and - * we want to ignore the message. - * @param h the channel handler the received the message - * @param m the message - */ - protected void unhandledMessageReceived(OFChannelHandler h, - OFMessage m) { - if (log.isDebugEnabled()) { - String msg = getSwitchStateMessage(h, m, - "Ignoring unexpected message"); - log.debug(msg); - } - } - - /** - * Log an OpenFlow error message from a switch. - * @param h The switch that sent the error - * @param error The error message - */ - protected void logError(OFChannelHandler h, OFErrorMsg error) { - log.error("{} from switch {} in state {}", - error, - h.getSwitchInfoString(), - this.toString()); - } - - /** - * Log an OpenFlow error message from a switch and disconnect the - * channel. - * - * @param h the IO channel for this switch. - * @param error The error message - */ - protected void logErrorDisconnect(OFChannelHandler h, OFErrorMsg error) { - logError(h, error); - h.channel.disconnect(); - } - - /** - * log an error message for a duplicate dpid and disconnect this channel. - * @param h the IO channel for this switch. - */ - protected void disconnectDuplicate(OFChannelHandler h) { - log.error("Duplicated dpid or incompleted cleanup - " - + "disconnecting channel {}", h.getSwitchInfoString()); - h.duplicateDpidFound = Boolean.TRUE; - h.channel.disconnect(); - } - - - - /** - * Handles all pending port status messages before a switch is declared - * activated in MASTER or EQUAL role. Note that since this handling - * precedes the activation (and therefore notification to IOFSwitchListerners) - * the changes to ports will already be visible once the switch is - * activated. As a result, no notifications are sent out for these - * pending portStatus messages. - * - * @param h the channel handler that received the message - */ - protected void handlePendingPortStatusMessages(OFChannelHandler h) { - try { - handlePendingPortStatusMessages(h, 0); - } catch (SwitchStateException e) { - log.error(e.getMessage()); - } - } - - private void handlePendingPortStatusMessages(OFChannelHandler h, int index) - throws SwitchStateException { - if (h.sw == null) { - String msg = "State machine error: switch is null. Should never " + - "happen"; - throw new SwitchStateException(msg); - } - log.info("Processing {} pending port status messages for {}", - h.pendingPortStatusMsg.size(), h.sw.getStringId()); - - ArrayList<OFPortStatus> temp = new ArrayList<OFPortStatus>(); - for (OFPortStatus ps: h.pendingPortStatusMsg) { - temp.add(ps); - handlePortStatusMessage(h, ps, false); - } - // expensive but ok - we don't expect too many port-status messages - // note that we cannot use clear(), because of the reasons below - h.pendingPortStatusMsg.removeAll(temp); - temp.clear(); - // the iterator above takes a snapshot of the list - so while we were - // dealing with the pending port-status messages, we could have received - // newer ones. Handle them recursively, but break the recursion after - // five steps to avoid an attack. - if (!h.pendingPortStatusMsg.isEmpty() && ++index < 5) { - handlePendingPortStatusMessages(h, index); - } - } - - /** - * Handle a port status message. - * - * Handle a port status message by updating the port maps in the - * IOFSwitch instance and notifying Controller about the change so - * it can dispatch a switch update. - * - * @param h The OFChannelHhandler that received the message - * @param m The PortStatus message we received - * @param doNotify if true switch port changed events will be - * dispatched - * @throws SwitchStateException if the switch is not bound to the channel - * - */ - protected void handlePortStatusMessage(OFChannelHandler h, OFPortStatus m, - boolean doNotify) throws SwitchStateException { - if (h.sw == null) { - String msg = getSwitchStateMessage(h, m, - "State machine error: switch is null. Should never " + - "happen"); - throw new SwitchStateException(msg); - } - - h.sw.handleMessage(m); - } - - - /** - * Process an OF message received on the channel and - * update state accordingly. - * - * The main "event" of the state machine. Process the received message, - * send follow up message if required and update state if required. - * - * Switches on the message type and calls more specific event handlers - * for each individual OF message type. If we receive a message that - * is supposed to be sent from a controller to a switch we throw - * a SwitchStateExeption. - * - * The more specific handlers can also throw SwitchStateExceptions - * - * @param h The OFChannelHandler that received the message - * @param m The message we received. - * @throws SwitchStateException if the switch is not bound to the channel - * @throws IOException if unable to send message back to the switch - */ - void processOFMessage(OFChannelHandler h, OFMessage m) - throws IOException, SwitchStateException { - switch(m.getType()) { - case HELLO: - processOFHello(h, (OFHello) m); - break; - case BARRIER_REPLY: - processOFBarrierReply(h, (OFBarrierReply) m); - break; - case ECHO_REPLY: - processOFEchoReply(h, (OFEchoReply) m); - break; - case ECHO_REQUEST: - processOFEchoRequest(h, (OFEchoRequest) m); - break; - case ERROR: - processOFError(h, (OFErrorMsg) m); - break; - case FEATURES_REPLY: - processOFFeaturesReply(h, (OFFeaturesReply) m); - break; - case FLOW_REMOVED: - processOFFlowRemoved(h, (OFFlowRemoved) m); - break; - case GET_CONFIG_REPLY: - processOFGetConfigReply(h, (OFGetConfigReply) m); - break; - case PACKET_IN: - processOFPacketIn(h, (OFPacketIn) m); - break; - case PORT_STATUS: - processOFPortStatus(h, (OFPortStatus) m); - break; - case QUEUE_GET_CONFIG_REPLY: - processOFQueueGetConfigReply(h, (OFQueueGetConfigReply) m); - break; - case STATS_REPLY: // multipart_reply in 1.3 - processOFStatisticsReply(h, (OFStatsReply) m); - break; - case EXPERIMENTER: - processOFExperimenter(h, (OFExperimenter) m); - break; - case ROLE_REPLY: - processOFRoleReply(h, (OFRoleReply) m); - break; - case GET_ASYNC_REPLY: - processOFGetAsyncReply(h, (OFAsyncGetReply) m); - break; - - // The following messages are sent to switches. The controller - // should never receive them - case SET_CONFIG: - case GET_CONFIG_REQUEST: - case PACKET_OUT: - case PORT_MOD: - case QUEUE_GET_CONFIG_REQUEST: - case BARRIER_REQUEST: - case STATS_REQUEST: // multipart request in 1.3 - case FEATURES_REQUEST: - case FLOW_MOD: - case GROUP_MOD: - case TABLE_MOD: - case GET_ASYNC_REQUEST: - case SET_ASYNC: - case METER_MOD: - default: - illegalMessageReceived(h, m); - break; - } - } - - /*----------------------------------------------------------------- - * Default implementation for message handlers in any state. - * - * Individual states must override these if they want a behavior - * that differs from the default. - * - * In general, these handlers simply ignore the message and do - * nothing. - * - * There are some exceptions though, since some messages really - * are handled the same way in every state (e.g., ECHO_REQUST) or - * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY - -----------------------------------------------------------------*/ - - void processOFHello(OFChannelHandler h, OFHello m) - throws IOException, SwitchStateException { - // we only expect hello in the WAIT_HELLO state - log.warn("Received Hello outside WAIT_HELLO state; switch {} is not complaint.", - h.channel.getRemoteAddress()); - } - - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) - throws IOException { - // Silently ignore. - } - - void processOFEchoRequest(OFChannelHandler h, OFEchoRequest m) - throws IOException { - if (h.ofVersion == null) { - log.error("No OF version set for {}. Not sending Echo REPLY", - h.channel.getRemoteAddress()); - return; - } - OFFactory factory = (h.ofVersion == OFVersion.OF_13) ? - h.controller.getOFMessageFactory13() : h.controller.getOFMessageFactory10(); - OFEchoReply reply = factory - .buildEchoReply() - .setXid(m.getXid()) - .setData(m.getData()) - .build(); - h.channel.write(Collections.singletonList(reply)); - } - - void processOFEchoReply(OFChannelHandler h, OFEchoReply m) - throws IOException { - // Do nothing with EchoReplies !! - } - - // no default implementation for OFError - // every state must override it - abstract void processOFError(OFChannelHandler h, OFErrorMsg m) - throws IOException, SwitchStateException; - - - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException, SwitchStateException { - unhandledMessageReceived(h, m); - } - - void processOFFlowRemoved(OFChannelHandler h, OFFlowRemoved m) - throws IOException { - unhandledMessageReceived(h, m); - } - - void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m) - throws IOException, SwitchStateException { - // we only expect config replies in the WAIT_CONFIG_REPLY state - illegalMessageReceived(h, m); - } - - void processOFPacketIn(OFChannelHandler h, OFPacketIn m) - throws IOException { - unhandledMessageReceived(h, m); - } - - // no default implementation. Every state needs to handle it. - abstract void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException, SwitchStateException; - - void processOFQueueGetConfigReply(OFChannelHandler h, - OFQueueGetConfigReply m) - throws IOException { - unhandledMessageReceived(h, m); - } - - void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m) - throws IOException, SwitchStateException { - unhandledMessageReceived(h, m); - } - - void processOFExperimenter(OFChannelHandler h, OFExperimenter m) - throws IOException, SwitchStateException { - // TODO: it might make sense to parse the vendor message here - // into the known vendor messages we support and then call more - // specific event handlers - unhandledMessageReceived(h, m); - } - - void processOFRoleReply(OFChannelHandler h, OFRoleReply m) - throws SwitchStateException, IOException { - unhandledMessageReceived(h, m); - } - - void processOFGetAsyncReply(OFChannelHandler h, - OFAsyncGetReply m) { - unhandledMessageReceived(h, m); - } - - } - - - - //************************* - // Channel handler methods - //************************* - - @Override - public void channelConnected(ChannelHandlerContext ctx, - ChannelStateEvent e) throws Exception { - channel = e.getChannel(); - log.info("New switch connection from {}", - channel.getRemoteAddress()); - /* - hack to wait for the switch to tell us what it's - max version is. This is not spec compliant and should - be removed as soon as switches behave better. - */ - //sendHandshakeHelloMessage(); - setState(ChannelState.WAIT_HELLO); - } - - @Override - public void channelDisconnected(ChannelHandlerContext ctx, - ChannelStateEvent e) throws Exception { - log.info("Switch disconnected callback for sw:{}. Cleaning up ...", - getSwitchInfoString()); - if (thisdpid != 0) { - if (!duplicateDpidFound) { - // if the disconnected switch (on this ChannelHandler) - // was not one with a duplicate-dpid, it is safe to remove all - // state for it at the controller. Notice that if the disconnected - // switch was a duplicate-dpid, calling the method below would clear - // all state for the original switch (with the same dpid), - // which we obviously don't want. - log.info("{}:removal called", getSwitchInfoString()); - if (sw != null) { - sw.removeConnectedSwitch(); - } - } else { - // A duplicate was disconnected on this ChannelHandler, - // this is the same switch reconnecting, but the original state was - // not cleaned up - XXX check liveness of original ChannelHandler - log.info("{}:duplicate found", getSwitchInfoString()); - duplicateDpidFound = Boolean.FALSE; - } - } else { - log.warn("no dpid in channelHandler registered for " - + "disconnected switch {}", getSwitchInfoString()); - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) - throws Exception { - if (e.getCause() instanceof ReadTimeoutException) { - // switch timeout - log.error("Disconnecting switch {} due to read timeout", - getSwitchInfoString()); - ctx.getChannel().close(); - } else if (e.getCause() instanceof HandshakeTimeoutException) { - log.error("Disconnecting switch {}: failed to complete handshake", - getSwitchInfoString()); - ctx.getChannel().close(); - } else if (e.getCause() instanceof ClosedChannelException) { - log.debug("Channel for sw {} already closed", getSwitchInfoString()); - } else if (e.getCause() instanceof IOException) { - if (!e.getCause().getMessage().equals(RESET_BY_PEER) && - !e.getCause().getMessage().equals(BROKEN_PIPE)) { - log.error("Disconnecting switch {} due to IO Error: {}", - getSwitchInfoString(), e.getCause().getMessage()); - if (log.isDebugEnabled()) { - // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); - } - } - ctx.getChannel().close(); - } else if (e.getCause() instanceof SwitchStateException) { - log.error("Disconnecting switch {} due to switch state error: {}", - getSwitchInfoString(), e.getCause().getMessage()); - if (log.isDebugEnabled()) { - // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); - } - ctx.getChannel().close(); - } else if (e.getCause() instanceof OFParseError) { - log.error("Disconnecting switch " - + getSwitchInfoString() + - " due to message parse failure", - e.getCause()); - ctx.getChannel().close(); - } else if (e.getCause() instanceof RejectedExecutionException) { - log.warn("Could not process message: queue full"); - } else { - log.error("Error while processing message from switch " - + getSwitchInfoString() - + "state " + this.state, e.getCause()); - ctx.getChannel().close(); - } - } - - @Override - public String toString() { - return getSwitchInfoString(); - } - - @Override - public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) - throws Exception { - OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10; - OFMessage m = factory.buildEchoRequest().build(); - log.debug("Sending Echo Request on idle channel: {}", - e.getChannel().getPipeline().getLast().toString()); - e.getChannel().write(Collections.singletonList(m)); - // XXX S some problems here -- echo request has no transaction id, and - // echo reply is not correlated to the echo request. - } - - @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) { - // Do the actual packet processing - state.processOFMessage(this, ofm); - } - } else { - state.processOFMessage(this, (OFMessage) e.getMessage()); - } - } - - - - //************************* - // Channel utility methods - //************************* - - /** - * Is this a state in which the handshake has completed? - * @return true if the handshake is complete - */ - public boolean isHandshakeComplete() { - return this.state.isHandshakeComplete(); - } - - private void dispatchMessage(OFMessage m) { - sw.handleMessage(m); - } - - /** - * Return a string describing this switch based on the already available - * information (DPID and/or remote socket). - * @return display string - */ - private String getSwitchInfoString() { - if (sw != null) { - return sw.toString(); - } - String channelString; - if (channel == null || channel.getRemoteAddress() == null) { - channelString = "?"; - } else { - channelString = channel.getRemoteAddress().toString(); - } - String dpidString; - if (featuresReply == null) { - dpidString = "?"; - } else { - dpidString = featuresReply.getDatapathId().toString(); - } - return String.format("[%s DPID[%s]]", channelString, dpidString); - } - - /** - * Update the channels state. Only called from the state machine. - * TODO: enforce restricted state transitions - * @param state - */ - private void setState(ChannelState state) { - this.state = state; - } - - /** - * Send hello message to the switch using the handshake transactions ids. - * @throws IOException - */ - private void sendHandshakeHelloMessage() throws IOException { - // The OF protocol requires us to start things off by sending the highest - // version of the protocol supported. - - // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04) - // see Sec. 7.5.1 of the OF1.3.4 spec - U32 bitmap = U32.ofRaw(0x00000012); - OFHelloElem hem = factory13.buildHelloElemVersionbitmap() - .setBitmaps(Collections.singletonList(bitmap)) - .build(); - OFMessage.Builder mb = factory13.buildHello() - .setXid(this.handshakeTransactionIds--) - .setElements(Collections.singletonList(hem)); - log.info("Sending OF_13 Hello to {}", channel.getRemoteAddress()); - channel.write(Collections.singletonList(mb.build())); - } - - /** - * Send featuresRequest msg to the switch using the handshake transactions ids. - * @throws IOException - */ - private void sendHandshakeFeaturesRequestMessage() throws IOException { - OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10; - OFMessage m = factory.buildFeaturesRequest() - .setXid(this.handshakeTransactionIds--) - .build(); - channel.write(Collections.singletonList(m)); - } - - /** - * Send the configuration requests to tell the switch we want full - * packets. - * @throws IOException - */ - private void sendHandshakeSetConfig() throws IOException { - OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10; - //log.debug("Sending CONFIG_REQUEST to {}", channel.getRemoteAddress()); - List<OFMessage> msglist = new ArrayList<OFMessage>(3); - - // Ensure we receive the full packet via PacketIn - // FIXME: We don't set the reassembly flags. - // Only send config to switches to send full packets, if they have a buffer. - // Saves a packet & OFSetConfig can't be handled by certain switches. - if(this.featuresReply.getNBuffers() > 0) { - OFSetConfig sc = factory - .buildSetConfig() - .setMissSendLen((short) 0xffff) - .setXid(this.handshakeTransactionIds--) - .build(); - msglist.add(sc); - } - - // Barrier - OFBarrierRequest br = factory - .buildBarrierRequest() - .setXid(this.handshakeTransactionIds--) - .build(); - msglist.add(br); - - // Verify (need barrier?) - OFGetConfigRequest gcr = factory - .buildGetConfigRequest() - .setXid(this.handshakeTransactionIds--) - .build(); - msglist.add(gcr); - channel.write(msglist); - } - - /** - * send a description state request. - * @throws IOException - */ - private void sendHandshakeDescriptionStatsRequest() throws IOException { - // Get Description to set switch-specific flags - OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10; - OFDescStatsRequest dreq = factory - .buildDescStatsRequest() - .setXid(handshakeTransactionIds--) - .build(); - channel.write(Collections.singletonList(dreq)); - } - - private void sendHandshakeOFPortDescRequest() throws IOException { - // Get port description for 1.3 switch - OFPortDescStatsRequest preq = factory13 - .buildPortDescStatsRequest() - .setXid(handshakeTransactionIds--) - .build(); - channel.write(Collections.singletonList(preq)); - } - - ChannelState getStateForTesting() { - return state; - } - -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageDecoder.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageDecoder.java deleted file mode 100644 index f52d27e5..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageDecoder.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - - -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 org.projectfloodlight.openflow.protocol.OFFactories; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFMessageReader; - -/** - * Decode an openflow message from a Channel, for use in a netty pipeline. - */ -public class OFMessageDecoder extends FrameDecoder { - - @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; - } - - // Note that a single call to decode results in reading a single - // OFMessage from the channel buffer, which is passed on to, and processed - // by, the controller (in OFChannelHandler). - // This is different from earlier behavior (with the original openflowj), - // where we parsed all the messages in the buffer, before passing on - // a list of the parsed messages to the controller. - // The performance *may or may not* not be as good as before. - OFMessageReader<OFMessage> reader = OFFactories.getGenericReader(); - OFMessage message = reader.readFrom(buffer); - - return message; - } - -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java deleted file mode 100644 index 4c1b16fe..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import java.util.List; - -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; - -/** - * Encode an openflow message for output into a ChannelBuffer, for use in a - * netty pipeline. - */ -public class OFMessageEncoder extends OneToOneEncoder { - - @Override - protected Object encode(ChannelHandlerContext ctx, Channel channel, - Object msg) throws Exception { - if (!(msg instanceof List)) { - return msg; - } - - @SuppressWarnings("unchecked") - List<OFMessage> msglist = (List<OFMessage>) msg; - /* XXX S can't get length of OFMessage in loxigen's openflowj?? - int size = 0; - for (OFMessage ofm : msglist) { - size += ofm.getLengthU(); - }*/ - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - - for (OFMessage ofm : msglist) { - if (ofm != null) { - ofm.writeTo(buf); - } - } - return buf; - } - -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java deleted file mode 100644 index fdcd2f00..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Property; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.net.driver.DefaultDriverProviderService; -import org.onosproject.net.driver.DriverService; -import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext; -import org.onosproject.openflow.controller.Dpid; -import org.onosproject.openflow.controller.OpenFlowController; -import org.onosproject.openflow.controller.OpenFlowEventListener; -import org.onosproject.openflow.controller.OpenFlowPacketContext; -import org.onosproject.openflow.controller.OpenFlowSwitch; -import org.onosproject.openflow.controller.OpenFlowSwitchListener; -import org.onosproject.openflow.controller.PacketListener; -import org.onosproject.openflow.controller.RoleState; -import org.onosproject.openflow.controller.driver.OpenFlowAgent; -import org.osgi.service.component.ComponentContext; -import org.projectfloodlight.openflow.protocol.OFCalientFlowStatsEntry; -import org.projectfloodlight.openflow.protocol.OFCalientFlowStatsReply; -import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus; -import org.projectfloodlight.openflow.protocol.OFExperimenter; -import org.projectfloodlight.openflow.protocol.OFFactories; -import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; -import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; -import org.projectfloodlight.openflow.protocol.OFTableStatsEntry; -import org.projectfloodlight.openflow.protocol.OFTableStatsReply; -import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry; -import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry; -import org.projectfloodlight.openflow.protocol.OFGroupStatsReply; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFPacketIn; -import org.projectfloodlight.openflow.protocol.OFPortDesc; -import org.projectfloodlight.openflow.protocol.OFPortStatsEntry; -import org.projectfloodlight.openflow.protocol.OFPortStatsReply; -import org.projectfloodlight.openflow.protocol.OFPortStatus; -import org.projectfloodlight.openflow.protocol.OFStatsReply; -import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; -import org.projectfloodlight.openflow.protocol.action.OFActionOutput; -import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static org.onlab.util.Tools.groupedThreads; - -@Component(immediate = true) -@Service -public class OpenFlowControllerImpl implements OpenFlowController { - private static final String DEFAULT_OFPORT = "6633,6653"; - private static final int DEFAULT_WORKER_THREADS = 16; - - private static final Logger log = - LoggerFactory.getLogger(OpenFlowControllerImpl.class); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DriverService driverService; - - // References exists merely for sequencing purpose to assure drivers are loaded - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DefaultDriverProviderService defaultDriverProviderService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ComponentConfigService cfgService; - - @Property(name = "openflowPorts", value = DEFAULT_OFPORT, - label = "Port numbers (comma separated) used by OpenFlow protocol; default is 6633,6653") - private String openflowPorts = DEFAULT_OFPORT; - - @Property(name = "workerThreads", intValue = DEFAULT_WORKER_THREADS, - label = "Number of controller worker threads; default is 16") - private int workerThreads = DEFAULT_WORKER_THREADS; - - private final ExecutorService executorMsgs = - Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d")); - - private final ExecutorService executorBarrier = - Executors.newFixedThreadPool(4, groupedThreads("onos/of", "event-barrier-%d")); - - protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches = - new ConcurrentHashMap<>(); - protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches = - new ConcurrentHashMap<>(); - protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches = - new ConcurrentHashMap<>(); - - protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent(); - protected Set<OpenFlowSwitchListener> ofSwitchListener = new CopyOnWriteArraySet<>(); - - protected Multimap<Integer, PacketListener> ofPacketListener = - ArrayListMultimap.create(); - - protected Set<OpenFlowEventListener> ofEventListener = new CopyOnWriteArraySet<>(); - - protected Multimap<Dpid, OFFlowStatsEntry> fullFlowStats = - ArrayListMultimap.create(); - - protected Multimap<Dpid, OFTableStatsEntry> fullTableStats = - ArrayListMultimap.create(); - - protected Multimap<Dpid, OFGroupStatsEntry> fullGroupStats = - ArrayListMultimap.create(); - - protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats = - ArrayListMultimap.create(); - - protected Multimap<Dpid, OFPortStatsEntry> fullPortStats = - ArrayListMultimap.create(); - - private final Controller ctrl = new Controller(); - - @Activate - public void activate(ComponentContext context) { - cfgService.registerProperties(getClass()); - ctrl.setConfigParams(context.getProperties()); - ctrl.start(agent, driverService); - } - - @Deactivate - public void deactivate() { - cfgService.unregisterProperties(getClass(), false); - ctrl.stop(); - } - - @Modified - public void modified(ComponentContext context) { - ctrl.stop(); - ctrl.setConfigParams(context.getProperties()); - ctrl.start(agent, driverService); - } - - @Override - public Iterable<OpenFlowSwitch> getSwitches() { - return connectedSwitches.values(); - } - - @Override - public Iterable<OpenFlowSwitch> getMasterSwitches() { - return activeMasterSwitches.values(); - } - - @Override - public Iterable<OpenFlowSwitch> getEqualSwitches() { - return activeEqualSwitches.values(); - } - - @Override - public OpenFlowSwitch getSwitch(Dpid dpid) { - return connectedSwitches.get(dpid); - } - - @Override - public OpenFlowSwitch getMasterSwitch(Dpid dpid) { - return activeMasterSwitches.get(dpid); - } - - @Override - public OpenFlowSwitch getEqualSwitch(Dpid dpid) { - return activeEqualSwitches.get(dpid); - } - - @Override - public void addListener(OpenFlowSwitchListener listener) { - if (!ofSwitchListener.contains(listener)) { - this.ofSwitchListener.add(listener); - } - } - - @Override - public void removeListener(OpenFlowSwitchListener listener) { - this.ofSwitchListener.remove(listener); - } - - @Override - public void addPacketListener(int priority, PacketListener listener) { - ofPacketListener.put(priority, listener); - } - - @Override - public void removePacketListener(PacketListener listener) { - ofPacketListener.values().remove(listener); - } - - @Override - public void addEventListener(OpenFlowEventListener listener) { - ofEventListener.add(listener); - } - - @Override - public void removeEventListener(OpenFlowEventListener listener) { - ofEventListener.remove(listener); - } - - @Override - public void write(Dpid dpid, OFMessage msg) { - this.getSwitch(dpid).sendMsg(msg); - } - - @Override - public void processPacket(Dpid dpid, OFMessage msg) { - Collection<OFFlowStatsEntry> flowStats; - Collection<OFTableStatsEntry> tableStats; - Collection<OFGroupStatsEntry> groupStats; - Collection<OFGroupDescStatsEntry> groupDescStats; - Collection<OFPortStatsEntry> portStats; - - switch (msg.getType()) { - case PORT_STATUS: - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.portChanged(dpid, (OFPortStatus) msg); - } - break; - case FEATURES_REPLY: - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.switchChanged(dpid); - } - break; - case PACKET_IN: - OpenFlowPacketContext pktCtx = DefaultOpenFlowPacketContext - .packetContextFromPacketIn(this.getSwitch(dpid), - (OFPacketIn) msg); - for (PacketListener p : ofPacketListener.values()) { - p.handlePacket(pktCtx); - } - break; - // TODO: Consider using separate threadpool for sensitive messages. - // ie. Back to back error could cause us to starve. - case FLOW_REMOVED: - case ERROR: - executorMsgs.submit(new OFMessageHandler(dpid, msg)); - break; - case STATS_REPLY: - OFStatsReply reply = (OFStatsReply) msg; - switch (reply.getStatsType()) { - case PORT_DESC: - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.switchChanged(dpid); - } - break; - case FLOW: - flowStats = publishFlowStats(dpid, (OFFlowStatsReply) reply); - if (flowStats != null) { - OFFlowStatsReply.Builder rep = - OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply(); - rep.setEntries(Lists.newLinkedList(flowStats)); - rep.setXid(reply.getXid()); - executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); - } - break; - case TABLE: - tableStats = publishTableStats(dpid, (OFTableStatsReply) reply); - if (tableStats != null) { - OFTableStatsReply.Builder rep = - OFFactories.getFactory(msg.getVersion()).buildTableStatsReply(); - rep.setEntries(Lists.newLinkedList(tableStats)); - executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); - } - break; - case GROUP: - groupStats = publishGroupStats(dpid, (OFGroupStatsReply) reply); - if (groupStats != null) { - OFGroupStatsReply.Builder rep = - OFFactories.getFactory(msg.getVersion()).buildGroupStatsReply(); - rep.setEntries(Lists.newLinkedList(groupStats)); - rep.setXid(reply.getXid()); - executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); - } - break; - case GROUP_DESC: - groupDescStats = publishGroupDescStats(dpid, - (OFGroupDescStatsReply) reply); - if (groupDescStats != null) { - OFGroupDescStatsReply.Builder rep = - OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply(); - rep.setEntries(Lists.newLinkedList(groupDescStats)); - rep.setXid(reply.getXid()); - executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); - } - break; - case PORT: - executorMsgs.submit(new OFMessageHandler(dpid, reply)); - break; - case METER: - executorMsgs.submit(new OFMessageHandler(dpid, reply)); - break; - case EXPERIMENTER: - if (reply instanceof OFCalientFlowStatsReply) { - // Convert Calient flow statistics to regular flow stats - // TODO: parse remaining fields such as power levels etc. when we have proper monitoring API - OFFlowStatsReply.Builder fsr = getSwitch(dpid).factory().buildFlowStatsReply(); - List<OFFlowStatsEntry> entries = new LinkedList<>(); - for (OFCalientFlowStatsEntry entry : ((OFCalientFlowStatsReply) msg).getEntries()) { - - // Single instruction, i.e., output to port - OFActionOutput action = OFFactories - .getFactory(msg.getVersion()) - .actions() - .buildOutput() - .setPort(entry.getOutPort()) - .build(); - OFInstruction instruction = OFFactories - .getFactory(msg.getVersion()) - .instructions() - .applyActions(Collections.singletonList(action)); - OFFlowStatsEntry fs = getSwitch(dpid).factory().buildFlowStatsEntry() - .setMatch(entry.getMatch()) - .setTableId(entry.getTableId()) - .setDurationSec(entry.getDurationSec()) - .setDurationNsec(entry.getDurationNsec()) - .setPriority(entry.getPriority()) - .setIdleTimeout(entry.getIdleTimeout()) - .setHardTimeout(entry.getHardTimeout()) - .setFlags(entry.getFlags()) - .setCookie(entry.getCookie()) - .setInstructions(Collections.singletonList(instruction)) - .build(); - entries.add(fs); - } - fsr.setEntries(entries); - - flowStats = publishFlowStats(dpid, fsr.build()); - if (flowStats != null) { - OFFlowStatsReply.Builder rep = - OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply(); - rep.setEntries(Lists.newLinkedList(flowStats)); - executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); - } - } else { - executorMsgs.submit(new OFMessageHandler(dpid, reply)); - } - break; - default: - log.warn("Discarding unknown stats reply type {}", reply.getStatsType()); - break; - } - break; - case BARRIER_REPLY: - executorBarrier.submit(new OFMessageHandler(dpid, msg)); - break; - case EXPERIMENTER: - long experimenter = ((OFExperimenter) msg).getExperimenter(); - if (experimenter == 0x748771) { - // LINC-OE port stats - OFCircuitPortStatus circuitPortStatus = (OFCircuitPortStatus) msg; - OFPortStatus.Builder portStatus = this.getSwitch(dpid).factory().buildPortStatus(); - OFPortDesc.Builder portDesc = this.getSwitch(dpid).factory().buildPortDesc(); - portDesc.setPortNo(circuitPortStatus.getPortNo()) - .setHwAddr(circuitPortStatus.getHwAddr()) - .setName(circuitPortStatus.getName()) - .setConfig(circuitPortStatus.getConfig()) - .setState(circuitPortStatus.getState()); - portStatus.setReason(circuitPortStatus.getReason()).setDesc(portDesc.build()); - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.portChanged(dpid, portStatus.build()); - } - } else { - log.warn("Handling experimenter type {} not yet implemented", - ((OFExperimenter) msg).getExperimenter(), msg); - } - break; - default: - log.warn("Handling message type {} not yet implemented {}", - msg.getType(), msg); - } - } - - private synchronized Collection<OFFlowStatsEntry> publishFlowStats(Dpid dpid, - OFFlowStatsReply reply) { - //TODO: Get rid of synchronized - fullFlowStats.putAll(dpid, reply.getEntries()); - if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - return fullFlowStats.removeAll(dpid); - } - return null; - } - - private synchronized Collection<OFTableStatsEntry> publishTableStats(Dpid dpid, - OFTableStatsReply reply) { - //TODO: Get rid of synchronized - fullTableStats.putAll(dpid, reply.getEntries()); - if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - return fullTableStats.removeAll(dpid); - } - return null; - } - - private synchronized Collection<OFGroupStatsEntry> publishGroupStats(Dpid dpid, - OFGroupStatsReply reply) { - //TODO: Get rid of synchronized - fullGroupStats.putAll(dpid, reply.getEntries()); - if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - return fullGroupStats.removeAll(dpid); - } - return null; - } - - private synchronized Collection<OFGroupDescStatsEntry> publishGroupDescStats(Dpid dpid, - OFGroupDescStatsReply reply) { - //TODO: Get rid of synchronized - fullGroupDescStats.putAll(dpid, reply.getEntries()); - if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - return fullGroupDescStats.removeAll(dpid); - } - return null; - } - - private synchronized Collection<OFPortStatsEntry> publishPortStats(Dpid dpid, - OFPortStatsReply reply) { - fullPortStats.putAll(dpid, reply.getEntries()); - if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - return fullPortStats.removeAll(dpid); - } - return null; - } - - @Override - public void setRole(Dpid dpid, RoleState role) { - final OpenFlowSwitch sw = getSwitch(dpid); - if (sw == null) { - log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role); - return; - } - sw.setRole(role); - } - - /** - * Implementation of an OpenFlow Agent which is responsible for - * keeping track of connected switches and the state in which - * they are. - */ - public class OpenFlowSwitchAgent implements OpenFlowAgent { - - private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class); - private final Lock switchLock = new ReentrantLock(); - - @Override - public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) { - - if (connectedSwitches.get(dpid) != null) { - log.error("Trying to add connectedSwitch but found a previous " - + "value for dpid: {}", dpid); - return false; - } else { - log.info("Added switch {}", dpid); - connectedSwitches.put(dpid, sw); - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.switchAdded(dpid); - } - return true; - } - } - - @Override - public boolean validActivation(Dpid dpid) { - if (connectedSwitches.get(dpid) == null) { - log.error("Trying to activate switch but is not in " - + "connected switches: dpid {}. Aborting ..", - dpid); - return false; - } - if (activeMasterSwitches.get(dpid) != null || - activeEqualSwitches.get(dpid) != null) { - log.error("Trying to activate switch but it is already " - + "activated: dpid {}. Found in activeMaster: {} " - + "Found in activeEqual: {}. Aborting ..", - dpid, - (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y', - (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'); - return false; - } - return true; - } - - - @Override - public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) { - switchLock.lock(); - try { - if (!validActivation(dpid)) { - return false; - } - activeMasterSwitches.put(dpid, sw); - return true; - } finally { - switchLock.unlock(); - } - } - - @Override - public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) { - switchLock.lock(); - try { - if (!validActivation(dpid)) { - return false; - } - activeEqualSwitches.put(dpid, sw); - log.info("Added Activated EQUAL Switch {}", dpid); - return true; - } finally { - switchLock.unlock(); - } - } - - @Override - public void transitionToMasterSwitch(Dpid dpid) { - switchLock.lock(); - try { - if (activeMasterSwitches.containsKey(dpid)) { - return; - } - OpenFlowSwitch sw = activeEqualSwitches.remove(dpid); - if (sw == null) { - sw = getSwitch(dpid); - if (sw == null) { - log.error("Transition to master called on sw {}, but switch " - + "was not found in controller-cache", dpid); - return; - } - } - log.info("Transitioned switch {} to MASTER", dpid); - activeMasterSwitches.put(dpid, sw); - } finally { - switchLock.unlock(); - } - } - - - @Override - public void transitionToEqualSwitch(Dpid dpid) { - switchLock.lock(); - try { - if (activeEqualSwitches.containsKey(dpid)) { - return; - } - OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); - if (sw == null) { - sw = getSwitch(dpid); - if (sw == null) { - log.error("Transition to equal called on sw {}, but switch " - + "was not found in controller-cache", dpid); - return; - } - } - log.info("Transitioned switch {} to EQUAL", dpid); - activeEqualSwitches.put(dpid, sw); - } finally { - switchLock.unlock(); - } - - } - - @Override - public void removeConnectedSwitch(Dpid dpid) { - connectedSwitches.remove(dpid); - OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); - if (sw == null) { - log.debug("sw was null for {}", dpid); - sw = activeEqualSwitches.remove(dpid); - } - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.switchRemoved(dpid); - } - } - - @Override - public void processMessage(Dpid dpid, OFMessage m) { - processPacket(dpid, m); - } - - @Override - public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) { - for (OpenFlowSwitchListener l : ofSwitchListener) { - l.receivedRoleReply(dpid, requested, response); - } - } - } - - private final class OFMessageHandler implements Runnable { - - private final OFMessage msg; - private final Dpid dpid; - - public OFMessageHandler(Dpid dpid, OFMessage msg) { - this.msg = msg; - this.dpid = dpid; - } - - @Override - public void run() { - for (OpenFlowEventListener listener : ofEventListener) { - listener.handleMessage(dpid, msg); - } - } - - } - -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenflowPipelineFactory.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenflowPipelineFactory.java deleted file mode 100644 index 1467520d..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenflowPipelineFactory.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import java.util.concurrent.ThreadPoolExecutor; - -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.handler.execution.ExecutionHandler; -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.HashedWheelTimer; -import org.jboss.netty.util.Timer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLEngine; - -/** - * Creates a ChannelPipeline for a server-side openflow channel. - */ -public class OpenflowPipelineFactory - implements ChannelPipelineFactory, ExternalResourceReleasable { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - private final SSLEngine sslEngine; - protected Controller controller; - protected ThreadPoolExecutor pipelineExecutor; - protected Timer timer; - protected IdleStateHandler idleHandler; - protected ReadTimeoutHandler readTimeoutHandler; - - public OpenflowPipelineFactory(Controller controller, - ThreadPoolExecutor pipelineExecutor, - SSLEngine sslEngine) { - super(); - this.controller = controller; - this.pipelineExecutor = pipelineExecutor; - this.timer = new HashedWheelTimer(); - this.idleHandler = new IdleStateHandler(timer, 20, 25, 0); - this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30); - this.sslEngine = sslEngine; - } - - @Override - public ChannelPipeline getPipeline() throws Exception { - OFChannelHandler handler = new OFChannelHandler(controller); - - ChannelPipeline pipeline = Channels.pipeline(); - if (sslEngine != null) { - log.info("OpenFlow SSL enabled."); - pipeline.addLast("ssl", - new org.jboss.netty.handler.ssl.SslHandler(sslEngine)); - } else { - log.info("OpenFlow SSL disabled"); - } - pipeline.addLast("ofmessagedecoder", new OFMessageDecoder()); - pipeline.addLast("ofmessageencoder", new OFMessageEncoder()); - pipeline.addLast("idle", idleHandler); - pipeline.addLast("timeout", readTimeoutHandler); - // XXX S ONOS: was 15 increased it to fix Issue #296 - pipeline.addLast("handshaketimeout", - new HandshakeTimeoutHandler(handler, timer, 60)); - if (pipelineExecutor != null) { - pipeline.addLast("pipelineExecutor", - new ExecutionHandler(pipelineExecutor)); - } - pipeline.addLast("handler", handler); - return pipeline; - } - - @Override - public void releaseExternalResources() { - timer.stop(); - } -} diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/RoleManager.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/RoleManager.java deleted file mode 100644 index bd4875cf..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/RoleManager.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import org.onosproject.openflow.controller.RoleState; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; -import org.onosproject.openflow.controller.driver.RoleHandler; -import org.onosproject.openflow.controller.driver.RoleRecvStatus; -import org.onosproject.openflow.controller.driver.RoleReplyInfo; -import org.onosproject.openflow.controller.driver.SwitchStateException; -import org.projectfloodlight.openflow.protocol.OFControllerRole; -import org.projectfloodlight.openflow.protocol.OFErrorMsg; -import org.projectfloodlight.openflow.protocol.OFErrorType; -import org.projectfloodlight.openflow.protocol.OFExperimenter; -import org.projectfloodlight.openflow.protocol.OFFactories; -import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole; -import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply; -import org.projectfloodlight.openflow.protocol.OFRoleReply; -import org.projectfloodlight.openflow.protocol.OFRoleRequest; -import org.projectfloodlight.openflow.protocol.OFVersion; -import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg; -import org.projectfloodlight.openflow.protocol.errormsg.OFRoleRequestFailedErrorMsg; -import org.projectfloodlight.openflow.types.U64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - - -/** - * A utility class to handle role requests and replies for this channel. - * After a role request is submitted the role changer keeps track of the - * pending request, collects the reply (if any) and times out the request - * if necessary. - */ -class RoleManager implements RoleHandler { - protected static final long NICIRA_EXPERIMENTER = 0x2320; - - private static Logger log = LoggerFactory.getLogger(RoleManager.class); - - // The time until cached XID is evicted. Arbitrary for now. - private final int pendingXidTimeoutSeconds = 60; - - // The cache for pending expected RoleReplies keyed on expected XID - private Cache<Integer, RoleState> pendingReplies = - CacheBuilder.newBuilder() - .expireAfterWrite(pendingXidTimeoutSeconds, TimeUnit.SECONDS) - .build(); - - // the expectation set by the caller for the returned role - private RoleRecvStatus expectation; - private final OpenFlowSwitchDriver sw; - - - public RoleManager(OpenFlowSwitchDriver sw) { - this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE; - this.sw = sw; - } - - /** - * Send NX role request message to the switch requesting the specified - * role. - * - * @param role role to request - */ - private int sendNxRoleRequest(RoleState role) throws IOException { - // Convert the role enum to the appropriate role to send - OFNiciraControllerRole roleToSend = OFNiciraControllerRole.ROLE_OTHER; - switch (role) { - case MASTER: - roleToSend = OFNiciraControllerRole.ROLE_MASTER; - break; - case SLAVE: - case EQUAL: - default: - // ensuring that the only two roles sent to 1.0 switches with - // Nicira role support, are MASTER and SLAVE - roleToSend = OFNiciraControllerRole.ROLE_OTHER; - log.debug("Sending Nx Role.SLAVE to switch {}.", sw); - } - int xid = sw.getNextTransactionId(); - OFExperimenter roleRequest = OFFactories.getFactory(OFVersion.OF_10) - .buildNiciraControllerRoleRequest() - .setXid(xid) - .setRole(roleToSend) - .build(); - sw.sendRoleRequest(roleRequest); - return xid; - } - - private int sendOF13RoleRequest(RoleState role) throws IOException { - // Convert the role enum to the appropriate role to send - OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE; - switch (role) { - case EQUAL: - roleToSend = OFControllerRole.ROLE_EQUAL; - break; - case MASTER: - roleToSend = OFControllerRole.ROLE_MASTER; - break; - case SLAVE: - roleToSend = OFControllerRole.ROLE_SLAVE; - break; - default: - log.warn("Sending default role.noChange to switch {}." - + " Should only be used for queries.", sw); - } - - int xid = sw.getNextTransactionId(); - OFRoleRequest rrm = OFFactories.getFactory(OFVersion.OF_13) - .buildRoleRequest() - .setRole(roleToSend) - .setXid(xid) - //FIXME fix below when we actually use generation ids - .setGenerationId(U64.ZERO) - .build(); - - sw.sendRoleRequest(rrm); - return xid; - } - - @Override - public synchronized boolean sendRoleRequest(RoleState role, RoleRecvStatus exp) - throws IOException { - this.expectation = exp; - - if (sw.factory().getVersion() == OFVersion.OF_10) { - Boolean supportsNxRole = sw.supportNxRole(); - if (!supportsNxRole) { - log.debug("Switch driver indicates no support for Nicira " - + "role request messages. Not sending ..."); - handleUnsentRoleMessage(role, - expectation); - return false; - } - // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn. - // make Role.EQUAL become Role.SLAVE - RoleState roleToSend = (role == RoleState.EQUAL) ? RoleState.SLAVE : role; - pendingReplies.put(sendNxRoleRequest(roleToSend), role); - } else { - // OF1.3 switch, use OFPT_ROLE_REQUEST message - pendingReplies.put(sendOF13RoleRequest(role), role); - } - return true; - } - - private void handleUnsentRoleMessage(RoleState role, - RoleRecvStatus exp) throws IOException { - // typically this is triggered for a switch where role messages - // are not supported - we confirm that the role being set is - // master - if (exp != RoleRecvStatus.MATCHED_SET_ROLE) { - - log.error("Expected MASTER role from registry for switch " - + "which has no support for role-messages." - + "Received {}. It is possible that this switch " - + "is connected to other controllers, in which " - + "case it should support role messages - not " - + "moving forward.", role); - - } - - } - - - @Override - public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri) - throws SwitchStateException { - int xid = (int) rri.getXid(); - RoleState receivedRole = rri.getRole(); - RoleState expectedRole = pendingReplies.getIfPresent(xid); - - if (expectedRole == null) { - RoleState currentRole = (sw != null) ? sw.getRole() : null; - if (currentRole != null) { - if (currentRole == rri.getRole()) { - // Don't disconnect if the role reply we received is - // for the same role we are already in. - // FIXME: but we do from the caller anyways. - log.debug("Received unexpected RoleReply from " - + "Switch: {}. " - + "Role in reply is same as current role of this " - + "controller for this sw. Ignoring ...", - sw.getStringId()); - return RoleRecvStatus.OTHER_EXPECTATION; - } else { - String msg = String.format("Switch: [%s], " - + "received unexpected RoleReply[%s]. " - + "No roles are pending, and this controller's " - + "current role:[%s] does not match reply. " - + "Disconnecting switch ... ", - sw.getStringId(), - rri, currentRole); - throw new SwitchStateException(msg); - } - } - log.debug("Received unexpected RoleReply {} from " - + "Switch: {}. " - + "This controller has no current role for this sw. " - + "Ignoring ...", - rri, - sw == null ? "(null)" : sw.getStringId()); - return RoleRecvStatus.OTHER_EXPECTATION; - } - - // XXX Should check generation id meaningfully and other cases of expectations - //if (pendingXid != xid) { - // log.info("Received older role reply from " + - // "switch {} ({}). Ignoring. " + - // "Waiting for {}, xid={}", - // new Object[] {sw.getStringId(), rri, - // pendingRole, pendingXid }); - // return RoleRecvStatus.OLD_REPLY; - //} - sw.returnRoleReply(expectedRole, receivedRole); - - if (expectedRole == receivedRole) { - log.debug("Received role reply message from {} that matched " - + "expected role-reply {} with expectations {}", - sw.getStringId(), receivedRole, expectation); - - // Done with this RoleReply; Invalidate - pendingReplies.invalidate(xid); - if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE || - expectation == RoleRecvStatus.MATCHED_SET_ROLE) { - return expectation; - } else { - return RoleRecvStatus.OTHER_EXPECTATION; - } - } - - pendingReplies.invalidate(xid); - // if xids match but role's don't, perhaps its a query (OF1.3) - if (expectation == RoleRecvStatus.REPLY_QUERY) { - return expectation; - } - - return RoleRecvStatus.OTHER_EXPECTATION; - } - - /** - * Called if we receive an error message. If the xid matches the - * pending request we handle it otherwise we ignore it. - * - * Note: since we only keep the last pending request we might get - * error messages for earlier role requests that we won't be able - * to handle - */ - @Override - public synchronized RoleRecvStatus deliverError(OFErrorMsg error) - throws SwitchStateException { - RoleState errorRole = pendingReplies.getIfPresent(error.getXid()); - if (errorRole == null) { - if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) { - log.debug("Received an error msg from sw {} for a role request," - + " but not for pending request in role-changer; " - + " ignoring error {} ...", - sw.getStringId(), error); - } else { - log.debug("Received an error msg from sw {}, but no pending " - + "requests in role-changer; not handling ...", - sw.getStringId()); - } - return RoleRecvStatus.OTHER_EXPECTATION; - } - // it is an error related to a currently pending role request message - if (error.getErrType() == OFErrorType.BAD_REQUEST) { - log.error("Received a error msg {} from sw {} for " - + "pending role request {}. Switch driver indicates " - + "role-messaging is supported. Possible issues in " - + "switch driver configuration?", - ((OFBadRequestErrorMsg) error).toString(), - sw.getStringId(), - errorRole); - return RoleRecvStatus.UNSUPPORTED; - } - - if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) { - OFRoleRequestFailedErrorMsg rrerr = - (OFRoleRequestFailedErrorMsg) error; - switch (rrerr.getCode()) { - case BAD_ROLE: - // switch says that current-role-req has bad role? - // for now we disconnect - // fall-thru - case STALE: - // switch says that current-role-req has stale gen-id? - // for now we disconnect - // fall-thru - case UNSUP: - // switch says that current-role-req has role that - // cannot be supported? for now we disconnect - String msgx = String.format("Switch: [%s], " - + "received Error to for pending role request [%s]. " - + "Error:[%s]. Disconnecting switch ... ", - sw.getStringId(), - errorRole, rrerr); - throw new SwitchStateException(msgx); - default: - break; - } - } - - // This error message was for a role request message but we dont know - // how to handle errors for nicira role request messages - return RoleRecvStatus.OTHER_EXPECTATION; - } - - /** - * Extract the role from an OFVendor message. - * - * Extract the role from an OFVendor message if the message is a - * Nicira role reply. Otherwise return null. - * - * @param experimenterMsg message - * @return The role in the message if the message is a Nicira role - * reply, null otherwise. - * @throws SwitchStateException If the message is a Nicira role reply - * but the numeric role value is unknown. - */ - @Override - public RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg) - throws SwitchStateException { - int vendor = (int) experimenterMsg.getExperimenter(); - if (vendor != 0x2320) { - return null; - } - OFNiciraControllerRoleReply nrr = - (OFNiciraControllerRoleReply) experimenterMsg; - - RoleState role = null; - OFNiciraControllerRole ncr = nrr.getRole(); - switch (ncr) { - case ROLE_MASTER: - role = RoleState.MASTER; - break; - case ROLE_OTHER: - role = RoleState.EQUAL; - break; - case ROLE_SLAVE: - role = RoleState.SLAVE; - break; - default: //handled below - } - - if (role == null) { - String msg = String.format("Switch: [%s], " - + "received NX_ROLE_REPLY with invalid role " - + "value %s", - sw.getStringId(), - nrr.getRole()); - throw new SwitchStateException(msg); - } - return role; - } - - /** - * Extract the role information from an OF1.3 Role Reply Message. - * - * @param rrmsg the role message - * @return RoleReplyInfo object - * @throws SwitchStateException if the role information could not be extracted. - */ - @Override - public RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg) - throws SwitchStateException { - OFControllerRole cr = rrmsg.getRole(); - RoleState role = null; - switch (cr) { - case ROLE_EQUAL: - role = RoleState.EQUAL; - break; - case ROLE_MASTER: - role = RoleState.MASTER; - break; - case ROLE_SLAVE: - role = RoleState.SLAVE; - break; - case ROLE_NOCHANGE: // switch should send current role - default: - String msg = String.format("Unknown controller role %s " - + "received from switch %s", cr, sw); - throw new SwitchStateException(msg); - } - - return new RoleReplyInfo(role, rrmsg.getGenerationId(), rrmsg.getXid()); - } - -} - diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/package-info.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/package-info.java deleted file mode 100644 index a5d9f274..00000000 --- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * 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. - */ - -/** - * Implementation of the OpenFlow controller IO subsystem. - */ -package org.onosproject.openflow.controller.impl; diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/ChannelAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/ChannelAdapter.java deleted file mode 100644 index 75260a1d..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/ChannelAdapter.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import java.net.SocketAddress; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelConfig; -import org.jboss.netty.channel.ChannelFactory; -import org.jboss.netty.channel.ChannelFuture; -import org.jboss.netty.channel.ChannelPipeline; - -/** - * Adapter for testing against a netty channel. - */ -public class ChannelAdapter implements Channel { - @Override - public Integer getId() { - return null; - } - - @Override - public ChannelFactory getFactory() { - return null; - } - - @Override - public Channel getParent() { - return null; - } - - @Override - public ChannelConfig getConfig() { - return null; - } - - @Override - public ChannelPipeline getPipeline() { - return null; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public boolean isBound() { - return false; - } - - @Override - public boolean isConnected() { - return false; - } - - @Override - public SocketAddress getLocalAddress() { - return null; - } - - @Override - public SocketAddress getRemoteAddress() { - return null; - } - - @Override - public ChannelFuture write(Object o) { - return null; - } - - @Override - public ChannelFuture write(Object o, SocketAddress socketAddress) { - return null; - } - - @Override - public ChannelFuture bind(SocketAddress socketAddress) { - return null; - } - - @Override - public ChannelFuture connect(SocketAddress socketAddress) { - return null; - } - - @Override - public ChannelFuture disconnect() { - return null; - } - - @Override - public ChannelFuture unbind() { - return null; - } - - @Override - public ChannelFuture close() { - return null; - } - - @Override - public ChannelFuture getCloseFuture() { - return null; - } - - @Override - public int getInterestOps() { - return 0; - } - - @Override - public boolean isReadable() { - return false; - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public ChannelFuture setInterestOps(int i) { - return null; - } - - @Override - public ChannelFuture setReadable(boolean b) { - return null; - } - - @Override - public Object getAttachment() { - return null; - } - - @Override - public void setAttachment(Object o) { - - } - - @Override - public int compareTo(Channel o) { - return 0; - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/ChannelHandlerContextAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/ChannelHandlerContextAdapter.java deleted file mode 100644 index 5b6c2a36..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/ChannelHandlerContextAdapter.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelEvent; -import org.jboss.netty.channel.ChannelHandler; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelPipeline; - -/** - * Adapter for testing against a netty channel handler context. - */ -public class ChannelHandlerContextAdapter implements ChannelHandlerContext { - @Override - public Channel getChannel() { - return null; - } - - @Override - public ChannelPipeline getPipeline() { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public ChannelHandler getHandler() { - return null; - } - - @Override - public boolean canHandleUpstream() { - return false; - } - - @Override - public boolean canHandleDownstream() { - return false; - } - - @Override - public void sendUpstream(ChannelEvent channelEvent) { - - } - - @Override - public void sendDownstream(ChannelEvent channelEvent) { - - } - - @Override - public Object getAttachment() { - return null; - } - - @Override - public void setAttachment(Object o) { - - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/DriverAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/DriverAdapter.java deleted file mode 100644 index 57becf94..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/DriverAdapter.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import java.util.Map; -import java.util.Set; - -import org.onosproject.net.driver.Behaviour; -import org.onosproject.net.driver.Driver; -import org.onosproject.net.driver.DriverData; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; - -/** - * Created by ray on 11/4/15. - */ -public class DriverAdapter implements Driver { - @Override - public String name() { - return null; - } - - @Override - public Driver parent() { - return null; - } - - @Override - public String manufacturer() { - return null; - } - - @Override - public String hwVersion() { - return null; - } - - @Override - public String swVersion() { - return null; - } - - @Override - public Set<Class<? extends Behaviour>> behaviours() { - return null; - } - - @Override - public Class<? extends Behaviour> implementation(Class<? extends Behaviour> behaviour) { - return null; - } - - @Override - public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) { - return true; - } - - @Override - public <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass) { - return null; - } - - @SuppressWarnings("unchecked") - @Override - public <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass) { - if (behaviourClass == OpenFlowSwitchDriver.class) { - return (T) new OpenflowSwitchDriverAdapter(); - } - return null; - } - - @Override - public Map<String, String> properties() { - return null; - } - - @Override - public Driver merge(Driver other) { - return null; - } - - @Override - public Set<String> keys() { - return null; - } - - @Override - public String value(String key) { - return null; - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/DriverServiceAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/DriverServiceAdapter.java deleted file mode 100644 index 25596ada..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/DriverServiceAdapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import java.util.Set; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.driver.Behaviour; -import org.onosproject.net.driver.Driver; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.net.driver.DriverService; - -/** - * Created by ray on 11/4/15. - */ -public class DriverServiceAdapter implements DriverService { - @Override - public Set<Driver> getDrivers() { - return null; - } - - @Override - public Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour) { - return null; - } - - @Override - public Driver getDriver(String mfr, String hw, String sw) { - return null; - } - - @Override - public Driver getDriver(DeviceId deviceId) { - return null; - } - - @Override - public DriverHandler createHandler(DeviceId deviceId, String... credentials) { - return null; - } - - @Override - public Driver getDriver(String driverName) { - return null; - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OFDescStatsReplyAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OFDescStatsReplyAdapter.java deleted file mode 100644 index 1e866413..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OFDescStatsReplyAdapter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import java.util.Set; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.projectfloodlight.openflow.protocol.OFDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; -import org.projectfloodlight.openflow.protocol.OFStatsType; -import org.projectfloodlight.openflow.protocol.OFType; -import org.projectfloodlight.openflow.protocol.OFVersion; - -import com.google.common.hash.PrimitiveSink; - -/** - * Created by ray on 11/4/15. - */ -public class OFDescStatsReplyAdapter implements OFDescStatsReply { - @Override - public OFVersion getVersion() { - return null; - } - - @Override - public OFType getType() { - return null; - } - - @Override - public long getXid() { - return 0; - } - - @Override - public OFStatsType getStatsType() { - return null; - } - - @Override - public Set<OFStatsReplyFlags> getFlags() { - return null; - } - - @Override - public String getMfrDesc() { - return null; - } - - @Override - public String getHwDesc() { - return null; - } - - @Override - public String getSwDesc() { - return null; - } - - @Override - public String getSerialNum() { - return null; - } - - @Override - public String getDpDesc() { - return null; - } - - @Override - public void writeTo(ChannelBuffer channelBuffer) { - - } - - @Override - public Builder createBuilder() { - return null; - } - - @Override - public void putTo(PrimitiveSink sink) { - - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OfMessageAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OfMessageAdapter.java deleted file mode 100644 index e9b38e3a..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OfMessageAdapter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFType; -import org.projectfloodlight.openflow.protocol.OFVersion; - -import com.google.common.hash.PrimitiveSink; - -/** - * Adapter for testing against an OpenFlow message. - */ -public class OfMessageAdapter implements OFMessage { - @Override - public OFVersion getVersion() { - return null; - } - - @Override - public OFType getType() { - return null; - } - - @Override - public long getXid() { - return 0; - } - - @Override - public void writeTo(ChannelBuffer channelBuffer) { } - - @Override - public Builder createBuilder() { - return null; - } - - @Override - public void putTo(PrimitiveSink sink) { } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OpenflowSwitchDriverAdapter.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OpenflowSwitchDriverAdapter.java deleted file mode 100644 index 9b899a67..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/OpenflowSwitchDriverAdapter.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow; - -import java.util.List; - -import org.jboss.netty.channel.Channel; -import org.onosproject.net.Device; -import org.onosproject.net.driver.DriverData; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.openflow.controller.Dpid; -import org.onosproject.openflow.controller.RoleState; -import org.onosproject.openflow.controller.driver.OpenFlowAgent; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; -import org.onosproject.openflow.controller.driver.RoleHandler; -import org.onosproject.openflow.controller.driver.SwitchStateException; -import org.projectfloodlight.openflow.protocol.OFDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFErrorMsg; -import org.projectfloodlight.openflow.protocol.OFFactories; -import org.projectfloodlight.openflow.protocol.OFFactory; -import org.projectfloodlight.openflow.protocol.OFFeaturesReply; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFPortDesc; -import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFVersion; - -/** - * Testing adapter for the OpenFlow switch driver class. - */ -public class OpenflowSwitchDriverAdapter implements OpenFlowSwitchDriver { - - RoleState role = RoleState.MASTER; - - @Override - public void setAgent(OpenFlowAgent agent) { - - } - - @Override - public void setRoleHandler(RoleHandler roleHandler) { - - } - - @Override - public void reassertRole() { - - } - - @Override - public boolean handleRoleError(OFErrorMsg error) { - return false; - } - - @Override - public void handleNiciraRole(OFMessage m) throws SwitchStateException { - - } - - @Override - public void handleRole(OFMessage m) throws SwitchStateException { - - } - - @Override - public boolean connectSwitch() { - return false; - } - - @Override - public boolean activateMasterSwitch() { - return false; - } - - @Override - public boolean activateEqualSwitch() { - return false; - } - - @Override - public void transitionToEqualSwitch() { - - } - - @Override - public void transitionToMasterSwitch() { - - } - - @Override - public void removeConnectedSwitch() { - - } - - @Override - public void setPortDescReply(OFPortDescStatsReply portDescReply) { - - } - - @Override - public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) { - - } - - @Override - public void setFeaturesReply(OFFeaturesReply featuresReply) { - - } - - @Override - public void setSwitchDescription(OFDescStatsReply desc) { - - } - - @Override - public int getNextTransactionId() { - return 0; - } - - @Override - public void setOFVersion(OFVersion ofV) { - - } - - @Override - public void setTableFull(boolean full) { - - } - - @Override - public void setChannel(Channel channel) { - - } - - @Override - public void setConnected(boolean connected) { - - } - - @Override - public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) { - - } - - @Override - public Boolean supportNxRole() { - return true; - } - - @Override - public void startDriverHandshake() { - - } - - @Override - public boolean isDriverHandshakeComplete() { - return false; - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - - } - - @Override - public void sendRoleRequest(OFMessage message) { - - } - - @Override - public void sendHandshakeMessage(OFMessage message) { - - } - - @Override - public DriverHandler handler() { - return null; - } - - @Override - public void setHandler(DriverHandler handler) { - - } - - @Override - public DriverData data() { - return null; - } - - @Override - public void setData(DriverData data) { - - } - - @Override - public void sendMsg(OFMessage msg) { - - } - - @Override - public void sendMsg(List<OFMessage> msgs) { - - } - - @Override - public void handleMessage(OFMessage fromSwitch) { - - } - - @Override - public void setRole(RoleState role) { - this.role = role; - } - - @Override - public RoleState getRole() { - return role; - } - - @Override - public List<OFPortDesc> getPorts() { - return null; - } - - @Override - public OFFactory factory() { - // return what-ever triggers requestPending = true - return OFFactories.getFactory(OFVersion.OF_10); - } - - @Override - public String getStringId() { - return "100"; - } - - @Override - public long getId() { - return 0; - } - - @Override - public String manufacturerDescription() { - return null; - } - - @Override - public String datapathDescription() { - return null; - } - - @Override - public String hardwareDescription() { - return null; - } - - @Override - public String softwareDescription() { - return null; - } - - @Override - public String serialNumber() { - return null; - } - - @Override - public boolean isConnected() { - return false; - } - - @Override - public void disconnectSwitch() { - - } - - @Override - public void returnRoleReply(RoleState requested, RoleState response) { - - } - - @Override - public Device.Type deviceType() { - return Device.Type.SWITCH; - } - - @Override - public String channelId() { - return null; - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/ControllerTest.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/ControllerTest.java deleted file mode 100644 index 3ff3bde5..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/ControllerTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import java.io.File; -import java.io.IOException; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.Map; -import java.util.stream.IntStream; - -import org.junit.Before; -import org.junit.Test; -import org.onlab.junit.TestTools; -import org.onlab.util.ItemNotFoundException; -import org.onosproject.net.DeviceId; -import org.onosproject.net.driver.Driver; -import org.onosproject.openflow.DriverAdapter; -import org.onosproject.openflow.DriverServiceAdapter; -import org.onosproject.openflow.OFDescStatsReplyAdapter; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; -import org.projectfloodlight.openflow.protocol.OFDescStatsReply; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.io.Files; - -import static com.google.common.io.ByteStreams.toByteArray; -import static com.google.common.io.Files.write; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; - -/** - * Unit tests for the OpenFlow controller class. - */ -public class ControllerTest { - - Controller controller; - protected static final Logger log = LoggerFactory.getLogger(ControllerTest.class); - - static final File TEST_DIR = Files.createTempDir(); - - /* - * Writes the necessary file for the tests in the temporary directory - */ - static File stageTestResource(String name) throws IOException { - File file = new File(TEST_DIR, name); - byte[] bytes = toByteArray(ControllerTest.class.getResourceAsStream(name)); - write(bytes, file); - return file; - } - - class MockDriverService extends DriverServiceAdapter { - static final int NO_SUCH_DRIVER_ID = 1; - static final int ITEM_NOT_FOUND_DRIVER_ID = 2; - static final int DRIVER_EXISTS_ID = 3; - - static final String BASE_DRIVER_NAME = "of:000000000000000"; - - static final String NO_SUCH_DRIVER = BASE_DRIVER_NAME - + NO_SUCH_DRIVER_ID; - static final String ITEM_NOT_FOUND_DRIVER = BASE_DRIVER_NAME - + ITEM_NOT_FOUND_DRIVER_ID; - static final String DRIVER_EXISTS = BASE_DRIVER_NAME - + DRIVER_EXISTS_ID; - - @Override - public Driver getDriver(DeviceId deviceId) { - switch (deviceId.toString()) { - case NO_SUCH_DRIVER: - return null; - case ITEM_NOT_FOUND_DRIVER: - throw new ItemNotFoundException(); - case DRIVER_EXISTS: - return new DriverAdapter(); - default: - throw new AssertionError(); - } - } - } - - /** - * Creates and initializes a new controller. - */ - @Before - public void setUp() { - controller = new Controller(); - Dictionary<String, String> properties = new Hashtable<>(); - properties.put("openflowPorts", - Integer.toString(TestTools.findAvailablePort(0))); - controller.setConfigParams(properties); - } - - /** - * Tests fetching a driver that does not exist. - */ - @Test - public void switchInstanceNotFoundTest() { - controller.start(null, new MockDriverService()); - OpenFlowSwitchDriver driver = - controller.getOFSwitchInstance(MockDriverService.NO_SUCH_DRIVER_ID, - null, - null); - assertThat(driver, nullValue()); - controller.stop(); - } - - /** - * Tests fetching a driver that throws an ItemNotFoundException. - */ - @Test - public void switchItemNotFoundTest() { - controller.start(null, new MockDriverService()); - OFDescStatsReply stats = - new OFDescStatsReplyAdapter(); - OpenFlowSwitchDriver driver = - controller.getOFSwitchInstance(MockDriverService.ITEM_NOT_FOUND_DRIVER_ID, - stats, - null); - assertThat(driver, nullValue()); - controller.stop(); - } - - /** - * Tests fetching a driver that throws an ItemNotFoundException. - */ - @Test - public void driverExistsTest() { - controller.start(null, new MockDriverService()); - OFDescStatsReply stats = - new OFDescStatsReplyAdapter(); - OpenFlowSwitchDriver driver = - controller.getOFSwitchInstance(MockDriverService.DRIVER_EXISTS_ID, - stats, - null); - assertThat(driver, notNullValue()); - controller.stop(); - } - - /** - * Tests configuring the controller. - */ - @Test - public void testConfiguration() { - Dictionary<String, String> properties = new Hashtable<>(); - properties.put("openflowPorts", "1,2,3,4,5"); - properties.put("workerThreads", "5"); - - controller.setConfigParams(properties); - IntStream.rangeClosed(1, 5) - .forEach(i -> assertThat(controller.openFlowPorts, hasItem(i))); - assertThat(controller.workerThreads, is(5)); - } - - /** - * Tests the SSL/TLS methods in the controller. - */ - @Test - public void testSsl() throws IOException { - File keystore = stageTestResource("ControllerTestKeystore.jks"); - String keystoreName = keystore.getAbsolutePath(); - - System.setProperty("enableOFTLS", Boolean.toString(Boolean.TRUE)); - System.setProperty("javax.net.ssl.keyStore", keystoreName); - System.setProperty("javax.net.ssl.trustStore", keystoreName); - System.setProperty("javax.net.ssl.keyStorePassword", "password"); - System.setProperty("javax.net.ssl.trustStorePassword", "password"); - Dictionary<String, String> properties = new Hashtable<>(); - properties.put("openflowPorts", - Integer.toString(TestTools.findAvailablePort(0))); - properties.put("workerThreads", "0"); - - controller.setConfigParams(properties); - controller.start(null, new MockDriverService()); - - assertThat(controller.serverSSLEngine, notNullValue()); - - controller.stop(); - boolean removed = keystore.delete(); - if (!removed) { - log.warn("Could not remove temporary file"); - } - } - - /** - * Tests controll utility health methods. - */ - @Test - public void testHealth() { - Map<String, Long> memory = controller.getMemory(); - assertThat(memory.size(), is(2)); - assertThat(memory.get("total"), is(not(0))); - assertThat(memory.get("free"), is(not(0))); - - long startTime = controller.getSystemStartTime(); - assertThat(startTime, lessThan(System.currentTimeMillis())); - - long upTime = controller.getSystemUptime(); - assertThat(upTime, lessThan(30L * 1000)); - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OFMessageDecoderTest.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OFMessageDecoderTest.java deleted file mode 100644 index ed1db238..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OFMessageDecoderTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.junit.Test; -import org.onosproject.openflow.ChannelAdapter; -import org.onosproject.openflow.ChannelHandlerContextAdapter; -import org.projectfloodlight.openflow.protocol.OFHello; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; - -/** - * Tests for the OpenFlow message decoder. - */ -public class OFMessageDecoderTest { - - static class ConnectedChannel extends ChannelAdapter { - @Override - public boolean isConnected() { - return true; - } - } - - private ChannelBuffer getHelloMessageBuffer() { - // OFHello, OF version 1, xid of 0, total of 8 bytes - byte[] messageData = {0x1, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0}; - ChannelBuffer channelBuffer = ChannelBuffers.dynamicBuffer(); - channelBuffer.writeBytes(messageData); - return channelBuffer; - } - - /** - * Tests decoding a message on a closed channel. - * - * @throws Exception when an exception is thrown from the decoder - */ - @Test - public void testDecodeNoChannel() throws Exception { - OFMessageDecoder decoder = new OFMessageDecoder(); - ChannelBuffer channelBuffer = getHelloMessageBuffer(); - Object message = - decoder.decode(new ChannelHandlerContextAdapter(), - new ChannelAdapter(), - channelBuffer); - assertThat(message, nullValue()); - } - - /** - * Tests decoding a message. - * - * @throws Exception when an exception is thrown from the decoder - */ - @Test - public void testDecode() throws Exception { - OFMessageDecoder decoder = new OFMessageDecoder(); - ChannelBuffer channelBuffer = getHelloMessageBuffer(); - Object message = - decoder.decode(new ChannelHandlerContextAdapter(), - new ConnectedChannel(), - channelBuffer); - assertThat(message, notNullValue()); - assertThat(message, instanceOf(OFHello.class)); - } - -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OFMessageEncoderTest.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OFMessageEncoderTest.java deleted file mode 100644 index 59685f16..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OFMessageEncoderTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.junit.Test; -import org.onosproject.openflow.OfMessageAdapter; -import org.projectfloodlight.openflow.protocol.OFMessage; - -import com.google.common.collect.ImmutableList; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -/** - * Tests for the OpenFlow message encoder. - */ -public class OFMessageEncoderTest { - - static class MockOfMessage extends OfMessageAdapter { - static int nextId = 1; - final int id; - - MockOfMessage() { - id = nextId++; - } - - @Override - public void writeTo(ChannelBuffer channelBuffer) { - String message = "message" + Integer.toString(id) + " "; - channelBuffer.writeBytes(message.getBytes(StandardCharsets.UTF_8)); - } - } - - /** - * Tests that encoding a non-list returns the object specified. - * - * @throws Exception on exception in the encoder - */ - @Test - public void testNoList() throws Exception { - OFMessageEncoder encoder = new OFMessageEncoder(); - MockOfMessage message = new MockOfMessage(); - OFMessage returnedMessage = - (OFMessage) encoder.encode(null, null, message); - assertThat(message, is(returnedMessage)); - } - - /** - * Tests that encoding a list returns the proper encoded payload. - * - * @throws Exception on exception in the encoder - */ - @Test - public void testList() throws Exception { - OFMessageEncoder encoder = new OFMessageEncoder(); - MockOfMessage message1 = new MockOfMessage(); - MockOfMessage message2 = new MockOfMessage(); - MockOfMessage message3 = new MockOfMessage(); - List<MockOfMessage> messages = ImmutableList.of(message1, message2, message3); - ChannelBuffer returnedChannel = - (ChannelBuffer) encoder.encode(null, null, messages); - assertThat(returnedChannel, notNullValue()); - byte[] channelBytes = returnedChannel.array(); - String expectedListMessage = "message1 message2 message3 "; - String listMessage = - (new String(channelBytes, StandardCharsets.UTF_8)) - .substring(0, expectedListMessage.length()); - assertThat(listMessage, is(expectedListMessage)); - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java deleted file mode 100644 index e079c590..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.List; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -import org.easymock.EasyMock; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.junit.TestTools; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.openflow.OpenflowSwitchDriverAdapter; -import org.onosproject.openflow.controller.Dpid; -import org.onosproject.openflow.controller.OpenFlowSwitch; -import org.onosproject.openflow.controller.OpenFlowSwitchListener; -import org.onosproject.openflow.controller.RoleState; -import org.osgi.service.component.ComponentContext; -import org.projectfloodlight.openflow.protocol.OFPortStatus; - -import com.google.common.collect.ImmutableSet; - -import static junit.framework.TestCase.fail; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.replay; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; - -/** - * Unit tests for the open flow controller implementation test. - */ -public class OpenFlowControllerImplTest { - - OpenFlowSwitch switch1; - Dpid dpid1; - OpenFlowSwitch switch2; - Dpid dpid2; - OpenFlowSwitch switch3; - Dpid dpid3; - - OpenFlowControllerImpl controller; - OpenFlowControllerImpl.OpenFlowSwitchAgent agent; - TestSwitchListener switchListener; - - /** - * Test harness for a switch listener. - */ - static class TestSwitchListener implements OpenFlowSwitchListener { - final List<Dpid> removedDpids = new ArrayList<>(); - final List<Dpid> addedDpids = new ArrayList<>(); - final List<Dpid> changedDpids = new ArrayList<>(); - - @Override - public void switchAdded(Dpid dpid) { - addedDpids.add(dpid); - } - - @Override - public void switchRemoved(Dpid dpid) { - removedDpids.add(dpid); - } - - @Override - public void switchChanged(Dpid dpid) { - changedDpids.add(dpid); - } - - @Override - public void portChanged(Dpid dpid, OFPortStatus status) { - // Stub - } - - @Override - public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) { - // Stub - } - } - - - /** - * Sets up switches to use as data, mocks and launches a controller instance. - */ - @Before - public void setUp() { - try { - switch1 = new OpenflowSwitchDriverAdapter(); - dpid1 = Dpid.dpid(new URI("of:0000000000000111")); - switch2 = new OpenflowSwitchDriverAdapter(); - dpid2 = Dpid.dpid(new URI("of:0000000000000222")); - switch3 = new OpenflowSwitchDriverAdapter(); - dpid3 = Dpid.dpid(new URI("of:0000000000000333")); - } catch (URISyntaxException ex) { - // Does not happen - fail(); - } - - controller = new OpenFlowControllerImpl(); - agent = controller.agent; - - switchListener = new TestSwitchListener(); - controller.addListener(switchListener); - - ComponentConfigService mockConfigService = - EasyMock.createMock(ComponentConfigService.class); - expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of()); - mockConfigService.registerProperties(controller.getClass()); - expectLastCall(); - mockConfigService.unregisterProperties(controller.getClass(), false); - expectLastCall(); - expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of()); - controller.cfgService = mockConfigService; - replay(mockConfigService); - - ComponentContext mockContext = EasyMock.createMock(ComponentContext.class); - Dictionary<String, String> properties = new Hashtable<>(); - properties.put("openflowPorts", - Integer.toString(TestTools.findAvailablePort(0))); - expect(mockContext.getProperties()).andReturn(properties); - replay(mockContext); - controller.activate(mockContext); - } - - @After - public void tearDown() { - controller.removeListener(switchListener); - controller.deactivate(); - } - - /** - * Converts an Iterable of some type into a stream of that type. - * - * @param items Iterable of objects - * @param <T> type of the items in the iterable - * @return stream of objects of type T - */ - private <T> Stream<T> makeIntoStream(Iterable<T> items) { - return StreamSupport.stream( - Spliterators.spliteratorUnknownSize( - items.iterator(), Spliterator.ORDERED), false); - } - - - /** - * Tests adding and removing connected switches. - */ - @Test - public void testAddRemoveConnectedSwitch() { - - // test adding connected switches - boolean addSwitch1 = agent.addConnectedSwitch(dpid1, switch1); - assertThat(addSwitch1, is(true)); - boolean addSwitch2 = agent.addConnectedSwitch(dpid2, switch2); - assertThat(addSwitch2, is(true)); - boolean addSwitch3 = agent.addConnectedSwitch(dpid3, switch3); - assertThat(addSwitch3, is(true)); - - // Make sure the listener add callbacks fired - assertThat(switchListener.addedDpids, hasSize(3)); - assertThat(switchListener.addedDpids, hasItems(dpid1, dpid2, dpid3)); - - // Test adding a switch twice - it should fail - boolean addBadSwitch1 = agent.addConnectedSwitch(dpid1, switch1); - assertThat(addBadSwitch1, is(false)); - - assertThat(controller.connectedSwitches.size(), is(3)); - - // test querying the switch list - Stream<OpenFlowSwitch> fetchedSwitches = - makeIntoStream(controller.getSwitches()); - long switchCount = fetchedSwitches.count(); - assertThat(switchCount, is(3L)); - - // test querying the individual switch - OpenFlowSwitch queriedSwitch = controller.getSwitch(dpid1); - assertThat(queriedSwitch, is(switch1)); - - // Remove a switch - agent.removeConnectedSwitch(dpid3); - Stream<OpenFlowSwitch> fetchedSwitchesAfterRemove = - makeIntoStream(controller.getSwitches()); - long switchCountAfterRemove = fetchedSwitchesAfterRemove.count(); - assertThat(switchCountAfterRemove, is(2L)); - - // Make sure the listener delete callbacks fired - assertThat(switchListener.removedDpids, hasSize(1)); - assertThat(switchListener.removedDpids, hasItems(dpid3)); - - // test querying the removed switch - OpenFlowSwitch queriedSwitchAfterRemove = controller.getSwitch(dpid3); - assertThat(queriedSwitchAfterRemove, nullValue()); - } - - /** - * Tests adding master switches. - */ - @Test - public void testMasterSwitch() { - agent.addConnectedSwitch(dpid1, switch1); - agent.transitionToMasterSwitch(dpid1); - - Stream<OpenFlowSwitch> fetchedMasterSwitches = - makeIntoStream(controller.getMasterSwitches()); - assertThat(fetchedMasterSwitches.count(), is(1L)); - Stream<OpenFlowSwitch> fetchedActivatedSwitches = - makeIntoStream(controller.getEqualSwitches()); - assertThat(fetchedActivatedSwitches.count(), is(0L)); - OpenFlowSwitch fetchedSwitch1 = controller.getMasterSwitch(dpid1); - assertThat(fetchedSwitch1, is(switch1)); - - agent.addConnectedSwitch(dpid2, switch2); - boolean addSwitch2 = agent.addActivatedMasterSwitch(dpid2, switch2); - assertThat(addSwitch2, is(true)); - OpenFlowSwitch fetchedSwitch2 = controller.getMasterSwitch(dpid2); - assertThat(fetchedSwitch2, is(switch2)); - } - - /** - * Tests adding equal switches. - */ - @Test - public void testEqualSwitch() { - agent.addConnectedSwitch(dpid1, switch1); - agent.transitionToEqualSwitch(dpid1); - - Stream<OpenFlowSwitch> fetchedEqualSwitches = - makeIntoStream(controller.getEqualSwitches()); - assertThat(fetchedEqualSwitches.count(), is(1L)); - Stream<OpenFlowSwitch> fetchedActivatedSwitches = - makeIntoStream(controller.getMasterSwitches()); - assertThat(fetchedActivatedSwitches.count(), is(0L)); - OpenFlowSwitch fetchedSwitch1 = controller.getEqualSwitch(dpid1); - assertThat(fetchedSwitch1, is(switch1)); - - agent.addConnectedSwitch(dpid2, switch2); - boolean addSwitch2 = agent.addActivatedEqualSwitch(dpid2, switch2); - assertThat(addSwitch2, is(true)); - OpenFlowSwitch fetchedSwitch2 = controller.getEqualSwitch(dpid2); - assertThat(fetchedSwitch2, is(switch2)); - } - - /** - * Tests changing switch role. - */ - @Test - public void testRoleSetting() { - agent.addConnectedSwitch(dpid2, switch2); - - // check that state can be changed for a connected switch - assertThat(switch2.getRole(), is(RoleState.MASTER)); - controller.setRole(dpid2, RoleState.EQUAL); - assertThat(switch2.getRole(), is(RoleState.EQUAL)); - - // check that changing state on an unconnected switch does not crash - controller.setRole(dpid3, RoleState.SLAVE); - } -} diff --git a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java b/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java deleted file mode 100644 index 4b594383..00000000 --- a/framework/src/onos/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * 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 org.onosproject.openflow.controller.impl; - -import java.io.IOException; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onosproject.openflow.OpenflowSwitchDriverAdapter; -import org.onosproject.openflow.controller.RoleState; -import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver; -import org.onosproject.openflow.controller.driver.RoleRecvStatus; -import org.onosproject.openflow.controller.driver.RoleReplyInfo; -import org.onosproject.openflow.controller.driver.SwitchStateException; -import org.projectfloodlight.openflow.protocol.OFDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFFeaturesReply; -import org.projectfloodlight.openflow.types.U64; - -import static org.junit.Assert.assertEquals; -import static org.onosproject.openflow.controller.RoleState.MASTER; -import static org.onosproject.openflow.controller.RoleState.SLAVE; -import static org.onosproject.openflow.controller.driver.RoleRecvStatus.MATCHED_CURRENT_ROLE; -import static org.onosproject.openflow.controller.driver.RoleRecvStatus.OTHER_EXPECTATION; - -public class RoleManagerTest { - - private static final U64 GID = U64.of(10L); - private static final long XID = 1L; - - private OpenFlowSwitchDriver sw; - private RoleManager manager; - - @Before - public void setUp() { - sw = new TestSwitchDriver(); - manager = new RoleManager(sw); - } - - @After - public void tearDown() { - manager = null; - sw = null; - } - - @Test - public void deliverRoleReply() { - RoleRecvStatus status; - - RoleReplyInfo asserted = new RoleReplyInfo(MASTER, GID, XID); - RoleReplyInfo unasserted = new RoleReplyInfo(SLAVE, GID, XID); - - try { - //call without sendRoleReq() for requestPending = false - //first, sw.role == null - status = manager.deliverRoleReply(asserted); - assertEquals("expectation wrong", OTHER_EXPECTATION, status); - - sw.setRole(MASTER); - assertEquals("expectation wrong", OTHER_EXPECTATION, status); - sw.setRole(SLAVE); - - //match to pendingRole = MASTER, requestPending = true - manager.sendRoleRequest(MASTER, MATCHED_CURRENT_ROLE); - status = manager.deliverRoleReply(asserted); - assertEquals("expectation wrong", MATCHED_CURRENT_ROLE, status); - - //requestPending never gets reset -- this might be a bug. - status = manager.deliverRoleReply(unasserted); - assertEquals("expectation wrong", OTHER_EXPECTATION, status); - assertEquals("pending role mismatch", MASTER, ((TestSwitchDriver) sw).failed); - - } catch (IOException | SwitchStateException e) { - assertEquals("unexpected error thrown", - SwitchStateException.class, e.getClass()); - } - } - - private class TestSwitchDriver extends OpenflowSwitchDriverAdapter { - - RoleState failed = null; - RoleState current = null; - - @Override - public void setRole(RoleState role) { - current = role; - } - - @Override - public RoleState getRole() { - return current; - } - - @Override - public void setFeaturesReply(OFFeaturesReply featuresReply) { - } - - @Override - public void setSwitchDescription(OFDescStatsReply desc) { - } - - @Override - public int getNextTransactionId() { - return (int) XID; - } - - @Override - public void returnRoleReply(RoleState requested, RoleState response) { - failed = requested; - } - - @Override - public String channelId() { - return "1.2.3.4:1"; - } - } -} |