Tutorial to Build a FloodLight SDN OpenFlow Controller Module

Tutorial to Build a FloodLight SDN OpenFlow Controller Module

Programming

Tutorial to Build a FloodLight SDN OpenFlow Controller Module

This how-to is a tutorial to build a FloodLight SDN OpenFlow controller module in Java using the open source OpenFlow controller FloodLight that BigSwitch open sourced to the community. The installation and class creation is documented on the FloodLight Wiki. I am adding a screencast of the installation for those who get stuck on any steps. This is just how to extract PacketIn fields, the next step is to create custom actions that can be programmatically executed. If comfortable with getting Floodlight up and running in a development environment you could skip to the 2nd post the not only extracts the packet-in but also a FlowMod is performed: Floodlight OpenFlow Controller: Using the Static Flow Entry Pusher

Preparing the System for Eclipse and FloodLight
  • The screencast is on a Mac running VMWare Fusion but VirtualBox works just the same for this tutorial and is free. VirtualBox can be downloaded here.
  • The OS is Ubuntu 12.04 installed on a VM. A tutorial for preparing the Ubuntu image is here. Just any vanilla Ubuntu or any other Linux distro will cover it so use whatever you like.
  • Mac installation is about the exact same.
  • Windows will need some trickery to get Apache Ant built.

Install the FloodLight OpenFlow SDN Controller

The following is from the FloodLight Wiki Installation Guide. It’s perfect so no need to rewrite it.

Open eclipse and create a new workspace (inside Eclipse) :

  • ./eclipse & <-Non-root from the command line or find the icon to launch it Eclipse.
  • File -> Import -> General -> Existing Projects into Workspace. Then click “Next”.
  • From “Select root directory” click “Browse”. Select the parent directory where you placed floodlight earlier.
  • Check the box for “Floodlight”. No other Projects should be present and none should be selected.
  • Click Finish.

Create the FloodlightLaunch target (inside Eclipse):

  • Click Run->Run Configurations
  • Right Click Java Application->New
  • For Name use FloodlightLaunch
  • For Project use Floodlight
  • For Main use net.floodlightcontroller.core.Main
  • Click Apply

Add a Class In Eclipse

I am naming this class HeaderExtract. A package is normally lower case “headerextract” while the class inside the package is named with some upper cases “HeaderExtract”

    1. Expand the “floodlight” item in the Package Explorer and find the “src/main/java” folder.
    2. Right-click on the “src/main/java” folder and choose “New/Class.”
    3. Enter “net.floodlightcontroller.headerextract” in the “Package” box.
    4. Enter “HeaderExtract” in the “name” box.
    5. Next to the “Interfaces” box, choose “Add…”
    6. Type “IOFMessageListener” into the search box, and choose “OK.”
    7. Type “IFloodlightModule” into the search box, and choose “OK.”
    8. Click “Finish” in the dialog.
  • Next add net.floodlightcontroller.headerextract.HeaderExtract to the default startup modules in:

floodlightdefault.properties should look something like this:

net.floodlight.core.module.IFloodlightModule should look something like this:

Keep in mind those modules are subject to change as new modules are added into the FloodLight trunk. The main reason I pasted it is in case it is confusing on where to paste the module you want to add.

Add code to your new Class

This is once you created your class you will have a skeleton configuration. You can delete what is in “HeaderExtract.java” and replace it with the code below. The only difference from the MacTracker tutorial is some of the imports and the initialization method. We are capturing the packet-in the same way but just pulling a couple of different fields than the MacTracker class.

  • Paste the above code into HeaderExtract.java and save it. Then run configuration and hopefully you don’t get too many errors. Refer to the video to see if you missed a step.

PacketIn Extract

The guts of this class is capturing the packet-in and extracting the L2-L4 headers, convert them from binary using various modules. The snippet below extracts the packet-in fields and displays them as a string. I am just using “println” function to spit out STDOUT. MacTracker uses a logging module that is sexier. The key is getting all of the various fields and then having the flexibility to instantiate whatever you want into the fields and even further down the road whatever meta-data you want to inject. This extensibility is easier in software switching today, but presumably will improve in hardware in the future.

  • Quick look at a snippet:

  • The output in your console will look like this:

