Version 17 (modified by, 6 years ago) (diff)


<OpenFlow Load Balancer Tutorial>

Hello GENI index Hello GENI index Hello GENI index

1. Debugging an OpenFlow Controller

You will find it helpful to know what is going on inside your OpenFlow controller and its associated switch when implementing these exercises.
This section contains a few tips that may help you out if you are using the Open vSwitch implementation provided with this tutorial. If you are using a hardware OpenFlow switch, your instructor can help you find equivalent commands.
The Open vSwitch installation provided by the RSpec included in this tutorial is located in /opt/openvswitch-1.6.1-F15. You will find Open vSwitch commands in /opt/openvswitch-1.6.1-F15/bin and /opt/openvswitch-1.6.1-F15/sbin. Some of these commands may be helpful to you. If you add these paths to your shell’s $PATH, you will be able to access their manual pages with man. Note that $PATH will not affect sudo, so you will still have to provide the absolute path to sudo; the absolute path is omitted from the following examples for clarity and formatting.

  • ovs-vsctl
    Open vSwitch switches are primarily configured using the ovs-vsctl command. For exploring, you may find the ovs-vsctl show command useful, as it dumps the status of all virtual switches on the local Open vSwitch instance. Once you have some information on the local switch configurations, ovs-vsctl provides a broad range of capabilities that you will likely find useful for expanding your network setup to more complex configurations for testing and verification. In particular, the subcommands add-br, add-port, and set-controller may be of interest.
  • ovs-ofctl
    The switch host configured by the given rspec listens for incoming OpenFlow connections on localhost port 6634. You can use this to query the switch state using the ovs-ofctl command. In particular, you may find the dump-tables and dump-flows subcommands useful. For example, sudo ovs-ofctl dump-flows tcp: will output lines that look like this:
    cookie=0x4, duration=6112.717s, table=0, n packets=1, n bytes=74, idle age=78,priority=5,tcp,
    nw src= actions=CONTROLLER:65535
    This indicates that any TCP segment with source IP in the subnet should be sent to the OpenFlow controller for processing, that it has been 78 seconds since such a segment was last seen, that one such segment has been seen so far, and the total number of bytes in packets matching this rule is 74. The other fields are perhaps interesting, but you will probably not need them for debugging. (Unless, of course, you choose to use multiple tables — an exercise in OpenFlow 1.1 functionality left to the reader.)
  • Unix utilities
    You will want to use a variety of Unix utilities, in addition to the tools listed in ExerciseLayout, to test your controllers. The standard ping and /usr/sbin/arping tools are useful for debugging connectivity (but make sure your controller passes ICMP ECHO REQUEST and REPLY packets and ARP traffic, respectively!), and the command netstat -an will show all active network connections on a Unix host; the TCP connections of interest in this exercise will be at the top of the listing. The format of netstat output is out of the scope of this tutorial, but information is available online and in the manual pages.

2. Implement a Load Balancing OpenFlow Controller

  • Files to download: load-balancer.rb
  • We will implement a Load Balancer OpenFlow Controller on node Switch using Trema.
  • Load balancing in computer networking is the division of network traffic between two or more network devices or paths, typically for the purpose of achieving higher total throughput than either one path, ensuring a specific maximum latency or minimum bandwidth to some or all flows, or similar purposes. For this exercise, you will design a load-balancing OpenFlow controller capable of collecting flow status data from OpenFlow switches and using it to divide traffic between dissimilar network paths so as to achieve full bandwidth utilization.
  • An interesting property of removing the controller from an OpenFlow device and placing it in an external system of arbitrary computing power and storage capability is that decision-making for network flows based on external state becomes reasonable. Traditional routing and switching devices make flow decisions based largely on local data (or perhaps data from adjacent network devices), but an OpenFlow controller can collect data from servers, network devices, or any other convenient source, and use this data to direct incoming flows.
  • For the purpose of this tutorial, data collection will be limited to the flow statistics reported by open vswitches.

2.1 Experimental Setup

Follow instructions in the DesignSetup step to build a load balancing experiment topology. Your GENI resources will be configured in a manner similar to the above figure. The various parts of the diagram are as follows:

  • Inside and Outside Nodes: These nodes can be any ExoGENI Virtual Nodes.
  • Switch: This node is a Linux host running Open vSwitch. Your Load Balancing OpenFlow Controller will be running on this node as well. This is the main node that you will be working on.
  • Traffic Shaping Nodes (Left and Right): These are Linux hosts with two network interfaces. You can configure netem on the two traffic shaping nodes to have differing characteristics; the specific values don’t matter, as long as they are reasonable. Use several different delay/loss combinations as you test your load balancer.
  • Aggregator: This node is a Linux host running Open vSwitch with a switch controller that will cause TCP connections to “follow” the decisions made by your OpenFlow controller on the Switch node. So leave this node alone, you only need to implement the OpenFlow controller on node Switch.

2.2 Linux netem

Use the tc command to enable and configure delay and lossrate constraints on the outgoing interfaces for traffic traveling from the OpenFlow switch to the Aggregator node. To configure a path with a 20 ms delay and 10% lossrate on eth2, you would issue the command:

sudo tc qdisc add dev eth2 root handle 1:0 netem delay 20ms loss 10%

Use the tc qdisc change command to reconfigure existing links,instead of tc qdisc add.
The outgoing links on node Switch in the provided rspec are numbered and for left and right, respectively.

2.3 Balancing the Load

