Mininet OpenFlow Tutorial
Mininet OpenFlow Tutorial
This tutorial is your opportunity to gain hands-on experience with the platforms and debugging tools
most useful for developing network control applications on OpenFlow. This page contains some
material to get you started with Openflow and Mininet. Check the side bar on the right for a list of
assignments to walk you through everything from the creation of your virtual machine to the
implementation of an openflow router.
The sidebar to the right is an index to the various sections of the tutorial. A good place to start is
Installing Required Software.
Table of Contents
o Welcome to the OpenFlow tutorial!
Overview
o Pre-requisites
o Stuck? Found a bug? Questions?
Learn More
o OpenFlow
o Additional Tools
o Old Regression Tests
Page 1
mininet Openflow Tutorial
Credits
Notes
o VM Creation Notes
Overview
In this tutorial, you'll turn the provided hub controller into a controller-based learning switch, then a
flow-accelerated learning switch, and extend this from a single-switch network to a multiple-switch
multiple-host network. You can also find guidelines for further extensions. Along the way, you'll learn
the full suite of OpenFlow debugging tools. You will:
After the tutorial, you can apply what you've learned to physical networks based on software switches,
NetFPGAs, or even hardware switches at line rate.
To get you started quickly, we provide a preconfigured virtual machine with the needed software.
Pre-requisites
You will need a computer with at least 1GB (preferably 2GB+) of RAM and at least 5GB of free hard
disk space (more preferred). A faster processor may speed up the virtual machine boot time, and a larger
screen may help to manage multiple terminal windows.
Page 2
mininet Openflow Tutorial
These instructions consider Linux, OS X, and Windows. Linux and OS X are preferred - there's less to
install.
The tutorial instructions require no prior knowledge of OpenFlow. The OpenFlow Learn More page is a
concise introduction, and more information is available from the Open Networking Foundation.
If you are asking a question or reporting a bug, try to include as many details about your setup as
possible. Include your OS, virtualization software info, X11 and ssh software you're using, VM image
you're using, memory size, and the step you're on.
Learn More
OpenFlow
To learn more about OpenFlow in general, consult the Open Networking Foundation OpenFlow site and
the historical OpenFlow page. There are videos, blog entries, and more. Check the wiki for link to
OpenFlow-based projects and demos.
Additional Tools
Mininet.
FlowVisor.
Page 3
mininet Openflow Tutorial
Pages 12
Home
Installing Required Software
Set Up Virtual Machine
VirtualBox Specific Instructions
Learn Development Tools
Create a Learning Switch
Control a Slice of a Real Network
Router Exercise
Advanced Topology
Create Firewall
Frequently Asked Questions (FAQ)
Resources
The files include virtualization software, a SSH-capable terminal, an X server, and the VM image.
The tutorial image is distributed as a compressed VirtualBox image (vdi). VirtualBox enables you to run
a virtual machine inside a physical machine, and is free and available for Windows, Mac and Linux.
You can export the VirtualBox image to vmdk format and use it with VMWare using the instructions
below.
The following instructions assume the use of VirtualBox, but the instructions should apply regardless of
virtual software after you complete the initial setup.
Download Files
You'll need to download the files corresponding to your OS, plus the tutorial VM.
Virtual Machine Image (OVF format, 64-bit, Mininet 2.2.0) (Recommended for most modern hardware
and OSes)
Virtual Machine Image (OVF format, 32-bit, Mininet 2.2.0) (Recommended for ancient hardware and
Windows)
Page 4
mininet Openflow Tutorial
Important: For these VM images, the user name is 'mininet' with password 'mininet'.
The OVF format can be imported into VirtualBox, VMware, or other popular virtualization programs.
You will also need virtualization software, an X server, and an ssh-capable terminal emulator:
Virtualization
OS Type OS Version X Server Terminal
Software
OS X 10.7-10.9
Terminal.app
Mac Lion/Mountain Lion/ VirtualBox download and install XQuartz
(built in)
Mavericks
gnome terminal +
Linux Ubuntu 10.04+ VirtualBox X server already installed
SSH built in
Page 5
mininet Openflow Tutorial
Start up VirtualBox, then select File>Import Appliance and select the .ovf image that you downloaded.
You may also be able to simply double-click the .ovf file to open it up in your installed virtualization program.
This step will take a while - the unpacked image is about 3 GB.
Finish VM Setup
You will need to complete one more step before you are done with the VM setup.
Select your VM and go to the Settings Tab. Go to Network->Adapter 2. Select the "Enable adapter" box,
and attach it to "host-only network".(Sidenote: on a new VirtualBox installation you may not have any
"host-only network" configured yet. To have one select File menu/Preferences/Network and "Add host-
only network" button with default settings. Then you can try the attach.) This will allow you to easily
access your VM through your host machine.
At that point you should be ready to start your VM. Press the "Start" arrow icon or double-click your
VM within the VirtualBox window.
In the VM console window, log in with the user name and password for your VM. These should both be
"mininet"
Page 6
mininet Openflow Tutorial
Note that this user is a sudoer, so you can execute commands with root permissions by typing sudo
command, where command is the command you wish to execute with root permission.
Nano: You can immediately modify a file. When you're done, hit 'ctrl-x', then say 'Yes' to the prompt, to
save and quit.
Vim: to modify a file, type 'i' to enter Insert mode, then use the arrow keys to navigate and edit. When
you're done, hit 'esc', type ':wq', then press enter, to save and quit.
Highly recommended for the NOX tutorial: add the following to ~/.vimrc in the VM:
set tabstop=4
set expandtab
Emacs: you can immediately modify a file. When you're done, hit 'ctrl-x', 'ctrl-s', then hit 'ctrl-x', 'ctrl-c'
to exit.
Eclipse: Eclipse and its dependencies would require about 500MB extra space on the VM image, so it's
not shipped by default. If you have Eclipse installed on the host VM, using the Remote Systems
Explorer can be a convenient way to access and modify text files on the VM, with many of the
advantages of Eclipse, such as syntax highlighting.
If you have another preferred text editor, feel free to install it now:
In this tutorial, commands are shown along with a command prompt to indicate what subsystem they are
intended for . For example,
$ ls
indicates that the ls command should be typed at a Unix (e.g. Linux or OS X) command prompt (which
generally ends in $ if you are a regular user or # if you are root.
mininet>
Page 7
mininet Openflow Tutorial
C:>
To start up the X forwarding, you'll first need to find the guest IP address.
VirtualBox
If you are running VirtualBox, you should make sure your VM has two network interfaces. One should
be a NAT interface that it can use to access the Internet, and the other should be a host-only interface
to enable it to communicate with the host machine. For example, your NAT interface could be eth0 and
have a 10.x IP address, and your host-only interface could be eth1 and have a 192.168.x IP address. You
should ssh into the host-only interface at its associated IP address. Both interfaces should be configured
using DHCP. If they are not already configured, you may have to run dhclient on each of them, as
described below.
From the virtual machine console, log in to the VM, then enter:
$ ifconfig -a
You should see three interfaces(eth0, eth1, lo), Both eth0 and eth1 should have IP address assigned. If
this is not the case, type
Replacing ethX with the name of a downed interfaces; sometimes the eth ports appear as eth2 or eth3,
you can fix this by editing /etc/udev/rules.d/70-persistent-net.rules and removing the existing
configuration lines.
Note the IP address (probably the 192.168 one) for the host-only network; you'll need it later. Next, log
in, which will depend on your OS.
Page 8
mininet Openflow Tutorial
Open a terminal (Terminal.app in Mac, Gnome terminal in Ubuntu, etc). In that terminal, run:
Replace [user] with the correct user name for your VM image.
Replace [Guest] with the IP you just noted. If ssh does not connect, make sure that you can ping the IP
address you are connecting to.
Enter the password for your VM image. Next, try starting up an X terminal using
$ xterm
and a new terminal window should appear. If you have succeeded, you are done with the basic setup.
Close the xterm. If you get a 'xterm: DISPLAY is not set error', verify your X server installation from
above.
Windows
In order to use X11 applications such as xterm and wireshark, the Xming server must be running, and
you must make an ssh connection with X11 forwarding enabled.
First, start Xming (e.g. by double-clicking its icon.) No window will appear, but if you wish you can
verify that it is running by looking for its process in Windows' task manger.
If you start up puTTY as a GUI application, you can connect by entering your VM's IP address and
enabling X11 forwarding.
To enable X11 forwarding from puTTY's GUI, click puTTY->Connection->SSH->X11, then click on
Forwarding->"Enable X11 Forwarding", as shown below:
Page 9
mininet Openflow Tutorial
You can also run putty (with the -X option for X11 forwarding) from the Windows command line:
Open a terminal: click the Windows 'Start' button, 'run', then enter 'cmd'.
C:> cd <dir>
Run:
If putty cannot connect, try pinging the VM's IP address to make sure you are connecting to the correct
interface.
Once the ssh connection succeeds or a terminal window for the VM pops up, log in to the VM. Now,
type:
Page 10
mininet Openflow Tutorial
to start an X terminal (the -sb 500 is optional but gives 500 lines of scrollback.)
A white terminal window should appear. If you have succeeded, you are done with the basic setup.
Close the xterm.
If the xterm window does not appear, or if you get an error like "xterm: DISPLAY is not set," make sure
that Xming is running in Windows and that you have correctly enabled X11 forwarding.
$ sudo apt-get update && sudo apt-get install xinit lxde virtualbox-guest-dkms
At this point, you should be able to start an X11 session in the VM console window by typing:
$ startx
If you are familiar with Linux, you may wish to install another desktop manager (e.g. flwm if you want
something even smaller/faster than lxde or even the full ubuntu-desktop) or any other GUI packages
that you prefer.
Page 11
mininet Openflow Tutorial
VirtualBox console terminal: connects to OpenFlowTutorial. This is the one created when you started up
the VM. You can't copy and paste from this tutorial page to the console terminal, so it's a bit of a pain.
Minimize this NOW, if you haven't already done so. Once you've used it to set up networking, it won't
be needed.
SSH terminal: connects to OpenFlowTutorial. Created by using putty on Windows or SSH on OS X / Linux,
as described in the previous section. Copy and paste should work on this terminal.
xterm terminal: connects to a host in the virtual network. Created in the next section when you start up
the virtual network. Will be labeled at the top with the name of the host.
The OpenFlowTutorial VM includes a number of OpenFlow-specific and general networking utilities pre-
installed. Please read the short descriptions:
OpenFlow Controller: sits above the OpenFlow interface. The OpenFlow reference distribution includes
a controller that acts as an Ethernet learning switch in combination with an OpenFlow switch. You'll run
it and look at messages being sent. Then, in the next section, you'll write our own controller on top of
NOX or Beacon (platforms for writing controller applications).
OpenFlow Switch: sits below the OpenFlow interface. The OpenFlow reference distribution includes a
user-space software switch. Open vSwitch is another software but kernel-based switch, while there is a
number of hardware switches available from Broadcom (Stanford Indigo release), HP, NEC, and others.
ovs-ofctl: command-line utility that sends quick OpenFlow messages, useful for viewing switch port and
flow stats or manually inserting flow entries.
Wireshark: general (non-OF-specific) graphical utility for viewing packets. The OpenFlow reference
distribution includes a Wireshark dissector, which parses OpenFlow messages sent to the OpenFlow
default port (6633) in a conveniently readable way.
iperf: general command-line utility for testing the speed of a single TCP connection.
Mininet: network emulation platform. Mininet creates a virtual OpenFlow network - controller,
switches, hosts, and links - on a single real or virtual machine. More Mininet details can be found at the
Mininet web page.
cbench: utility for testing the flow setup rate of OpenFlow controllers.
From here on out, make sure to copy and paste as much as possible! For example, manually typing in ‘sudo dpctl
show n1:0’ may look correct, but will cause a confusing error; the 'nl' is short for NetLink, not n-one.
Table of Contents
Page 12
mininet Openflow Tutorial
o Start Network
o Mininet Brief Intro
o ovs-ofctl Example Usage
Accessing remote OVS instances or the Stanford reference switch
o Ping Test
o Start Wireshark
o Start Controller and view Startup messages in Wireshark
o View OpenFlow Messages for Ping
o Benchmark Controller w/iperf
o Next Step
Start Network
The network you'll use for the first exercise includes 3 hosts and a switch (and, eventually, an OpenFlow
controller, but we'll get to that later):
This tells Mininet to start up a 3-host, single-(openvSwitch-based)switch topology, set the MAC address
of each host equal to its IP, and point to a remote controller which defaults to the localhost.
Page 13
mininet Openflow Tutorial
mininet> nodes
mininet> help
To run a single command on a node, prepend the command with the name of the node. For example, to
check the IP of a virtual host, in the Mininet console, run:
mininet> h1 ifconfig
The alternative - better for running interactive commands and watching debug output - is to spawn an
xterm for one or more virtual hosts. In the Mininet console, run:
mininet> xterm h1 h2
You can close these windows now, as we'll run through most commands in the Mininet console.
If Mininet is not working correctly (or has crashed and needs to be restarted), first quit Mininet if
necessary (using the exit command, or control-D), and then try clearing any residual state or processes
using:
$ sudo mn -c
NB: The prompt mininet> is for Mininet console, $ is for SSH terminal (normal user) and # is for
SSH terminal (root user) (See Command Prompt Notes). Hereafter we follow with this rule.
Mininet has loads of other commands and startup options to help with debugging, and this brief starter
should be sufficient for the tutorial. If you're curious about other options, follow the Mininet
Walkthrough after the main tutorial.
Page 14
mininet Openflow Tutorial
ovs-ofctl is a utility that comes with Open vSwitch and enables visibility and control over a single
switch's flow table. It is especially useful for debugging, by viewing flow state and flow counters. Most
OpenFlow switches can start up with a passive listening port, from which you can poll the switch,
without having to add debugging code to the controller.
Create a second SSH window if you don't already have one, and run:
$ ovs-ofctl show s1
One user reports the need to prepend with sudo, otherwise a "permission denied" comes back:
The show command connects to the switch and dumps out its port state and capabilities.
$ ovs-ofctl dump-flows s1
Since we haven't started any controller yet, the flow-table should be empty.
Note: In the above example, ovs-ofctl is talking to a local instance of Open vSwitch via a Unix
domain socket which it is looking up by name. The actual socket is probably something like
/var/run/openvswitch/s1.mgmt . If you were running another switch such as the Stanford reference
switch or even a hardware OpenFlow switch, you would need to connect to a passive TCP port using a
command like
where {ip address} is the IP address of the switch's management interface and {port} is the passive
OpenFlow listening/management port. If Mininet is invoked with --switch user, it will open up a
passive listening port for each switch at port (6633+n) where n is the number of the switch. This will
enable ovs-ofctl to be used in commands like
For the purposes of this tutorial, you will usually be using Open vSwitch so you can just use the simple
form of the ovs-ofctl command.
Page 15
mininet Openflow Tutorial
Note that there are also dpctl and ovs-dpctl commands; usually these commands should not be used
and ovs-ofctl should be used instead! With Open vSwitch, those commands can allow you to examine
OVS's kernel flow cache, which is usually a subset of the full OpenFlow flow table which you or the
controller have programmed. Flows in OVS's flow cache will usually time out quickly, for example
within 5 seconds. This allows OVS to support large flow tables reasonably efficiently without a huge
kernel flow cache, but it can also introduce slowdowns when flows miss in the kernel flow cache and
have to be reloaded from user space.
Ping Test
Now, go back to the mininet console and try to ping h2 from h1. In the Mininet console:
Note that the name of host h2 is automatically replaced when running commands in the Mininet console
with its IP address (10.0.0.2).
As you saw before, switch flow table is empty. Besides that, there is no controller connected to the
switch and therefore the switch doesn't know what to do with incoming traffic, leading to ping failure.
You'll use ovs-ofctl to manually install the necessary flows. In your SSH terminal:
This will forward packets coming at port 1 to port 2 and vice-verca. Verify by checking the flow-table
# ovs-ofctl dump-flows s1
Do you get replies now? Check the flow-table again and look the statistics for each flow entry. Is this
what you expected to see based on the ping traffic?
Start Wireshark
The VM image includes the OpenFlow Wireshark dissector pre-installed. Wireshark is extremely useful
for watching OpenFlow protocol messages, as well as general debugging.
Start a new SSH terminal and connect to the VM with X11 forwarding.
Page 16
mininet Openflow Tutorial
$ ssh -X mininet@[guest]
You'll probably get a warning message for using wireshark with root access. Press OK.
Click on Capture->Interfaces in the menu bar. Click on the Start button next to 'lo', the loopback
interface. You may see some packets going by.
Now, set up a filter for OpenFlow control traffic, by typing 'of' in Filter box near the top:
of
Press the apply button to apply the filter to all recorded traffic.
$ controller ptcp:
This starts a simple controller that acts as a learning switch without installing any flow-entries.
You should see a bunch of messages displayed in Wireshark, from the Hello exchange onwards. As an
example, click on the Features Reply message. Click on the triangle by the 'OpenFlow Protocol' line in
the center section to expand the message fields. Click the triangle by Switch Features to display datapath
capabilities - feel free to explore.
Hello Controller- following the TCP handshake, the controller sends its version number to the
Page 17
mininet Openflow Tutorial
>Switch switch.
Switch-
Hello the switch replies with its supported version number.
>Controller
Features Controller-
the controller asks to see which ports are available.
Request >Switch
Controller-
Set Config in this case, the controller asks the switch to send flow expirations.
>Switch
Features Switch- the switch replies with a list of ports, port speeds, and supported tables and
Reply >Controller actions.
Switch- enables the switch to inform that controller of changes to port speeds or
Port Status
>Controller connectivity. Ignore this one, it appears to be a bug.
Since all messages are sent over localhost when using Mininet, determining the sender of a message can
get confusing when there are lots of emulated switches. However, this won't be an issue, since we only
have one switch. The controller is at the standard OpenFlow port (6633), while the switch is at some
other user-level port.
Before that update your wireshark filter to ignore the echo-request/reply messages (these are used to
keep the connection between the switch and controller alive): Type the following in your wireshark
filter, then press apply:
Note that there are a variety of other ways that you could express that filter.
If you have an old version of the wireshark plugin, you may need to use a slightly different syntax:
Run a ping to view the OpenFlow messages being used. You will need to run this without having any
flows between h1 and h2 already installed, e.g. from the "add-flows" command above:
Page 18
mininet Openflow Tutorial
It's also recommended to clean up ARP cache on both hosts, otherwise you might not see some ARP
requests/replies as the cache will be used instead:
In the Wireshark window, you should see a number of new message types:
Switch- a packet was received and it didn't match any entry in the switch's flow table,
Packet-In
>Controller causing the packet to be sent to the controller.
Controller-
Packet-Out controller send a packet out one or more switch ports.
>Switch
Controller-
Flow-Mod instructs a switch to add a particular flow to its flow table.
>Switch
Flow- Switch-
a flow timed out after a period of inactivity.
Expired >Controller
First, you see an ARP request miss the flow table, which generates a broadcast Packet-Out message.
Next, the ARP response comes back; with both MAC addresses now known to the controller, it can push
down a flow to the switch with a Flow-Mod message. The switch does then pushes flows for the ICMP
packets. Subsequent ping requests go straight through the datapath, and should incur no extra messages;
with the flows connecting h1 and h2 already pushed to the switch, there was no controller involvement.
Re-run the ping, again from the Mininet console (hitting up is sufficient - the Mininet console has a
history buffer):
If the ping takes the same amount of time, run the ping once more; the flow entries may have timed out
while reading the above text.
Page 19
mininet Openflow Tutorial
This is an example of using OpenFlow in a reactive mode, when flows are pushed down in response to
individual packets.
Alternately, flows can be pushed down before packets, in a proactive mode, to avoid the round-trip
times and flow insertion delays.
Here, you'll benchmark the reference controller; later, you'll compare this with the provided hub
controller, and your flow-based switch (when you've implemented it).
mininet> iperf
This Mininet command runs an iperf TCP server on one virtual host, then runs an iperf client on a
second virtual host. Once connected, they blast packets between each other and report the results.
mininet> exit
mininet> iperf
See a difference? With the user-space switch, packets must cross from user-space to kernel-space and
back on every hop, rather than staying in the kernel as they go through the switch. The user-space switch
is easier to modify (no kernel oops'es to deal with), but slower for simulation.
Exit Mininet:
mininet> exit
Page 20
mininet Openflow Tutorial
Later, you'll turn this into a flow-based switch, where seeing a packet with a known source and dest
causes a flow entry to get pushed down.
For this tutorial you will need to choose a controller platform to build on top of. The best option is likely
the controller written in the language you are most familiar with, although we recommend POX, as the
rest of the tutorial is based on it. Your options are:
Table of Contents
o Controller Choice: POX (Python)
Verify Hub Behavior with tcpdump
Benchmark Hub Controller w/iperf
Open Hub Code and Begin
Learning Python
Sending OpenFlow messages with POX
ofp_action_output class
ofp_match class
ofp_packet_out OpenFlow message
ofp_flow_mod OpenFlow message
Parsing Packets with the POX packet libraries
of_tutorial.py Walkthrough
o Controller Choice: Beacon (Java)
Setting up a Beacon Development Environment
Prerequisites
Setup
Running the Tutorial Controller
Verify Hub Behavior with tcpdump
Benchmark Hub Controller w/iperf
Open Tutorial Code and Begin
Phase 1
Phase 2
Learning Java and Beacon
Page 21
mininet Openflow Tutorial
One option for the first exercise is to use POX. POX is a Python-based SDN controller platform geared
towards research and education. For more details on POX, see the POX Wiki.
We're not going to be using the reference controller anymore, which may still be running (do 'ps -A |
grep controller' if you're unsure), so you should either press Ctrl-C in the window running the
controller program, or kill it from the other SSH window:
You should also run sudo mn -c and restart Mininet to make sure that everything is "clean" and using
the faster kernel switch. From your Mininet console:
mininet> exit
$ sudo mn -c
$ sudo mn --topo single,3 --mac --switch ovsk --controller remote
Page 22
mininet Openflow Tutorial
Newer mininet releases have POX preinstalled. If it's missing on your VM, or if you want a later version
of POX, download it from the POX repository on github into your VM:
This tells POX to enable verbose logging and to start the of_tutorial component which you'll be using
(which currently acts like a hub).
The switches may take a little bit of time to connect. When an OpenFlow switch loses its connection to a
controller, it will generally increase the period between which it attempts to contact the controller, up to
a maximum of 15 seconds. Since the OpenFlow switch has not connected yet, this delay may be
anything between 0 and 15 seconds. If this is too long to wait, the switch can be configured to wait no
more than N seconds using the --max-backoff parameter. Alternately, you exit Mininet to remove the
switch(es), start the controller, and then start Mininet to immediately connect.
Wait until the application indicates that the OpenFlow switch has connected. When the switch connects,
POX will print something like this:
The first line is from the portion of POX that handles OpenFlow connections. The second is from the
tutorial component itself.
Now we verify that hosts can ping each other, and that all hosts see the exact same traffic - the behavior
of a hub. To do this, we'll create xterms for each host and view the traffic in each. In the Mininet
console, start up three xterms:
mininet> xterm h1 h2 h3
Note: the xterm command does not work and will throw an error if you try to call it from the virtual box
directly, instead use another terminal window to call xterm.
Arrange each xterm so that they're all on the screen at once. This may require reducing the height of to
fit a cramped laptop screen.
Page 23
mininet Openflow Tutorial
In the xterms for h2 and h3, run tcpdump, a utility to print the packets seen by a host:
and respectively:
The ping packets are now going up to the controller, which then floods them out all interfaces except the
sending one. You should see identical ARP and ICMP packets corresponding to the ping in both xterms
running tcpdump. This is how a hub works; it sends all packets to every port on the network.
Now, see what happens when a non-existent host doesn't reply. From h1 xterm:
You should see three unanswered ARP requests in the tcpdump xterms. If your code is off later, three
unanswered ARP requests is a signal that you might be accidentally dropping packets.
First, verify reachability. Mininet should be running, along with the POX hub in a second window. In
the Mininet console, run:
mininet> pingall
This is just a sanity check for connectivity. Now, in the Mininet console, run:
mininet> iperf
Now, compare your number with the reference controller you saw before. How does that compare?
Go to your SSH terminal and stop the tutorial hub controller using Ctrl-C. The file you'll modify is
pox/misc/of_tutorial.py. Open this file in your favorite editor. Vim is a good choice, it comes already
Page 24
mininet Openflow Tutorial
downloaded with terminal. It has some funky commands to edit text so http://vim.rtorr.com can be of
use. To use vim, make sure you are in the correct directory (pox/pox/misc) and enter:
$ vi of_tutorial.py
The current code calls act_like_hub() from the handler for packet_in messages to implement switch
behavior. You'll want to switch to using the act_like_switch() function, which contains a sketch of what
your final learning switch code should look like.
Each time you change and save this file, make sure to restart POX, then use pings to verify the behavior
of the combination of switch and controller as a (1) hub, (2) controller-based Ethernet learning switch,
and (3) flow-accelerated learning switch. For (2) and (3), hosts that are not the destination for a ping
should display no tcpdump traffic after the initial broadcast ARP request.
To test your code: Make sure you have mininet running and then put ./pox.py log.level --DEBUG
misc.of_tutorial in the other terminal window. Once it’s connected, try a couple pings to see if the
switch is working. The bandwidth returned by iperf from a switch (Gbits) should be much faster than a
hub (Mbits).
Additionally, Pox has an api written by the ONOS project that is pretty useful. You can find it at
pox.onosproject.org.
Learning Python
Python:
is a dynamic, interpreted language. There is no separate compilation step - just update your code and
re-run it.
uses indentation rather than curly braces and semicolons to delimit code. Four spaces denote the body
of a for loop, for example.
is dynamically typed. There is no need to pre-declare variables and types are automatically managed.
has built-in hash tables, called dictionaries, and vectors, called lists.
is object-oriented and introspective. You can easily print the member variables and functions of an
object at runtime.
runs slower than native code because it is interpreted. Performance-critical controllers may want to
distribute processing to multiple nodes or switch to a more optimized language.
Common operations:
To initialize a dictionary:
mactable = {}
Page 25
mininet Openflow Tutorial
mactable[0x123] = 2
if 0x123 in mactable:
print 'element 2 is in mactable'
if 0x123 not in mactable:
print 'element 2 is not in mactable'
print dir(object)
The subsections below give details about POX APIs that should prove useful in the exercise. There is also other
documentation available in the appropriate section of POX's website.
When a connection to a switch starts, a ConnectionUp event is fired. The example code creates a new
Tutorial object that holds a reference to the associated Connection object. This can later be used to send
commands (OpenFlow messages) to the switch.
ofp_action_output class
This is an action for use with ofp_packet_out and ofp_flow_mod. It specifies a switch port that you wish
to send the packet out of. It can also take various "special" port numbers. An example of this would be
OFPP_FLOOD which sends the packet out all ports except the one the packet originally arrived on.
Example. Create an output action that would send packets to all ports:
Page 26
mininet Openflow Tutorial
ofp_match class
Objects of this class describe packet header fields and an input port to match on. All fields are optional -
- items that are not specified are "wildcards" and will match on anything.
The ofp_packet_out message instructs a switch to send a packet. The packet might be one constructed at
the controller, or it might be one that the switch received, buffered, and forwarded to the controller (and
is now referenced by a buffer_id).
buffer_id - The buffer_id of a buffer you wish to send. Do not set if you are sending a constructed
packet.
data - Raw bytes you wish the switch to send. Do not set if you are sending a buffered packet.
actions - A list of actions to apply (for this tutorial, this is just a single ofp_action_output action).
in_port - The port number this packet initially arrived on if you are sending by buffer_id, otherwise
OFPP_NONE.
This instructs a switch to install a flow table entry. Flow table entries match some fields of incoming
packets, and executes some list of actions on matching packets. The actions are the same as for
ofp_packet_out, mentioned above (and, again, for the tutorial all you need is the simple
ofp_action_output action). The match is described by an ofp_match object.
Page 27
mininet Openflow Tutorial
idle_timeout - Number of idle seconds before the flow entry is removed. Defaults to no idle timeout.
hard_timeout - Number of seconds before the flow entry is removed. Defaults to no timeout.
actions - A list of actions to perform on matching packets (e.g., ofp_action_output)
priority - When using non-exact (wildcarded) matches, this specifies the priority for overlapping
matches. Higher values are higher priority. Not important for exact or non-overlapping entries.
buffer_id - The buffer_id of a buffer to apply the actions to immediately. Leave unspecified for none.
in_port - If using a buffer_id, this is the associated input port.
match - An ofp_match object. By default, this matches everything, so you should probably set some of
its fields!
Example. Create a flow_mod that sends packets from port 3 out of port 4.
fm = of.ofp_flow_mod()
fm.match.in_port = 3
fm.actions.append(of.ofp_action_output(port = 4))
For more information about OpenFlow constants, see the main OpenFlow types/enums/structs file,
openflow.h, in ~/openflow/include/openflow/openflow.h You may also wish to consult POX's
OpenFlow library in pox/openflow/libopenflow_01.py and, of course, the OpenFlow 1.0 Specification.
The POX packet library is used to parse packets and make each protocol field available to Python. This
library can also be used to construct packets for sending.
pox/lib/packet/
For the first exercise, you'll only need to access the Ethernet source and destination fields. To extract the
source of a packet, use the dot notation:
packet.src
The Ethernet src and dst fields are stored as pox.lib.addresses.EthAddr objects. These can easily be
converted to their common string representation (str(addr) will return something like
"01:ea:be:02:05:01"), or created from their common string representation
(EthAddr("01:ea:be:02:05:01")).
print dir(packet)
Page 28
mininet Openflow Tutorial
Many fields are common to all Python objects and can be ignored, but this can be a quick way to avoid a
trip to a function's documentation.
of_tutorial.py Walkthrough
Now that you have a basic overview of some of the relevant ‘of’ classes and methods, here is a simple
overview of the tutorial and what you are trying to accomplish.
In the initializer (the _init_ method), the class’s instance variables are set accordingly and an empty
dictionary (on that will later consist of MAC Address keys to port number values) is created.
The first method you see, act_like_hub, describes the hub behavior, or sending received packets to all
ports, using the resend_packet. Look at the comments for these two methods for some more information
about what’s going on.
You will be writing the act_like_switch method in order to allow for learning switch behavior. The first
thing you have to do is learn the port for the source MAC, which essentially means to populate the
dictionary with the input packet’s source MAC Address and input port. Look at the Python tutorial
above to learn how to add/replace items in a dictionary. (Additional thought: Do you really need to
check if the key/value pair is already in there?). Furthermore, look at the corresponding fields for the
method’s parameters, packet and packet_in, as both have different fields. Setting a variable to equal the
corresponding port to the packet’s destination MAC Address here is recommended.
Then you should create a ofp_match object and if the packet’s destination port (the one you just found)
is not null, send the packet out to that port using resend_packet, and make a flow mod. Otherwise, send
the packet to all ports (“Flood” behavior) by using the port “of.OFPP_ALL”.
Creating an ofp_flow_mod is simple. Use the methods as described above and set the appropriate fields.
The fields you should set are match (using the created ofp_match object), idle-timeout and hard-timeout
(not necessary), and append a newly created ofp_action_output to the ‘actions’ field. Look at the
resend_packet method to see how an ofp_action_output is created.
Finally, send the flow mod out of the connection, similar again to the resend_packet method.
Page 29
mininet Openflow Tutorial
Beacon is very easily developed using the Eclipse Integrated Development Environment which runs on
any operating system (OS).
Therefore, for this tutorial you will you need to download Beacon and run Eclipse on your host
machine, rather than inside the Mininet virtual machine.
Prerequisites
Note: I you already have eclipse you need to get the PDE download, which you can by clicking on help->install
new software. Then under work with choose The Eclipse Project updates and check the box for Eclipse Plugin
Development Tools.
If you don’t have eclipse, when you download the newest version of eclipse make sure you download
the RCP + REP version.
Next, download the Beacon tutorial package for your host machine's operating system, the file names
begin with beacon-tutorial-eclipse:
Tutorial Packages
After the download is complete extract it to your desktop, or somewhere else that is convenient. For guide
purposes, the folder you extracted it to will be referred to by <path>/beacon-tutorial-1.0.2
Setup
Launch Eclipse by running the eclipse executable inside <path></path></beacon-tutorial-
1.0.2/eclipse/ (optional)></path>Create a new Eclipse workspace if you are not starting from a fresh Eclipse
install
File -> Switch Workspace -> Other, pick a new folder to host the workspace
Window (or Eclipse for MAC) -> Preferences -> Java -> Compiler then under JDK Compliance, change
Compiler compliance level to 1.6.
Page 30
mininet Openflow Tutorial
File -> Import -> General -> Existing Projects into Workspace, Select <path>/beacon-tutorial-
1.0.2/beacon-tutorial-1.0.2/src as the root directory, click ok, then select all the projects, ensure copy
projects into workspace is not checked and click finish.
Note at this point you will see many Java errors, the libraries Beacon depends on will be installed in the next
step which will resolve the errors, do not panic!
Open the Beacon Main Target project, double click the main-local.target file.
Click Set as Target Platform in the top right corner of the main.target window. (Note if you click before it
has been resolved, you will receive an error). Wait a few seconds, at this point all compilation errors
should be gone.
Click Window -> Preferences. Then in the left column click Java -> Code Style -> Formatter, then click the
Import button, and select <path></path></beacon-tutorial-1.0.2/src/beacon-
1.0.2/beacon_style_settings.xml></path>and hit ok, then ensure the Active profile is Beacon.
Back in your VM, We're not going to be using the reference controller anymore, which is running in the
background (do 'ps -A | grep controller' if you're unsure).
The switches are all trying to connect to a controller, and will increase the period of their attempts to
contact the controller, up to a maximum of 15 seconds. Since the OpenFlow switch has not connected
yet, this delay may be anything between 0 and 15 seconds. If this is too long to wait, the switch can be
configured to wait no more than N seconds using the --max-backoff parameter.
Make sure the reference controller used before is not running: $ sudo killall controller
You will need to tell the Mininet virtual switches to connect to your host machine's IP address. To get
that, from your Mininet ssh window run the command sudo route:
openflow@openflowtutorial:~$ sudo route Kernel IP routing table Destination Gateway Genmask Flags
Metric Ref Use Iface 192.168.206.0 * 255.255.255.0 U 0 0 0 eth0 default 192.168.206.2 0.0.0.0 UG 0 0
0 eth0
Look for the line that starts with default, and typically your host's IP address will be the IP in the
Gateway column. If that IP address ends with .1, and later you are unable to connect Mininet to Beacon,
try the same IP but swapping the ending .1 with .2.
Page 31
mininet Openflow Tutorial
You should also restart Mininet to make sure that everything is "clean". From your Mininet console:
mininet> exit $ sudo mn --topo single,3 --mac --switch ovsk --controller
remote,ip=<your_host_ip></your_host_ip>
Make sure you do not add extra spaces around the comma.
Note: The above syntax is for Mininet 2.0 - for Mininet 1.0, use the following syntax instead: $ sudo mn
--topo single,3 --mac --switch ovsk --controller remote --ip <your_host_ip>
The ip parameter defines in which IP your controller is located. Note that this is the IP your host uses to
communicate with the VM, as discussed above. In my case, the VM's IP is 192.168.206.4 and the host's
IP is 192.168.206.2 . Thus, I started mininet using $ sudo mn --topo single,3 --mac --switch ovsk --
controller remote,ip=192.168.206.2
This command will start Beacon, including the 'tutorial' bundle, listening to incoming connection from switches
on the standard OpenFlow port (6633).
Wait until the application indicates that the OpenFlow switch has connected. When the switch connects,
your Eclipse console should print something like this:
Now we verify that hosts can ping each other, and that all hosts see the exact same traffic - the behavior
of a hub. To do this, we'll create xterms for each host, and view the traffic in each. In the Mininet
console, start up three xterms: mininet> xterm h1 h2 h3
Note: the xterm command does not work and will through an error if you try to call it from the virtual
box directly, instead use another terminal window to call xterm.
Arrange each xterm so that they're all on the screen at once. This may require reducing the height of to
fit a cramped laptop screen.
In the xterms for h2 and h3, run tcpdump, a utility to print the packets seen by a host: # tcpdump -XX -n
-i h2-eth0
Page 32
mininet Openflow Tutorial
The ping packets are now going up to the controller, which then floods them out all interfaces except the
sending one. You should see identical ARP and ICMP packets corresponding to the ping in both xterms
running tcpdump.
Now, see what happens when a non-existent host doesn't reply. From h1 xterm: # ping -c1 10.0.0.5
You should see three unanswered ARP requests in the tcpdump xterms. If your code is off later, three
unanswered ARP requests is a signal that you might be accidentally dropping packets.
Here, you'll benchmark the provided hub code, part of the Tutorial bundle.
First, verify reachability. Mininet should be running, along with your Beacon tutorial controller. In the
Mininet console, run: mininet> pingall
This is just a sanity check for connectivity. Now, in the Mininet console, run: mininet> iperf
Now, compare your number with the reference controller you saw before. How does that compare?
Go to Eclipse and stop Beacon (you should see a square, red button in the console window, or the top
left section of Eclipse if you are in the Debug perspective).
NOTE : You can run only one controller at the same time (otherwise you'll get a port conflict).
Make sure that you stop any running instance of Beacon before you start another one. With
Eclipse this might be tricky. To check the running programs open the Debug perspective
(Window->Open Perspective->Debug). On the top-left corner you can see the running programs,
click on it then hit the red square to terminate the redundant ones...
Take a quick look through the file, the key things to notice:
Page 33
mininet Openflow Tutorial
The receive method is where packets initially arrive from switches, by default this method calls
forwardAsHub. Once you have implemented the code in forwardAsLearningSwitch you should change
receive by commenting out the call to forwardAsHub, and uncommenting the call to
forwardAsLearningSwitch.
The forwardAsHub method behaves as a broadcast hub, and has code that gives you an example of how
to send an OFPacketOut message.
The forwardAsLearningSwitch method is where you will be writing all of your code (with the exception
of the receive method mentioned earlier). It should take you around 30 lines of code in this method to
implement a learning switch.
Wireshark will be very useful to you in getting your code working. Try starting Beacon and doing some pings with
Mininet while capturing with Wireshark. You should see OFPacketIn and OFPacketOut messages, and if you
explore the OFPacketOut messages you should see their action is to flood.
Each time you change and save the LearningSwitchTutorial file, make sure to stop and start your
running instance, then use pings to verify hub or Ethernet learning switch behavior. Hosts that are not
the destination should display no tcpdump traffic after the initial broadcast ARP request.
There is a significant number of comments in the LearningSwitchTutorial file to help you create the
proper functionality, and tips provided in the subsequent sections of this tutorial (read these!). At a high
level there are two phases of work for you to do.
Phase 1
At the end of this phase you should be able to send pings back and forth, and in Wireshark you should see an
initial OFPacketOut in both directions with its action set to flood, subsequent OFPacketOut messages should
have their action set to send to a single port.
Phase 2
If the destination port is known, instead of sending an OFPacketOut, send an OFFlowMod so that
subsequent pings are matched on the switch.
At the end of phase 2, when pinging and viewing the controller traffic in Wireshark you should see an initial
OFPacketOut that floods for the request/response, then an OFFlowMod being sent for both request/response,
then no further traffic for the same ping.
Remember that running this is exactly as you did above. You go to Run - Debug Configurations ->
OSGi Framework -> beacon tutorial LearningSwitch and then choose Debug to actually start the
controller. Then from terminal send out a couple pings or check the bandwidth by using iperf.
Page 34
mininet Openflow Tutorial
Here are a few Java tips you might find useful down the road.
You can change the logging level using info or error instead of debug.
The subsections below give details about a few Beacon Classes that should prove useful in the exercise.
In your beacon-tutorial-1.0.2 directory, there is an apidocs folder which contains Javadoc documentation
for all essential classes in this assignment. Open your browser and point to
<your></your></apidocs/index.html></your_host_ip>and look for the classes
mentioned below, which should help while implementing your code.
To send a message to an OpenFlow switch, look at IOFSwitch class. The starter forward_as_hub
function sends packets out using: sw.getOutputStream().write(po);
Look at OFMatch and OFPacketIn to get header information from an OpenFlow packet-in. You should
find the following command particularly useful: match.loadFromPacket(pi.getPacketData(),
pi.getInPort());
Down the road, you may want to print a mac address, or use it as a key to a HashMap. OFMatch will
give you the address as a byte array. Use the functions/classes below in case needed:
HexString.toHexString(byte[] bytes) // Convert a string of bytes to a ':' separated hex string Long
mac_address_key = Ethernet.toLong(byte array); // Creates a Long key from a byte array.
Finally, at some point you will have to install a flow in the network. Use OFFlowMod and
OFActionOutput to do that. Here is a way to initialize a flow-mod message for a specific switch:
OFFlowMod fm = new OFFlowMod();
Use the appropriate setters to construct the flow-mod you need. Assuming you know the outgoing port
for this flow, this is a snippet on how to include this in your flow-mod message: OFActionOutput action
= new OFActionOutput(outPort); fm.setActions(Collections.singletonList((OFAction)action));
Page 35
mininet Openflow Tutorial
Install Prerequisites
Note: these instructions are a customized version of those on the Floodlight Download page
Make sure that you have Internet access: ping -c1 www.stanford.edu
If not, ensure that each ethX interface on your VM has an IP assigned via DHCP: ifconfig -a
Run for each interface without an IP assigned, replacing ethX as necessary: sudo dhclient ethX
Install prereqs: time sudo apt-get install build-essential default-jdk ant python-dev
Getting Started
While the dependencies are installing on your VM, follow the Floodlight Getting Started instructions.
Developing
Once through with the getting started part, work through Developing on Floodlight.
Install Prerequisites
Make sure that you have Internet access: ping -c1 www.stanford.edu
If not, ensure that each ethX interface on your VM has an IP assigned via DHCP: ifconfig -a
Run for each interface without an IP assigned, replacing ethX as necessary: sudo dhclient ethX
Page 36
mininet Openflow Tutorial
Getting Started
Follow the instructions on the main Trema page, which has links to tutorial videos and more.
Ryu VM Image
This can be import into virtualbox, VMWare or other popular virtualization programs.
Important: For this VM image, the user name is 'ryu' with password 'ryu'.
Supplement on VM Setup
If you have troubles to connect into guest with ssh, please try
Add host-only network (If your virtual box is not so-new, the host-only network is already created by
default. In that case, skip to the next step) file menu/Preferences/Network and "Add host-only network"
button with default settings.
select your VM and go to the Setting Tab. Go to Network->Adapter 2. Select the "Enable Adapter" box
and attach it to "host-only network" which was created at the step 1.
Install Prerequisites
You will need the following installed in your environment that runs Ryu
python-gevent>=0.13
python-routes
python-webob
python-paramiko
If not, ensure that each ethX interface on your VM has an IP assigned via DHCP: ifconfig -a
Run for each interface without an IP assigned, replacing ethX as necessary: sudo dhclient ethX
Page 37
mininet Openflow Tutorial
install prereqs: time sudo apt-get install python-gevent python-routes python-webob python-paramiko
One option for the first exercise is to use NOX, a controller platform that allows you to write a controller
on top, in Python, C++, or some combination of the two. From noxrepo.org:
NOX is an open-source platform that simplifies the creation of software for controlling or monitoring networks.
Programs written within NOX (using either C++ or Python) have flow-level control of the network. This means
that they can determine which flows are allowed on the network and the path they take.
If NOX classic is not already installed in your Mininet 2.0 VM, you can install it by typing cd ~
mininet/util/install.sh -x
This may take some time (20 minutes), so it is recommended that you do this in advance if you are
planning to use NOX classic. The older Mininet 1.0 VM includes NOX classic.
We're not going to be using the reference controller anymore, which is running in the background (do 'ps
-A | grep controller' if you're unsure).
Make sure the reference controller used before is not running, so that NOX can use port 6633. Press
Ctrl-C in the window running the controller program, or in the other SSH window run: $ sudo killall
controller
You should also run sudo mn -c and restart Mininet to make sure that everything is "clean" and using
the faster kernel switch. From your Mininet console: mininet> exit $ sudo mn -c $ sudo mn --topo
single,3 --mac --switch ovsk --controller remote
NOTE: The following usage instructions conforms perfectly with NOX Classic (bundled with
Mininet 1.0 VM). However, there may be some minor variations with other versions.
Go to the directory holding the built NOX executable (~/noxcore/build/src) in the other SSH window: $
cd ~/nox/build/src
Page 38
mininet Openflow Tutorial
Then, in the same window, start the base Python hub code: $ ./nox_core -v -i ptcp: pytutorial
This command told NOX to start the 'tutorial' application, to print verbose debug information, and to
passively listen for new switch connections on the standard OpenFlow port (6633).
The switches may take a little bit of time to connect. When an OpenFlow switch loses its connection to a
controller, it will generally increase the period between which it attempts to contact the controller, up to
a maximum of 15 seconds. Since the OpenFlow switch has not connected yet, this delay may be
anything between 0 and 15 seconds. If this is too long to wait, the switch can be configured to wait no
more than N seconds using the --max-backoff parameter. Alternately, you exit Mininet to remove the
switch(es), start the controller, and then start Mininet to immediately connect.
Wait until the application indicates that the OpenFlow switch has connected. When the switch connects,
NOX will print something like this: 00039|nox|DBG:Registering switch with DPID = 1
If you see the switch print out a message like "sent error in response to capability reply, assuming no
management support", this is OK. Open vSwitch has custom extensions to support a management
database, but we're not enabling them on our OpenFlow switch.
Now we verify that hosts can ping each other, and that all hosts see the exact same traffic - the behavior
of a hub. To do this, we'll create xterms for each host and view the traffic in each. In the Mininet
console, start up three xterms: mininet> xterm h1 h2 h3
Arrange each xterm so that they're all on the screen at once. This may require reducing the height of to
fit a cramped laptop screen.
In the xterms for h2 and h3, run tcpdump, a utility to print the packets seen by a host: # tcpdump -XX -n
-i h2-eth0
The ping packets are now going up to the controller, which then floods them out all interfaces except the
sending one. You should see identical ARP and ICMP packets corresponding to the ping in both xterms
running tcpdump. This is how a hub works; it sends all packets to every port on the network.
Now, see what happens when a non-existent host doesn't reply. From h2 xterm: # ping -c1 10.0.0.5
You should see three unanswered ARP requests in the tcpdump xterms. If your code is off later, three
unanswered ARP requests is a signal that you might be accidentally dropping packets.
Page 39
mininet Openflow Tutorial
First, verify reachability. Mininet should be running, along with the NOX tutorial in a second window.
In the Mininet console, run: mininet> pingall
This is just a sanity check for connectivity. Now, in the Mininet console, run: mininet> iperf
Now, compare your number with the reference controller you saw before. How does that compare?
Go to your SSH terminal and stop the NOX hub controller using Ctrl-C. The file you'll modify is
~/nox/src/nox/coreapps/tutorial/pytutorial.py. Open this file in your favorite editor.
Most of the code will go in one function, learn_and_forward(). There isn't much code here, yet it's
sufficient to make a complete hub and serve as an example of a minimal NOX app. You'll need to add
roughly 10 lines to make a learning switch.
Each time you change and save this file, make sure to restart NOX, then use pings to verify the behavior
of the combination of switch and controller as a (1) hub, (2) controller-based Ethernet learning switch,
and (3) flow-accelerated learning switch. For (2) and (3), hosts that are not the destination for a ping
should display no tcpdump traffic after the initial broadcast ARP request.
Learning Python
Python:
is a dynamic, interpreted language. There is no separate compilation step - just update your code and
re-run it.
uses indentation rather than curly braces and semicolons to delimit code. Four spaces denote the body
of a for loop, for example.
is dynamically typed. There is no need to pre-declare variables and types are automatically managed.
has built-in hash tables, called dictionaries, and vectors, called lists.
is object-oriented and introspective. You can easily print the member variables and functions of an
object at runtime.
runs slower than native code because it is interpreted. Performance-critical controllers may want to
distribute processing to multiple nodes or switch to a more optimized language.
Common operations:
Page 40
mininet Openflow Tutorial
The subsections below give details about NOX APIs that should prove useful in the exercise.
NOX API documentation can be found here. Please look there for the appropriate calls. We also list a
few functions here, that will be useful for your first steps into NOX.
These functions, part of the core NOX API, are defined in /home/openflow/nox/src/nox/lib/core.py. To
save the need to look through this source code, the relevant documentation is below:
send_openflow( ... )
dp_id - datapath to send packet to buffer_id - id of buffer to send out packet - data to put in openflow
packet actions - list of actions or dp port to send out of inport - dp port to mark as source (defaults to
Controller port) """
Here's an example use, from the pytutorial.py starter code: self.send_openflow(dpid, bufid, buf,
openflow.OFPP_FLOOD, inport)
This code floods a packet cached at the switch (with the given bufid) out all ports but the input port.
Replace openflow.OFPP_FLOOD with a port number to send a packet packet out a specific port,
unmodified.
Page 41
mininet Openflow Tutorial
install_datapath_flow( .... )
actions - a list where each entry is a two-element list representing an action. Elem 0 of an action list
should be an ofp_action_type and elem 1 should be the action argument (if needed). For
OFPAT_OUTPUT, this should be another two-element list with max_len as the first elem, and port_no
as the second
buffer_id - the ID of the buffer to apply the action(s) to as well. Defaults to None if the actions should
not be applied to a buffer
priority - when wildcards are present, this value determines the order in which rules are matched in the
switch (higher values take precedence over lower ones)
packet - If buffer_id is None, then a data packet to which the actions should be applied, or None if none.
inport - When packet is sent, the port on which packet came in as input, so that it can be omitted from
any OFPP_FLOOD outputs. """
Note that install_datapath_flow() takes in an attributes dictionary with parts of the OpenFlow match.
Here's an example: attrs = {} attrs[core.IN_PORT] = inport attrs[core.DL_DST] = packet.dst
You will want to use exactly this action list for the tutorial. The format is a list of actions; we've defined
one action, which forwards to a single port (OFPAT = OpenFlow Action Type: Output). The [0,] part
that follows is the set of parameters for the output action type: 0 is max_len, which is only defined for
packets forwarded to the controller (ignore this), while the outport param specifies the output port.
The priority shouldn't matter, unless you have overlapping entries. For example, the priority field could
be: openflow.OFP_DEFAULT_PRIORITY
For more details on the format, see the NOX core Python API code in src/nox/core.py.
Page 42
mininet Openflow Tutorial
For more information about OpenFlow constants, see the main OpenFlow types/enums/structs file,
openflow.h, in ~/openflow/include/openflow/openflow.h
The NOX packet parsing libraries are automatically called to parse a packet and make each protocol
field available to Python.
For the first exercise, you'll only need to access the Ethernet source and destination fields. To extract the
source of a packet, use the dot notation: packet.src
The Ethernet src and dst fields are stored as arrays, so you'll probably want to to use the mac_to_str()
function or mac_to_int. I suggest mac_to_str, and it avoids the need to do any hex conversion when
printing. The mac_to_str() function is already imported, and comes from packet_utils in
~/nox/src/nox/lib/packet/packet_utils.py
To see all members of a parsed packet object: print dir(packet) Here's what you'd see for an ARP packet:
['ARP_TYPE',] Many fields are common to all Python objects and can be ignored, but this can be a
quick way to avoid a trip to a function's documentation.
Once the switch no longer has hub behavior, work to push down a flow when the source and destination
ports are known. You can use ovs-ofctl to verify the flow counters, and if subsequent pings complete
much faster, you'll know that they're not passing through the controller. You can also verify this
behavior by running iperf in Mininet and checking that no OpenFlow packet-in messages are getting
sent. The reported iperf bandwidth should be much higher as well, and should match the number you got
when using the reference learning switch controller earlier.
Page 43
mininet Openflow Tutorial
If you are working with POX, your code should already be able to pass the following tests because it
creates one instance per switch and each instance maintains its own MAC table. Otherwise, your
controller so far may have probably only supported a single switch, with a single MAC table. In this
section, you'll extend it to support multiple switches.
Start mininet with a different topology. In the Mininet console: mininet> exit $ sudo mn --topo linear --
switch ovsk --controller remote
If you are using Beacon and Mininet 2.0, use the ip= option: mininet> exit $ sudo mn --topo linear --
switch ovsk --controller remote,ip=<your_host_ip></your_host_ip>
If you are using Beacon and Mininet 1.0, use the --ip option: mininet> exit $ sudo mn --topo linear --
switch ovsk --controller remote --ip <your_host_ip></your_host_ip>
Note: for Mininet 2.0, the hosts are h1/10.1 and h2/10.2
This will create a 2-switch topology where each switch has a single connected host.
Now, modify your switch so that it stores a MAC-to-port table for each DPID. This strategy only works
on spanning tree networks, and the delay for setting up new paths between far-away hosts is
proportional to the number of switches between them. Other modules could act smarter. For example,
one can maintain an all-pairs shortest path data structure and immediately push down all flow entries
needed to previously-seen sources and destinations. This is out-of-scope for this assignment.
After the mods, to verify that your controller works, in the Mininet console, run: mininet> pingall
Page 44
mininet Openflow Tutorial
In this exercise you'll use the code you have so far to control a slice of a real network consisting of 3
OpenFlow switches, a server and a wireless client. Your goal is to access a website and post a message.
The interesting part is that your controller should allow traffic to go from client to server and vice versa.
The setup includes:
Ideally, you shouldn't write any code for this experiment. You will have to form teams though. When you are
ready to start, ask the instructors to put you in a team.
Table of Contents
o Setting up your Network
Page 45
mininet Openflow Tutorial
mininet> exit
1. The control network which will allow your controller to talk with the FlowVisor and OpenFlow switches
(192.168.10. subnet).
2. The actual network we want to control, i.e. your wireless client to access the Web Server (10.0.0.
subnet).
Ask the instructor for an ethernet cable. This will go to a standard (non-OpenFlow) switch and connects
to the FlowVisor.
At your local machine, configure the interface where you plugged your ethernet cable with the following
characteristics:
For MAC
For Windows
Page 46
mininet Openflow Tutorial
Now your local machine can access FlowVisor. To verify, ping FlowVisor from a terminal on your local
machine:
ping 192.168.10.1
But what we really need is the guest VM - where the controller is - to be able to communicate with the
FlowVisor. We will use port-forwarding to do that.
First, note the IP address of your VM guest. At your VM's shell, type:
$ ifconfig eth1
where <guestip></guestip> is the IP address of the eth1 interface of the VM, and X is 100 + your team
number.
Windows users
To enable port forwarding on the Putty, please enter the appropriate fields during connection setup
Page 47
mininet Openflow Tutorial
Verify reachability
To verify that everything worked, use tcpdump at your guest VM and see whether you receive any
incoming OpenFlow-related packets
Note: The reason we specify the interface 'lo' not 'eth1' here is that SSH port forwarding arrives to the
interface eth1 tcp port 22 and forwarded to the local interface 'lo' tcp port 6633.
Due to reconnection backoff, it might take up to one minute before you see any packets coming in. If
you don't get any packets after 1 minute, ask one of the instructors for help.
You will have to configure your wireless client's network interface. First login to the wireless network
with SSID "OpenFlow-Tutorial". Depending on your OS use ControlPanel/ifconfig or any other similar
utility :
For Linux:
Page 48
mininet Openflow Tutorial
For Mac:
Write down your wireless card MAC address. We'll use this shortly.
FlowVisor Configuration
Several teams will be using the same switches at the same time, so we have to virtualize our network
and give each team a separate slice. Each controller will have a limited view of the network, as this is
dictated by its slice configuration. In this exercise, each team will control all the traffic that comes from
and goes to its wireless client. To do that we will need the MAC address of your team's wireless client.
Hopefully you already have this from the previous step. Give this MAC address to the instructor to
update your slice configuration at the FlowVisor.
Note that 192.168.10.101:6633 points to this slice's OF controller, 00:22:41:66:13:1c is the MAC
address of the wireless client, and every packet with that ethernet_src or ethernet_dst is assigned to this
controller.
$ cd ~/noxcore/build/src/
$ ./nox_core -i ptcp: -v pytutorial
What do you see? Are there any switches connecting to your controller? Use your debug messages or
wireshark for that.
Page 49
mininet Openflow Tutorial
$ ping 10.0.0.1
Does it work now? How packets travel from client to the server? Check the switch flow-tables using
dpctl.
If ping works, you are ready to go to the final step. Fire your browser and go to http://10.0.0.1:8000
Write and post a short message and make sure you fill your team's number.
Page 50
mininet Openflow Tutorial
Router Exercise
In this exercise, you'll make a static layer-3 forwarder/switch. It's not exactly a router, because it won't
decrement the IP TTL and recompute the checksum at each hop (so traceroute won't work). Actions to
do TTL and checksum modification are expected in the upcoming OpenFlow version 1.1. However, it
will match on masked IP prefix ranges, just like a real router.
An IP router can be distinguished from other sorts of packet switching devices in that a router examines
the IP protocol header as part of the switching process. It generally removes the Link Layer header a
message was received with, modifies the IP header, and replaces the Link Layer header for
retransmission.
To simplify the exercise, your "router" will be completely static. With no BGP or OSPF, you'll have no
need to send or receive route table updates.
Each network node will have a configured subnet. If a packet is destined for a host within that subnet,
the node acts as a switch and forwards the packet with no changes, to a known port or broadcast, just
like in the previous exercise. If a packet is destined for some IP address for which the router knows the
next hop, it should modify the layer-2 destination and forward the packet to the correct port.
Our hope is that this exercise will show that with an OpenFlow-enabled forwarding device, the network
is effectively layerless; you can mix switch, router, and higher-layer functionality.
Table of Contents
o Create Topology
o Set up hosts
o ARP
o Static Routing
o ICMP
o Testing your router
o Flow Mods
o Next Step
Create Topology
You'll need a slightly different topology, something like this: Note: For Mininet 2.0, the hosts have
been renumbered h1-h3 and 10.1-10.3.
Page 51
mininet Openflow Tutorial
~/mininet/custom/topo-2sw-2host.py
$ cp ~/mininet/custom/topo-2sw-2host.py mytopo.py
To run a custom topology, pass Mininet the custom file and pass in the custom topology:
mininet> pingall
Now, modify your topology file to match the picture and verify full host connectivity with pingall in the
Mininet console.
Set up hosts
Set up IP configuration on each virtual host to force each one to send to the gateway for destination IPs
that are outside of their configured subnet.
Page 52
mininet Openflow Tutorial
You'll need to configure each host with a subnet, IP, gateway, and netmask.
It may seem obvious, but we will warn you anyway: do not attempt to assign IP addresses to the
interfaces belonging to switches s1 and s2. If you need to handle traffic "to" or "from" a switch, do so
using OpenFlow.
We can do this directly from the custom topology that you created with mininet. Edit your "mytopo.py"
to include the information above.
Helpful Code:
ARP
A router generally has to respond to ARP requests. You will see ethernet broadcasts which will (initially
at least) be forwarded to the controller.
Your controller should construct ARP replies and forward them out the appropriate ports.
* arp cache
* routing table (create a structure with all of the information statically
assigned)
* ip to port dictionary
* message queue (while the router waits for an ARP reply)
(ip with network prefix, ip of host, interface name, interface address, switch port)
NOTE: the port number does not correspond to the switch name. This is not a typo but a known
mininet bug.
You will need to send a MAC address back to the host that is arping for you. It does not matter what this
address is, so feel free to make up your own!
Helpful information about packet structure: NOTE: The following information is specific to the POX
Controller
Page 53
mininet Openflow Tutorial
protocol = packet.payload strips the ethernet header and contains the ipv4 or arp packet
packet.payload.payload strips the protocol header and contains the underlying packet(ICMP?)
packet.payload.payload.payload strips the ICMP header and contains the echo or unreach packet,
assuming this is an ICMP packet
...etc
Static Routing
Once ARP has been handled, you will need to handle routing for the static configuration. Since we know
what is connected to each port, we can match on IP address (or prefix, in the case of the remote subnet)
and forward out the appropriate port.
We need to handle all ipv4 traffic that comes through the router by forwarding it to the correct subnet.
The only change in the packet should be the source and destination MAC addresses.
If the router does not know the MAC address of the destination, it will have to arp for that host.
ICMP
Additionally, your controller may receive ICMP echo (ping) requests for the router, which it should
respond to.
Lastly, packets for unreachable subnets should be responded to with ICMP network unreachable
messages.
NOTE: the controller only accepts 128 byte packet_ins by default. If your messages are getting
truncated, this could be why. As a workaround, add another component at the end of your call too
the controller. it should look like this:
Page 54
mininet Openflow Tutorial
attempts to send from 10.0.1.2 to an unknown address range like 10.99.0.1 should yield an ICMP
destination unreachable message.
packets sent to hosts on a known address range should have their MAC dst field changed to that
of the next-hop router.
the router should be pingable, and should generate an ICMP echo reply in response to an ICMP
echo request.
Now run iperf to test tcp and udp traffic. In mininet, open up xterm in host 1 and host 3 with
mininet>xterm h1 h3
host 3 will be the iperf server, so in it's own terminal run the command
$ iperf -s
host 1 will be the client, so in it's own terminal run the command
you may also test udp traffic by adding a -u option to the end of both commands
Note the results for this test. In your code's current state, the router sends all of the traffic to the
controller via packet_ins, which makes a routing decision and sends a packet_out to the router. The next
step is to install flow mods, which should yield better performance with iperf.
Flow Mods
Flow mods should be relatively easy to install. There are a few important structures to consider when
creating the flow mod:
of.ofp_flow_mod() ==> the packet that will eventually be sent to the router to add a flow entry
of.ofp_match() ==> the structure containing the criteria for a packet to be matched on
of.ofp_action_output(port = [port]) ==> action to be performed on matching packets. This action
specifies a port to output the packet to
of.ofp_action_dl_addr.set_src([hwsrc]) ==> action to change the ethernet packet's hardware
source address
There are many other actions that may be performed on matching packets. See the open flow spec 1.0
for more information
Page 55
mininet Openflow Tutorial
Now that you have flow mods installed, run the iperf tests again and notice the performance difference
The exercise is meant to give more practice with packet parsing and show how to use OpenFlow to
modify packets.
Page 56
mininet Openflow Tutorial
Advanced Topology
The instructions are the same for this exercise as the last one. The only difference is the topology, which
includes two routers controlling different subnets.
This is an advanced exercise, and most implementation details will be left to you.
Topology
You'll need a slightly different topology, something like this:
Modify your topology file to match the picture and verify full host connectivity with pingall in the
Mininet console.
This is just one idea for a more advanced topology. Feel free to adjust this exercise in any way you
would like. The rest is up to you, so have fun!
Page 57
mininet Openflow Tutorial
Create Firewall
In this exercise, you'll modify your switch to reject connection attempts to specific ports, just like a
firewall.
This exercise is meant to show how OpenFlow can even do basic layer-4 tasks. Other uses could even
extend into layer 7; cookie-based load balancing, for example.
$ iperf -s
$ iperf -c 10.0.0.2
Your task is to prevent this from happening, and to block all flow entries with this particular port.
You can change the port used by iperf with the -p option. Both server and client will need this option
specified. Again, NOX core.py will be useful for figuring out how to specify a flow entry that matches
on wildcard ports. Also note that an empty action list will drop a packet; there's no explicit drop action.
Page 58
mininet Openflow Tutorial
If you have VMware installed, you may find that it is advantageous to run the VM under VMware rather
than VirtualBox.
For VMware Player on Windows, use the "Export Appliance..." menu command from inside
VirtualBox. Make sure you select the "Write Manifest file" option. This will create a .ova virtual
machine archive which can be imported into VMware.
To import the .ova into VMware Player on Windows, open it using the "Open..." menu command.
For VMware Fusion on the Mac, it's slightly more complicated, but not terribly so. Use the "Export
Appliance..." menu command from inside VirtualBox, making sure to save an .ovf (and .vmdk) file by
pressing "Choose..." and selecting "Open Virtualization Format (*.ovf)" from the "Files of type:" pop-up
menu. This will create a .ovf file, which you can ignore (or import using VMware's ovf tool if you have
it installed), and a .vmdk disk image, which is exactly what you need.
(If you create an .ova file by mistake, you can either try again or rename the .ova file to a .tar file and
extract it to get the .vmdk image.)
Next, create a new VM in VMware Fusion, delete its default hard disk (if any), and add a new hard disk,
specifying the .vmdk file as the existing disk image to use. Once the VM has a single hard drive
specified as the .vmdk file, it should be able to boot and run.
For VMware player on Ubuntu, you should be able to use the above approach that works for
Windows, but I haven't tested it yet.
Alternately, you can create a .vmdk image from the .vdi file by using qemu-img from the qemu package;
for example:
Page 59
mininet Openflow Tutorial
You can then attach it to a new VM as described in the VMware Fusion instructions.
Start it with the flag -sb 500 to store 500 lines of output, e.g.
then use a scroll wheel, trackpad scrolling, or the middle mouse button to scroll with the quaint Athena
scroll widget (i.e. grey bar on the left side of the window.)
If you want a more advanced terminal, you might wish to try installing gnome-terminal, e.g.
You may not be able to connect to a VirtualBox VM that only has NAT networking enabled. Make sure
that you have followed the instructions above and configured host-only networking on at least one
interface in the VM settings, and make sure that the host-only interface is configured and that you are
connecting to its correct IP address.
If this does not work, or for more advanced setup, see below.
This probably means that you have not successfully connected to the VM with ssh and X11 forwarding
enabled.
Make sure that you have carefully followed our instructions. If you are on Windows, make sure that:
Page 60
mininet Openflow Tutorial
You have verified that you can ssh into the Mininet VM (using ssh -X from Terminal) and start up an
xterm
===> If you cannot start up an xterm, you will not be able to run wireshark!!!
Page 61
mininet Openflow Tutorial
Resources
Table of Contents
o Resources
Mininet
Controllers
POX
NOX
Ryu
Floodlight
Trema
Beacon
OpenFlow
Resources
Mininet
Mininet Website
Mininet Wiki
Controllers
POX
Source Code
Wiki
SDN Hub Pox Tutorial
Pox Versions/Download Page
NOX
Source Code
Official Nox Documentation
Ryu
Source Code
Ryu Wiki
Ryu Official Website
Read The Docs Tutorial
Page 62
mininet Openflow Tutorial
Floodlight
Source Code
Official Website
Official Documentation
Trema
Source Code
Documentation
Website
Beacon
Source Code
Web Site
OpenFlow
Page 63