Download Install Mininet that acts as an OpenFlow enabled vSwitch

  • Download Mininet from here.
  • Installation instructions are here.

Essentially its pretty easy peasy, just download and extract the image and start it in your hypervisor (VM Fusion, VirtualBox). You will now have two VMs if you are nesting both your Linux image and Mininet or just one if you are running Eclipse on your Mac/Linux/Windows native OS.

Once installed and booted the following should get you going.

TRealtime OpenFlow SDN Magic on the FloodLight Controller

ssh to your Mininet instance with the following:

Start FloodLight in Eclipse and you should see Mininet attach to the controller.

From your ssh window some commands to get started are:

  • pingall <-H2 (host2) and H3 (host3) will ping one another.
  • dump <-Displays the configuration and IPs
  • Help <- Well you get this one.
  • xterm h2 <- Will spawn an Xterm window that gives you the console on h2.
  • (In Xterm) tcpdump -XX -n <-Will run tcpdump from the host perspective.
  • You can also run Wireshark over the SSH session and capture any of the interfaces with ‘wireshark’ from the command line.

ScreenCast of the Build

If interested, get involved in the OpevSwitch and Openflow communities. Anyone can be part of shaping the industry in the coming years. I can attest that folks from BigSwitch like Paul Lappas, Nick Bastin, Alex Riemers and (KC) Wang and everyone else I have meet or spoken with online are all super helpful in fostering the FloodLight dev community. They have amazing tutorials on their wiki and OpenFlow hub found here.


Building OpenFlow Applications
The second part of this tutorial can be found at Floodlight OpenFlow Controller: Using the Static Flow Entry

Thanks for stopping by!


About the Author

