Homework Assignment 3
This homework will cover the some of the networking in cloud computing. In particular it will introduce you to software defined networking (SDN). Scott Shenker, professor at the UC Berkeley are giving a lot of good talks on SDN and why we need it, one of which you can find here. The homework is based on this Github turorial so if you find the instructions here confusing, I recommend that you look around in that one:)
Overview
The goal of this homework is to develop a network control application using OpenFlow. OpenFlow is an open interface for remotely controlling the forwarding tables in network switches, routers and access points. The network we will control will be built on Mininet, which creates a realistic virtual network on a single machine (VM).
There are a bunch of available controller platforms to build this application on. However, we recommend using POX (which is written in python). The rest of this homework will be based on it, but as usual, feel free to use whatever platform you wish!
The structure of the homework is as follows:
- Install all the necessary software
- Learn mininet, and create a topology (starting code exist)
- Learn how to connect a remote controller to your network switch
- Develop a learning switch (starting code exist)
- Develop a flow-based learning switch
Some platforms:
Java: Beacon, Floodlight
Ruby: Trema
Deadline and Deliverables
Deadline for this homework is March 31. You will hand in the source code (usually just two files) and a short text (1/4 - 1/2 page) that answers the following questions:
- How does a hub work?
- How does a learning switch work?
- How can you test if your switch is indeed a learning switch?
- Show us some output from your switch (e.g. tcp-dump, WireShark screen dump, …)
- How much more aggregate throughput can you get when using flows?
- What numbers did you get?
- How can you measure/know if the performance of a hub/switch is competitive?
- What numbers are good?
Installing the necessary software
As with the privious homeworks this one does also reqwuire you to install some software. First off you will need to install a Virtual Machine (like VirualBox which is free, or VMware).
- Install a Virtual Machine - VirtualBox (is free and works on any platform)
- Download and install Mininet - great install instructions can be found here
- Make sure that you can
ssh
into your virtual machine! - Read about mininet
- Go through the Mininet tutorial.
- Install POX (official tutorial here)
- Open a new terminal-window (W1) and
ssh
into your virtual machine (VM) - In (W1):
$ git clone http://github.com/noxrepo/pox
- Open a new terminal-window (W1) and
Create a topology in Mininet
There are many different ways of creating a network topology in mininet. Most of them are explained here
To prepare for the next homework assignment, we will learn how to create and define a topology using the mininet API, and Pyhton. Make sure to download and look through our file hw3_start.py
(can be found here). In this file we have already created a topology corresponding to the figure below. It also contains some useful comments on how you can change the file so that the switches can use a remote controller - which is exactly what you want when you will create your learning switch!
Follow these steps to familiarize yourself with the topology, and the mininet API:
ssh
into your VM- copy
hw3_start.py
into your VM - can be found here - Run the file
$ sudo ./hw3_start.py
- You should now be in the mininet-client!
- Investigate what happens when you do the following commands:
mininet> pingall
mininet> h1 ping h2
mininet> h1 ifconfig
mininet> s1 ifconfig
- Exit with
mininet> exit
- Open
hw3_start.py
in a text editor:- Change the file so that you now connect to a remote controller
- save it and run it again:
$ sudo ./hw3_start.py
- Do the same commands again and see what happens!!
- Let’s now make things interesting!!
- Change the topology in the file so that it matches the figure below:
- 5 hosts
- 2 switches
- 1 controller (controlling both switches)
- you can start with the default controller and make sure that everything is connected!
- then do as above, and connect to a remote controller instead
Connect a controller to your network
When running a remote controller it is up to you to make sure that you actually connect a controller. The controller you specified in your mininet topology (in hw3_start.py
) will only ensure that your switch(es) listen for a connection from a remote controller.
These steps will guide you on how to connect a remote controller to your network switch. The remote controller that we will connect is the one that currently acts as a hub. You will later edit this controller so that it instead acts as a learning switch.
- Fire up 2 terminal windows and
ssh
into your VM on both of them- To try and keep things clear (W1) = window 1, and (W2) = window 2
- (W1): This window will be used to run mininet
- Open your
hw3_start.py
-file - Make sure that it connects to a remote controller
- Make sure that it have the topology specified above
- Run your file:
$ sudo ./hw3_start.py
- Check connectivity:
mininet> pingall
- Should drop all the packets
- Open your
- (W2): This will be used to run your controller
- go to the
pox
-folder:$ cd pox/
- open the following file in a text editor:
pox/misc/of_tutorial.py
- this is the file where the controller is defined
- look through the code and then close the file
- Now let’s start the controller!
$ ./pox.py log.level --DEBUG misc.of_tutorial
- This enables logging in debug mode, and that the controller is defined in
/misc/of_tutorial.py
- You should see this ouput (tells you that you’ve connected to the two switches):
POX 0.1.0 (betta) / Copyright 2011-2013 James McCauley, et al. DEBUG:core:POX 0.1.0 (betta) going up... DEBUG:core:Running on CPython (2.7.6/Mar 22 2014 22:59:56) DEBUG:core:Platform is Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14.04-trusty INFO:core:POX 0.1.0 (betta) is up. DEBUG:openflow.of_01:Listening on 0.0.0.0:6633 INFO:openflow.of_01:[00-00-00-00-00-02 1] connected DEBUG:misc.of_tutorial:Controlling [00-00-00-00-00-02 1] INFO:openflow.of_01:[00-00-00-00-00-01 2] connected DEBUG:misc.of_tutorial:Controlling [00-00-00-00-00-01 2]
- go to the
- (W1): Try the following commands and see what happens:
mininet> pingall
mininet> h1 ping h5
mininet> iperf
Turing a Hub into a Learning Switch
This is the main part of the homework assignment. Here you will take the provided controller (of_tutorial.py
) which acts as a hub and turn it into a learning switch. You should have done the above steps before doing this one!
- Fire up 2 terminal windows again, and
ssh
into your VM - (W1): Will be used for mininet
- We assume that you know how to start your topology by now…
- We also assume that you know how to test stuff, and edit stuff..
- (W2): Will be used for POX
$ cd pox/
- open:
pox/misc/of_tutorial.py
in your favorite text editor - Study the code! Make sure that you understand how it works as a hub before you continue!!!
- You’ll see that it calls the function:
self.act_like_hub(packet, packet_in)
from_handle_PacketIN()
- The hub will send an incoming packet to every outgoing port:
self.resend_packet(packet_in, of.OFPP_ALL)
- You’ll see that it calls the function:
- To turn the controller into a switch you need to call
self.act_like_switch(packet, packet_in)
- Change it and connect the controller:
$ ./pox.py log.level --DEBUG misc.of_tutorial
- Check if your switch works! (or maybe you actually have to change some more stuff… ;)
- Follow the schema outlined by the comments in
of_tutorial.py
to build your learning switch. - During development: when you change something, restart your controller and check if it works!
- In the sections below you will find some help on Python, POX, and OpenFlow!
- Again, I recommend looking at the original tutorial for further help!
Python help
If you are unfamiliar with Python, you can check out some good commands below, or this turorial.
mactable = {}
- Initialize a dictionarymactable[0x123] = 2
- Add an element to itCheck for a member in the dictionary:
if 0x123 in mactable: print 'element 2 is in mactable' if 0x123 not in mactable: print 'element 2 is not in mactable'
log.debug('saw a new MAC!')
- Print a debug message in POXlog.error('unexpected packet causing system meltdown!')
- Print an error message in POXprint dir(object)
- Print all member variables and functions of an objectprepend code with a #
- Comment a line of code
OpenFlow and POX help
I highly recommend the OpenFlow POX wiki for any question on OpenFlow and POX. However, I will list some useful commands below:
packet.src
- Get the source of a packet (the parsed packet data)packet.dst
- Get the destination of a packet (the parsed packet data)packet_in.in_port
- Get the inport of apacket_in
(the actualofp_packet_in
message)self.resend_packet(packet_in, out_port)
- Send a packet to a certain portlog.debug("Sent packet: %s.%i -> %s.%i" %(mac_src, inport, mac_dst, outport))
- Example of alog.debug
message
Installing a flow
To install a flow table entry into a switch you will have to send an ofp_flow_mod
message to it. The message contains some fields that need to be set.
ofp_flow_mod
message fields:
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
)buffer_id
- The buffer_id of a buffer to apply the actions to immediately.in_port
- If using abuffer_id
, this is the associated input port.match
- Anofp_match
object. By default, this matches everything, so you should probably set some of its fields!
ofp_match
fields:
dl_src
- The data link layer (MAC) source address.dl_dst
- The data link layer (MAC) destination address.in_port
- The packet input switch port.
Some examples of how to use these fields:
- To create a new flow_message:
msg = of.opf_flow_mod()
- Set source MAC:
msg.match.dl_src = ...
- Set destination MAC:
msg.match.dl_dst = ...
- Set idle_timout:
msg.idle_timeout = ...
- Set hard_timeout:
msg.hard_timeout = ...
- Choose output port:
msg.actions.append(of.ofp_action_output(port = outport))
- Set the buffer id for the message:
msg.buffer_id = packet_in.buffer_id
- Send the message:
self.connection.send(msg)