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.

sudo apt-get install build-essential default-jdk ant python-dev eclipse
git clone git://github.com/floodlight/floodlight.git
cd floodlight
ant eclipse

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:
src/main/resources/floodlightdefault.properties
src/main/resources/META-INF/services/net.floodlight.core.module.IFloodlightModule

floodlightdefault.properties should look something like this:

floodlight.modules = net.floodlightcontroller.storage.memory.MemoryStorageSource,\
net.floodlightcontroller.core.FloodlightProvider,\
net.floodlightcontroller.threadpool.ThreadPool,\
net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl,\
net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier,\
net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher,\
net.floodlightcontroller.firewall.Firewall,\
net.floodlightcontroller.forwarding.Forwarding,\
net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager, \
net.floodlightcontroller.topology.TopologyManager, \
net.floodlightcontroller.flowcache.FlowCache, \
net.floodlightcontroller.flowcache.FlowReconcileManager, \
net.floodlightcontroller.jython.JythonDebugInterface,\
net.floodlightcontroller.counter.CounterStore,\
net.floodlightcontroller.perfmon.PktInProcessingTime,\
net.floodlightcontroller.ui.web.StaticWebRoutable,\
net.floodlightcontroller.headerextract.HeaderExtract
net.floodlightcontroller.restserver.RestApiServer.port = 8080
net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
net.floodlightcontroller.jython.JythonDebugInterface.port = 6655
net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
src/main/resources/META-INF/services/net.floodlight.core.module.IFloodlightModule

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

net.floodlightcontroller.core.FloodlightProvider
net.floodlightcontroller.storage.memory.MemoryStorageSource
net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl
net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager
net.floodlightcontroller.topology.TopologyManager
net.floodlightcontroller.forwarding.Forwarding
net.floodlightcontroller.flowcache.FlowCache
net.floodlightcontroller.flowcache.FlowReconcileManager
net.floodlightcontroller.core.OFMessageFilterManager
net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher
net.floodlightcontroller.perfmon.PktInProcessingTime
net.floodlightcontroller.perfmon.NullPktInProcessingTime
net.floodlightcontroller.restserver.RestApiServer
net.floodlightcontroller.learningswitch.LearningSwitch
net.floodlightcontroller.hub.Hub
net.floodlightcontroller.jython.JythonDebugInterface
net.floodlightcontroller.counter.CounterStore
net.floodlightcontroller.counter.NullCounterStore
net.floodlightcontroller.threadpool.ThreadPool
net.floodlightcontroller.ui.web.StaticWebRoutable
net.floodlightcontroller.virtualnetwork.VirtualNetworkFilter
net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier
net.floodlightcontroller.devicemanager.test.MockDeviceManager
net.floodlightcontroller.core.test.MockFloodlightProvider
net.floodlightcontroller.core.test.MockThreadPoolService
net.floodlightcontroller.firewall.Firewall
net.floodlightcontroller.headerextract.HeaderExtract

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.

package net.floodlightcontroller.headerextract;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFType;
import org.openflow.util.HexString;
import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFMessageListener;
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.packet.BasePacket;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService;
public class HeaderExtract implements IFloodlightModule, IOFMessageListener {
public final int DEFAULT_CACHE_SIZE = 10;
 protected IFloodlightProviderService floodlightProvider;
 private IStaticFlowEntryPusherService flowPusher;
@Override
 public String getName() {
 return "Names";
 }
 @Override
 public boolean isCallbackOrderingPrereq(OFType type, String name) {
 return false;
 }
 @Override
 public boolean isCallbackOrderingPostreq(OFType type, String name) {
 return false;
 }
//This is where we pull fields from the packet-in
 @Override
 public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
 BasePacket pkt = (BasePacket) IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
 //Instantiate two objects for OFMatch and OFPacketIn
 OFPacketIn pin = (OFPacketIn) msg;
 OFMatch match = new OFMatch();
 match.loadFromPacket(pin.getPacketData(), pin.getInPort());
//Destination IP Address for each packet-in
System.out.println("$$$$$-Get the Desitnation IP Address-$$$$$");
System.out.println(IPv4.fromIPv4Address(match.getNetworkDestination()));
// Source Mac Address for each packet-in
System.out.println("$$$$$-Mac Address Destination-$$$$$$");
Long sourceMACHash = Ethernet.toLong(match.getDataLayerDestination());
System.out.println(HexString.toHexString(sourceMACHash));
//Here we print the entire packet-in array which has all matchable fields
System.out.println("$$$$$-PacketIn ARRAY-$$$$$");
System.out.println(Arrays.asList(match));

return Command.CONTINUE;
}
@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() {
Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
return l;
}

@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
}
@Override
public void startUp(FloodlightModuleContext context) {
floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
}
}
  • 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:
System.out.println("$$$$-PacketIn ARRAY-$$$$"); <--Just a string denoting the beginning of the next line.
System.out.println(Arrays.asList(match)); <-Print the packet-in OFMatch object elements packed in an array
  • The output in your console will look like this:
$$$$$$$$$$$$-PacketIn ARRAY-$$$$$$$$$$$$
[OFMatch[in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_src=e6:69:06:a0:98:0b,dl_type=0x806,dl_vlan=0xffff,dl_vlan_pcp=0,nw_dst=10.0.0.3,nw_src=10.0.0.2,nw_proto=1,nw_tos=0,tp_dst=1,tp_src=0]]

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.

ifconfig eth0 <-grab the IP address of the device.
sudo passwd root <- Optional but I do everything as root in this.
apt-get install ssh

TRealtime OpenFlow SDN Magic on the FloodLight Controller

ssh to your Mininet instance with the following:

ssh -YC root@<insert ip address of the Mininet host from ifconfig eth0> 
mn --controller=remote --ip=<Eclipse Floodlight IP> --port=6633

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 SalisburyBrent Salisbury works as a Network Architect, CCIE #11972. He blogs at NetworkStatic.net with a focus on disruptive technologies, that have a focus on operational efficiencies. Brent can be reached on Twitter @NetworkStatic.View 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.

Leave a Reply