From: Jason Ye Date: Wed, 24 Apr 2013 16:55:27 +0000 (-0700) Subject: - Plugin sends Barrier msg every 100 async msgs (configurable thru config.ini: of... X-Git-Tag: releasepom-0.1.0~533 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=e326757873804be369d20efd0b54467871094c06 - Plugin sends Barrier msg every 100 async msgs (configurable thru config.ini: of.barrierMessagePriorCount) - SAL/plugin provide service to send Barrier message on demand. FM/application should invoke it explictly for sync purpose. - LLDP interval is set to 5 mins (configurable thru config.ini: of.discoveryInterval) - LLDP timeout is set to 1 min (configurable thru config.ini: of.discoveryTimeout). Retry 2 times. - Switch liveness timeout is set to 60.5 sec (configurable thru config.ini: of.switchLivenessTimeout) - SAL generates Request ID and passes it down to the plugin (IPluginInFlowProgrammerService: addFlowAsync(Node node, Flow flow, long rid), modifyFlowAsync(), deleteFlowAsync()) - STATS_REPLY timeout is configurable now thru config.ini of.messageResponseTimer - Same priority messages are in FIFO manner - Fix invalid ChassisID in LLDP packet - Debugging messages - Code style formatting Signed-off-by: Jason Ye --- diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index 5cababb85b..6a7d68c8d0 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -48,6 +48,14 @@ org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml # of.listenPort=6633 # The time (in milliseconds) the controller will wait for a response after sending a Barrier Request or a Statistic Request message (default 2000 msec) # of.messageResponseTimer=2000 +# The switch liveness timeout value (default 60500 msec) +# of.switchLivenessTimeout=60500 +# The maximum number of asynchronous messages can be sent before sending a Barrier Request (default 100) +# of.barrierMessagePriorCount=100 +# The interval which determines how often the discovery packets should be sent (default 300 sec) +# of.discoveryInterval=300 +# The timeout value in waiting for returned discovery packet (default 60 sec) +# of.discoveryTimeout=60 # TLS configuration # To enable TLS, set secureChannelEnabled=true and specify the location of controller Java KeyStore and TrustStore files. diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java index a15c2e5c71..ee46ce2302 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,169 +19,205 @@ import org.openflow.protocol.OFStatisticsRequest; /** * This interface defines an abstraction of an Open Flow Switch. - * + * */ public interface ISwitch { - /** - * Gets a unique XID. - * @return XID - */ - public int getNextXid(); - - /** - * Returns the Switch's ID. - * @return the Switch's ID - */ - public Long getId(); - - /** - * Returns the Switch's table numbers supported by datapath - * @return the tables - */ - public Byte getTables(); - - /** - * Returns the Switch's bitmap of supported ofp_action_type - * @return the actions - */ - public Integer getActions(); - - /** - * Returns the Switch's bitmap of supported ofp_capabilities - * @return the capabilities - */ - public Integer getCapabilities(); - - /** - * Returns the Switch's buffering capacity in Number of Pkts - * @return the buffers - */ - public Integer getBuffers(); - - /** - * Returns the Date when the switch was connected. - * @return Date The date when the switch was connected - */ - public Date getConnectedDate(); - - /** - * This method puts the message in an outgoing priority queue with normal - * priority. It will be served after high priority messages. The method - * should be used for non-critical messages such as statistics request, - * discovery packets, etc. An unique XID is generated automatically and - * inserted into the message. - * - * @param msg The OF message to be sent - * @return The XID used - */ - public Integer asyncSend(OFMessage msg); - - /** - * This method puts the message in an outgoing priority queue with normal - * priority. It will be served after high priority messages. The method - * should be used for non-critical messages such as statistics request, - * discovery packets, etc. The specified XID is inserted into the message. - * - * @param msg The OF message to be Sent - * @param xid The XID to be used in the message - * @return The XID used - */ - public Integer asyncSend(OFMessage msg, int xid); - - /** - * This method puts the message in an outgoing priority queue with high - * priority. It will be served first before normal priority messages. The - * method should be used for critical messages such as hello, echo reply - * etc. An unique XID is generated automatically and inserted into the - * message. - * - * @param msg The OF message to be sent - * @return The XID used - */ - public Integer asyncFastSend(OFMessage msg); - - /** - * This method puts the message in an outgoing priority queue with high - * priority. It will be served first before normal priority messages. The - * method should be used for critical messages such as hello, echo reply - * etc. The specified XID is inserted into the message. - * - * @param msg The OF message to be sent - * @return The XID used - */ - public Integer asyncFastSend(OFMessage msg, int xid); - - /** - * Sends the OF message followed by a Barrier Request with a unique XID which is automatically generated, - * and waits for a result from the switch. - * @param msg The message to be sent - * @return An Object which has one of the followings instances/values: - * Boolean with value true to indicate the message has been successfully processed and acknowledged by the switch; - * Boolean with value false to indicate the message has failed to be processed by the switch within a period of time or - * OFError to indicate that the message has been denied by the switch which responded with OFError. - */ - public Object syncSend(OFMessage msg); - - /** - * Returns a map containing all OFPhysicalPorts of this switch. - * @return The Map of OFPhysicalPort - */ - public Map getPhysicalPorts(); - - /** - * Returns a Set containing all port IDs of this switch. - * @return The Set of port ID - */ - public Set getPorts(); - - /** - * Returns OFPhysicalPort of the specified portNumber of this switch. - * @param portNumber The port ID - * @return OFPhysicalPort for the specified PortNumber - */ - public OFPhysicalPort getPhysicalPort(Short portNumber); - - /** - * Returns the bandwidth of the specified portNumber of this switch. - * @param portNumber the port ID - * @return bandwidth - */ - public Integer getPortBandwidth(Short portNumber); - - /** - * Returns True if the port is enabled, - * @param portNumber - * @return True if the port is enabled - */ - public boolean isPortEnabled(short portNumber); - - /** - * Returns True if the port is enabled. - * @param port - * @return True if the port is enabled - */ - public boolean isPortEnabled(OFPhysicalPort port); - - /** - * Returns a list containing all enabled ports of this switch. - * @return: List containing all enabled ports of this switch - */ - public List getEnabledPorts(); - - /** - * Sends OFStatisticsRequest with a unique XID generated automatically and waits for a result from the switch. - * @param req the OF Statistic Request to be sent - * @return Object has one of the following instances/values:: - * List, a list of statistics records received from the switch as response from the request; - * OFError if the switch failed handle the request or - * NULL if timeout has occurred while waiting for the response. - */ - public Object getStatistics(OFStatisticsRequest req); - - /** - * Returns true if the switch has reached the operational state (has sent FEATURE_REPLY to the controller). - * @return true if the switch is operational - */ - public boolean isOperational(); - + /** + * Gets a unique XID. + * + * @return XID + */ + public int getNextXid(); + + /** + * Returns the Switch's ID. + * + * @return the Switch's ID + */ + public Long getId(); + + /** + * Returns the Switch's table numbers supported by datapath + * + * @return the tables + */ + public Byte getTables(); + + /** + * Returns the Switch's bitmap of supported ofp_action_type + * + * @return the actions + */ + public Integer getActions(); + + /** + * Returns the Switch's bitmap of supported ofp_capabilities + * + * @return the capabilities + */ + public Integer getCapabilities(); + + /** + * Returns the Switch's buffering capacity in Number of Pkts + * + * @return the buffers + */ + public Integer getBuffers(); + + /** + * Returns the Date when the switch was connected. + * + * @return Date The date when the switch was connected + */ + public Date getConnectedDate(); + + /** + * This method puts the message in an outgoing priority queue with normal + * priority. It will be served after high priority messages. The method + * should be used for non-critical messages such as statistics request, + * discovery packets, etc. An unique XID is generated automatically and + * inserted into the message. + * + * @param msg + * The OF message to be sent + * @return The XID used + */ + public Integer asyncSend(OFMessage msg); + + /** + * This method puts the message in an outgoing priority queue with normal + * priority. It will be served after high priority messages. The method + * should be used for non-critical messages such as statistics request, + * discovery packets, etc. The specified XID is inserted into the message. + * + * @param msg + * The OF message to be Sent + * @param xid + * The XID to be used in the message + * @return The XID used + */ + public Integer asyncSend(OFMessage msg, int xid); + + /** + * This method puts the message in an outgoing priority queue with high + * priority. It will be served first before normal priority messages. The + * method should be used for critical messages such as hello, echo reply + * etc. An unique XID is generated automatically and inserted into the + * message. + * + * @param msg + * The OF message to be sent + * @return The XID used + */ + public Integer asyncFastSend(OFMessage msg); + + /** + * This method puts the message in an outgoing priority queue with high + * priority. It will be served first before normal priority messages. The + * method should be used for critical messages such as hello, echo reply + * etc. The specified XID is inserted into the message. + * + * @param msg + * The OF message to be sent + * @return The XID used + */ + public Integer asyncFastSend(OFMessage msg, int xid); + + /** + * Sends the OF message followed by a Barrier Request with a unique XID + * which is automatically generated, and waits for a result from the switch. + * + * @param msg + * The message to be sent + * @return An Object which has one of the followings instances/values: + * Boolean with value true to indicate the message has been + * successfully processed and acknowledged by the switch; Boolean + * with value false to indicate the message has failed to be + * processed by the switch within a period of time or OFError to + * indicate that the message has been denied by the switch which + * responded with OFError. + */ + public Object syncSend(OFMessage msg); + + /** + * Returns a map containing all OFPhysicalPorts of this switch. + * + * @return The Map of OFPhysicalPort + */ + public Map getPhysicalPorts(); + + /** + * Returns a Set containing all port IDs of this switch. + * + * @return The Set of port ID + */ + public Set getPorts(); + + /** + * Returns OFPhysicalPort of the specified portNumber of this switch. + * + * @param portNumber + * The port ID + * @return OFPhysicalPort for the specified PortNumber + */ + public OFPhysicalPort getPhysicalPort(Short portNumber); + + /** + * Returns the bandwidth of the specified portNumber of this switch. + * + * @param portNumber + * the port ID + * @return bandwidth + */ + public Integer getPortBandwidth(Short portNumber); + + /** + * Returns True if the port is enabled, + * + * @param portNumber + * @return True if the port is enabled + */ + public boolean isPortEnabled(short portNumber); + + /** + * Returns True if the port is enabled. + * + * @param port + * @return True if the port is enabled + */ + public boolean isPortEnabled(OFPhysicalPort port); + + /** + * Returns a list containing all enabled ports of this switch. + * + * @return: List containing all enabled ports of this switch + */ + public List getEnabledPorts(); + + /** + * Sends OFStatisticsRequest with a unique XID generated automatically and + * waits for a result from the switch. + * + * @param req + * the OF Statistic Request to be sent + * @return Object has one of the following instances/values:: + * List, a list of statistics records received from + * the switch as response from the request; OFError if the switch + * failed handle the request or NULL if timeout has occurred while + * waiting for the response. + */ + public Object getStatistics(OFStatisticsRequest req); + + /** + * Returns true if the switch has reached the operational state (has sent + * FEATURE_REPLY to the controller). + * + * @return true if the switch is operational + */ + public boolean isOperational(); + + /** + * Sends synchronous Barrier message + */ + public Object sendBarrierMessage(); } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java index 32cdeaa614..9ec5b10ea8 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.protocol_plugin.openflow.core.internal; -import java.io.FileNotFoundException; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; @@ -122,7 +121,6 @@ public class Controller implements IController, CommandProvider { this.switchStateListener = null; this.switchInstanceNumber = new AtomicInteger(0); registerWithOSGIConsole(); - } /** @@ -147,7 +145,7 @@ public class Controller implements IController, CommandProvider { logger.error("Caught exception: " + ex + " during start"); } } - + /** * Function called by the dependency manager before the services * exported by the component are unregistered, this will be @@ -340,24 +338,24 @@ public class Controller implements IController, CommandProvider { } public void _controllerShowConnConfig(CommandInterpreter ci) { - String str = System.getProperty("secureChannelEnabled"); - if ((str != null) && (str.trim().equalsIgnoreCase("true"))) { - ci.print("The Controller and Switch should communicate through TLS connetion.\n"); - - String keyStoreFile = System.getProperty("controllerKeyStore"); - String trustStoreFile = System.getProperty("controllerTrustStore"); - if ((keyStoreFile == null) || keyStoreFile.trim().isEmpty()) { - ci.print("controllerKeyStore not specified in ./configuration/config.ini\n"); - } else { - ci.print("controllerKeyStore=" + keyStoreFile + "\n"); - } - if ((trustStoreFile == null) || trustStoreFile.trim().isEmpty()) { - ci.print("controllerTrustStore not specified in ./configuration/config.ini\n"); - } else { - ci.print("controllerTrustStore=" + trustStoreFile + "\n"); - } + String str = System.getProperty("secureChannelEnabled"); + if ((str != null) && (str.trim().equalsIgnoreCase("true"))) { + ci.print("The Controller and Switch should communicate through TLS connetion.\n"); + + String keyStoreFile = System.getProperty("controllerKeyStore"); + String trustStoreFile = System.getProperty("controllerTrustStore"); + if ((keyStoreFile == null) || keyStoreFile.trim().isEmpty()) { + ci.print("controllerKeyStore not specified in ./configuration/config.ini\n"); + } else { + ci.print("controllerKeyStore=" + keyStoreFile + "\n"); + } + if ((trustStoreFile == null) || trustStoreFile.trim().isEmpty()) { + ci.print("controllerTrustStore not specified in ./configuration/config.ini\n"); + } else { + ci.print("controllerTrustStore=" + trustStoreFile + "\n"); + } } else { - ci.print("The Controller and Switch should communicate through TCP connetion.\n"); + ci.print("The Controller and Switch should communicate through TCP connetion.\n"); } } @@ -371,10 +369,10 @@ public class Controller implements IController, CommandProvider { @Override public String getHelp() { StringBuffer help = new StringBuffer(); - help.append("--Open Flow Controller --\n"); - help.append("\tcontrollerShowSwitches\n"); - help.append("\tcontrollerReset\n"); - help.append("\tcontrollerShowConnConfig\n"); + help.append("-- Open Flow Controller --\n"); + help.append("\t controllerShowSwitches\n"); + help.append("\t controllerReset\n"); + help.append("\t controllerShowConnConfig\n"); return help.toString(); } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/MessageReadWriteService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/MessageReadWriteService.java index 8e611924e4..3dd99e6006 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/MessageReadWriteService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/MessageReadWriteService.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -40,96 +39,98 @@ public class MessageReadWriteService implements IMessageReadWrite { private ByteBuffer outBuffer; private BasicFactory factory; - public MessageReadWriteService(SocketChannel socket, Selector selector) throws ClosedChannelException { - this.socket = socket; - this.selector = selector; - this.factory = new BasicFactory(); - this.inBuffer = ByteBuffer.allocateDirect(bufferSize); - this.outBuffer = ByteBuffer.allocateDirect(bufferSize); - this.clientSelectionKey = this.socket.register(this.selector, - SelectionKey.OP_READ); + public MessageReadWriteService(SocketChannel socket, Selector selector) + throws ClosedChannelException { + this.socket = socket; + this.selector = selector; + this.factory = new BasicFactory(); + this.inBuffer = ByteBuffer.allocateDirect(bufferSize); + this.outBuffer = ByteBuffer.allocateDirect(bufferSize); + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_READ); } - /** - * Sends the OF message out over the socket channel. - * - * @param msg OF message to be sent - * @throws Exception - */ + /** + * Sends the OF message out over the socket channel. + * + * @param msg + * OF message to be sent + * @throws Exception + */ @Override public void asyncSend(OFMessage msg) throws IOException { - synchronized (outBuffer) { - int msgLen = msg.getLengthU(); - if (outBuffer.remaining() < msgLen) { - // increase the buffer size so that it can contain this message - ByteBuffer newBuffer = ByteBuffer.allocateDirect(outBuffer - .capacity() - + msgLen); - outBuffer.flip(); - newBuffer.put(outBuffer); - outBuffer = newBuffer; - } - } - synchronized (outBuffer) { - msg.writeTo(outBuffer); - - if (!socket.isOpen()) { - return; - } - - outBuffer.flip(); - socket.write(outBuffer); - outBuffer.compact(); - if (outBuffer.position() > 0) { - this.clientSelectionKey = this.socket.register( - this.selector, SelectionKey.OP_WRITE, this); - } - logger.trace("Message sent: {}", msg.toString()); - } + synchronized (outBuffer) { + int msgLen = msg.getLengthU(); + if (outBuffer.remaining() < msgLen) { + // increase the buffer size so that it can contain this message + ByteBuffer newBuffer = ByteBuffer.allocateDirect(outBuffer + .capacity() + msgLen); + outBuffer.flip(); + newBuffer.put(outBuffer); + outBuffer = newBuffer; + } + } + synchronized (outBuffer) { + msg.writeTo(outBuffer); + + if (!socket.isOpen()) { + return; + } + + outBuffer.flip(); + socket.write(outBuffer); + outBuffer.compact(); + if (outBuffer.position() > 0) { + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_WRITE, this); + } + logger.trace("Message sent: {}", msg.toString()); + } } - /** - * Resumes sending the remaining messages in the outgoing buffer - * @throws Exception - */ + /** + * Resumes sending the remaining messages in the outgoing buffer + * + * @throws Exception + */ @Override public void resumeSend() throws IOException { - synchronized (outBuffer) { - if (!socket.isOpen()) { - return; - } - - outBuffer.flip(); - socket.write(outBuffer); - outBuffer.compact(); - if (outBuffer.position() > 0) { - this.clientSelectionKey = this.socket.register( - this.selector, SelectionKey.OP_WRITE, this); - } else { - this.clientSelectionKey = this.socket.register( - this.selector, SelectionKey.OP_READ, this); - } + synchronized (outBuffer) { + if (!socket.isOpen()) { + return; + } + + outBuffer.flip(); + socket.write(outBuffer); + outBuffer.compact(); + if (outBuffer.position() > 0) { + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_WRITE, this); + } else { + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_READ, this); + } } } - /** - * Reads the incoming network data from the socket and retrieves the OF - * messages. - * - * @return list of OF messages - * @throws Exception - */ + /** + * Reads the incoming network data from the socket and retrieves the OF + * messages. + * + * @return list of OF messages + * @throws Exception + */ @Override public List readMessages() throws IOException { - if (!socket.isOpen()) { - return null; - } + if (!socket.isOpen()) { + return null; + } - List msgs = null; - int bytesRead = -1; + List msgs = null; + int bytesRead = -1; bytesRead = socket.read(inBuffer); if (bytesRead < 0) { - throw new AsynchronousCloseException(); + throw new AsynchronousCloseException(); } inBuffer.flip(); @@ -142,9 +143,9 @@ public class MessageReadWriteService implements IMessageReadWrite { return msgs; } - @Override - public void stop() { - inBuffer = null; - outBuffer = null; - } + @Override + public void stop() { + inBuffer = null; + outBuffer = null; + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/PriorityMessage.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/PriorityMessage.java index 6bc4f1083b..2f23d36e07 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/PriorityMessage.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/PriorityMessage.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -9,6 +8,8 @@ package org.opendaylight.controller.protocol_plugin.openflow.core.internal; +import java.util.concurrent.atomic.AtomicLong; + import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; @@ -18,31 +19,34 @@ import org.openflow.protocol.OFMessage; * This class describes an OpenFlow message with priority */ class PriorityMessage { - OFMessage msg; - int priority; - - public PriorityMessage(OFMessage msg, int priority) { - this.msg = msg; - this.priority = priority; - } - - public OFMessage getMsg() { - return msg; - } - - public void setMsg(OFMessage msg) { - this.msg = msg; - } - - public int getPriority() { - return priority; - } - - public void setPriority(int priority) { - this.priority = priority; - } - - @Override + OFMessage msg; + int priority; + final static AtomicLong seq = new AtomicLong(); + final long seqNum; + + public PriorityMessage(OFMessage msg, int priority) { + this.msg = msg; + this.priority = priority; + this.seqNum = seq.getAndIncrement(); + } + + public OFMessage getMsg() { + return msg; + } + + public void setMsg(OFMessage msg) { + this.msg = msg; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } @@ -54,6 +58,7 @@ class PriorityMessage { @Override public String toString() { - return "PriorityMessage[" + ReflectionToStringBuilder.toString(this) + "]"; + return "PriorityMessage[" + ReflectionToStringBuilder.toString(this) + + "]"; } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SecureMessageReadWriteService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SecureMessageReadWriteService.java index bb8ba04fb8..27a5cc6906 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SecureMessageReadWriteService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SecureMessageReadWriteService.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -47,64 +46,73 @@ public class SecureMessageReadWriteService implements IMessageReadWrite { private BasicFactory factory; private SSLEngine sslEngine; - private SSLEngineResult sslEngineResult; // results from sslEngine last operation - private ByteBuffer myAppData; // clear text message to be sent - private ByteBuffer myNetData; // encrypted message to be sent - private ByteBuffer peerAppData; // clear text message received from the switch - private ByteBuffer peerNetData; // encrypted message from the switch + private SSLEngineResult sslEngineResult; // results from sslEngine last operation + private ByteBuffer myAppData; // clear text message to be sent + private ByteBuffer myNetData; // encrypted message to be sent + private ByteBuffer peerAppData; // clear text message received from the + // switch + private ByteBuffer peerNetData; // encrypted message from the switch private FileInputStream kfd = null, tfd = null; - public SecureMessageReadWriteService(SocketChannel socket, Selector selector) throws Exception { - this.socket = socket; - this.selector = selector; - this.factory = new BasicFactory(); - - try { - createSecureChannel(socket); - createBuffers(sslEngine); - } catch (Exception e) { - stop(); - throw e; - } + public SecureMessageReadWriteService(SocketChannel socket, Selector selector) + throws Exception { + this.socket = socket; + this.selector = selector; + this.factory = new BasicFactory(); + + try { + createSecureChannel(socket); + createBuffers(sslEngine); + } catch (Exception e) { + stop(); + throw e; + } } - /** - * Bring up secure channel using SSL Engine - * - * @param socket TCP socket channel - * @throws Exception - */ + /** + * Bring up secure channel using SSL Engine + * + * @param socket + * TCP socket channel + * @throws Exception + */ private void createSecureChannel(SocketChannel socket) throws Exception { - String keyStoreFile = System.getProperty("controllerKeyStore"); - String keyStorePassword = System.getProperty("controllerKeyStorePassword"); - String trustStoreFile = System.getProperty("controllerTrustStore"); - String trustStorePassword = System.getProperty("controllerTrustStorePassword"); - - if (keyStoreFile != null) { - keyStoreFile = keyStoreFile.trim(); - } - if ((keyStoreFile == null) || keyStoreFile.isEmpty()) { - throw new FileNotFoundException("controllerKeyStore not specified in ./configuration/config.ini"); - } - if (keyStorePassword != null) { - keyStorePassword = keyStorePassword.trim(); - } - if ((keyStorePassword == null) || keyStorePassword.isEmpty()) { - throw new FileNotFoundException("controllerKeyStorePassword not specified in ./configuration/config.ini"); - } - if (trustStoreFile != null) { - trustStoreFile = trustStoreFile.trim(); - } - if ((trustStoreFile == null) || trustStoreFile.isEmpty()) { - throw new FileNotFoundException("controllerTrustStore not specified in ./configuration/config.ini"); - } - if (trustStorePassword != null) { - trustStorePassword = trustStorePassword.trim(); - } + String keyStoreFile = System.getProperty("controllerKeyStore"); + String keyStorePassword = System + .getProperty("controllerKeyStorePassword"); + String trustStoreFile = System.getProperty("controllerTrustStore"); + String trustStorePassword = System + .getProperty("controllerTrustStorePassword"); + + if (keyStoreFile != null) { + keyStoreFile = keyStoreFile.trim(); + } + if ((keyStoreFile == null) || keyStoreFile.isEmpty()) { + throw new FileNotFoundException( + "controllerKeyStore not specified in ./configuration/config.ini"); + } + if (keyStorePassword != null) { + keyStorePassword = keyStorePassword.trim(); + } + if ((keyStorePassword == null) || keyStorePassword.isEmpty()) { + throw new FileNotFoundException( + "controllerKeyStorePassword not specified in ./configuration/config.ini"); + } + if (trustStoreFile != null) { + trustStoreFile = trustStoreFile.trim(); + } + if ((trustStoreFile == null) || trustStoreFile.isEmpty()) { + throw new FileNotFoundException( + "controllerTrustStore not specified in ./configuration/config.ini"); + } + if (trustStorePassword != null) { + trustStorePassword = trustStorePassword.trim(); + } if ((trustStorePassword == null) || trustStorePassword.isEmpty()) { - throw new FileNotFoundException("controllerTrustStorePassword not specified in ./configuration/config.ini"); - } - + throw new FileNotFoundException( + "controllerTrustStorePassword not specified in ./configuration/config.ini"); + } + KeyStore ks = KeyStore.getInstance("JKS"); KeyStore ts = KeyStore.getInstance("JKS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); @@ -119,285 +127,293 @@ public class SecureMessageReadWriteService implements IMessageReadWrite { SecureRandom random = new SecureRandom(); random.nextInt(); - SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), random); - sslEngine = sslContext.createSSLEngine(); - sslEngine.setUseClientMode(false); - sslEngine.setNeedClientAuth(true); - - // Do initial handshake - doHandshake(socket, sslEngine); - + sslEngine = sslContext.createSSLEngine(); + sslEngine.setUseClientMode(false); + sslEngine.setNeedClientAuth(true); + + // Do initial handshake + doHandshake(socket, sslEngine); + this.clientSelectionKey = this.socket.register(this.selector, SelectionKey.OP_READ); } - /** - * Sends the OF message out over the socket channel. The message is - * encrypted by SSL Engine. - * - * @param msg OF message to be sent - * @throws Exception - */ + /** + * Sends the OF message out over the socket channel. The message is + * encrypted by SSL Engine. + * + * @param msg + * OF message to be sent + * @throws Exception + */ @Override public void asyncSend(OFMessage msg) throws Exception { - synchronized (myAppData) { - int msgLen = msg.getLengthU(); - if (myAppData.remaining() < msgLen) { - // increase the buffer size so that it can contain this message - ByteBuffer newBuffer = ByteBuffer.allocateDirect(myAppData - .capacity() - + msgLen); - myAppData.flip(); - newBuffer.put(myAppData); - myAppData = newBuffer; - } - } - synchronized (myAppData) { - msg.writeTo(myAppData); - myAppData.flip(); - sslEngineResult = sslEngine.wrap(myAppData, myNetData); - logger.trace("asyncSend sslEngine wrap: {}", sslEngineResult); - runDelegatedTasks(sslEngineResult, sslEngine); - - if (!socket.isOpen()) { - return; - } - - myNetData.flip(); - socket.write(myNetData); - if (myNetData.hasRemaining()) { - myNetData.compact(); - } else { - myNetData.clear(); - } - - if (myAppData.hasRemaining()) { - myAppData.compact(); - this.clientSelectionKey = this.socket.register( - this.selector, SelectionKey.OP_WRITE, this); - } else { - myAppData.clear(); - this.clientSelectionKey = this.socket.register( - this.selector, SelectionKey.OP_READ, this); - } - - logger.trace("Message sent: {}", msg.toString()); - } + synchronized (myAppData) { + int msgLen = msg.getLengthU(); + if (myAppData.remaining() < msgLen) { + // increase the buffer size so that it can contain this message + ByteBuffer newBuffer = ByteBuffer.allocateDirect(myAppData + .capacity() + msgLen); + myAppData.flip(); + newBuffer.put(myAppData); + myAppData = newBuffer; + } + } + synchronized (myAppData) { + msg.writeTo(myAppData); + myAppData.flip(); + sslEngineResult = sslEngine.wrap(myAppData, myNetData); + logger.trace("asyncSend sslEngine wrap: {}", sslEngineResult); + runDelegatedTasks(sslEngineResult, sslEngine); + + if (!socket.isOpen()) { + return; + } + + myNetData.flip(); + socket.write(myNetData); + if (myNetData.hasRemaining()) { + myNetData.compact(); + } else { + myNetData.clear(); + } + + if (myAppData.hasRemaining()) { + myAppData.compact(); + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_WRITE, this); + } else { + myAppData.clear(); + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_READ, this); + } + + logger.trace("Message sent: {}", msg.toString()); + } } - /** - * Resumes sending the remaining messages in the outgoing buffer - * @throws Exception - */ + /** + * Resumes sending the remaining messages in the outgoing buffer + * + * @throws Exception + */ @Override public void resumeSend() throws Exception { - synchronized (myAppData) { - myAppData.flip(); - sslEngineResult = sslEngine.wrap(myAppData, myNetData); - logger.trace("resumeSend sslEngine wrap: {}", sslEngineResult); - runDelegatedTasks(sslEngineResult, sslEngine); - - if (!socket.isOpen()) { - return; - } - - myNetData.flip(); - socket.write(myNetData); - if (myNetData.hasRemaining()) { - myNetData.compact(); - } else { - myNetData.clear(); - } - - if (myAppData.hasRemaining()) { - myAppData.compact(); - this.clientSelectionKey = this.socket.register(this.selector, - SelectionKey.OP_WRITE, this); - } else { - myAppData.clear(); - this.clientSelectionKey = this.socket.register(this.selector, - SelectionKey.OP_READ, this); - } - } + synchronized (myAppData) { + myAppData.flip(); + sslEngineResult = sslEngine.wrap(myAppData, myNetData); + logger.trace("resumeSend sslEngine wrap: {}", sslEngineResult); + runDelegatedTasks(sslEngineResult, sslEngine); + + if (!socket.isOpen()) { + return; + } + + myNetData.flip(); + socket.write(myNetData); + if (myNetData.hasRemaining()) { + myNetData.compact(); + } else { + myNetData.clear(); + } + + if (myAppData.hasRemaining()) { + myAppData.compact(); + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_WRITE, this); + } else { + myAppData.clear(); + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_READ, this); + } + } } - /** - * Reads the incoming network data from the socket, decryptes them and then - * retrieves the OF messages. - * - * @return list of OF messages - * @throws Exception - */ + /** + * Reads the incoming network data from the socket, decryptes them and then + * retrieves the OF messages. + * + * @return list of OF messages + * @throws Exception + */ @Override public List readMessages() throws Exception { - if (!socket.isOpen()) { - return null; - } + if (!socket.isOpen()) { + return null; + } - List msgs = null; + List msgs = null; int bytesRead = -1; - int countDown = 50; - - bytesRead = socket.read(peerNetData); - if (bytesRead < 0) { - logger.debug("Message read operation failed"); - throw new AsynchronousCloseException(); - } - - do { - peerNetData.flip(); - sslEngineResult = sslEngine.unwrap(peerNetData, peerAppData); - if (peerNetData.hasRemaining()) { - peerNetData.compact(); - } else { - peerNetData.clear(); - } - logger.trace("sslEngine unwrap result: {}", sslEngineResult); - runDelegatedTasks(sslEngineResult, sslEngine); - } while ((sslEngineResult.getStatus() == SSLEngineResult.Status.OK) && - peerNetData.hasRemaining() && (--countDown > 0)); - - if (countDown == 0) { - logger.trace("countDown reaches 0. peerNetData pos {} lim {}", peerNetData.position(), peerNetData.limit()); - } - - peerAppData.flip(); - msgs = factory.parseMessages(peerAppData); - if (peerAppData.hasRemaining()) { - peerAppData.compact(); - } else { - peerAppData.clear(); - } - - this.clientSelectionKey = this.socket.register( - this.selector, SelectionKey.OP_READ, this); - + int countDown = 50; + + bytesRead = socket.read(peerNetData); + if (bytesRead < 0) { + logger.debug("Message read operation failed"); + throw new AsynchronousCloseException(); + } + + do { + peerNetData.flip(); + sslEngineResult = sslEngine.unwrap(peerNetData, peerAppData); + if (peerNetData.hasRemaining()) { + peerNetData.compact(); + } else { + peerNetData.clear(); + } + logger.trace("sslEngine unwrap result: {}", sslEngineResult); + runDelegatedTasks(sslEngineResult, sslEngine); + } while ((sslEngineResult.getStatus() == SSLEngineResult.Status.OK) + && peerNetData.hasRemaining() && (--countDown > 0)); + + if (countDown == 0) { + logger.trace("countDown reaches 0. peerNetData pos {} lim {}", + peerNetData.position(), peerNetData.limit()); + } + + peerAppData.flip(); + msgs = factory.parseMessages(peerAppData); + if (peerAppData.hasRemaining()) { + peerAppData.compact(); + } else { + peerAppData.clear(); + } + + this.clientSelectionKey = this.socket.register(this.selector, + SelectionKey.OP_READ, this); + return msgs; } /** - * If the result indicates that we have outstanding tasks to do, - * go ahead and run them in this thread. + * If the result indicates that we have outstanding tasks to do, go ahead + * and run them in this thread. */ - private void runDelegatedTasks(SSLEngineResult result, - SSLEngine engine) throws Exception { - - if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { - Runnable runnable; - while ((runnable = engine.getDelegatedTask()) != null) { - logger.debug("\trunning delegated task..."); - runnable.run(); - } - HandshakeStatus hsStatus = engine.getHandshakeStatus(); - if (hsStatus == HandshakeStatus.NEED_TASK) { - throw new Exception( - "handshake shouldn't need additional tasks"); - } - logger.debug("\tnew HandshakeStatus: {}", hsStatus); - } + private void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) + throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + logger.debug("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception("handshake shouldn't need additional tasks"); + } + logger.debug("\tnew HandshakeStatus: {}", hsStatus); + } } - private void doHandshake(SocketChannel socket, SSLEngine engine) throws Exception { - SSLSession session = engine.getSession(); - ByteBuffer myAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); - ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); - ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize()); - ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize()); - - // Begin handshake - engine.beginHandshake(); - SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); - - // Process handshaking message - while (hs != SSLEngineResult.HandshakeStatus.FINISHED && - hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { - switch (hs) { - case NEED_UNWRAP: - // Receive handshaking data from peer - if (socket.read(peerNetData) < 0) { - throw new AsynchronousCloseException(); - } - - // Process incoming handshaking data - peerNetData.flip(); - SSLEngineResult res = engine.unwrap(peerNetData, peerAppData); - peerNetData.compact(); - hs = res.getHandshakeStatus(); - - // Check status - switch (res.getStatus()) { - case OK : - // Handle OK status - break; - } - break; - - case NEED_WRAP : - // Empty the local network packet buffer. - myNetData.clear(); - - // Generate handshaking data - res = engine.wrap(myAppData, myNetData); - hs = res.getHandshakeStatus(); - - // Check status - switch (res.getStatus()) { - case OK : - myNetData.flip(); - - // Send the handshaking data to peer - while (myNetData.hasRemaining()) { - if (socket.write(myNetData) < 0) { - throw new AsynchronousCloseException(); - } - } - break; - } - break; - - case NEED_TASK : - // Handle blocking tasks - Runnable runnable; - while ((runnable = engine.getDelegatedTask()) != null) { - logger.debug("\trunning delegated task..."); - runnable.run(); - } - hs = engine.getHandshakeStatus(); - if (hs == HandshakeStatus.NEED_TASK) { - throw new Exception( - "handshake shouldn't need additional tasks"); - } - logger.debug("\tnew HandshakeStatus: {}", hs); - break; - } - } + private void doHandshake(SocketChannel socket, SSLEngine engine) + throws Exception { + SSLSession session = engine.getSession(); + ByteBuffer myAppData = ByteBuffer.allocate(session + .getApplicationBufferSize()); + ByteBuffer peerAppData = ByteBuffer.allocate(session + .getApplicationBufferSize()); + ByteBuffer myNetData = ByteBuffer.allocate(session + .getPacketBufferSize()); + ByteBuffer peerNetData = ByteBuffer.allocate(session + .getPacketBufferSize()); + + // Begin handshake + engine.beginHandshake(); + SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); + + // Process handshaking message + while (hs != SSLEngineResult.HandshakeStatus.FINISHED + && hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { + switch (hs) { + case NEED_UNWRAP: + // Receive handshaking data from peer + if (socket.read(peerNetData) < 0) { + throw new AsynchronousCloseException(); + } + + // Process incoming handshaking data + peerNetData.flip(); + SSLEngineResult res = engine.unwrap(peerNetData, peerAppData); + peerNetData.compact(); + hs = res.getHandshakeStatus(); + + // Check status + switch (res.getStatus()) { + case OK: + // Handle OK status + break; + } + break; + + case NEED_WRAP: + // Empty the local network packet buffer. + myNetData.clear(); + + // Generate handshaking data + res = engine.wrap(myAppData, myNetData); + hs = res.getHandshakeStatus(); + + // Check status + switch (res.getStatus()) { + case OK: + myNetData.flip(); + + // Send the handshaking data to peer + while (myNetData.hasRemaining()) { + if (socket.write(myNetData) < 0) { + throw new AsynchronousCloseException(); + } + } + break; + } + break; + + case NEED_TASK: + // Handle blocking tasks + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + logger.debug("\trunning delegated task..."); + runnable.run(); + } + hs = engine.getHandshakeStatus(); + if (hs == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + logger.debug("\tnew HandshakeStatus: {}", hs); + break; + } + } } - + private void createBuffers(SSLEngine engine) { - SSLSession session = engine.getSession(); - this.myAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); - this.peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); - this.myNetData = ByteBuffer.allocate(session.getPacketBufferSize()); - this.peerNetData = ByteBuffer.allocate(session.getPacketBufferSize()); + SSLSession session = engine.getSession(); + this.myAppData = ByteBuffer + .allocate(session.getApplicationBufferSize()); + this.peerAppData = ByteBuffer.allocate(session + .getApplicationBufferSize()); + this.myNetData = ByteBuffer.allocate(session.getPacketBufferSize()); + this.peerNetData = ByteBuffer.allocate(session.getPacketBufferSize()); } - @Override - public void stop() throws IOException { - this.sslEngine = null; - this.sslEngineResult = null; - this.myAppData = null; - this.myNetData = null; - this.peerAppData = null; - this.peerNetData = null; - - if (this.kfd != null) { - this.kfd.close(); - this.kfd = null; - } - if (this.tfd != null) { - this.tfd.close(); - this.tfd = null; - } - } + @Override + public void stop() throws IOException { + this.sslEngine = null; + this.sslEngineResult = null; + this.myAppData = null; + this.myNetData = null; + this.peerAppData = null; + this.peerNetData = null; + + if (this.kfd != null) { + this.kfd.close(); + this.kfd = null; + } + if (this.tfd != null) { + this.tfd.close(); + this.tfd = null; + } + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java index 5913ad0dd9..bbf3e91462 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -9,6 +8,7 @@ package org.opendaylight.controller.protocol_plugin.openflow.core.internal; +import java.io.IOException; import java.net.SocketException; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.SelectionKey; @@ -38,6 +38,7 @@ import org.opendaylight.controller.protocol_plugin.openflow.core.IController; import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch; import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageReadWrite; import org.openflow.protocol.OFBarrierReply; +import org.openflow.protocol.OFBarrierRequest; import org.openflow.protocol.OFEchoReply; import org.openflow.protocol.OFError; import org.openflow.protocol.OFFeaturesReply; @@ -65,7 +66,7 @@ public class SwitchHandler implements ISwitch { private static final Logger logger = LoggerFactory .getLogger(SwitchHandler.class); private static final int SWITCH_LIVENESS_TIMER = 5000; - private static final int SWITCH_LIVENESS_TIMEOUT = 2 * SWITCH_LIVENESS_TIMER + 500; + private static final int switchLivenessTimeout = getSwitchLivenessTimeout(); private int MESSAGE_RESPONSE_TIMER = 2000; private String instanceName; @@ -93,9 +94,9 @@ public class SwitchHandler implements ISwitch { private IMessageReadWrite msgReadWriteService; private Thread switchHandlerThread; private Integer responseTimerValue; - private PriorityBlockingQueue transmitQ; + private PriorityBlockingQueue transmitQ; private Thread transmitThread; - + private enum SwitchState { NON_OPERATIONAL(0), WAIT_FEATURES_REPLY(1), WAIT_CONFIG_REPLY(2), OPERATIONAL( 3); @@ -116,10 +117,10 @@ public class SwitchHandler implements ISwitch { this.instanceName = name; this.thisISwitch = this; this.sid = (long) 0; - this.buffers = (int)0; - this.capabilities = (int)0; - this.tables = (byte)0; - this.actions = (int)0; + this.buffers = (int) 0; + this.capabilities = (int) 0; + this.tables = (byte) 0; + this.actions = (int) 0; this.core = core; this.socket = sc; this.factory = new BasicFactory(); @@ -136,20 +137,21 @@ public class SwitchHandler implements ISwitch { this.responseTimerValue = MESSAGE_RESPONSE_TIMER; String rTimer = System.getProperty("of.messageResponseTimer"); if (rTimer != null) { - try { - responseTimerValue = Integer.decode(rTimer); - } catch (NumberFormatException e) { - logger.warn("Invalid of.messageResponseTimer: {} use default({})", - rTimer, MESSAGE_RESPONSE_TIMER); - } + try { + responseTimerValue = Integer.decode(rTimer); + } catch (NumberFormatException e) { + logger.warn( + "Invalid of.messageResponseTimer: {} use default({})", + rTimer, MESSAGE_RESPONSE_TIMER); + } } - } + } public void start() { try { - startTransmitThread(); - setupCommChannel(); - sendFirstHello(); + startTransmitThread(); + setupCommChannel(); + sendFirstHello(); startHandlerThread(); } catch (Exception e) { reportError(e); @@ -163,7 +165,7 @@ public class SwitchHandler implements ISwitch { running = true; while (running) { try { - // wait for an incoming connection + // wait for an incoming connection selector.select(0); Iterator selectedKeys = selector .selectedKeys().iterator(); @@ -178,7 +180,7 @@ public class SwitchHandler implements ISwitch { } } } catch (Exception e) { - reportError(e); + reportError(e); } } } @@ -187,33 +189,32 @@ public class SwitchHandler implements ISwitch { } public void stop() { - running = false; - cancelSwitchTimer(); - try { - selector.wakeup(); - selector.close(); - } catch (Exception e) { - } - try { - socket.close(); - } catch (Exception e) { - } - try { - msgReadWriteService.stop(); - } catch (Exception e) { - } - executor.shutdown(); - - selector = null; - socket = null; - msgReadWriteService = null; - - if (switchHandlerThread != null) { - switchHandlerThread.interrupt(); - } - if (transmitThread != null) { - transmitThread.interrupt(); - } + running = false; + cancelSwitchTimer(); + try { + selector.wakeup(); + selector.close(); + } catch (Exception e) { + } + try { + socket.close(); + } catch (Exception e) { + } + try { + msgReadWriteService.stop(); + } catch (Exception e) { + } + executor.shutdown(); + + selector = null; + msgReadWriteService = null; + + if (switchHandlerThread != null) { + switchHandlerThread.interrupt(); + } + if (transmitThread != null) { + transmitThread.interrupt(); + } } @Override @@ -221,92 +222,132 @@ public class SwitchHandler implements ISwitch { return this.xid.incrementAndGet(); } - /** - * This method puts the message in an outgoing priority queue with normal - * priority. It will be served after high priority messages. The method - * should be used for non-critical messages such as statistics request, - * discovery packets, etc. An unique XID is generated automatically and - * inserted into the message. - * - * @param msg The OF message to be sent - * @return The XID used - */ + /** + * This method puts the message in an outgoing priority queue with normal + * priority. It will be served after high priority messages. The method + * should be used for non-critical messages such as statistics request, + * discovery packets, etc. An unique XID is generated automatically and + * inserted into the message. + * + * @param msg + * The OF message to be sent + * @return The XID used + */ @Override public Integer asyncSend(OFMessage msg) { - return asyncSend(msg, getNextXid()); - } - - /** - * This method puts the message in an outgoing priority queue with normal - * priority. It will be served after high priority messages. The method - * should be used for non-critical messages such as statistics request, - * discovery packets, etc. The specified XID is inserted into the message. - * - * @param msg The OF message to be Sent - * @param xid The XID to be used in the message - * @return The XID used - */ + return asyncSend(msg, getNextXid()); + } + + private Object syncSend(OFMessage msg, int xid) { + SynchronousMessage worker = new SynchronousMessage(this, xid, msg); + messageWaitingDone.put(xid, worker); + Object result = null; + Boolean status = false; + Future submit = executor.submit(worker); + try { + result = submit.get(responseTimerValue, TimeUnit.MILLISECONDS); + messageWaitingDone.remove(xid); + if (result == null) { + // if result is null, then it means the switch can handle this + // message successfully + // convert the result into a Boolean with value true + status = true; + // logger.debug("Successfully send " + + // msg.getType().toString()); + result = status; + } else { + // if result is not null, this means the switch can't handle + // this message + // the result if OFError already + logger.debug("Send {} failed --> {}", msg.getType().toString(), + ((OFError) result).toString()); + } + return result; + } catch (Exception e) { + logger.warn("Timeout while waiting for {} reply", msg.getType() + .toString()); + // convert the result into a Boolean with value false + status = false; + result = status; + return result; + } + } + + /** + * This method puts the message in an outgoing priority queue with normal + * priority. It will be served after high priority messages. The method + * should be used for non-critical messages such as statistics request, + * discovery packets, etc. The specified XID is inserted into the message. + * + * @param msg + * The OF message to be Sent + * @param xid + * The XID to be used in the message + * @return The XID used + */ @Override public Integer asyncSend(OFMessage msg, int xid) { - msg.setXid(xid); - if (transmitQ != null) { - transmitQ.add(new PriorityMessage(msg, 0)); - } + msg.setXid(xid); + if (transmitQ != null) { + transmitQ.add(new PriorityMessage(msg, 0)); + } return xid; } - /** - * This method puts the message in an outgoing priority queue with high - * priority. It will be served first before normal priority messages. The - * method should be used for critical messages such as hello, echo reply - * etc. An unique XID is generated automatically and inserted into the - * message. - * - * @param msg The OF message to be sent - * @return The XID used - */ + /** + * This method puts the message in an outgoing priority queue with high + * priority. It will be served first before normal priority messages. The + * method should be used for critical messages such as hello, echo reply + * etc. An unique XID is generated automatically and inserted into the + * message. + * + * @param msg + * The OF message to be sent + * @return The XID used + */ @Override public Integer asyncFastSend(OFMessage msg) { - return asyncFastSend(msg, getNextXid()); - } - - /** - * This method puts the message in an outgoing priority queue with high - * priority. It will be served first before normal priority messages. The - * method should be used for critical messages such as hello, echo reply - * etc. The specified XID is inserted into the message. - * - * @param msg The OF message to be sent - * @return The XID used - */ + return asyncFastSend(msg, getNextXid()); + } + + /** + * This method puts the message in an outgoing priority queue with high + * priority. It will be served first before normal priority messages. The + * method should be used for critical messages such as hello, echo reply + * etc. The specified XID is inserted into the message. + * + * @param msg + * The OF message to be sent + * @return The XID used + */ @Override public Integer asyncFastSend(OFMessage msg, int xid) { - msg.setXid(xid); - if (transmitQ != null) { - transmitQ.add(new PriorityMessage(msg, 1)); - } + msg.setXid(xid); + if (transmitQ != null) { + transmitQ.add(new PriorityMessage(msg, 1)); + } return xid; } - public void resumeSend() { + public void resumeSend() { try { - if (msgReadWriteService != null) { - msgReadWriteService.resumeSend(); - } - } catch (Exception e) { - reportError(e); - } + if (msgReadWriteService != null) { + msgReadWriteService.resumeSend(); + } + } catch (Exception e) { + reportError(e); + } } public void handleMessages() { List msgs = null; - + try { - msgs = msgReadWriteService.readMessages(); - } catch (Exception e) { - reportError(e); - } - + msgs = msgReadWriteService.readMessages(); + } catch (Exception e) { + reportError(e); + } + if (msgs == null) { logger.debug("{} is down", toString()); // the connection is down, inform core @@ -316,10 +357,9 @@ public class SwitchHandler implements ISwitch { for (OFMessage msg : msgs) { logger.trace("Message received: {}", msg.toString()); /* - if ((msg.getType() != OFType.ECHO_REQUEST) && - (msg.getType() != OFType.ECHO_REPLY)) { - logger.debug(msg.getType().toString() + " received from sw " + toString()); - } + * if ((msg.getType() != OFType.ECHO_REQUEST) && (msg.getType() != + * OFType.ECHO_REPLY)) { logger.debug(msg.getType().toString() + + * " received from sw " + toString()); } */ this.lastMsgReceivedTimeStamp = System.currentTimeMillis(); OFType type = msg.getType(); @@ -334,8 +374,8 @@ public class SwitchHandler implements ISwitch { OFFlowMod flowMod = (OFFlowMod) factory .getMessage(OFType.FLOW_MOD); flowMod.setMatch(match).setCommand(OFFlowMod.OFPFC_DELETE) - .setOutPort(OFPort.OFPP_NONE).setLength( - (short) OFFlowMod.MINIMUM_LENGTH); + .setOutPort(OFPort.OFPP_NONE) + .setLength((short) OFFlowMod.MINIMUM_LENGTH); asyncFastSend(flowMod); this.state = SwitchState.WAIT_FEATURES_REPLY; startSwitchTimer(); @@ -352,7 +392,8 @@ public class SwitchHandler implements ISwitch { processFeaturesReply((OFFeaturesReply) msg); break; case GET_CONFIG_REPLY: - // make sure that the switch can send the whole packet to the controller + // make sure that the switch can send the whole packet to the + // controller if (((OFGetConfigReply) msg).getMissSendLength() == (short) 0xffff) { this.state = SwitchState.OPERATIONAL; } @@ -381,18 +422,21 @@ public class SwitchHandler implements ISwitch { } private void processPortStatusMsg(OFPortStatus msg) { - //short portNumber = msg.getDesc().getPortNumber(); + // short portNumber = msg.getDesc().getPortNumber(); OFPhysicalPort port = msg.getDesc(); if (msg.getReason() == (byte) OFPortReason.OFPPR_MODIFY.ordinal()) { updatePhysicalPort(port); - //logger.debug("Port " + portNumber + " on " + toString() + " modified"); + // logger.debug("Port " + portNumber + " on " + toString() + + // " modified"); } else if (msg.getReason() == (byte) OFPortReason.OFPPR_ADD.ordinal()) { updatePhysicalPort(port); - //logger.debug("Port " + portNumber + " on " + toString() + " added"); + // logger.debug("Port " + portNumber + " on " + toString() + + // " added"); } else if (msg.getReason() == (byte) OFPortReason.OFPPR_DELETE .ordinal()) { deletePhysicalPort(port); - //logger.debug("Port " + portNumber + " on " + toString() + " deleted"); + // logger.debug("Port " + portNumber + " on " + toString() + + // " deleted"); } } @@ -404,14 +448,17 @@ public class SwitchHandler implements ISwitch { public void run() { try { Long now = System.currentTimeMillis(); - if ((now - lastMsgReceivedTimeStamp) > SWITCH_LIVENESS_TIMEOUT) { + if ((now - lastMsgReceivedTimeStamp) > switchLivenessTimeout) { if (probeSent) { - // switch failed to respond to our probe, consider it down - logger.warn("{} is idle for too long, disconnect", toString()); + // switch failed to respond to our probe, consider + // it down + logger.warn("{} is idle for too long, disconnect", + toString()); reportSwitchStateChange(false); } else { // send a probe to see if the switch is still alive - //logger.debug("Send idle probe (Echo Request) to " + switchName()); + // logger.debug("Send idle probe (Echo Request) to " + // + switchName()); probeSent = true; OFMessage echo = factory .getMessage(OFType.ECHO_REQUEST); @@ -425,7 +472,7 @@ public class SwitchHandler implements ISwitch { asyncFastSend(request); } else { if (state == SwitchState.WAIT_CONFIG_REPLY) { - // send another config request + // send another config request OFSetConfig config = (OFSetConfig) factory .getMessage(OFType.SET_CONFIG); config.setMissSendLength((short) 0xffff) @@ -451,13 +498,14 @@ public class SwitchHandler implements ISwitch { } private void reportError(Exception e) { - if (e instanceof AsynchronousCloseException || - e instanceof InterruptedException || - e instanceof SocketException) { - logger.debug("Caught exception {}", e.getMessage()); - } else { - logger.warn("Caught exception {}", e.getMessage()); - } + if (e instanceof AsynchronousCloseException + || e instanceof InterruptedException + || e instanceof SocketException + || e instanceof IOException) { + logger.debug("Caught exception {}", e.getMessage()); + } else { + logger.warn("Caught exception ", e); + } // notify core of this error event and disconnect the switch ((Controller) core).takeSwitchEventError(this); } @@ -492,7 +540,8 @@ public class SwitchHandler implements ISwitch { config.setMissSendLength((short) 0xffff).setLengthU( OFSetConfig.MINIMUM_LENGTH); asyncFastSend(config); - // send config request to make sure the switch can handle the set config + // send config request to make sure the switch can handle the set + // config OFMessage getConfig = factory.getMessage(OFType.GET_CONFIG_REQUEST); asyncFastSend(getConfig); this.state = SwitchState.WAIT_CONFIG_REPLY; @@ -505,8 +554,7 @@ public class SwitchHandler implements ISwitch { Short portNumber = port.getPortNumber(); physicalPorts.put(portNumber, port); portBandwidth - .put( - portNumber, + .put(portNumber, port.getCurrentFeatures() & (OFPortFeatures.OFPPF_10MB_FD.getValue() | OFPortFeatures.OFPPF_10MB_HD @@ -559,8 +607,7 @@ public class SwitchHandler implements ISwitch { Future submit = executor.submit(worker); Object result = null; try { - result = submit - .get(MESSAGE_RESPONSE_TIMER, TimeUnit.MILLISECONDS); + result = submit.get(responseTimerValue, TimeUnit.MILLISECONDS); return result; } catch (Exception e) { logger.warn("Timeout while waiting for {} replies", req.getType()); @@ -571,41 +618,13 @@ public class SwitchHandler implements ISwitch { @Override public Object syncSend(OFMessage msg) { - Integer xid = getNextXid(); - SynchronousMessage worker = new SynchronousMessage(this, xid, msg); - messageWaitingDone.put(xid, worker); - Object result = null; - Boolean status = false; - Future submit = executor.submit(worker); - try { - result = submit - .get(responseTimerValue, TimeUnit.MILLISECONDS); - messageWaitingDone.remove(xid); - if (result == null) { - // if result is null, then it means the switch can handle this message successfully - // convert the result into a Boolean with value true - status = true; - //logger.debug("Successfully send " + msg.getType().toString()); - result = status; - } else { - // if result is not null, this means the switch can't handle this message - // the result if OFError already - logger.debug("Send {} failed --> {}", - msg.getType().toString(), ((OFError) result).toString()); - } - return result; - } catch (Exception e) { - logger.warn("Timeout while waiting for {} reply", msg.getType().toString()); - // convert the result into a Boolean with value false - status = false; - result = status; - return result; - } + int xid = getNextXid(); + return syncSend(msg, xid); } /* - * Either a BarrierReply or a OFError is received. If this is a reply for an outstanding sync message, - * wake up associated task so that it can continue + * Either a BarrierReply or a OFError is received. If this is a reply for an + * outstanding sync message, wake up associated task so that it can continue */ private void processBarrierReply(OFBarrierReply msg) { Integer xid = msg.getXid(); @@ -626,7 +645,8 @@ public class SwitchHandler implements ISwitch { xid = errorMsg.getXid(); } /* - * the error can be a reply to a synchronous message or to a statistic request message + * the error can be a reply to a synchronous message or to a statistic + * request message */ Callable worker = messageWaitingDone.remove(xid); if (worker == null) { @@ -653,7 +673,7 @@ public class SwitchHandler implements ISwitch { worker.wakeup(); } } - + @Override public Map getPhysicalPorts() { return this.physicalPorts; @@ -678,12 +698,12 @@ public class SwitchHandler implements ISwitch { public Byte getTables() { return this.tables; } - + @Override public Integer getActions() { return this.actions; } - + @Override public Integer getCapabilities() { return this.capabilities; @@ -732,68 +752,103 @@ public class SwitchHandler implements ISwitch { return result; } - /* - * Transmit thread polls the message out of the priority queue and invokes - * messaging service to transmit it over the socket channel - */ + /* + * Transmit thread polls the message out of the priority queue and invokes + * messaging service to transmit it over the socket channel + */ class PriorityMessageTransmit implements Runnable { public void run() { running = true; while (running) { - try { - if (!transmitQ.isEmpty()) { - PriorityMessage pmsg = transmitQ.poll(); - msgReadWriteService.asyncSend(pmsg.msg); - logger.trace("Message sent: {}", pmsg.toString()); - } - Thread.sleep(10); - } catch (InterruptedException ie) { - reportError(new InterruptedException("PriorityMessageTransmit thread interrupted")); - } catch (Exception e) { - reportError(e); - } + try { + if (!transmitQ.isEmpty()) { + PriorityMessage pmsg = transmitQ.poll(); + msgReadWriteService.asyncSend(pmsg.msg); + logger.trace("Message sent: {}", pmsg.toString()); + } + Thread.sleep(10); + } catch (InterruptedException ie) { + reportError(new InterruptedException( + "PriorityMessageTransmit thread interrupted")); + } catch (Exception e) { + reportError(e); + } } - transmitQ = null; + transmitQ = null; } } /* * Setup and start the transmit thread */ - private void startTransmitThread() { - this.transmitQ = new PriorityBlockingQueue(11, - new Comparator() { - public int compare(PriorityMessage p1, PriorityMessage p2) { - return p2.priority - p1.priority; - } - }); + private void startTransmitThread() { + this.transmitQ = new PriorityBlockingQueue(11, + new Comparator() { + public int compare(PriorityMessage p1, PriorityMessage p2) { + if (p2.priority != p1.priority) { + return p2.priority - p1.priority; + } else { + return (p2.seqNum < p1.seqNum) ? 1 : -1; + } + } + }); this.transmitThread = new Thread(new PriorityMessageTransmit()); this.transmitThread.start(); } - + /* * Setup communication services */ private void setupCommChannel() throws Exception { this.selector = SelectorProvider.provider().openSelector(); this.socket.configureBlocking(false); - this.socket.socket().setTcpNoDelay(true); + this.socket.socket().setTcpNoDelay(true); this.msgReadWriteService = getMessageReadWriteService(); } private void sendFirstHello() { - try { - OFMessage msg = factory.getMessage(OFType.HELLO); - asyncFastSend(msg); - } catch (Exception e) { - reportError(e); - } + try { + OFMessage msg = factory.getMessage(OFType.HELLO); + asyncFastSend(msg); + } catch (Exception e) { + reportError(e); + } } - + private IMessageReadWrite getMessageReadWriteService() throws Exception { - String str = System.getProperty("secureChannelEnabled"); - return ((str != null) && (str.trim().equalsIgnoreCase("true"))) ? - new SecureMessageReadWriteService(socket, selector) : - new MessageReadWriteService(socket, selector); + String str = System.getProperty("secureChannelEnabled"); + return ((str != null) && (str.trim().equalsIgnoreCase("true"))) ? new SecureMessageReadWriteService( + socket, selector) : new MessageReadWriteService(socket, + selector); + } + + /** + * Sends synchronous Barrier message + */ + @Override + public Object sendBarrierMessage() { + OFBarrierRequest barrierMsg = new OFBarrierRequest(); + return syncSend(barrierMsg); + } + + /** + * This method returns the switch liveness timeout value. If controller did + * not receive any message from the switch for such a long period, + * controller will tear down the connection to the switch. + * + * @return The timeout value + */ + private static int getSwitchLivenessTimeout() { + String timeout = System.getProperty("of.switchLivenessTimeout"); + int rv = 60500; + + try { + if (timeout != null) { + rv = Integer.parseInt(timeout); + } + } catch (Exception e) { + } + + return rv; } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SynchronousMessage.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SynchronousMessage.java index 5e613e8642..4737d4cea9 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SynchronousMessage.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SynchronousMessage.java @@ -46,8 +46,10 @@ public class SynchronousMessage implements Callable { @Override public Object call() throws Exception { sw.asyncSend(syncMsg, xid); - OFBarrierRequest barrierMsg = new OFBarrierRequest(); - sw.asyncSend(barrierMsg, xid); + if (!(syncMsg instanceof OFBarrierRequest)) { + OFBarrierRequest barrierMsg = new OFBarrierRequest(); + sw.asyncSend(barrierMsg, xid); + } latch.await(); return result; } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java index 26471a7f75..9bccbd1d68 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java @@ -238,7 +238,9 @@ public class Activator extends ComponentActivatorAbstractBase { new String[] { IPluginInFlowProgrammerService.class.getName(), IMessageListener.class.getName(), - IContainerListener.class.getName() }, props); + IContainerListener.class.getName(), + IInventoryShimExternalListener.class.getName() }, + props); c.add(createServiceDependency() .setService(IController.class, "(name=Controller)") diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java index eab87a4440..5775895664 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java @@ -85,11 +85,11 @@ public class DiscoveryService implements IInventoryShimExternalListener, private long discoveryTimerTick = 1L * 1000; // per tick in msec private int discoveryTimerTickCount = 0; // main tick counter private int discoveryBatchMaxPorts = 500; // max # of ports handled in one batch - private int discoveryBatchRestartTicks = 30; // periodically restart batching process - private int discoveryBatchPausePeriod = 2; // pause for few secs + private int discoveryBatchRestartTicks = getDiscoveryInterval(); // periodically restart batching process + private int discoveryBatchPausePeriod = 5; // pause for few secs private int discoveryBatchPauseTicks = discoveryBatchRestartTicks - discoveryBatchPausePeriod; // pause after this point - private int discoveryRetry = 1; // number of retry after initial timeout - private int discoveryTimeoutTicks = 2; // timeout 2 sec + private int discoveryRetry = 2; // number of retry after initial timeout + private int discoveryTimeoutTicks = getDiscoveryTimeout(); // timeout in sec private int discoveryAgeoutTicks = 120; // age out 2 min private int discoveryConsistencyCheckMultiple = 2; // multiple of discoveryBatchRestartTicks private int discoveryConsistencyCheckTickCount = discoveryBatchPauseTicks; // CC tick counter @@ -1349,7 +1349,7 @@ public class DiscoveryService implements IInventoryShimExternalListener, portIdTlv.setType((byte) LLDPTLV.TLVType.PortID.getValue()); // Create LLDP TTL TLV - byte[] ttl = new byte[] { (byte) 120 }; + byte[] ttl = new byte[] {(byte) 0, (byte) 120 }; ttlTlv = new LLDPTLV(); ttlTlv.setType((byte) LLDPTLV.TLVType.TTL.getValue()).setLength( (short) ttl.length).setValue(ttl); @@ -1475,4 +1475,44 @@ public class DiscoveryService implements IInventoryShimExternalListener, return sourceMac; } + + /** + * This method returns the interval which determines how often the discovery + * packets will be sent. Default is 300 seconds. + * + * @return The discovery interval in second + */ + private static int getDiscoveryInterval() { + String elapsedTime = System.getProperty("of.discoveryInterval"); + int rv = 300; + + try { + if (elapsedTime != null) { + rv = Integer.parseInt(elapsedTime); + } + } catch (Exception e) { + } + + return rv; + } + + /** + * This method returns the timeout value in waiting for response of a + * discovery query. Default is 60 seconds. + * + * @return The discovery timeout in second + */ + private static int getDiscoveryTimeout() { + String elapsedTime = System.getProperty("of.discoveryTimeout"); + int rv = 60; + + try { + if (elapsedTime != null) { + rv = Integer.parseInt(elapsedTime); + } + } catch (Exception e) { + } + + return rv; + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java index 2926c22c43..230376555e 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java @@ -10,13 +10,17 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.eclipse.osgi.framework.console.CommandInterpreter; +import org.eclipse.osgi.framework.console.CommandProvider; import org.opendaylight.controller.protocol_plugin.openflow.IFlowProgrammerNotifier; +import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExternalListener; import org.opendaylight.controller.protocol_plugin.openflow.core.IController; import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener; import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch; @@ -34,15 +38,19 @@ import org.opendaylight.controller.sal.core.IContainerListener; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.Node.NodeIDType; import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.GlobalConstants; +import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.NodeCreator; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.Status; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,16 +59,20 @@ import org.slf4j.LoggerFactory; * the flow programming and relay them to functional modules above SAL. */ public class FlowProgrammerService implements IPluginInFlowProgrammerService, - IMessageListener, IContainerListener { + IMessageListener, IContainerListener, IInventoryShimExternalListener, + CommandProvider { private static final Logger log = LoggerFactory .getLogger(FlowProgrammerService.class); private IController controller; private ConcurrentMap flowProgrammerNotifiers; private Map> containerToNc; + private ConcurrentMap> xid2rid; + private int barrierMessagePriorCount = getBarrierMessagePriorCount(); public FlowProgrammerService() { controller = null; flowProgrammerNotifiers = new ConcurrentHashMap(); + xid2rid = new ConcurrentHashMap>(); } public void setController(IController core) { @@ -104,6 +116,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, */ void init() { this.controller.addMessageListener(OFType.FLOW_REMOVED, this); + registerWithOSGIConsole(); } /** @@ -134,6 +147,36 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, @Override public Status addFlow(Node node, Flow flow) { + return addFlowInternal(node, flow, 0); + } + + @Override + public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) { + return modifyFlowInternal(node, oldFlow, newFlow, 0); + } + + @Override + public Status removeFlow(Node node, Flow flow) { + return removeFlowInternal(node, flow, 0); + } + + @Override + public Status addFlowAsync(Node node, Flow flow, long rid) { + return addFlowInternal(node, flow, rid); + } + + @Override + public Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, + long rid) { + return modifyFlowInternal(node, oldFlow, newFlow, rid); + } + + @Override + public Status removeFlowAsync(Node node, Flow flow, long rid) { + return removeFlowInternal(node, flow, rid); + } + + private Status addFlowInternal(Node node, Flow flow, long rid) { String action = "add"; if (!node.getType().equals(NodeIDType.OPENFLOW)) { return new Status(StatusCode.NOTACCEPTABLE, errorString("send", @@ -146,10 +189,21 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, FlowConverter x = new FlowConverter(flow); OFMessage msg = x.getOFFlowMod(OFFlowMod.OFPFC_ADD, null); - /* - * Synchronous message send - */ - Object result = sw.syncSend(msg); + Object result; + if (rid == 0) { + /* + * Synchronous message send. Each message is followed by a + * Barrier message. + */ + result = sw.syncSend(msg); + } else { + /* + * Message will be sent asynchronously. A Barrier message + * will be inserted automatically to synchronize the + * progression. + */ + result = asyncMsgSend(node, sw, msg, rid); + } if (result instanceof Boolean) { return ((Boolean) result == Boolean.TRUE) ? new Status( StatusCode.SUCCESS, null) : new Status( @@ -183,8 +237,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, "Internal plugin error")); } - @Override - public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) { + private Status modifyFlowInternal(Node node, Flow oldFlow, Flow newFlow, long rid) { String action = "modify"; if (!node.getType().equals(NodeIDType.OPENFLOW)) { return new Status(StatusCode.NOTACCEPTABLE, errorString("send", @@ -211,7 +264,21 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, * Synchronous message send */ action = (msg2 == null) ? "modify" : "delete"; - Object result = sw.syncSend(msg1); + Object result; + if (rid == 0) { + /* + * Synchronous message send. Each message is followed by a + * Barrier message. + */ + result = sw.syncSend(msg1); + } else { + /* + * Message will be sent asynchronously. A Barrier message + * will be inserted automatically to synchronize the + * progression. + */ + result = asyncMsgSend(node, sw, msg1, rid); + } if (result instanceof Boolean) { if ((Boolean) result == Boolean.FALSE) { return new Status(StatusCode.TIMEOUT, errorString(null, @@ -230,7 +297,20 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, if (msg2 != null) { action = "add"; - result = sw.syncSend(msg2); + if (rid == 0) { + /* + * Synchronous message send. Each message is followed by a + * Barrier message. + */ + result = sw.syncSend(msg2); + } else { + /* + * Message will be sent asynchronously. A Barrier message + * will be inserted automatically to synchronize the + * progression. + */ + result = asyncMsgSend(node, sw, msg2, rid); + } if (result instanceof Boolean) { return ((Boolean) result == Boolean.TRUE) ? new Status( StatusCode.SUCCESS, null) : new Status( @@ -254,8 +334,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, "Internal plugin error")); } - @Override - public Status removeFlow(Node node, Flow flow) { + private Status removeFlowInternal(Node node, Flow flow, long rid) { String action = "remove"; if (!node.getType().equals(NodeIDType.OPENFLOW)) { return new Status(StatusCode.NOTACCEPTABLE, errorString("send", @@ -266,7 +345,21 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, if (sw != null) { OFMessage msg = new FlowConverter(flow).getOFFlowMod( OFFlowMod.OFPFC_DELETE_STRICT, OFPort.OFPP_NONE); - Object result = sw.syncSend(msg); + Object result; + if (rid == 0) { + /* + * Synchronous message send. Each message is followed by a + * Barrier message. + */ + result = sw.syncSend(msg); + } else { + /* + * Message will be sent asynchronously. A Barrier message + * will be inserted automatically to synchronize the + * progression. + */ + result = asyncMsgSend(node, sw, msg, rid); + } if (result instanceof Boolean) { return ((Boolean) result == Boolean.TRUE) ? new Status( StatusCode.SUCCESS, null) : new Status( @@ -371,11 +464,254 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, break; default: } - } @Override public void containerModeUpdated(UpdateType t) { } + + @Override + public Status sendBarrierMessage(Node node) { + if (!node.getType().equals(NodeIDType.OPENFLOW)) { + return new Status(StatusCode.NOTACCEPTABLE, + "The node does not support Barrier message."); + } + + if (controller != null) { + long swid = (Long) node.getID(); + ISwitch sw = controller.getSwitch(swid); + if (sw != null) { + sw.sendBarrierMessage(); + clearXid2Rid(swid); + return (new Status(StatusCode.SUCCESS, null)); + } else { + return new Status(StatusCode.GONE, + "The node does not have a valid Switch reference."); + } + } + return new Status(StatusCode.INTERNALERROR, + "Failed to send Barrier message."); + } + + /** + * This method sends the message asynchronously until the number of messages + * sent reaches a threshold. Then a Barrier message is sent automatically + * for sync purpose. An unique Request ID associated with the message is + * passed down by the caller. The Request ID will be returned to the caller + * when an error message is received from the switch. + * + * @param node + * The node + * @param msg + * The switch + * @param msg + * The OF message to be sent + * @param rid + * The Request Id + * @return result + */ + private Object asyncMsgSend(Node node, ISwitch sw, OFMessage msg, long rid) { + Object result = Boolean.TRUE; + long swid = (Long) node.getID(); + int xid; + + xid = sw.asyncSend(msg); + addXid2Rid(swid, xid, rid); + + Map swxid2rid = this.xid2rid.get(swid); + if (swxid2rid == null) { + return result; + } + + int size = swxid2rid.size(); + if (size % barrierMessagePriorCount == 0) { + result = sendBarrierMessage(node); + } + + return result; + } + + /** + * A number of async messages are sent followed by a synchronous Barrier + * message. This method returns the maximum async messages that can be sent + * before the Barrier message. + * + * @return The max count of async messages sent prior to Barrier message + */ + private int getBarrierMessagePriorCount() { + String count = System.getProperty("of.barrierMessagePriorCount"); + int rv = 100; + + if (count != null) { + try { + rv = Integer.parseInt(count); + } catch (Exception e) { + } + } + + return rv; + } + + /** + * This method returns the message Request ID previously assigned by the + * caller for a given OF message xid + * + * @param swid + * The switch id + * @param xid + * The OF message xid + * @return The Request ID + */ + public long getMessageRid(long swid, int xid) { + Map swxid2rid = this.xid2rid.get(swid); + long rid = 0; + + if (swxid2rid != null) { + rid = swxid2rid.get(xid); + } + return rid; + } + + /** + * This method returns a copy of outstanding xid to rid mappings.for a given + * switch + * + * @param swid + * The switch id + * @return a copy of xid2rid mappings + */ + public Map getSwXid2Rid(long swid) { + Map swxid2rid = this.xid2rid.get(swid); + + if (swxid2rid != null) { + return new HashMap(swxid2rid); + } else { + return new HashMap(); + } + } + + /** + * Adds xid to rid mapping to the local DB + * + * @param swid + * The switch id + * @param xid + * The OF message xid + * @param rid + * The message Request ID + */ + private void addXid2Rid(long swid, int xid, long rid) { + Map swxid2rid = this.xid2rid.get(swid); + if (swxid2rid != null) { + swxid2rid.put(xid, rid); + } + } + + /** + * When an Error message is received, this method will be invoked to remove + * the offending xid from the local DB. + * + * @param swid + * The switch id + * @param xid + * The OF message xid + */ + private void removeXid2Rid(long swid, int xid) { + Map swxid2rid = this.xid2rid.get(swid); + if (swxid2rid != null) { + swxid2rid.remove(xid); + } + } + + /** + * When a Barrier reply is received, this method will be invoked to clear + * the local DB + * + * @param swid + * The switch id + */ + private void clearXid2Rid(long swid) { + Map swxid2rid = this.xid2rid.get(swid); + if (swxid2rid != null) { + swxid2rid.clear(); + } + } + + @Override + public void updateNode(Node node, UpdateType type, Set props) { + long swid = (Long)node.getID(); + + switch (type) { + case ADDED: + Map swxid2rid = new HashMap(); + this.xid2rid.put(swid, swxid2rid); + break; + case CHANGED: + break; + case REMOVED: + this.xid2rid.remove(swid); + break; + default: + } + } + + @Override + public void updateNodeConnector(NodeConnector nodeConnector, + UpdateType type, Set props) { + } + + private void registerWithOSGIConsole() { + BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()) + .getBundleContext(); + bundleContext.registerService(CommandProvider.class.getName(), this, + null); + } + + @Override + public String getHelp() { + StringBuffer help = new StringBuffer(); + help.append("-- Flow Programmer Service --\n"); + help.append("\t px2r - Print outstanding xid2rid mappings for a given node id\n"); + help.append("\t px2rc - Print max num of async msgs prior to the Barrier\n"); + return help.toString(); + } + + public void _px2r(CommandInterpreter ci) { + String st = ci.nextArgument(); + if (st == null) { + ci.println("Please enter a valid node id"); + return; + } + + long sid; + try { + sid = HexEncode.stringToLong(st); + } catch (NumberFormatException e) { + ci.println("Please enter a valid node id"); + return; + } + + Map swxid2rid = this.xid2rid.get(sid); + if (swxid2rid == null) { + ci.println("The node id entered does not exist"); + return; + } + + ci.println("xid rid"); + + Set xidSet = swxid2rid.keySet(); + if (xidSet == null) { + return; + } + + for (Integer xid : xidSet) { + ci.println(xid + " " + swxid2rid.get(xid)); + } + } + + public void _px2rc(CommandInterpreter ci) { + ci.println("Max num of async messages sent prior to the Barrier message is " + + barrierMessagePriorCount); + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java index d00cd58c59..3a3eaad93e 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -48,8 +47,8 @@ import org.slf4j.LoggerFactory; * container of the network. Each instance gets container specific inventory * events from InventoryServiceShim. It interacts with SAL to pass inventory * data to the upper application. - * - * + * + * */ public class InventoryService implements IInventoryShimInternalListener, IPluginInInventoryService, IStatisticsListener { @@ -58,8 +57,8 @@ public class InventoryService implements IInventoryShimInternalListener, private Set pluginOutInventoryServices = Collections .synchronizedSet(new HashSet()); private IController controller = null; - private ConcurrentMap> nodeProps; // properties are maintained in default container only - private ConcurrentMap> nodeConnectorProps; // properties are maintained in default container only + private ConcurrentMap> nodeProps; // properties are maintained in global container only + private ConcurrentMap> nodeConnectorProps; // properties are maintained in global container only private boolean isDefaultContainer = false; void setController(IController s) { @@ -75,7 +74,7 @@ public class InventoryService implements IInventoryShimInternalListener, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ @SuppressWarnings("rawtypes") void init(Component c) { @@ -96,7 +95,7 @@ public class InventoryService implements IInventoryShimInternalListener, * Function called by the dependency manager when at least one dependency * become unsatisfied or when the component is shutting down because for * example bundle is being stopped. - * + * */ void destroy() { logger.trace("DESTROY called!"); @@ -105,7 +104,7 @@ public class InventoryService implements IInventoryShimInternalListener, /** * Function called by dependency manager after "init ()" is called and after * the services provided by the class are registered in the service registry - * + * */ void start() { logger.trace("START called!"); @@ -115,7 +114,7 @@ public class InventoryService implements IInventoryShimInternalListener, * Function called by the dependency manager before the services exported by * the component are unregistered, this will be followed by a "destroy ()" * calls - * + * */ void stop() { logger.trace("STOP called!"); @@ -158,7 +157,7 @@ public class InventoryService implements IInventoryShimInternalListener, return null; Map switches = controller.getSwitches(); for (Map.Entry entry : switches.entrySet()) { - ISwitch sw = entry.getValue(); + ISwitch sw = entry.getValue(); Node node = OFSwitchToNode(sw); Map propMap = null; if (isDefaultContainer) { @@ -166,22 +165,22 @@ public class InventoryService implements IInventoryShimInternalListener, byte tables = sw.getTables(); Tables t = new Tables(tables); if (t != null) { - propMap.put(Tables.TablesPropName,t); + propMap.put(Tables.TablesPropName, t); } int cap = sw.getCapabilities(); Capabilities c = new Capabilities(cap); if (c != null) { - propMap.put(Capabilities.CapabilitiesPropName, c); + propMap.put(Capabilities.CapabilitiesPropName, c); } int act = sw.getActions(); Actions a = new Actions(act); if (a != null) { - propMap.put(Actions.ActionsPropName,a); + propMap.put(Actions.ActionsPropName, a); } int buffers = sw.getBuffers(); Buffers b = new Buffers(buffers); if (b != null) { - propMap.put(Buffers.BuffersPropName,b); + propMap.put(Buffers.BuffersPropName, b); } Date connectedSince = sw.getConnectedDate(); Long connectedSinceTime = (connectedSince == null) ? 0 @@ -208,8 +207,8 @@ public class InventoryService implements IInventoryShimInternalListener, .OFSwitchToProps(sw); for (Map.Entry> entry : ncProps .entrySet()) { - updateNodeConnector(entry.getKey(), UpdateType.ADDED, entry - .getValue()); + updateNodeConnector(entry.getKey(), UpdateType.ADDED, + entry.getValue()); } } } @@ -220,18 +219,14 @@ public class InventoryService implements IInventoryShimInternalListener, @Override public void updateNodeConnector(NodeConnector nodeConnector, UpdateType type, Set props) { - logger.trace("NodeConnector id " + nodeConnector.getID() - + " type " + nodeConnector.getType() + " " - + type.getName() + " for Node id " - + nodeConnector.getNode().getID()); - + logger.trace("updateNodeConnector {} type {}", nodeConnector, + type.getName()); if (nodeConnectorProps == null) { + logger.trace("nodeConnectorProps is null"); return; } - - Map propMap = nodeConnectorProps - .get(nodeConnector); + Map propMap = nodeConnectorProps.get(nodeConnector); switch (type) { case ADDED: case CHANGED: @@ -306,7 +301,6 @@ public class InventoryService implements IInventoryShimInternalListener, } } - private void updateSwitchProperty(Long switchId, Set propSet) { // update local cache Node node = OFSwitchToNode(controller.getSwitch(switchId)); @@ -314,25 +308,25 @@ public class InventoryService implements IInventoryShimInternalListener, if (propMap == null) { propMap = new HashMap(); } - + boolean change = false; for (Property prop : propSet) { - String propertyName = prop.getName(); - Property currentProp = propMap.get(propertyName); - if (!prop.equals(currentProp)) { - change = true; - propMap.put(propertyName, prop); - } + String propertyName = prop.getName(); + Property currentProp = propMap.get(propertyName); + if (!prop.equals(currentProp)) { + change = true; + propMap.put(propertyName, prop); + } } nodeProps.put(node, propMap); // Update sal if any of the properties has changed if (change) { - synchronized (pluginOutInventoryServices) { - for (IPluginOutInventoryService service : pluginOutInventoryServices) { - service.updateNode(node, UpdateType.CHANGED, propSet); - } - } + synchronized (pluginOutInventoryServices) { + for (IPluginOutInventoryService service : pluginOutInventoryServices) { + service.updateNode(node, UpdateType.CHANGED, propSet); + } + } } } @@ -350,14 +344,14 @@ public class InventoryService implements IInventoryShimInternalListener, } } - @Override - public void descriptionRefreshed(Long switchId, - OFDescriptionStatistics descriptionStats) { - - Set propSet = new HashSet(1); - Description desc = - new Description(descriptionStats.getDatapathDescription()); - propSet.add(desc); - this.updateSwitchProperty(switchId, propSet); - } + @Override + public void descriptionRefreshed(Long switchId, + OFDescriptionStatistics descriptionStats) { + + Set propSet = new HashSet(1); + Description desc = new Description( + descriptionStats.getDatapathDescription()); + propSet.add(desc); + this.updateSwitchProperty(switchId, propSet); + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java index fb295a24c0..b522063ad7 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -49,8 +48,8 @@ import org.slf4j.LoggerFactory; * The class describes a shim layer that bridges inventory events from Openflow * core to various listeners. The notifications are filtered based on container * configurations. - * - * + * + * */ public class InventoryServiceShim implements IContainerListener, IMessageListener, ISwitchStateListener { @@ -74,42 +73,42 @@ public class InventoryServiceShim implements IContainerListener, void setInventoryShimInternalListener(Map props, IInventoryShimInternalListener s) { if (props == null) { - logger.error("Didn't receive the service properties"); + logger.error("setInventoryShimInternalListener property is null"); return; } String containerName = (String) props.get("containerName"); if (containerName == null) { - logger.error("containerName not supplied"); + logger.error("setInventoryShimInternalListener containerName not supplied"); return; } if ((this.inventoryShimInternalListeners != null) && !this.inventoryShimInternalListeners.containsValue(s)) { this.inventoryShimInternalListeners.put(containerName, s); - logger.trace("Added inventoryShimInternalListener for container:" - + containerName); + logger.trace( + "Added inventoryShimInternalListener for container {}", + containerName); } } void unsetInventoryShimInternalListener(Map props, IInventoryShimInternalListener s) { if (props == null) { - logger.error("Didn't receive the service properties"); + logger.error("unsetInventoryShimInternalListener property is null"); return; } String containerName = (String) props.get("containerName"); if (containerName == null) { - logger.error("containerName not supplied"); + logger.error("unsetInventoryShimInternalListener containerName not supplied"); return; } if ((this.inventoryShimInternalListeners != null) - && this.inventoryShimInternalListeners - .get(containerName) != null - && this.inventoryShimInternalListeners - .get(containerName).equals(s)) { + && this.inventoryShimInternalListeners.get(containerName) != null + && this.inventoryShimInternalListeners.get(containerName) + .equals(s)) { this.inventoryShimInternalListeners.remove(containerName); - logger - .trace("Removed inventoryShimInternalListener for container: " - + containerName); + logger.trace( + "Removed inventoryShimInternalListener for container {}", + containerName); } } @@ -131,7 +130,7 @@ public class InventoryServiceShim implements IContainerListener, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ void init() { this.controller.addMessageListener(OFType.PORT_STATUS, this); @@ -139,8 +138,7 @@ public class InventoryServiceShim implements IContainerListener, } /** - * Function called after registering the - * service in OSGi service registry. + * Function called after registering the service in OSGi service registry. */ void started() { /* Start with existing switches */ @@ -148,10 +146,10 @@ public class InventoryServiceShim implements IContainerListener, } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. - * + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * */ void destroy() { this.controller.removeMessageListener(OFType.PACKET_IN, this); @@ -189,6 +187,8 @@ public class InventoryServiceShim implements IContainerListener, type = UpdateType.CHANGED; } + logger.trace("handlePortStatusMessage {} type {}", nodeConnector, type); + if (type != null) { // get node connector properties Set props = InventoryServiceHelper.OFPortToProps(m @@ -206,8 +206,8 @@ public class InventoryServiceShim implements IContainerListener, Map> ncProps = InventoryServiceHelper .OFSwitchToProps(sw); for (Map.Entry> entry : ncProps.entrySet()) { - notifyInventoryShimListener(entry.getKey(), UpdateType.ADDED, entry - .getValue()); + notifyInventoryShimListener(entry.getKey(), UpdateType.ADDED, + entry.getValue()); } // Add this node @@ -300,17 +300,19 @@ public class InventoryServiceShim implements IContainerListener, if (inventoryShimInternalListener != null) { inventoryShimInternalListener.updateNodeConnector(nodeConnector, type, props); - logger.trace(type + " " + nodeConnector + " on container " - + container); + logger.trace( + "notifyInventoryShimInternalListener {} type {} for container {}", + nodeConnector, type, container); } } /* - * Notify all internal and external listeners + * Notify all internal and external listeners */ private void notifyInventoryShimListener(NodeConnector nodeConnector, UpdateType type, Set props) { - // Always notify default InventoryService. Store properties in default one. + // Always notify default InventoryService. Store properties in default + // one. notifyInventoryShimInternalListener(GlobalConstants.DEFAULT.toString(), nodeConnector, type, props); @@ -329,7 +331,7 @@ public class InventoryServiceShim implements IContainerListener, } /* - * Notify all internal and external listeners + * Notify all internal and external listeners */ private void notifyInventoryShimListener(Node node, UpdateType type, Set props) { @@ -380,22 +382,22 @@ public class InventoryServiceShim implements IContainerListener, byte tables = sw.getTables(); Tables t = new Tables(tables); if (t != null) { - props.add(t); + props.add(t); } int cap = sw.getCapabilities(); Capabilities c = new Capabilities(cap); if (c != null) { - props.add(c); + props.add(c); } int act = sw.getActions(); Actions a = new Actions(act); if (a != null) { - props.add(a); + props.add(a); } int buffers = sw.getBuffers(); Buffers b = new Buffers(buffers); if (b != null) { - props.add(b); + props.add(b); } // Notify all internal and external listeners notifyInventoryShimListener(node, type, props); diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java index 6fda92c023..424af8d4f4 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -104,7 +103,7 @@ public class TopologyServiceShim implements IDiscoveryService, entry = null; } catch (InterruptedException e1) { - logger.warn("TopologyNotify interrupted", e1.getMessage()); + logger.warn("TopologyNotify interrupted {}", e1.getMessage()); if (shuttingDown) { return; } @@ -156,7 +155,7 @@ public class TopologyServiceShim implements IDiscoveryService, } } catch (InterruptedException e1) { logger.warn( - "Edge Bandwidth Utilization Notify Thread interrupted", + "Edge Bandwidth Utilization Notify Thread interrupted {}", e1.getMessage()); if (shuttingDown) { return; @@ -329,8 +328,8 @@ public class TopologyServiceShim implements IDiscoveryService, && !this.topologyServiceShimListeners .containsKey(containerName)) { this.topologyServiceShimListeners.put(containerName, s); - logger.trace("Added topologyServiceShimListener for container:" - + containerName); + logger.trace("Added topologyServiceShimListener for container: {}", + containerName); } } @@ -350,8 +349,8 @@ public class TopologyServiceShim implements IDiscoveryService, && this.topologyServiceShimListeners.get(containerName).equals( s)) { this.topologyServiceShimListeners.remove(containerName); - logger.trace("Removed topologyServiceShimListener for container: " - + containerName); + logger.trace("Removed topologyServiceShimListener for container: {}", + containerName); } } @@ -423,14 +422,15 @@ public class TopologyServiceShim implements IDiscoveryService, } break; default: - logger.debug("Invalid " + type + " Edge " + edge - + " in container {}", container); + logger.debug("notifyEdge: invalid {} for Edge {} in container {}", + type, edge, container); return; } notifyQ.add(new NotifyEntry(container, edgeProps, type)); - logger.trace(type + " Edge " + edge + " in container {}", container); + logger.debug("notifyEdge: {} Edge {} in container {}", + type, edge, container); } @Override diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServices.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServices.java index 57a7b03dd9..64515887c0 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServices.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServices.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -35,91 +34,94 @@ public class TopologyServices implements ITopologyServiceShimListener, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ @SuppressWarnings("unchecked") void init(Component c) { - logger.debug("INIT called!"); + logger.trace("INIT called!"); Dictionary props = c.getServiceProperties(); containerName = (props != null) ? (String) props.get("containerName") : null; } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. - * + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * */ void destroy() { - logger.debug("DESTROY called!"); + logger.trace("DESTROY called!"); } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry - * + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * */ void start() { - logger.debug("START called!"); + logger.trace("START called!"); } /** - * Function called by the dependency manager before the services - * exported by the component are unregistered, this will be - * followed by a "destroy ()" calls - * + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * */ void stop() { - logger.debug("STOP called!"); + logger.trace("STOP called!"); } /** * Retrieve SAL service IPluginOutTopologyService - * - * @param s Called by Dependency Manager as soon as the SAL - * service is available + * + * @param s + * Called by Dependency Manager as soon as the SAL service is + * available */ public void setPluginOutTopologyService(IPluginOutTopologyService s) { - logger.debug("Setting IPluginOutTopologyService to:" + s); + logger.trace("Setting IPluginOutTopologyService to: {}", s); this.salTopoService = s; } /** * called when SAL service IPluginOutTopologyService is no longer available - * - * @param s Called by Dependency Manager as soon as the SAL - * service is unavailable + * + * @param s + * Called by Dependency Manager as soon as the SAL service is + * unavailable */ public void unsetPluginOutTopologyService(IPluginOutTopologyService s) { if (this.salTopoService == s) { - logger.debug("UNSetting IPluginOutTopologyService from:" + s); + logger.trace("UNSetting IPluginOutTopologyService from: {}", s); this.salTopoService = null; } } /** * Retrieve OF protocol_plugin service IRefreshInternalProvider - * - * @param s Called by Dependency Manager as soon as the SAL - * service is available + * + * @param s + * Called by Dependency Manager as soon as the SAL service is + * available */ public void setRefreshInternalProvider(IRefreshInternalProvider s) { - logger.debug("Setting IRefreshInternalProvider to:" + s); + logger.trace("Setting IRefreshInternalProvider to: {}", s); this.topoRefreshService = s; } /** - * called when OF protocol_plugin service IRefreshInternalProvider - * is no longer available - * - * @param s Called by Dependency Manager as soon as the SAL - * service is unavailable + * called when OF protocol_plugin service IRefreshInternalProvider is no + * longer available + * + * @param s + * Called by Dependency Manager as soon as the SAL service is + * unavailable */ public void unsetRefreshInternalProvider(IRefreshInternalProvider s) { if (this.topoRefreshService == s) { - logger.debug("UNSetting IRefreshInternalProvider from:" + s); + logger.trace("UNSetting IRefreshInternalProvider from: {}", s); this.topoRefreshService = null; } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java index 69972d6776..5cdf9d8368 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java @@ -17,7 +17,7 @@ import org.opendaylight.controller.sal.utils.Status; */ public interface IFlowProgrammerService { /** - * Add a flow to the network node + * Synchronously add a flow to the network node * * @param node * @param flow @@ -25,25 +25,56 @@ public interface IFlowProgrammerService { Status addFlow(Node node, Flow flow); /** - * Modify existing flow on the switch + * Synchronously modify existing flow on the switch * * @param node * @param flow */ - Status modifyFlow(Node node, Flow oldflow, Flow newFlow); + Status modifyFlow(Node node, Flow oldFlow, Flow newFlow); /** - * Remove the flow from the network node + * Synchronously remove the flow from the network node * * @param node * @param flow */ Status removeFlow(Node node, Flow flow); + /** + * Asynchronously add a flow to the network node + * + * @param node + * @param flow + */ + Status addFlowAsync(Node node, Flow flow); + + /** + * Asynchronously modify existing flow on the switch + * + * @param node + * @param flow + */ + Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow); + + /** + * Asynchronously remove the flow from the network node + * + * @param node + * @param flow + */ + Status removeFlowAsync(Node node, Flow flow); + /** * Remove all flows present on the network node * * @param node */ Status removeAllFlows(Node node); + + /** + * Send synchronous Barrier message + * + * @param node + */ + Status sendBarrierMessage(Node node); } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java index 79924fc3dd..c72353055d 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java @@ -18,7 +18,7 @@ import org.opendaylight.controller.sal.utils.Status; */ public interface IPluginInFlowProgrammerService { /** - * Add a flow to the network node + * Synchronously add a flow to the network node * * @param node * @param flow @@ -26,7 +26,7 @@ public interface IPluginInFlowProgrammerService { Status addFlow(Node node, Flow flow); /** - * Modify existing flow on the switch + * Synchronously modify existing flow on the switch * * @param node * @param flow @@ -34,17 +34,51 @@ public interface IPluginInFlowProgrammerService { Status modifyFlow(Node node, Flow oldFlow, Flow newFlow); /** - * Remove the flow from the network node + * Synchronously remove the flow from the network node * * @param node * @param flow */ Status removeFlow(Node node, Flow flow); + /** + * Asynchronously add a flow to the network node + * + * @param node + * @param flow + * @param rid + */ + Status addFlowAsync(Node node, Flow flow, long rid); + + /** + * Asynchronously modify existing flow on the switch + * + * @param node + * @param flow + * @param rid + */ + Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid); + + /** + * Asynchronously remove the flow from the network node + * + * @param node + * @param flow + * @param rid + */ + Status removeFlowAsync(Node node, Flow flow, long rid); + /** * Remove all flows present on the network node * * @param node */ Status removeAllFlows(Node node); + + /** + * Send synchronous Barrier message + * + * @param node + */ + Status sendBarrierMessage(Node node); } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java index b530e38022..45706fc77c 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -31,30 +30,29 @@ public class LLDPTLV extends Packet { private static final String LENGTH = "Length"; private static final String VALUE = "Value"; private static final int LLDPTLVFields = 3; - public static final byte[] OFOUI = new byte[] {(byte)0x00, (byte)0x26, (byte)0xe1}; // OpenFlow OUI - public static final byte[] customTlvSubType = new byte[] {0}; - public static final int customTlvOffset = OFOUI.length + customTlvSubType.length; - public static final byte chassisIDSubType[] = new byte[] {4}; // MAC address for the system - public static final byte portIDSubType[] = new byte[] {7}; // locally assigned - - public enum TLVType { - Unknown ((byte)0), - ChassisID ((byte)1), - PortID ((byte)2), - TTL ((byte)3), - PortDesc ((byte)4), - SystemName ((byte)5), - SystemDesc ((byte)6), - Custom ((byte)127); - - private byte value; - private TLVType(byte value) { - this.value = value; - } - public byte getValue() { - return value; - } - } + public static final byte[] OFOUI = new byte[] { (byte) 0x00, (byte) 0x26, + (byte) 0xe1 }; // OpenFlow OUI + public static final byte[] customTlvSubType = new byte[] { 0 }; + public static final int customTlvOffset = OFOUI.length + + customTlvSubType.length; + public static final byte chassisIDSubType[] = new byte[] { 4 }; // MAC address for the system + public static final byte portIDSubType[] = new byte[] { 7 }; // locally assigned + + public enum TLVType { + Unknown((byte) 0), ChassisID((byte) 1), PortID((byte) 2), TTL((byte) 3), PortDesc( + (byte) 4), SystemName((byte) 5), SystemDesc((byte) 6), Custom( + (byte) 127); + + private byte value; + + private TLVType(byte value) { + this.value = value; + } + + public byte getValue() { + return value; + } + } private static Map> fieldCoordinates = new LinkedHashMap>() { private static final long serialVersionUID = 1L; @@ -69,8 +67,8 @@ public class LLDPTLV extends Packet { protected Map fieldValues; /** - * Default constructor that creates and sets the hash map values - * and sets the payload to null + * Default constructor that creates and sets the hash map values and sets + * the payload to null */ public LLDPTLV() { payload = null; @@ -80,8 +78,7 @@ public class LLDPTLV extends Packet { } /** - * Constructor that writes the passed LLDPTLV values to the - * hdrFieldsMap + * Constructor that writes the passed LLDPTLV values to the hdrFieldsMap */ public LLDPTLV(LLDPTLV other) { for (Map.Entry entry : other.hdrFieldsMap.entrySet()) { @@ -166,6 +163,7 @@ public class LLDPTLV extends Packet { /** * Returns the size in bits of the whole TLV + * * @return int - size in bits of full TLV * @throws Exception */ @@ -174,27 +172,41 @@ public class LLDPTLV extends Packet { LLDPTLV.fieldCoordinates.get(LENGTH).getRight() + // static getfieldnumBits(VALUE)); // variable } - + /** - * Creates the ChassisID TLV value including the subtype and ChassisID string + * Creates the ChassisID TLV value including the subtype and ChassisID + * string * - * @param nodeId node identifier string + * @param nodeId + * node identifier string * @return the ChassisID TLV value in byte array */ static public byte[] createChassisIDTLVValue(String nodeId) { - byte[] cid = HexEncode.bytesFromHexString(nodeId); + byte[] nid = HexEncode.bytesFromHexString(nodeId); + byte[] cid = new byte[6]; + int srcPos = 0, dstPos = 0; + + if (nid.length > cid.length) { + srcPos = nid.length - cid.length; + } else { + dstPos = cid.length - nid.length; + } + System.arraycopy(nid, srcPos, cid, dstPos, cid.length); + byte[] cidValue = new byte[cid.length + chassisIDSubType.length]; - System.arraycopy(chassisIDSubType, 0, cidValue, 0, chassisIDSubType.length); + System.arraycopy(chassisIDSubType, 0, cidValue, 0, + chassisIDSubType.length); System.arraycopy(cid, 0, cidValue, chassisIDSubType.length, cid.length); - return cidValue; + return cidValue; } /** * Creates the PortID TLV value including the subtype and PortID string * - * @param portId port identifier string + * @param portId + * port identifier string * @return the PortID TLV value in byte array */ static public byte[] createPortIDTLVValue(String portId) { @@ -204,13 +216,14 @@ public class LLDPTLV extends Packet { System.arraycopy(portIDSubType, 0, pidValue, 0, portIDSubType.length); System.arraycopy(pid, 0, pidValue, portIDSubType.length, pid.length); - return pidValue; + return pidValue; } /** * Creates the custom TLV value including OUI, subtype and custom string * - * @param portId port identifier string + * @param portId + * port identifier string * @return the custom TLV value in byte array */ static public byte[] createCustomTLVValue(String customString) { @@ -223,40 +236,49 @@ public class LLDPTLV extends Packet { System.arraycopy(customArray, 0, customValue, customTlvOffset, customArray.length); - return customValue; + return customValue; } /** * Retrieves the string from TLV value and returns it in HexString format * - * @param tlvValue the TLV value - * @param tlvLen the TLV length + * @param tlvValue + * the TLV value + * @param tlvLen + * the TLV length * @return the HexString */ static public String getHexStringValue(byte[] tlvValue, int tlvLen) { - byte[] cidBytes = new byte[tlvLen - chassisIDSubType.length]; - System.arraycopy(tlvValue, chassisIDSubType.length, cidBytes, 0, cidBytes.length); - return HexEncode.bytesToHexStringFormat(cidBytes); + byte[] cidBytes = new byte[tlvLen - chassisIDSubType.length]; + System.arraycopy(tlvValue, chassisIDSubType.length, cidBytes, 0, + cidBytes.length); + return HexEncode.bytesToHexStringFormat(cidBytes); } /** * Retrieves the string from TLV value * - * @param tlvValue the TLV value - * @param tlvLen the TLV length + * @param tlvValue + * the TLV value + * @param tlvLen + * the TLV length * @return the string */ static public String getStringValue(byte[] tlvValue, int tlvLen) { - byte[] pidBytes = new byte[tlvLen - portIDSubType.length]; - System.arraycopy(tlvValue, portIDSubType.length, pidBytes, 0, pidBytes.length); - return (new String(pidBytes)); + byte[] pidBytes = new byte[tlvLen - portIDSubType.length]; + System.arraycopy(tlvValue, portIDSubType.length, pidBytes, 0, + pidBytes.length); + return (new String(pidBytes)); } /** - * Retrieves the custom string from the Custom TLV value which includes OUI, subtype and custom string + * Retrieves the custom string from the Custom TLV value which includes OUI, + * subtype and custom string * - * @param customTlvValue the custom TLV value - * @param customTlvLen the custom TLV length + * @param customTlvValue + * the custom TLV value + * @param customTlvLen + * the custom TLV length * @return the custom string */ static public String getCustomString(byte[] customTlvValue, int customTlvLen) { @@ -266,14 +288,14 @@ public class LLDPTLV extends Packet { if (Arrays.equals(vendor, LLDPTLV.OFOUI)) { int customArrayLength = customTlvLen - customTlvOffset; byte[] customArray = new byte[customArrayLength]; - System.arraycopy(customTlvValue, customTlvOffset, - customArray, 0, customArrayLength); + System.arraycopy(customTlvValue, customTlvOffset, customArray, 0, + customArrayLength); try { - customString = new String(customArray, "UTF-8"); + customString = new String(customArray, "UTF-8"); } catch (UnsupportedEncodingException e) { } } - - return customString; - } + + return customString; + } } diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java index dd1277311e..f85420ee3e 100644 --- a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.implementation.internal; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; @@ -58,10 +59,17 @@ public class FlowProgrammerService implements IFlowProgrammerService, .getLogger(FlowProgrammerService.class); private ConcurrentHashMap pluginFlowProgrammer; private Set listener; + private AtomicLong seq; public FlowProgrammerService() { pluginFlowProgrammer = new ConcurrentHashMap(); listener = new HashSet(); + seq = new AtomicLong(); + /* + * This Request ID generator starts with 1. Each aysnc message is + * associated with an unique Request ID (!= 0). + */ + seq.lazySet(1); } /** @@ -213,6 +221,39 @@ public class FlowProgrammerService implements IFlowProgrammerService, return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); } + @Override + public Status addFlowAsync(Node node, Flow flow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()).addFlowAsync( + node, flow, getNextRid()); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status removeFlowAsync(Node node, Flow flow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .removeFlowAsync(node, flow, getNextRid()); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .modifyFlowAsync(node, oldFlow, newFlow, getNextRid()); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + @Override public void flowRemoved(Node node, Flow flow) { for (IFlowProgrammerListener l : listener) { @@ -254,7 +295,7 @@ public class FlowProgrammerService implements IFlowProgrammerService, } ci.println(this.addFlow(node, getSampleFlow(node))); } - + public void _modifyflow(CommandInterpreter ci) throws UnknownHostException { Node node = null; String nodeId = ci.nextArgument(); @@ -440,4 +481,22 @@ public class FlowProgrammerService implements IFlowProgrammerService, return flow; } + /* + * This Request ID generator starts with 1. Each aysnc message is + * associated with an unique Request ID (!= 0). + */ + private long getNextRid() { + return seq.getAndIncrement(); + } + + @Override + public Status sendBarrierMessage(Node node) { + if (this.pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .sendBarrierMessage(node); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } } diff --git a/opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java b/opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java index 0d5781bdf2..8ed7e46275 100755 --- a/opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java +++ b/opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -96,10 +95,10 @@ public class SwitchManagerImpl implements ISwitchManager, private ConcurrentMap subnets; // set of Subnets keyed by the InetAddress private ConcurrentMap subnetsConfigList; private ConcurrentMap spanConfigList; - private ConcurrentMap nodeConfigList; // manually configured parameters for the node, like name and tier + private ConcurrentMap nodeConfigList; // manually configured parameters for the node like name and tier private ConcurrentMap configSaveEvent; - private ConcurrentMap> nodeProps; // properties are maintained in default container only - private ConcurrentMap> nodeConnectorProps; // properties are maintained in default container only + private ConcurrentMap> nodeProps; // properties are maintained in global container only + private ConcurrentMap> nodeConnectorProps; // properties are maintained in global container only private ConcurrentMap> nodeConnectorNames; private IInventoryService inventoryService; private Set switchManagerAware = Collections @@ -114,7 +113,7 @@ public class SwitchManagerImpl implements ISwitchManager, private IClusterContainerServices clusterContainerService = null; private String containerName = null; private boolean isDefaultContainer = true; - + public enum ReasonCode { SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF( "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT( @@ -137,7 +136,8 @@ public class SwitchManagerImpl implements ISwitchManager, try { ((ISwitchManagerAware) subAware).subnetNotify(sub, add); } catch (Exception e) { - log.error("Failed to notify Subnet change", e); + log.error("Failed to notify Subnet change {}", + e.getMessage()); } } } @@ -150,7 +150,8 @@ public class SwitchManagerImpl implements ISwitchManager, try { ((ISpanAware) sa).spanUpdate(node, ports, add); } catch (Exception e) { - log.error("Failed to notify Span Interface change", e); + log.error("Failed to notify Span Interface change {}", + e.getMessage()); } } } @@ -162,7 +163,8 @@ public class SwitchManagerImpl implements ISwitchManager, try { service.modeChangeNotify(node, proactive); } catch (Exception e) { - log.error("Failed to notify Subnet change", e); + log.error("Failed to notify Subnet change {}", + e.getMessage()); } } } @@ -198,16 +200,16 @@ public class SwitchManagerImpl implements ISwitchManager, } @SuppressWarnings("deprecation") - private void allocateCaches() { + private void allocateCaches() { if (this.clusterContainerService == null) { - log.info("un-initialized clusterContainerService, can't create cache"); + log.warn("un-initialized clusterContainerService, can't create cache"); return; } try { clusterContainerService.createCache( - "switchmanager.subnetsConfigList", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + "switchmanager.subnetsConfigList", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); clusterContainerService.createCache("switchmanager.spanConfigList", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); clusterContainerService.createCache("switchmanager.nodeConfigList", @@ -215,16 +217,16 @@ public class SwitchManagerImpl implements ISwitchManager, clusterContainerService.createCache("switchmanager.subnets", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); clusterContainerService.createCache( - "switchmanager.configSaveEvent", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + "switchmanager.configSaveEvent", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); clusterContainerService.createCache("switchmanager.nodeProps", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); clusterContainerService.createCache( - "switchmanager.nodeConnectorProps", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + "switchmanager.nodeConnectorProps", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); clusterContainerService.createCache( - "switchmanager.nodeConnectorNames", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + "switchmanager.nodeConnectorNames", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); } catch (CacheConfigException cce) { log.error("\nCache configuration invalid - check cache mode"); } catch (CacheExistException ce) { @@ -235,8 +237,7 @@ public class SwitchManagerImpl implements ISwitchManager, @SuppressWarnings({ "unchecked", "deprecation" }) private void retrieveCaches() { if (this.clusterContainerService == null) { - log - .info("un-initialized clusterContainerService, can't create cache"); + log.info("un-initialized clusterContainerService, can't create cache"); return; } @@ -301,10 +302,9 @@ public class SwitchManagerImpl implements ISwitchManager, } @SuppressWarnings("deprecation") - private void destroyCaches(String container) { + private void destroyCaches(String container) { if (this.clusterContainerService == null) { - log - .info("un-initialized clusterContainerService, can't create cache"); + log.info("un-initialized clusterContainerService, can't create cache"); return; } @@ -411,7 +411,7 @@ public class SwitchManagerImpl implements ISwitchManager, Subnet newSubnet = new Subnet(conf); Set IPs = subnets.keySet(); if (IPs == null) { - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS, null); } for (InetAddress i : IPs) { Subnet existingSubnet = subnets.get(i); @@ -426,7 +426,7 @@ public class SwitchManagerImpl implements ISwitchManager, private Status addRemoveSubnet(SubnetConfig conf, boolean add) { // Valid config check if (!conf.isValidConfig()) { - String msg = "Invalid Subnet configuration"; + String msg = "Invalid Subnet configuration"; log.warn(msg); return new Status(StatusCode.BADREQUEST, msg); } @@ -434,8 +434,8 @@ public class SwitchManagerImpl implements ISwitchManager, if (add) { // Presence check if (subnetsConfigList.containsKey(conf.getName())) { - return new Status(StatusCode.CONFLICT, - "Same subnet config already exists"); + return new Status(StatusCode.CONFLICT, + "Same subnet config already exists"); } // Semantyc check Status rc = semanticCheck(conf); @@ -481,7 +481,7 @@ public class SwitchManagerImpl implements ISwitchManager, return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); } if (!conf.isValidSwitchPort(switchPorts)) { - return new Status(StatusCode.BADREQUEST, "Invalid switchports"); + return new Status(StatusCode.BADREQUEST, "Invalid switchports"); } conf.addNodeConnectors(switchPorts); @@ -498,7 +498,7 @@ public class SwitchManagerImpl implements ISwitchManager, // Update Configuration SubnetConfig conf = subnetsConfigList.get(name); if (conf == null) { - return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); + return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); } conf.removeNodeConnectors(switchPorts); @@ -609,15 +609,15 @@ public class SwitchManagerImpl implements ISwitchManager, propMap.put(tier.getName(), tier); addNodeProps(node, propMap); - log.info("Set Node {}'s Mode to {}", nodeId, cfgObject - .getMode()); + log.info("Set Node {}'s Mode to {}", nodeId, + cfgObject.getMode()); if (modeChange) { notifyModeChange(node, cfgObject.isProactive()); } } } catch (Exception e) { - log.debug("updateSwitchConfig: {}", e); + log.debug("updateSwitchConfig: {}", e.getMessage()); } } @@ -659,14 +659,14 @@ public class SwitchManagerImpl implements ISwitchManager, public Status addSpanConfig(SpanConfig conf) { // Valid config check if (!conf.isValidConfig()) { - String msg = "Invalid Span configuration"; + String msg = "Invalid Span configuration"; log.warn(msg); return new Status(StatusCode.BADREQUEST, msg); } // Presence check if (spanConfigList.containsKey(conf.hashCode())) { - return new Status(StatusCode.CONFLICT, "Same span config exists"); + return new Status(StatusCode.CONFLICT, "Same span config exists"); } // Update database and notify clients @@ -740,7 +740,8 @@ public class SwitchManagerImpl implements ISwitchManager, String nodeId = node.toString(); for (SwitchConfig conf : nodeConfigList.values()) { if (conf.getNodeId().equals(nodeId)) { - Property description = new Description(conf.getNodeDescription()); + Property description = new Description( + conf.getNodeDescription()); propMap.put(description.getName(), description); Property tier = new Tier(Integer.parseInt(conf.getTier())); propMap.put(tier.getName(), tier); @@ -756,10 +757,10 @@ public class SwitchManagerImpl implements ISwitchManager, // notify node listeners notifyNode(node, UpdateType.ADDED, propMap); - + // notify proactive mode forwarding if (proactiveForwarding) { - notifyModeChange(node, true); + notifyModeChange(node, true); } } @@ -873,7 +874,7 @@ public class SwitchManagerImpl implements ISwitchManager, Set nodes = getNodes(); if (nodes != null) { for (Node node : nodes) { - if (id.equals((Long)node.getID())) { + if (id.equals((Long) node.getID())) { return node; } } @@ -883,9 +884,12 @@ public class SwitchManagerImpl implements ISwitchManager, /* * Returns a copy of a list of properties for a given node - * + * * (non-Javadoc) - * @see org.opendaylight.controller.switchmanager.ISwitchManager#getNodeProps(org.opendaylight.controller.sal.core.Node) + * + * @see + * org.opendaylight.controller.switchmanager.ISwitchManager#getNodeProps + * (org.opendaylight.controller.sal.core.Node) */ @Override public Map getNodeProps(Node node) { @@ -902,8 +906,8 @@ public class SwitchManagerImpl implements ISwitchManager, } else { // get it from default container ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper - .getInstance(ISwitchManager.class, GlobalConstants.DEFAULT - .toString(), this); + .getInstance(ISwitchManager.class, + GlobalConstants.DEFAULT.toString(), this); return defaultSwitchManager.getNodeProps(node); } } @@ -929,8 +933,8 @@ public class SwitchManagerImpl implements ISwitchManager, public Status removeNodeProp(Node node, String propName) { Map propMap = getNodeProps(node); if (propMap != null) { - propMap.remove(propName); - this.nodeProps.put(node, propMap); + propMap.remove(propName); + this.nodeProps.put(node, propMap); } return new Status(StatusCode.SUCCESS, null); } @@ -948,8 +952,8 @@ public class SwitchManagerImpl implements ISwitchManager, Set nodeConnectorSet = new HashSet(); for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { - if (((Long) nodeConnector.getNode().getID()) - .longValue() != (Long) node.getID()) + if (((Long) nodeConnector.getNode().getID()).longValue() != (Long) node + .getID()) continue; if (isNodeConnectorEnabled(nodeConnector)) nodeConnectorSet.add(nodeConnector); @@ -965,8 +969,8 @@ public class SwitchManagerImpl implements ISwitchManager, Set nodeConnectorSet = new HashSet(); for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { - if (((Long) nodeConnector.getNode().getID()) - .longValue() != (Long) node.getID()) + if (((Long) nodeConnector.getNode().getID()).longValue() != (Long) node + .getID()) continue; nodeConnectorSet.add(nodeConnector); } @@ -992,7 +996,8 @@ public class SwitchManagerImpl implements ISwitchManager, } /* - * testing utility function which assumes we are dealing with OF Node nodeconnectors only + * testing utility function which assumes we are dealing with OF Node + * nodeconnectors only */ @SuppressWarnings("unused") private Set getEnabledNodeConnectorIds(Node node) { @@ -1023,8 +1028,8 @@ public class SwitchManagerImpl implements ISwitchManager, } else { // get it from default container ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper - .getInstance(ISwitchManager.class, GlobalConstants.DEFAULT - .toString(), this); + .getInstance(ISwitchManager.class, + GlobalConstants.DEFAULT.toString(), this); return defaultSwitchManager.getNodeConnectorProps(nodeConnector); } } @@ -1089,19 +1094,23 @@ public class SwitchManagerImpl implements ISwitchManager, /** * Adds a node connector and its property if any * - * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} - * @param propName name of {@link org.opendaylight.controller.sal.core.Property} + * @param nodeConnector + * {@link org.opendaylight.controller.sal.core.NodeConnector} + * @param propName + * name of {@link org.opendaylight.controller.sal.core.Property} * @return success or failed reason */ @Override - public Status addNodeConnectorProp(NodeConnector nodeConnector, Property prop) { + public Status addNodeConnectorProp(NodeConnector nodeConnector, + Property prop) { Map propMap = getNodeConnectorProps(nodeConnector); if (propMap == null) { propMap = new HashMap(); } - // Just add the nodeConnector if prop is not available (in a non-default container) + // Just add the nodeConnector if prop is not available (in a non-default + // container) if (prop == null) { nodeConnectorProps.put(nodeConnector, propMap); return new Status(StatusCode.SUCCESS, null); @@ -1129,16 +1138,19 @@ public class SwitchManagerImpl implements ISwitchManager, /** * Removes one property of a node connector * - * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} - * @param propName name of {@link org.opendaylight.controller.sal.core.Property} + * @param nodeConnector + * {@link org.opendaylight.controller.sal.core.NodeConnector} + * @param propName + * name of {@link org.opendaylight.controller.sal.core.Property} * @return success or failed reason */ @Override - public Status removeNodeConnectorProp(NodeConnector nodeConnector, String propName) { + public Status removeNodeConnectorProp(NodeConnector nodeConnector, + String propName) { Map propMap = getNodeConnectorProps(nodeConnector); if (propMap == null) { - /* Nothing to remove */ + /* Nothing to remove */ return new Status(StatusCode.SUCCESS, null); } @@ -1164,7 +1176,8 @@ public class SwitchManagerImpl implements ISwitchManager, /** * Removes all the properties of a node connector * - * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} + * @param nodeConnector + * {@link org.opendaylight.controller.sal.core.NodeConnector} * @return success or failed reason */ @Override @@ -1189,13 +1202,13 @@ public class SwitchManagerImpl implements ISwitchManager, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ void init(Component c) { Dictionary props = c.getServiceProperties(); if (props != null) { this.containerName = (String) props.get("containerName"); - log.trace("Running containerName:" + this.containerName); + log.trace("Running containerName: {}", this.containerName); } else { // In the Global instance case the containerName is empty this.containerName = ""; @@ -1207,20 +1220,19 @@ public class SwitchManagerImpl implements ISwitchManager, } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. - * + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * */ void destroy() { shutDown(); } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry - * + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * */ void start() { // OSGI console @@ -1228,8 +1240,7 @@ public class SwitchManagerImpl implements ISwitchManager, } /** - * Function called after registered the - * service in OSGi service registry. + * Function called after registered the service in OSGi service registry. */ void started() { // solicit for existing inventories @@ -1237,10 +1248,10 @@ public class SwitchManagerImpl implements ISwitchManager, } /** - * Function called by the dependency manager before the services - * exported by the component are unregistered, this will be - * followed by a "destroy ()" calls - * + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * */ void stop() { } @@ -1449,12 +1460,13 @@ public class SwitchManagerImpl implements ISwitchManager, return; } for (Node node : nodeSet) { - Description desc = ((Description) getNodeProp(node, Description.propertyName)); + Description desc = ((Description) getNodeProp(node, + Description.propertyName)); Tier tier = ((Tier) getNodeProp(node, Tier.TierPropName)); String nodeName = (desc == null) ? "" : desc.getValue(); int tierNum = (tier == null) ? 0 : tier.getValue(); - ci.println(node + " " + node.getType() - + " " + nodeName + " " + tierNum); + ci.println(node + " " + node.getType() + " " + + nodeName + " " + tierNum); } ci.println("Total number of Nodes: " + nodeSet.size()); } @@ -1555,12 +1567,12 @@ public class SwitchManagerImpl implements ISwitchManager, } ci.println(nodeConnector - + " " - + ((nodeConnectorName == null) ? "" - : nodeConnectorName) + "(" - + nodeConnector.getID() + ")"); + + " " + + ((nodeConnectorName == null) ? "" : nodeConnectorName) + + "(" + nodeConnector.getID() + ")"); } - ci.println("Total number of NodeConnectors: " + nodeConnectorSet.size()); + ci.println("Total number of NodeConnectors: " + + nodeConnectorSet.size()); } } @@ -1636,10 +1648,10 @@ public class SwitchManagerImpl implements ISwitchManager, @Override public boolean isSpecial(NodeConnector p) { - if (p.getType().equals(NodeConnectorIDType.CONTROLLER) || - p.getType().equals(NodeConnectorIDType.ALL) || - p.getType().equals(NodeConnectorIDType.SWSTACK) || - p.getType().equals(NodeConnectorIDType.HWPATH)) { + if (p.getType().equals(NodeConnectorIDType.CONTROLLER) + || p.getType().equals(NodeConnectorIDType.ALL) + || p.getType().equals(NodeConnectorIDType.SWSTACK) + || p.getType().equals(NodeConnectorIDType.HWPATH)) { return true; } return false; @@ -1723,58 +1735,61 @@ public class SwitchManagerImpl implements ISwitchManager, return saveSwitchConfig(); } - /** - * Creates a Name/Tier/Bandwidth Property object based on given property - * name and value. Other property types are not supported yet. - * - * @param propName Name of the Property - * @param propValue Value of the Property - * @return {@link org.opendaylight.controller.sal.core.Property} - */ - @Override - public Property createProperty(String propName, String propValue) { - if (propName == null) { - log.debug("propName is null"); - return null; - } - if (propValue == null) { - log.debug("propValue is null"); - return null; - } - - try { - if (propName.equalsIgnoreCase(Description.propertyName)) { - return new Description(propValue); - } else if (propName.equalsIgnoreCase(Tier.TierPropName)) { - int tier = Integer.parseInt(propValue); - return new Tier(tier); - } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) { - long bw = Long.parseLong(propValue); - return new Bandwidth(bw); - } else { - log.debug("Not able to create {} property", propName); - } - } catch (Exception e) { - log.debug(e.getMessage()); - } - - return null; - } - - @Override - public String getNodeDescription(Node node) { - // Check first if user configured a name + /** + * Creates a Name/Tier/Bandwidth Property object based on given property + * name and value. Other property types are not supported yet. + * + * @param propName + * Name of the Property + * @param propValue + * Value of the Property + * @return {@link org.opendaylight.controller.sal.core.Property} + */ + @Override + public Property createProperty(String propName, String propValue) { + if (propName == null) { + log.debug("propName is null"); + return null; + } + if (propValue == null) { + log.debug("propValue is null"); + return null; + } + + try { + if (propName.equalsIgnoreCase(Description.propertyName)) { + return new Description(propValue); + } else if (propName.equalsIgnoreCase(Tier.TierPropName)) { + int tier = Integer.parseInt(propValue); + return new Tier(tier); + } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) { + long bw = Long.parseLong(propValue); + return new Bandwidth(bw); + } else { + log.debug("Not able to create {} property", propName); + } + } catch (Exception e) { + log.debug("createProperty caught exception {}", e.getMessage()); + } + + return null; + } + + @Override + public String getNodeDescription(Node node) { + // Check first if user configured a name SwitchConfig config = getSwitchConfig(node.toString()); if (config != null) { - String configuredDesc = config.getNodeDescription(); - if (configuredDesc != null && !configuredDesc.isEmpty()) { - return configuredDesc; - } + String configuredDesc = config.getNodeDescription(); + if (configuredDesc != null && !configuredDesc.isEmpty()) { + return configuredDesc; + } } - + // No name configured by user, get the node advertised name - Description desc = (Description) getNodeProp(node, Description.propertyName); - return (desc == null /*|| desc.getValue().equalsIgnoreCase("none")*/) ? - "" : desc.getValue(); + Description desc = (Description) getNodeProp(node, + Description.propertyName); + return (desc == null /* || desc.getValue().equalsIgnoreCase("none") */) ? "" + : desc.getValue(); } }