How to implement Quality Of Service using Floodlight
This has not been ported to Floodlight v1.0 at this time.
This open-source project is in affiliation with Marist College in New York.
Ryan Wallner
ryan.wallner1@marist.edu
A video tutorial on some the features:
http://www.youtube.com/watch?v=M03p8_hJxdc
The code is available here: (rough around the edges but good enough to play with)
https://github.com/wallnerryan/floodlight-qos-beta.git
$git clone https://github.com/wallnerryan/floodlight-qos-beta.git
$cd floodlight-qos-beta
$ant; ./floodlight.sh
(open your bowser and visit localhost:8080/ui/index.html and click Tools
[Update Jan 2013]
Both python apps will be re-factored to use a more flexible arg parsing lib
The module itself is also being prepared to be only the QoS module, no UI or other code. This is
so it can eventually integrate into the master. Modifying existing QoS policies will also be added.
[update 4-22-13] I will be updating this tutorial in the coming days.
Implementing QoS using Floodlight
- Quality of Service is at its infancy when it comes to OpenFlow. The OpenFlow 1.0 spec included ways in which you can set the network
type of service on a flow, as well as enqueue the packets matching the flow to a specific queue on a specific port. What this module tries to do
is give a user a way to simply push QoS state to switches that support these features. This modules will aim to tackle the "enqueue" and "set-nw-tos"
actions. The static flow pusher API calls this "set-tos-bits". As future specs such as 1.3 become adopted I plan to implement features that take advantage
of 1.3's "set-queue" and and meter tables. Setting of the DSCP or ToS bits will continue to be supported, but there are plans to create a more in-depth
QoS framework in the future specs. OFConfig can play a major role in Quality of Service as well, the implementation of such a protocol could prove
very useful in the set-up and tear-down of qos-based queues.
- The example below shows how to push rate-limiting QoS state into OVswitches that utilize queues attached to ports. Other switches can take advantage of the network ToS bits,(which is very vendor specific) and you can ultimately push a "network wide" policy that abides by what ever the ToS bits are set to do in your network.
Some additional references:
- OpenFlow (1.0) supports setting the network type of service bits and enqueuing packets. This does not however mean that every switch will support these actions.
- Queuing Methods:
Some Openflow implementation do NOT support queuing structures to attach to a specific ports, in turn then "enqueue:port:queue" action in Openflow 1.0 is optional. Therefore resulting in failure on some switches
- DSCP /DiffServ and other class based quality of service are rarely, if at all supported by any 1.0 spec switched. (that I know of, would love to hear otherwise) RFC : http://tools.ietf.org/html/rfc2474 Guidlines: http://tools.ietf.org/html/rfc4594
- The application takes into account that both methods, queuing and class bases "could" be supported.
- OF 1.3 calls enqueue, "set_queue" (future revision).
- Switches must be set "by hand" / "Manually" to support ToS or Queues. (OFConfig is trying to reform this.) https://www.opennetworking.org/images/stories/downloads/of-config/of-config-1.1.pdf https://www.opennetworking.org/images/stories/downloads/of-config/of-config-1.2.pdf
QoS Application.
Module: Allows the QoS service and policies to be managed on the controller and applied to the network
REST API | GET | POST | Description of use |
---|---|---|---|
/wm/qos/tool/<op>/json | Yes | N/A | Use "status", "enable" or "disable" |
/wm/qos/service/json | Yes | Yes | Accepts a service that can be added to the controller. This service can |
/wm/qos/policy/json | Yes | Yes | Accepts a policy to enforce. Policies can be applied to a single switch, a list of |
Service
Field | Description |
---|---|
id | unique identifier (not needed in POST) |
name | unique, gives a human readable description for the policy. I.e. "Best Effort" |
tos | Represents the type of service or DSCP (Differentiated Services Code Point) bits |
Policy
Field | Description |
---|---|
id | unique identifier (not needed in POST) |
name | Unique. human readable name for the policy i.e "Enqueue 1:1 on switch 1" |
sw | this can have several values.
|
service | reference a ToS classification service from a list of known services by the controller. Will set the policy to action _set-nw-tos. _Default is "Best Effort" with a tos=0x00. |
queue | queue used in the enqueue method. queue cannot be set without enqueue |
enqueue-port | This will set the action to enqueue and set the action to enqueue to this port. This will need queue to be set as well. |
priority | The priority of the policy (flow)
|
Policy Match Fields | same from the staticflowpusher |
protocol | Can be hexadecimal (with leading 0x) or decimal |
eth-type | Can be hexadecimal (with leading 0x) or decimal |
ingress-port | switch port on which the packet is received |
ip-src | xx.xx.xx.xx |
ip-dst | xx.xx.xx.xx |
tos | Can be hexadecimal (with leading 0x) or decimal |
vlan-id | Can be hexadecimal (with leading 0x) or decimal |
eth-src | Can be hexadecimal (with leading 0x) or decimal |
eth-dst | Can be hexadecimal (with leading 0x) or decimal |
src-port | Can be hexadecimal (with leading 0x) or decimal |
dst-port | Can be hexadecimal (with leading 0x) or decimal |
*"wildcards" and "active" keys are unsupported right now. |
Rest Applications
QoSPusher.py Python application used to manage QoS from the command line
(Example coming soon)
QoSPath.py QoSPath is a python application that utilizes cirtcuitpusher.py to push QoS state along a specific circuit in a network.
Example
*sorry for the typos in the screen shots
Network
Mininet Topo Used #sudo mn --topo linear,4 --switch ovsk --controller=remote,ip= --ipbase=10.0.0.0/8
Enable QoS on the controller:
1. Visit the tools seciton and click on "Quality of Service"
2. Verify that the module is enabled.
- From the topology above, say we want to Rate-Limit traffic from Host 10.0.0.1 to Host 10.0.0.2 to only 2Mbps.
- The links suggest we need to place 2 flows, one in switch 00:00:00:00:00:00:01
- and another in 00:00:00:00:00:00:02 that enqueue the packets that match Host 1 to the rate-limited queue.
- Knowing queue 2 on these switches rate limit the flows, we can use the QoSPusher application to push 2 policies that do just that.
#./qospusher.py add policy ' {"name": "Enqueue 2:2 s1?, "protocol":"6?,"eth-type": "0×0800?, "ingress-port": "1?,"ip-src":"10.0.0.1?, "sw": "00:00:00:00:00:00:00:01?,"queue":"2?,"enqueue-port":"2?}' 127.0.0.1 QoSHTTPHelper Trying to connect to 127.0.0.1... Trying server... Connected to: 127.0.0.1:8080 Connection Succesful Trying to add policy {"name": "Enqueue 2:2 s1?, "protocol":"6?,"eth-type": "0×0800?, "ingress-port": "1?,"ip-src":"10.0.0.1?, "sw": "00:00:00:00:00:00:00:01?,"queue":"2?,"enqueue-port":"2?} [CONTROLLER]: {"status" : "Trying to Policy: Enqueue 2:2 s1?} Writing policy to qos.state.json { "services": [], "policies": [ " {\"name\": \"Enqueue 2:2 s1\", \"protocol\":\"6\",\"eth-type\": \"0x0800\", \"ingress-port\": \"1\",\"ip-src\":\"10.0.0.1\", \"sw\": \"00:00:00:00:00:00:00:01\",\"queue\":\"2\",\"enqueue-port\":\"2\"}" ]} Closed connection successfully
#./qospusher.py add policy ' {"name": "Enqueue 1:2 s2?, "protocol":"6?,"eth-type": "0×0800?, "ingress-port": "1?,"ip-src":"10.0.0.1?, "sw": "00:00:00:00:00:00:00:02?,"queue":"2?,"enqueue-port":"1?}' 127.0.0.1 QoSHTTPHelper Trying to connect to 127.0.0.1... Trying server... Connected to: 127.0.0.1:8080 Connection Succesful Trying to add policy {"name": "Enqueue 1:2 s2?, "protocol":"6?,"eth-type": "0×0800?, "ingress-port": "1?,"ip-src":"10.0.0.1?, "sw": "00:00:00:00:00:00:00:02?,"queue":"2?,"enqueue-port":"1?} [CONTROLLER]: {"status" : "Trying to Policy: Enqueue 1:2 s2?} Writing policy to qos.state.json { "services": [], "policies": [ " {\"name\": \"Enqueue 2:2 s1\", \"protocol\":\"6\",\"eth-type\": \"0x0800\", \"ingress-port\": \"1\",\"ip-src\":\"10.0.0.1\", \"sw\": \"00:00:00:00:00:00:00:01\",\"queue\":\"2\",\"enqueue-port\":\"2\"}", " {\"name\": \"Enqueue 1:2 s2\", \"protocol\":\"6\",\"eth-type\": \"0x0800\", \"ingress-port\": \"1\",\"ip-src\":\"10.0.0.1\", \"sw\": \"00:00:00:00:00:00:00:02\",\"queue\":\"2\",\"enqueue-port\":\"1\"}" ]} Closed connection successfully
Take a look in the Browser to make sure it was taken
Verify the flows work, using iperf, from h1 --> h2
Iperf shows that the bandwith is limited to ~2Mbps. See below for counter iperf test to verify h2 -->
Verify the opposite direction is unchanged. (getting ~30mbps benchmark )
The set-up of the queues on OVS was left out of this example. but the basic setup is as follows:
- Give 10GB bandwidth to the port (thats what it supports)
- Add a qos record with 3 queues on it
- 1st queue, q0 is default, give it a max of 10GB
- 2nd queue is q1, rate limited it to 20Mbps
- 3rd queue is q2, rate limited to 2Mbps.
Ultimately QoS and OpenFlow are at their beginning still, it will mature as the latter specs become adopted by hardware and virtual switches. The improvement and adoption of OFConfig will also play a major role in this realm. But this is used as a simple implementation of how it may work. Integrating OFConfig would be an exciting feature.