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/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java index 532e895ef7b80a7f9ce74310004e656c1af411ca..cd829e308e07ccb67a401ef7815ee790e809e4ec 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java @@ -753,20 +753,24 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen * Get default max table for forward to controller flows. * Internal default set as class variable at top of OFSwitchManager. */ - String defaultFlowsUpToTable = configParams.get("defaultMaxTableToReceiveTableMissFlow"); + String defaultFlowsUpToTable = configParams.get("defaultMaxTablesToReceiveTableMissFlow"); + /* Backward compatibility */ + if (defaultFlowsUpToTable == null || defaultFlowsUpToTable.isEmpty()) { + defaultFlowsUpToTable = configParams.get("defaultMaxTableToReceiveTableMissFlow"); + } if (defaultFlowsUpToTable != null && !defaultFlowsUpToTable.isEmpty()) { defaultFlowsUpToTable = defaultFlowsUpToTable.toLowerCase().trim(); try { forwardToControllerFlowsUpToTable = TableId.of(defaultFlowsUpToTable.startsWith("0x") ? Integer.parseInt(defaultFlowsUpToTable.replaceFirst("0x", ""), 16) : Integer.parseInt(defaultFlowsUpToTable)); - log.info("Setting {} as the default max table to receive table-miss flow", forwardToControllerFlowsUpToTable.toString()); + log.info("Setting {} as the default max tables to receive table-miss flow", forwardToControllerFlowsUpToTable.toString()); } catch (IllegalArgumentException e) { - log.error("Invalid table ID {} for default max table to receive table-miss flow. Using pre-set of {}", + log.error("Invalid table ID {} for default max tables to receive table-miss flow. Using pre-set of {}", defaultFlowsUpToTable, forwardToControllerFlowsUpToTable.toString()); } } else { - log.info("Default max table to receive table-miss flow not configured. Using {}", forwardToControllerFlowsUpToTable.toString()); + log.info("Default max tables to receive table-miss flow not configured. Using {}", forwardToControllerFlowsUpToTable.toString()); } /* @@ -774,10 +778,13 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen * default forward-to-controller flow. This can be used to * reduce the number of such flows if only a reduced set of * tables are being used. - * - * By default, */ - forwardToControllerFlowsUpToTableByDpid = jsonToSwitchTableIdMap(configParams.get("maxTableToReceiveTableMissFlowPerDpid")); + String maxPerDpid = configParams.get("maxTablesToReceiveTableMissFlowPerDpid"); + /* Backward compatibility */ + if (maxPerDpid == null || maxPerDpid.isEmpty()) { + maxPerDpid = configParams.get("maxTableToReceiveTableMissFlowPerDpid"); + } + forwardToControllerFlowsUpToTableByDpid = jsonToSwitchTableIdMap(maxPerDpid); /* * Get config to determine what versions of OpenFlow we will @@ -949,18 +956,18 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen : Integer.parseInt(value) ); /* will throw exception if outside valid TableId number range */ retValue.put(dpid, tablesToGetDefaultFlow); - log.info("Setting max table to receive table-miss flow to {} for DPID {}", + log.info("Setting max tables to receive table-miss flow to {} for DPID {}", tablesToGetDefaultFlow.toString(), dpid.toString()); } catch (IllegalArgumentException e) { /* catches both IllegalArgumentExcpt. and NumberFormatExcpt. */ - log.error("Invalid value of {} for max table to receive table-miss flow for DPID {}. Using default of {}.", value, dpid.toString()); + log.error("Invalid value of {} for max tables to receive table-miss flow for DPID {}. Using default of {}.", value, dpid.toString()); } } } catch (NumberFormatException e) { - log.error("Invalid DPID format {} for max table to receive table-miss flow for specific DPID. Using default for the intended DPID.", n); + log.error("Invalid DPID format {} for max tables to receive table-miss flow for specific DPID. Using default for the intended DPID.", n); } } } catch (IOException e) { - log.error("Using default for remaining DPIDs. JSON formatting error in max table to receive table-miss flow for DPID input String: {}", e); + log.error("Using default for remaining DPIDs. JSON formatting error in max tables to receive table-miss flow for DPID input String: {}", e); } return retValue; } diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties index eb354532c36c036904aafe218478c9970d206dba..ddf7fa36d5a9dc25596a1cb0368b945d3b017737 100644 --- a/src/main/resources/floodlightdefault.properties +++ b/src/main/resources/floodlightdefault.properties @@ -23,7 +23,7 @@ org.sdnplatform.sync.internal.SyncManager.port=6642 net.floodlightcontroller.forwarding.Forwarding.match=vlan, mac, ip, transport net.floodlightcontroller.core.internal.FloodlightProvider.openflowPort=6653 net.floodlightcontroller.core.internal.FloodlightProvider.role=ACTIVE -net.floodlightcontroller.core.internal.OFSwitchManager.defaultMaxTableToReceiveTableMissFlow=4 +net.floodlightcontroller.core.internal.OFSwitchManager.defaultMaxTablesToReceiveTableMissFlow=4 net.floodlightcontroller.core.internal.OFSwitchManager.maxTableToReceiveTableMissFlowPerDpid={"00:00:00:00:00:00:00:01":"4","2":"4"} net.floodlightcontroller.core.internal.OFSwitchManager.clearTablesOnInitialHandshakeAsMaster=YES net.floodlightcontroller.core.internal.OFSwitchManager.clearTablesOnEachTransitionToMaster=YES diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml index 2c8ca28ccbefd41c21583decb480458dc076366a..95ba59679ace01c1d8334da23b24909768cd8d25 100644 --- a/src/main/resources/logback-test.xml +++ b/src/main/resources/logback-test.xml @@ -17,7 +17,7 @@ <logger name="net.floodlightcontroller.devicemanager" level="INFO"></logger> <logger name="net.floodlightcontroller.packet" level="INFO"></logger> <logger name="net.floodlightcontroller.forwarding" level="INFO"></logger> - <logger name="net.floodlightcontroller.routing" level="INFO"></logger> + <logger name="net.floodlightcontroller.devicemanager" level="INFO"></logger> <logger name="net.floodlightcontroller.core.internal" level="INFO"></logger> <logger level="INFO" name="net.floodlightcontroller.learningswitch"></logger> <logger level="INFO" name="org.projectfloodlight.openflow"></logger> 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);