Static Flow Pusher API pre-v1.0

What is Static Flow Pusher?

(info)

This documentation is for all Floodlight versions pre-v1.0, such as v0.9 and v0.91. If you haven't already, please consider upgrading to Floodlight v1.0, which has separate documentation here.

Static Flow Pusher is a Floodlight module, exposed via REST API, that allows a user to manually insert flows into an OpenFlow network.

Proactive vs Reactive Flow Insertion

OpenFlow supports two methods of flow insertion: proactive and reactive. Reactive flow insertion occurs when a packet reaches an OpenFlow switch without a matching flow. The packet is sent to the controller, which evaluates it, adds the appropriate flows, and lets the switch continue its forwarding. Alternatively, flows can be inserted proactively by the controller in switches before packets arrive.

Floodlight supports both mechanisms of flow insertion. Static Flow Pusher is generally useful for proactive flow insertion.

Note that by default, Floodlight loads the Forwarding module which does reactive flow pushing. If you would like to exclusively use static flows, you must remove Forwarding from the floodlight.properties file.

How to Use It?

API Summary

URI 

Description 

Arguments 

/wm/staticflowentrypusher/json

Add/Delete static flow

HTTP POST data (add flow), HTTP DELETE (for deletion)

/wm/staticflowentrypusher/list/<switch>/json

List static flows for a switch or all switches

switch: Valid Switch DPID (XX:XX:XX:XX:XX:XX:XX:XX) or "all"

/wm/staticflowentrypusher/clear/<switch>/json

Clear static flows for a switch or all switches

switch: Valid Switch DPID (XX:XX:XX:XX:XX:XX:XX:XX) or "all"

Adding a static flow

Static Flow Pusher is accessible via a REST api so there are multiple ways to access it. For example, to insert a flow on switch 1 that takes packets from port 1 and outputs them on port 2, you can simply use a curl command. The second command will dump the flow so you can see it set.

curl -d '{"switch": "00:00:00:00:00:00:00:01", "name":"flow-mod-1", "priority":"32768", "ingress-port":"1","active":"true", "actions":"output=2"}' http://<controller_ip>:8080/wm/staticflowentrypusher/json

curl http://<controller_ip>:8080/wm/core/switch/1/flow/json;

Deleting a static flow

To delete a static flow you send an HTTP DELETE that includes the name of the flow.

curl -X DELETE -d '{"name":"flow-mod-1"}' http://<controller_ip>:8080/wm/staticflowentrypusher/json

Possible properties of a flow entry:

Key 

Value 

Notes 

switch

<switch ID>

ID of the switch (data path) that this rule should be added to 
xx:xx:xx:xx:xx:xx:xx:xx

name

<string>

Name of the flow entry, this is the primary key, it MUST be unique

actions

<key>=<value>

See table of actions below 
Specify multiple actions using a comma-separated list 
Specifying no actions will cause the packets to be dropped

priority

<number>

default is 32767 
maximum value is 32767

active

<boolean>

 

wildcards

 

 

ingress-port

<number>

switch port on which the packet is received 
Can be hexadecimal (with leading 0x) or decimal

src-mac

<mac address>

xx:xx:xx:xx:xx:xx

dst-mac

<mac address>

xx:xx:xx:xx:xx:xx

vlan-id

<number>

Can be hexadecimal (with leading 0x) or decimal

vlan-priority

<number>

Can be hexadecimal (with leading 0x) or decimal

ether-type

<number>

Can be hexadecimal (with leading 0x) or decimal

tos-bits

<number>

Can be hexadecimal (with leading 0x) or decimal

protocol

<number>

Can be hexadecimal (with leading 0x) or decimal

src-ip

<ip address>

xx.xx.xx.xx

dst-ip

<ip address>

xx.xx.xx.xx

src-port

<number>

Can be hexadecimal (with leading 0x) or decimal

dst-port

<number>

Can be hexadecimal (with leading 0x) or decimal

Possible actions within the "action" field:

Key 

Value

Notes

output

<number> 
all 
controller 
local 
ingress-port 
normal 
flood

no "drop" option 
(instead, specify no action to drop packets) 

enqueue

<number>:<number>

First number is port number, second is queue ID 
Can be hexadecimal (with leading 0x) or decimal

strip-vlan

 

 

set-vlan-id

<number>

Can be hexadecimal (with leading 0x) or decimal

set-vlan-priority

<number>

Can be hexadecimal (with leading 0x) or decimal

set-src-mac

<mac address>

xx:xx:xx:xx:xx:xx

set-dst-mac

<mac address>

xx:xx:xx:xx:xx:xx

set-tos-bits

<number>

 

set-src-ip

<ip address>

xx.xx.xx.xx

set-dst-ip

<ip address>

xx.xx.xx.xx

set-src-port

<number>

Can be hexadecimal (with leading 0x) or decimal

set-dst-port

<number>

Can be hexadecimal (with leading 0x) or decimal

Using Static Flow Pusher in Practice

Static Flow Pusher can we scripted using simple python code to control a network. As an example, set up a simple network in a mininet vm after starting the floodlight controller. The default topology is one switch (s1) and two hosts connected to it (h2 and h3).

sudo mn --controller=remote --ip=<controller ip> --port=6633

The code below will insert a flow from h2 to h3 and one from h3 to h2.

import httplib
import json

class StaticFlowPusher(object):

    def __init__(self, server):
        self.server = server

    def get(self, data):
        ret = self.rest_call({}, 'GET')
        return json.loads(ret[2])

    def set(self, data):
        ret = self.rest_call(data, 'POST')
        return ret[0] == 200

    def remove(self, objtype, data):
        ret = self.rest_call(data, 'DELETE')
        return ret[0] == 200

    def rest_call(self, data, action):
        path = '/wm/staticflowentrypusher/json'
        headers = {
            'Content-type': 'application/json',
            'Accept': 'application/json',
            }
        body = json.dumps(data)
        conn = httplib.HTTPConnection(self.server, 8080)
        conn.request(action, path, body, headers)
        response = conn.getresponse()
        ret = (response.status, response.reason, response.read())
        print ret
        conn.close()
        return ret

pusher = StaticFlowPusher('<insert_controller_ip')

flow1 = {
    'switch':"00:00:00:00:00:00:00:01",
    "name":"flow-mod-1",
    "cookie":"0",
    "priority":"32768",
    "ingress-port":"1",
    "active":"true",
    "actions":"output=flood"
    }

flow2 =	{
    'switch':"00:00:00:00:00:00:00:01",
    "name":"flow-mod-2",
    "cookie":"0",
    "priority":"32768",
    "ingress-port":"2",
    "active":"true",
    "actions":"output=flood"
    }

pusher.set(flow1)
pusher.set(flow2)

To test this out, run a pingtest in the mininet vm (note: you may want to disable the learning switch and other routing code in advance to make sure your static flows are taken).

 mininet> h2 ping h3