I wanted to access a Floodlight OpenFlow Controller from RHEL 6.4. This can be done with cURL http://curl.haxx.se/ or Python.
Some cURL commands that worked in my environment are below.
Some cURL commands that worked in my environment are below.
Get features of switch:
$ curl http://9.23.13.143:8080/wm/core/switch/00:01:XX:XX:XX:XX:XX:XX/features/json | python -m json.tool
$ curl http://9.23.13.143:8080/wm/core/switch/all/features/json | python -m json.tool
$ curl http://9.23.13.143:8080/wm/core/switch/all/port/json | python -m json.tool
Push a flow:
$ curl -d '{"switch": "00:01:XX:XX:XX:XX:XX:XX", "name":"flow-mod-1", "cookie":"0", "priority":"32768", "ingress-port":"50","active":"true", "actions":"output=51"}'
Get flows:
$ curl http://9.23.13.143:8080/wm/staticflowpusher/list/00:01:XX:XX:XX:XX:XX:XX/json
| python -m json.tool
Delete a flow:
$ curl -X DELETE -d '{"name":"flow-mod-1"}' http://<controller_ip>:8080/wm/staticflowpusher/json
The switch can also be managed using Python without cURL. The following script is cobbled together from various others I found, including https://raw.githubusercontent.com/xsited/sdn/master/python/staticflowpusher.py. My version of the script contains changes from the ones I found around the internet so that it works in my environment.
#!/usr/bin/env python
import httplib
import json
class StaticFlowPusher(object):
def __init__(self, server):
self.server = server
def get(self, path, data):
ret = self.rest_call(path, {}, 'GET')
return json.loads(ret[2])
def set(self, path, data):
ret = self.rest_call(path, data, 'POST')
# return ret[0] == 200
def remove(self, path, data):
ret = self.rest_call(path, data, 'DELETE')
# return ret[0] == 200
def rest_call(self, path, data, action):
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
flow1 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-1",
"cookie":"0",
"priority":"32750",
"in_port":"51",
"active":"true"
}
flow3 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-3",
"cookie":"0",
"priority":"32751",
"actions":"output=51",
# "instruction_write_actions":"
# "table":"0x27",
# "ingress-port":"51",
"in_port":"50",
# "eth_vlan_vid":"0x1002",
# "ip_proto":"0x06",
# "output":"51",
# "eth_dst":"00:01:FF:DD:EE:AA:CC:F3",
# "eth_src":"00:01:AA:BB:CC:DD:EE:F1",
# "tp_src":"0x0CBD",
# "tp_dst":"0x0CBE",
# "ipv4_src":"9.1.2.3/24",
# "eth_type":"0x8100",
# "eth-vlan-pcp":"0x3",
# "eth_type":"0x810",
# "eth_vlan_pcp":"0x3",
# "set_vlan_vid":"1002",
# "set_vlan_pcp":"0x4",
# "set_eth_src":"00:01:22:33:44:55:66:F4",
"active":"true"
}
flow4 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-4",
"cookie":"0",
"priority":"32751",
"actions":"output=51",
"in_port":"50",
"active":"true"
}
flow5 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-5",
"cookie":"0",
"priority":"32751",
"actions":"output=50",
"in_port":"51",
"active":"true"
}
switch01 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX"
}
switchpath = '00:01:XX:XX:XX:XX:XX:XX'
pushflowpath = '/wm/staticflowpusher/json'
#getflowpath = '/wm/staticflowpusher/list/00:01:XX:XX:XX:XX:XX:XX/json'
getflowpath = '/wm/staticflowpusher/list/'+switchpath+'/json'
getallflowpath = '/wm/staticflowpusher/list/all/json'
pusher = StaticFlowPusher('127.0.0.1')
print 'pushing flowpath 4'
pusher.set(pushflowpath, flow4)
print 'pushing flowpath 5'
pusher.set(pushflowpath, flow5)
#print 'pushing flowpath 1'
#pusher.set(pushflowpath, flow1)
print 'getting flowpath'
pusher.get(getflowpath, switch01)
print 'getting all flowpaths'
pusher.get(getallflowpath, switch01)
#print 'removing flowpath'
#pusher.remove(pushflowpath, {"name": "flow-mod-3"})
print 'getting flowpath'
pusher.get(getflowpath, switch01)
import httplib
import json
class StaticFlowPusher(object):
def __init__(self, server):
self.server = server
def get(self, path, data):
ret = self.rest_call(path, {}, 'GET')
return json.loads(ret[2])
def set(self, path, data):
ret = self.rest_call(path, data, 'POST')
# return ret[0] == 200
def remove(self, path, data):
ret = self.rest_call(path, data, 'DELETE')
# return ret[0] == 200
def rest_call(self, path, data, action):
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
flow1 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-1",
"cookie":"0",
"priority":"32750",
"in_port":"51",
"active":"true"
}
flow3 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-3",
"cookie":"0",
"priority":"32751",
"actions":"output=51",
# "instruction_write_actions":"
# "table":"0x27",
# "ingress-port":"51",
"in_port":"50",
# "eth_vlan_vid":"0x1002",
# "ip_proto":"0x06",
# "output":"51",
# "eth_dst":"00:01:FF:DD:EE:AA:CC:F3",
# "eth_src":"00:01:AA:BB:CC:DD:EE:F1",
# "tp_src":"0x0CBD",
# "tp_dst":"0x0CBE",
# "ipv4_src":"9.1.2.3/24",
# "eth_type":"0x8100",
# "eth-vlan-pcp":"0x3",
# "eth_type":"0x810",
# "eth_vlan_pcp":"0x3",
# "set_vlan_vid":"1002",
# "set_vlan_pcp":"0x4",
# "set_eth_src":"00:01:22:33:44:55:66:F4",
"active":"true"
}
flow4 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-4",
"cookie":"0",
"priority":"32751",
"actions":"output=51",
"in_port":"50",
"active":"true"
}
flow5 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX",
"name":"flow-mod-5",
"cookie":"0",
"priority":"32751",
"actions":"output=50",
"in_port":"51",
"active":"true"
}
switch01 = {
'switch':"00:01:XX:XX:XX:XX:XX:XX"
}
switchpath = '00:01:XX:XX:XX:XX:XX:XX'
pushflowpath = '/wm/staticflowpusher/json'
#getflowpath = '/wm/staticflowpusher/list/00:01:XX:XX:XX:XX:XX:XX/json'
getflowpath = '/wm/staticflowpusher/list/'+switchpath+'/json'
getallflowpath = '/wm/staticflowpusher/list/all/json'
pusher = StaticFlowPusher('127.0.0.1')
print 'pushing flowpath 4'
pusher.set(pushflowpath, flow4)
print 'pushing flowpath 5'
pusher.set(pushflowpath, flow5)
#print 'pushing flowpath 1'
#pusher.set(pushflowpath, flow1)
print 'getting flowpath'
pusher.get(getflowpath, switch01)
print 'getting all flowpaths'
pusher.get(getallflowpath, switch01)
#print 'removing flowpath'
#pusher.remove(pushflowpath, {"name": "flow-mod-3"})
print 'getting flowpath'
pusher.get(getflowpath, switch01)
Links to related information:
Floodlight and Python documentation.
http://www.openflowhub.org/display/floodlightcontroller/Static+Flow+Pusher+API+%28New%29
https://raw.githubusercontent.com/xsited/sdn/master/python/staticflowpusher.py
https://raw.githubusercontent.com/xsited/sdn/master/python/staticflowpusher.py
Versions:
Python 2.6.6
Linux 2.6.39-400.17.1.el6uek.x86_64
Floodlight v1.0.
OpenFlow 1.0 switch.
OpenFlow 1.0 switch.
No comments:
Post a Comment