From 6dfda4a227c493c1aed6c468d763650d21d5acce Mon Sep 17 00:00:00 2001 From: Satoshi Fujimoto Date: Wed, 22 Mar 2017 13:23:07 +0900 Subject: [PATCH] ofctl_rest: Add get role API Signed-off-by: Satoshi Fujimoto Signed-off-by: FUJITA Tomonori --- doc/source/app/ofctl_rest.rst | 66 +++++++++++++++++++++++++++++++++++ ryu/app/ofctl_rest.py | 13 ++++++- ryu/lib/ofctl_utils.py | 19 ++++++++++ ryu/lib/ofctl_v1_2.py | 4 +++ ryu/lib/ofctl_v1_3.py | 4 +++ ryu/lib/ofctl_v1_4.py | 4 +++ ryu/lib/ofctl_v1_5.py | 4 +++ 7 files changed, 113 insertions(+), 1 deletion(-) diff --git a/doc/source/app/ofctl_rest.rst b/doc/source/app/ofctl_rest.rst index 03f4b29f..ffe31321 100644 --- a/doc/source/app/ofctl_rest.rst +++ b/doc/source/app/ofctl_rest.rst @@ -1794,6 +1794,72 @@ Get meter features stats } +Get role +-------- + + Get the current role of the controller from the switch. + + Usage: + + ======= ========================= + Method GET + URI /stats/role/ + ======= ========================= + + Response message body(Openflow1.4 or earlier): + + ============= ============================= ========= + Attribute Description Example + ============= ============================= ========= + dpid Datapath ID 1 + role One of OFPCR_ROLE_* "EQUAL" + generation_id Master Election Generation Id 0 + ============= ============================= ========= + + Response message body(Openflow1.5 or later): + + ============= ============================= ========= + Attribute Description Example + ============= ============================= ========= + dpid Datapath ID 1 + role One of OFPCR_ROLE_* "EQUAL" + short_id ID number for the controller 0 + generation_id Master Election Generation Id 0 + ============= ============================= ========= + + Example of use:: + + $ curl -X GET http://localhost:8080/stats/role/1 + + Response (Openflow1.4 or earlier): + + .. code-block:: javascript + + { + "1": [ + { + "generation_id": 0, + "role": "EQUAL" + } + ] + } + + + Response (Openflow1.5 or later): + + .. code-block:: javascript + + { + "1": [ + { + "generation_id": 0, + "role": "EQUAL", + "short_id": 0 + } + ] + } + + Update the switch stats ======================= diff --git a/ryu/app/ofctl_rest.py b/ryu/app/ofctl_rest.py index 98118dcc..addc8e89 100644 --- a/ryu/app/ofctl_rest.py +++ b/ryu/app/ofctl_rest.py @@ -416,6 +416,10 @@ class StatsController(ControllerBase): else: return ofctl.get_port_desc(dp, self.waiters, port_no) + @stats_method + def get_role(self, req, dp, ofctl, **kwargs): + return ofctl.get_role(dp, self.waiters) + @command_method def mod_flow_entry(self, req, dp, ofctl, flow, cmd, **kwargs): cmd_convert = { @@ -674,6 +678,11 @@ class RestStatsApi(app_manager.RyuApp): controller=StatsController, action='get_port_desc', conditions=dict(method=['GET'])) + uri = path + '/role/{dpid}' + mapper.connect('stats', uri, + controller=StatsController, action='get_role', + conditions=dict(method=['GET'])) + uri = path + '/flowentry/{cmd}' mapper.connect('stats', uri, controller=StatsController, action='mod_flow_entry', @@ -751,7 +760,9 @@ class RestStatsApi(app_manager.RyuApp): lock.set() @set_ev_cls([ofp_event.EventOFPSwitchFeatures, - ofp_event.EventOFPQueueGetConfigReply], MAIN_DISPATCHER) + ofp_event.EventOFPQueueGetConfigReply, + ofp_event.EventOFPRoleReply, + ], MAIN_DISPATCHER) def features_reply_handler(self, ev): msg = ev.msg dp = msg.datapath diff --git a/ryu/lib/ofctl_utils.py b/ryu/lib/ofctl_utils.py index 634df81d..493ca354 100644 --- a/ryu/lib/ofctl_utils.py +++ b/ryu/lib/ofctl_utils.py @@ -266,6 +266,22 @@ def str_to_int(str_num): return int(str(str_num), 0) +def get_role(dp, waiters, to_user): + stats = dp.ofproto_parser.OFPRoleRequest( + dp, dp.ofproto.OFPCR_ROLE_NOCHANGE, generation_id=0) + msgs = [] + send_stats_request(dp, stats, waiters, msgs, LOG) + descs = [] + + for msg in msgs: + d = msg.to_jsondict()[msg.__class__.__name__] + if to_user: + d['role'] = OFCtlUtil(dp.ofproto).ofp_role_to_user(d['role']) + descs.append(d) + + return {str(dp.id): descs} + + class OFCtlUtil(object): def __init__(self, ofproto): @@ -430,3 +446,6 @@ class OFCtlUtil(object): def ofp_role_from_user(self, role): return self._reserved_num_from_user(role, 'OFPCR_ROLE_') + + def ofp_role_to_user(self, role): + return self._reserved_num_to_user(role, 'OFPCR_ROLE_') diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py index f458d767..7dfc7b9e 100644 --- a/ryu/lib/ofctl_v1_2.py +++ b/ryu/lib/ofctl_v1_2.py @@ -763,6 +763,10 @@ def get_port_desc(dp, waiters): return {str(dp.id): descs} +def get_role(dp, waiters, to_user=True): + return ofctl_utils.get_role(dp, waiters, to_user) + + def mod_flow_entry(dp, flow, cmd): cookie = str_to_int(flow.get('cookie', 0)) cookie_mask = str_to_int(flow.get('cookie_mask', 0)) diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py index c52fb644..91ae9a0f 100644 --- a/ryu/lib/ofctl_v1_3.py +++ b/ryu/lib/ofctl_v1_3.py @@ -1042,6 +1042,10 @@ def get_port_desc(dp, waiters, to_user=True): return wrap_dpid_dict(dp, descs, to_user) +def get_role(dp, waiters, to_user=True): + return ofctl_utils.get_role(dp, waiters, to_user) + + def mod_flow_entry(dp, flow, cmd): cookie = str_to_int(flow.get('cookie', 0)) cookie_mask = str_to_int(flow.get('cookie_mask', 0)) diff --git a/ryu/lib/ofctl_v1_4.py b/ryu/lib/ofctl_v1_4.py index f71be3b4..600f9915 100644 --- a/ryu/lib/ofctl_v1_4.py +++ b/ryu/lib/ofctl_v1_4.py @@ -817,6 +817,10 @@ def get_port_desc(dp, waiters, port_no=None, to_user=True): return wrap_dpid_dict(dp, descs, to_user) +def get_role(dp, waiters, to_user=True): + return ofctl_utils.get_role(dp, waiters, to_user) + + def mod_flow_entry(dp, flow, cmd): cookie = str_to_int(flow.get('cookie', 0)) cookie_mask = str_to_int(flow.get('cookie_mask', 0)) diff --git a/ryu/lib/ofctl_v1_5.py b/ryu/lib/ofctl_v1_5.py index abd7e385..1b4b4552 100644 --- a/ryu/lib/ofctl_v1_5.py +++ b/ryu/lib/ofctl_v1_5.py @@ -914,6 +914,10 @@ def get_port_desc(dp, waiters, port_no=None, to_user=True): return wrap_dpid_dict(dp, descs, to_user) +def get_role(dp, waiters, to_user=True): + return ofctl_utils.get_role(dp, waiters, to_user) + + def mod_flow_entry(dp, flow, cmd): cookie = str_to_int(flow.get('cookie', 0)) cookie_mask = str_to_int(flow.get('cookie_mask', 0))