Ryu控制器部署及其与Rest API接口调用问题解决
来源:互联网 发布:淘宝实名账号购买 编辑:程序博客网 时间:2024/06/05 21:15
系统环境为Ubuntu14.04
所用restful接口调用软件为postman
首先要安装部署Ryu控制器,这个很多人没成功我觉得其实主要是前面的基本环境和依赖包要先搞好,即以下步骤一所示:
步骤一:依赖环境安装
sudo apt-get updatesudo apt-get install gitsudo apt-get install Python-pip build-essential python-dev libxml2-dev libxslt1-dev python-paramiko python-webob python-routessudo pip install -U pip six oslo.config==3.0.0 eventlet msgpack-python
步骤二:Ryu安装
git clone git://github.com/osrg/ryu.gitcd ./ryupython ./setup.py install
接着是使用Postman调用restful接口,然而是要自己从GIthub上下载两个组件的Python文件并运行才可以正常通过Rest API接口进行GET或者POST等操作。两个组件Python文件如下,也可自行从GitHUB上下载。
# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or# implied.# See the License for the specific language governing permissions and# limitations under the License.from ryu.base import app_managerfrom ryu.controller import ofp_eventfrom ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHERfrom ryu.controller.handler import set_ev_clsfrom ryu.ofproto import ofproto_v1_3from ryu.lib.packet import packetfrom ryu.lib.packet import ethernetfrom ryu.lib.packet import ether_typesclass SimpleSwitch13(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] def __init__(self, *args, **kwargs): super(SimpleSwitch13, self).__init__(*args, **kwargs) self.mac_to_port = {} @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def switch_features_handler(self, ev): datapath = ev.msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser # install table-miss flow entry # # We specify NO BUFFER to max_len of the output action due to # OVS bug. At this moment, if we specify a lesser number, e.g., # 128, OVS will send Packet-In with invalid buffer_id and # truncated packet data. In that case, we cannot output packets # correctly. The bug has been fixed in OVS v2.1.0. match = parser.OFPMatch() actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions) def add_flow(self, datapath, priority, match, actions, buffer_id=None): ofproto = datapath.ofproto parser = datapath.ofproto_parser inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] if buffer_id: mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, priority=priority, match=match, instructions=inst) else: mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst) datapath.send_msg(mod) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def _packet_in_handler(self, ev): # If you hit this you might want to increase # the "miss_send_length" of your switch if ev.msg.msg_len < ev.msg.total_len: self.logger.debug("packet truncated: only %s of %s bytes", ev.msg.msg_len, ev.msg.total_len) msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] if eth.ethertype == ether_types.ETH_TYPE_LLDP: # ignore lldp packet return dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) # learn a mac address to avoid FLOOD next time. self.mac_to_port[dpid][src] = in_port if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD actions = [parser.OFPActionOutput(out_port)] # install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: match = parser.OFPMatch(in_port=in_port, eth_dst=dst) # verify if we have a valid buffer_id, if yes avoid to send both # flow_mod & packet_out if msg.buffer_id != ofproto.OFP_NO_BUFFER: self.add_flow(datapath, 1, match, actions, msg.buffer_id) return else: self.add_flow(datapath, 1, match, actions) data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) datapath.send_msg(out)empty
# Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or# implied.# See the License for the specific language governing permissions and# limitations under the License.import loggingimport jsonimport astfrom ryu.base import app_managerfrom ryu.controller import ofp_eventfrom ryu.controller import dpsetfrom ryu.controller.handler import MAIN_DISPATCHERfrom ryu.controller.handler import set_ev_clsfrom ryu.exception import RyuExceptionfrom ryu.ofproto import ofproto_v1_0from ryu.ofproto import ofproto_v1_2from ryu.ofproto import ofproto_v1_3from ryu.ofproto import ofproto_v1_4from ryu.ofproto import ofproto_v1_5from ryu.lib import ofctl_v1_0from ryu.lib import ofctl_v1_2from ryu.lib import ofctl_v1_3from ryu.lib import ofctl_v1_4from ryu.lib import ofctl_v1_5from ryu.app.wsgi import ControllerBasefrom ryu.app.wsgi import Responsefrom ryu.app.wsgi import WSGIApplicationLOG = logging.getLogger('ryu.app.ofctl_rest')# supported ofctl versions in this restful appsupported_ofctl = { ofproto_v1_0.OFP_VERSION: ofctl_v1_0, ofproto_v1_2.OFP_VERSION: ofctl_v1_2, ofproto_v1_3.OFP_VERSION: ofctl_v1_3, ofproto_v1_4.OFP_VERSION: ofctl_v1_4, ofproto_v1_5.OFP_VERSION: ofctl_v1_5,}# REST API## Retrieve the switch stats## get the list of all switches# GET /stats/switches## get the desc stats of the switch# GET /stats/desc/## get flows desc stats of the switch# GET /stats/flowdesc/ ## get flows desc stats of the switch filtered by the fields# POST /stats/flowdesc/ ## get flows stats of the switch# GET /stats/flow/ ## get flows stats of the switch filtered by the fields# POST /stats/flow/ ## get aggregate flows stats of the switch# GET /stats/aggregateflow/ ## get aggregate flows stats of the switch filtered by the fields# POST /stats/aggregateflow/ ## get table stats of the switch# GET /stats/table/ ## get table features stats of the switch# GET /stats/tablefeatures/ ## get ports stats of the switch# GET /stats/port/ [/ ]# Note: Specification of port number is optional## get queues stats of the switch# GET /stats/queue/ [/ [/ ]]# Note: Specification of port number and queue id are optional# If you want to omitting the port number and setting the queue id,# please specify the keyword "ALL" to the port number# e.g. GET /stats/queue/1/ALL/1## get queues config stats of the switch# GET /stats/queueconfig/ [/ ]# Note: Specification of port number is optional## get queues desc stats of the switch# GET /stats/queuedesc/ [/ [/ ]]# Note: Specification of port number and queue id are optional# If you want to omitting the port number and setting the queue id,# please specify the keyword "ALL" to the port number# e.g. GET /stats/queuedesc/1/ALL/1## get meter features stats of the switch# GET /stats/meterfeatures/ ## get meter config stats of the switch# GET /stats/meterconfig/ [/ ]# Note: Specification of meter id is optional## get meter desc stats of the switch# GET /stats/meterdesc/ [/ ]# Note: Specification of meter id is optional## get meters stats of the switch# GET /stats/meter/ [/ ]# Note: Specification of meter id is optional## get group features stats of the switch# GET /stats/groupfeatures/ ## get groups desc stats of the switch# GET /stats/groupdesc/ [/ ]# Note: Specification of group id is optional (OpenFlow 1.5 or later)## get groups stats of the switch# GET /stats/group/ [/ ]# Note: Specification of group id is optional## get ports description of the switch# GET /stats/portdesc/ [/ ]# Note: Specification of port number is optional (OpenFlow 1.5 or later)# Update the switch stats## add a flow entry# POST /stats/flowentry/add## modify all matching flow entries# POST /stats/flowentry/modify## modify flow entry strictly matching wildcards and priority# POST /stats/flowentry/modify_strict## delete all matching flow entries# POST /stats/flowentry/delete## delete flow entry strictly matching wildcards and priority# POST /stats/flowentry/delete_strict## delete all flow entries of the switch# DELETE /stats/flowentry/clear/ ## add a meter entry# POST /stats/meterentry/add## modify a meter entry# POST /stats/meterentry/modify## delete a meter entry# POST /stats/meterentry/delete## add a group entry# POST /stats/groupentry/add## modify a group entry# POST /stats/groupentry/modify## delete a group entry# POST /stats/groupentry/delete## modify behavior of the physical port# POST /stats/portdesc/modify## modify role of controller# POST /stats/role### send a experimeter message# POST /stats/experimenter/ class CommandNotFoundError(RyuException): message = 'No such command : %(cmd)s'class PortNotFoundError(RyuException): message = 'No such port info: %(port_no)s'def stats_method(method): def wrapper(self, req, dpid, *args, **kwargs): # Get datapath instance from DPSet try: dp = self.dpset.get(int(str(dpid), 0)) except ValueError: LOG.exception('Invalid dpid: %s', dpid) return Response(status=400) if dp is None: LOG.error('No such Datapath: %s', dpid) return Response(status=404) # Get lib/ofctl_* module try: ofctl = supported_ofctl.get(dp.ofproto.OFP_VERSION) except KeyError: LOG.exception('Unsupported OF version: %s', dp.ofproto.OFP_VERSION) return Response(status=501) # Invoke StatsController method try: ret = method(self, req, dp, ofctl, *args, **kwargs) return Response(content_type='application/json', body=json.dumps(ret)) except ValueError: LOG.exception('Invalid syntax: %s', req.body) return Response(status=400) except AttributeError: LOG.exception('Unsupported OF request in this version: %s', dp.ofproto.OFP_VERSION) return Response(status=501) return wrapperdef command_method(method): def wrapper(self, req, *args, **kwargs): # Parse request json body try: if req.body: # We use ast.literal_eval() to parse request json body # instead of json.loads(). # Because we need to parse binary format body # in send_experimenter(). body = ast.literal_eval(req.body.decode('utf-8')) else: body = {} except SyntaxError: LOG.exception('Invalid syntax: %s', req.body) return Response(status=400) # Get datapath_id from request parameters dpid = body.get('dpid', None) if not dpid: try: dpid = kwargs.pop('dpid') except KeyError: LOG.exception('Cannot get dpid from request parameters') return Response(status=400) # Get datapath instance from DPSet try: dp = self.dpset.get(int(str(dpid), 0)) except ValueError: LOG.exception('Invalid dpid: %s', dpid) return Response(status=400) if dp is None: LOG.error('No such Datapath: %s', dpid) return Response(status=404) # Get lib/ofctl_* module try: ofctl = supported_ofctl.get(dp.ofproto.OFP_VERSION) except KeyError: LOG.exception('Unsupported OF version: version=%s', dp.ofproto.OFP_VERSION) return Response(status=501) # Invoke StatsController method try: method(self, req, dp, ofctl, body, *args, **kwargs) return Response(status=200) except ValueError: LOG.exception('Invalid syntax: %s', req.body) return Response(status=400) except AttributeError: LOG.exception('Unsupported OF request in this version: %s', dp.ofproto.OFP_VERSION) return Response(status=501) except CommandNotFoundError as e: LOG.exception(e.message) return Response(status=404) except PortNotFoundError as e: LOG.exception(e.message) return Response(status=404) return wrapperclass StatsController(ControllerBase): def __init__(self, req, link, data, **config): super(StatsController, self).__init__(req, link, data, **config) self.dpset = data['dpset'] self.waiters = data['waiters'] def get_dpids(self, req, **_kwargs): dps = list(self.dpset.dps.keys()) body = json.dumps(dps) return Response(content_type='application/json', body=body) @stats_method def get_desc_stats(self, req, dp, ofctl, **kwargs): return ofctl.get_desc_stats(dp, self.waiters) @stats_method def get_flow_desc(self, req, dp, ofctl, **kwargs): flow = req.json if req.body else {} return ofctl.get_flow_desc(dp, self.waiters, flow) @stats_method def get_flow_stats(self, req, dp, ofctl, **kwargs): flow = req.json if req.body else {} return ofctl.get_flow_stats(dp, self.waiters, flow) @stats_method def get_aggregate_flow_stats(self, req, dp, ofctl, **kwargs): flow = req.json if req.body else {} return ofctl.get_aggregate_flow_stats(dp, self.waiters, flow) @stats_method def get_table_stats(self, req, dp, ofctl, **kwargs): return ofctl.get_table_stats(dp, self.waiters) @stats_method def get_table_features(self, req, dp, ofctl, **kwargs): return ofctl.get_table_features(dp, self.waiters) @stats_method def get_port_stats(self, req, dp, ofctl, port=None, **kwargs): if port == "ALL": port = None return ofctl.get_port_stats(dp, self.waiters, port) @stats_method def get_queue_stats(self, req, dp, ofctl, port=None, queue_id=None, **kwargs): if port == "ALL": port = None if queue_id == "ALL": queue_id = None return ofctl.get_queue_stats(dp, self.waiters, port, queue_id) @stats_method def get_queue_config(self, req, dp, ofctl, port=None, **kwargs): if port == "ALL": port = None return ofctl.get_queue_config(dp, self.waiters, port) @stats_method def get_queue_desc(self, req, dp, ofctl, port=None, queue=None, **_kwargs): if port == "ALL": port = None if queue == "ALL": queue = None return ofctl.get_queue_desc(dp, self.waiters, port, queue) @stats_method def get_meter_features(self, req, dp, ofctl, **kwargs): return ofctl.get_meter_features(dp, self.waiters) @stats_method def get_meter_config(self, req, dp, ofctl, meter_id=None, **kwargs): if meter_id == "ALL": meter_id = None return ofctl.get_meter_config(dp, self.waiters, meter_id) @stats_method def get_meter_desc(self, req, dp, ofctl, meter_id=None, **kwargs): if meter_id == "ALL": meter_id = None return ofctl.get_meter_desc(dp, self.waiters, meter_id) @stats_method def get_meter_stats(self, req, dp, ofctl, meter_id=None, **kwargs): if meter_id == "ALL": meter_id = None return ofctl.get_meter_stats(dp, self.waiters, meter_id) @stats_method def get_group_features(self, req, dp, ofctl, **kwargs): return ofctl.get_group_features(dp, self.waiters) @stats_method def get_group_desc(self, req, dp, ofctl, group_id=None, **kwargs): if dp.ofproto.OFP_VERSION < ofproto_v1_5.OFP_VERSION: return ofctl.get_group_desc(dp, self.waiters) else: return ofctl.get_group_desc(dp, self.waiters, group_id) @stats_method def get_group_stats(self, req, dp, ofctl, group_id=None, **kwargs): if group_id == "ALL": group_id = None return ofctl.get_group_stats(dp, self.waiters, group_id) @stats_method def get_port_desc(self, req, dp, ofctl, port_no=None, **kwargs): if dp.ofproto.OFP_VERSION < ofproto_v1_5.OFP_VERSION: return ofctl.get_port_desc(dp, self.waiters) 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 = { 'add': dp.ofproto.OFPFC_ADD, 'modify': dp.ofproto.OFPFC_MODIFY, 'modify_strict': dp.ofproto.OFPFC_MODIFY_STRICT, 'delete': dp.ofproto.OFPFC_DELETE, 'delete_strict': dp.ofproto.OFPFC_DELETE_STRICT, } mod_cmd = cmd_convert.get(cmd, None) if mod_cmd is None: raise CommandNotFoundError(cmd=cmd) ofctl.mod_flow_entry(dp, flow, mod_cmd) @command_method def delete_flow_entry(self, req, dp, ofctl, flow, **kwargs): if ofproto_v1_0.OFP_VERSION == dp.ofproto.OFP_VERSION: flow = {} else: flow = {'table_id': dp.ofproto.OFPTT_ALL} ofctl.mod_flow_entry(dp, flow, dp.ofproto.OFPFC_DELETE) @command_method def mod_meter_entry(self, req, dp, ofctl, meter, cmd, **kwargs): cmd_convert = { 'add': dp.ofproto.OFPMC_ADD, 'modify': dp.ofproto.OFPMC_MODIFY, 'delete': dp.ofproto.OFPMC_DELETE, } mod_cmd = cmd_convert.get(cmd, None) if mod_cmd is None: raise CommandNotFoundError(cmd=cmd) ofctl.mod_meter_entry(dp, meter, mod_cmd) @command_method def mod_group_entry(self, req, dp, ofctl, group, cmd, **kwargs): cmd_convert = { 'add': dp.ofproto.OFPGC_ADD, 'modify': dp.ofproto.OFPGC_MODIFY, 'delete': dp.ofproto.OFPGC_DELETE, } mod_cmd = cmd_convert.get(cmd, None) if mod_cmd is None: raise CommandNotFoundError(cmd=cmd) ofctl.mod_group_entry(dp, group, mod_cmd) @command_method def mod_port_behavior(self, req, dp, ofctl, port_config, cmd, **kwargs): port_no = port_config.get('port_no', None) port_no = int(str(port_no), 0) port_info = self.dpset.port_state[int(dp.id)].get(port_no) if port_info: port_config.setdefault('hw_addr', port_info.hw_addr) if dp.ofproto.OFP_VERSION < ofproto_v1_4.OFP_VERSION: port_config.setdefault('advertise', port_info.advertised) else: port_config.setdefault('properties', port_info.properties) else: raise PortNotFoundError(port_no=port_no) if cmd != 'modify': raise CommandNotFoundError(cmd=cmd) ofctl.mod_port_behavior(dp, port_config) @command_method def send_experimenter(self, req, dp, ofctl, exp, **kwargs): ofctl.send_experimenter(dp, exp) @command_method def set_role(self, req, dp, ofctl, role, **kwargs): ofctl.set_role(dp, role)class RestStatsApi(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION, ofproto_v1_2.OFP_VERSION, ofproto_v1_3.OFP_VERSION, ofproto_v1_4.OFP_VERSION, ofproto_v1_5.OFP_VERSION] _CONTEXTS = { 'dpset': dpset.DPSet, 'wsgi': WSGIApplication } def __init__(self, *args, **kwargs): super(RestStatsApi, self).__init__(*args, **kwargs) self.dpset = kwargs['dpset'] wsgi = kwargs['wsgi'] self.waiters = {} self.data = {} self.data['dpset'] = self.dpset self.data['waiters'] = self.waiters mapper = wsgi.mapper wsgi.registory['StatsController'] = self.data path = '/stats' uri = path + '/switches' mapper.connect('stats', uri, controller=StatsController, action='get_dpids', conditions=dict(method=['GET'])) uri = path + '/desc/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_desc_stats', conditions=dict(method=['GET'])) uri = path + '/flowdesc/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_flow_stats', conditions=dict(method=['GET', 'POST'])) uri = path + '/flow/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_flow_stats', conditions=dict(method=['GET', 'POST'])) uri = path + '/aggregateflow/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_aggregate_flow_stats', conditions=dict(method=['GET', 'POST'])) uri = path + '/table/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_table_stats', conditions=dict(method=['GET'])) uri = path + '/tablefeatures/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_table_features', conditions=dict(method=['GET'])) uri = path + '/port/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_port_stats', conditions=dict(method=['GET'])) uri = path + '/port/{dpid}/{port}' mapper.connect('stats', uri, controller=StatsController, action='get_port_stats', conditions=dict(method=['GET'])) uri = path + '/queue/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_stats', conditions=dict(method=['GET'])) uri = path + '/queue/{dpid}/{port}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_stats', conditions=dict(method=['GET'])) uri = path + '/queue/{dpid}/{port}/{queue_id}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_stats', conditions=dict(method=['GET'])) uri = path + '/queueconfig/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_config', conditions=dict(method=['GET'])) uri = path + '/queueconfig/{dpid}/{port}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_config', conditions=dict(method=['GET'])) uri = path + '/queuedesc/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_desc', conditions=dict(method=['GET'])) uri = path + '/queuedesc/{dpid}/{port}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_desc', conditions=dict(method=['GET'])) uri = path + '/queuedesc/{dpid}/{port}/{queue}' mapper.connect('stats', uri, controller=StatsController, action='get_queue_desc', conditions=dict(method=['GET'])) uri = path + '/meterfeatures/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_features', conditions=dict(method=['GET'])) uri = path + '/meterconfig/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_config', conditions=dict(method=['GET'])) uri = path + '/meterconfig/{dpid}/{meter_id}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_config', conditions=dict(method=['GET'])) uri = path + '/meterdesc/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_desc', conditions=dict(method=['GET'])) uri = path + '/meterdesc/{dpid}/{meter_id}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_desc', conditions=dict(method=['GET'])) uri = path + '/meter/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_stats', conditions=dict(method=['GET'])) uri = path + '/meter/{dpid}/{meter_id}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_stats', conditions=dict(method=['GET'])) uri = path + '/groupfeatures/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_group_features', conditions=dict(method=['GET'])) uri = path + '/groupdesc/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_group_desc', conditions=dict(method=['GET'])) uri = path + '/groupdesc/{dpid}/{group_id}' mapper.connect('stats', uri, controller=StatsController, action='get_group_desc', conditions=dict(method=['GET'])) uri = path + '/group/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_group_stats', conditions=dict(method=['GET'])) uri = path + '/group/{dpid}/{group_id}' mapper.connect('stats', uri, controller=StatsController, action='get_group_stats', conditions=dict(method=['GET'])) uri = path + '/portdesc/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_port_desc', conditions=dict(method=['GET'])) uri = path + '/portdesc/{dpid}/{port_no}' mapper.connect('stats', uri, 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', conditions=dict(method=['POST'])) uri = path + '/flowentry/clear/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='delete_flow_entry', conditions=dict(method=['DELETE'])) uri = path + '/meterentry/{cmd}' mapper.connect('stats', uri, controller=StatsController, action='mod_meter_entry', conditions=dict(method=['POST'])) uri = path + '/groupentry/{cmd}' mapper.connect('stats', uri, controller=StatsController, action='mod_group_entry', conditions=dict(method=['POST'])) uri = path + '/portdesc/{cmd}' mapper.connect('stats', uri, controller=StatsController, action='mod_port_behavior', conditions=dict(method=['POST'])) uri = path + '/experimenter/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='send_experimenter', conditions=dict(method=['POST'])) uri = path + '/role' mapper.connect('stats', uri, controller=StatsController, action='set_role', conditions=dict(method=['POST'])) @set_ev_cls([ofp_event.EventOFPStatsReply, ofp_event.EventOFPDescStatsReply, ofp_event.EventOFPFlowStatsReply, ofp_event.EventOFPAggregateStatsReply, ofp_event.EventOFPTableStatsReply, ofp_event.EventOFPTableFeaturesStatsReply, ofp_event.EventOFPPortStatsReply, ofp_event.EventOFPQueueStatsReply, ofp_event.EventOFPQueueDescStatsReply, ofp_event.EventOFPMeterStatsReply, ofp_event.EventOFPMeterFeaturesStatsReply, ofp_event.EventOFPMeterConfigStatsReply, ofp_event.EventOFPGroupStatsReply, ofp_event.EventOFPGroupFeaturesStatsReply, ofp_event.EventOFPGroupDescStatsReply, ofp_event.EventOFPPortDescStatsReply ], MAIN_DISPATCHER) def stats_reply_handler(self, ev): msg = ev.msg dp = msg.datapath if dp.id not in self.waiters: return if msg.xid not in self.waiters[dp.id]: return lock, msgs = self.waiters[dp.id][msg.xid] msgs.append(msg) flags = 0 if dp.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION: flags = dp.ofproto.OFPSF_REPLY_MORE elif dp.ofproto.OFP_VERSION == ofproto_v1_2.OFP_VERSION: flags = dp.ofproto.OFPSF_REPLY_MORE elif dp.ofproto.OFP_VERSION >= ofproto_v1_3.OFP_VERSION: flags = dp.ofproto.OFPMPF_REPLY_MORE if msg.flags & flags: return del self.waiters[dp.id][msg.xid] lock.set() @set_ev_cls([ofp_event.EventOFPSwitchFeatures, ofp_event.EventOFPQueueGetConfigReply, ofp_event.EventOFPRoleReply, ], MAIN_DISPATCHER) def features_reply_handler(self, ev): msg = ev.msg dp = msg.datapath if dp.id not in self.waiters: return if msg.xid not in self.waiters[dp.id]: return lock, msgs = self.waiters[dp.id][msg.xid] msgs.append(msg) del self.waiters[dp.id][msg.xid] lock.set()
然后就可以启用Ryu相关组件并通过Rest API接口交互:
ryu-manager ofctl_rest.py simple_switch_13.py
阅读全文
1 0
- Ryu控制器部署及其与Rest API接口调用问题解决
- RYU REST API学习-调用示例
- Ryu基本操作的REST API调用示例
- Ryu基本操作的REST API调用示例
- RYU REST API学习-基本概念
- RYU REST API学习-应用实践
- JavaScript+Html 调用Wcf Rest Api接口
- JAVA模拟浏览器调用rest api接口
- arcgis rest api 离线部署与应用
- RYU实战,REST API流表控制(1)
- RYU实战,REST API流表控制(2)
- RYU的REST API 获取拓扑发现结果
- C#调用REST API
- C#调用REST API
- magento rest api 调用
- magento rest api 调用!
- magento rest api 调用
- 调用marathon rest API
- 机器学习笔记-第二章 多变量线性回归
- 关于项目中web.xml配置文件里面的spring的配置contextConfigLocation
- 一致性hash
- navicat连接虚拟机中的数据库
- 【Kotlin】Kotlin与Java反射实践
- Ryu控制器部署及其与Rest API接口调用问题解决
- 量化投资
- PAT乙级 1050. 螺旋矩阵(25)
- matlab初级
- [leetcode]627. Swap Salary
- shell中的eval以及与 反引号``、$()的区别
- 支持向量机(SVM)
- Android Webview 软键盘遮挡输入框
- sacla(1)----- 简介及安装