diff --git a/build.xml b/build.xml index 3093f956856f9b2ca13bf9e67fe37d573ee1f609..cdea14c7ef4982b658d8e0ce0fe74198c3154cc5 100644 --- a/build.xml +++ b/build.xml @@ -27,10 +27,11 @@ <property name="build-test" location="${target}/bin-test"/> <property name="test-output" location="${target}/test"/> <property name="source" location="src/main/java"/> + <property name="resources" location="src/main/resources/"/> <property name="source-test" location="src/test/java"/> <property name="python-src" location="src/main/python"/> <property name="docs" location="${target}/docs"/> - <property name="main-class" value="net.floodlightcontroller.core.internal.Controller"/> + <property name="main-class" value="net.floodlightcontroller.core.Main"/> <property name="packetstreamer-gen" location="${target}/gen-java" /> <property name="packetstreamer-gen-build" location="${target}/gen-java-bin"/> <property name="packetstreamer-thrift-jar" location="${target}/lib/packetstreamer-thrift.jar"/> @@ -102,6 +103,7 @@ <target name="compile-tests" depends="compile-test"/> <target name="compile-test" depends="compile"> + <fileset dir="${resources}"/> <javac includeAntRuntime="false" debug="true" srcdir="${source-test}" classpath="${build}" @@ -159,6 +161,7 @@ <attribute name="Class-Path" value="."/> </manifest> <fileset dir="${build}"/> + <fileset dir="${resources}"/> <fileset dir="${python-src}"> <include name="**/*.py"/> </fileset> @@ -174,6 +177,7 @@ <attribute name="Class-Path" value="."/> </manifest> <fileset dir="${build-test}"/> + <fileset dir="${resources}"/> <zipgroupfileset dir="lib"> <patternset refid="lib-test"/> </zipgroupfileset> diff --git a/setup-eclipse.sh b/setup-eclipse.sh index d7e9a06fb126b99ffe22cc670926f34d28a3bc9d..bdf87200a57a97a7d618303da714356cc86d53a6 100755 --- a/setup-eclipse.sh +++ b/setup-eclipse.sh @@ -31,6 +31,7 @@ cat >$d/.classpath <<EOF <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src/main/java" output="target/bin"/> + <classpathentry kind="src" path="src/main/resources"/> <classpathentry kind="src" path="src/test/java" output="target/bin-test"/> EOF ( diff --git a/src/main/java/net/floodlightcontroller/core/CoreModule.java b/src/main/java/net/floodlightcontroller/core/CoreModule.java new file mode 100644 index 0000000000000000000000000000000000000000..be4ebc25e644ca7794cc2930c5125e961f363f82 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/CoreModule.java @@ -0,0 +1,77 @@ +package net.floodlightcontroller.core; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import net.floodlightcontroller.core.internal.Controller; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.counter.CounterStore; +import net.floodlightcontroller.counter.ICounterStoreService; +import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; +import net.floodlightcontroller.restserver.IRestApiService; +import net.floodlightcontroller.storage.IStorageSourceService; + +public class CoreModule implements IFloodlightModule { + Controller controller; + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> services = + new ArrayList<Class<? extends IFloodlightService>>(2); + services.add(IFloodlightProviderService.class); + services.add(ICounterStoreService.class); + return services; + } + + @Override + public Map<Class<? extends IFloodlightService>, + IFloodlightService> getServiceImpls() { + controller = new Controller(); + ICounterStoreService counterStore = new CounterStore(); + controller.setCounterStore(counterStore); + + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + m.put(IFloodlightProviderService.class, controller); + m.put(ICounterStoreService.class, counterStore); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> dependencies = + new ArrayList<Class<? extends IFloodlightService>>(4); + dependencies.add(IStorageSourceService.class); + dependencies.add(IOFMessageFilterManagerService.class); + dependencies.add(IPktInProcessingTimeService.class); + dependencies.add(IRestApiService.class); + return dependencies; + } + + @Override + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + controller.setStorageSourceService( + context.getServiceImpl(IStorageSourceService.class)); + controller.setPktInProcessingService( + context.getServiceImpl(IPktInProcessingTimeService.class)); + controller.setCounterStore( + context.getServiceImpl(ICounterStoreService.class)); + controller.setMessageFilterManagerService( + context.getServiceImpl(IOFMessageFilterManagerService.class)); + controller.setRestApiService( + context.getServiceImpl(IRestApiService.class)); + controller.init(); + } + + @Override + public void startUp(FloodlightModuleContext context) { + controller.startupComponents(); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java similarity index 91% rename from src/main/java/net/floodlightcontroller/core/IFloodlightProvider.java rename to src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java index 6cf9515b9fcfa2c350f5bae11b392dce34a81d93..c2d5cf433297e7b89af5b95370a70862e2825012 100644 --- a/src/main/java/net/floodlightcontroller/core/IFloodlightProvider.java +++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; +import net.floodlightcontroller.core.internal.CmdLineSettings; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.packet.Ethernet; import org.openflow.protocol.OFMessage; @@ -33,7 +35,7 @@ import org.openflow.protocol.factory.BasicFactory; * * @author David Erickson (daviderickson@cs.stanford.edu) */ -public interface IFloodlightProvider { +public interface IFloodlightProviderService extends IFloodlightService { /** * A value stored in the floodlight context containing a parsed packet @@ -133,4 +135,14 @@ public interface IFloodlightProvider { * @return an OpenFlow message factory */ public BasicFactory getOFMessageFactory(); + + /** + * Run the main I/O loop of the Controller. + */ + public void run(); + + /** + * Sets the command line settings + */ + public void setCmdLineOptions(CmdLineSettings settings); } diff --git a/src/main/java/net/floodlightcontroller/core/IOFMessageFilterManagerService.java b/src/main/java/net/floodlightcontroller/core/IOFMessageFilterManagerService.java new file mode 100644 index 0000000000000000000000000000000000000000..58de92ca04d6b7ad519b2fa85b6d2e06d56ecf47 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/IOFMessageFilterManagerService.java @@ -0,0 +1,12 @@ +package net.floodlightcontroller.core; + +import net.floodlightcontroller.core.module.IFloodlightService; + +import org.openflow.protocol.OFMessage; + +public interface IOFMessageFilterManagerService extends IFloodlightService { + + public String getDataAsString(IOFSwitch sw, OFMessage msg, + FloodlightContext cntx); + +} diff --git a/src/main/java/net/floodlightcontroller/core/Main.java b/src/main/java/net/floodlightcontroller/core/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..10ad853e1a18adf0e695c65afabe4ea3965dbb95 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/Main.java @@ -0,0 +1,45 @@ +package net.floodlightcontroller.core; + +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; + +import net.floodlightcontroller.core.internal.CmdLineSettings; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.FloodlightModuleLoader; +import net.floodlightcontroller.core.module.IFloodlightModuleContext; +import net.floodlightcontroller.restserver.IRestApiService; + +/** + * Host for the Floodlight main method + * @author alexreimers + */ +public class Main { + + /** + * Main method to load configuration and modules + * @param args + * @throws FloodlightModuleException + */ + public static void main(String[] args) throws FloodlightModuleException { + System.setProperty("org.restlet.engine.loggerFacadeClass", + "org.restlet.ext.slf4j.Slf4jLoggerFacade"); + + CmdLineSettings settings = new CmdLineSettings(); + CmdLineParser parser = new CmdLineParser(settings); + try { + parser.parseArgument(args); + } catch (CmdLineException e) { + parser.printUsage(System.out); + System.exit(1); + } + + FloodlightModuleLoader fml = new FloodlightModuleLoader(); + IFloodlightModuleContext moduleContext = fml.loadModulesFromConfig(settings.getModuleFile()); + IRestApiService restApi = moduleContext.getServiceImpl(IRestApiService.class); + restApi.run(); + IFloodlightProviderService controller = + moduleContext.getServiceImpl(IFloodlightProviderService.class); + controller.setCmdLineOptions(settings); + controller.run(); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java index 316c200bb59bfde85e37a99e7425b2b7c00ec4fd..d787fc702ceca3b08c6d5b22e2b94731632e841b 100644 --- a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java +++ b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java @@ -19,7 +19,9 @@ package net.floodlightcontroller.core; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -49,10 +51,15 @@ import org.apache.thrift.transport.TTransportException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packetstreamer.thrift.*; -public class OFMessageFilterManager implements IOFMessageListener { +public class OFMessageFilterManager + implements IOFMessageListener, IFloodlightModule, IOFMessageFilterManagerService { /** * @author Srini @@ -65,7 +72,7 @@ public class OFMessageFilterManager implements IOFMessageListener { protected static TTransport transport = null; protected static PacketStreamer.Client packetClient = null; - protected IFloodlightProvider floodlightProvider = null; + protected IFloodlightProviderService floodlightProvider = null; // filter List is a key value pair. Key is the session id, value is the filter rules. protected ConcurrentHashMap<String, ConcurrentHashMap<String,String>> filterMap = null; protected ConcurrentHashMap<String, Long> filterTimeoutMap = null; @@ -91,13 +98,6 @@ public class OFMessageFilterManager implements IOFMessageListener { FILTER_NOT_DEFINED, FILTER_NO_MATCH, FILTER_MATCH } - public void init (IFloodlightProvider bp) { - floodlightProvider = bp; - filterMap = new ConcurrentHashMap<String, ConcurrentHashMap<String,String>>(); - filterTimeoutMap = new ConcurrentHashMap<String, Long>(); - serverPort = Integer.parseInt(System.getProperty("net.floodlightcontroller.packetstreamer.port", "9090")); - } - protected String addFilter(ConcurrentHashMap<String,String> f, long delta) { // Create unique session ID. @@ -200,8 +200,8 @@ public class OFMessageFilterManager implements IOFMessageListener { Ethernet eth = null; if (m.getType() == OFType.PACKET_IN) { - eth = IFloodlightProvider.bcStore.get(cntx, - IFloodlightProvider.CONTEXT_PI_PAYLOAD); + eth = IFloodlightProviderService.bcStore.get(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD); } else if (m.getType() == OFType.PACKET_OUT) { eth = new Ethernet(); OFPacketOut p = (OFPacketOut) m; @@ -254,30 +254,7 @@ public class OFMessageFilterManager implements IOFMessageListener { else return matchedFilters; } - - - protected void startListening() { - floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); - floodlightProvider.addOFMessageListener(OFType.PACKET_OUT, this); - floodlightProvider.addOFMessageListener(OFType.FLOW_MOD, this); - } - - protected void stopListening() { - floodlightProvider.removeOFMessageListener(OFType.PACKET_IN, this); - floodlightProvider.removeOFMessageListener(OFType.PACKET_OUT, this); - floodlightProvider.removeOFMessageListener(OFType.FLOW_MOD, this); - } - - public void startUp() { - startListening(); - //connectToPSServer(); - } - - public void shutDown() { - stopListening(); - disconnectFromPSServer(); - } - + public boolean connectToPSServer() { int numRetries = 0; if (transport != null && transport.isOpen()) { @@ -464,6 +441,7 @@ public class OFMessageFilterManager implements IOFMessageListener { } } + @Override public String getDataAsString(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { Ethernet eth; @@ -495,8 +473,8 @@ public class OFMessageFilterManager implements IOFMessageListener { // If the conext is not set by floodlight, then ignore. if (cntx != null) { // packet type icmp, arp, etc. - eth = IFloodlightProvider.bcStore.get(cntx, - IFloodlightProvider.CONTEXT_PI_PAYLOAD); + eth = IFloodlightProviderService.bcStore.get(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD); if (eth != null) sb.append(eth.toString()); } @@ -528,8 +506,8 @@ public class OFMessageFilterManager implements IOFMessageListener { // If the conext is not set by floodlight, then ignore. if (cntx != null) { - eth = IFloodlightProvider.bcStore.get(cntx, - IFloodlightProvider.CONTEXT_PI_PAYLOAD); + eth = IFloodlightProviderService.bcStore.get(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD); if (eth != null) sb.append(eth.toString()); } @@ -565,4 +543,53 @@ public class OFMessageFilterManager implements IOFMessageListener { return this.getDataAsString(sw, msg, cntx).getBytes(); } + // IFloodlightModule methods + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IOFMessageFilterManagerService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + // We are the class that implements the service + m.put(IOFMessageFilterManagerService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IFloodlightProviderService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + this.floodlightProvider = + context.getServiceImpl(IFloodlightProviderService.class); + } + + @Override + public void startUp(FloodlightModuleContext context) { + // This is our 'constructor' + + filterMap = new ConcurrentHashMap<String, ConcurrentHashMap<String,String>>(); + filterTimeoutMap = new ConcurrentHashMap<String, Long>(); + serverPort = Integer.parseInt(System.getProperty("net.floodlightcontroller.packetstreamer.port", "9090")); + + floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); + floodlightProvider.addOFMessageListener(OFType.PACKET_OUT, this); + floodlightProvider.addOFMessageListener(OFType.FLOW_MOD, this); + } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/CmdLineSettings.java b/src/main/java/net/floodlightcontroller/core/internal/CmdLineSettings.java index f4a654fe70e08b4f6f21356de8e6b513af1a2b22..dc81f044ba08c5dae1a5f22e6b984a2247e3457b 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/CmdLineSettings.java +++ b/src/main/java/net/floodlightcontroller/core/internal/CmdLineSettings.java @@ -6,14 +6,17 @@ import org.kohsuke.args4j.Option; * Expresses the port settings of OpenFlow controller. */ public class CmdLineSettings { - private final int DEFAULT_OPENFLOW_PORT = 6633; - private final int DEFAULT_REST_PORT = 8080; + public static final int DEFAULT_OPENFLOW_PORT = 6633; + public static final int DEFAULT_REST_PORT = 8080; + public static final String DEFAULT_CONFIG_FILE = "floodlightdefault.properties"; private final int DEFAULT_WORKER_THREADS = 0; @Option(name="-ofp", aliases="--openFlowPort",metaVar="PORT", usage="Port number for OpenFlow") private int openFlowPort = DEFAULT_OPENFLOW_PORT; @Option(name="-rp", aliases="--restPort", metaVar="PORT", usage="Port number for REST API") private int restPort = DEFAULT_REST_PORT; + @Option(name="-cf", aliases="--configFile", metaVar="FILE", usage="Floodlight configuration file") + private String configFile = DEFAULT_CONFIG_FILE; @Option(name="-wt", aliases="--workerThreads", metaVar="THREADS", usage="Number of worker threads") private int workerThreads = DEFAULT_WORKER_THREADS; @@ -25,6 +28,10 @@ public class CmdLineSettings { return restPort; } + public String getModuleFile() { + return configFile; + } + public int getWorkerThreads() { return workerThreads; } diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 13afeb3592a111aed976c17e28d8ee4b590c5206..3630ce6070c4221af5136fbadaab7fda1b3dea1c 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -21,11 +21,9 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -46,43 +44,31 @@ import java.util.concurrent.TimeoutException; import java.nio.channels.ClosedChannelException; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFController; +import net.floodlightcontroller.core.IOFMessageFilterManagerService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFMessageListener.Command; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitchFilter; import net.floodlightcontroller.core.IOFSwitchListener; -import net.floodlightcontroller.core.OFMessageFilterManager; import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState; import net.floodlightcontroller.core.util.ListenerDispatcher; import net.floodlightcontroller.core.web.CoreWebRoutable; -import net.floodlightcontroller.core.web.JacksonCustomConverter; -import net.floodlightcontroller.core.web.RestletRoutable; import static net.floodlightcontroller.counter.CounterValue.CounterType; import net.floodlightcontroller.counter.CounterStore; import net.floodlightcontroller.counter.ICounter; import net.floodlightcontroller.counter.CounterStore.NetworkLayer; -import net.floodlightcontroller.devicemanager.IDeviceManagerAware; -import net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl; -import net.floodlightcontroller.forwarding.Forwarding; +import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.jython.Server; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; -import net.floodlightcontroller.routing.dijkstra.RoutingImpl; -import net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher; -import net.floodlightcontroller.perfmon.PktinProcessingTime; +import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; +import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.IStorageExceptionHandler; -import net.floodlightcontroller.storage.IStorageSource; +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.OperatorPredicate; import net.floodlightcontroller.storage.StorageException; -import net.floodlightcontroller.storage.memory.MemoryStorageSource; -import net.floodlightcontroller.storage.web.StorageWebRoutable; -import net.floodlightcontroller.topology.ITopologyAware; -import net.floodlightcontroller.topology.internal.TopologyImpl; -import net.floodlightcontroller.topology.web.TopologyWebRouteable; - import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; @@ -100,8 +86,6 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler; import org.jboss.netty.handler.timeout.IdleStateEvent; import org.jboss.netty.handler.timeout.ReadTimeoutException; -import org.kohsuke.args4j.CmdLineException; -import org.kohsuke.args4j.CmdLineParser; import org.openflow.protocol.OFEchoReply; import org.openflow.protocol.OFError; import org.openflow.protocol.OFError.OFBadActionCode; @@ -130,17 +114,6 @@ import org.openflow.protocol.factory.MessageParseException; import org.openflow.util.HexString; import org.openflow.util.U16; import org.openflow.util.U32; -import org.restlet.Component; -import org.restlet.Context; -import org.restlet.Request; -import org.restlet.Response; -import org.restlet.Restlet; -import org.restlet.data.Protocol; -import org.restlet.data.Reference; -import org.restlet.routing.Filter; -import org.restlet.routing.Router; -import org.restlet.routing.Template; -import org.restlet.Application; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -149,8 +122,7 @@ import org.slf4j.LoggerFactory; * The main controller class. Handles all setup and network listeners */ public class Controller - extends Application - implements IFloodlightProvider, IOFController { + implements IFloodlightProviderService, IOFController { protected static Logger log = LoggerFactory.getLogger(Controller.class); @@ -161,27 +133,22 @@ public class Controller protected ConcurrentHashMap<Long, IOFSwitch> switches; protected Set<IOFSwitchListener> switchListeners; protected BlockingQueue<Update> updates; - protected CounterStore counterStore; + protected ICounterStoreService counterStore; + protected IRestApiService restApi; protected ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); - protected IStorageSource storageSource; - protected TopologyImpl topology; - protected DeviceManagerImpl deviceManager; - protected RoutingImpl routingEngine; - protected Forwarding forwarding; - protected OFMessageFilterManager messageFilterManager; - protected PktinProcessingTime pktinProcTime; - private StaticFlowEntryPusher staticFlowEntryPusher; - protected long ptWarningThresholdInNano; + protected IStorageSourceService storageSource; + protected IOFMessageFilterManagerService messageFilterManager; + protected IPktInProcessingTimeService pktinProcTime; - protected List<RestletRoutable> restlets; - - protected int restPort; - protected int openFlowPort; + // Configuration options + protected int openFlowPort = 6633; + protected long ptWarningThresholdInNano; protected int workerThreads; - + + // Storage table names protected static final String CONTROLLER_TABLE_NAME = "controller_controller"; protected static final String CONTROLLER_ID = "id"; @@ -220,24 +187,31 @@ public class Controller this.added = added; } } - - public Controller() { - this(new CmdLineSettings()); + + // *************** + // Getters/Setters + // *************** + + public void setStorageSourceService(IStorageSourceService storageSource) { + this.storageSource = storageSource; } - - public Controller(CmdLineSettings settings) { - this.messageListeners = - new ConcurrentHashMap<OFType, - ListenerDispatcher<OFType, - IOFMessageListener>>(); - this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); - this.updates = new LinkedBlockingQueue<Update>(); - this.restlets = new ArrayList<RestletRoutable>(); - this.restPort = settings.getRestPort(); - this.openFlowPort = settings.getOpenFlowPort(); - this.workerThreads = settings.getWorkerThreads(); + + public void setCounterStore(ICounterStoreService counterStore) { + this.counterStore = counterStore; + } + + public void setMessageFilterManagerService(IOFMessageFilterManagerService mfm) { + this.messageFilterManager = mfm; } + public void setPktInProcessingService(IPktInProcessingTimeService pits) { + this.pktinProcTime = pits; + } + + public void setRestApiService(IRestApiService restApi) { + this.restApi = restApi; + } + // ********************** // ChannelUpstreamHandler // ********************** @@ -543,20 +517,6 @@ public class Controller processSwitchDescReply(); } break; - /* - * "Trivial" server to test raw low-level throughput - case PACKET_IN: - OFPacketIn pi = (OFPacketIn)m; - - OFFlowMod fm = - (OFFlowMod)factory.getMessage(OFType.FLOW_MOD); - OFMatch match = new OFMatch(); - match.loadFromPacket(pi.getPacketData(), pi.getInPort()); - fm.setBufferId(pi.getBufferId()); - fm.setMatch(match); - sw.write(fm, null); - break; - */ case PORT_STATUS: boolean swadded = state.hsState.equals(HandshakeState.READY); @@ -690,7 +650,7 @@ public class Controller portL3Counter.increment(); switchL3Counter.increment(); - if (etherType.compareTo(CounterStore.L3ET_IPV4) == 0) { + if (etherType.compareTo(ICounterStoreService.L3ET_IPV4) == 0) { IPv4 ipV4 = (IPv4)eth.getPayload(); String l4Type = String.format("%02x", ipV4.getProtocol()); if (TypeAliases.l4TypeAliasMap != null && @@ -780,8 +740,8 @@ public class Controller bc = bContext; } if (eth != null) { - IFloodlightProvider.bcStore.put(bc, - IFloodlightProvider.CONTEXT_PI_PAYLOAD, + IFloodlightProviderService.bcStore.put(bc, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); } @@ -1088,96 +1048,9 @@ public class Controller return "localhost"; } - // *********** - // Application - // *********** - - @Override - public Restlet createInboundRoot() { - Context context = getContext(); - initRestContext(context); - - Router baseRouter = new Router(context); - baseRouter.setDefaultMatchingMode(Template.MODE_STARTS_WITH); - for (RestletRoutable rr : restlets) { - baseRouter.attach(rr.basePath(), rr.getRestlet(context)); - } - - Filter slashFilter = new Filter() { - @Override - protected int beforeHandle(Request request, Response response) { - Reference ref = request.getResourceRef(); - String originalPath = ref.getPath(); - if (originalPath.contains("//")) - { - String newPath = originalPath.replaceAll("/+", "/"); - ref.setPath(newPath); - } - return Filter.CONTINUE; - } - - }; - slashFilter.setNext(baseRouter); - - return slashFilter; - } - // ************** // Initialization // ************** - - /** - * Call after init() has run, but before this.run() - * @throws IOException - */ - - protected void startUp() throws IOException { - // Connect to the storage source to update info about this controller - // node, and wait indefinitely if the storage source is unavailable; - // don't want switches to connect before we have a database - while (true) { - try { - updateControllerInfo(); - break; - } - catch (StorageException e) { - log.info("Waiting for storage source"); - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - } - } - } - log.info("Connected to storage source"); - - switches = new ConcurrentHashMap<Long, IOFSwitch>(); - - this.factory = new BasicFactory(); - } - - protected void shutDown() { - try { - removeControllerInfo(); - } catch (StorageException e) { - } - - log.info("Shutdown complete"); - } - - protected void setStorageSource(IStorageSource storageSource) { - this.storageSource = storageSource; - IStorageExceptionHandler handler = - new TerminationStorageExceptionHandler(this); - storageSource.setExceptionHandler(handler); - storageSource.createTable(CONTROLLER_TABLE_NAME, null); - storageSource.createTable(SWITCH_TABLE_NAME, null); - storageSource.createTable(PORT_TABLE_NAME, null); - storageSource.setTablePrimaryKeyName(CONTROLLER_TABLE_NAME, - CONTROLLER_ID); - storageSource.setTablePrimaryKeyName(SWITCH_TABLE_NAME, - SWITCH_DATAPATH_ID); - storageSource.setTablePrimaryKeyName(PORT_TABLE_NAME, PORT_ID); - } protected void updateAllInactiveSwitchInfo() { String controllerId = getControllerId(); @@ -1243,17 +1116,6 @@ public class Controller storageSource.updateRow(CONTROLLER_TABLE_NAME, controllerInfo); } - protected void removeControllerInfo() { - // Update the controller info in the storage source to be inactive -// Map<String, Object> controllerInfo = new HashMap<String, Object>(); -// String id = getControllerId(); -// controllerInfo.put(CONTROLLER_ID, id); -// controllerInfo.put(CONTROLLER_ACTIVE, Boolean.FALSE); -// storageSource.updateRow(CONTROLLER_TABLE_NAME, controllerInfo); - - updateAllInactiveSwitchInfo(); - } - protected void updateActiveSwitchInfo(IOFSwitch sw) { // Obtain the row info for the switch Map<String, Object> switchInfo = new HashMap<String, Object>(); @@ -1346,34 +1208,14 @@ public class Controller * Tell controller that we're ready to accept switches loop * @throws IOException */ - protected void run() { + public void run() { try { - // Start listening for REST requests - final Component component = new Component(); - component.getServers().add(Protocol.HTTP, restPort); - component.getDefaultHost().attach(this); - - component.start(); - - // Start listening for switch connections - //int threads = - // Runtime.getRuntime().availableProcessors() * 2 + 1; - //int threads = 1; - //long maxMem = Runtime.getRuntime().maxMemory() * 1 / 3; - //long memPerChannel = 2 * 1024 * 1024; - - final ServerBootstrap bootstrap = createServerBootStrap(workerThreads); + final ServerBootstrap bootstrap = createServerBootStrap(workerThreads); bootstrap.setOption("reuseAddr", true); bootstrap.setOption("child.keepAlive", true); bootstrap.setOption("child.tcpNoDelay", true); - //OrderedMemoryAwareThreadPoolExecutor pipelineExecutor = - // new OrderedMemoryAwareThreadPoolExecutor( - // threads, memPerChannel, maxMem, - // 1000, TimeUnit.SECONDS, - // Executors.defaultThreadFactory()); - ChannelPipelineFactory pfact = new OpenflowPipelineFactory(this, null); bootstrap.setPipelineFactory(pfact); @@ -1428,170 +1270,87 @@ public class Controller } /** - * Initialize all of the controller's components; override me for - * new components - */ - protected void init() { - topology = new TopologyImpl(); - deviceManager = new DeviceManagerImpl(); - counterStore = new CounterStore(); - pktinProcTime = new PktinProcessingTime(); - routingEngine = new RoutingImpl(); - initStorageSource(); - - topology.setFloodlightProvider(this); - topology.setStorageSource(storageSource); - - deviceManager.setFloodlightProvider(this); - deviceManager.setStorageSource(storageSource); - deviceManager.setTopology(topology); - - initMessageFilterManager(); - initStaticFlowPusher(); - initForwarding(); - - // call this explicitly because it does setup - this.setStorageSource(storageSource); - - - ArrayList<ITopologyAware> topologyAware = new ArrayList<ITopologyAware>(); - topologyAware.add(deviceManager); - topologyAware.add(routingEngine); - topology.setTopologyAware(topologyAware); - topology.setRoutingEngine(routingEngine); - - HashSet<IDeviceManagerAware> dmAware = - new HashSet<IDeviceManagerAware>(); - dmAware.add(forwarding); - //deviceManager.setDeviceManagerAware(dmAware); - - restlets.add(new CoreWebRoutable()); - restlets.add(new StorageWebRoutable()); - restlets.add(new TopologyWebRouteable()); - JacksonCustomConverter.replaceConverter(); - - // Processing Time Warning Threshold - ptWarningThresholdInNano = Long.parseLong(System.getProperty("net.floodlightcontroller.core.PTWarningThresholdInMilli", "0")) * 1000000; - if (ptWarningThresholdInNano > 0) { - log.info("Packet processing time threshold for warning set to {} ms.", - ptWarningThresholdInNano/1000000); - } - } - - protected void initStorageSource() { - MemoryStorageSource memoryStorageSource = new MemoryStorageSource(); - memoryStorageSource.setCounterStore(counterStore); - storageSource = memoryStorageSource; - } - - protected void initMessageFilterManager() { - messageFilterManager = new OFMessageFilterManager(); - messageFilterManager.init(this); - } - - protected void initStaticFlowPusher() { - staticFlowEntryPusher = new StaticFlowEntryPusher(); - staticFlowEntryPusher.setFloodlightProvider(this); - } - - protected void initForwarding() { - forwarding = new Forwarding(); - forwarding.setFloodlightProvider(this); - forwarding.setCounterStore(counterStore); - forwarding.setDeviceManager(deviceManager); - forwarding.setRoutingEngine(routingEngine); - forwarding.setTopology(topology); - } - - /** - * Initialize the rest context + * Initialize internal datastructures */ - protected void initRestContext(Context context) { - context.getAttributes().put("floodlightProvider", this); - context.getAttributes().put("counterStore", counterStore); - context.getAttributes().put("storageSource", storageSource); - context.getAttributes().put("deviceManager", deviceManager); - context.getAttributes().put("messageFilterManager", - messageFilterManager); - context.getAttributes().put("pktinProcessingTime", pktinProcTime); - if (staticFlowEntryPusher != null) { - context.getAttributes().put("staticFlowEntryPusher", - staticFlowEntryPusher); - } - context.getAttributes().put("topology", topology); + public void init() { + // These data structures are initialized here because other + // module's startUp() might be called before ours + this.messageListeners = + new ConcurrentHashMap<OFType, + ListenerDispatcher<OFType, + IOFMessageListener>>(); + this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); + this.switches = new ConcurrentHashMap<Long, IOFSwitch>(); + this.updates = new LinkedBlockingQueue<Update>(); + this.factory = new BasicFactory(); } /** * Startup all of the controller's components */ - protected void startupComponents() { - // now, do our own init - try { - log.debug("Doing controller internal setup"); - this.startUp(); - } catch (IOException e) { - throw new RuntimeException(e); - } + public void startupComponents() { + log.debug("Doing controller internal setup"); + // Create the table names we use + storageSource.createTable(CONTROLLER_TABLE_NAME, null); + storageSource.createTable(SWITCH_TABLE_NAME, null); + storageSource.createTable(PORT_TABLE_NAME, null); + storageSource.setTablePrimaryKeyName(CONTROLLER_TABLE_NAME, + CONTROLLER_ID); + storageSource.setTablePrimaryKeyName(SWITCH_TABLE_NAME, + SWITCH_DATAPATH_ID); + storageSource.setTablePrimaryKeyName(PORT_TABLE_NAME, PORT_ID); - log.debug("Starting topology service"); - topology.startUp(); - log.debug("Starting deviceManager service"); - deviceManager.startUp(); - // no need to do storageSource.startUp() - log.debug("Starting counterStore service"); - counterStore.startUp(); - log.debug("Starting routingEngine service"); - routingEngine.startUp(); - log.debug("Starting forwarding service"); - forwarding.startUp(); - log.debug("Starting messageFilter service"); - messageFilterManager.startUp(); - log.debug("Starting staticFlowEntryPusher service"); - staticFlowEntryPusher.startUp(); - log.debug("Starting DebugServer"); - this.debugserver_start(); + while (true) { + try { + updateControllerInfo(); + break; + } + catch (StorageException e) { + log.info("Waiting for storage source"); + try { + Thread.sleep(1000); + } catch (InterruptedException e1) { + } + } + } + log.info("Connected to storage source"); + + // Processing Time Warning Threshold + ptWarningThresholdInNano = Long.parseLong(System.getProperty( + "net.floodlightcontroller.core.PTWarningThresholdInMilli", "0")) * 1000000; + if (ptWarningThresholdInNano > 0) { + log.info("Packet processing time threshold for warning set to {} ms.", + ptWarningThresholdInNano/1000000); + } + + // Add our REST API + restApi.addRestletRoutable(new CoreWebRoutable()); } /** * Start debug server, put global state as local variables for the jython shell */ + // TODO - make this a module protected void debugserver_start() { + log.debug("Starting DebugServer"); Map<String, Object> locals = new HashMap<String, Object>(); locals.put("controller", this); - locals.put("deviceManager", this.deviceManager); - locals.put("topology", this.topology); - locals.put("routingEngine", this.routingEngine); - locals.put("forwarding", this.forwarding); - locals.put("staticFlowEntryPusher", this.staticFlowEntryPusher); + //locals.put("deviceManager", this.deviceManager); + //locals.put("topology", this.topology); + //locals.put("routingEngine", this.routingEngine); + //locals.put("forwarding", this.forwarding); + //locals.put("staticFlowEntryPusher", this.staticFlowEntryPusher); locals.put("counterStore", this.counterStore); locals.put("storageSource", this.storageSource); locals.put("switches", this.switches); - locals.put("messageFilterManager", this.messageFilterManager); + //locals.put("messageFilterManager", this.messageFilterManager); Server debug_server = new Server(6655, locals); debug_server.start(); } - - /** - * Main function entry point; override init() for adding modules - * @param args Command line arguments - */ - public static void main(String args[]) throws Exception { - System.setProperty("org.restlet.engine.loggerFacadeClass", - "org.restlet.ext.slf4j.Slf4jLoggerFacade"); - - CmdLineSettings settings = new CmdLineSettings(); - CmdLineParser parser = new CmdLineParser(settings); - try { - parser.parseArgument(args); - } catch (CmdLineException e) { - parser.printUsage(System.out); - System.exit(1); - } - - Controller controller = new Controller(settings); - controller.init(); - controller.startupComponents(); - controller.run(); + + @Override + public void setCmdLineOptions(CmdLineSettings settings) { + this.openFlowPort = settings.getOpenFlowPort(); } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java index 4435682802c6901b2509ad3ee60ec44ab2c5f0b5..9f8b30e141ae0b915f006fad251a1bb8bc1fa724 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java @@ -26,7 +26,7 @@ import java.util.concurrent.TimeoutException; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFType; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitchFilter; import net.floodlightcontroller.core.IOFSwitchListener; @@ -42,7 +42,7 @@ import net.floodlightcontroller.core.IOFSwitchListener; public abstract class OFMessageFuture<T,V> implements Future<V>, IOFSwitchFilter, IOFSwitchListener { - protected IFloodlightProvider floodlightProvider; + protected IFloodlightProviderService floodlightProvider; protected volatile boolean canceled; protected CountDownLatch latch; protected OFType responseType; @@ -51,12 +51,12 @@ public abstract class OFMessageFuture<T,V> implements Future<V>, protected Runnable timeoutTimer; protected int transactionId; - public OFMessageFuture(IFloodlightProvider floodlightProvider, IOFSwitch sw, + public OFMessageFuture(IFloodlightProviderService floodlightProvider, IOFSwitch sw, OFType responseType, int transactionId) { this(floodlightProvider, sw, responseType, transactionId, 60, TimeUnit.SECONDS); } - public OFMessageFuture(IFloodlightProvider floodlightProvider, IOFSwitch sw, + public OFMessageFuture(IFloodlightProviderService floodlightProvider, IOFSwitch sw, OFType responseType, int transactionId, long timeout, TimeUnit unit) { this.floodlightProvider = floodlightProvider; this.canceled = false; diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java index 6c9870c518a11305f0d0086401132d05793d8393..306d38eeabb4e7f91219cb829fb909826a17a489 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import org.openflow.protocol.OFMessage; @@ -40,13 +40,13 @@ public class OFStatisticsFuture extends protected volatile boolean finished; - public OFStatisticsFuture(IFloodlightProvider floodlightProvider, IOFSwitch sw, + public OFStatisticsFuture(IFloodlightProviderService floodlightProvider, IOFSwitch sw, int transactionId) { super(floodlightProvider, sw, OFType.STATS_REPLY, transactionId); init(); } - public OFStatisticsFuture(IFloodlightProvider floodlightProvider, IOFSwitch sw, + public OFStatisticsFuture(IFloodlightProviderService floodlightProvider, IOFSwitch sw, int transactionId, long timeout, TimeUnit unit) { super(floodlightProvider, sw, OFType.STATS_REPLY, transactionId, timeout, unit); init(); diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java index c514d19907fb1bb11ff9ee340d99274ce47168df..e280358f952e5b489744e2c85e49b92938eb41a0 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java @@ -30,7 +30,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.types.MacVlanPair; import net.floodlightcontroller.util.TimedCache; @@ -62,7 +62,7 @@ public class OFSwitchImpl implements IOFSwitch { protected static Logger log = LoggerFactory.getLogger(OFSwitchImpl.class); protected ConcurrentMap<Object, Object> attributes; - protected IFloodlightProvider floodlightProvider; + protected IFloodlightProviderService floodlightProvider; protected Date connectedSince; protected OFFeaturesReply featuresReply; protected String stringId; @@ -275,7 +275,7 @@ public class OFSwitchImpl implements IOFSwitch { /** * @param floodlightProvider the floodlightProvider to set */ - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { + public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } diff --git a/src/main/java/net/floodlightcontroller/core/internal/TerminationStorageExceptionHandler.java b/src/main/java/net/floodlightcontroller/core/internal/TerminationStorageExceptionHandler.java index 111dc291766f6fef159d585d422f14e606b1569c..9b27ae1db7b20a33eb41ded28f46993b3963f34f 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/TerminationStorageExceptionHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/TerminationStorageExceptionHandler.java @@ -20,15 +20,15 @@ package net.floodlightcontroller.core.internal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.storage.IStorageExceptionHandler; public class TerminationStorageExceptionHandler implements IStorageExceptionHandler { protected static Logger log = LoggerFactory.getLogger(TerminationStorageExceptionHandler.class); - private IFloodlightProvider floodlightProvider; + private IFloodlightProviderService floodlightProvider; - TerminationStorageExceptionHandler(IFloodlightProvider floodlightProvider) { + TerminationStorageExceptionHandler(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java new file mode 100644 index 0000000000000000000000000000000000000000..2f90c3a33dd4e49590c050218c7c535e61228fe9 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java @@ -0,0 +1,45 @@ +package net.floodlightcontroller.core.module; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * The service registry for an IFloodlightProvider. + * @author alexreimers + */ +public class FloodlightModuleContext implements IFloodlightModuleContext { + protected Map<Class<? extends IFloodlightService>, IFloodlightService> serviceMap; + + /** + * Creates the ModuleContext for use with this IFloodlightProvider. + * This will be used as a module registry for all IFloodlightModule(s). + */ + public FloodlightModuleContext() { + serviceMap = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + } + + /** + * Adds a IFloodlightModule for this Context. + * @param clazz the service class + * @param module The IFloodlightModule to add to the registry + */ + public void addService(Class<? extends IFloodlightService> clazz, + IFloodlightService service) { + serviceMap.put(clazz, service); + } + + @SuppressWarnings("unchecked") + @Override + public <T extends IFloodlightService> T getServiceImpl(Class<T> service) { + IFloodlightService s = serviceMap.get(service); + return (T)s; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getAllServices() { + return serviceMap.keySet(); + } + } diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java new file mode 100644 index 0000000000000000000000000000000000000000..20ccc86d478d0869f71251025960bda89060fd50 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java @@ -0,0 +1,9 @@ +package net.floodlightcontroller.core.module; + +public class FloodlightModuleException extends Exception { + private static final long serialVersionUID = 1L; + + public FloodlightModuleException(String error) { + super(error); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..9781c398f85404b8055887d34f63953239b54cc8 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java @@ -0,0 +1,289 @@ +package net.floodlightcontroller.core.module; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Queue; +import java.util.ServiceLoader; +import java.util.Set; + + +import net.floodlightcontroller.core.internal.CmdLineSettings; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Finds all Floodlight modules in the class path and loads/starts them. + * @author alexreimers + * + */ +public class FloodlightModuleLoader { + protected static Logger logger = + LoggerFactory.getLogger(FloodlightModuleLoader.class); + + protected static Map<Class<? extends IFloodlightService>, + Collection<IFloodlightModule>> serviceMap; + protected static Map<IFloodlightModule, + Collection<Class<? extends + IFloodlightService>>> moduleServiceMap; + protected static Map<String, IFloodlightModule> moduleNameMap; + protected static Object lock = new Object(); + + protected FloodlightModuleContext floodlightModuleContext; + + public FloodlightModuleLoader() { + floodlightModuleContext = new FloodlightModuleContext(); + } + + /** + * Finds all IFloodlightModule(s) in the classpath. It creates 3 Maps. + * serviceMap -> Maps a service to a module + * moduleServiceMap -> Maps a module to all the services it provides + * moduleNameMap -> Maps the string name to the module + */ + protected static void findAllModules() { + synchronized (lock) { + if (serviceMap != null) return; + serviceMap = + new HashMap<Class<? extends IFloodlightService>, + Collection<IFloodlightModule>>(); + moduleServiceMap = + new HashMap<IFloodlightModule, + Collection<Class<? extends + IFloodlightService>>>(); + moduleNameMap = new HashMap<String, IFloodlightModule>(); + + // Get all the current modules in the classpath + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + ServiceLoader<IFloodlightModule> moduleLoader + = ServiceLoader.load(IFloodlightModule.class, cl); + // Iterate for each module, iterate through and add it's services + for (IFloodlightModule m : moduleLoader) { + if (logger.isDebugEnabled()) { + logger.debug("Found module " + m.getClass().getName()); + } + + // Set up moduleNameMap + moduleNameMap.put(m.getClass().getCanonicalName(), m); + + // Set up serviceMap + Collection<Class<? extends IFloodlightService>> servs = + m.getModuleServices(); + if (servs != null) { + moduleServiceMap.put(m, servs); + for (Class<? extends IFloodlightService> s : servs) { + Collection<IFloodlightModule> mods = + serviceMap.get(s); + if (mods == null) { + mods = new ArrayList<IFloodlightModule>(); + serviceMap.put(s, mods); + } + mods.add(m); + } + } + } + } + } + + /** + * Loads + * @param fName + * @return + * @throws FloodlightModuleException + */ + public IFloodlightModuleContext loadModulesFromConfig(String fName) + throws FloodlightModuleException { + Properties prop = new Properties(); + + // Load defaults if no properties file exists + if (fName == null) { + logger.debug("No module file specified, using defaults"); + String[] mList = new String[2]; + mList[0] = "net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher"; + mList[1] = "net.floodlightcontroller.forwarding.Forwarding"; + return loadModulesFromList(mList); + } else { + try { + if (fName == CmdLineSettings.DEFAULT_CONFIG_FILE) { + logger.debug("Loading default module file " + fName); + InputStream is = this.getClass().getClassLoader().getResourceAsStream(fName); + if (is == null) { + logger.error("Could not find default properties file!"); + System.exit(1); + } + prop.load(is); + } else { + logger.debug("Loading modules from file " + fName); + prop.load(new FileInputStream(fName)); + } + } catch (IOException ex) { + logger.debug("Properties file " + fName + " not found!"); + ex.printStackTrace(); + System.exit(1); + } + return loadModulesFromList(prop.getProperty("floodlight.modules").split(",")); + } + } + + /** + * Loads modules (and their dependencies) specified in the list + * @param mList The array of fully qualified module names + * @return The ModuleContext containing all the loaded modules + * @throws FloodlightModuleException + */ + public IFloodlightModuleContext loadModulesFromList(String[] mList) + throws FloodlightModuleException { + logger.debug("Starting module loader"); + findAllModules(); + + Set<IFloodlightModule> moduleSet = new HashSet<IFloodlightModule>(); + Map<Class<? extends IFloodlightService>, IFloodlightModule> moduleMap = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightModule>(); + + HashSet<String> configMods = new HashSet<String>(); + configMods.addAll(Arrays.asList(mList)); + Queue<String> moduleQ = new LinkedList<String>(); + // Add the explicitly configured modules to the q + moduleQ.addAll(configMods); + Set<String> modsVisited = new HashSet<String>(); + + while (!moduleQ.isEmpty()) { + String moduleName = moduleQ.remove(); + if (modsVisited.contains(moduleName)) + continue; + modsVisited.add(moduleName); + IFloodlightModule module = moduleNameMap.get(moduleName); + if (module == null) { + throw new FloodlightModuleException("Module " + + moduleName + " not found"); + } + // Add the module to be loaded + addModule(moduleMap, moduleSet, module); + // Add it's dep's to the queue + Collection<Class<? extends IFloodlightService>> deps = + module.getModuleDependencies(); + if (deps != null) { + for (Class<? extends IFloodlightService> c : deps) { + IFloodlightModule m = moduleMap.get(c); + if (m == null) { + Collection<IFloodlightModule> mods = serviceMap.get(c); + // Make sure only one module is loaded + if ((mods == null) || (mods.size() == 0)) { + System.out.println(serviceMap.keySet()); + throw new FloodlightModuleException("ERROR! Could not " + + "find an IFloodlightModule that provides service " + + c.toString()); + } else if (mods.size() == 1) { + IFloodlightModule mod = mods.iterator().next(); + if (!modsVisited.contains(mod.getClass().getCanonicalName())) + moduleQ.add(mod.getClass().getCanonicalName()); + } else { + boolean found = false; + for (IFloodlightModule moduleDep : mods) { + if (configMods.contains(moduleDep.getClass().getCanonicalName())) { + // Module will be loaded, we can continue + found = true; + break; + } + } + if (!found) { + throw new FloodlightModuleException("ERROR! Found more " + + "than one (" + mods.size() + ") IFloodlightModules that provides " + + "service " + c.toString() + + ". Please resolve this in the config"); + } + } + } + } + } + } + + initModules(moduleSet); + startupModules(moduleSet); + + return floodlightModuleContext; + } + + /** + * Add a module to the set of modules to load and register its services + * @param moduleMap the module map + * @param moduleSet the module set + * @param module the module to add + */ + protected void addModule(Map<Class<? extends IFloodlightService>, + IFloodlightModule> moduleMap, + Set<IFloodlightModule> moduleSet, + IFloodlightModule module) { + if (!moduleSet.contains(module)) { + Collection<Class<? extends IFloodlightService>> servs = + moduleServiceMap.get(module); + if (servs != null) { + for (Class<? extends IFloodlightService> c : servs) + moduleMap.put(c, module); + } + moduleSet.add(module); + } + } + + /** + * Allocate service implementations and then init all the modules + * @param moduleSet The set of modules to call their init function on + * @throws FloodlightModuleException If a module can not properly be loaded + */ + protected void initModules(Set<IFloodlightModule> moduleSet) + throws FloodlightModuleException { + for (IFloodlightModule module : moduleSet) { + // Get the module's service instance(s) + Map<Class<? extends IFloodlightService>, + IFloodlightService> simpls = module.getServiceImpls(); + + // add its services to the context + if (simpls != null) { + for (Entry<Class<? extends IFloodlightService>, + IFloodlightService> s : simpls.entrySet()) { + if (logger.isDebugEnabled()) { + logger.debug("Setting " + s.getValue() + + " as provider for " + + s.getKey().getCanonicalName()); + } + floodlightModuleContext.addService(s.getKey(), + s.getValue()); + } + } + } + + for (IFloodlightModule module : moduleSet) { + // init the module + if (logger.isDebugEnabled()) { + logger.debug("Initializing " + + module.getClass().getCanonicalName()); + } + module.init(floodlightModuleContext); + } + } + + /** + * Call each loaded module's startup method + * @param moduleSet the module set to start up + */ + protected void startupModules(Set<IFloodlightModule> moduleSet) { + for (IFloodlightModule m : moduleSet) { + if (logger.isDebugEnabled()) { + logger.debug("Starting " + + m.getClass().getCanonicalName()); + } + m.startUp(floodlightModuleContext); + } + } +} diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java new file mode 100644 index 0000000000000000000000000000000000000000..003e0a119d1eeda8abc1a7ee45798e552622956f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java @@ -0,0 +1,77 @@ +package net.floodlightcontroller.core.module; + +import java.util.Collection; +import java.util.Map; + + +/** + * Defines an interface for loadable Floodlight modules. + * + * At a high level, these functions are called in the following order: + * <ol> + * <li> getServices() : what services does this module provide + * <li> getDependencies() : list the dependencies + * <li> init() : internal initializations (don't touch other modules) + * <li> startUp() : external initializations (<em>do</em> touch other modules) + * </ol> + * + * @author alexreimers + */ +public interface IFloodlightModule { + + /** + * Return the list of interfaces that this module implements. + * All interfaces must inherit IFloodlightService + * @return + */ + + public Collection<Class<? extends IFloodlightService>> getModuleServices(); + + /** + * Instantiate (as needed) and return objects that implement each + * of the services exported by this module. The map returned maps + * the implemented service to the object. The object could be the + * same object or different objects for different exported services. + * @return The map from service interface class to service implementation + */ + public Map<Class<? extends IFloodlightService>, + IFloodlightService> getServiceImpls(); + + /** + * Get a list of Modules that this module depends on. The module system + * will ensure that each these dependencies is resolved before the + * subsequent calls to init(). + * @return The Collection of IFloodlightServices that this module depnds + * on. + */ + + public Collection<Class<? extends IFloodlightService>> getModuleDependencies(); + + /** + * This is a hook for each module to do its <em>internal</em> initialization, + * e.g., call setService(context.getService("Service")) + * + * All module dependencies are resolved when this is called, but not every module + * is initialized. + * + * @param context + * @throws FloodlightModuleException + */ + + void init(FloodlightModuleContext context) throws FloodlightModuleException; + + /** + * This is a hook for each module to do its <em>external</em> initializations, + * e.g., register for callbacks or query for state in other modules + * + * It is expected that this function will not block and that modules that want + * non-event driven CPU will spawn their own threads. + * + * @param context + */ + + void startUp(FloodlightModuleContext context); + + // TODO add getName() getId() + +} diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java new file mode 100644 index 0000000000000000000000000000000000000000..a22c3807201b42d6db2997e1f54f1357e0296ffb --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java @@ -0,0 +1,21 @@ +package net.floodlightcontroller.core.module; + +import java.util.Collection; + + +public interface IFloodlightModuleContext { + /** + * Retrieves a casted version of a module from the registry. + * @param name The IFloodlightService object type + * @return The IFloodlightService + * @throws FloodlightModuleException If the module was not found + * or a ClassCastException was encountered. + */ + public <T extends IFloodlightService> T getServiceImpl(Class<T> service); + + /** + * Returns all loaded services + * @return A collection of service classes that have been loaded + */ + public Collection<Class<? extends IFloodlightService>> getAllServices(); +} diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java new file mode 100644 index 0000000000000000000000000000000000000000..8bf26cca38d3d8a8d0ec0b80f23ea19616fb8327 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java @@ -0,0 +1,12 @@ +package net.floodlightcontroller.core.module; + +/** + * This is the base interface for any IFloodlightModule package that provides + * a service. + * @author alexreimers + * + */ +// TODO change this to IFloodlightExclusiveService +public abstract interface IFloodlightService { + // This space is intentionally left blank....don't touch it +} diff --git a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java index 2ef32f13d94978889d3ed387bbe03cf3c31de609..f8509d9223e38b3f689edeb16d1be576e50a8c69 100644 --- a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.types.MacVlanPair; import org.openflow.protocol.OFFeaturesReply; @@ -80,7 +80,9 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { return model; } - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); Long[] switchDpids = floodlightProvider.getSwitches().keySet().toArray(new Long[0]); List<GetConcurrentStatsThread> activeThreads = new ArrayList<GetConcurrentStatsThread>(switchDpids.length); List<GetConcurrentStatsThread> pendingRemovalThreads = new ArrayList<GetConcurrentStatsThread>(); @@ -167,7 +169,9 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { } public void run() { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); if ((requestType == REQUESTTYPE.OFSTATS) && (statType != null)) { switchReply = getSwitchStatistics(switchId, statType); diff --git a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java index b2d903a6ec6d712f4529c84f05c4480fb6ab6136..c8f74860e7369ecb789be974bc3343ba86afcf78 100644 --- a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java @@ -22,7 +22,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import org.restlet.resource.Get; @@ -35,9 +35,10 @@ import org.restlet.resource.ServerResource; public class ControllerSwitchesResource extends ServerResource { @Get("json") public List<Map<String, String>> retrieve() { - List<Map<String, String>> switchIds = new ArrayList<Map<String, String>>(); - - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + List<Map<String, String>> switchIds = new ArrayList<Map<String, String>>(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); Map<Long, IOFSwitch> switches = floodlightProvider.getSwitches(); for (IOFSwitch s: switches.values()) { diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java index d798d263665de61349f95e6796f1323b9a236f0b..81fe2fa41852209daabe40eb4641c9cc6e2dd1d1 100644 --- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java @@ -17,6 +17,8 @@ package net.floodlightcontroller.core.web; +import net.floodlightcontroller.restserver.RestletRoutable; + import org.restlet.Context; import org.restlet.Restlet; import org.restlet.routing.Router; diff --git a/src/main/java/net/floodlightcontroller/core/web/CounterResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/CounterResourceBase.java index e27b0ae31236b65243d6cffb4e558a62415b073b..70e90ed231431b7c88e1377183671698686b5f75 100644 --- a/src/main/java/net/floodlightcontroller/core/web/CounterResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/CounterResourceBase.java @@ -17,18 +17,19 @@ package net.floodlightcontroller.core.web; -import net.floodlightcontroller.counter.CounterStore; +import net.floodlightcontroller.counter.ICounterStoreService; import org.restlet.resource.ResourceException; import org.restlet.resource.ServerResource; public class CounterResourceBase extends ServerResource { - protected CounterStore counterStore; + protected ICounterStoreService counterStore; @Override protected void doInit() throws ResourceException { super.doInit(); counterStore = - (CounterStore)getContext().getAttributes().get("counterStore"); + (ICounterStoreService)getContext().getAttributes(). + get(ICounterStoreService.class.getCanonicalName()); } } diff --git a/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java b/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java index 0bd3336657c32d5b9515f673037f528c5557a460..1a41ffc301c6702b78a8b8f484f224d1f7ba2a03 100644 --- a/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java @@ -76,12 +76,13 @@ public class PacketTraceResource extends ServerResource { @Post("json") public PacketTraceOutput packettrace(FilterParameters fp) { - ConcurrentHashMap <String,String> filter = new ConcurrentHashMap<String,String> (); + ConcurrentHashMap <String,String> filter = new ConcurrentHashMap<String,String> (); String sid = null; PacketTraceOutput output = new PacketTraceOutput(); OFMessageFilterManager manager = (OFMessageFilterManager)getContext() - .getAttributes().get("messageFilterManager"); + .getAttributes(). + get(OFMessageFilterManager.class.getCanonicalName()); if (manager == null) { sid = null; diff --git a/src/main/java/net/floodlightcontroller/core/web/StaticFlowEntryPusherResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/StaticFlowEntryPusherResourceBase.java index d1b0abb088c6ad6779173a8b4208e63b1c7192e3..61254552261ed868edde881ca3b30abcc1ab779e 100644 --- a/src/main/java/net/floodlightcontroller/core/web/StaticFlowEntryPusherResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/StaticFlowEntryPusherResourceBase.java @@ -28,6 +28,7 @@ public class StaticFlowEntryPusherResourceBase extends ServerResource { protected void doInit() throws ResourceException { super.doInit(); staticFlowEntryPusher = - (StaticFlowEntryPusher)getContext().getAttributes().get("staticFlowEntryPusher"); + (StaticFlowEntryPusher)getContext().getAttributes(). + get(IStaticFlowEntryPusherService.class); } } \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/web/StorageSourceTablesResource.java b/src/main/java/net/floodlightcontroller/core/web/StorageSourceTablesResource.java index e657251e87bc0b0cf7da94c610e0c918764d857f..51f514f50506a0cf7ff0db1bd5306bedda6e41c9 100644 --- a/src/main/java/net/floodlightcontroller/core/web/StorageSourceTablesResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/StorageSourceTablesResource.java @@ -2,7 +2,7 @@ package net.floodlightcontroller.core.web; import java.util.Set; -import net.floodlightcontroller.storage.IStorageSource; +import net.floodlightcontroller.storage.IStorageSourceService; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; @@ -10,7 +10,8 @@ import org.restlet.resource.ServerResource; public class StorageSourceTablesResource extends ServerResource { @Get("json") public Set<String> retrieve() { - IStorageSource storageSource = (IStorageSource)getContext().getAttributes().get("storageSource"); + IStorageSourceService storageSource = (IStorageSourceService)getContext(). + getAttributes().get(IStorageSourceService.class.getCanonicalName()); Set<String> allTableNames = storageSource.getAllTableNames(); return allTableNames; } diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchClustersResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchClustersResource.java index c3d8ae6ac4d34ae6ffa2efcbf1ff41c09e4ab422..8ac83ce8f1a6aa3843a0f023fb0550d6cf2c99f2 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchClustersResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchClustersResource.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import org.openflow.util.HexString; @@ -36,7 +36,9 @@ import org.restlet.resource.ServerResource; public class SwitchClustersResource extends ServerResource { @Get("json") public Map<String, List<String>> retrieve() { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); Map<String, List<String>> switchClusterMap = new HashMap<String, List<String>>(); for (Entry<Long, IOFSwitch> entry : floodlightProvider.getSwitches().entrySet()) { Long clusterDpid = entry.getValue().getSwitchClusterId(); diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java index dbce9f0880e46bb74eb910c2753e9d39c5a1c9d0..f14d7062eb658f334f8b11108c5f9dfe6d5e20af 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java @@ -26,9 +26,9 @@ import java.util.Map; import org.openflow.util.HexString; import org.restlet.resource.Get; -import net.floodlightcontroller.core.IFloodlightProvider; -import net.floodlightcontroller.counter.CounterStore; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.counter.CounterStore.NetworkLayer; +import net.floodlightcontroller.counter.ICounterStoreService; /** * Get the counter categories for a particular switch @@ -37,7 +37,9 @@ import net.floodlightcontroller.counter.CounterStore.NetworkLayer; public class SwitchCounterCategoriesResource extends CounterResourceBase { @Get("json") public Map<String, Object> retrieve() { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); HashMap<String,Object> model = new HashMap<String,Object>(); String switchID = (String) getRequestAttributes().get("switchId"); @@ -69,7 +71,7 @@ public class SwitchCounterCategoriesResource extends CounterResourceBase { try { counterName = URLDecoder.decode(counterName, "UTF-8"); layer = URLDecoder.decode(layer, "UTF-8"); - fullCounterName = switchID + CounterStore.TitleDelimitor + counterName; + fullCounterName = switchID + ICounterStoreService.TitleDelimitor + counterName; } catch (UnsupportedEncodingException e) { //Just leave counterTitle undecoded if there is an issue - fail silently } diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java index 143121417dc2ba0a715395ae3dcb2fbeb96fe435..0af59c42fa5fdb8eb46bcc66cf48395ec90a7383 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java @@ -25,9 +25,9 @@ import java.util.Map; import org.openflow.util.HexString; import org.restlet.resource.Get; -import net.floodlightcontroller.core.IFloodlightProvider; -import net.floodlightcontroller.counter.CounterStore; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.counter.ICounter; +import net.floodlightcontroller.counter.ICounterStoreService; /** * Get counters for a particular switch @@ -36,7 +36,9 @@ import net.floodlightcontroller.counter.ICounter; public class SwitchCounterResource extends CounterResourceBase { @Get("json") public Map<String, Object> retrieve() { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); HashMap<String,Object> model = new HashMap<String,Object>(); String switchID = (String) getRequestAttributes().get("switchId"); @@ -63,7 +65,7 @@ public class SwitchCounterResource extends CounterResourceBase { try { counterName = URLDecoder.decode(counterName, "UTF-8"); fullCounterName = - switchID + CounterStore.TitleDelimitor + counterName; + switchID + ICounterStoreService.TitleDelimitor + counterName; } catch (UnsupportedEncodingException e) { //Just leave counterTitle undecoded if there is an issue - fail silently } diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java index 8ea10996543a0bdf1490383a58755c94aff07fe3..83234ce62ed12bd456258056da2408b713fa2f3f 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java @@ -26,7 +26,7 @@ import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.types.MacVlanPair; @@ -66,7 +66,9 @@ public class SwitchResourceBase extends ServerResource { } protected List<OFStatistics> getSwitchStatistics(long switchId, OFStatisticsType statType) { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); IOFSwitch sw = floodlightProvider.getSwitches().get(switchId); Future<List<OFStatistics>> future; @@ -132,7 +134,9 @@ public class SwitchResourceBase extends ServerResource { * @return A list of switch table entries */ protected List<Map<String, Object>> getSwitchTableJson(long switchId) { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); IOFSwitch sw = floodlightProvider.getSwitches().get(switchId); List<Map<String, Object>> switchTableJson = null; diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java index 0f10c2538e1c888fd2db3c98a16d659b0ebf4702..41c779ba9d1e5641adf6552e613c2202d5097747 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java @@ -21,7 +21,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import org.openflow.protocol.OFFeaturesReply; @@ -42,7 +42,9 @@ public class SwitchStatisticsResource extends SwitchResourceBase { @Get("json") public Map<String, Object> retrieve() { - IFloodlightProvider floodlightProvider = (IFloodlightProvider)getApplication(); + IFloodlightProviderService floodlightProvider = + (IFloodlightProviderService)getContext().getAttributes(). + get(IFloodlightProviderService.class.getCanonicalName()); HashMap<String,Object> result = new HashMap<String,Object>(); List<OFStatistics> values = null; diff --git a/src/main/java/net/floodlightcontroller/counter/CounterStore.java b/src/main/java/net/floodlightcontroller/counter/CounterStore.java index 0da77e20088bf59851a427b6bd686884885b8495..585afc6a3f2b031933037c0ff216a2393cb0cd5d 100644 --- a/src/main/java/net/floodlightcontroller/counter/CounterStore.java +++ b/src/main/java/net/floodlightcontroller/counter/CounterStore.java @@ -35,12 +35,7 @@ import javax.annotation.PostConstruct; * @author kyle * */ -public class CounterStore { - public final static String TitleDelimitor = "__"; - - /** L2 EtherType subCategories */ - public final static String L3ET_IPV4 = "L3_IPv4"; - +public class CounterStore implements ICounterStoreService { public enum NetworkLayer { L3, L4 } @@ -121,10 +116,7 @@ public class CounterStore { return fullCounterName; } - /** - * Retrieve a list of subCategories by counterName. - * null if nothing. - */ + @Override public List<String> getAllCategories(String counterName, NetworkLayer layer) { if (layeredCategories.containsKey(layer)) { Map<String, List<String>> counterToCategories = layeredCategories.get(layer); @@ -135,14 +127,7 @@ public class CounterStore { return null; } - /** - * Create a new ICounter and set the title. Note that the title must be unique, otherwise this will - * throw an IllegalArgumentException. - * - * @param key - * @param type - * @return - */ + @Override public ICounter createCounter(String key, CounterValue.CounterType type) { CounterEntry ce; ICounter c; @@ -175,9 +160,7 @@ public class CounterStore { }}, 100, 100, TimeUnit.MILLISECONDS); } - /** - * Retrieves a counter with the given title, or null if none can be found. - */ + @Override public ICounter getCounter(String key) { CounterEntry counter = nameToCEIndex.get(key); if (counter != null) { @@ -187,11 +170,10 @@ public class CounterStore { } } - /** - * Returns an immutable map of title:counter with all of the counters in the store. - * - * (Note - this method may be slow - primarily for debugging/UI) + /* (non-Javadoc) + * @see net.floodlightcontroller.counter.ICounterStoreService#getAll() */ + @Override public Map<String, ICounter> getAll() { Map<String, ICounter> ret = new ConcurrentHashMap<String, ICounter>(); for(Map.Entry<String, CounterEntry> counterEntry : this.nameToCEIndex.entrySet()) { diff --git a/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java b/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java new file mode 100644 index 0000000000000000000000000000000000000000..86e71f8d695f148ff38e7415eb9bca2822d9007e --- /dev/null +++ b/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java @@ -0,0 +1,43 @@ +package net.floodlightcontroller.counter; + +import java.util.List; +import java.util.Map; + +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.counter.CounterStore.NetworkLayer; + +public interface ICounterStoreService extends IFloodlightService { + + public final static String TitleDelimitor = "__"; + /** L2 EtherType subCategories */ + public final static String L3ET_IPV4 = "L3_IPv4"; + + /** + * Retrieve a list of subCategories by counterName. + * null if nothing. + */ + public List<String> getAllCategories(String counterName, + NetworkLayer layer); + + /** + * Create a new ICounter and set the title. Note that the title must be + * unique, otherwise this will throw an IllegalArgumentException. + * + * @param key + * @param type + * @return + */ + public ICounter createCounter(String key, CounterValue.CounterType type); + + /** + * Retrieves a counter with the given title, or null if none can be found. + */ + public ICounter getCounter(String key); + + /** + * Returns an immutable map of title:counter with all of the counters in the store. + * + * (Note - this method may be slow - primarily for debugging/UI) + */ + public Map<String, ICounter> getAll(); +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceManager.java b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceManagerService.java similarity index 90% rename from src/main/java/net/floodlightcontroller/devicemanager/IDeviceManager.java rename to src/main/java/net/floodlightcontroller/devicemanager/IDeviceManagerService.java index 14bed96ad758f53bf2f59ac5cd4c880b2fd843e7..e0bd44f193d8026c7e78b087abb6edc3dde038be 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceManager.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceManagerService.java @@ -21,12 +21,14 @@ import java.util.Collection; import net.floodlightcontroller.core.FloodlightContextStore; +import net.floodlightcontroller.core.module.IFloodlightService; + /** * Device manager allows interacting with devices on the network. Note * that under normal circumstances, {@link Device} objects should be retrieved * from the {@link FloodlightContext} rather than from {@link IDeviceManager}. */ -public interface IDeviceManager { +public interface IDeviceManagerService extends IFloodlightService { /** * The source device for the current packet-in, if applicable. */ @@ -45,7 +47,7 @@ public interface IDeviceManager { */ public static final FloodlightContextStore<IDevice> fcStore = new FloodlightContextStore<IDevice>(); - + /** * Set the entity classifier for the device manager to use to * differentiate devices on the network. If no classifier is set, @@ -54,7 +56,7 @@ public interface IDeviceManager { * @param classifier the classifier to set. */ public void setEntityClassifier(IEntityClassifier classifier); - + /** * Flush and/or reclassify all entities in a class * @@ -63,7 +65,7 @@ public interface IDeviceManager { * flushed entities */ public void flushEntityCache(IEntityClass entityClass, boolean reclassify); - + /** * Search for a device using entity fields. Only the key fields as * defined by the {@link IEntityClassifier} will be important in this @@ -79,10 +81,16 @@ public interface IDeviceManager { public IDevice findDevice(long macAddress, Integer ipv4Address, Short vlan, Long switchDPID, Integer switchPort); - + /** * Get an unmodifiable collection view over all devices currently known. * @return the collection of all devices */ public Collection<? extends IDevice> getAllDevices(); + + /** + * Adds a listener to listen for IDeviceManagerServices notifications + * @param listener The listener that wants the notifications + */ + public void addListener(IDeviceManagerAware listener); } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index 04fe294fc8a04d73dd9f6793f556292b9dffb6fb..3ce0d6d832a62ae1984cc228e130498f5f4617a7 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -22,28 +22,35 @@ import java.util.Collection; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitchListener; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.devicemanager.IDevice; -import net.floodlightcontroller.devicemanager.IDeviceManager; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.devicemanager.IEntityClassifier; import net.floodlightcontroller.devicemanager.IEntityClassifier.EntityField; +import net.floodlightcontroller.devicemanager.IDeviceManagerAware; import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.DHCP; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.packet.UDP; -import net.floodlightcontroller.storage.IStorageSource; +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.IStorageSourceListener; -import net.floodlightcontroller.topology.ITopology; -import net.floodlightcontroller.topology.ITopologyAware; +import net.floodlightcontroller.topology.ITopologyService; +import net.floodlightcontroller.topology.ITopologyListener; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFPortStatus; @@ -57,21 +64,23 @@ import org.slf4j.LoggerFactory; * within the network. * @author readams */ -public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, - IOFSwitchListener, ITopologyAware, IStorageSourceListener { +public class DeviceManagerImpl implements + IDeviceManagerService, IOFMessageListener, + IOFSwitchListener, ITopologyListener, + IStorageSourceListener, IFloodlightModule { protected static Logger logger = LoggerFactory.getLogger(DeviceManagerImpl.class); - protected IFloodlightProvider floodlightProvider; - protected ITopology topology; - protected IStorageSource storageSource; + protected IFloodlightProviderService floodlightProvider; + protected ITopologyService topology; + protected IStorageSourceService storageSource; /** * This is the master device map that maps device IDs to {@link Device} * objects. */ protected ConcurrentHashMap<Long, Device> deviceMap; - + /** * Counter used to generate device keys */ @@ -135,10 +144,13 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, if (!keyFieldsMatchPrimary) classIndex = new ConcurrentHashMap<IndexedEntity, Long>(); } - - } + /** + * Device manager event listeners + */ + protected Set<IDeviceManagerAware> deviceManagerAware; + // ************** // IDeviceManager // ************** @@ -171,11 +183,15 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, return Collections.unmodifiableCollection(deviceMap.values()); } + @Override + public void addListener(IDeviceManagerAware listener) { + deviceManagerAware.add(listener); + } + // ****************** // IOFMessageListener // ****************** - @Override public String getName() { return "devicemanager"; @@ -280,27 +296,54 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, // TODO Auto-generated method stub } - // ************** - // Initialization - // ************** - - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { - this.floodlightProvider = floodlightProvider; + // ***************** + // IFloodlightModule + // ***************** + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IDeviceManagerService.class); + return l; } - public void setStorageSource(IStorageSource storageSource) { - this.storageSource = storageSource; + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + // We are the class that implements the service + m.put(IDeviceManagerService.class, this); + return m; } - public void setTopology(ITopology topology) { - this.topology = topology; + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IFloodlightProviderService.class); + l.add(IStorageSourceService.class); + l.add(ITopologyService.class); + return l; } - - public void init() { + + @Override + public void init(FloodlightModuleContext fmc) { + this.deviceManagerAware = new HashSet<IDeviceManagerAware>(); + this.floodlightProvider = + fmc.getServiceImpl(IFloodlightProviderService.class); + this.storageSource = + fmc.getServiceImpl(IStorageSourceService.class); + this.topology = + fmc.getServiceImpl(ITopologyService.class); } - - public void startUp() { + + @Override + public void startUp(FloodlightModuleContext fmc) { if (entityClassifier == null) setEntityClassifier(new DefaultEntityClassifier()); @@ -309,8 +352,16 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, classStateMap = new ConcurrentHashMap<IEntityClass, ClassState>(); + if (topology != null) { + // Register to get updates from topology + topology.addListener(this); + } else { + logger.error("Could add not toplogy listener"); + } + floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this); + floodlightProvider.addOFSwitchListener(this); // XXX - TODO entity aging timer } @@ -336,8 +387,8 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, FloodlightContext cntx) { try { Ethernet eth = - IFloodlightProvider.bcStore. - get(cntx,IFloodlightProvider.CONTEXT_PI_PAYLOAD); + IFloodlightProviderService.bcStore. + get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD); // Extract source entity information Entity srcEntity = @@ -734,5 +785,4 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, return true; } - } diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index 9fd7fb857150cbd15003ecccdb670d6cc130c905..7a59d45a18f2f0b6abe39c0da4442468aadf64de 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -21,19 +21,27 @@ package net.floodlightcontroller.forwarding; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Map; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.devicemanager.IDevice; -import net.floodlightcontroller.devicemanager.IDeviceManager; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; import net.floodlightcontroller.devicemanager.SwitchPort; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.routing.ForwardingBase; import net.floodlightcontroller.routing.IRoutingDecision; +import net.floodlightcontroller.routing.IRoutingEngineService; import net.floodlightcontroller.routing.Route; +import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.LinkInfo; import net.floodlightcontroller.topology.SwitchPortTuple; @@ -48,13 +56,13 @@ import org.openflow.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Forwarding extends ForwardingBase { +public class Forwarding extends ForwardingBase implements IFloodlightModule { protected static Logger log = LoggerFactory.getLogger(Forwarding.class); @Override public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { - Ethernet eth = IFloodlightProvider.bcStore.get(cntx, - IFloodlightProvider.CONTEXT_PI_PAYLOAD); + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD); if (eth.isBroadcast() || eth.isMulticast()) { // For now we treat multicast as broadcast doFlood(sw, pi, cntx); @@ -73,13 +81,13 @@ public class Forwarding extends ForwardingBase { // Check if we have the location of the destination IDevice dstDevice = - IDeviceManager.fcStore.get(cntx, - IDeviceManager.CONTEXT_DST_DEVICE); + IDeviceManagerService.fcStore. + get(cntx, IDeviceManagerService.CONTEXT_DST_DEVICE); if (dstDevice != null) { IDevice srcDevice = - IDeviceManager.fcStore. - get(cntx, IDeviceManager.CONTEXT_SRC_DEVICE); + IDeviceManagerService.fcStore. + get(cntx, IDeviceManagerService.CONTEXT_SRC_DEVICE); Long srcIsland = sw.getSwitchClusterId(); if (srcDevice == null) { @@ -262,4 +270,48 @@ public class Forwarding extends ForwardingBase { return srcTuple.getSwitchDPID() == dstTuple.getSwitchDPID() && srcTuple.getPort() != dstTuple.getPort(); } + + // IFloodlightModule methods + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + // We don't export any services + return null; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + // We don't have any services + return null; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IFloodlightProviderService.class); + l.add(IDeviceManagerService.class); + l.add(IRoutingEngineService.class); + l.add(ITopologyService.class); + l.add(ICounterStoreService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + this.setFloodlightProvider(context.getServiceImpl(IFloodlightProviderService.class)); + this.setDeviceManager(context.getServiceImpl(IDeviceManagerService.class)); + this.setRoutingEngine(context.getServiceImpl(IRoutingEngineService.class)); + this.setTopology(context.getServiceImpl(ITopologyService.class)); + this.setCounterStore(context.getServiceImpl(ICounterStoreService.class)); + } + + @Override + public void startUp(FloodlightModuleContext context) { + if (log.isDebugEnabled()) { + log.debug("Starting " + this.getClass().getCanonicalName()); + } + super.startUp(); + } } diff --git a/src/main/java/net/floodlightcontroller/hub/Hub.java b/src/main/java/net/floodlightcontroller/hub/Hub.java index 29b26f31610f939db6296f72bb59c78b843f94d0..db20e43f069643e0d9b29d9d9db3d0c800b787b2 100644 --- a/src/main/java/net/floodlightcontroller/hub/Hub.java +++ b/src/main/java/net/floodlightcontroller/hub/Hub.java @@ -21,7 +21,7 @@ import java.io.IOException; import java.util.Collections; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; @@ -43,12 +43,12 @@ import org.slf4j.LoggerFactory; public class Hub implements IOFMessageListener { protected static Logger log = LoggerFactory.getLogger(Hub.class); - protected IFloodlightProvider floodlightProvider; + protected IFloodlightProviderService floodlightProvider; /** * @param floodlightProvider the floodlightProvider to set */ - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { + public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } diff --git a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java index 0c1a383380da6708fe228ad3c7a686f4be4ec8cd..f677a76f7bef219aa44ff0dd314d09ec5ceab43e 100644 --- a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java +++ b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java @@ -35,12 +35,13 @@ import java.util.Arrays; import java.util.List; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.counter.CounterStore; import net.floodlightcontroller.counter.CounterValue; import net.floodlightcontroller.counter.ICounter; +import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.packet.Ethernet; import org.openflow.protocol.OFError; @@ -62,8 +63,8 @@ import org.slf4j.LoggerFactory; public class LearningSwitch implements IOFMessageListener { protected static Logger log = LoggerFactory.getLogger(LearningSwitch.class); - protected IFloodlightProvider floodlightProvider; - protected CounterStore counterStore; + protected IFloodlightProviderService floodlightProvider; + protected ICounterStoreService counterStore; // flow-mod - for use in the cookie public static final int LEARNING_SWITCH_APP_ID = 1; @@ -84,15 +85,15 @@ public class LearningSwitch implements IOFMessageListener { /** * @param floodlightProvider the floodlightProvider to set */ - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { + public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } - public CounterStore getCounterStore() { + public ICounterStoreService getCounterStore() { return counterStore; } - public void setCounterStore(CounterStore counterStore) { + public void setCounterStore(ICounterStoreService counterStore) { this.counterStore = counterStore; } @@ -257,7 +258,7 @@ public class LearningSwitch implements IOFMessageListener { } } - private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi) { + private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { // Read in packet data headers by using OFMatch OFMatch match = new OFMatch(); match.loadFromPacket(pi.getPacketData(), pi.getInPort(), sw.getId()); @@ -378,7 +379,7 @@ public class LearningSwitch implements IOFMessageListener { public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: - return this.processPacketInMessage(sw, (OFPacketIn) msg); + return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx); case PORT_STATUS: return this.processPortStatusMessage(sw, (OFPortStatus) msg); case FLOW_REMOVED: diff --git a/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java b/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java index 9af4ba19659f5888bd5581a8d7609c053c44b2e1..70f5735aaf89105fc2bf378b9cb0a518e4119268 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java +++ b/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java @@ -191,7 +191,7 @@ public class CumulativeTimeBucket { cumulativeTimeBkt.avgTotalProcTime_us = 0; cumulativeTimeBkt.sigmaTotalProcTime_us = 0; for (int idx = FlListenerID.FL_FIRST_LISTENER_ID; - idx <= PktinProcessingTime.BB_LAST_LISTENER_ID; idx++) { + idx <= PktInProcessingTime.BB_LAST_LISTENER_ID; idx++) { OneComponentTime oct = cumulativeTimeBkt.tComps.oneComp[idx]; oct.pktCnt = 0; oct.sumProcTime_us = 0; diff --git a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java new file mode 100644 index 0000000000000000000000000000000000000000..b6bf1dd9e8349e3810b818532715a54f6eed1778 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java @@ -0,0 +1,43 @@ +package net.floodlightcontroller.perfmon; + +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.perfmon.PktInProcessingTime.CircularTimeBucketSet; +import net.floodlightcontroller.perfmon.PktInProcessingTime.PerfMonConfigs; + +public interface IPktInProcessingTimeService extends IFloodlightService { + + public Long getLastPktTime_ns(); + + public void setLastPktTime_ns(Long lastPktTime_ns); + + public long getCurBucketStartTime(); + + public void setCurBucketStartTime(long curBucketStartTime); + + public CumulativeTimeBucket getCtb(); + + public void setCtb(CumulativeTimeBucket ctb); + + public CircularTimeBucketSet getCtbs(); + + public void setCtbs(CircularTimeBucketSet ctbs); + + public PerfMonConfigs getPerfMonCfgs(); + + public void setPerfMonCfgs(PerfMonConfigs perfMonCfgs); + + public int getNumComponents(); + + public void setNumComponents(int numComponents); + + public long getStartTimeOnePkt(); + + // Component refers to software component like forwarding + public long getStartTimeOneComponent(); + + public void updateCumulativeTimeOneComp(long onePktOneCompProcTime_ns, + int id); + + public void updateCumulativeTimeTotal(long onePktStartTime_ns); + +} diff --git a/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java similarity index 76% rename from src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java rename to src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java index c0e7dfa03c7c02355d5a9370f465c4d2863bca4c..ea89fd824200f4da76e10827118bec859bf57095 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java @@ -3,7 +3,16 @@ */ package net.floodlightcontroller.perfmon; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + import net.floodlightcontroller.core.IOFMessageListener.FlListenerID; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,7 +21,8 @@ import org.slf4j.LoggerFactory; * @author subrata * */ -public class PktinProcessingTime { +public class PktInProcessingTime + implements IFloodlightModule, IPktInProcessingTimeService { /*** * This class contains a set of buckets (called time buckets as the @@ -40,7 +50,7 @@ public class PktinProcessingTime { */ protected static Logger logger = - LoggerFactory.getLogger(PktinProcessingTime.class); + LoggerFactory.getLogger(PktInProcessingTime.class); /*** * procTimeMonitoringState: true if monitoring is on, default is false @@ -85,7 +95,7 @@ public class PktinProcessingTime { } } - protected PerfMonConfigs perfMonCfgs; + protected PerfMonConfigs perfMonCfgs; // Maintains the time when the last packet was processed protected long lastPktTime_ns; protected long curBucketStartTime; @@ -96,39 +106,87 @@ public class PktinProcessingTime { private int numBuckets; // number of time buckets, each 10s long + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getLastPktTime_ns() + */ + @Override public Long getLastPktTime_ns() { return lastPktTime_ns; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#setLastPktTime_ns(java.lang.Long) + */ + @Override public void setLastPktTime_ns(Long lastPktTime_ns) { this.lastPktTime_ns = lastPktTime_ns; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getCurBucketStartTime() + */ + @Override public long getCurBucketStartTime() { return curBucketStartTime; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#setCurBucketStartTime(long) + */ + @Override public void setCurBucketStartTime(long curBucketStartTime) { this.curBucketStartTime = curBucketStartTime; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getCtb() + */ + @Override public CumulativeTimeBucket getCtb() { return ctb; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#setCtb(net.floodlightcontroller.perfmon.CumulativeTimeBucket) + */ + @Override public void setCtb(CumulativeTimeBucket ctb) { this.ctb = ctb; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getCtbs() + */ + @Override public CircularTimeBucketSet getCtbs() { return ctbs; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#setCtbs(net.floodlightcontroller.perfmon.PktinProcessingTime.CircularTimeBucketSet) + */ + @Override public void setCtbs(CircularTimeBucketSet ctbs) { this.ctbs = ctbs; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getPerfMonCfgs() + */ + @Override public PerfMonConfigs getPerfMonCfgs() { return perfMonCfgs; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#setPerfMonCfgs(net.floodlightcontroller.perfmon.PktinProcessingTime.PerfMonConfigs) + */ + @Override public void setPerfMonCfgs(PerfMonConfigs perfMonCfgs) { this.perfMonCfgs = perfMonCfgs; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getNumComponents() + */ + @Override public int getNumComponents() { return numComponents; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#setNumComponents(int) + */ + @Override public void setNumComponents(int numComponents) { this.numComponents = numComponents; } @@ -139,18 +197,7 @@ public class PktinProcessingTime { public void setNumBuckets(int numBuckets) { this.numBuckets = numBuckets; } - // Constructor - public PktinProcessingTime() { - FlListenerID.populateCompNames(); - setNumComponents(BB_LAST_LISTENER_ID + 1); - perfMonCfgs = new PerfMonConfigs(); - numBuckets = BUCKET_SET_SIZE; - ctbs = new CircularTimeBucketSet(getNumComponents(), numBuckets); - ctb = ctbs.timeBucketSet[ctbs.curBucketIdx]; - ctb.startTime_ms = System.currentTimeMillis(); - ctb.startTime_ns = System.nanoTime(); - } - + /*** * BUCKET_SET_SIZE buckets each holding 10s of processing time data, a total * of 30*10s = 5mins of processing time data is maintained @@ -217,6 +264,10 @@ public class PktinProcessingTime { } } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getStartTimeOnePkt() + */ + @Override public long getStartTimeOnePkt() { if (this.perfMonCfgs.procTimeMonitoringState) { long startTime_ns = System.nanoTime(); @@ -227,6 +278,10 @@ public class PktinProcessingTime { } // Component refers to software component like forwarding + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#getStartTimeOneComponent() + */ + @Override public long getStartTimeOneComponent() { if (this.perfMonCfgs.procTimeMonitoringState) { return System.nanoTime(); @@ -234,6 +289,10 @@ public class PktinProcessingTime { return 0L; } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#updateCumulativeTimeOneComp(long, int) + */ + @Override public void updateCumulativeTimeOneComp( long onePktOneCompProcTime_ns, int id) { if (this.perfMonCfgs.procTimeMonitoringState) { @@ -253,6 +312,10 @@ public class PktinProcessingTime { } } + /* (non-Javadoc) + * @see net.floodlightcontroller.perfmon.IPktInProcessingTimeService#updateCumulativeTimeTotal(long) + */ + @Override public void updateCumulativeTimeTotal(long onePktStartTime_ns) { if (this.perfMonCfgs.procTimeMonitoringState) { // There is no api to get time in microseconds, milliseconds is @@ -374,4 +437,55 @@ public class PktinProcessingTime { ctb.initializeCumulativeTimeBucket(ctb); } } + + public PktInProcessingTime() { + perfMonCfgs = new PerfMonConfigs(); + } + + // IFloodlightModule methods + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IPktInProcessingTimeService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + // We are the class that implements the service + m.put(IPktInProcessingTimeService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + // We don't have any dependencies + return null; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + // no-op + } + + @Override + public void startUp(FloodlightModuleContext context) { + // Our 'constructor' + FlListenerID.populateCompNames(); + setNumComponents(BB_LAST_LISTENER_ID + 1); + perfMonCfgs = new PerfMonConfigs(); + numBuckets = BUCKET_SET_SIZE; + ctbs = new CircularTimeBucketSet(getNumComponents(), numBuckets); + ctb = ctbs.timeBucketSet[ctbs.curBucketIdx]; + ctb.startTime_ms = System.currentTimeMillis(); + ctb.startTime_ns = System.nanoTime(); + } } diff --git a/src/main/java/net/floodlightcontroller/restserver/IRestApiService.java b/src/main/java/net/floodlightcontroller/restserver/IRestApiService.java new file mode 100644 index 0000000000000000000000000000000000000000..d90679580e0adfbc645368dac58c179ef1490846 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/restserver/IRestApiService.java @@ -0,0 +1,16 @@ +package net.floodlightcontroller.restserver; + +import net.floodlightcontroller.core.module.IFloodlightService; + +public interface IRestApiService extends IFloodlightService { + /** + * Adds a REST API + * @param routeable + */ + public void addRestletRoutable(RestletRoutable routable); + + /** + * Runs the REST API server + */ + public void run(); +} diff --git a/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java b/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java new file mode 100644 index 0000000000000000000000000000000000000000..95a3b8dee730dbc6c21fbc1c733a3111deae3bad --- /dev/null +++ b/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java @@ -0,0 +1,158 @@ +package net.floodlightcontroller.restserver; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.restlet.Application; +import org.restlet.Component; +import org.restlet.Context; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.Restlet; +import org.restlet.data.Protocol; +import org.restlet.data.Reference; +import org.restlet.routing.Filter; +import org.restlet.routing.Router; +import org.restlet.routing.Template; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.core.web.JacksonCustomConverter; + +public class RestApiServer + implements IFloodlightModule, IRestApiService { + protected static Logger logger = LoggerFactory.getLogger(RestApiServer.class); + protected List<RestletRoutable> restlets; + protected int restPort = 8080; + protected FloodlightModuleContext fmlContext; + + // *********** + // Application + // *********** + + protected class RestApplication extends Application { + protected Context context; + + public RestApplication() { + super(new Context()); + this.context = getContext(); + } + + @Override + public Restlet createInboundRoot() { + Router baseRouter = new Router(context); + baseRouter.setDefaultMatchingMode(Template.MODE_STARTS_WITH); + for (RestletRoutable rr : restlets) { + baseRouter.attach(rr.basePath(), rr.getRestlet(context)); + } + + Filter slashFilter = new Filter() { + @Override + protected int beforeHandle(Request request, Response response) { + Reference ref = request.getResourceRef(); + String originalPath = ref.getPath(); + if (originalPath.contains("//")) + { + String newPath = originalPath.replaceAll("/+", "/"); + ref.setPath(newPath); + } + return Filter.CONTINUE; + } + + }; + slashFilter.setNext(baseRouter); + + return slashFilter; + } + + public void run(FloodlightModuleContext fmlContext) { + // Add everything in the module context to the rest + for (Class<? extends IFloodlightService> s : fmlContext.getAllServices()) { + context.getAttributes().put(s.getCanonicalName(), + fmlContext.getServiceImpl(s)); + } + + // Use our custom serializers + JacksonCustomConverter.replaceConverter(); + + // Start listening for REST requests + try { + final Component component = new Component(); + component.getServers().add(Protocol.HTTP, restPort); + component.getDefaultHost().attach(this); + component.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + // *************** + // IRestApiService + // *************** + + @Override + public void addRestletRoutable(RestletRoutable routable) { + if (logger.isDebugEnabled()) { + logger.debug("Adding REST API routable " + + routable.getClass().getCanonicalName()); + } + restlets.add(routable); + } + + @Override + public void run() { + RestApplication restApp = new RestApplication(); + restApp.run(fmlContext); + } + + // ***************** + // IFloodlightModule + // ***************** + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> services = + new ArrayList<Class<? extends IFloodlightService>>(1); + services.add(IRestApiService.class); + return services; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + m.put(IRestApiService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + // We don't have any + return null; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + // This has to be done here since we don't know what order the + // startUp methods will be called + this.restlets = new ArrayList<RestletRoutable>(); + this.fmlContext = context; + } + + @Override + public void startUp(FloodlightModuleContext Context) { + // no-op + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/web/RestletRoutable.java b/src/main/java/net/floodlightcontroller/restserver/RestletRoutable.java similarity index 96% rename from src/main/java/net/floodlightcontroller/core/web/RestletRoutable.java rename to src/main/java/net/floodlightcontroller/restserver/RestletRoutable.java index a0dd751dad4a9b577d80a090dee2528f7919a339..cb7dfce8c26e8aa7eb83a1e6f2cc688345d564ff 100644 --- a/src/main/java/net/floodlightcontroller/core/web/RestletRoutable.java +++ b/src/main/java/net/floodlightcontroller/restserver/RestletRoutable.java @@ -15,7 +15,7 @@ * under the License. **/ -package net.floodlightcontroller.core.web; +package net.floodlightcontroller.restserver; import org.restlet.Context; import org.restlet.Restlet; diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index 37dea45a0b81f49c1f897bb3ae3c6d0e5e71d4c2..1987d0fac511bff6eef9f0c38ea471fee890ec72 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -1,19 +1,19 @@ /** -* 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. -**/ + * 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.routing; @@ -24,24 +24,25 @@ import java.util.List; import java.util.Map; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.counter.CounterStore; import net.floodlightcontroller.counter.CounterValue; import net.floodlightcontroller.counter.ICounter; +import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.devicemanager.DeviceNetworkAddress; -import net.floodlightcontroller.devicemanager.IDeviceManager; import net.floodlightcontroller.devicemanager.IDeviceManagerAware; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; import net.floodlightcontroller.devicemanager.SwitchPort; import net.floodlightcontroller.devicemanager.internal.Device; import net.floodlightcontroller.packet.Ethernet; -import net.floodlightcontroller.routing.IRoutingEngine; +import net.floodlightcontroller.routing.IRoutingEngineService; import net.floodlightcontroller.routing.IRoutingDecision; import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Route; -import net.floodlightcontroller.topology.ITopology; +import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.SwitchPortTuple; import org.openflow.protocol.OFFlowMod; @@ -58,151 +59,197 @@ import org.openflow.util.U16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class ForwardingBase implements IOFMessageListener, IDeviceManagerAware { - protected static Logger log = LoggerFactory.getLogger(ForwardingBase.class); - - public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT=5; // in seconds - - protected IFloodlightProvider floodlightProvider; - protected IDeviceManager deviceManager; - protected IRoutingEngine routingEngine; - protected ITopology topology; - protected CounterStore counterStore; - +public abstract class ForwardingBase implements + IOFMessageListener, + IDeviceManagerAware { + protected static Logger log = + LoggerFactory.getLogger(ForwardingBase.class); + + public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT = 5; // in seconds + + protected IFloodlightProviderService floodlightProvider; + protected IDeviceManagerService deviceManager; + protected IRoutingEngineService routingEngine; + protected ITopologyService topology; + protected ICounterStoreService counterStore; + // flow-mod - for use in the cookie - public static final int FORWARDING_APP_ID = 2; // TODO: This must be managed by a global APP_ID class + public static final int FORWARDING_APP_ID = 2; // TODO: This must be managed + // by a global APP_ID class // Comparator for sorting by SwitchCluster public Comparator<SwitchPort> clusterIdComparator = new Comparator<SwitchPort>() { - @Override - public int compare(SwitchPort d1, SwitchPort d2) { - Map<Long, IOFSwitch> switches = floodlightProvider.getSwitches(); - IOFSwitch sw1 = switches.get(d1.getSwitchDPID()); - IOFSwitch sw2 = switches.get(d2.getSwitchDPID()); - - Long d1ClusterId = sw1.getSwitchClusterId(); - Long d2ClusterId = sw2.getSwitchClusterId(); - - return d1ClusterId.compareTo(d2ClusterId); - } - }; - + @Override + public int compare(SwitchPort d1, SwitchPort d2) { + Map<Long, IOFSwitch> switches = + floodlightProvider.getSwitches(); + IOFSwitch sw1 = switches.get(d1.getSwitchDPID()); + IOFSwitch sw2 = switches.get(d2.getSwitchDPID()); + + Long d1ClusterId = sw1.getSwitchClusterId(); + Long d2ClusterId = sw2.getSwitchClusterId(); + + return d1ClusterId.compareTo(d2ClusterId); + } + }; + public void startUp() { + deviceManager.addListener(this); floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); } - public void shutDown() { - floodlightProvider.removeOFMessageListener(OFType.PACKET_IN, this); - } - @Override public String getName() { return "forwarding"; } - + @Override public int getId() { return FlListenerID.FORWARDINGBASE; } /** - * All subclasses must define this function if they want any specific forwarding action - * @param sw Switch that the packet came in from - * @param pi The packet that came in - * @param decision Any decision made by a policy engine + * All subclasses must define this function if they want any specific + * forwarding action + * + * @param sw + * Switch that the packet came in from + * @param pi + * The packet that came in + * @param decision + * Any decision made by a policy engine */ - public abstract Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx); + public abstract Command + processPacketInMessage(IOFSwitch sw, OFPacketIn pi, + IRoutingDecision decision, + FloodlightContext cntx); @Override - public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { + public Command receive(IOFSwitch sw, OFMessage msg, + FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: IRoutingDecision decision = null; - if (cntx != null) decision = - IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); - - return this.processPacketInMessage(sw, (OFPacketIn) msg, decision, cntx); + if (cntx != null) + decision = + IRoutingDecision.rtStore.get(cntx, + IRoutingDecision.CONTEXT_DECISION); + + return this.processPacketInMessage(sw, + (OFPacketIn) msg, + decision, + cntx); } - log.error("received an unexpected message {} from switch {}", msg, sw); + log.error("received an unexpected message {} from switch {}", + msg, + sw); return Command.CONTINUE; } private void updateCounterStore(IOFSwitch sw, OFFlowMod flowMod) { if (counterStore != null) { String packetName = flowMod.getType().toClass().getName(); - packetName = packetName.substring(packetName.lastIndexOf('.')+1); + packetName = + packetName.substring(packetName.lastIndexOf('.') + 1); // flowmod is per switch. portid = -1 - String counterName = CounterStore.createCounterName(sw.getStringId(), -1, packetName); + String counterName = + CounterStore.createCounterName(sw.getStringId(), + -1, + packetName); try { ICounter counter = counterStore.getCounter(counterName); if (counter == null) { - counter = counterStore.createCounter(counterName, CounterValue.CounterType.LONG); + counter = + counterStore.createCounter(counterName, + CounterValue.CounterType.LONG); } counter.increment(); - } - catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { log.error("Invalid Counter, " + counterName); } } } - + /** * Push routes from back to front - * @param route Route to push - * @param match OpenFlow fields to match on - * @param srcSwPort Source switch port for the first hop - * @param dstSwPort Destination switch port for final hop - * @param bufferId BufferId of the original PacketIn - * @return srcSwitchIincluded True if the source switch is included in this route + * + * @param route + * Route to push + * @param match + * OpenFlow fields to match on + * @param srcSwPort + * Source switch port for the first hop + * @param dstSwPort + * Destination switch port for final hop + * @param bufferId + * BufferId of the original PacketIn + * @return srcSwitchIincluded True if the source switch is included in this + * route */ - public boolean pushRoute(Route route, OFMatch match, - Integer wildcard_hints, - SwitchPort srcSwPort, - SwitchPort dstSwPort, - int bufferId, - IOFSwitch srcSwitch, - OFPacketIn pi, + public boolean pushRoute(Route route, OFMatch match, + Integer wildcard_hints, SwitchPort srcSwPort, + SwitchPort dstSwPort, int bufferId, + IOFSwitch srcSwitch, OFPacketIn pi, FloodlightContext cntx, boolean reqeustFlowRemovedNotifn) { long cookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); - return pushRoute(route, match, wildcard_hints, srcSwPort, dstSwPort, - bufferId, srcSwitch, pi, cookie, cntx, reqeustFlowRemovedNotifn); + return pushRoute(route, + match, + wildcard_hints, + srcSwPort, + dstSwPort, + bufferId, + srcSwitch, + pi, + cookie, + cntx, + reqeustFlowRemovedNotifn); } - + /** * Push routes from back to front - * @param route Route to push - * @param match OpenFlow fields to match on - * @param srcSwPort Source switch port for the first hop - * @param dstSwPort Destination switch port for final hop - * @param bufferId BufferId of the original PacketIn - * @param cookie The cookie to set in each flow_mod - * @return srcSwitchIincluded True if the source switch is included in this route + * + * @param route + * Route to push + * @param match + * OpenFlow fields to match on + * @param srcSwPort + * Source switch port for the first hop + * @param dstSwPort + * Destination switch port for final hop + * @param bufferId + * BufferId of the original PacketIn + * @param cookie + * The cookie to set in each flow_mod + * @return srcSwitchIincluded True if the source switch is included in this + * route */ - public boolean pushRoute(Route route, OFMatch match, Integer wildcard_hints, - SwitchPort srcSwPort, + public boolean pushRoute(Route route, OFMatch match, + Integer wildcard_hints, SwitchPort srcSwPort, SwitchPort dstSwPort, int bufferId, - IOFSwitch srcSwitch, OFPacketIn pi, long cookie, - FloodlightContext cntx, + IOFSwitch srcSwitch, OFPacketIn pi, + long cookie, FloodlightContext cntx, boolean reqeustFlowRemovedNotifn) { boolean srcSwitchIncluded = false; - OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD); + OFFlowMod fm = + (OFFlowMod) floodlightProvider.getOFMessageFactory() + .getMessage(OFType.FLOW_MOD); OFActionOutput action = new OFActionOutput(); List<OFAction> actions = new ArrayList<OFAction>(); actions.add(action); - fm.setIdleTimeout((short)5) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setCookie(cookie) - .setMatch(match) - .setActions(actions) - .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH); + fm.setIdleTimeout((short) 5) + .setBufferId(OFPacketOut.BUFFER_ID_NONE) + .setCookie(cookie) + .setMatch(match) + .setActions(actions) + .setLengthU(OFFlowMod.MINIMUM_LENGTH + + OFActionOutput.MINIMUM_LENGTH); Map<Long, IOFSwitch> switches = floodlightProvider.getSwitches(); IOFSwitch sw = switches.get(dstSwPort.getSwitchDPID()); - ((OFActionOutput)fm.getActions().get(0)). - setPort((short)dstSwPort.getPort()); + ((OFActionOutput) fm.getActions().get(0)).setPort((short) dstSwPort.getPort()); if (route != null) { for (int routeIndx = route.getPath().size() - 1; routeIndx >= 0; --routeIndx) { @@ -213,14 +260,22 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag updateCounterStore(sw, fm); if (log.isDebugEnabled()) { log.debug("Pushing Route flowmod routeIndx={} sw={} inPort={} outPort={}", - new Object[] { routeIndx, sw, fm.getMatch().getInputPort(), - ((OFActionOutput)fm.getActions().get(0)).getPort() }); + new Object[] { + routeIndx, + sw, + fm.getMatch().getInputPort(), + ((OFActionOutput) fm.getActions() + .get(0)).getPort() }); } sw.write(fm, cntx); // Push the packet out the source switch if (sw.getId() == srcSwitch.getId()) { - pushPacket(srcSwitch, match, pi, ((OFActionOutput)fm.getActions().get(0)).getPort(), cntx); + pushPacket(srcSwitch, + match, + pi, + ((OFActionOutput) fm.getActions().get(0)).getPort(), + cntx); srcSwitchIncluded = true; } } catch (IOException e) { @@ -233,34 +288,43 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag } // setup for the next loop iteration - ((OFActionOutput)fm.getActions().get(0)).setPort(link.getOutPort()); + ((OFActionOutput) fm.getActions().get(0)).setPort(link.getOutPort()); if (routeIndx > 0) { - sw = floodlightProvider.getSwitches().get(route.getPath().get(routeIndx-1).getDst()); + sw = + floodlightProvider.getSwitches() + .get(route.getPath() + .get(routeIndx - 1) + .getDst()); } else { - sw = floodlightProvider.getSwitches().get(route.getId().getSrc()); + sw = + floodlightProvider.getSwitches() + .get(route.getId().getSrc()); } if (sw == null) { if (log.isWarnEnabled()) { log.warn("Unable to push route, switch at DPID {} not available", - (routeIndx > 0) ? HexString.toHexString(route.getPath() - .get(routeIndx - 1).getDst()) : HexString - .toHexString(route.getId().getSrc())); + (routeIndx > 0) + ? HexString.toHexString(route.getPath() + .get(routeIndx - 1) + .getDst()) + : HexString.toHexString(route.getId() + .getSrc())); } return srcSwitchIncluded; } } } - + // set the original match for the first switch, and buffer id fm.setMatch(match); fm.setBufferId(bufferId); fm.setMatch(wildcard(match, sw, wildcard_hints)); - fm.getMatch().setInputPort((short)srcSwPort.getPort()); - // Set the flag to request flow-mod removal notifications only for the + fm.getMatch().setInputPort((short) srcSwPort.getPort()); + // Set the flag to request flow-mod removal notifications only for the // source switch. The removal message is used to maintain the flow // cache. Don't set the flag for ARP messages - TODO generalize check - if ((reqeustFlowRemovedNotifn) && - (match.getDataLayerType() != Ethernet.TYPE_ARP)) { + if ((reqeustFlowRemovedNotifn) + && (match.getDataLayerType() != Ethernet.TYPE_ARP)) { fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM); match.setWildcards(fm.getMatch().getWildcards()); } @@ -268,15 +332,21 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag updateCounterStore(sw, fm); try { log.debug("pushRoute flowmod sw={} inPort={} outPort={}", - new Object[] { sw, fm.getMatch().getInputPort(), - ((OFActionOutput)fm.getActions().get(0)).getPort() }); + new Object[] { + sw, + fm.getMatch().getInputPort(), + ((OFActionOutput) fm.getActions().get(0)).getPort() }); log.info("Flow mod sent: Wildcard={} match={}", - Integer.toHexString(fm.getMatch().getWildcards()), - fm.getMatch().toString()); + Integer.toHexString(fm.getMatch().getWildcards()), + fm.getMatch().toString()); sw.write(fm, cntx); if (sw.getId() == srcSwitch.getId()) { - pushPacket(srcSwitch, match, pi, ((OFActionOutput)fm.getActions().get(0)).getPort(), cntx); + pushPacket(srcSwitch, + match, + pi, + ((OFActionOutput) fm.getActions().get(0)).getPort(), + cntx); srcSwitchIncluded = true; } match = fm.getMatch(); @@ -287,37 +357,43 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag return srcSwitchIncluded; } - protected OFMatch wildcard(OFMatch match, IOFSwitch sw, Integer wildcard_hints) { + protected OFMatch wildcard(OFMatch match, IOFSwitch sw, + Integer wildcard_hints) { if (wildcard_hints != null) { return match.clone().setWildcards(wildcard_hints.intValue()); } return match.clone(); } - public void pushPacket(IOFSwitch sw, OFMatch match, OFPacketIn pi, short outport, FloodlightContext cntx) { - + public void pushPacket(IOFSwitch sw, OFMatch match, OFPacketIn pi, + short outport, FloodlightContext cntx) { + if (pi == null) { return; } - + if (log.isDebugEnabled()) { - log.debug("PacketOut srcSwitch={} match={} pi={}", new Object[] {sw, match, pi}); + log.debug("PacketOut srcSwitch={} match={} pi={}", + new Object[] { sw, match, pi }); } - - OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); + + OFPacketOut po = + (OFPacketOut) floodlightProvider.getOFMessageFactory() + .getMessage(OFType.PACKET_OUT); // set actions List<OFAction> actions = new ArrayList<OFAction>(); actions.add(new OFActionOutput(outport, (short) 0)); po.setActions(actions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); - short poLength = (short)(po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); - + .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); + short poLength = + (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); + // set buffer_id, in_port po.setBufferId(pi.getBufferId()); po.setInPort(pi.getInPort()); - + // set data - only if buffer_id == -1 if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { byte[] packetData = pi.getPacketData(); @@ -326,7 +402,7 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag } po.setLength(poLength); - + try { sw.write(po, cntx); } catch (IOException e) { @@ -334,40 +410,44 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag } } - public static boolean blockHost(IFloodlightProvider floodlightProvider, - SwitchPortTuple sw_tup, long host_mac, - short hardTimeout) { + public static boolean + blockHost(IFloodlightProviderService floodlightProvider, + SwitchPortTuple sw_tup, long host_mac, + short hardTimeout) { if ((sw_tup == null) || sw_tup.getSw() == null) { return false; } IOFSwitch sw = sw_tup.getSw(); - short inputPort = sw_tup.getPort().shortValue(); + short inputPort = sw_tup.getPort().shortValue(); log.debug("blockHost sw={} port={} mac={}", - new Object[] { sw, sw_tup.getPort(), new Long(host_mac) }); + new Object[] { sw, sw_tup.getPort(), new Long(host_mac) }); // Create flow-mod based on packet-in and src-switch - OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD); + OFFlowMod fm = + (OFFlowMod) floodlightProvider.getOFMessageFactory() + .getMessage(OFType.FLOW_MOD); OFMatch match = new OFMatch(); - List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to drop + List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to + // drop match.setDataLayerSource(Ethernet.toByteArray(host_mac)) - .setInputPort(inputPort) - .setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_IN_PORT); + .setInputPort(inputPort) + .setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC + & ~OFMatch.OFPFW_IN_PORT); fm.setCookie(AppCookie.makeCookie(FORWARDING_APP_ID, 0)) - .setHardTimeout((short)hardTimeout) - .setIdleTimeout((short)5) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setMatch(match) - .setActions(actions) - .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH); + .setHardTimeout((short) hardTimeout) + .setIdleTimeout((short) 5) + .setBufferId(OFPacketOut.BUFFER_ID_NONE) + .setMatch(match) + .setActions(actions) + .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH); try { log.debug("write drop flow-mod sw={} match={} flow-mod={}", - new Object[] {sw, match, fm}); + new Object[] { sw, match, fm }); sw.write(fm, null); - } - catch (IOException e) { + } catch (IOException e) { log.error("Failure writing deny flow mod", e); return false; } @@ -376,38 +456,44 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag } /** - * @param floodlightProvider the floodlightProvider to set + * @param floodlightProvider + * the floodlightProvider to set */ - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { + public + void + setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } /** - * @param routingEngine the routingEngine to set + * @param routingEngine + * the routingEngine to set */ - public void setRoutingEngine(IRoutingEngine routingEngine) { + public void setRoutingEngine(IRoutingEngineService routingEngine) { this.routingEngine = routingEngine; } /** - * @param deviceManager the deviceManager to set + * @param deviceManager + * the deviceManager to set */ - public void setDeviceManager(IDeviceManager deviceManager) { + public void setDeviceManager(IDeviceManagerService deviceManager) { this.deviceManager = deviceManager; } /** - * @param topology the topology to set + * @param topology + * the topology to set */ - public void setTopology(ITopology topology) { + public void setTopology(ITopologyService topology) { this.topology = topology; } - public CounterStore getCounterStore() { + public ICounterStoreService getCounterStore() { return counterStore; } - public void setCounterStore(CounterStore counterStore) { + public void setCounterStore(ICounterStoreService counterStore) { this.counterStore = counterStore; } @@ -423,40 +509,41 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag @Override public void deviceMoved(Device device, IOFSwitch oldSw, Short oldPort, - IOFSwitch sw, Short port) { + IOFSwitch sw, Short port) { // Build flow mod to delete based on destination mac == device mac OFMatch match = new OFMatch(); match.setDataLayerDestination(Ethernet.toByteArray(device.getMACAddress())); match.setWildcards(OFMatch.OFPFW_ALL ^ OFMatch.OFPFW_DL_DST); - OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD)) - .setCommand(OFFlowMod.OFPFC_DELETE) - .setOutPort((short) OFPort.OFPP_NONE.getValue()) - .setMatch(match) - .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); + OFMessage fm = + ((OFFlowMod) floodlightProvider.getOFMessageFactory() + .getMessage(OFType.FLOW_MOD)).setCommand(OFFlowMod.OFPFC_DELETE) + .setOutPort((short) OFPort.OFPP_NONE.getValue()) + .setMatch(match) + .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); // Flush to all switches for (IOFSwitch outSw : floodlightProvider.getSwitches().values()) { try { outSw.write(fm, null); } catch (IOException e) { - log.error("Failure sending flow mod delete for moved device", e); + log.error("Failure sending flow mod delete for moved device", + e); } } } @Override public void deviceNetworkAddressAdded(Device device, - DeviceNetworkAddress address) { - + DeviceNetworkAddress address) { + } @Override public void deviceNetworkAddressRemoved(Device device, - DeviceNetworkAddress address) { - + DeviceNetworkAddress address) { + } - + @Override public void deviceVlanChanged(Device device) { @@ -464,8 +551,7 @@ public abstract class ForwardingBase implements IOFMessageListener, IDeviceManag @Override public boolean isCallbackOrderingPrereq(OFType type, String name) { - return (type.equals(OFType.PACKET_IN) && - (name.equals("topology") || name.equals("devicemanager"))); + return (type.equals(OFType.PACKET_IN) && (name.equals("topology") || name.equals("devicemanager"))); } @Override diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingEngine.java b/src/main/java/net/floodlightcontroller/routing/IRoutingEngineService.java similarity index 94% rename from src/main/java/net/floodlightcontroller/routing/IRoutingEngine.java rename to src/main/java/net/floodlightcontroller/routing/IRoutingEngineService.java index 1a04ebbab7a07af154087e65139b259c1aef388b..768d242646b8122a0cc2264d4a6723d18184722a 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingEngine.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingEngineService.java @@ -18,6 +18,7 @@ package net.floodlightcontroller.routing; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.routing.Route; /** @@ -25,7 +26,7 @@ import net.floodlightcontroller.routing.Route; * * @author David Erickson (daviderickson@cs.stanford.edu) */ -public interface IRoutingEngine { +public interface IRoutingEngineService extends IFloodlightService { public Route getRoute(IOFSwitch src, IOFSwitch dst); public Route getRoute(Long srcDpid, Long dstDpid); diff --git a/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java b/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java index 2f8553ef0f79fe0e81e2e157cabe24899dfb17ee..ff1cf1d16e551374f6adbdd6099bc19f538e80c7 100644 --- a/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java +++ b/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java @@ -20,8 +20,11 @@ */ package net.floodlightcontroller.routing.dijkstra; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; import java.util.PriorityQueue; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -31,19 +34,25 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.routing.BroadcastTree; -import net.floodlightcontroller.routing.IRoutingEngine; +import net.floodlightcontroller.routing.IRoutingEngineService; import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.routing.RouteId; -import net.floodlightcontroller.topology.ITopologyAware; +import net.floodlightcontroller.topology.ITopologyListener; +import net.floodlightcontroller.topology.ITopologyService; /** * Floodlight component to find shortest paths based on dijkstra's algorithm * * @author Mandeep Dhami (mandeep.dhami@bigswitch.com) */ -public class RoutingImpl implements IRoutingEngine, ITopologyAware { +public class RoutingImpl + implements IRoutingEngineService, ITopologyListener, IFloodlightModule { public static final int MAX_LINK_WEIGHT = 1000; public static final int MAX_PATH_WEIGHT = Integer.MAX_VALUE - MAX_LINK_WEIGHT - 1; @@ -55,17 +64,7 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { protected HashMap<Long, HashMap<Long, Link>> nexthoplinkmaps; protected HashMap<Long, HashMap<Long, Long>> nexthopnodemaps; protected LRUHashMap<RouteId, Route> pathcache; - - public RoutingImpl() { - lock = new ReentrantReadWriteLock(); - - network = new HashMap<Long, HashMap<Link, Link>>(); - nexthoplinkmaps = new HashMap<Long, HashMap<Long, Link>>(); - nexthopnodemaps = new HashMap<Long, HashMap<Long, Long>>(); - pathcache = new LRUHashMap<RouteId, Route>(PATH_CACHE_SIZE); - - log.info("Initialized Dijkstra RouterImpl"); - } + protected ITopologyService topology; @Override public boolean routeExists(Long srcId, Long dstId) { @@ -121,7 +120,9 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { } lock.readLock().unlock(); - log.debug("getRoute: {} -> {}", id, result); + if (log.isDebugEnabled()) { + log.debug("getRoute: {} -> {}", id, result); + } return result; } @@ -152,7 +153,9 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { Route result = null; if (path != null) result = new Route(id, path); - log.debug("buildroute: {}", result); + if (log.isDebugEnabled()) { + log.debug("buildroute: {}", result); + } return result; } @@ -321,10 +324,7 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { BroadcastTree ret = new BroadcastTree(nexthoplinks, nexthopnodes); return ret; } - - public void startUp() {} - public void shutDown() {} - + @Override public void clusterMerged() { // no-op @@ -335,4 +335,50 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { // Ignored by RoutingImpl } + // IFloodlightModule + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IRoutingEngineService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + // We are the class that implements the service + m.put(IRoutingEngineService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(ITopologyService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + topology = context.getServiceImpl(ITopologyService.class); + lock = new ReentrantReadWriteLock(); + network = new HashMap<Long, HashMap<Link, Link>>(); + nexthoplinkmaps = new HashMap<Long, HashMap<Long, Link>>(); + nexthopnodemaps = new HashMap<Long, HashMap<Long, Long>>(); + pathcache = new LRUHashMap<RouteId, Route>(PATH_CACHE_SIZE); + } + + @Override + public void startUp(FloodlightModuleContext context) { + // Register to get updates from topology + topology.addListener(this); + } } diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java similarity index 95% rename from src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusher.java rename to src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java index 9962b391bd2f1e627667435e5ef4c9ba6f210edf..4d3e572d802b4d19e1e1f3fce50275d9b64158d9 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusher.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java @@ -21,13 +21,15 @@ import java.util.HashMap; import java.util.List; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.IFloodlightService; + import org.openflow.protocol.OFFlowMod; /** * Represents the parts of the staticflowentry that are exposed as a service to other floodlight apps * */ -public interface IStaticFlowEntryPusher { +public interface IStaticFlowEntryPusherService extends IFloodlightService { /** * Pushes a flow-mod to this switch as a one-time push * diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java index b1ca17b463d393de02fb872cc04661842a982dea..15cb5309156a89a299868ffad9fc8481bcac18db 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java @@ -24,16 +24,22 @@ package net.floodlightcontroller.staticflowentry; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitchListener; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; @@ -51,7 +57,8 @@ import org.openflow.util.U16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class StaticFlowEntryPusher implements IStaticFlowEntryPusher, IOFSwitchListener { +public class StaticFlowEntryPusher + implements IStaticFlowEntryPusherService, IOFSwitchListener, IFloodlightModule { // Utility data structure private class FlowModFields { @@ -63,32 +70,18 @@ public class StaticFlowEntryPusher implements IStaticFlowEntryPusher, IOFSwitchL } protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusher.class); - protected IFloodlightProvider floodlightProvider; + protected IFloodlightProviderService floodlightProvider; protected ArrayList<String> flowmodList; protected ArrayList<IOFSwitch> activeSwitches; protected HashMap<Long, HashMap<String, OFFlowMod>> flowmods; protected int pushEntriesFrequency = 25000; // milliseconds protected Runnable pushEntriesTimer; - - public StaticFlowEntryPusher() { - flowmodList = new ArrayList<String>(); - flowmods = new HashMap<Long, HashMap<String, OFFlowMod>>(); - activeSwitches = new ArrayList<IOFSwitch>(); - } @Override public String getName() { return "staticflowentry"; } - - public IFloodlightProvider getFloodlightProvider() { - return floodlightProvider; - } - - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { - this.floodlightProvider = floodlightProvider; - } /** * Gets the static flow entry push interval @@ -604,7 +597,68 @@ public class StaticFlowEntryPusher implements IStaticFlowEntryPusher, IOFSwitchL return entryCookie; } - public void startUp() { + /** + * Pushes all entries associated with all switches (from the store) + */ + protected void pushAllEntries() { + for (IOFSwitch sw : activeSwitches) { + for (OFFlowMod fm : getEntries(sw).values()) { + pushEntry(sw, fm); + } + } + } + + public void shutDown() { + log.info("shutdown"); + pushEntriesTimer = null; + floodlightProvider.removeOFSwitchListener(this); + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IStaticFlowEntryPusherService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + // We are the class that implements the service + m.put(IStaticFlowEntryPusherService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IFloodlightProviderService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + // Wire up all our dependencies + floodlightProvider = + context.getServiceImpl(IFloodlightProviderService.class); + } + + @Override + public void startUp(FloodlightModuleContext context) { + // This is our 'constructor' + if (log.isDebugEnabled()) { + log.debug("Starting " + this.getClass().getCanonicalName()); + } + flowmodList = new ArrayList<String>(); + flowmods = new HashMap<Long, HashMap<String, OFFlowMod>>(); + activeSwitches = new ArrayList<IOFSwitch>(); floodlightProvider.addOFSwitchListener(this); pushEntriesTimer = new Runnable() { @Override @@ -624,21 +678,4 @@ public class StaticFlowEntryPusher implements IStaticFlowEntryPusher, IOFSwitchL pushEntriesFrequency, TimeUnit.MILLISECONDS); } - - /** - * Pushes all entries associated with all switches (from the store) - */ - protected void pushAllEntries() { - for (IOFSwitch sw : activeSwitches) { - for (OFFlowMod fm : getEntries(sw).values()) { - pushEntry(sw, fm); - } - } - } - - public void shutDown() { - log.info("shutdown"); - pushEntriesTimer = null; - floodlightProvider.removeOFSwitchListener(this); - } } diff --git a/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java b/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java index 2c5bd128e551b4300291e63c69edefeba265547d..e80c86bb0a7e1e19eb02791a0289c43a06548c80 100644 --- a/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java +++ b/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java @@ -18,6 +18,8 @@ package net.floodlightcontroller.storage; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -27,14 +29,23 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.counter.ICounter; import net.floodlightcontroller.counter.CounterStore; +import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.counter.CounterValue.CounterType; +import net.floodlightcontroller.restserver.IRestApiService; +import net.floodlightcontroller.storage.web.StorageWebRoutable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public abstract class AbstractStorageSource implements IStorageSource { +public abstract class AbstractStorageSource + implements IStorageSourceService, IFloodlightModule { protected static Logger logger = LoggerFactory.getLogger(AbstractStorageSource.class); // Shared instance of the executor to use to execute the storage tasks. @@ -52,13 +63,16 @@ public abstract class AbstractStorageSource implements IStorageSource { protected final static String STORAGE_DELETE_COUNTER_NAME = "StorageDelete"; protected Set<String> allTableNames = new CopyOnWriteArraySet<String>(); - protected CounterStore counterStore; + protected ICounterStoreService counterStore; protected ExecutorService executorService = defaultExecutorService; protected IStorageExceptionHandler exceptionHandler; private Map<String, Set<IStorageSourceListener>> listeners = new ConcurrentHashMap<String, Set<IStorageSourceListener>>(); + // Our dependencies + protected IRestApiService restApi = null; + abstract class StorageCallable<V> implements Callable<V> { public V call() { try { @@ -93,12 +107,6 @@ public abstract class AbstractStorageSource implements IStorageSource { this.executorService = defaultExecutorService; } - public AbstractStorageSource(ExecutorService executorService, - IStorageExceptionHandler exceptionHandler) { - setExecutorService(executorService); - this.exceptionHandler = exceptionHandler; - } - public void setExecutorService(ExecutorService executorService) { this.executorService = (executorService != null) ? executorService : defaultExecutorService; @@ -460,4 +468,47 @@ public abstract class AbstractStorageSource implements IStorageSource { notifyListeners(notification); } + // IFloodlightModule + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IStorageSourceService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, + IFloodlightService> getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + m.put(IStorageSourceService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IRestApiService.class); + l.add(ICounterStoreService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + restApi = + context.getServiceImpl(IRestApiService.class); + counterStore = + context.getServiceImpl(ICounterStoreService.class); + } + + @Override + public void startUp(FloodlightModuleContext context) { + restApi.addRestletRoutable(new StorageWebRoutable()); + } } diff --git a/src/main/java/net/floodlightcontroller/storage/IStorageSource.java b/src/main/java/net/floodlightcontroller/storage/IStorageSourceService.java similarity index 97% rename from src/main/java/net/floodlightcontroller/storage/IStorageSource.java rename to src/main/java/net/floodlightcontroller/storage/IStorageSourceService.java index d4d1195e1c7efb6c5f85665fd52e0c5055422690..de87476418d5f67ce801f66a4d150f60e8a1f980 100644 --- a/src/main/java/net/floodlightcontroller/storage/IStorageSource.java +++ b/src/main/java/net/floodlightcontroller/storage/IStorageSourceService.java @@ -22,9 +22,10 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Future; -import net.floodlightcontroller.perfmon.PktinProcessingTime; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; -public interface IStorageSource { +public interface IStorageSourceService extends IFloodlightService { /** Set the column to be used as the primary key for a table. This should * be guaranteed to be unique for all of the rows in the table, although the @@ -329,5 +330,5 @@ public interface IStorageSource { */ public void notifyListeners(List<StorageSourceNotification> notifications); - public void setPktinProcessingTime(PktinProcessingTime pktinProcessingTime); + public void setPktinProcessingTime(IPktInProcessingTimeService pktinProcessingTime); } diff --git a/src/main/java/net/floodlightcontroller/storage/memory/MemoryStorageSource.java b/src/main/java/net/floodlightcontroller/storage/memory/MemoryStorageSource.java index 181bd9fd12d6041b150f691bab6264fbb17b9609..a122a05d298ce0694f877e928e98ac160fecac17 100644 --- a/src/main/java/net/floodlightcontroller/storage/memory/MemoryStorageSource.java +++ b/src/main/java/net/floodlightcontroller/storage/memory/MemoryStorageSource.java @@ -17,7 +17,8 @@ package net.floodlightcontroller.storage.memory; -import net.floodlightcontroller.perfmon.PktinProcessingTime; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; import net.floodlightcontroller.storage.nosql.NoSqlStorageSource; import net.floodlightcontroller.storage.SynchronousExecutorService; @@ -33,18 +34,13 @@ import net.floodlightcontroller.storage.StorageException; public class MemoryStorageSource extends NoSqlStorageSource { private Map<String, MemoryTable> tableMap = new HashMap<String,MemoryTable>(); - - PktinProcessingTime pktinProcessingTime; - - public MemoryStorageSource() { - super(new SynchronousExecutorService(), null); - } + IPktInProcessingTimeService pktinProcessingTime; synchronized private MemoryTable getTable(String tableName, boolean create) { MemoryTable table = tableMap.get(tableName); if (table == null) { if (!create) - throw new StorageException("Table does not exist"); + throw new StorageException("Table " + tableName + " does not exist"); table = new MemoryTable(tableName); tableMap.put(tableName, table); } @@ -175,7 +171,15 @@ public class MemoryStorageSource extends NoSqlStorageSource { } public void setPktinProcessingTime( - PktinProcessingTime pktinProcessingTime) { + IPktInProcessingTimeService pktinProcessingTime) { this.pktinProcessingTime = pktinProcessingTime; } + + // IFloodlightModule methods + + @Override + public void startUp(FloodlightModuleContext context) { + super.startUp(context); + executorService = new SynchronousExecutorService(); + } } diff --git a/src/main/java/net/floodlightcontroller/storage/nosql/NoSqlStorageSource.java b/src/main/java/net/floodlightcontroller/storage/nosql/NoSqlStorageSource.java index 37e02f71d1ecc18dbdaa974f7b14e863dac5510f..d7e5f956b4ddee76c68c99cc802a2fa447b19a00 100644 --- a/src/main/java/net/floodlightcontroller/storage/nosql/NoSqlStorageSource.java +++ b/src/main/java/net/floodlightcontroller/storage/nosql/NoSqlStorageSource.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TimeZone; -import java.util.concurrent.ExecutorService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +42,6 @@ import net.floodlightcontroller.storage.CompoundPredicate; import net.floodlightcontroller.storage.IPredicate; import net.floodlightcontroller.storage.IQuery; import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.IStorageExceptionHandler; import net.floodlightcontroller.storage.OperatorPredicate; import net.floodlightcontroller.storage.RowOrdering; import net.floodlightcontroller.storage.StorageException; @@ -525,11 +523,6 @@ public abstract class NoSqlStorageSource extends AbstractStorageSource { super(); } - public NoSqlStorageSource(ExecutorService executorService, - IStorageExceptionHandler exceptionHandler) { - super(executorService, exceptionHandler); - } - @Override public void createTable(String tableName, Set<String> indexedColumns) { super.createTable(tableName, indexedColumns); diff --git a/src/main/java/net/floodlightcontroller/storage/web/StorageNotifyResource.java b/src/main/java/net/floodlightcontroller/storage/web/StorageNotifyResource.java index 17d129444d95ca9890688679fe83721ab34954f4..fcfa96f40d6b0e27271f48b9a91524d5b6a52a0e 100644 --- a/src/main/java/net/floodlightcontroller/storage/web/StorageNotifyResource.java +++ b/src/main/java/net/floodlightcontroller/storage/web/StorageNotifyResource.java @@ -21,7 +21,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.floodlightcontroller.storage.IStorageSource; +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.StorageSourceNotification; import org.codehaus.jackson.map.ObjectMapper; @@ -42,8 +42,9 @@ public class StorageNotifyResource extends ServerResource { mapper.readValue(entity, new TypeReference<List<StorageSourceNotification>>(){}); - IStorageSource storageSource = - (IStorageSource)getContext().getAttributes().get("storageSource"); + IStorageSourceService storageSource = + (IStorageSourceService)getContext().getAttributes(). + get(IStorageSourceService.class.getCanonicalName()); storageSource.notifyListeners(notifications); HashMap<String, Object> model = new HashMap<String,Object>(); diff --git a/src/main/java/net/floodlightcontroller/storage/web/StorageWebRoutable.java b/src/main/java/net/floodlightcontroller/storage/web/StorageWebRoutable.java index 8f25d914b10f303f543bac5c83301d1579291e58..681847d8fa1013ef1a39c299ba2a03f8e710d6b1 100644 --- a/src/main/java/net/floodlightcontroller/storage/web/StorageWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/storage/web/StorageWebRoutable.java @@ -21,7 +21,7 @@ import org.restlet.Context; import org.restlet.Restlet; import org.restlet.routing.Router; -import net.floodlightcontroller.core.web.RestletRoutable; +import net.floodlightcontroller.restserver.RestletRoutable; /** * Creates a router to handle the storage web URIs diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyAware.java b/src/main/java/net/floodlightcontroller/topology/ITopologyListener.java similarity index 92% rename from src/main/java/net/floodlightcontroller/topology/ITopologyAware.java rename to src/main/java/net/floodlightcontroller/topology/ITopologyListener.java index 464996f167e4f1ff13c377120bab6369f7e13429..d27a1aa5fdade6b419e9eff7283f9af2e7584470 100644 --- a/src/main/java/net/floodlightcontroller/topology/ITopologyAware.java +++ b/src/main/java/net/floodlightcontroller/topology/ITopologyListener.java @@ -24,7 +24,7 @@ import net.floodlightcontroller.core.IOFSwitch; * * @author David Erickson (daviderickson@cs.stanford.edu) */ -public interface ITopologyAware { +public interface ITopologyListener { /** * @param srcSw the source switch * @param srcPort the source port from the source switch @@ -56,9 +56,12 @@ public interface ITopologyAware { IOFSwitch dstSw, short dstPort); /** - * @param sw + * @param sw The IOFSwitch that has been updated */ public void updatedSwitch(IOFSwitch sw); + /** + * Happens when the switch clusters are recomputed + */ void clusterMerged(); } diff --git a/src/main/java/net/floodlightcontroller/topology/ITopology.java b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java similarity index 90% rename from src/main/java/net/floodlightcontroller/topology/ITopology.java rename to src/main/java/net/floodlightcontroller/topology/ITopologyService.java index 0816124a0b979258fc2420ce07db0bdd09ebcc0f..36fa63711e38fdf931c9e4c95616355180ae48f5 100644 --- a/src/main/java/net/floodlightcontroller/topology/ITopology.java +++ b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java @@ -25,14 +25,16 @@ package net.floodlightcontroller.topology; import java.util.Map; import java.util.Set; + import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.IFloodlightService; /** * * * @author David Erickson (daviderickson@cs.stanford.edu) */ -public interface ITopology { +public interface ITopologyService extends IFloodlightService { /** * Query to determine if the specified switch id and port are * connected to another switch or not. If so, this means the link @@ -93,4 +95,10 @@ public interface ITopology { * as an endpoint. */ public Map<IOFSwitch, Set<LinkTuple>> getSwitchLinks(); + + /** + * Adds a listener to listen for ITopologyService messages + * @param listener The listener that wants the notifications + */ + public void addListener(ITopologyListener listener); } diff --git a/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java b/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java index 8ca453c3935a4a7cc3c125419bc9736e056288e0..7bc8580d37fbdd885fe296b9065d5e338f50287e 100644 --- a/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java +++ b/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java @@ -24,6 +24,7 @@ import java.net.NetworkInterface; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -39,30 +40,36 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitchListener; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.util.SingletonTask; import net.floodlightcontroller.packet.BPDU; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.packet.LLDP; import net.floodlightcontroller.packet.LLDPTLV; +import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.routing.BroadcastTree; -import net.floodlightcontroller.routing.IRoutingEngine; +import net.floodlightcontroller.routing.IRoutingEngineService; import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.IStorageSource; +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.IStorageSourceListener; import net.floodlightcontroller.storage.OperatorPredicate; import net.floodlightcontroller.storage.StorageException; +import net.floodlightcontroller.topology.ITopologyService; +import net.floodlightcontroller.topology.ITopologyListener; import net.floodlightcontroller.topology.BroadcastDomain; -import net.floodlightcontroller.topology.ITopology; -import net.floodlightcontroller.topology.ITopologyAware; import net.floodlightcontroller.topology.LinkInfo; import net.floodlightcontroller.topology.LinkTuple; import net.floodlightcontroller.topology.SwitchCluster; import net.floodlightcontroller.topology.SwitchPortTuple; +import net.floodlightcontroller.topology.web.TopologyWebRoutable; import net.floodlightcontroller.util.ClusterDFS; import net.floodlightcontroller.util.EventHistory; import net.floodlightcontroller.util.EventHistory.EvAction; @@ -106,8 +113,10 @@ import org.slf4j.LoggerFactory; * * @author David Erickson (daviderickson@cs.stanford.edu) */ -public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, - IStorageSourceListener, ITopology { +public class TopologyImpl + implements IOFMessageListener, IOFSwitchListener, + IStorageSourceListener, ITopologyService, + IFloodlightModule { protected static Logger log = LoggerFactory.getLogger(TopologyImpl.class); // Names of table/fields for links in the storage API @@ -124,16 +133,15 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, private static final String SWITCH_TABLE_NAME = "controller_switch"; private static final String SWITCH_CORE_SWITCH = "core_switch"; - // + protected IFloodlightProviderService floodlightProvider; + protected IStorageSourceService storageSource; + protected IRoutingEngineService routingEngine; + protected IRestApiService restApi; + private static final String LLDP_STANDARD_DST_MAC_STRING = "01:80:c2:00:00:00"; // BigSwitch OUI is 5C:16:C7, so 5D:16:C7 is the multicast version private static final String LLDP_BSN_DST_MAC_STRING = "5d:16:c7:00:00:01"; - - protected IFloodlightProvider floodlightProvider; - protected IStorageSource storageSource; - protected IRoutingEngine routingEngine; - /** * Map from link to the most recent time it was verified functioning */ @@ -164,7 +172,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, protected Map<IOFSwitch, Set<LinkTuple>> switchLinks; /* topology aware components are called in the order they were added to the * the array */ - protected ArrayList<ITopologyAware> topologyAware; + protected ArrayList<ITopologyListener> topologyAware; protected BlockingQueue<Update> updates; protected Thread updatesThread; @@ -245,29 +253,12 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, this.operation = operation; } } - - public TopologyImpl() { - this.lock = new ReentrantReadWriteLock(); - this.updates = new LinkedBlockingQueue<Update>(); - this.links = new HashMap<LinkTuple, LinkInfo>(); - this.portLinks = new HashMap<SwitchPortTuple, Set<LinkTuple>>(); - this.portBroadcastDomainLinks = new HashMap<SwitchPortTuple, Set<LinkTuple>>(); - this.switchLinks = new HashMap<IOFSwitch, Set<LinkTuple>>(); - this.evHistTopologySwitch = - new EventHistory<EventHistoryTopologySwitch>("Topology: Switch"); - this.evHistTopologyLink = - new EventHistory<EventHistoryTopologyLink>("Topology: Link"); - this.evHistTopologyCluster = - new EventHistory<EventHistoryTopologyCluster>("Topology: Cluster"); - - setControllerTLV(); - } - + private void doUpdatesThread() throws InterruptedException { do { Update update = updates.take(); if (topologyAware != null) { - for (ITopologyAware ta : topologyAware) { // order maintained + for (ITopologyListener ta : topologyAware) { // order maintained if (log.isDebugEnabled()) { log.debug("Dispatching topology update {} {} {} {} {}", new Object[]{update.operation, @@ -304,88 +295,6 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, detectLoop(); } - public void startUp() { - floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); - floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this); - floodlightProvider.addOFSwitchListener(this); - - ScheduledExecutorService ses = floodlightProvider.getScheduledExecutor(); - - Runnable lldpSendTimer = new Runnable() { - @Override - public void run() { - try { - sendLLDPs(); - - if (!shuttingDown) { - ScheduledExecutorService ses = - floodlightProvider.getScheduledExecutor(); - ses.schedule(this, lldpFrequency, - TimeUnit.MILLISECONDS); - } - } catch (StorageException e) { - log.error("Storage exception in LLDP send timer; " + - "terminating process", e); - floodlightProvider.terminate(); - } catch (Exception e) { - log.error("Exception in LLDP send timer", e); - } - } - }; - ses.schedule(lldpSendTimer, 1000, TimeUnit.MILLISECONDS); - - Runnable timeoutLinksTimer = new Runnable() { - @Override - public void run() { - log.trace("Running timeoutLinksTimer"); - try { - timeoutLinks(); - if (!shuttingDown) { - ScheduledExecutorService ses = - floodlightProvider.getScheduledExecutor(); - ses.schedule(this, lldpTimeout, TimeUnit.MILLISECONDS); - } - } catch (StorageException e) { - log.error("Storage exception in link timer; " + - "terminating process", e); - floodlightProvider.terminate(); - } catch (Exception e) { - log.error("Exception in timeoutLinksTimer", e); - } - } - }; - ses.schedule(timeoutLinksTimer, 1000, TimeUnit.MILLISECONDS); - - updatesThread = new Thread(new Runnable () { - @Override - public void run() { - while (true) { - try { - doUpdatesThread(); - } catch (InterruptedException e) { - return; - } - } - }}, "Topology Updates"); - updatesThread.start(); - - try { - storageSource.addListener(SWITCH_TABLE_NAME, this); - } - catch (StorageException ex) { - log.error("Error in installing listener for switch table - {}", SWITCH_TABLE_NAME); - // floodlightProvider.terminate(); // For now, log this error and continue - } - } - - protected void shutDown() { - shuttingDown = true; - floodlightProvider.removeOFSwitchListener(this); - floodlightProvider.removeOFMessageListener(OFType.PACKET_IN, this); - floodlightProvider.removeOFMessageListener(OFType.PORT_STATUS, this); - updatesThread.interrupt(); - } - /** * Detect loops in the openflow clusters and construct spanning trees * for broadcast @@ -611,7 +520,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, public String getName() { return "topology"; } - + @Override public int getId() { return FlListenerID.TOPOLOGYIMPL; @@ -667,7 +576,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, // This is not the LLDP sent by this controller. // If the LLDP message has multicast bit set, then we need to broadcast // the packet as a regular packet. - Ethernet eth = IFloodlightProvider.bcStore.get(cntx, IFloodlightProvider.CONTEXT_PI_PAYLOAD); + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); if (eth.isMulticast()) { if (log.isTraceEnabled()) log.trace("Received a multicast LLDP packet from a different controller, allowing the packet to follow normal processing chain."); @@ -733,9 +642,9 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, protected Command handlePacketIn(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { - Ethernet eth = - IFloodlightProvider.bcStore.get(cntx, - IFloodlightProvider.CONTEXT_PI_PAYLOAD); + Ethernet eth = + IFloodlightProviderService.bcStore.get(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD); if (eth.getPayload() instanceof LLDP) { String dstMacString = HexString.toHexString(eth.getDestinationMACAddress()); @@ -1138,7 +1047,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * Sets the IFloodlightProvider for this TopologyImpl. * @param floodlightProvider the floodlightProvider to set */ - public void setFloodlightProvider(IFloodlightProvider floodlightProvider) { + public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } @@ -1300,7 +1209,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * compute connected components. */ protected void updateBroadcastDomains() { - Map<SwitchPortTuple, Set<LinkTuple>> pbdLinks = getPortBroadcastDomainLinks(); + Map<SwitchPortTuple, Set<LinkTuple>> pbdLinks = getPortBroadcastDomainLinks(); Set<SwitchPortTuple> visitedSwt = new HashSet<SwitchPortTuple>(); Map<Long, BroadcastDomain> bdMap = new HashMap<Long, BroadcastDomain>(); Map<SwitchPortTuple, BroadcastDomain> spbdMap = new HashMap<SwitchPortTuple, BroadcastDomain>(); @@ -1712,20 +1621,17 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, String id = getLinkId(lt); storageSource.deleteRowAsync(LINK_TABLE_NAME, id); } - - /** - * @param topologyAware the topologyAware to set - */ - public void setTopologyAware(ArrayList<ITopologyAware> topologyAware) { - // TODO make this a copy on write set or lock it somehow - this.topologyAware = topologyAware; + + @Override + public void addListener(ITopologyListener listener) { + topologyAware.add(listener); } - + /** * Register a topology aware component * @param topoAwareComponent */ - public void addTopologyAware(ITopologyAware topoAwareComponent) { + public void addTopologyAware(ITopologyListener topoAwareComponent) { // TODO make this a copy on write set or lock it somehow this.topologyAware.add(topoAwareComponent); } @@ -1734,7 +1640,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * Deregister a topology aware component * @param topoAwareComponent */ - public void removeTopologyAware(ITopologyAware topoAwareComponent) { + public void removeTopologyAware(ITopologyListener topoAwareComponent) { // TODO make this a copy on write set or lock it somehow this.topologyAware.remove(topoAwareComponent); } @@ -1743,27 +1649,23 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * Sets the IStorageSource to use for ITology * @param storageSource the storage source to use */ - public void setStorageSource(IStorageSource storageSource) { + public void setStorageSource(IStorageSourceService storageSource) { this.storageSource = storageSource; - storageSource.createTable(LINK_TABLE_NAME, null); - storageSource.setTablePrimaryKeyName(LINK_TABLE_NAME, LINK_ID); } /** * Gets the storage source for this ITopology * @return The IStorageSource ITopology is writing to */ - public IStorageSource getStorageSource() { + public IStorageSourceService getStorageSource() { return storageSource; } /** * @param routingEngine the storage source to use for persisting link info */ - public void setRoutingEngine(IRoutingEngine routingEngine) { + public void setRoutingEngine(IRoutingEngineService routingEngine) { this.routingEngine = routingEngine; - storageSource.createTable(LINK_TABLE_NAME, null); - storageSource.setTablePrimaryKeyName(LINK_TABLE_NAME, LINK_ID); } @Override @@ -1832,6 +1734,154 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, // Ignore delete events, the switch delete will do the right thing on it's own } + // IFloodlightModule classes + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(ITopologyService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + // We are the class that implements the service + m.put(ITopologyService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IFloodlightProviderService.class); + l.add(IStorageSourceService.class); + l.add(IRoutingEngineService.class); + l.add(IRestApiService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); + storageSource = context.getServiceImpl(IStorageSourceService.class); + routingEngine = context.getServiceImpl(IRoutingEngineService.class); + restApi = context.getServiceImpl(IRestApiService.class); + + // We create this here because there is no ordering guarantee + this.topologyAware = new ArrayList<ITopologyListener>(); + this.lock = new ReentrantReadWriteLock(); + this.updates = new LinkedBlockingQueue<Update>(); + this.links = new HashMap<LinkTuple, LinkInfo>(); + this.portLinks = new HashMap<SwitchPortTuple, Set<LinkTuple>>(); + this.portBroadcastDomainLinks = new HashMap<SwitchPortTuple, Set<LinkTuple>>(); + this.switchLinks = new HashMap<IOFSwitch, Set<LinkTuple>>(); + this.evHistTopologySwitch = + new EventHistory<EventHistoryTopologySwitch>("Topology: Switch"); + this.evHistTopologyLink = + new EventHistory<EventHistoryTopologyLink>("Topology: Link"); + this.evHistTopologyCluster = + new EventHistory<EventHistoryTopologyCluster>("Topology: Cluster"); + } + + @Override + public void startUp(FloodlightModuleContext context) { + // Create our storage tables + storageSource.createTable(LINK_TABLE_NAME, null); + storageSource.setTablePrimaryKeyName(LINK_TABLE_NAME, LINK_ID); + storageSource.createTable(LINK_TABLE_NAME, null); + storageSource.setTablePrimaryKeyName(LINK_TABLE_NAME, LINK_ID); + // Register for storage updates for the switch table + try { + storageSource.addListener(SWITCH_TABLE_NAME, this); + } catch (StorageException ex) { + log.error("Error in installing listener for switch table - {}", SWITCH_TABLE_NAME); + } + + ScheduledExecutorService ses = floodlightProvider.getScheduledExecutor(); + + // Setup sending out LLDPs + Runnable lldpSendTimer = new Runnable() { + @Override + public void run() { + try { + sendLLDPs(); + + if (!shuttingDown) { + ScheduledExecutorService ses = + floodlightProvider.getScheduledExecutor(); + ses.schedule(this, lldpFrequency, + TimeUnit.MILLISECONDS); + } + } catch (StorageException e) { + log.error("Storage exception in LLDP send timer; " + + "terminating process", e); + floodlightProvider.terminate(); + } catch (Exception e) { + log.error("Exception in LLDP send timer", e); + } + } + }; + ses.schedule(lldpSendTimer, 1000, TimeUnit.MILLISECONDS); + + Runnable timeoutLinksTimer = new Runnable() { + @Override + public void run() { + log.trace("Running timeoutLinksTimer"); + try { + timeoutLinks(); + if (!shuttingDown) { + ScheduledExecutorService ses = + floodlightProvider.getScheduledExecutor(); + ses.schedule(this, lldpTimeout, TimeUnit.MILLISECONDS); + } + } catch (StorageException e) { + log.error("Storage exception in link timer; " + + "terminating process", e); + floodlightProvider.terminate(); + } catch (Exception e) { + log.error("Exception in timeoutLinksTimer", e); + } + } + }; + ses.schedule(timeoutLinksTimer, 1000, TimeUnit.MILLISECONDS); + + updatesThread = new Thread(new Runnable () { + @Override + public void run() { + while (true) { + try { + doUpdatesThread(); + } catch (InterruptedException e) { + return; + } + } + }}, "Topology Updates"); + updatesThread.start(); + + // Register for the OpenFlow messages we want to receive + floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); + floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this); + // Register for switch updates + floodlightProvider.addOFSwitchListener(this); + + // init our rest api + if (restApi != null) { + restApi.addRestletRoutable(new TopologyWebRoutable()); + } else { + log.error("Could not instantiate REST API"); + } + + setControllerTLV(); + } + // **************************************************** // Topology Manager's Event History members and methods // **************************************************** diff --git a/src/main/java/net/floodlightcontroller/topology/web/LinksResource.java b/src/main/java/net/floodlightcontroller/topology/web/LinksResource.java index 48b2f664870de232a968e2fd8cf7065bdb4a92c3..9c4f57d5d9ad6ee6ae55f9f6cd698629d447d710 100644 --- a/src/main/java/net/floodlightcontroller/topology/web/LinksResource.java +++ b/src/main/java/net/floodlightcontroller/topology/web/LinksResource.java @@ -3,7 +3,7 @@ package net.floodlightcontroller.topology.web; import java.util.HashSet; import java.util.Set; -import net.floodlightcontroller.topology.ITopology; +import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.LinkTuple; import org.restlet.resource.Get; @@ -12,7 +12,8 @@ import org.restlet.resource.ServerResource; public class LinksResource extends ServerResource { @Get("json") public Set<LinkTuple> retrieve() { - ITopology topo = (ITopology)getContext().getAttributes().get("topology"); + ITopologyService topo = (ITopologyService)getContext().getAttributes(). + get(ITopologyService.class.getCanonicalName()); Set <LinkTuple> links = new HashSet<LinkTuple>(); if (topo != null) { for (Set<LinkTuple> linkSet : topo.getSwitchLinks().values()) { diff --git a/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRouteable.java b/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java similarity index 85% rename from src/main/java/net/floodlightcontroller/topology/web/TopologyWebRouteable.java rename to src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java index 096b4601c56a3588f6f2d48c9bffeec8bc9e5d5e..fa918c450dbe250d973861db226afa8f26f5ac06 100644 --- a/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRouteable.java +++ b/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java @@ -4,10 +4,10 @@ import org.restlet.Context; import org.restlet.Restlet; import org.restlet.routing.Router; -import net.floodlightcontroller.core.web.RestletRoutable; import net.floodlightcontroller.core.web.SwitchClustersResource; +import net.floodlightcontroller.restserver.RestletRoutable; -public class TopologyWebRouteable implements RestletRoutable { +public class TopologyWebRoutable implements RestletRoutable { /** * Create the Restlet router and bind to the proper resources. */ diff --git a/src/main/java/net/floodlightcontroller/util/TimedCache.java b/src/main/java/net/floodlightcontroller/util/TimedCache.java index 107da08217c46962b7d70b0f8b3fcfb3628ef658..857d57de9046fb02abb5778f63b2666dcd15d446 100644 --- a/src/main/java/net/floodlightcontroller/util/TimedCache.java +++ b/src/main/java/net/floodlightcontroller/util/TimedCache.java @@ -20,7 +20,6 @@ package net.floodlightcontroller.util; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import java.util.concurrent.ConcurrentMap; - /** * The key is any object/hash-code * The value is time-stamp in milliseconds @@ -29,7 +28,7 @@ import java.util.concurrent.ConcurrentMap; * * @param <K> Type of the values in this cache */ -public class TimedCache<K> { +public class TimedCache<K> { private final long timeoutInterval; //specified in milliseconds. private ConcurrentMap<K, Long> cache; private long cacheHits; @@ -85,4 +84,4 @@ public class TimedCache<K> { this.cacheHits++; return true; } -} \ No newline at end of file +} diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule new file mode 100644 index 0000000000000000000000000000000000000000..1207638607366e0818a2c375d8b16f68a2ee760e --- /dev/null +++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule @@ -0,0 +1,10 @@ +net.floodlightcontroller.core.CoreModule +net.floodlightcontroller.storage.memory.MemoryStorageSource +net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl +net.floodlightcontroller.topology.internal.TopologyImpl +net.floodlightcontroller.routing.dijkstra.RoutingImpl +net.floodlightcontroller.forwarding.Forwarding +net.floodlightcontroller.core.OFMessageFilterManager +net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher +net.floodlightcontroller.perfmon.PktInProcessingTime +net.floodlightcontroller.restserver.RestApiServer \ No newline at end of file diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties new file mode 100644 index 0000000000000000000000000000000000000000..6d2dbca087f960ab50baae674e40c72fce4c1ef5 --- /dev/null +++ b/src/main/resources/floodlightdefault.properties @@ -0,0 +1 @@ +floodlight.modules = net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher,net.floodlightcontroller.forwarding.Forwarding diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java index ae443bb462f3d623529e71c73d6d49d637b7aee4..2ba77e55e207a5e63670a74d5d0bd2d57ab41a70 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java @@ -29,11 +29,15 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; +import net.floodlightcontroller.core.IOFMessageFilterManagerService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFMessageListener.Command; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.OFMessageFilterManager; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleLoader; +import net.floodlightcontroller.core.module.IFloodlightModuleContext; import net.floodlightcontroller.core.test.MockFloodlightProvider; import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.Ethernet; @@ -66,11 +70,14 @@ public class ControllerTest extends FloodlightTestCase { private Controller controller; @Override - public void setUp() { + public void setUp() throws Exception { super.setUp(); - - controller = new Controller(); - controller.init(); + FloodlightModuleLoader fml = new FloodlightModuleLoader(); + IFloodlightModuleContext moduleContext = fml.loadModulesFromList( + new String[] {"net.floodlightcontroller.core.CoreModule"}); + controller = + (Controller) moduleContext. + getServiceImpl(IFloodlightProviderService.class); } public Controller getController() { @@ -280,13 +287,16 @@ public class ControllerTest extends FloodlightTestCase { @Test public void testMessageFilterManager() throws Exception { - - MockFloodlightProvider mbp = new MockFloodlightProvider(); + FloodlightModuleContext fmCntx = new FloodlightModuleContext(); + MockFloodlightProvider mfp = new MockFloodlightProvider(); + OFMessageFilterManager mfm = new OFMessageFilterManager(); + fmCntx.addService(IOFMessageFilterManagerService.class, mfm); + fmCntx.addService(IFloodlightProviderService.class, mfp); String sid = null; - OFMessageFilterManager mfm = new OFMessageFilterManager(); - mfm.init(mbp); - mfm.startUp(); + + mfm.init(fmCntx); + mfm.startUp(fmCntx); ConcurrentHashMap <String, String> filter; int i; @@ -353,22 +363,22 @@ public class ControllerTest extends FloodlightTestCase { .setLengthU(OFPacketOut.MINIMUM_LENGTH+packetOut.getActionsLength()+testPacketSerialized.length); FloodlightContext cntx = new FloodlightContext(); - IFloodlightProvider.bcStore.put(cntx, IFloodlightProvider.CONTEXT_PI_PAYLOAD, (Ethernet) testPacket); + IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, (Ethernet) testPacket); // Let's check the listeners. List <IOFMessageListener> lm; // Check to see if all the listeners are active. - lm = mbp.getListeners().get(OFType.PACKET_OUT); + lm = mfp.getListeners().get(OFType.PACKET_OUT); assertTrue(lm.size() == 1); assertTrue(lm.get(0).equals(mfm)); - lm = mbp.getListeners().get(OFType.FLOW_MOD); + lm = mfp.getListeners().get(OFType.FLOW_MOD); assertTrue(lm.size() == 1); assertTrue(lm.get(0).equals(mfm)); - lm = mbp.getListeners().get(OFType.PACKET_IN); + lm = mfp.getListeners().get(OFType.PACKET_IN); assertTrue(lm.size() == 1); assertTrue(lm.get(0).equals(mfm)); diff --git a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java index 9758c6a08abf8a21a4f2e09897b0a8d9d75b9d6d..86d3427d61712901cb2a4bf0509fc90ea367703e 100644 --- a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java +++ b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java @@ -18,6 +18,7 @@ package net.floodlightcontroller.core.test; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -26,12 +27,17 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledExecutorService; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IOFSwitchFilter; import net.floodlightcontroller.core.IOFSwitchListener; import net.floodlightcontroller.core.IOFMessageListener.Command; +import net.floodlightcontroller.core.internal.CmdLineSettings; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.packet.Ethernet; import org.openflow.protocol.OFMessage; @@ -43,7 +49,7 @@ import org.openflow.protocol.factory.BasicFactory; * * @author David Erickson (daviderickson@cs.stanford.edu) */ -public class MockFloodlightProvider implements IFloodlightProvider { +public class MockFloodlightProvider implements IFloodlightModule, IFloodlightProviderService { protected Map<OFType, List<IOFMessageListener>> listeners; protected List<IOFSwitchListener> switchListeners; protected Map<Long, IOFSwitch> switches; @@ -123,8 +129,8 @@ public class MockFloodlightProvider implements IFloodlightProvider { OFPacketIn pi = (OFPacketIn)msg; Ethernet eth = new Ethernet(); eth.deserialize(pi.getPacketData(), 0, pi.getPacketData().length); - IFloodlightProvider.bcStore.put(bc, - IFloodlightProvider.CONTEXT_PI_PAYLOAD, + IFloodlightProviderService.bcStore.put(bc, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); } while (it.hasNext() && !Command.STOP.equals(result)) { @@ -194,4 +200,49 @@ public class MockFloodlightProvider implements IFloodlightProvider { public BasicFactory getOFMessageFactory() { return factory; } + + @Override + public void run() { + // no-op + } + + @Override + public void setCmdLineOptions(CmdLineSettings settings) { + // no-op + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + // TODO Auto-generated method stub + return null; + } + + @Override + public + void + init(FloodlightModuleContext context) + throws FloodlightModuleException { + // TODO Auto-generated method stub + + } + + @Override + public void startUp(FloodlightModuleContext context) { + // TODO Auto-generated method stub + + } } diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java index 4e559b775845a226b78f09d18ec6f3eda19aa2fa..227c7937b6f239ee0b73e8b7a5e91d589db71b4f 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java @@ -32,21 +32,26 @@ import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.reset; import static org.easymock.EasyMock.verify; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockFloodlightProvider; import net.floodlightcontroller.devicemanager.DeviceAttachmentPoint; import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.devicemanager.IEntityClassifier; import net.floodlightcontroller.devicemanager.IEntityClassifier.EntityField; import net.floodlightcontroller.devicemanager.SwitchPort; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPacket; import net.floodlightcontroller.packet.IPv4; -import net.floodlightcontroller.storage.IStorageSource; +import net.floodlightcontroller.restserver.IRestApiService; +import net.floodlightcontroller.restserver.RestApiServer; +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.memory.MemoryStorageSource; import net.floodlightcontroller.test.FloodlightTestCase; -import net.floodlightcontroller.topology.ITopology; +import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.SwitchPortTuple; import static org.junit.Assert.*; @@ -67,18 +72,26 @@ public class DeviceManagerImplTest extends FloodlightTestCase { private byte[] testPacketSerialized; MockFloodlightProvider mockFloodlightProvider; DeviceManagerImpl deviceManager; - IStorageSource storageSource; + MemoryStorageSource storageSource; @Before - public void setUp() { + public void setUp() throws Exception { super.setUp(); + FloodlightModuleContext fmc = new FloodlightModuleContext(); + RestApiServer restApi = new RestApiServer(); mockFloodlightProvider = getMockFloodlightProvider(); deviceManager = new DeviceManagerImpl(); + fmc.addService(IDeviceManagerService.class, deviceManager); storageSource = new MemoryStorageSource(); - deviceManager.setFloodlightProvider(mockFloodlightProvider); - deviceManager.setStorageSource(storageSource); - deviceManager.startUp(); + fmc.addService(IStorageSourceService.class, storageSource); + fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); + fmc.addService(IRestApiService.class, restApi); + restApi.init(fmc); + storageSource.init(fmc); + deviceManager.init(fmc); + storageSource.startUp(fmc); + deviceManager.startUp(fmc); // Build our test packet this.testPacket = new Ethernet() @@ -241,9 +254,9 @@ public class DeviceManagerImplTest extends FloodlightTestCase { IOFSwitch mockSwitch = createMock(IOFSwitch.class); expect(mockSwitch.getId()).andReturn(1L).anyTimes(); expect(mockSwitch.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes(); - ITopology mockTopology = createMock(ITopology.class); + ITopologyService mockTopology = createMock(ITopologyService.class); expect(mockTopology.isInternal(mockSwitch, (short)1)).andReturn(false).anyTimes(); - deviceManager.setTopology(mockTopology); + deviceManager.topology = mockTopology; Date currentDate = new Date(); @@ -304,7 +317,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase { fail(); } - @Test public void testDeviceUpdateLastSeenToStorage() throws Exception { fail(); @@ -317,7 +329,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase { // Mock up our expected behavior IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class); expect(mockSwitch.getId()).andReturn(1L).atLeastOnce(); - ITopology mockTopology = createNiceMock(ITopology.class); + ITopologyService mockTopology = createNiceMock(ITopologyService.class); //expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 1))).andReturn(false); deviceManager.setTopology(mockTopology); @@ -367,7 +379,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase { IOFSwitch mockSwitch = createMock(IOFSwitch.class); expect(mockSwitch.getId()).andReturn(1L).anyTimes(); expect(mockSwitch.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes(); - ITopology mockTopology = createMock(ITopology.class); + ITopologyService mockTopology = createMock(ITopologyService.class); expect(mockSwitch.getPort((short)1)).andReturn(port1).anyTimes(); expect(mockSwitch.getPort((short)2)).andReturn(port2).anyTimes(); expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 1))) @@ -423,7 +435,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase { } private void setupPortChannel() { - storageSource.insertRow(DeviceManagerImpl.PORT_CHANNEL_TABLE_NAME, pcPort1); storageSource.insertRow(DeviceManagerImpl.PORT_CHANNEL_TABLE_NAME, pcPort2); deviceManager.readPortChannelConfigFromStorage(); @@ -459,7 +470,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase { expect(mockSwitch.getPort((short)2)).andReturn(port2).anyTimes(); expect(mockSwitch.getId()).andReturn(1L).anyTimes(); expect(mockSwitch.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes(); - ITopology mockTopology = createMock(ITopology.class); + ITopologyService mockTopology = createMock(ITopologyService.class); expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 1))) .andReturn(false).atLeastOnce(); expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 2))) diff --git a/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java b/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java index 4a3d3c450fa1c82da11e882cc8a1c4bc2a81a4a7..4e2fb6cddd9baebbaa55dc8bc47b4a0a30b35cce 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java @@ -23,12 +23,17 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import net.floodlightcontroller.devicemanager.IDevice; -import net.floodlightcontroller.devicemanager.IDeviceManager; import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.devicemanager.IEntityClassifier; import net.floodlightcontroller.devicemanager.internal.Device; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.devicemanager.IDeviceManagerAware; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; -public class MockDeviceManager implements IDeviceManager { +public class MockDeviceManager implements IFloodlightModule, IDeviceManagerService { protected Map<Long, Device> devices; public MockDeviceManager() { @@ -73,4 +78,45 @@ public class MockDeviceManager implements IDeviceManager { // TODO Auto-generated method stub return null; } + + @Override + public void addListener(IDeviceManagerAware listener) { + // TODO Auto-generated method stub + + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + // TODO Auto-generated method stub + return null; + } + + @Override + public + void + init(FloodlightModuleContext context) + throws FloodlightModuleException { + // TODO Auto-generated method stub + + } + + @Override + public void startUp(FloodlightModuleContext context) { + // TODO Auto-generated method stub + + } } diff --git a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java index e55152a48b4083550f626dda399f2ad998ccd567..06a6b19b85c5f7324ae411b61e1caf7c4bdf7a3f 100644 --- a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java +++ b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java @@ -31,23 +31,23 @@ import java.util.List; import java.util.Map; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.test.MockFloodlightProvider; -import net.floodlightcontroller.devicemanager.IDeviceManager; import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier; import net.floodlightcontroller.devicemanager.internal.Device; import net.floodlightcontroller.devicemanager.internal.Entity; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; import net.floodlightcontroller.packet.Data; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPacket; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.packet.UDP; -import net.floodlightcontroller.routing.IRoutingEngine; +import net.floodlightcontroller.routing.IRoutingEngineService; import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.test.FloodlightTestCase; -import net.floodlightcontroller.topology.ITopology; +import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.forwarding.Forwarding; import org.easymock.Capture; @@ -67,10 +67,10 @@ import org.openflow.protocol.action.OFActionOutput; public class ForwardingTest extends FloodlightTestCase { protected MockFloodlightProvider mockFloodlightProvider; protected FloodlightContext cntx; - protected IDeviceManager deviceManager; - protected IRoutingEngine routingEngine; + protected IDeviceManagerService deviceManager; + protected IRoutingEngineService routingEngine; protected Forwarding forwarding; - protected ITopology topology; + protected ITopologyService topology; protected IOFSwitch sw1, sw2; protected Device srcDevice, dstDevice1, dstDevice2; protected OFPacketIn packetIn; @@ -81,16 +81,16 @@ public class ForwardingTest extends FloodlightTestCase { protected Date currentDate; @Override - public void setUp() { + public void setUp() throws Exception { super.setUp(); // Mock context cntx = new FloodlightContext(); mockFloodlightProvider = getMockFloodlightProvider(); forwarding = getForwarding(); - deviceManager = createMock(IDeviceManager.class); - routingEngine = createMock(IRoutingEngine.class); - topology = createMock(ITopology.class); + deviceManager = createMock(IDeviceManagerService.class); + routingEngine = createMock(IRoutingEngineService.class); + topology = createMock(ITopologyService.class); forwarding.setFloodlightProvider(mockFloodlightProvider); forwarding.setDeviceManager(deviceManager); forwarding.setRoutingEngine(routingEngine); @@ -213,12 +213,14 @@ public class ForwardingTest extends FloodlightTestCase { ~OFMatch.OFPFW_NW_DST_MASK; // Add the packet to the context store - IFloodlightProvider.bcStore.put(cntx, - IFloodlightProvider.CONTEXT_PI_PAYLOAD, - (Ethernet)testPacket); - IDeviceManager.fcStore.put(cntx, - IDeviceManager.CONTEXT_SRC_DEVICE, - srcDevice); + IFloodlightProviderService.bcStore. + put(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, + (Ethernet)testPacket); + IDeviceManagerService.fcStore. + put(cntx, + IDeviceManagerService.CONTEXT_SRC_DEVICE, + srcDevice); } private Forwarding getForwarding() { @@ -236,9 +238,10 @@ public class ForwardingTest extends FloodlightTestCase { new Capture<FloodlightContext>(CaptureType.ALL); // Set destination as sw2 and Mock route - IDeviceManager.fcStore.put(cntx, - IDeviceManager.CONTEXT_DST_DEVICE, - dstDevice1); + IDeviceManagerService.fcStore. + put(cntx, + IDeviceManagerService.CONTEXT_DST_DEVICE, + dstDevice1); Route route = new Route(1L, 2L); route.setPath(new ArrayList<Link>()); @@ -296,9 +299,10 @@ public class ForwardingTest extends FloodlightTestCase { @Test public void testForwardSingleSwitchPath() throws Exception { // Set destination as local and Mock route - IDeviceManager.fcStore.put(cntx, - IDeviceManager.CONTEXT_DST_DEVICE, - dstDevice2); + IDeviceManagerService.fcStore. + put(cntx, + IDeviceManagerService.CONTEXT_DST_DEVICE, + dstDevice2); expect(routingEngine.getRoute(1L, 1L)).andReturn(null).atLeastOnce(); // Expected Flow-mods diff --git a/src/test/java/net/floodlightcontroller/hub/HubTest.java b/src/test/java/net/floodlightcontroller/hub/HubTest.java index 6311b2518e067349f215be66b6775adb375739f1..b4a215cd066a7772fc669683dba47aedeb8e7bca 100644 --- a/src/test/java/net/floodlightcontroller/hub/HubTest.java +++ b/src/test/java/net/floodlightcontroller/hub/HubTest.java @@ -60,7 +60,7 @@ public class HubTest extends FloodlightTestCase { private Hub hub; @Before - public void setUp() { + public void setUp() throws Exception { super.setUp(); mockFloodlightProvider = getMockFloodlightProvider(); diff --git a/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java b/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java index ecbb4d2a2991a54a25276e3ee19c133e27b06bdc..613f8990dacbf0e965b9426b39cebd5b144cf9cd 100644 --- a/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java +++ b/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java @@ -63,7 +63,7 @@ public class LearningSwitchTest extends FloodlightTestCase { private LearningSwitch learningSwitch; @Before - public void setUp() { + public void setUp() throws Exception { super.setUp(); mockFloodlightProvider = getMockFloodlightProvider(); diff --git a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java index fbd700e28ddaf385f36fc07cf0dbfbd5e836962e..825f2f1194f9bb1639f13dabd362c76cf18b435a 100644 --- a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java +++ b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java @@ -27,9 +27,10 @@ import org.openflow.util.HexString; public class StaticFlowEntryPusherTest extends FloodlightTestCase { String flowMod1, flowMod2; static String TestSwitch1DPID = "00:00:00:00:00:00:00:01"; + StaticFlowEntryPusher staticFlowEntryPusher; @Before - public void setUp() { + public void setUp() throws Exception { super.setUp(); flowMod1 = "{\"switch\": \"00:00:00:00:00:00:00:01\", " + "\"name\": \"flow-mod-1\", " + @@ -46,13 +47,17 @@ public class StaticFlowEntryPusherTest extends FloodlightTestCase { "\"ingress-port\": \"2\"," + "\"active\": \"true\", " + "\"actions\": \"output=3\"}"; + + staticFlowEntryPusher = new StaticFlowEntryPusher(); + staticFlowEntryPusher.floodlightProvider = + getMockFloodlightProvider(); + staticFlowEntryPusher.setFlowPushTime(200); + staticFlowEntryPusher.startUp(null); } @Test public void testAddAndRemoveEntries() throws Exception { - StaticFlowEntryPusher staticFlowEntryPusher = - new StaticFlowEntryPusher(); - staticFlowEntryPusher.setFlowPushTime(200); + IOFSwitch mockSwitch = createMock(IOFSwitch.class); long dpid = HexString.toLong(TestSwitch1DPID); Capture<OFMessage> writeCapture = new Capture<OFMessage>(CaptureType.ALL); @@ -70,9 +75,6 @@ public class StaticFlowEntryPusherTest extends FloodlightTestCase { Map<Long, IOFSwitch> switchMap = new HashMap<Long, IOFSwitch>(); switchMap.put(dpid, mockSwitch); mockFloodlightProvider.setSwitches(switchMap); - staticFlowEntryPusher.setFloodlightProvider(mockFloodlightProvider); - staticFlowEntryPusher.startUp(); - // if someone calls getId(), return this dpid instead expect(mockSwitch.getId()).andReturn(dpid).anyTimes(); replay(mockSwitch); @@ -93,8 +95,9 @@ public class StaticFlowEntryPusherTest extends FloodlightTestCase { while (count >= 0) { Thread.sleep(staticFlowEntryPusher.getFlowPushTime()); - if (writeCapture.getValues().size() >= 4) + if (writeCapture.getValues().size() >= 4) { break; + } count -= 1; } diff --git a/src/test/java/net/floodlightcontroller/storage/memory/tests/MemoryStorageTest.java b/src/test/java/net/floodlightcontroller/storage/memory/tests/MemoryStorageTest.java index 9e8d7c0a82b0f0afe484804208a00d795a93f678..c2500662218deb316fcb2cb620f766c04012c3a6 100644 --- a/src/test/java/net/floodlightcontroller/storage/memory/tests/MemoryStorageTest.java +++ b/src/test/java/net/floodlightcontroller/storage/memory/tests/MemoryStorageTest.java @@ -17,6 +17,9 @@ package net.floodlightcontroller.storage.memory.tests; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.restserver.IRestApiService; +import net.floodlightcontroller.restserver.RestApiServer; import net.floodlightcontroller.storage.memory.MemoryStorageSource; import net.floodlightcontroller.storage.tests.StorageTest; import org.junit.Before; @@ -24,8 +27,15 @@ import org.junit.Before; public class MemoryStorageTest extends StorageTest { @Before - public void setUp() { + public void setUp() throws Exception { storageSource = new MemoryStorageSource(); + restApi = new RestApiServer(); + FloodlightModuleContext fmc = new FloodlightModuleContext(); + fmc.addService(IRestApiService.class, restApi); + restApi.init(fmc); + storageSource.init(fmc); + restApi.startUp(fmc); + storageSource.startUp(fmc); super.setUp(); } } diff --git a/src/test/java/net/floodlightcontroller/storage/tests/StorageTest.java b/src/test/java/net/floodlightcontroller/storage/tests/StorageTest.java index 78957a3fdc3b10c8692743f1df20f2fd596bcce1..a76b98cbc6ed716532a74aacb3e321ade40a300c 100644 --- a/src/test/java/net/floodlightcontroller/storage/tests/StorageTest.java +++ b/src/test/java/net/floodlightcontroller/storage/tests/StorageTest.java @@ -30,25 +30,27 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import net.floodlightcontroller.perfmon.PktinProcessingTime; +import net.floodlightcontroller.perfmon.PktInProcessingTime; +import net.floodlightcontroller.restserver.RestApiServer; import net.floodlightcontroller.storage.CompoundPredicate; import net.floodlightcontroller.storage.IStorageExceptionHandler; import net.floodlightcontroller.storage.IPredicate; import net.floodlightcontroller.storage.IQuery; import net.floodlightcontroller.storage.IResultSet; import net.floodlightcontroller.storage.IRowMapper; -import net.floodlightcontroller.storage.IStorageSource; import net.floodlightcontroller.storage.IStorageSourceListener; import net.floodlightcontroller.storage.NullValueStorageException; import net.floodlightcontroller.storage.OperatorPredicate; import net.floodlightcontroller.storage.RowOrdering; +import net.floodlightcontroller.storage.nosql.NoSqlStorageSource; import net.floodlightcontroller.test.FloodlightTestCase; import org.junit.Test; public abstract class StorageTest extends FloodlightTestCase { - protected IStorageSource storageSource; + protected NoSqlStorageSource storageSource; + protected RestApiServer restApi; protected String PERSON_TABLE_NAME = "Person"; @@ -138,9 +140,10 @@ public abstract class StorageTest extends FloodlightTestCase { } } - public void setUp() { + public void setUp() throws Exception { super.setUp(); - PktinProcessingTime pktinProcessingTime = new PktinProcessingTime(); + PktInProcessingTime pktinProcessingTime = new PktInProcessingTime(); + pktinProcessingTime.startUp(null); storageSource.setPktinProcessingTime(pktinProcessingTime); Set<String> indexedColumnNames = new HashSet<String>(); indexedColumnNames.add(PERSON_LAST_NAME); diff --git a/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java b/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java index 46a0ede9763abfbfaa59db7505ff532d9e947f33..ac711dbd3837d2109c45905761798df975cef2e1 100644 --- a/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java +++ b/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java @@ -19,7 +19,7 @@ package net.floodlightcontroller.test; import junit.framework.TestCase; import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProvider; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.test.MockFloodlightProvider; import net.floodlightcontroller.packet.Ethernet; @@ -34,8 +34,6 @@ import org.openflow.protocol.OFType; * @author David Erickson (daviderickson@cs.stanford.edu) */ public class FloodlightTestCase extends TestCase { - - protected MockFloodlightProvider mockFloodlightProvider; public MockFloodlightProvider getMockFloodlightProvider() { @@ -56,15 +54,15 @@ public class FloodlightTestCase extends TestCase { OFPacketIn pi = (OFPacketIn)m; Ethernet eth = new Ethernet(); eth.deserialize(pi.getPacketData(), 0, pi.getPacketData().length); - IFloodlightProvider.bcStore.put(bc, - IFloodlightProvider.CONTEXT_PI_PAYLOAD, + IFloodlightProviderService.bcStore.put(bc, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); } return bc; } @Override - public void setUp() { + public void setUp() throws Exception { mockFloodlightProvider = new MockFloodlightProvider(); } diff --git a/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java b/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java index 399bc3af6f9c076ed10c073a0c171d2f843f3b3b..eb6a3f58d197a28bba5a26427a138cc213efb0ce 100644 --- a/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java +++ b/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java @@ -33,11 +33,16 @@ import org.junit.Test; import org.openflow.protocol.OFPortStatus; import org.openflow.protocol.OFPhysicalPort; +import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.routing.IRoutingEngineService; import net.floodlightcontroller.routing.dijkstra.RoutingImpl; +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.memory.MemoryStorageSource; import net.floodlightcontroller.test.FloodlightTestCase; -import net.floodlightcontroller.topology.ITopologyAware; +import net.floodlightcontroller.topology.ITopologyListener; +import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.LinkInfo; import net.floodlightcontroller.topology.LinkTuple; @@ -59,17 +64,20 @@ public class TopologyImplTest extends FloodlightTestCase { } @Before - public void setUp() { + public void setUp() throws Exception { super.setUp(); + FloodlightModuleContext cntx = new FloodlightModuleContext(); topology = new TopologyImpl(); - topology.setFloodlightProvider(getMockFloodlightProvider()); - topology.setStorageSource(new MemoryStorageSource()); RoutingImpl routingEngine = new RoutingImpl(); - topology.setRoutingEngine(routingEngine); - ArrayList<ITopologyAware> topologyAware = new ArrayList<ITopologyAware>(); - topologyAware.add(routingEngine); - topology.setTopologyAware(topologyAware); - topology.startUp(); + topology.topologyAware = new ArrayList<ITopologyListener>(); + cntx.addService(IRoutingEngineService.class, routingEngine); + cntx.addService(ITopologyService.class, topology); + cntx.addService(IStorageSourceService.class, new MemoryStorageSource()); + cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider()); + routingEngine.init(cntx); + topology.init(cntx); + routingEngine.startUp(cntx); + topology.startUp(cntx); } @Test