Brent SalisburyI have over 20 years of experience wearing various hats from, network engineer, architect, ops and software engineer. More at Brent's LinkedInView all posts by Brent Salisbury →

  1. JasonJason11-29-2012


    I’m just getting up to speed on OpenFlow, and one of the things I keep hearing about is the ability to build applications around OpenFlow. But if I understand OpenFlow correctly, its for switch to controller communication, and not for communication between my application and the switch.

    Instead my custom application will use the API exposed by the controller (REST or perhaps as a loadable module for FloodLight). So as an application writer, I’ll be writing against a controllers API, and not really gaining from the standard protocol of OpenFlow?

  2. Brent SalisburyBrent Salisbury12-03-2012


    Heya Jason,

    Apologies for the delayed response. I would agree that most likely the majority applications will be written against a more abstracted primitive than OpenFlow. Even inside of FloodLight some applications are written to an API rather than breaking into the application logic.

    FloodLight REST API:
    http://www.openflowhub.org/display/floodlightcontroller/Floodlight+REST+API

    FloodLight CircuitPusher:
    http://www.openflowhub.org/display/floodlightcontroller/Circuit+Pusher

    Here is a great tutorial from David Erickson using Beacon which FloodLight was built on top of:
    http://www.openflow.org/wk/index.php/BeaconTutorial

    Thanks,
    -Brent

  3. GaganGagan12-16-2012


    Hi,

    That was pretty informative. I have a few doubts though. Could you please explain ?

    The contrasting point between your implementation and the MACTracker in Floodlight tutorials, is in the extraction of the header fields.

    In the MACTracker, the MAC address is extracted using :

    Ethernet eth =
    IFloodlightProviderService.bcStore.get(cntx,
    IFloodlightProviderService.CONTEXT_PI_PAYLOAD);

    Long sourceMACHash = Ethernet.toLong(eth.getSourceMACAddress());

    Clearly they do not use the input parameter ‘OFmessage msg’. (or are they ?)

    And in your implementation, the headers are extracted from OFmessage, and although you are capturing the ‘BasePacket pkt’ it is not being used anywhere.

    Could you please explain what these all data types and parameters mean ? OFMessage must be the OpenFlow message that we are getting from the switch, as the name suggests. But I dont understand this BasePacket thing, or the way header is extracted in MACTracker.

    Like, the way you have extracted the headers is intuitive, but how it is done in MACTracker, doesnt make much sense to me.

    Can we do the same thing using OFMessage as well as the BasePacket ? What is BasePacket actually ?

    If you have any link/references to these, please share. And pardon me if my doubts are too naive. I am just a beginner.

    Thanks

  4. RameshRamesh07-16-2013


    Hello Sir i m new to SDN and tryin to add a module in floodlight controller and keeps on getting this two things in my console continously can u please help me out with this

    10:39:20.939 [Scheduled-3] DEBUG o.s.s.i.config.DelegatingCCProvider – ClusterConfig provider PropertyCCProvider failed: Configuration properties nodes or thisNode not set
    10:39:20.957 [Scheduled-3] DEBUG o.s.s.i.config.DelegatingCCProvider – ClusterConfig provider StorageCCProvider failed: No controller ID configured and could not read /opt/bigswitch/run/boot-config

  5. ZuhranZuhran07-22-2013


    Sir, i have currently installed Floodlight and am running it in Eclipse. But the problem is that it doesn’t stop and keep sending “LLDP messages on all ports”. How to solve the problem please.

  6. Milson MunakamiMilson Munakami04-22-2014


    Everything I configure as you mentioned but as soon as I copy the code for ExtractHeader.java file and run it shows long list of errors and I can’t continue further>

    20:49:37.548 INFO [n.f.c.m.FloodlightModuleLoader:main] Loading default modules
    20:49:39.000 INFO [n.f.c.i.Controller:main] Controller role set to MASTER
    20:49:39.012 INFO [n.f.c.i.Controller:main] Flush switches on reconnect — Disabled
    20:49:41.595 ERROR [o.s.s.i.c.DelegatingCCProvider:main] Failed to initialize provider org.sdnplatform.sync.internal.config.SyncStoreCCProvider
    org.sdnplatform.sync.error.PersistException: Could not initialize persistent storage
    at org.sdnplatform.sync.internal.store.JavaDBStorageEngine.(JavaDBStorageEngine.java:106) ~[bin/:na]
    at org.sdnplatform.sync.internal.StoreRegistry.register(StoreRegistry.java:116) ~[bin/:na]
    at org.sdnplatform.sync.internal.SyncManager.registerPersistentStore(SyncManager.java:184) [bin/:na]
    at org.sdnplatform.sync.internal.config.SyncStoreCCProvider.init(SyncStoreCCProvider.java:85) ~[bin/:na]
    at org.sdnplatform.sync.internal.config.DelegatingCCProvider.init(DelegatingCCProvider.java:37) ~[bin/:na]
    at org.sdnplatform.sync.internal.SyncManager.init(SyncManager.java:489) [bin/:na]
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.initModules(FloodlightModuleLoader.java:436) [bin/:na]
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.loadModulesFromList(FloodlightModuleLoader.java:353) [bin/:na]
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.loadModulesFromList(FloodlightModuleLoader.java:362) [bin/:na]
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.loadModulesFromConfig(FloodlightModuleLoader.java:200) [bin/:na]
    at net.floodlightcontroller.core.Main.main(Main.java:55) [bin/:na]
    Caused by: java.sql.SQLException: Failed to create database ‘/var/lib/floodlight/SyncDB’, see the next exception for details.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.Util.seeNextException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.EmbedConnection.createDatabase(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.EmbedConnection.(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.EmbedConnection30.(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.EmbedConnection40.(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.Driver40.getNewEmbedConnection(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.EmbeddedDataSource.getConnection(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.EmbedPooledConnection.openRealConnection(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.EmbedPooledConnection.(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.EmbedPooledConnection40.(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.Driver40.getNewPooledConnection(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource.createPooledConnection(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource.getPooledConnection(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.sdnplatform.sync.internal.store.JavaDBStorageEngine.getConnection(JavaDBStorageEngine.java:368) ~[bin/:na]
    at org.sdnplatform.sync.internal.store.JavaDBStorageEngine.initTable(JavaDBStorageEngine.java:375) ~[bin/:na]
    at org.sdnplatform.sync.internal.store.JavaDBStorageEngine.(JavaDBStorageEngine.java:104) ~[bin/:na]
    … 10 common frames omitted
    Caused by: org.apache.derby.impl.jdbc.EmbedSQLException: Failed to create database ‘/var/lib/floodlight/SyncDB’, see the next exception for details.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source) ~[derby-10.9.1.0.jar:na]
    … 29 common frames omitted
    Caused by: org.apache.derby.impl.jdbc.EmbedSQLException: Directory /var/lib/floodlight/SyncDB cannot be created.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    … 26 common frames omitted
    Caused by: org.apache.derby.iapi.error.StandardException: Directory /var/lib/floodlight/SyncDB cannot be created.
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.services.monitor.StorageFactoryService$9.run(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_51]
    at org.apache.derby.impl.services.monitor.StorageFactoryService.createServiceRoot(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.services.monitor.BaseMonitor.bootService(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.impl.services.monitor.BaseMonitor.createPersistentService(Unknown Source) ~[derby-10.9.1.0.jar:na]
    at org.apache.derby.iapi.services.monitor.Monitor.createPersistentService(Unknown Source) ~[derby-10.9.1.0.jar:na]
    … 26 common frames omitted
    20:49:42.436 INFO [n.f.l.i.LinkDiscoveryManager:main] Setting autoportfast feature to OFF
    20:49:43.040 INFO [o.s.s.i.c.FallbackCCProvider:main] Cluster not yet configured; using fallback local configuration
    20:49:43.049 INFO [o.s.s.i.SyncManager:main] [32767] Updating sync configuration ClusterConfig [allNodes={32767=Node [hostname=localhost, port=6642, nodeId=32767, domainId=32767]}, authScheme=CHALLENGE_RESPONSE, keyStorePath=/etc/floodlight/auth_credentials.jceks, keyStorePassword is unset]
    Exception in thread “main” org.jboss.netty.channel.ChannelException: Failed to bind to: localhost/127.0.0.1:6642
    at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:303)
    at org.sdnplatform.sync.internal.rpc.RPCService.startServer(RPCService.java:465)
    at org.sdnplatform.sync.internal.rpc.RPCService.run(RPCService.java:219)
    at org.sdnplatform.sync.internal.SyncManager.startUp(SyncManager.java:585)
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.startupModules(FloodlightModuleLoader.java:455)
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.loadModulesFromList(FloodlightModuleLoader.java:354)
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.loadModulesFromList(FloodlightModuleLoader.java:362)
    at net.floodlightcontroller.core.module.FloodlightModuleLoader.loadModulesFromConfig(FloodlightModuleLoader.java:200)
    at net.floodlightcontroller.core.Main.main(Main.java:55)
    Caused by: java.net.BindException: Address already in use
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Net.java:444)
    at sun.nio.ch.Net.bind(Net.java:436)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.bind(NioServerSocketPipelineSink.java:148)
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleServerSocket(NioServerSocketPipelineSink.java:100)
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:74)
    at org.jboss.netty.channel.Channels.bind(Channels.java:468)
    at org.jboss.netty.channel.AbstractChannel.bind(AbstractChannel.java:192)
    at org.jboss.netty.bootstrap.ServerBootstrap$Binder.channelOpen(ServerBootstrap.java:348)
    at org.jboss.netty.channel.Channels.fireChannelOpen(Channels.java:176)
    at org.jboss.netty.channel.socket.nio.NioServerSocketChannel.(NioServerSocketChannel.java:85)
    at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.newChannel(NioServerSocketChannelFactory.java:142)
    at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.newChannel(NioServerSocketChannelFactory.java:90)
    at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:282)
    … 8 more
    20:49:51.306 INFO [n.f.j.JythonServer:debugserver-main] Starting DebugServer on :6655
    Exception in thread “debugserver-main” Traceback (most recent call last):
    File “”, line 1, in
    File “/home/milson/floodlight/target/bin/../../src/main/python/debugserver.py”, line 69, in run_server
    server = DebugServer((host, port), DebugServerHandler)
    File “/home/milson/floodlight/lib/jython-2.5.2.jar/Lib/SocketServer.py”, line 331, in __init__
    File “/home/milson/floodlight/lib/jython-2.5.2.jar/Lib/SocketServer.py”, line 350, in server_activate
    File “”, line 1, in listen
    File “/home/milson/floodlight/lib/jython-2.5.2.jar/Lib/socket.py”, line 934, in listen
    socket.error: (98, ‘Address already in use’)

    Can you explain why and how can I fix this issue with eclipse?