diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java index 081f177d3f2a6525731c57f97c4270c55c63b676..36b2be09f955572166d73e6c4a3e9a969cb614fe 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java @@ -103,7 +103,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { private OFFactory factory = OFFactories.getFactory(OFVersion.OF_14); private final OFFeaturesReply featuresReply; private final Timer timer; - + private volatile OFControllerRole initialRole = null; private final ArrayList<OFPortStatus> pendingPortStatusMsg; @@ -500,17 +500,22 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { .setOutPort(OFPort.CONTROLLER) .build(); this.sw.write(deleteFlow); - + 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.getMaxTableForTableMissFlow().getValue(); tableId++) { - OFFlowAdd defaultFlow = this.factory.buildFlowAdd() - .setTableId(TableId.of(tableId)) - .setPriority(0) - .setActions(actions) - .build(); - flows.add(defaultFlow); + /* Use <, not <=, since we want to allow for zero table miss flows */ + for (int tableId = 0; tableId < this.sw.getMaxTableForTableMissFlow().getValue(); tableId++) { + /* Only add the flow if the table exists and if it supports sending to the controller */ + TableFeatures tf = this.sw.getTableFeatures(TableId.of(tableId)); + if (tf != null /* TODO && tf.supportsSendingToController() -- we need something like this, but how? */) { + OFFlowAdd defaultFlow = this.factory.buildFlowAdd() + .setTableId(TableId.of(tableId)) + .setPriority(0) + .setActions(actions) + .build(); + flows.add(defaultFlow); + } } this.sw.write(flows); } @@ -768,7 +773,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { switchManager.notifyPortChanged(sw, ev.port, ev.type); } } - + /** * Handle a table features message. * @@ -1048,7 +1053,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { sendHandshakeDescriptionStatsRequest(); } } - + /* * New state: WaitSwitchTableFeaturesReplyState */ @@ -1059,7 +1064,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { super(false); replies = new ArrayList<OFTableFeaturesStatsReply>(); } - + @Override /** * Accumulate a list of the OFTableFeaturesStatsReply's until there @@ -1082,23 +1087,23 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { /* should only receive TABLE_FEATURES here */ log.error("Received {} message but expected TABLE_FEATURES.", m.getStatsType().toString()); } - + } - + @Override void processOFError(OFErrorMsg m) { if ((m.getErrType() == OFErrorType.BAD_REQUEST) && ((((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.MULTIPART_BUFFER_OVERFLOW) - || ((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.BAD_STAT)) { + || ((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.BAD_STAT)) { log.warn("Switch {} is {} but does not support OFTableFeaturesStats. Assuming all tables can perform any match, action, and instruction in the spec.", sw.getId().toString(), sw.getOFFactory().getVersion().toString()); } else { log.error("Received unexpected OFErrorMsg {} on switch {}.", m.toString(), sw.getId().toString()); } nextState(); - + } - + private void nextState() { /* move on to the next state */ sw.startDriverHandshake(); @@ -1108,7 +1113,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { setState(new WaitSwitchDriverSubHandshakeState()); } } - + @Override void enterState() { if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) < 0) { @@ -1117,7 +1122,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { sendHandshakeTableFeaturesRequest(); } } - + } public class WaitSwitchDriverSubHandshakeState extends OFSwitchHandshakeState { @@ -1445,7 +1450,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { void processOFFlowRemoved(OFFlowRemoved m) { dispatchMessage(m); } - + @Override void processOFStatsReply(OFStatsReply m) { // TODO Auto-generated method stub @@ -1768,7 +1773,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener { .build(); mainConnection.write(descStatsRequest); } - + /** * send a table features request */ diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java index 87841aa6f58169888ff3eddd93ac71bf57c58847..12cd0be082139ef0005164619a576c8ff0961b33 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java @@ -529,7 +529,8 @@ public abstract class OFSwitchHandlerTestBase { expectLastCall().anyTimes(); if (SwitchStatus.MASTER == newStatus) { if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) { - expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2); + expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(1); + expect(sw.getTableFeatures(TableId.ZERO)).andReturn(TableFeatures.of(createTableFeaturesStatsReply().getEntries().get(0))).anyTimes(); } } @@ -605,7 +606,8 @@ public abstract class OFSwitchHandlerTestBase { sw.setStatus(SwitchStatus.MASTER); expectLastCall().once(); if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) { - expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2); + expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(1); + expect(sw.getTableFeatures(TableId.ZERO)).andReturn(TableFeatures.of(createTableFeaturesStatsReply().getEntries().get(0))).anyTimes(); } replay(sw); @@ -698,7 +700,8 @@ public abstract class OFSwitchHandlerTestBase { sw.setStatus(SwitchStatus.MASTER); expectLastCall().once(); if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) { - expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2); + expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(1); + expect(sw.getTableFeatures(TableId.ZERO)).andReturn(TableFeatures.of(createTableFeaturesStatsReply().getEntries().get(0))).anyTimes(); } replay(sw); @@ -759,7 +762,8 @@ public abstract class OFSwitchHandlerTestBase { sw.setStatus(SwitchStatus.MASTER); expectLastCall().once(); if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) { - expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2); + expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(1); + expect(sw.getTableFeatures(TableId.ZERO)).andReturn(TableFeatures.of(createTableFeaturesStatsReply().getEntries().get(0))).anyTimes(); } replay(sw);