diff --git a/src/main/java/net/floodlightcontroller/core/IOFController.java b/src/main/java/net/floodlightcontroller/core/IOFController.java deleted file mode 100644 index dfa871617e5111f3fa53208e199769cd42586322..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/IOFController.java +++ /dev/null @@ -1,23 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* Licensed under the Apache License, Version 2.0 (the "License"); you may -* not use this file except in compliance with the License. You may obtain -* a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -**/ - -package net.floodlightcontroller.core; - -public interface IOFController { - - public String getControllerId(); -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 77674efe0a7a318a81361ace47ad9037c3dc0184..590d0c353b34ee161f1e1b09248d088e57de6dc7 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -49,7 +49,6 @@ import java.util.concurrent.TimeoutException; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IInfoProvider; -import net.floodlightcontroller.core.IOFController; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFMessageListener.Command; import net.floodlightcontroller.core.IOFSwitch; @@ -129,8 +128,7 @@ import org.slf4j.LoggerFactory; /** * The main controller class. Handles all setup and network listeners */ -public class Controller - implements IFloodlightProviderService, IOFController { +public class Controller implements IFloodlightProviderService { protected static Logger log = LoggerFactory.getLogger(Controller.class); @@ -257,6 +255,9 @@ public class Controller log.error("Error sending role request message to switch {}", sw); } } + + // Send an update + // TODO send update } /** @@ -938,6 +939,13 @@ public class Controller switch (m.getType()) { case PACKET_IN: OFPacketIn pi = (OFPacketIn)m; + + if (pi.getPacketData().length <= 0) { + log.error("Ignoring PacketIn (Xid = " + pi.getXid() + + ") because the data field is empty."); + return; + } + if (Controller.ALWAYS_DECODE_ETH) { eth = new Ethernet(); eth.deserialize(pi.getPacketData(), 0, @@ -986,15 +994,12 @@ public class Controller pktinProcTime.recordStartTimeComp(listener); cmd = listener.receive(sw, m, bc); pktinProcTime.recordEndTimeComp(listener); - //updateCumulativeTimeOneComp(compStartTime_ns, - // listener.getId()); if (Command.STOP.equals(cmd)) { break; } } pktinProcTime.recordEndTimePktIn(sw, m, bc); - //updateCumulativeTimeTotal(startTime_ns); } else { log.error("Unhandled OF Message: {} from {}", m, sw); } @@ -1363,11 +1368,6 @@ public class Controller return factory; } - // ************* - // IOFController - // ************* - - @Override public String getControllerId() { return "localhost"; } diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java index 363856695a526de68b304836a75140ebac041659..9c7b238b2433d07f684bce2fc3024d2f7e8d9669 100644 --- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java @@ -58,7 +58,7 @@ public class FloodlightModuleLoader { * @throws FloodlightModuleException If two modules are specified in the configuration * that provide the same service. */ - protected static void findAllModules(Set<String> mList) throws FloodlightModuleException { + protected static void findAllModules(Collection<String> mList) throws FloodlightModuleException { synchronized (lock) { if (serviceMap != null) return; serviceMap = @@ -156,7 +156,7 @@ public class FloodlightModuleLoader { String moduleList = prop.getProperty(FLOODLIGHT_MODULES_KEY) .replaceAll("\\s", ""); - Set<String> configMods = new HashSet<String>(); + Collection<String> configMods = new ArrayList<String>(); configMods.addAll(Arrays.asList(moduleList.split(","))); return loadModulesFromList(configMods, prop); } @@ -167,7 +167,7 @@ public class FloodlightModuleLoader { * @return The ModuleContext containing all the loaded modules * @throws FloodlightModuleException */ - public IFloodlightModuleContext loadModulesFromList(Set<String> configMods, Properties prop) + public IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop) throws FloodlightModuleException { logger.debug("Starting module loader"); findAllModules(configMods); @@ -287,8 +287,18 @@ public class FloodlightModuleLoader { " as provider for " + s.getKey().getCanonicalName()); } - floodlightModuleContext.addService(s.getKey(), - s.getValue()); + if (floodlightModuleContext.getServiceImpl(s.getKey()) == null) { + floodlightModuleContext.addService(s.getKey(), + s.getValue()); + } else { + throw new FloodlightModuleException("Cannot set " + + s.getValue() + + " as the provider for " + + s.getKey().getCanonicalName() + + " because " + + floodlightModuleContext.getServiceImpl(s.getKey()) + + " already provides it"); + } } } } diff --git a/src/main/java/net/floodlightcontroller/counter/CounterStore.java b/src/main/java/net/floodlightcontroller/counter/CounterStore.java index dca628e5ba85e3f51b5b9d5a0f378567b8c3769d..9ec37349fe065623221244c4a68b7fdaabb0498e 100644 --- a/src/main/java/net/floodlightcontroller/counter/CounterStore.java +++ b/src/main/java/net/floodlightcontroller/counter/CounterStore.java @@ -82,6 +82,9 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { public void updatePacketInCounters(IOFSwitch sw, OFMessage m, Ethernet eth) { OFPacketIn packet = (OFPacketIn)m; + // Make sure there is data + if (packet.getPacketData().length <= 0) return; + /* Extract the etherType and protocol field for IPv4 packet. */ String etherType = String.format("%04x", eth.getEtherType()); diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index e80c778feb1557d3c7194fc90f61d64ad849c072..4645c0d7c0b3ebbb7878956ba0a22d4172a2091b 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -499,7 +499,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe /** * Delete an attachment point from a device - * @param d the device + * @param dlAddr the data link layer's address of the device * @param swPort the {@link SwitchPortTuple} to remove */ protected void delDevAttachmentPoint(long dlAddr, SwitchPortTuple swPort) { @@ -580,7 +580,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe /** * Add switch-port to port_channel mapping to portChannelMap * @param switch_id - * @param port_no + * @param port_name * @param port_channel */ protected void addPortToPortChannel(String switch_id, @@ -860,8 +860,8 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe match.loadFromPacket(pi.getPacketData(), pi.getInPort(), sw.getId()); // Add this packet-in to event history evHistPktIn(match); - if (log.isDebugEnabled()) - log.debug("Entering packet_in processing sw {}, port {}. {} --> {}, type {}", + if (log.isTraceEnabled()) + log.trace("Entering packet_in processing sw {}, port {}. {} --> {}, type {}", new Object[] { sw.getStringId(), pi.getInPort(), HexString.toHexString(match.getDataLayerSource()), HexString.toHexString(match.getDataLayerDestination()), @@ -1334,7 +1334,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe } /** - * @param topology the topology to set + * @param linkDiscovery the link discovery service to set */ public void setLinkDiscovery(ILinkDiscoveryService linkDiscovery) { this.linkDiscovery = linkDiscovery; diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index 40f94014248ebb04bbcbf436665464df24eccb22..90ce4f502543b91327b3c6df99586c9aa1390adc 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -190,8 +190,8 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { /** * Creates a OFPacketOut with the OFPacketIn data that is flooded on all ports unless * the port is blocked, in which case the packet will be dropped. + * @param sw The switch that receives the OFPacketIn * @param pi The OFPacketIn that came to the switch - * @param decision The Forwarding decision * @param cntx The FloodlightContext associated with this OFPacketIn */ protected void doFlood(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { diff --git a/src/main/java/net/floodlightcontroller/packet/Ethernet.java b/src/main/java/net/floodlightcontroller/packet/Ethernet.java index 9eba6e9baa77960ab048f598a59238541afa1f90..70ba984a155d90b7888f37effe11c6941f8f3f1d 100644 --- a/src/main/java/net/floodlightcontroller/packet/Ethernet.java +++ b/src/main/java/net/floodlightcontroller/packet/Ethernet.java @@ -216,6 +216,8 @@ public class Ethernet extends BasePacket { @Override public IPacket deserialize(byte[] data, int offset, int length) { + if (length <= 0) + return null; ByteBuffer bb = ByteBuffer.wrap(data, offset, length); if (this.destinationMACAddress == null) this.destinationMACAddress = MACAddress.valueOf(new byte[6]); diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java index 7d3715c469b5bc89f445a6b970cf2494c1699823..f39520f1e18f09c22687e32fbcb829244966df09 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java @@ -85,7 +85,7 @@ public class StaticFlowEntries { * Gets the entry name of a flow mod * @param fmJson The OFFlowMod in a JSON representation * @return The name of the OFFlowMod, null if not found - * @throws IOException If ther was an error parsing the JSON + * @throws IOException If there was an error parsing the JSON */ public static String getEntryNameFromJson(String fmJson) throws IOException{ MappingJsonFactory f = new MappingJsonFactory(); @@ -373,7 +373,7 @@ public class StaticFlowEntries { n = Pattern.compile("output=(?:((?:0x)?\\d+)|(all)|(controller)|(local)|(ingress-port)|(normal)|(flood))").matcher(subaction); if (n.matches()) { OFActionOutput action = new OFActionOutput(); - action.setMaxLength((short) 0); + action.setMaxLength((short) Short.MAX_VALUE); short port = OFPort.OFPP_NONE.getValue(); if (n.group(1) != null) { try { diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java b/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java index b3cc1677210bc8a3b624f0a6b37a5a75c86022ff..5fd18e5622774d0c479660b44455784239d089d3 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java @@ -39,8 +39,47 @@ import net.floodlightcontroller.storage.IStorageSourceService; public class StaticFlowEntryPusherResource extends ServerResource { protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusherResource.class); + /** + * Checks to see if the user matches IP information without + * checking for the correct ether-type (2048). + * @param rows The Map that is a string representation of + * the static flow. + * @reutrn True if they checked the ether-type, false otherwise + */ + private boolean checkMatchIp(Map<String, Object> rows) { + boolean matchEther = false; + String val = (String) rows.get(StaticFlowEntryPusher.COLUMN_DL_TYPE); + if (val != null) { + int type = 0; + // check both hex and decimal + if (val.startsWith("0x")) { + type = Integer.parseInt(val.substring(2), 16); + } else { + try { + type = Integer.parseInt(val); + } catch (NumberFormatException e) { /* fail silently */} + } + if (type == 2048) matchEther = true; + } + + if ((rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_DST) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_SRC) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_PROTO) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_TOS)) && + (matchEther == false)) + return false; + + return true; + } + + /** + * Takes a Static Flow Pusher string in JSON format and parses it into + * our database schema then pushes it to the database. + * @param fmJson The Static Flow Pusher entry in JSON format. + * @return A string status message + */ @Post - public void store(String fmJson) { + public String store(String fmJson) { IStorageSourceService storageSource = (IStorageSourceService)getContext().getAttributes(). get(IStorageSourceService.class.getCanonicalName()); @@ -48,25 +87,45 @@ public class StaticFlowEntryPusherResource extends ServerResource { Map<String, Object> rowValues; try { rowValues = StaticFlowEntries.jsonToStorageEntry(fmJson); + String status = null; + if (!checkMatchIp(rowValues)) { + status = "Warning! Pushing a static flow entry that matches IP " + + "fields without matching for IP payload (ether-type 2048) will cause " + + "the switch to wildcard higher level fields."; + log.error(status); + } else { + status = "Entry pushed"; + } storageSource.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, rowValues); + return ("{\"status\" : \"" + status + "\"}"); } catch (IOException e) { log.error("Error parsing push flow mod request: " + fmJson, e); e.printStackTrace(); + return "{\"status\" : \"Error! Could not parse flod mod, see log for details.\"}"; } } @Delete - public void del(String fmJson) { + public String del(String fmJson) { IStorageSourceService storageSource = (IStorageSourceService)getContext().getAttributes(). get(IStorageSourceService.class.getCanonicalName()); - + String fmName = null; + if (fmJson == null) { + return "{\"status\" : \"Error! No data posted.\"}"; + } try { - String fmName = StaticFlowEntries.getEntryNameFromJson(fmJson); - storageSource.deleteRow(StaticFlowEntryPusher.TABLE_NAME, fmName); + fmName = StaticFlowEntries.getEntryNameFromJson(fmJson); + if (fmName == null) { + return "{\"status\" : \"Error deleting entry, no name provided\"}"; + } } catch (IOException e) { log.error("Error deleting flow mod request: " + fmJson, e); e.printStackTrace(); + return "{\"status\" : \"Error deleting entry, see log for details\"}"; } + + storageSource.deleteRowAsync(StaticFlowEntryPusher.TABLE_NAME, fmName); + return "{\"status\" : \"Entry " + fmName + " deleted\"}"; } } diff --git a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java index d390f2ed9a5a655b754546498e7e191ed69487c8..9227eff8f581f2e2910836ce97ee9f40a2fd677b 100644 --- a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java +++ b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java @@ -57,7 +57,7 @@ public class StaticFlowTests extends FloodlightTestCase { // setup actions List<OFAction> actions = new LinkedList<OFAction>(); TestRule1.put(COLUMN_ACTIONS, "output=1"); - actions.add(new OFActionOutput((short)1, (short) 0)); + actions.add(new OFActionOutput((short)1, (short) Short.MAX_VALUE)); // done FlowMod1.setMatch(match); FlowMod1.setActions(actions); @@ -82,7 +82,7 @@ public class StaticFlowTests extends FloodlightTestCase { // setup actions List<OFAction> actions = new LinkedList<OFAction>(); TestRule2.put(COLUMN_ACTIONS, "output=1"); - actions.add(new OFActionOutput((short)1, (short) 0)); + actions.add(new OFActionOutput((short)1, (short) Short.MAX_VALUE)); // done FlowMod2.setMatch(match); FlowMod2.setActions(actions); @@ -109,7 +109,7 @@ public class StaticFlowTests extends FloodlightTestCase { // setup actions TestRule3.put(COLUMN_ACTIONS, "output=controller"); List<OFAction> actions = new LinkedList<OFAction>(); - actions.add(new OFActionOutput(OFPort.OFPP_CONTROLLER.getValue(), (short) 0)); + actions.add(new OFActionOutput(OFPort.OFPP_CONTROLLER.getValue(), (short) Short.MAX_VALUE)); // done FlowMod3.setMatch(match); FlowMod3.setActions(actions);