Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
index f3568c1..798440a 100644
--- a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
@@ -1,23 +1,78 @@
package org.onlab.onos.of.controller;
+import java.util.List;
+
+import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
/**
- * Abstract model of an OpenFlow Switch.
- *
+ * Represents to provider facing side of a switch.
*/
public interface OpenFlowSwitch {
/**
- * Writes the message to this switch.
+ * Writes the message to the driver.
*
* @param msg the message to write
*/
public void sendMsg(OFMessage msg);
/**
+ * Writes to the OFMessage list to the driver.
+ *
+ * @param msgs the messages to be written
+ */
+ public void sendMsg(List<OFMessage> msgs);
+
+ /**
* Handle a message from the switch.
* @param fromSwitch the message to handle
*/
public void handleMessage(OFMessage fromSwitch);
+
+ /**
+ * Sets the role for this switch.
+ * @param role the role to set.
+ */
+ public void setRole(RoleState role);
+
+ /**
+ * Fetch the role for this switch.
+ * @return the role.
+ */
+ public RoleState getRole();
+
+ /**
+ * Fetches the ports of this switch.
+ * @return unmodifiable list of the ports.
+ */
+ public List<OFPortDesc> getPorts();
+
+ /**
+ * Provides the factory for this OF version.
+ * @return OF version specific factory.
+ */
+ public OFFactory factory();
+
+ /**
+ * Gets a string version of the ID for this switch.
+ *
+ * @return string version of the ID
+ */
+ public String getStringId();
+
+ /**
+ * Gets the datapathId of the switch.
+ *
+ * @return the switch dpid in long format
+ */
+ public long getId();
+
+ /**
+ * Disconnects the switch by closing the TCP connection. Results in a call
+ * to the channel handler's channelDisconnected method for cleanup
+ */
+ public void disconnectSwitch();
+
}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java b/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
index 527a91c..db8efd1 100644
--- a/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
@@ -21,3 +21,5 @@
}
+
+
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/AbstractOpenFlowSwitch.java
similarity index 64%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/AbstractOpenFlowSwitch.java
index 534daa0..ce6365a 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/AbstractOpenFlowSwitch.java
@@ -15,7 +15,7 @@
* under the License.
**/
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
import java.io.IOException;
import java.util.Collections;
@@ -24,11 +24,7 @@
import org.jboss.netty.channel.Channel;
import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.OpenFlowSwitch;
import org.onlab.onos.of.controller.RoleState;
-import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
-import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleRecvStatus;
-import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleReplyInfo;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFExperimenter;
@@ -43,19 +39,22 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
+/**
+ * An abstract representation of an OpenFlow switch. Can be extended by others
+ * to serve as a base for their vendor specific representation of a switch.
+ */
+public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
private static Logger log =
LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
protected Channel channel;
- protected boolean startDriverHandshakeCalled = false;
private boolean connected;
- private Dpid dpid;
- private OpenFlowSwitchAgent agent;
- private AtomicInteger xidCounter = new AtomicInteger(0);
+ protected boolean startDriverHandshakeCalled = false;
+ private final Dpid dpid;
+ private OpenFlowAgent agent;
+ private final AtomicInteger xidCounter = new AtomicInteger(0);
private OFVersion ofVersion;
@@ -63,12 +62,17 @@
protected boolean tableFull;
- private final RoleManager roleMan = new RoleManager(this);
+ private RoleHandler roleMan;
protected RoleState role;
protected OFFeaturesReply features;
+ protected OFDescStatsReply desc;
+ /**
+ * Given a dpid build this switch.
+ * @param dp the dpid
+ */
protected AbstractOpenFlowSwitch(Dpid dp) {
this.dpid = dp;
}
@@ -77,59 +81,38 @@
// Channel related
//************************
- /**
- * Disconnects the switch by closing the TCP connection. Results in a call
- * to the channel handler's channelDisconnected method for cleanup
- * @throws IOException
- */
+ @Override
public final void disconnectSwitch() {
this.channel.close();
}
- /**
- * Writes to the OFMessage to the output stream.
- *
- * @param m the message to be written
- */
- public abstract void sendMsg(OFMessage m);
-
- /**
- * Writes to the OFMessage list to the output stream.
- *
- * @param msgs the messages to be written
- */
- public void write(List<OFMessage> msgs) {
- this.channel.write(msgs);
+ @Override
+ public final void sendMsg(OFMessage m) {
+ this.write(m);
}
+ @Override
+ public final void sendMsg(List<OFMessage> msgs) {
+ this.write(msgs);
+ }
- /**
- * Checks if the switch is still connected.
- * Only call while holding processMessageLock
- *
- * @return whether the switch is still disconnected
- */
+ @Override
+ public abstract void write(OFMessage msg);
+
+ @Override
+ public abstract void write(List<OFMessage> msgs);
+
+ @Override
public final boolean isConnected() {
return this.connected;
}
- /**
- * Sets whether the switch is connected.
- * Only call while holding modifySwitchLock
- *
- * @param connected whether the switch is connected
- */
- final void setConnected(boolean connected) {
+ @Override
+ public final void setConnected(boolean connected) {
this.connected = connected;
};
- /**
- * Sets the Netty Channel this switch instance is associated with.
- * <p>
- * Called immediately after instantiation
- *
- * @param channel the channel
- */
+ @Override
public final void setChannel(Channel channel) {
this.channel = channel;
};
@@ -138,41 +121,32 @@
// Switch features related
//************************
- /**
- * Gets the datapathId of the switch.
- *
- * @return the switch buffers
- */
+ @Override
public final long getId() {
return this.dpid.value();
};
- /**
- * Gets a string version of the ID for this switch.
- *
- * @return string version of the ID
- */
+ @Override
public final String getStringId() {
return this.dpid.toString();
}
+ @Override
public final void setOFVersion(OFVersion ofV) {
this.ofVersion = ofV;
}
- void setTableFull(boolean full) {
+ @Override
+ public void setTableFull(boolean full) {
this.tableFull = full;
}
+ @Override
public void setFeaturesReply(OFFeaturesReply featuresReply) {
this.features = featuresReply;
}
- /**
- * Let peoeple know if you support Nicira style role requests.
- *
- * @return support Nicira roles or not.
- */
+ @Override
public abstract Boolean supportNxRole();
//************************
@@ -183,65 +157,80 @@
*
* @param m the actual message
*/
+ @Override
public final void handleMessage(OFMessage m) {
this.agent.processMessage(m);
}
+ @Override
public RoleState getRole() {
return role;
};
- final boolean addConnectedSwitch() {
- return this.agent.addConnectedSwitch(this.getId(), this);
+ @Override
+ public final boolean connectSwitch() {
+ return this.agent.addConnectedSwitch(dpid, this);
}
- final boolean addActivatedMasterSwitch() {
- return this.agent.addActivatedMasterSwitch(this.getId(), this);
+ @Override
+ public final boolean activateMasterSwitch() {
+ return this.agent.addActivatedMasterSwitch(dpid, this);
}
- final boolean addActivatedEqualSwitch() {
- return this.agent.addActivatedEqualSwitch(this.getId(), this);
+ @Override
+ public final boolean activateEqualSwitch() {
+ return this.agent.addActivatedEqualSwitch(dpid, this);
}
- final void transitionToEqualSwitch() {
- this.agent.transitionToEqualSwitch(this.getId());
+ @Override
+ public final void transitionToEqualSwitch() {
+ this.agent.transitionToEqualSwitch(dpid);
}
- final void transitionToMasterSwitch() {
- this.agent.transitionToMasterSwitch(this.getId());
+ @Override
+ public final void transitionToMasterSwitch() {
+ this.agent.transitionToMasterSwitch(dpid);
}
- final void removeConnectedSwitch() {
- this.agent.removeConnectedSwitch(this.getId());
+ @Override
+ public final void removeConnectedSwitch() {
+ this.agent.removeConnectedSwitch(dpid);
}
- protected OFFactory factory() {
+ @Override
+ public OFFactory factory() {
return OFFactories.getFactory(ofVersion);
}
+ @Override
public void setPortDescReply(OFPortDescStatsReply portDescReply) {
this.ports = portDescReply;
}
+ @Override
public abstract void startDriverHandshake();
+ @Override
public abstract boolean isDriverHandshakeComplete();
+ @Override
public abstract void processDriverHandshakeMessage(OFMessage m);
+ @Override
public void setRole(RoleState role) {
try {
if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
this.role = role;
}
} catch (IOException e) {
- log.error("Unable to write to switch {}.", this.dpid);
+ log.error("Unable to write to switch {}.", this.dpid);
}
}
// Role Handling
- void handleRole(OFMessage m) throws SwitchStateException {
+ @Override
+ public void handleRole(OFMessage m) throws SwitchStateException {
RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
@@ -254,7 +243,8 @@
}
}
- void handleNiciraRole(OFMessage m) throws SwitchStateException {
+ @Override
+ public void handleNiciraRole(OFMessage m) throws SwitchStateException {
RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
if (r == null) {
// The message wasn't really a Nicira role reply. We just
@@ -274,7 +264,8 @@
}
}
- boolean handleRoleError(OFErrorMsg error) {
+ @Override
+ public boolean handleRoleError(OFErrorMsg error) {
try {
return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
} catch (SwitchStateException e) {
@@ -283,25 +274,39 @@
return true;
}
- void reassertRole() {
+ @Override
+ public void reassertRole() {
if (this.getRole() == RoleState.MASTER) {
this.setRole(RoleState.MASTER);
}
}
- void setAgent(OpenFlowSwitchAgent ag) {
- this.agent = ag;
+ @Override
+ public final void setAgent(OpenFlowAgent ag) {
+ if (this.agent == null) {
+ this.agent = ag;
+ }
}
- public void setSwitchDescription(OFDescStatsReply desc) {
- // TODO Auto-generated method stub
+ @Override
+ public final void setRoleHandler(RoleHandler roleHandler) {
+ if (this.roleMan == null) {
+ this.roleMan = roleHandler;
+ }
}
- protected int getNextTransactionId() {
+ @Override
+ public void setSwitchDescription(OFDescStatsReply d) {
+ this.desc = d;
+ }
+
+ @Override
+ public int getNextTransactionId() {
return this.xidCounter.getAndIncrement();
}
- protected List<OFPortDesc> getPorts() {
+ @Override
+ public List<OFPortDesc> getPorts() {
return Collections.unmodifiableList(ports.getEntries());
}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowAgent.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowAgent.java
new file mode 100644
index 0000000..a0f64e2
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowAgent.java
@@ -0,0 +1,75 @@
+package org.onlab.onos.of.controller.driver;
+
+import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+/**
+ * Responsible for keeping track of the current set of switches
+ * connected to the system. As well as whether they are in Master
+ * role or not.
+ *
+ */
+public interface OpenFlowAgent {
+
+ /**
+ * Add a switch that has just connected to the system.
+ * @param dpid the dpid to add
+ * @param sw the actual switch object.
+ * @return true if added, false otherwise.
+ */
+ public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw);
+
+ /**
+ * Checks if the activation for this switch is valid.
+ * @param dpid the dpid to check
+ * @return true if valid, false otherwise
+ */
+ public boolean validActivation(Dpid dpid);
+
+ /**
+ * Called when a switch is activated, with this controller's role as MASTER.
+ * @param dpid the dpid to add.
+ * @param sw the actual switch
+ * @return true if added, false otherwise.
+ */
+ public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw);
+
+ /**
+ * Called when a switch is activated, with this controller's role as EQUAL.
+ * @param dpid the dpid to add.
+ * @param sw the actual switch
+ * @return true if added, false otherwise.
+ */
+ public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw);
+
+ /**
+ * Called when this controller's role for a switch transitions from equal
+ * to master. For 1.0 switches, we internally refer to the role 'slave' as
+ * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
+ * @param dpid the dpid to transistion.
+ */
+ public void transitionToMasterSwitch(Dpid dpid);
+
+ /**
+ * Called when this controller's role for a switch transitions to equal.
+ * For 1.0 switches, we internally refer to the role 'slave' as
+ * 'equal'.
+ * @param dpid the dpid to transistion.
+ */
+ public void transitionToEqualSwitch(Dpid dpid);
+
+ /**
+ * Clear all state in controller switch maps for a switch that has
+ * disconnected from the local controller. Also release control for
+ * that switch from the global repository. Notify switch listeners.
+ * @param dpid the dpid to remove.
+ */
+ public void removeConnectedSwitch(Dpid dpid);
+
+ /**
+ * Process a message coming from a switch.
+ * @param m the message to process
+ */
+ public void processMessage(OFMessage m);
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriver.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriver.java
new file mode 100644
index 0000000..be99973
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriver.java
@@ -0,0 +1,197 @@
+package org.onlab.onos.of.controller.driver;
+
+import java.util.List;
+
+import org.jboss.netty.channel.Channel;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+/**
+ * Represents the driver side of an OpenFlow switch.
+ * This interface should never be exposed to consumers.
+ *
+ */
+public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
+
+ /**
+ * Sets the OpenFlow agent to be used. This method
+ * can only be called once.
+ * @param agent the agent to set.
+ */
+ public void setAgent(OpenFlowAgent agent);
+
+ /**
+ * Sets the Role handler object.
+ * This method can only be called once.
+ * @param roleHandler the roleHandler class
+ */
+ public void setRoleHandler(RoleHandler roleHandler);
+
+ /**
+ * Reasserts this controllers role to the switch.
+ * Useful in cases where the switch no longer agrees
+ * that this controller has the role it claims.
+ */
+ public void reassertRole();
+
+ /**
+ * Handle the situation where the role request triggers an error.
+ * @param error the error to handle.
+ * @return true if handled, false if not.
+ */
+ public boolean handleRoleError(OFErrorMsg error);
+
+ /**
+ * If this driver know of Nicira style role messages, these should
+ * be handled here.
+ * @param m the role message to handle.
+ * @throws SwitchStateException if the message received was
+ * not a nicira role or was malformed.
+ */
+ public void handleNiciraRole(OFMessage m) throws SwitchStateException;
+
+ /**
+ * Handle OF 1.x (where x > 0) role messages.
+ * @param m the role message to handle
+ * @throws SwitchStateException if the message received was
+ * not a nicira role or was malformed.
+ */
+ public void handleRole(OFMessage m) throws SwitchStateException;
+
+ /**
+ * Starts the driver specific handshake process.
+ */
+ public void startDriverHandshake();
+
+ /**
+ * Checks whether the driver specific handshake is complete.
+ * @return true is finished, false if not.
+ */
+ public boolean isDriverHandshakeComplete();
+
+ /**
+ * Process a message during the driver specific handshake.
+ * @param m the message to process.
+ */
+ public void processDriverHandshakeMessage(OFMessage m);
+
+ /**
+ * Announce to the OpenFlow agent that this switch has connected.
+ * @return true if successful, false if duplicate switch.
+ */
+ public boolean connectSwitch();
+
+ /**
+ * Activate this MASTER switch-controller relationship in the OF agent.
+ * @return true is successful, false is switch has not
+ * connected or is unknown to the system.
+ */
+ public boolean activateMasterSwitch();
+
+ /**
+ * Activate this EQUAL switch-controller relationship in the OF agent.
+ * @return true is successful, false is switch has not
+ * connected or is unknown to the system.
+ */
+ public boolean activateEqualSwitch();
+
+ /**
+ * Transition this switch-controller relationship to an EQUAL state.
+ */
+ public void transitionToEqualSwitch();
+
+ /**
+ * Transition this switch-controller relationship to an Master state.
+ */
+ public void transitionToMasterSwitch();
+
+ /**
+ * Remove this switch from the openflow agent.
+ */
+ public void removeConnectedSwitch();
+
+ /**
+ * Sets the ports on this switch.
+ * @param portDescReply the port set and descriptions
+ */
+ public void setPortDescReply(OFPortDescStatsReply portDescReply);
+
+ /**
+ * Sets the features reply for this switch.
+ * @param featuresReply the features to set.
+ */
+ public void setFeaturesReply(OFFeaturesReply featuresReply);
+
+ /**
+ * Sets the switch description.
+ * @param desc the descriptions
+ */
+ public void setSwitchDescription(OFDescStatsReply desc);
+
+ /**
+ * Gets the next transaction id to use.
+ * @return the xid
+ */
+ public int getNextTransactionId();
+
+
+ /**
+ * Does this switch support Nicira Role messages.
+ * @return true if supports, false otherwise.
+ */
+ public Boolean supportNxRole();
+
+ /**
+ * Sets the OF version for this switch.
+ * @param ofV the version to set.
+ */
+ public void setOFVersion(OFVersion ofV);
+
+ /**
+ * Sets this switch has having a full flowtable.
+ * @param full true if full, false otherswise.
+ */
+ public void setTableFull(boolean full);
+
+ /**
+ * Sets the associated Netty channel for this switch.
+ * @param channel the Netty channel
+ */
+ public void setChannel(Channel channel);
+
+ /**
+ * Sets whether the switch is connected.
+ *
+ * @param connected whether the switch is connected
+ */
+ public void setConnected(boolean connected);
+
+ /**
+ * Checks if the switch is still connected.
+ *
+ * @return whether the switch is still connected
+ */
+ public boolean isConnected();
+
+ /**
+ * Writes the message to the output stream
+ * in a driver specific manner.
+ *
+ * @param msg the message to write
+ */
+ public void write(OFMessage msg);
+
+ /**
+ * Writes to the OFMessage list to the output stream
+ * in a driver specific manner.
+ *
+ * @param msgs the messages to be written
+ */
+ public void write(List<OFMessage> msgs);
+
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriverFactory.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriverFactory.java
new file mode 100644
index 0000000..4e84d28
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriverFactory.java
@@ -0,0 +1,24 @@
+package org.onlab.onos.of.controller.driver;
+
+import org.onlab.onos.of.controller.Dpid;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+/**
+ * Switch factory which returns concrete switch objects for the
+ * physical openflow switch in use.
+ *
+ */
+public interface OpenFlowSwitchDriverFactory {
+
+
+ /**
+ * Constructs the real openflow switch representation.
+ * @param dpid the dpid for this switch.
+ * @param desc its description.
+ * @param ofv the OF version in use
+ * @return the openflow switch representation.
+ */
+ public OpenFlowSwitchDriver getOFSwitchImpl(Dpid dpid,
+ OFDescStatsReply desc, OFVersion ofv);
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleHandler.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleHandler.java
new file mode 100644
index 0000000..ac1e1ab
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleHandler.java
@@ -0,0 +1,95 @@
+package org.onlab.onos.of.controller.driver;
+
+import java.io.IOException;
+
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFRoleReply;
+
+/**
+ * Role handling.
+ *
+ */
+public interface RoleHandler {
+
+ /**
+ * Extract the role from an OFVendor message.
+ *
+ * Extract the role from an OFVendor message if the message is a
+ * Nicira role reply. Otherwise return null.
+ *
+ * @param experimenterMsg The vendor message to parse.
+ * @return The role in the message if the message is a Nicira role
+ * reply, null otherwise.
+ * @throws SwitchStateException If the message is a Nicira role reply
+ * but the numeric role value is unknown.
+ */
+ public RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
+ throws SwitchStateException;
+
+ /**
+ * Send a role request with the given role to the switch and update
+ * the pending request and timestamp.
+ * Sends an OFPT_ROLE_REQUEST to an OF1.3 switch, OR
+ * Sends an NX_ROLE_REQUEST to an OF1.0 switch if configured to support it
+ * in the IOFSwitch driver. If not supported, this method sends nothing
+ * and returns 'false'. The caller should take appropriate action.
+ *
+ * One other optimization we do here is that for OF1.0 switches with
+ * Nicira role message support, we force the Role.EQUAL to become
+ * Role.SLAVE, as there is no defined behavior for the Nicira role OTHER.
+ * We cannot expect it to behave like SLAVE. We don't have this problem with
+ * OF1.3 switches, because Role.EQUAL is well defined and we can simulate
+ * SLAVE behavior by using ASYNC messages.
+ *
+ * @param role
+ * @throws IOException
+ * @returns false if and only if the switch does not support role-request
+ * messages, according to the switch driver; true otherwise.
+ */
+ public boolean sendRoleRequest(RoleState role, RoleRecvStatus exp)
+ throws IOException;
+
+ /**
+ * Extract the role information from an OF1.3 Role Reply Message.
+ * @param h
+ * @param rrmsg
+ * @return RoleReplyInfo object
+ * @throws SwitchStateException
+ */
+ public RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
+ throws SwitchStateException;
+
+ /**
+ * Deliver a received role reply.
+ *
+ * Check if a request is pending and if the received reply matches the
+ * the expected pending reply (we check both role and xid) we set
+ * the role for the switch/channel.
+ *
+ * If a request is pending but doesn't match the reply we ignore it, and
+ * return
+ *
+ * If no request is pending we disconnect with a SwitchStateException
+ *
+ * @param rri information about role-reply in format that
+ * controller can understand.
+ * @throws SwitchStateException if no request is pending
+ */
+ public RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
+ throws SwitchStateException;
+
+
+ /**
+ * Called if we receive an error message. If the xid matches the
+ * pending request we handle it otherwise we ignore it.
+ *
+ * Note: since we only keep the last pending request we might get
+ * error messages for earlier role requests that we won't be able
+ * to handle
+ */
+ public RoleRecvStatus deliverError(OFErrorMsg error)
+ throws SwitchStateException;
+
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleRecvStatus.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleRecvStatus.java
new file mode 100644
index 0000000..0a10978
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleRecvStatus.java
@@ -0,0 +1,37 @@
+package org.onlab.onos.of.controller.driver;
+
+/**
+ * When we remove a pending role request we use this enum to indicate how we
+ * arrived at the decision. When we send a role request to the switch, we
+ * also use this enum to indicate what we expect back from the switch, so the
+ * role changer can match the reply to our expectation.
+ */
+public enum RoleRecvStatus {
+ /** The switch returned an error indicating that roles are not.
+ * supported*/
+ UNSUPPORTED,
+ /** The request timed out. */
+ NO_REPLY,
+ /** The reply was old, there is a newer request pending. */
+ OLD_REPLY,
+ /**
+ * The reply's role matched the role that this controller set in the
+ * request message - invoked either initially at startup or to reassert
+ * current role.
+ */
+ MATCHED_CURRENT_ROLE,
+ /**
+ * The reply's role matched the role that this controller set in the
+ * request message - this is the result of a callback from the
+ * global registry, followed by a role request sent to the switch.
+ */
+ MATCHED_SET_ROLE,
+ /**
+ * The reply's role was a response to the query made by this controller.
+ */
+ REPLY_QUERY,
+ /** We received a role reply message from the switch
+ * but the expectation was unclear, or there was no expectation.
+ */
+ OTHER_EXPECTATION,
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleReplyInfo.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleReplyInfo.java
new file mode 100644
index 0000000..cc3c483
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/RoleReplyInfo.java
@@ -0,0 +1,27 @@
+package org.onlab.onos.of.controller.driver;
+
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.types.U64;
+
+/**
+ * Helper class returns role reply information in the format understood
+ * by the controller.
+ */
+public class RoleReplyInfo {
+ private final RoleState role;
+ private final U64 genId;
+ private final long xid;
+
+ public RoleReplyInfo(RoleState role, U64 genId, long xid) {
+ this.role = role;
+ this.genId = genId;
+ this.xid = xid;
+ }
+ public RoleState getRole() { return role; }
+ public U64 getGenId() { return genId; }
+ public long getXid() { return xid; }
+ @Override
+ public String toString() {
+ return "[Role:" + role + " GenId:" + genId + " Xid:" + xid + "]";
+ }
+}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeAlreadyStarted.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
similarity index 86%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeAlreadyStarted.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
index 53227aa..16ed93a 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeAlreadyStarted.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
/**
* Thrown when IOFSwitch.startDriverHandshake() is called more than once.
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeCompleted.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeCompleted.java
similarity index 91%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeCompleted.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeCompleted.java
index ba792e5..1c6dac9 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeCompleted.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeCompleted.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
import org.projectfloodlight.openflow.protocol.OFMessage;
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeException.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeException.java
similarity index 91%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeException.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeException.java
index 49fdead..1c9a710 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeException.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeException.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
/**
* Base class for exception thrown by switch driver sub-handshake processing.
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeNotStarted.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeNotStarted.java
similarity index 87%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeNotStarted.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeNotStarted.java
index 72b17dc..0f34b0e 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeNotStarted.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeNotStarted.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
/**
* Thrown when a switch driver's sub-handshake has not been started but an
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeStateException.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeStateException.java
similarity index 88%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeStateException.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeStateException.java
index 191d1bb..09e737e 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeStateException.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeStateException.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
/**
* Thrown when a switch driver's sub-handshake state-machine receives an
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchStateException.java b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchStateException.java
similarity index 96%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchStateException.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchStateException.java
index d82e917..55b12de 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchStateException.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchStateException.java
@@ -15,7 +15,7 @@
* under the License.
**/
-package org.onlab.onos.of.controller.impl.internal;
+package org.onlab.onos.of.controller.driver;
/**
* This exception indicates an error or unexpected message during
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
index b88a9ec..ab9315f 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
@@ -30,9 +30,10 @@
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.driver.OpenFlowAgent;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
-import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
import org.onlab.onos.of.drivers.DriverManager;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactories;
@@ -74,7 +75,7 @@
// Flag to always flush flow table on switch reconnect (HA or otherwise)
protected boolean alwaysClearFlowsOnSwAdd = false;
- private OpenFlowSwitchAgent agent;
+ private OpenFlowAgent agent;
// Perf. related configuration
protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
@@ -120,17 +121,17 @@
* Tell controller that we're ready to accept switches loop.
*/
@LogMessageDocs({
- @LogMessageDoc(message = "Listening for switch connections on {address}",
- explanation = "The controller is ready and listening for new" +
- " switch connections"),
- @LogMessageDoc(message = "Storage exception in controller " +
- "updates loop; terminating process",
- explanation = ERROR_DATABASE,
- recommendation = LogMessageDoc.CHECK_CONTROLLER),
- @LogMessageDoc(level = "ERROR",
- message = "Exception in controller updates loop",
- explanation = "Failed to dispatch controller event",
- recommendation = LogMessageDoc.GENERIC_ACTION)
+ @LogMessageDoc(message = "Listening for switch connections on {address}",
+ explanation = "The controller is ready and listening for new" +
+ " switch connections"),
+ @LogMessageDoc(message = "Storage exception in controller " +
+ "updates loop; terminating process",
+ explanation = ERROR_DATABASE,
+ recommendation = LogMessageDoc.CHECK_CONTROLLER),
+ @LogMessageDoc(level = "ERROR",
+ message = "Exception in controller updates loop",
+ explanation = "Failed to dispatch controller event",
+ recommendation = LogMessageDoc.GENERIC_ACTION)
})
public void run() {
@@ -221,15 +222,16 @@
* @param desc
* @return switch instance
*/
- protected AbstractOpenFlowSwitch getOFSwitchInstance(long dpid,
+ protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
OFDescStatsReply desc, OFVersion ofv) {
- AbstractOpenFlowSwitch sw = DriverManager.getOFSwitchImpl(new Dpid(dpid),
+ OpenFlowSwitchDriver sw = DriverManager.getSwitch(new Dpid(dpid),
desc, ofv);
sw.setAgent(agent);
+ sw.setRoleHandler(new RoleManager(sw));
return sw;
}
- public void start(OpenFlowSwitchAgent ag) {
+ public void start(OpenFlowAgent ag) {
log.info("Initialising OpenFlow Lib and IO");
this.agent = ag;
this.init(new HashMap<String, String>());
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
index 4b2f7c3..035c4ca 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
@@ -1,5 +1,6 @@
package org.onlab.onos.of.controller.impl.internal;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFVersion;
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
index 23bc994..768362f 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
@@ -18,6 +18,8 @@
import org.jboss.netty.handler.timeout.IdleStateEvent;
import org.jboss.netty.handler.timeout.ReadTimeoutException;
import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
+import org.onlab.onos.of.controller.driver.SwitchStateException;
import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
import org.projectfloodlight.openflow.exceptions.OFParseError;
@@ -66,7 +68,7 @@
class OFChannelHandler extends IdleStateAwareChannelHandler {
private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
private final Controller controller;
- private AbstractOpenFlowSwitch sw;
+ private OpenFlowSwitchDriver sw;
private long thisdpid; // channelHandler cached value of connected switch id
private Channel channel;
// State needs to be volatile because the HandshakeTimeoutHandler
@@ -413,7 +415,7 @@
OFDescStatsReply drep = (OFDescStatsReply) m;
// Here is where we differentiate between different kinds of switches
h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion);
- boolean success = h.sw.addConnectedSwitch();
+ boolean success = h.sw.connectSwitch();
if (!success) {
disconnectDuplicate(h);
return;
@@ -431,7 +433,7 @@
//Put switch in EQUAL mode until we hear back from the global registry
log.debug("Setting new switch {} to EQUAL and sending Role request",
h.sw.getStringId());
- h.sw.addActivatedEqualSwitch();
+ h.sw.activateEqualSwitch();
//h.setSwitchRole(RoleState.EQUAL);
h.setSwitchRole(RoleState.MASTER);
h.sw.startDriverHandshake();
@@ -489,8 +491,8 @@
}
}
} else {
- if (m.getType() == OFType.EXPERIMENTER &&
- ((OFExperimenter) m).getExperimenter() ==
+ if (m.getType() == OFType.EXPERIMENTER &&
+ ((OFExperimenter) m).getExperimenter() ==
RoleManager.NICIRA_EXPERIMENTER) {
h.sw.handleNiciraRole(m);
} else {
@@ -848,8 +850,8 @@
processOFQueueGetConfigReply(h, (OFQueueGetConfigReply) m);
break;
case STATS_REPLY: // multipart_reply in 1.3
- processOFStatisticsReply(h, (OFStatsReply) m);
- break;
+ processOFStatisticsReply(h, (OFStatsReply) m);
+ break;
case EXPERIMENTER:
processOFExperimenter(h, (OFExperimenter) m);
break;
@@ -916,12 +918,12 @@
}
OFFactory factory = (h.ofVersion == OFVersion.OF_13) ?
h.controller.getOFMessageFactory13() : h.controller.getOFMessageFactory10();
- OFEchoReply reply = factory
- .buildEchoReply()
- .setXid(m.getXid())
- .setData(m.getData())
- .build();
- h.channel.write(Collections.singletonList(reply));
+ OFEchoReply reply = factory
+ .buildEchoReply()
+ .setXid(m.getXid())
+ .setData(m.getData())
+ .build();
+ h.channel.write(Collections.singletonList(reply));
}
void processOFEchoReply(OFChannelHandler h, OFEchoReply m)
@@ -1044,41 +1046,41 @@
message = "Disconnecting switch {switch} due to read timeout",
explanation = "The connected switch has failed to send any "
+ "messages or respond to echo requests",
- recommendation = LogMessageDoc.CHECK_SWITCH),
+ recommendation = LogMessageDoc.CHECK_SWITCH),
@LogMessageDoc(level = "ERROR",
- message = "Disconnecting switch {switch}: failed to "
- + "complete handshake",
- explanation = "The switch did not respond correctly "
- + "to handshake messages",
- recommendation = LogMessageDoc.CHECK_SWITCH),
- @LogMessageDoc(level = "ERROR",
- message = "Disconnecting switch {switch} due to IO Error: {}",
- explanation = "There was an error communicating with the switch",
- recommendation = LogMessageDoc.CHECK_SWITCH),
- @LogMessageDoc(level = "ERROR",
- message = "Disconnecting switch {switch} due to switch "
- + "state error: {error}",
- explanation = "The switch sent an unexpected message",
- recommendation = LogMessageDoc.CHECK_SWITCH),
- @LogMessageDoc(level = "ERROR",
- message = "Disconnecting switch {switch} due to "
- + "message parse failure",
- explanation = "Could not parse a message from the switch",
- recommendation = LogMessageDoc.CHECK_SWITCH),
- @LogMessageDoc(level = "ERROR",
- message = "Terminating controller due to storage exception",
- explanation = Controller.ERROR_DATABASE,
- recommendation = LogMessageDoc.CHECK_CONTROLLER),
- @LogMessageDoc(level = "ERROR",
- message = "Could not process message: queue full",
- explanation = "OpenFlow messages are arriving faster than "
- + "the controller can process them.",
- recommendation = LogMessageDoc.CHECK_CONTROLLER),
- @LogMessageDoc(level = "ERROR",
- message = "Error while processing message "
- + "from switch {switch} {cause}",
- explanation = "An error occurred processing the switch message",
- recommendation = LogMessageDoc.GENERIC_ACTION)
+ message = "Disconnecting switch {switch}: failed to "
+ + "complete handshake",
+ explanation = "The switch did not respond correctly "
+ + "to handshake messages",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to IO Error: {}",
+ explanation = "There was an error communicating with the switch",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to switch "
+ + "state error: {error}",
+ explanation = "The switch sent an unexpected message",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to "
+ + "message parse failure",
+ explanation = "Could not parse a message from the switch",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Terminating controller due to storage exception",
+ explanation = Controller.ERROR_DATABASE,
+ recommendation = LogMessageDoc.CHECK_CONTROLLER),
+ @LogMessageDoc(level = "ERROR",
+ message = "Could not process message: queue full",
+ explanation = "OpenFlow messages are arriving faster than "
+ + "the controller can process them.",
+ recommendation = LogMessageDoc.CHECK_CONTROLLER),
+ @LogMessageDoc(level = "ERROR",
+ message = "Error while processing message "
+ + "from switch {switch} {cause}",
+ explanation = "An error occurred processing the switch message",
+ recommendation = LogMessageDoc.GENERIC_ACTION)
})
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
index f846e65..b7ba4c7 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
@@ -15,8 +15,9 @@
import org.onlab.onos.of.controller.OpenFlowSwitchListener;
import org.onlab.onos.of.controller.PacketListener;
import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.OpenFlowAgent;
import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,12 +28,12 @@
private static final Logger log =
LoggerFactory.getLogger(OpenFlowControllerImpl.class);
- protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches =
- new ConcurrentHashMap<Long, OpenFlowSwitch>();
- protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches =
- new ConcurrentHashMap<Long, OpenFlowSwitch>();
- protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches =
- new ConcurrentHashMap<Long, OpenFlowSwitch>();
+ protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
+ new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
+ protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
+ new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
+ protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
+ new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
protected ArrayList<OpenFlowSwitchListener> ofEventListener =
@@ -118,12 +119,13 @@
((AbstractOpenFlowSwitch) getSwitch(dpid)).setRole(role);
}
- public class OpenFlowSwitchAgent {
+ public class OpenFlowSwitchAgent implements OpenFlowAgent {
private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
- private Lock switchLock = new ReentrantLock();
+ private final Lock switchLock = new ReentrantLock();
- public boolean addConnectedSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+ @Override
+ public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
if (connectedSwitches.get(dpid) != null) {
log.error("Trying to add connectedSwitch but found a previous "
+ "value for dpid: {}", dpid);
@@ -132,17 +134,18 @@
log.error("Added switch {}", dpid);
connectedSwitches.put(dpid, sw);
for (OpenFlowSwitchListener l : ofEventListener) {
- l.switchAdded(new Dpid(dpid));
+ l.switchAdded(dpid);
}
return true;
}
}
- private boolean validActivation(long dpid) {
+ @Override
+ public boolean validActivation(Dpid dpid) {
if (connectedSwitches.get(dpid) == null) {
log.error("Trying to activate switch but is not in "
+ "connected switches: dpid {}. Aborting ..",
- HexString.toHexString(dpid));
+ dpid);
return false;
}
if (activeMasterSwitches.get(dpid) != null ||
@@ -150,18 +153,17 @@
log.error("Trying to activate switch but it is already "
+ "activated: dpid {}. Found in activeMaster: {} "
+ "Found in activeEqual: {}. Aborting ..", new Object[] {
- HexString.toHexString(dpid),
+ dpid,
(activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
- (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
+ (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
return false;
}
return true;
}
- /**
- * Called when a switch is activated, with this controller's role as MASTER.
- */
- protected boolean addActivatedMasterSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+
+ @Override
+ public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
switchLock.lock();
try {
if (!validActivation(dpid)) {
@@ -172,31 +174,25 @@
} finally {
switchLock.unlock();
}
- }
+ }
- /**
- * Called when a switch is activated, with this controller's role as EQUAL.
- */
- protected boolean addActivatedEqualSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+ @Override
+ public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
switchLock.lock();
try {
- if (!validActivation(dpid)) {
- return false;
- }
- activeEqualSwitches.put(dpid, sw);
- log.info("Added Activated EQUAL Switch {}", dpid);
- return true;
+ if (!validActivation(dpid)) {
+ return false;
+ }
+ activeEqualSwitches.put(dpid, sw);
+ log.info("Added Activated EQUAL Switch {}", dpid);
+ return true;
} finally {
switchLock.unlock();
}
}
- /**
- * Called when this controller's role for a switch transitions from equal
- * to master. For 1.0 switches, we internally refer to the role 'slave' as
- * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
- */
- protected void transitionToMasterSwitch(long dpid) {
+ @Override
+ public void transitionToMasterSwitch(Dpid dpid) {
switchLock.lock();
try {
if (activeMasterSwitches.containsKey(dpid)) {
@@ -215,12 +211,8 @@
}
- /**
- * Called when this controller's role for a switch transitions to equal.
- * For 1.0 switches, we internally refer to the role 'slave' as
- * 'equal'.
- */
- protected void transitionToEqualSwitch(long dpid) {
+ @Override
+ public void transitionToEqualSwitch(Dpid dpid) {
switchLock.lock();
try {
if (activeEqualSwitches.containsKey(dpid)) {
@@ -239,22 +231,19 @@
}
- /**
- * Clear all state in controller switch maps for a switch that has
- * disconnected from the local controller. Also release control for
- * that switch from the global repository. Notify switch listeners.
- */
- public void removeConnectedSwitch(long dpid) {
+ @Override
+ public void removeConnectedSwitch(Dpid dpid) {
connectedSwitches.remove(dpid);
OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
if (sw == null) {
sw = activeEqualSwitches.remove(dpid);
}
for (OpenFlowSwitchListener l : ofEventListener) {
- l.switchRemoved(new Dpid(dpid));
+ l.switchRemoved(dpid);
}
}
+ @Override
public void processMessage(OFMessage m) {
processPacket(m);
}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
index 99e9173..235eb61 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
@@ -4,6 +4,11 @@
import java.util.Collections;
import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
+import org.onlab.onos.of.controller.driver.RoleHandler;
+import org.onlab.onos.of.controller.driver.RoleRecvStatus;
+import org.onlab.onos.of.controller.driver.RoleReplyInfo;
+import org.onlab.onos.of.controller.driver.SwitchStateException;
import org.projectfloodlight.openflow.protocol.OFControllerRole;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFErrorType;
@@ -35,7 +40,7 @@
* a new request is submitted before the timeout triggers. If necessary
* we could work around that though.
*/
-class RoleManager {
+class RoleManager implements RoleHandler {
protected static final long NICIRA_EXPERIMENTER = 0x2320;
private static Logger log = LoggerFactory.getLogger(RoleManager.class);
@@ -49,10 +54,10 @@
// the expectation set by the caller for the returned role
private RoleRecvStatus expectation;
- private AbstractOpenFlowSwitch sw;
+ private final OpenFlowSwitchDriver sw;
- public RoleManager(AbstractOpenFlowSwitch sw) {
+ public RoleManager(OpenFlowSwitchDriver sw) {
this.requestPending = false;
this.pendingXid = -1;
this.pendingRole = null;
@@ -122,33 +127,13 @@
return xid;
}
- /**
- * Send a role request with the given role to the switch and update
- * the pending request and timestamp.
- * Sends an OFPT_ROLE_REQUEST to an OF1.3 switch, OR
- * Sends an NX_ROLE_REQUEST to an OF1.0 switch if configured to support it
- * in the IOFSwitch driver. If not supported, this method sends nothing
- * and returns 'false'. The caller should take appropriate action.
- *
- * One other optimization we do here is that for OF1.0 switches with
- * Nicira role message support, we force the Role.EQUAL to become
- * Role.SLAVE, as there is no defined behavior for the Nicira role OTHER.
- * We cannot expect it to behave like SLAVE. We don't have this problem with
- * OF1.3 switches, because Role.EQUAL is well defined and we can simulate
- * SLAVE behavior by using ASYNC messages.
- *
- * @param role
- * @throws IOException
- * @returns false if and only if the switch does not support role-request
- * messages, according to the switch driver; true otherwise.
- */
- synchronized boolean sendRoleRequest(RoleState role, RoleRecvStatus exp)
+ @Override
+ public synchronized boolean sendRoleRequest(RoleState role, RoleRecvStatus exp)
throws IOException {
this.expectation = exp;
if (sw.factory().getVersion() == OFVersion.OF_10) {
- Boolean supportsNxRole = (Boolean)
- sw.supportNxRole();
+ Boolean supportsNxRole = sw.supportNxRole();
if (!supportsNxRole) {
log.debug("Switch driver indicates no support for Nicira "
+ "role request messages. Not sending ...");
@@ -189,23 +174,9 @@
}
- /**
- * Deliver a received role reply.
- *
- * Check if a request is pending and if the received reply matches the
- * the expected pending reply (we check both role and xid) we set
- * the role for the switch/channel.
- *
- * If a request is pending but doesn't match the reply we ignore it, and
- * return
- *
- * If no request is pending we disconnect with a SwitchStateException
- *
- * @param RoleReplyInfo information about role-reply in format that
- * controller can understand.
- * @throws SwitchStateException if no request is pending
- */
- synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
+
+ @Override
+ public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
throws SwitchStateException {
if (!requestPending) {
RoleState currentRole = (sw != null) ? sw.getRole() : null;
@@ -280,12 +251,13 @@
* error messages for earlier role requests that we won't be able
* to handle
*/
- synchronized RoleRecvStatus deliverError(OFErrorMsg error)
+ @Override
+ public synchronized RoleRecvStatus deliverError(OFErrorMsg error)
throws SwitchStateException {
if (!requestPending) {
log.debug("Received an error msg from sw {}, but no pending "
+ "requests in role-changer; not handling ...",
- sw.getStringId());
+ sw.getStringId());
return RoleRecvStatus.OTHER_EXPECTATION;
}
if (pendingXid != error.getXid()) {
@@ -353,7 +325,8 @@
* @throws SwitchStateException If the message is a Nicira role reply
* but the numeric role value is unknown.
*/
- protected RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
+ @Override
+ public RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
throws SwitchStateException {
int vendor = (int) experimenterMsg.getExperimenter();
if (vendor != 0x2320) {
@@ -389,72 +362,14 @@
}
/**
- * When we remove a pending role request we use this enum to indicate how we
- * arrived at the decision. When we send a role request to the switch, we
- * also use this enum to indicate what we expect back from the switch, so the
- * role changer can match the reply to our expectation.
- */
- public enum RoleRecvStatus {
- /** The switch returned an error indicating that roles are not.
- * supported*/
- UNSUPPORTED,
- /** The request timed out. */
- NO_REPLY,
- /** The reply was old, there is a newer request pending. */
- OLD_REPLY,
- /**
- * The reply's role matched the role that this controller set in the
- * request message - invoked either initially at startup or to reassert
- * current role.
- */
- MATCHED_CURRENT_ROLE,
- /**
- * The reply's role matched the role that this controller set in the
- * request message - this is the result of a callback from the
- * global registry, followed by a role request sent to the switch.
- */
- MATCHED_SET_ROLE,
- /**
- * The reply's role was a response to the query made by this controller.
- */
- REPLY_QUERY,
- /** We received a role reply message from the switch
- * but the expectation was unclear, or there was no expectation.
- */
- OTHER_EXPECTATION,
- }
-
- /**
- * Helper class returns role reply information in the format understood
- * by the controller.
- */
- protected static class RoleReplyInfo {
- private RoleState role;
- private U64 genId;
- private long xid;
-
- RoleReplyInfo(RoleState role, U64 genId, long xid) {
- this.role = role;
- this.genId = genId;
- this.xid = xid;
- }
- public RoleState getRole() { return role; }
- public U64 getGenId() { return genId; }
- public long getXid() { return xid; }
- @Override
- public String toString() {
- return "[Role:" + role + " GenId:" + genId + " Xid:" + xid + "]";
- }
- }
-
- /**
* Extract the role information from an OF1.3 Role Reply Message.
* @param h
- * @param rrmsg
+ * @param rrmsg the role message
* @return RoleReplyInfo object
- * @throws SwitchStateException
+ * @throws SwitchStateException if the role information could not be extracted.
*/
- protected RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
+ @Override
+ public RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
throws SwitchStateException {
OFControllerRole cr = rrmsg.getRole();
RoleState role = null;
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java
index b475c91..97f94d3 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java
@@ -3,11 +3,9 @@
import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.RoleState;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriverFactory;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
-import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -16,7 +14,7 @@
* A simple implementation of a driver manager that differentiates between
* connected switches using the OF Description Statistics Reply message.
*/
-public final class DriverManager {
+public final class DriverManager implements OpenFlowSwitchDriverFactory {
private static final Logger log = LoggerFactory.getLogger(DriverManager.class);
@@ -32,7 +30,8 @@
* @return A IOFSwitch instance if the driver found an implementation for
* the given description. Otherwise it returns OFSwitchImplBase
*/
- public static AbstractOpenFlowSwitch getOFSwitchImpl(Dpid dpid,
+ @Override
+ public OpenFlowSwitchDriver getOFSwitchImpl(Dpid dpid,
OFDescStatsReply desc, OFVersion ofv) {
String vendor = desc.getMfrDesc();
String hw = desc.getHwDesc();
@@ -53,42 +52,7 @@
log.warn("DriverManager could not identify switch desc: {}. "
+ "Assigning OFSwitchImplBase", desc);
- AbstractOpenFlowSwitch base = new AbstractOpenFlowSwitch(dpid) {
-
-
- @Override
- public void sendMsg(OFMessage m) {
- channel.write(m);
- }
-
- @Override
- public Boolean supportNxRole() {
- return false;
- }
-
- @Override
- public void startDriverHandshake() {}
-
- @Override
- public void setFeaturesReply(OFFeaturesReply featuresReply) {
- this.features = featuresReply;
- }
-
- @Override
- public void processDriverHandshakeMessage(OFMessage m) {}
-
- @Override
- public boolean isDriverHandshakeComplete() {
- return true;
- }
-
- @Override
- public RoleState getRole() {
- return role;
- }
- };
- base.setSwitchDescription(desc);
- return base;
+ return null;
}
/**
@@ -108,4 +72,10 @@
public static void setConfigForCpqd(boolean usePipeline13) {
cpqdUsePipeline13 = usePipeline13;
}
+
+ public static OpenFlowSwitchDriver getSwitch(Dpid dpid,
+ OFDescStatsReply desc, OFVersion ofv) {
+ return new DriverManager().getOFSwitchImpl(dpid, desc, ofv);
+ }
+
}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java
index 6f78e8f..b2881ba 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java
@@ -10,15 +10,14 @@
import org.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.RoleState;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFBucket;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
@@ -61,11 +60,11 @@
*/
public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
- private Logger log =
+ private final Logger log =
LoggerFactory.getLogger(OFSwitchImplCPqD13.class);
private static final int VLAN_ID_OFFSET = 16;
- private AtomicBoolean driverHandshakeComplete;
+ private final AtomicBoolean driverHandshakeComplete;
private OFFactory factory;
private static final int OFPCML_NO_BUFFER = 0xffff;
// Configuration of asynch messages to controller. We need different
@@ -96,7 +95,7 @@
private static final short MIN_PRIORITY = 0x0;
private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
- private Map<Integer, OFGroup> l2groups;
+ private final Map<Integer, OFGroup> l2groups;
private final boolean usePipeline13;
@@ -131,7 +130,7 @@
// Send packet-in to controller if a packet misses the first table
populateTableMissEntry(0, true, false, false, 0);
} //else {
- // configureSwitch();
+ // configureSwitch();
//}
sendBarrier(true);
}
@@ -146,14 +145,7 @@
@Override
public void processDriverHandshakeMessage(OFMessage m) {
- if (!startDriverHandshakeCalled) {
- throw new SwitchDriverSubHandshakeNotStarted();
- }
- if (driverHandshakeComplete.get()) {
- throw new SwitchDriverSubHandshakeCompleted(m);
- }
-
- if (!startDriverHandshakeCalled) {
+ if (!startDriverHandshakeCalled || !startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
if (driverHandshakeComplete.get()) {
@@ -168,30 +160,23 @@
break;
case ERROR:
- log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
+ log.error("Switch {} Error {}", getStringId(), m);
break;
- case FEATURES_REPLY:
- break;
- case FLOW_REMOVED:
- break;
case GET_ASYNC_REPLY:
OFAsyncGetReply asrep = (OFAsyncGetReply) m;
decodeAsyncGetReply(asrep);
break;
-
- case PACKET_IN:
- break;
- case PORT_STATUS:
- break;
- case QUEUE_GET_CONFIG_REPLY:
- break;
- case ROLE_REPLY:
- break;
-
case STATS_REPLY:
processStatsReply((OFStatsReply) m);
break;
+ case PACKET_IN:
+ case PORT_STATUS:
+ case QUEUE_GET_CONFIG_REPLY:
+ case ROLE_REPLY:
+ case FEATURES_REPLY:
+ case FLOW_REMOVED:
+ break;
default:
log.debug("Received message {} during switch-driver subhandshake "
@@ -254,7 +239,7 @@
.build();
msglist.add(getAC);
- write(msglist);
+ sendMsg(msglist);
}
private void decodeAsyncGetReply(OFAsyncGetReply rep) {
@@ -327,7 +312,7 @@
}
}
log.debug("Creating {} L2 groups in sw {}", msglist.size(), getStringId());
- write(msglist);
+ sendMsg(msglist);
}
private int getVlanConfig(int portnum) {
@@ -405,9 +390,9 @@
List<OFAction> actions = new ArrayList<OFAction>();
actions.add(decTtl); // decrement the IP TTL/do-checksum/check TTL
- // and MTU
+ // and MTU
actions.add(setVlan); // set the vlan-id of the exit-port (and
- // l2group)
+ // l2group)
actions.add(setSA); // set this routers mac address
// make L3Unicast group setDA for known (configured) ports
// that connect to other routers
@@ -428,7 +413,7 @@
.build();
msglist.add(gmAdd);
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Creating {} L3 groups in sw {}", msglist.size(), getStringId());
}
@@ -449,8 +434,8 @@
// setDA will only be non-null for ports connected to routers
if (setDA != null) {
OFGroup gl3 = OFGroup.of(0xa0000000 | portnum); // different id
- // for mpls
- // group
+ // for mpls
+ // group
OFAction group = factory.actions().buildGroup()
.setGroup(gl2).build();
OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
@@ -462,9 +447,9 @@
OFAction decMplsTtl = factory.actions().decMplsTtl();
List<OFAction> actions = new ArrayList<OFAction>();
actions.add(decMplsTtl); // decrement the MPLS
- // TTL/do-checksum/check TTL and MTU
+ // TTL/do-checksum/check TTL and MTU
actions.add(setVlan); // set the vlan-id of the exit-port (and
- // l2group)
+ // l2group)
actions.add(setSA); // set this routers mac address
actions.add(setDA);
actions.add(group);
@@ -480,7 +465,7 @@
msglist.add(gmAdd);
}
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
}
@@ -586,7 +571,7 @@
.setMatch(match)
.setInstructions(instructions)
.setPriority(1000) // does not matter - all rules
- // exclusive
+ // exclusive
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
@@ -597,7 +582,7 @@
}
// table-vlan has no table-miss entry, and so packets that miss are
// essentially dropped
- write(msglist);
+ sendMsg(msglist);
log.debug("Adding {} vlan-rules in sw {}", msglist.size(), getStringId());
}
@@ -615,7 +600,7 @@
.setMatch(matchIp)
.setInstructions(instructionsIp)
.setPriority(1000) // strict priority required lower than
- // multicastMac
+ // multicastMac
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
@@ -635,7 +620,7 @@
.setMatch(matchMpls)
.setInstructions(instructionsMpls)
.setPriority(1001) // strict priority required lower than
- // multicastMac
+ // multicastMac
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
@@ -649,7 +634,7 @@
List<OFMessage> msglist = new ArrayList<OFMessage>(2);
msglist.add(ipEntry);
msglist.add(mplsEntry);
- write(msglist);
+ sendMsg(msglist);
}
private List<String> getMyIps() { // send to controller
@@ -712,13 +697,13 @@
List<RouteEntry> routerNextHopIps = new ArrayList<RouteEntry>();
if (getId() == 0x1) {
routerNextHopIps
- .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
+ .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
routerNextHopIps
- .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
+ .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
routerNextHopIps.add(new RouteEntry("7.7.7.0", "255.255.255.0", 6, 103));
}
//if (getId() == 0x2) {
- /* These are required for normal IP routing without labels.
+ /* These are required for normal IP routing without labels.
routerNextHopIps.add(new RouteEntry("192.168.0.1","255.255.255.255",1));
routerNextHopIps.add(new RouteEntry("192.168.0.3","255.255.255.255",2));
routerNextHopIps.add(new RouteEntry("10.0.1.0","255.255.255.0",1));
@@ -728,9 +713,9 @@
//}
if (getId() == 0x3) {
routerNextHopIps
- .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
+ .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
routerNextHopIps
- .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
+ .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
routerNextHopIps.add(new RouteEntry("10.0.1.0", "255.255.255.0", 2, 101));
routerNextHopIps.add(new RouteEntry("10.0.2.0", "255.255.255.0", 2, 101));
routerNextHopIps.add(new RouteEntry("10.0.3.0", "255.255.255.0", 2, 101));
@@ -794,7 +779,7 @@
.setMatch(match)
.setInstructions(instructions)
.setPriority(MAX_PRIORITY) // highest priority for exact
- // match
+ // match
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
@@ -802,7 +787,7 @@
.build();
msglist.add(myIpEntry);
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Adding {} my-ip-rules in sw {}", msglist.size(), getStringId());
}
@@ -844,7 +829,7 @@
.build();
msglist.add(myIpEntry);
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Adding {} subnet-ip-rules in sw {}", msglist.size(), getStringId());
msglist.clear();
}
@@ -861,14 +846,14 @@
.ipv4DstMasked(
IPv4Address.of(routerNextHopIps.get(i).prefix),
IPv4Address.of(routerNextHopIps.get(i).mask)
- );
+ );
OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
OFMatchV3 match = factory.buildMatchV3()
.setOxmList(oxmListSlash32).build();
OFAction outg = factory.actions().buildGroup()
.setGroup(OFGroup.of(0xa0000000 | // mpls group id
routerNextHopIps.get(i).nextHopPort))
- .build();
+ .build();
// lots of actions before forwarding to mpls group, and
// unfortunately
// they need to be apply-actions
@@ -887,7 +872,7 @@
writeActions.add(copyTtlOut); // matched in pseudo-table
//writeActions.add(setlabelid); // bad support in cpqd
//writeActions.add(setBos); no support in loxigen
- */
+ */
List<OFAction> applyActions = new ArrayList<OFAction>();
applyActions.add(pushlabel);
@@ -896,7 +881,7 @@
.setActions(applyActions).build();
List<OFAction> writeActions = new ArrayList<OFAction>();
writeActions.add(outg); // group will decr mpls-ttl, set mac-sa/da,
- // vlan
+ // vlan
OFInstruction writeInstr = factory.instructions().buildWriteActions()
.setActions(writeActions).build();
@@ -950,7 +935,7 @@
OFAction outg2 = factory.actions().buildGroup()
.setGroup(OFGroup.of(routerNextHopIps.get(i).nextHopPort |
(192 << VLAN_ID_OFFSET)))
- .build();
+ .build();
writeActions2.add(outg2);
OFInstruction writeInstr2 = factory.instructions().buildWriteActions()
.setActions(writeActions2).build();
@@ -989,7 +974,7 @@
msglist.add(myMetaEntry);
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Adding {} next-hop-router-rules in sw {}", msglist.size(),
getStringId());
@@ -1022,7 +1007,7 @@
.setField(dmac).build();
outg = factory.actions().buildGroup()
.setGroup(OFGroup.of(0x20000000 | hostNextHopIps.get(i).nextHopPort)) // l3group
- // id
+ // id
.build();
List<OFAction> writeActions = new ArrayList<OFAction>();
writeActions.add(setDmac);
@@ -1039,7 +1024,7 @@
.setMatch(match)
.setInstructions(instructions)
.setPriority(MAX_PRIORITY) // highest priority for exact
- // match
+ // match
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
@@ -1047,7 +1032,7 @@
.build();
msglist.add(myIpEntry);
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
}
@@ -1121,7 +1106,7 @@
.build();
msglist.add(myMplsEntry);
}
- write(msglist);
+ sendMsg(msglist);
log.debug("Adding {} mpls-forwarding-rules in sw {}", msglist.size(),
getStringId());
@@ -1190,7 +1175,7 @@
// executed - if there is an action to output/group in the action
// set
// the packet will be sent there, otherwise it will be dropped.
- instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
+ instructions = Collections.EMPTY_LIST;
}
OFMessage tableMissEntry = factory.buildFlowAdd()
@@ -1219,20 +1204,19 @@
}
@Override
- public void sendMsg(OFMessage m) {
- channel.write(m);
+ public Boolean supportNxRole() {
+ return false;
+ }
+
+ @Override
+ public void write(OFMessage msg) {
+ this.channel.write(msg);
+
}
@Override
public void write(List<OFMessage> msgs) {
- for (OFMessage m : msgs) {
- channel.write(m);
- }
- }
-
- @Override
- public Boolean supportNxRole() {
- return false;
+ this.channel.write(msgs);
}
}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java
index 45228dc..bc42636 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java
@@ -1,7 +1,9 @@
package org.onlab.onos.of.drivers;
+import java.util.List;
+
import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
@@ -29,11 +31,6 @@
}
@Override
- public void sendMsg(OFMessage m) {
- channel.write(m);
- }
-
- @Override
public Boolean supportNxRole() {
return true;
}
@@ -48,4 +45,15 @@
@Override
public void processDriverHandshakeMessage(OFMessage m) {}
+
+ @Override
+ public void write(OFMessage msg) {
+ channel.write(msg);
+
+ }
+
+ @Override
+ public void write(List<OFMessage> msgs) {
+ channel.write(msgs);
+ }
}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java
index 1ab1f047..40750f7 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java
@@ -1,15 +1,15 @@
package org.onlab.onos.of.drivers;
+import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.slf4j.Logger;
@@ -25,7 +25,7 @@
private static Logger log =
LoggerFactory.getLogger(OFSwitchImplOVS13.class);
- private AtomicBoolean driverHandshakeComplete;
+ private final AtomicBoolean driverHandshakeComplete;
private OFFactory factory;
private long barrierXidToWaitFor = -1;
@@ -78,7 +78,7 @@
break;
case ERROR:
- log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
+ log.error("Switch {} Error {}", getStringId(), m);
break;
case FEATURES_REPLY:
@@ -129,12 +129,18 @@
}
@Override
- public void sendMsg(OFMessage m) {
- channel.write(m);
+ public Boolean supportNxRole() {
+ return false;
}
@Override
- public Boolean supportNxRole() {
- return false;
+ public void write(OFMessage msg) {
+ channel.write(msg);
+
+ }
+
+ @Override
+ public void write(List<OFMessage> msgs) {
+ channel.write(msgs);
}
}