-
Notifications
You must be signed in to change notification settings - Fork 0
/
app_3_mac_rest_api.py
99 lines (82 loc) · 4.23 KB
/
app_3_mac_rest_api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import json
import logging
from ryu.app import simple_switch_13
from webob import Response
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.app.wsgi import ControllerBase, WSGIApplication, route
from ryu.lib import dpid as dpid_lib
simple_switch_instance_name = 'simple_switch_api_app'
url = '/simpleswitch/mactable/{dpid}'
class SimpleSwitchRest13(simple_switch_13.SimpleSwitch13):
_CONTEXTS = {'wsgi':WSGIApplication}
def __init__(self, *args, **kwargs):
super(SimpleSwitchRest13, self).__init__(*args, **kwargs)
self.switches = {}
wsgi = kwargs['wsgi']
wsgi.register(SimpleSwitchController, {simple_switch_instance_name:self})
# Register SimpleSwitchController and SimpleSwitchRest13
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
super(SimpleSwitchRest13, self).switch_features_handler(ev)
# Execute his father method first
datapath = ev.msg.datapath
self.switches[datapath.id] = datapath
self.mac_to_port.setdefault(datapath.id, {})
# create switches and mac address table dict
def set_mac_to_port(self, dpid, entry):
# This methon will be called when REST API is called
# by the PUT method.
mac_table = self.mac_to_port.setdefault(dpid, {})
datapath = self.switches.get(dpid)
entry_port = entry['port']
entry_mac = entry['mac']
if datapath is not None:
parser = datapath.ofproto_parser
if entry_port not in mac_table.values():
for mac, port in mac_table.items():
# from the knows device to the new
actions = [parser.OFPActionOutput(entry_port)]
match = parser.OFPMatch(in_port=port, eth_dst=entry_mac)
self.add_flow(datapath, 1, match, actions)
# from the new device to the known
actions = [parser.OFPActionOutput(port)]
match = parser.OFPMatch(in_port=entry_port, eth_dst=mac)
self.add_flow(datapath, 1, match, actions)
mac_table.update({entry_mac:entry_port})
return mac_table
class SimpleSwitchController(ControllerBase):
def __init__(self, req, link, data, **config):
super(SimpleSwitchController, self).__init__(req, link, data, **config)
self.simpl_switch_spp = data[simple_switch_instance_name]
@route('simpleswitch', url, methods=['GET'], requirements={'dpid':dpid_lib.DPID_PATTERN})
def list_mac_table(self, req, **kwargs):
# If the method of http://<server IP>:8080/second-argument is GET,
# the local method will be called.
# or command curl -X GET http://<server IP>:8080/second-argument
# If find the matching datapath, the mac_table will be displayed,
# else will display '404'
simple_switch = self.simpl_switch_spp
dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
if dpid not in simple_switch.mac_to_port:
return Response(status=404)
mac_table = simple_switch.mac_to_port.get(dpid, {})
body = json.dumps(mac_table)
return Response(content_type='application/json', body=body)
@route('simpleswitch', url, methods=['PUT'], requirements={'dpid':dpid_lib.DPID_PATTERN})
def put_mac_table(self, req, **kwargs):
# If the method of http://<server IP>:8080/second-argument is PUT,
# the local method will be called.
# or cammand curl -X PUT -d '{"mac":"", "port":2}' http://<server IP>:8080/second-argument
simple_switch = self.simpl_switch_spp
dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
new_entry = eval(req.body)
if dpid not in simple_switch.mac_to_port:
return Response(status=404)
try:
mac_table = simple_switch.set_mac_to_port(dpid, new_entry)
body = json.dumps(mac_table)
return Response(content_type='application/json', body=body)
except Exception as e:
return Response(status=500)