An example openflow controller that arbitrarily assigns incoming TCP connections to alternating paths can be found at load-balancer.rb.

Log on to node switch, download the load balancing controller by running:

wget /root/

(If you have already downloaded it, ignore this)

2.4 Use GIMI Portal to run the experiment and monitor the load balancer

  • Log on to your LabWiki Account on , on the Prepare Column, type OpenFlow, it will pop up with a list of .rb choices. Choose any one, and replace the whole content with the ruby script HERE.
  • Log on to node switch and do ifconfig to see the IP addresses on each interfaces. Identify the two interfaces that you want to monitor: the interfaces with IP address and respectively. On the LabWiki page, in your ruby script, find the following line:
    options = { 'sample-interval' => 1, 'monitor_interface' => 'eth1 -i eth3' }
  • Change eth1 and eth3 to the corresponding two interfaces you found with IP address and and press the save icon on your LabWiki page.
  • Drag the file Icon on your LabWiki page from Prepare column and drop it to Execute column. Fill in the name of your LabWiki experiment (this can be anything), the name of your slice (this has to be your slice name), and type true in the graph box to enable graph. And then press Start Experiment button.
  • Note: Do not start another experiment (i.e., drag and drop the file icon in LabWiki and press Start Experiment) before your current experiment is finished.

2.5 Fetch experimental results from your iRods account

  • Log in your iRods account on, use "" as Host/IP, "1247" as Port.
  • Download your experimental results from your user directory under /geniRenci/home/

2.6 Change network delay and lossrate parameter of left path using tc and repeat the experiment

  • use the following command to change network condition on node "Switch": here we assume eth2 is the interface connecting node "Left". User may use "ifconfig" to figure out the correct interface.
    tc qdisc add dev eth2 root handle 1:0 netem delay 20ms loss 10%
  • Did you see any difference from the graphs plotted on LabWiki, compared with the graphs plotted in the first experiment? why?
  • Check out the OpenFlow Load Balancing Controller's Log on node "Switch" at /tmp/lb.tmp and tell how many flows are directed to the left path and how many are on the right path, why?
  • To answer the above question, you need to understand the Load Balancing controller. Check out the "load-balancer.rb" file in your home directory on node "Switch". Check Section 3 for hints/explanations about this OpenFlow Controller.

2.7 Modify the OpenFlow Controller to maximize per-flow throughput

  • You need to calculate the average per-flow throughput observed from both left and right path in function "stats_reply" in your load-balancer.rb
  • In function "packet_in", change the path decision based on the calculated average per-flow throughput: forward the flow onto the path with more average per-flow throughput. (Why? Hint: TCP tries its best to suck up the whole bandwidth)
  • If you do not know where to start, check the hints in Section 3. If you really do not know where to start after reading at the hints, download the answer from Here.
  • Redo the above experiment (the one with some lossrate on the left path), check the graphs plotted on LabWiki as well as the controller's log on node "Switch" at /tmp/lb.tmp and see the difference.
  • If you have more time or are interested in trying out things, go ahead. The tutorial is over now and feel free to ask questions :-)

3. Hints

3.1 About the OpenFlow controller load-balancer.rb

  • Trema web site:
  • Treme ruby API document:
  • Functions used in our tutorial:
    • start: is the function that will be called when the OpenFlow Controller is started. Here in our case, we read the file /tmp/portmap and figures out which OpenFlow port points to which path
    • switch_ready: is the function that will be called each time a switch connects to the OpenFlow Controller. Here in our case, we allow all non-TCP flows to pass (including ARP and ICMP packets) and ask new inbound TCP flow to go to the controller.
    • packet_in: is the function that will be called each time a packet arrives at the controller. Here in our case, we send out a flow_stats_request to get the current statistics about each flow. Then based on the last received statistics (so we are not using the current statistics to make path decisions--there is a delay of two flows), we make our path choices.
    • stats_reply: is the function that will be called when the OpenFlow Controller receives a flow_stats_reply message from the OpenFlow Switch. Here in our case, we update the flow statistics here in this function.
    • send_flow_mod_add(): is the function that you should use to add a flow entry into an OpenFlow Switch.
  • Process: Upon the arrival of a new TCP flow, the OpenFlow controller should send out a FlowStatsRequest message to the OpenFlow switch. The OpenFlow switch will reply with statistics information about all flows in its flow table. This flow statistics message will be fetched by the stats_reply function in the openflow controller implemented by the user on node switch. Based on the statistics, experimenters can apply their own policy on which path to choose in different situations. The FlowStatsReply message is in the following format:
      :length => 96,
      :table_id => 0,
      :match =>
      :duration_sec => 10,
      :duration_nsec => 106000000,
      :priority => 0,
      :idle_timeout => 0,
      :hard_timeout => 0,
      :cookie => 0xabcd,
      :packet_count => 1,
      :byte_count => 1,
      :actions => [ ]
  • Note: since Trema does not yet support multi-thread mode, this simple implementation runs in one thread. As a result, users will experience some delay in fetching the flow statistics (i.e., stats_reply will not be called right after a FlowStatsRequest message has been sent in packet_in function). Also, it seems that it will take some time for the Open vSwitch to be able to report some flow statistics to the controller. In our experience, Open vSwitch will start to report flow statistics after two flows have already been established. So do not be panic when flow_stats_reply says nothing when one or two flows are already running.

3.2 About the GIMI script you run on LabWiki

Next: Teardown Experiment

Attachments (2)

Download all attachments as: .zip