Homework 9: Custom Routing Algorithms in an SDN Controller
This assignment is optional and is due at 11:59 pm on Wednesday, May 06.**
You can access the homework starter code here.
In this homework, you will implement a few different routing algorithms within an SDN Controller. To do this, you will use the OpenFlow Protocol, the Ryu SDN Framework, and the Mininet Network Emulator.
The rest of this assignment description is organized into the following sections:
- Environment Setup
- OpenFlow Overview
- Ryu SDN Controller Overview
- Skeleton Code
- Program Requirements (Programming Tasks)
- Testing
- Grading
Environmental Setup
To write a simple SDN Controller, we are going to the using the Ryu SDN Controller. To simplify things, it is recommend that you use a [pre-built VM][vm] that already has both Ryu and Mininet installed. However, it is also possible to install both of these programs locally, if you would like. The rest of this section describes both approaches. However, the provided code is written for the versions of Ryu and Mininet that are installed on the VM. If you use more recent versions of Ryu or Mininet that you install yourself, you may have to forward port the provided code.
Installing Either a VM or Packages
VM for Ryu/Mininet
Ryu provides [pre-built VMs][vm] that make it simple to get started. If you have never used a VM before, it is recommended that you install and use the VirtualBox Virtual Machine Monitor (VMM/Hypervisor).
Note: The following two pages from the mininet wiki may also be helpful:
After installing VirtualBox, you will need to download the Ryu VM for
the OpenFlow Tutorial. It is recommended that you download
OpenFlow_Tutorial_Ryu3.6.ova.
After downloading the ova
file, you will need to import it into
VirtualBox and start it:
File
->Import Appliance...
-> SelectFile:
->Next
-> Change settings if you want ->Import
- From there, you should select the VM and press “Start” to run the VM.
Once the VM is running, you can use its terminal directly and do not need any more environmental configuration. However, it is highly recommended to set up the VM’s network configuration so that you can SSH into the VM. This is because having two or more terminals open and using X11 forwarding with Mininet is helpful. To do this, you need to also set up port forwarding for the VM.
- Right-click the VM -> “Settings” -> Network -> Advanced -> Port
Forwarding -> Add new rule
- Name: SSH, Protocol: TCP, Host IP: 127.0.0.1, Host Port 2222, Guest IP: “” (Blank), Guest Port: 22.
ssh -X -p 2222 ryu@127.0.0.1
will now enable you to SSH into the guest.
Installing packages Locally
Installing Ryu Locally
You can install Ryu locally with:
pip install ryu
Installing Mininet Locally
If you are on a Debian/Ubuntu based Linux distro, installing Mininet is easy:
sudo apt install mininet
For other platforms, see the Mininet install instructions from the official Mininet website.
Verifying the Installation and Learning Mininet
To verify that everything is working, you will be following the Ryu Tutorial. For reference, some key commands will be included below. Also, note that the Ryu Tutorial is based on a much more in-depth Mininet Tutorial. Additionally, this tutorial is based on another OpenFlow tutorial (Archived here and here) created by Brandon Heller and Yiannis Yiakoumis and beta-tested by Bob Lantz, KK Yap and Masayoshi Kobayashi.
Kill any old controllers
sudo killall controller
Note that you will likely want to have two open SSH connections to your VM so that you can run Mininet in a separate window (tab) than starting your controller application. To quit Mininet, run:
mininet> exit
Run Mininet as follows to clean any old instances of Mininet that may be running and to start a simple topology with a single switch and three hosts:
sudo mn -c # Cleanup (remove old topologies)
sudo mn --topo single,3 --mac --switch ovsk --controller remote
Note that your controller will be run on localhost:6633
Now, run Ryu’s example simple_switch.py
program:
cd ~/ryu/
PYTHONPATH=. ./bin/ryu-manager --verbose ryu/app/simple_switch.py
Finally, verify that everything is working as expected by running the following command within Mininet:
mininet> pingall
Further, you can test the throughput of the virtual switch used with Mininet by running the following:
mininet> iperf
OpenFlow Overview
This homework is intended to introduce you to both high-level SDN concepts as well as give you low-level experience with OpenFlow, an open SDN protocol.
Although this homework hides many aspects of the OpenFlow protocol from you, it will probably be helpful to familiarize yourself with key concepts related to OpenFlow before starting. The following links can help you familiarize yourself with OpenFlow.
- Slides for an OpenFlow Tutorial
- The OpenFlow v1.0 Specification (Although this is an older version of the OpenFlow specification, this version is more simple than later versions, so it may be easier to understand.)
- An SDNHub tutorial on OpenFlow v1.3
Because you are required to implement a routing algorithm that is run in
a controller in response to PacketIn
messages and to broadcast packets
on a spanning tree with PacketOut
messages, you should pay particular
attention to the PacketIn
and PacketOut
concepts. You should also
pay attention to FlowMod
messages, matching, and actions.
Ryu SDN Controller Overview
This homework also hides many aspects of the Ryu controller from you. However, it is reasonable that you may want to become more familiar with the Ryu SDN Controller, especially if you are stuck debugging your application. The rest of this section gives an introduction to writing applications in Ryu, the overall design of Ryu, and the automatically generated function level documentation of Ryu.
For an introduction to Ryu, the following may be helpful:
- Slides for an Introduction to Ryu
- Writing your first Ryu Application
- An SDN Hub Tutorial on the Ryu Controller
For in-depth documentation on the design and use of Ryu, See the “Ryu SDN Framework” book (Ryubook):
Finally, the automatically generated documentation for v3.6 of Ryu can
be found in the ryu_documentation_release3_6.pdf
file in your starter
code.
(The documentation for the most up to date version of Ryu can be found
here)
Skeleton Code
You should start this assignment by checking out your github classroom
repository into the home directory of the Ryu VM (/home/ryu/
). In
this repository, there is provided code in hw9.py
, and this file
contains a complete Ryu application that implements the functionality of
an Ethernet switch. However, all packets in this application flow
through the controller, which is inefficient, and this program fails to
correctly deliver packets on networks with cycles because it uses naive
broadcasting. Your assignment is to then implement additional
routing algorithms on top of this skeleton code. Importantly, all of
the sections that require additional student code are marked by
#HW9TODO
. To help you with this task, this section introduces you to
the key functions in the hw9.py
file:
__init__
: In addition to initializing variables, this function reads data from a Ryu configuration file to configure which of a few routing algorithms will be used in response to aPacketIn
message. There are four different routing algorithms in total, and all algorithms already have a configuration file created:noop
: “noop” (conf/noop.conf
) is a NOOP (no-op) routing algorithm. When this is used, no packets should flow through your network.flood
: “flood” (conf/flood.conf
) is a routing algorithm that uses the controller to flood every packet recieved from a PacketIn message all of the ports of the switch that caused the PacketIn message.broadcast_stp
: “broadcast_stp” (conf/brodcast_stp.conf
) is a routing algorithm that uses the contorller to broadcast the packet out only the ports of the switch that are part of a spanning tree computed by the controller. Finishing writing this routing algorithm is part of this assignment.per-flow
: “per-flow” (conf/per_flow.conf
) is a routing algorithm that uses the controller to install a route for every source MAC/destination MAC (SMAC/DMAC) pair that try to communicate, falling back on broadcasting using the “broadcast_stp” algorithm when it has yet to learn the destination for a packet. Finishing writing this routing algorithm is part of this assignment.
flood
: This function implements the flooding routing algorithm, using OpenFlow’sOFPP_FLOOD
action. This function is already correctly implemented and is included as an example routing function.output_packet_port
: This function will send a packet from the controller application to a given switch for outputting out a given port with thePacketOut
message.get_topology_data
: This function will fetch the full network topology from another Ryu application that you must ensure is running as well as your application (This assignments provides a scriptrun_hw9.sh
that already does this for you). This function returns a graph G = (V, E) = (switch_list, link_list). You can uncomment debugging information in this function if you are confused by what objects exactly are returned.build_spanning_tree
: This function gets the current topology, and builds a spanning tree that will be used to determine which ports packets will be broadcast out. Finishing writing this function is part of this assignment.broadcast_stp
: This function implements the “broadcast_stp” routing algorithm. Finishing writing this function is part of this assignment.install_path
: Given a source MAC (src
), a destination MAC (dst
), and a path (path
) that is a list of (DPID, input_port, output_port) tuples, build and send the appropriateFlowMod
messages to every switch in the path. This function is already implemented for you.find_path
: Find a path given a source switch DPID and input port and a destination switch DPID and an output port. As part of implementing this function, you are not allowed to use any outside libraries or additional imports. Finishing writing this function is part of this assignment.per_flow
: This function implements the “per-flow” routing algorithm. Finishing writing this function is part of this assignment.
Program Requirements (Programming Tasks)
The tasks to be completed as part of this assignment amount to finishing
implementing both the broadcast_stp
and per-flow
routing algorithms.
To help make things as clear as possible, the skeleton code marks
incomplete or temporary code that needs to be replaced. The rest of
this section describes how these different routing algorithms should
behave and how you should approach completing the implementation of
these different algorithms.
“broadcast_stp” Routing Algorithm
This algorithm is intended to solve a problem with using the flood
routing algorithm on a topology that contains cycles. In particular,
the flood
algorithm is not able to send pings on a network that has
cycles because broadcast storms will overwhelm the controller. The
purpose of this algorithm is to, using full knowledge of the network
topology from another running Ryu application
(ryu/ryu/topology/switches.py
), build a spanning tree that will be
used to determine how packets are broadcast at every switch.
In this routing algorithm, every packet that is received from a
PacketIn
message is to be then forwarded out every single port of the
switch that generated the message that is a member of the spanning tree.
This includes ports that are connected to hosts, and this includes ports
connected to other switches that are a part of the spanning tree that is
computed the first time this routing algorithm is run.
The primary difficulty in completing this routing algorithm is in searching the topology and creating a spanning tree. For this, you should implement a common spanning tree algorithm like Breadth-first search (BFS) or Depth-first search.
This routing algorithm is only practical for bootstrapping connectivity
in an SDN network. This is because every packet in the entire network
flow though the controller via PacketIn
messages. In an operational
SDN network, it is necessary to install rules in flow tables for
performance.
per-flow
Routing Algorithm
The per-flow
routing algorithm learns the locations of end-hosts in
the network, computes routes between them, and installs rules in flow
tables in the appropriate switches along the path so as to ensure that
packets can flow in the network between the source and destination
without the intervention of the controller. Because the skeleton
code for this algorithm is designed to fall back on the broadcast_stp
algorithm, it is easy to incorrectly conclude that this algorithm is
implemented correctly. For this routing algorithm to be correctly
implemented, you should be able to run pingall
and iperf
without any
packets being forwarded to the controller.
In this algorithm, you must find a path from the source to destination. For this, it is recommend that you implement with your own code an algorithm like Dijkstra’s Shortest Path First algorithm.
Testing
The homework template contains scripts and configuration files that are
intended to help with running and testing your Ryu application. In
order to enable topology discovery, it is necessary to always run the
switches.py
(ryu/ryu/topology/switches.py) Ryu application along with
the hw3.py
Ryu application. The run_hw9.sh
script will take care of
invoking this for you. However, if you want to invoke your Ryu program
without this script, or you are using a more recent version of Ryu, then
you will need to sure that you are also running the appropriate topology
discovery application.
The rest of this section contains useful information for testing your Ryu application.
Run the skeleton code with the following command:
sudo bash -c "/home/ryu/cs450-net-hw9-*/run_hw9.sh /home/ryu/cs450-net-hw9-*/conf/flood.conf"
sudo bash -c "/home/ryu/cs450-net-hw9-*/run_hw9.sh /home/ryu/cs450-net-hw9-*/conf/broadcast_stp.conf"
sudo bash -c "/home/ryu/cs450-net-hw9-*/run_hw9.sh /home/ryu/cs450-net-hw9-*/conf/per-flow.conf"
Topology is an important part of configuring Mininet. For this
assignment, you should use the single
and linear
topologies that are
built into Mininet. The template for this assignment also contains the
mesh
(topos/mesh.py
) and fattree
(topos/fattree.py
) topologies.
The following are useful commands for running Mininet with these
different topologies:
sudo mn --topo single,4 --mac --switch ovsk --controller remote
sudo mn --topo linear,4 --mac --switch ovsk --controller remote
sudo bash -c "mn --custom /home/ryu/cs450-net-hw9-*/topos/fattree.py --topo fattree,4 --mac --switch ovsk --controller remote"
sudo bash -c "mn --custom /home/ryu/cs450-net-hw9-*/topos/mesh.py --topo mesh,5 --mac --switch ovsk --controller remote"
All of the routing algorithms that you create should work correctly on
all of the above topologies. However, none of the included algorithms
currently work correctly on all topologies. This is because packet
flooding will overwhelm the controller, and no routes (FlowMod
s) are
installed.
Notes:
- Mininet will connect with OpenFlow v1.0.
- Because topology auto-discovery is enabled, the
switches.py
Ryu program will automatically send LLDP packets in the network, so the controller will always be receiving some packets in any topology with more than one switch. - The
-v debug
flag is very helpful for debugging Mininet topologies. - In the Mininet terminal, using
xterm h1
throughxterm h<n>
is useful for gaining more control over the endhosts in your emulated network.
Grading
For this homework we will be using an autograder to grade your work, and
./tester.py
is the autograder that we will use. Like before, you can
create as many backups as you like using git commit -a
and git push
.
There is a total of 100 points on this assignment, with extra bonus points being awarded for exceptional new test cases. Additionally, there are extra credit points available for finding bugs in any part of this assignment infrastructure.
The points for this assignment are broken down as follows:
- 35 Points: Correctness of the
broadcast_stp
routing algorithm. - 35 Points Correctness of the
per-flow
routing algorithm. - 10 Points: Code style for routing algorithms
- 20 Points: Questions in
WRITEUP.md
There are two questions in the WRITEUP. The first is to describe the algorithm you used to compute a spanning tree. The second is to describe the algorithm you used to compute per-flow paths.
Submission
You will be making the submission for this homework through github.
The files which will be submitted through github:
hw9.py
: This file will contain both of your routing algorithmsWRITEUP.md
: This file will contain a brief description of your implementation
To submit your work, run git commit -a
and git push
. Like previously, you are allowed to make multiple submissions
but you have limited attempts with the grader.