高级
How can I measure link bandwidth and latency in Floodlight?
如何在Floodlight里测量连接带宽和延时
通过查询 REST API一个端口特征值查询理想化最大连接带宽。用OpenFlow实现的话需要为网络中的交换机建立阶段性的流状态查询,问题是状态不准确 最好的测量是第三方应用
How can I implement VLANs using Floodlight?
VirtualNetworkFilter 可以实现虚拟子网,他建立了虚拟网络并可以为虚拟网络加入主机。Controller使用主机的 mac 地址来绑定所在的虚拟网络,并允许同一虚拟网络内主机交互。
Listen Address and Port Configuration
监听地址和端口配置
在属性文件中使用如下配置参数,可以改变某一特定服务监听的主机地址和端头
net.floodlightcontroller.restserver.RestApiServer.host
net.floodlightcontroller.restserver.RestApiServer.port
net.floodlightcontroller.core.FloodlightProvider.openflowhost
net.floodlightcontroller.core.FloodlightProvider.openflowport
net.floodlightcontroller.jython.JythonDebugInterface.host
net.floodlightcontroller.jython.JythonDebugInterface.port
Floodlight自带的默认的属性文件(i.e., floodlightdefault.properties) 只指定了服务端口号 然而服务监听的地址是0.0.0.0/0一次设置为接收所有可能的链接。通过设定openflowhost参数,这一参数也可以影响RestApiServer 以及 JythonDebugInterface 服务的监听地址。可以通过明确这些服务的主机参数来修改RestApiServer 和JythonDebugInterface监听的地址。
All 3 servers listen on 192.168.1.1:
net.floodlightcontroller.core.FloodlightProvider.openflowhost = 192.168.1.1
All 3 servers listen on different hosts:
net.floodlightcontroller.restserver.RestApiServer.host = 192.168.1.1
net.floodlightcontroller.core.FloodlightProvider.openflowhost = 192.168.1.2
net.floodlightcontroller.jython.JythonDebugInterface.host = 192.168.1.3
Controller and REST API server listen on 192.168.1.1, Jython server listens on 192.168.1.2:
net.floodlightcontroller.core.FloodlightProvider.openflowhost = 192.168.1.1
net.floodlightcontroller.jython.JythonDebugInterface.host = 192.168.1.2
The Floodlight REST API
一个稳定的REST APIA框架很快就会提出。下面总结的API可能会有小小的改变。
REST API是推荐大家使用Floodlight 的特性开发应用的接口, controller.的8080
端口支持API
一个REST调用的例子是:
curl http://192.168.110.2:8080/wm/core/controller/switches/json
通过REST:提供的其他功能有
URI | Method | Description | Arguments参数 |
/wm/core/switch/all/<statType>/json | GET | Retrieve aggregate stats across all switches检索统计所有交换机的状态 | statType: port, queue, flow, aggregate, desc, table, features |
/wm/core/switch/<switchId>/<statType>/json | GET | Retrieve per switch stats 检索单个交换机的状态 | switchId: Valid Switch DPID (XX:XX:XX:XX:XX:XX:XX:XX) |
/wm/core/controller/switches/json | GET | List of all switch DPIDs connected to the controller 连接 controller的所有交换机的DPIDs列表 | none |
/wm/core/counter/<counterTitle>/json | GET | List of global traffic counters in the controller (across all switches) Controller的所有交换机的全局通信数量 | counterTitle: "all" or something of the form DPID_Port#OFEventL3/4_Type. See CounterStore.java for details. |
/wm/core/counter/<switchId>/<counterName>/json | GET | List of traffic counters per switch
| switchId: Valid Switch DPID |
/wm/core/memory/json | GET | Current controller memory usage当前controller 内存使用 | none |
/wm/topology/links/json | GET | List all the inter-switch links. Note that these are only for switches connected to the same controller. This is not available in the 0.8 release. 连接在一个controller上的.交换机之间的连接列表 | none |
/wm/topology/switchclusters/json | GET | List of all switch clusters connected to the controller. This is not available in the 0.8 release. 连接于 controller上的所有交换机列表 | none |
/wm/topology/external-links/json | GET | Show "external" links, i.e., multi-hop links discovered by BDDP instead of LLDP packets 显示外部链接比如BDDP而不是LLDP 发现的多跳连接 | none |
/wm/topology/links/json | GET | Show DIRECT and TUNNEL links discovered based on LLDP packets 显示基于 LLDP包发现的的DIRECT和TUNNEL连接 | none |
/wm/device/ | GET | List of all devices tracked by the controller. This includes MACs, IPs, and attachment points. Controller追踪到的所有设备列表含MACs, IPs, and attachment points. | Passed as GET parameters: mac (colon-separated hex-encoded), ipv4 (dotted decimal), vlan, dpid attachment point DPID (colon-separated hex-encoded) and port the attachment point port. |
/wm/staticflowentrypusher/json | POST/DELETE | Add/Delete static flow 增加、删除静态流 | HTTP POST data (add flow), HTTP DELETE (for deletion) |
/wm/staticflowentrypusher/list/<switch>/json | GET | 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 | GET | Clear static flows for a switch or all switches清除一个或所有交换机的静态流列表 | switch: Valid Switch DPID (XX:XX:XX:XX:XX:XX:XX:XX) or "all" |
More information available on How to Use Static Flow Pusher API | |||
/networkService/v1.1/tenants/<tenant>/networks/<network> | PUT/POST/DELETE | Creates a new virtual network. Name and ID are required, gateway is optional. 生成一个新的虚拟网络,需要Name and ID,网关可选 | URI argument: tenant: Currently ignored. network: ID (not name) of the network |
/networkService/v1.1/tenants/<tenant>/networks/<network>/ports/<port>/attachment | PUT/DELETE | Attaches a host to a virtual network. 将一台主机连接到一个虚拟网络中 | URI argument: tenant: Currently ignored. network: ID (not name) of the network. port: Logical port name |
/networkService/v1.1/tenants/<tenant>/networks | GET | Shows all networks and their gateway, ID, and hosts mac in json format. 用json格式显示所有网络以及gateway, ID, and hosts mac | URI argument: tenant: Currently ignored. |
More information available on Virtual Network Filter REST API
| |||
/wm/firewall/module/<op>/json | GET | 查询状态设置防火墙可用或不可用状态 | query the status of, enable, and disable the firewall |
/wm/firewall/rules/json | GET/POST/DELETE | GET: None | List all existing rules in json format 用json格式列出所有已存在的规则 生成一个新的防火墙规则,通过规则编号删除一个已有规则 |
More information available on Firewall REST API
|
对于Floodlight 的开发者来说,How to Add Services to a Module. 教你学习怎么为 Floodlight services增加新的 REST APIs at
VirtualNetworkFilter REST API
URI | Method | URI Arguments | Data | Data Fields | Description |
/networkService/v1.1/tenants/{tenant}/networks/{network} | PUT/POST/DELETE | Tenant: Currently ignored | {"network": { "gateway": "<IP>", "name": "<Name>" }}\ | IP: Gateway IP in "1.1.1.1" format, can be null | Creates a new virtual network. Name and ID are required, gateway is optional. 创建一个性的虚拟网络,需要Name 和ID,网关可选 |
/networkService/v1.1/tenants/{tenant}/networks/{network}/ports/{port}/attachment | PUT/DELETE | Tenant: Currently ignored | {"attachment": {"id": "<Network ID>", "mac": "<MAC>"}} | Network ID: Network ID as a string, the one you just created | Attaches a host to a virtual network. 为虚拟网络增加一台主机 |
/networkService/v1.1/tenants/{tenant}/networks | GET | Tenant: Currently ignored | None | None | Shows all networks and their gateway, ID, and hosts mac in json format 用json格式显示所有网络及其网关、ID主机MAC地址 |
创建一个虚拟网路:名字"VirtualNetwork1",,ID: "NetworkId1",,网关 "10.0.0.7"租户为"default" (which is currently ignored).
curl -X PUT -d '{ "network": { "gateway": "10.0.0.7", "name": "virtualNetwork1" } }' http://localhost:8080/networkService/v1.1/tenants/default/networks/NetworkId1
为VirtualNetwork1 增加一个MAC地址是 "00:00:00:00:00:08" 端口号为"port1"的主机。
curl -X PUT -d '{"attachment": {"id": "NetworkId1", "mac": "00:00:00:00:00:08"}}' http://localhost:8080/networkService/v1.1/tenants/default/networks/NetworkId1/ports/port1/attachment
Floodlight 的Static Flow Pusher API
Static Flow Pusher是一个Floodlight 功能模块,通过REST API提供,允许一个用户为一个OpenFlow网络手动添加流
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.
OpenFlow 支持两种流插入方法:主动式和被动式。当一个包到达一个OpenFlow switch,并且没有匹配到任何一个流表项时,会发生被动流插入。数据包会被转发到controller,由controller来决定将它插入到哪个流表项并由switch继续转发。或者在包到达之前controller在switch上主动添加流表项。
Floodlight支持这两种流插入机制。Static Flow Pusher 通常用于主动流插入
默认状态下Floodlight加载的转发块式支持被动插入。如果你想设置自己的静态流格式,就需要修改floodlight的启动配置文件,关掉转发(转发就是被动插入流的功能)
API 综述
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" |
Static Flow Pusher 可以通过REST api 读取,因此有很多种方式取得。例如,为了给在端口1上取数据并在端口2上发送数据的交换机1增加一个流,你可以使用一个简单的curl 命令。第二条命令可以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;
发送一个包含流名字的HTTP DELETE 可以删除
curl -X DELETE -d '{"name":"flow-mod-1"}' http://<controller_ip>:8080/wm/staticflowentrypusher/json
一个流表项可能的属性
Key | Value | Notes |
switch | <switch ID> | ID of the switch (data path) that this rule should be added to 需要添加规则的交换机(data path)的ID |
name | <string> | Name of the flow entry, this is the primary key, it MUST be unique 流条目的名字,是关键值,必须唯一 |
actions | <key>=<value> | See table of actions below 看以下action的表 |
priority | <number> | default is 32767 |
active | <boolean> |
|
wildcards |
|
|
ingress-port | <number> | switch port on which the packet is received 接受数据包的交互机端口十进制或十六进制(0x开头) |
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 |
"action" 字段的可能的行为
Key | Value | Notes |
output | <number> | no "drop" option |
enqueue | <number>:<number> | First number is port number, second is queue ID |
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 |
Static Flow Pusher使我们可以通过简单的python代码来控制一个网络。例如,启动floodlight controller后通过mininet vm来设定一个简单的网络。默认的拓扑是一个交换机 (s1)和两个连在上面的主机 (h2 and h3).
sudo mn --controller=remote --ip=<controller ip> --port=6633
下面的代码将增加一个h2到h3的流和一个的h3到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)
在mininet vm下运行 pingtest测试下。 (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
防火墙 REST 接口
Firewall模块exposes REST interface implemented as RestletRoutable using Rest API Service.
下面是发布的REST方法
URI | Method | URI Arguments | Data | Data Fields | Description |
/wm/firewall/module/<op>/json | GET | op: status, enable, disable, storageRules, subnet-mask | None | None | query the status of, enable, and disable the firewall 查询、启用和关闭防火墙 |
/wm/firewall/rules/json | GET | None | None | None | List all existing rules in json format 列出所有存在的规则 |
| POST | None | {"<field 1>":"<value 1>", "<field 2>":"<value 2>", ...} | "field":"value" pairs below in any order and combination: | Create new firewall rule 生成新的防火墙规则 |
| DELETE | None | {"<ruleid>":"<int>"} | "ruleid": "<int>" | Delete a rule by ruleid 通过规则编号删除一条规则 |
假设controller运行在本机上localhost, 显示防火墙是否可用
curl http://localhost:8080/wm/firewall/module/status/json
开启防火墙,除非 创建一个明确的ALLOW规则,否则就通过默认防火墙拒绝通信
curl http://localhost:8080/wm/firewall/module/enable/json
为通过交换机(00:00:00:00:00:00:00:01)的所有数据流增加一个ALLOW 规则
curl -X POST -d '{"switchid": "00:00:00:00:00:00:00:01"}' http://localhost:8080/wm/firewall/rules/json
在主机 IP 10.0.0.3 和 10.0.1.5之间增加一个ALLOW规则 Not specifying action implies ALLOW rule.
curl -X POST -d '{"src-ip": "10.0.0.3/32"}' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.3/32"}' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.7/32"}' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.7/32"}' http://localhost:8080/wm/firewall/rules/json
在主机MAC00:00:00:00:00:0a 和 00:00:00:00:00:0b之间增加ALLOW
curl -X POST -d '{"src-mac": "00:00:00:00:00:0a"}' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-mac": "00:00:00:00:00:0a"}' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-mac": "00:00:00:00:00:0b"}' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-mac": "00:00:00:00:00:0b"}' http://localhost:8080/wm/firewall/rules/json
Adding an ALLOW rule for ping to work between IP hosts 10.0.0.3 and 10.0.0.7.
curl -X POST -d '{"src-ip": "10.0.0.3/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.3/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.7/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.7/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.3/32", "nw-proto":"ICMP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.3/32", "nw-proto":"ICMP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.7/32", "nw-proto":"ICMP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.7/32", "nw-proto":"ICMP" }' http://localhost:8080/wm/firewall/rules/json
Adding an ALLOW rule for UDP (such as iperf) to work between IP hosts 10.0.0.4 and 10.0.0.10, and then blocking port 5010.
curl -X POST -d '{"src-ip": "10.0.0.4/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.4/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.10/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.10/32", "dl-type":"ARP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.4/32", "nw-proto":"UDP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.4/32", "nw-proto":"UDP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.10/32", "nw-proto":"UDP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.10/32", "nw-proto":"UDP" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.4/32", "nw-proto":"UDP", "tp-src":"5010", "action":"DENY" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.4/32", "nw-proto":"UDP", "tp-dst":"5010", "action":"DENY" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"src-ip": "10.0.0.10/32", "nw-proto":"UDP", "tp-src":"5010", "action":"DENY" }' http://localhost:8080/wm/firewall/rules/json
curl -X POST -d '{"dst-ip": "10.0.0.10/32", "nw-proto":"UDP", "tp-dst":"5010", "action":"DENY
应用
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)
2.2. Circuit Pusher
Circuit Pusher基于SFP,也支持用户主动(proactively)创建转发的单条最短路径。
该模块利用REST API 创建一个在两端点之间的双向链路。支持的语法有
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)
2.2. Circuit Pusher
Circuit Pusher基于SFP,也支持用户主动(proactively)创建转发的单条最短路径。
该模块利用REST API 创建一个在两端点之间的双向链路。支持的语法有
Circuit Pusher使用floodlight rest APIs 来建立一个双向环,例如,基于某一确定优先权的IP地址在连接两个设备的所有的交换机上的永久的流条目
Notes:
1. circuit pusher 当前值创建两个IP结点为终点的环路。though it is straightforward to extend it to create circuits based on CIDR style IP prefixes (e.g., 192.168.0.0/16) as it is supported by Static Flow Pusher.
2. Prior to sending restAPI requests to the circuit pusher,明确的终结点必须为conroller 已知的(i.e., already have sent packets on the network, easy way to assure this is to do a ping (to any target) from the two hosts. Only so will the controller know the attachment point of the devices and thereby compute a route for them.
3. 当前支持的命令行格式如下:
a) circuitpusher.py --controller={IP}:{rest port} --type ip --src {IP} --dst {IP} --add --name {circuit-name}
adds a new circuit between src and dst devices Currently ip circuit is supported. ARP is automatically supported.
Currently a simple circuit record storage is provided in a text file circuits.json in the working directory.
The file is not protected and does not clean itself between controller restarts. The file is needed for correct operation
and the user should make sure deleting the file when floodlight controller is restarted.
b) circuitpusher.py --controller={IP}:{rest port} --delete --name {circuit-name}
deletes a created circuit (as recorded in circuits.json) using the previously given name