Overview

From CS244 Wiki
Revision as of 07:01, 5 January 2010 by Yapkke (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents


OpenFlow

OpenFlow is an open standard that enables researchers to run experimental protocols in the campus networks we use every day. OpenFlow is added as a feature to commercial Ethernet switches, routers and wireless access points - and provides a standardized hook to allow researchers to run experiments, without requiring vendors to expose the internal workings of their network devices. OpenFlow is currently being implemented by major vendors, and we expect OpenFlow enabled switches to be commerically available in 2009.

How does OpenFlow Work?

In a classical router or switch, the fast packet forwarding (data path) and the high level routing decisions (control path) occur on the same device. An OpenFlow Switch separates these two functions. The data path portion still resides on the switch, while high-level routing decisions are moved to a separate controller, typically a standard server. The OpenFlow Switch and Controller communicate via the OpenFlow protocol, which defines messages, such as packet-received, send-packet-out, modify-forwarding-table, and get-stats.

OpenFlow allows us to control the flows - by choosing the routes their packets follow and the processing they receive. In this way, OpenFlow makes it possible to try new protocols such as new routing protocols, security models, and addressing schemes. The datapath of an OpenFlow Switch consists of a Flow Table, and an action associated with each flow entry.

Flow Table Entries

Each flow-entry in the flow table of the switch has a simple action associated with it; the three basic actions are:

  1. Forward this flow’s packets to a given port (or ports). This allows packets to be routed through the network. In most switches this is expected to take place at line rate.
  2. Encapsulate and forward this flow’s packets to a controller. Packet is delivered to Secure Channel, where it is encapsulated and sent to a controller. Typically used for the first packet in a new flow, so a controller can decide if the flow should be added to the Flow Table. Or in some experiments, it could be used to forward all packets to a controller for processing.
  3. Drop this flow’s packets. Can be used for security, to curb denial of service attacks, or to reduce spurious broadcast discovery traffic from end-hosts.

An entry in the Flow-Table has three fields:

  1. A rule that defines the flow, i.e., the packets that is classified to be part of the flow. The rule consists of mainly field in the packet header.
  2. The action, which defines how the packets should be processed, and
  3. Statistics, which keep track of the number of packets and bytes for each flow, and the time since the last packet matched the flow (to help with the removal of inactive flows).

The flow header is a 10-tuple as shown below. Each header field can be a wildcard to allow for aggregation of flows. Some examples of flow table entries and actions are shown below. In the example, a TCP flow could be specified by all ten fields (as in the example in the middle), whereas an L2 switch may insert flow that only includes the mac field (as in the example on the top).

How Does OpenFlow Process Packets?

To process packets in OpenFlow, the simplest way is to force all of a flow’s packets (or packets' 10-tuple headers) to pass through the controller. To do this, a controller doesn’t add a new flow entry into the OpenFlow Switch — it just allows the switch to default to forwarding every packet to the controller. This has the advantage of flexibility, at the cost of performance. It might provide a useful way to test the functionality of a new protocol, but is unlikely to be of much interest for deployment in a large network.

Alternatively, we can set a flow table entry in the switch as soon as the controller decides on the corresponding action (based on the protocol we implement). When subsequent packets arrive at a switch, they are processed quickly (and at line-rate) by the Flow Table.

OpenFlow Controller

A controller adds and removes flow-entries from the Flow Table on behalf of experiments. For example, a static controller might be a simple application running on a PC to statically establish flows to interconnect a set of test computers for the duration of an experiment. One can also imagine more sophisticated controllers that dynamically add/remove flows as an experiment progresses.

NOX Controller

In this course, you will use a particular controller (NOX), and a subset of the functionalities presented in NOX. Here we will focus on three basic APIs that should be sufficient for the course. They are

  1. Receiving packets from a switch
  2. Sending the packets
  3. Managing the flow table inside a switch (inserting or removing flow entries)

(Note that in general more than one OpenFlow switch might be connected to the controller).

The controller also provides a choice of programming languages, namely Python and C/C++.

API in C/C++

The skeleton file noxcore/src/nox/coreapps/learningswitch.cc provided will serve as the basis for the first and second assignments. This file demonstrates how a C application in NOX is provided. The basic steps to create a C/C++ component are as follows.

  1. create a directory in srx/nox/coreapps/ (lets call it learningswitch)
  2. copy from src/nox/coreapps/simple_cc_app
    • Makefile.am
    • simple_cc_app.cc to learningswitch.cc
    • meta.xml
  3. Edit Makefile.am and meta.xml to use learningswitch* instead of simple_c*
  4. Edit learningswitch.cc to taste (rename class SimpleCCApp to LearningSwitch)
  5. Modify configure.ac to add learningswitch to
ACI_PACKAGE([coreapps],[core application set],
            [pyrt simple_c_app simple_c_py_app hub switch examples],[yes])
  1. Rebuild using nox-compile

Receiving a packet

The primary mechanism for gaining access to network events is to register a handler. In the learning switch skeleton file, the following line of the code registers the handler:

register_handler<Packet_in_event> (boost::bind(&LearningSwitch::handle, this, _1));

This results in a callback when a packet is received by the controller. The function being called is exemplified as below.

Disposition handle(const Event& e)
{    
   const Packet_in_event& pi = assert_cast<const Packet_in_event&>(e);
   cout << " Received packet in on port " << pi.in_port << endl;
   
   return CONTINUE;
}

The first line in the function cast the event received as an Packet_in_event, and the second line prints the input port of the received packet. Returning CONTINUE indicates that the event is passed on to the next component registered in nox.xml.

In this function, you can manipulate the packet received, to your liking. In the learning switch example, the flow parameters are extracted using function

 Flow flow(pi.in_port, *pi.get_buffer());

Finally, you must edit src/etc/nox.xml to add your application to Packet_in_event.

Sending a packet

Applications can send packets on the network using one of the following methods:

// Instruct a switch to send a packet it has buffered
int send_openflow_packet(const datapathid&, uint32_t buffer_id,
                        uint16_t out_port, uint16_t in_port,
                        bool block) const;

// Send a packet in a Buffer object out on the network
int send_openflow_packet(const datapathid&, const Buffer&,
                        uint16_t out_port, uint16_t in_port,
                        bool block) const;

The first method accepts a buffer_id and assumes that the switch is already buffering the packet. Unless otherwise instructed, switches buffer incoming packets and only send the first 128 bytes to the controller. The buffer_id is then passed to the application in a Packet_in_event. Use the first method to send this packet out again.

The second method allows an application to construct and send an arbitrary packet out on the network.

Note that the datapathid is the a value that is used to indicate which switch the data should be sent to (this is needed as there might be more than one OpenFlow switch controlled by this controller). This is available in the Packet_in_event, so are the buffer_id and the in_port parameters. The out_port is what needs to be decided by the controller. Flooding to all ports can be specified using the special port OFPP_FLOOD. Finally, this function can be called as a blocking call by setting the last parameter to true.

Managing the Flow Table

Applications can manage forwarding packets in the switch by adding and deleting flow entries in the OpenFlow switch. The general function doing this is:

int send_openflow_command(const datapathid&, const ofp_header*, bool block) const;

API in Python

The skeleton file noxcore/src/nox/coreapps/pylearningswitch.py provided will serve as the basis for the first and second assignments. This file demonstrates how a Python application in NOX is provided. The basic steps to create a Python component are as follows.

  1. create a directory in srx/nox/coreapps/ (lets call it learningswitch)
  2. copy from src/nox/coreapps/examples
    • Makefile.am
    • meta.xml
    • __init__.py
  3. Edit Makefile.am and meta.xml to use learningswitch
  4. Create and edit learningswitch.py to taste
  5. Modify configure.ac to add learningswitch to
ACI_PACKAGE([coreapps],[core application set],
            [pyrt simple_c_app simple_c_py_app hub switch examples],
            [yes])
  1. Rebuild using nox-compile

Receiving a packet

To received a packet, you have to register for a packet-in event in NOX using the following code.

 inst.register_for_packet_in(packet_in_callback)

Here inst is an instance of Component. This results in a callback when a packet is received by the controller. The function being called is exemplified as below.

def packet_in_callback(dpid, inport, reason, len, bufid, packet):
      return CONTINUE

This is provided in the skeleton file. Returning CONTINUE indicates that the event is pass on to the next component registered in nox.xml.

In this function, you can manipulate the packet received, to your liking. Flow parameters can be extracted using function

flow = extract_flow(packet)

which returns a flow object that provides hooks to the various parameters.

Finally, you must edit src/etc/nox.xml to add your application to Packet_in_event.

Sending a packet

To send a packet to a certain port in the switch, we use the command

inst.send_openflow(dpid, bufid, buf, outport, inport)

Note that the dpid is the a value that is used to indicate the switch. The outport is what needs to be decided by the controller. Flooding to all ports can be specified using the special port openflow.OFPP_FLOOD.

Managing the Flow Table

To setup a flow entry, we have to send a command to the OpenFlow switch. This is achieved using

 inst.install_datapath_flow(dpid, flow, idle_timeout, hard_timeout, actions,
                            bufferid, priority, inport, buffer)

To call this function you have to declare the actions whuch can be done as follow.

  actions = [[openflow.OFPAT_OUTPUT, [0, outport]]]

Development Environment -- VirtualBox

The VirtualBox NOX development environment can be pictorially represented as below. As seen, VirtualBox hosts a Linux installation (Debian unstable), which is connected to the host OS via NAT. To gain access to GUI, we allow X11 forwarding via a SSH connection.

Virtual Network

In the VirtualBox image, we will run a virtual network, using VDE (Virtual Distributed Ethernet) and qemu. The OpenFlow switches and hosts are qemu virtual machines, connected via VDE. This virtual network is shown in red in the above diagram.

To complete the OpenFlow network, the OpenFlow switches are connected to an OpenFlow controller (namely NOX) in the VirtualBox VM. These connections are shown in blue. It is worth noting that the OpenFlow switches are software Linux switches, that runs the OpenFlow kernel module and secchan user space program.

A detailed description of the environment can be found at noxtrial (viewable only in Stanford).

Setting up VirtualBox

We begin by getting Sun's VirtualBox up and running. Download a copy for virtualbox.org for your platform. Once installed, create a virtual machine with the following disk image, downloadable from as a tgz archive here (1 GB). It is recommended that the machine has 512MB RAM and a minimum amount of video memory will suffice. The username and password are both openflow. Note that the openflow user is a sudoer.

To allow network access in the VM, execute

sudo dhclient eth1

to grab an IP address. Else, you can change the default interface as shown below and execute sudo dhclient eth0. Now we need to provide SSH access into VirtualBox. <guestname> refers to the VM name, which by default is DebianMin. On the local machine (not the VM), run:

VBoxManage setextradata <guestname> "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort" 2222
VBoxManage setextradata <guestname> "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/GuestPort" 22
VBoxManage setextradata <guestname> "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/Protocol" TCP

You can check the settings using

VBoxManage getextradata <guestname> enumerate

In Windows XP, you can do this in the console (i.e., run cmd) , after changing directory using

cd "C:\Program Files\Sun\xVM VirtualBox"

To save your settings, power down the VM:

sudo poweroff

SSH Access into VM

Mac OS X and Linux

Now start the virtual machine and ssh into it using

ssh -Y -l openflow -p 2222 localhost

with password openflow. Test the X11 forwarding by running

xterm

and a new terminal window should appear. And if you have succeeded, you are done with the basic setup.

Windows XP

For Window XP, you need to change some configuration in the VM. So begin by start ing DebianMin (login with username: openflow, passwd: openflow). Edit /etc/network/interfaces with your favorite editor in Linux, changing eth0 -> eth1 on "Primary Interface" section as follows

allow hot-plug eth1
iface eth1 inet dhcp

save the file and poweroff using

sudo poweroff
  1. Start VirtualBox and run the given image
  2. Start Xming
  3. Run putty with X11 forwarding on
  4. Run xterm and if a new console window appears, you are okay.

Want to know more about OpenFlow/NOX?

There are many resources available for you! Check out http://www.openflowswitch.org/wp/learnmore/ You can watch the video, read the OpenFlow white paper, or take a look at the OpenFlow presentation.

To understand the full glory of NOX, you can visit http://noxrepo.org. Here, the setup of the system will be discussed in detail.

Personal tools