Skip to content
Snippets Groups Projects
Commit df825121 authored by Ryan Izard's avatar Ryan Izard
Browse files

Added insertion of default table-miss flow for OF1.3 switches. Also added...

Added insertion of default table-miss flow for OF1.3 switches. Also added clearing of switch tables when switch connects. Both of these only occur if the controller is in the MASTER role for the switch. It if is placed in SLAVE, the switch flow tables will not be modified. Also had to update the unit tests with new expectations for IOFSwitchBackend fuction calls (which was a real pain).
parent 07cf733b
No related branches found
No related tags found
No related merge requests found
...@@ -37,6 +37,8 @@ import org.projectfloodlight.openflow.protocol.OFExperimenter; ...@@ -37,6 +37,8 @@ import org.projectfloodlight.openflow.protocol.OFExperimenter;
import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply; import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowDelete;
import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode; import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode;
import org.projectfloodlight.openflow.protocol.OFFlowRemoved; import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
import org.projectfloodlight.openflow.protocol.OFGetConfigReply; import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
...@@ -57,10 +59,13 @@ import org.projectfloodlight.openflow.protocol.OFStatsRequestFlags; ...@@ -57,10 +59,13 @@ import org.projectfloodlight.openflow.protocol.OFStatsRequestFlags;
import org.projectfloodlight.openflow.protocol.OFStatsType; import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.protocol.OFType; import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg; import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg; import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFAuxId; import org.projectfloodlight.openflow.types.OFAuxId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.U64;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -417,6 +422,51 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { ...@@ -417,6 +422,51 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener {
} }
} }
/**
* Removes all present flows and adds an initial table-miss flow to each
* and every table on the switch. This replaces the default behavior of
* forwarding table-miss packets to the controller. The table-miss flows
* inserted will forward all packets that do not match a flow to the
* controller for processing.
*
* Adding the default flow only applies to OpenFlow 1.3+ switches, which
* remove the default forward-to-controller behavior of flow tables.
*/
private void clearAndSetDefaultFlows() {
/*
* No tables for OF1.0, so omit that field for flow deletion.
*/
if (this.sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) == 0) {
OFFlowDelete deleteFlows = this.factory.buildFlowDelete()
.build();
this.sw.write(deleteFlows);
} else { /* All other OFVersions support multiple tables. */
OFFlowDelete deleteFlows = this.factory.buildFlowDelete()
.setTableId(TableId.ALL)
.build();
this.sw.write(deleteFlows);
}
/*
* Only for OF1.3+, insert the default forward-to-controller flow for
* each table. This is priority=0 with no Match.
*/
if (this.sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
ArrayList<OFAction> actions = new ArrayList<OFAction>(1);
actions.add(factory.actions().output(OFPort.CONTROLLER, 0xffFFffFF));
ArrayList<OFMessage> flows = new ArrayList<OFMessage>();
for (int tableId = 0; tableId < this.sw.getTables(); tableId++) {
OFFlowAdd defaultFlow = this.factory.buildFlowAdd()
.setTableId(TableId.of(tableId))
.setPriority(0)
.setActions(actions)
.build();
flows.add(defaultFlow);
}
this.sw.write(flows);
}
}
/** /**
* Default implementation for message handlers in any state. * Default implementation for message handlers in any state.
* *
...@@ -1084,6 +1134,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { ...@@ -1084,6 +1134,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener {
@Override @Override
void enterState() { void enterState() {
setSwitchStatus(SwitchStatus.MASTER); setSwitchStatus(SwitchStatus.MASTER);
clearAndSetDefaultFlows();
} }
@LogMessageDoc(level="WARN", @LogMessageDoc(level="WARN",
......
...@@ -32,6 +32,7 @@ import org.jboss.netty.util.TimerTask; ...@@ -32,6 +32,7 @@ import org.jboss.netty.util.TimerTask;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import net.floodlightcontroller.core.HARole; import net.floodlightcontroller.core.HARole;
import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitch.SwitchStatus; import net.floodlightcontroller.core.IOFSwitch.SwitchStatus;
...@@ -43,6 +44,7 @@ import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.Quarantin ...@@ -43,6 +44,7 @@ import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.Quarantin
import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState; import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState;
import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl; import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl;
import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.debugcounter.IDebugCounterService;
import org.projectfloodlight.openflow.protocol.OFBadActionCode; import org.projectfloodlight.openflow.protocol.OFBadActionCode;
import org.projectfloodlight.openflow.protocol.OFBadRequestCode; import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
import org.projectfloodlight.openflow.protocol.OFControllerRole; import org.projectfloodlight.openflow.protocol.OFControllerRole;
...@@ -65,6 +67,7 @@ import org.projectfloodlight.openflow.protocol.match.Match; ...@@ -65,6 +67,7 @@ import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFAuxId; import org.projectfloodlight.openflow.types.OFAuxId;
import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFPort;
import net.floodlightcontroller.util.LinkedHashSetWrapper; import net.floodlightcontroller.util.LinkedHashSetWrapper;
import net.floodlightcontroller.util.OrderedCollection; import net.floodlightcontroller.util.OrderedCollection;
...@@ -139,7 +142,7 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -139,7 +142,7 @@ public abstract class OFSwitchHandlerTestBase {
replay(switchManager); replay(switchManager);
connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN); connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN);
switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer); switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer);
// replay sw. Reset it if you need more specific behavior // replay sw. Reset it if you need more specific behavior
replay(sw); replay(sw);
} }
...@@ -473,7 +476,8 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -473,7 +476,8 @@ public abstract class OFSwitchHandlerTestBase {
* Needs to verify and reset the controller since we need to set * Needs to verify and reset the controller since we need to set
* an expectation * an expectation
*/ */
private void setupSwitchRoleChangeUnsupported(int xid, @SuppressWarnings("unchecked")
private void setupSwitchRoleChangeUnsupported(int xid,
OFControllerRole role) { OFControllerRole role) {
SwitchStatus newStatus = role != OFControllerRole.ROLE_SLAVE ? SwitchStatus.MASTER : SwitchStatus.SLAVE; SwitchStatus newStatus = role != OFControllerRole.ROLE_SLAVE ? SwitchStatus.MASTER : SwitchStatus.SLAVE;
boolean supportsNxRole = false; boolean supportsNxRole = false;
...@@ -483,6 +487,12 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -483,6 +487,12 @@ public abstract class OFSwitchHandlerTestBase {
.andReturn(supportsNxRole).atLeastOnce(); .andReturn(supportsNxRole).atLeastOnce();
// TODO: hmmm. While it's not incorrect that we set the attribute // TODO: hmmm. While it's not incorrect that we set the attribute
// again it looks odd. Maybe change // again it looks odd. Maybe change
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
sw.write(anyObject(OFMessage.class));
expectLastCall().anyTimes();
sw.write(anyObject(Iterable.class));
expectLastCall().anyTimes();
expect(sw.getTables()).andStubReturn((short)0);
sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
expectLastCall().anyTimes(); expectLastCall().anyTimes();
sw.setControllerRole(role); sw.setControllerRole(role);
...@@ -530,7 +540,8 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -530,7 +540,8 @@ public abstract class OFSwitchHandlerTestBase {
* This method tests only the simple case that the switch supports roles * This method tests only the simple case that the switch supports roles
* and transitions to MASTER * and transitions to MASTER
*/ */
@Test @SuppressWarnings("unchecked")
@Test
public void testInitialMoveToMasterWithRole() throws Exception { public void testInitialMoveToMasterWithRole() throws Exception {
// first, move us to WAIT_INITIAL_ROLE_STATE // first, move us to WAIT_INITIAL_ROLE_STATE
moveToWaitInitialRole(); moveToWaitInitialRole();
...@@ -542,6 +553,12 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -542,6 +553,12 @@ public abstract class OFSwitchHandlerTestBase {
// prepare mocks and inject the role reply message // prepare mocks and inject the role reply message
reset(sw); reset(sw);
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
sw.write(anyObject(OFMessage.class));
expectLastCall().anyTimes();
sw.write(anyObject(Iterable.class));
expectLastCall().anyTimes();
expect(sw.getTables()).andStubReturn((short)0);
sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
expectLastCall().once(); expectLastCall().once();
sw.setControllerRole(OFControllerRole.ROLE_MASTER); sw.setControllerRole(OFControllerRole.ROLE_MASTER);
...@@ -613,7 +630,8 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -613,7 +630,8 @@ public abstract class OFSwitchHandlerTestBase {
* The channel handler still needs to send the initial request to find * The channel handler still needs to send the initial request to find
* out that whether the switch supports roles. * out that whether the switch supports roles.
*/ */
@Test @SuppressWarnings("unchecked")
@Test
public void testInitialMoveToMasterNoRole() throws Exception { public void testInitialMoveToMasterNoRole() throws Exception {
// first, move us to WAIT_INITIAL_ROLE_STATE // first, move us to WAIT_INITIAL_ROLE_STATE
moveToWaitInitialRole(); moveToWaitInitialRole();
...@@ -625,6 +643,12 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -625,6 +643,12 @@ public abstract class OFSwitchHandlerTestBase {
// prepare mocks and inject the role reply message // prepare mocks and inject the role reply message
reset(sw); reset(sw);
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
sw.write(anyObject(OFMessage.class));
expectLastCall().anyTimes();
sw.write(anyObject(Iterable.class));
expectLastCall().anyTimes();
expect(sw.getTables()).andStubReturn((short)0);
sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
expectLastCall().once(); expectLastCall().once();
sw.setControllerRole(OFControllerRole.ROLE_MASTER); sw.setControllerRole(OFControllerRole.ROLE_MASTER);
...@@ -661,7 +685,8 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -661,7 +685,8 @@ public abstract class OFSwitchHandlerTestBase {
* We let the initial role request time out. Role support should be * We let the initial role request time out. Role support should be
* disabled but the switch should be activated. * disabled but the switch should be activated.
*/ */
@Test @SuppressWarnings("unchecked")
@Test
public void testInitialMoveToMasterTimeout() throws Exception { public void testInitialMoveToMasterTimeout() throws Exception {
int timeout = 50; int timeout = 50;
switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout); switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout);
...@@ -676,6 +701,12 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -676,6 +701,12 @@ public abstract class OFSwitchHandlerTestBase {
// prepare mocks and inject the role reply message // prepare mocks and inject the role reply message
reset(sw); reset(sw);
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
sw.write(anyObject(OFMessage.class));
expectLastCall().anyTimes();
sw.write(anyObject(Iterable.class));
expectLastCall().anyTimes();
expect(sw.getTables()).andStubReturn((short)0);
sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
expectLastCall().once(); expectLastCall().once();
sw.setControllerRole(OFControllerRole.ROLE_MASTER); sw.setControllerRole(OFControllerRole.ROLE_MASTER);
...@@ -820,7 +851,8 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -820,7 +851,8 @@ public abstract class OFSwitchHandlerTestBase {
* Expects that the channel is in MASTER or SLAVE state. * Expects that the channel is in MASTER or SLAVE state.
* *
*/ */
public void changeRoleToMasterWithRequest() throws Exception { @SuppressWarnings("unchecked")
public void changeRoleToMasterWithRequest() throws Exception {
assertTrue("This method can only be called when handler is in " + assertTrue("This method can only be called when handler is in " +
"MASTER or SLAVE role", switchHandler.isHandshakeComplete()); "MASTER or SLAVE role", switchHandler.isHandshakeComplete());
...@@ -829,6 +861,12 @@ public abstract class OFSwitchHandlerTestBase { ...@@ -829,6 +861,12 @@ public abstract class OFSwitchHandlerTestBase {
// prepare mocks and inject the role reply message // prepare mocks and inject the role reply message
reset(sw); reset(sw);
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
sw.write(anyObject(OFMessage.class));
expectLastCall().anyTimes();
sw.write(anyObject(Iterable.class));
expectLastCall().anyTimes();
expect(sw.getTables()).andStubReturn((short)0);
sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
expectLastCall().once(); expectLastCall().once();
sw.setControllerRole(OFControllerRole.ROLE_MASTER); sw.setControllerRole(OFControllerRole.ROLE_MASTER);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment