diff options
author | Yuichi Ito <ito.yuichi0@gmail.com> | 2013-12-20 16:10:40 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-12-24 20:38:33 +0900 |
commit | 119990d1eba339e1088cf87b32d39eb3169ddcde (patch) | |
tree | a64b7e874c0cd71cec9083cbc43e5270d798ed95 | |
parent | d30e9da4da4e03161d77df0d049dfa9bebe0457b (diff) |
ofctl_v1_3: support OFPMeterConfigStats
Changes v2 -> v3:
- correct the following description
this patch implements a REST API for OFPMeterConfigStats.
e.g., when you send a MeterMod message as:
curl -X POST -d '{"dpid": 1,
"meter_id": 1,
"flags": "KBPS",
"bands": [{"type": "DROP", "rate": 1000},
{"type": "REMARK", "rate": 2000},
{"type": "EXPERIMENTER", "rate": 3000}
]}' http://localhost:8080/stats/meterentry/add
and you do the following command:
curl http://localhost:8080/stats/meterconfig/1
then you will get the configuration as:
{"1": [{"bands": [{"burst_size": 0, "rate": 1000, "type": "DROP"},
{"prec_level": 0, "burst_size": 0, "rate": 2000, "type": "REMARK"},
{"burst_size": 0, "rate": 3000, "experimenter": 0, "type": "EXPERIMENTER"}],
"flags": "KBPS",
"meter_id": 1}]}
Signed-off-by: Yuichi Ito <ito.yuichi0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/app/ofctl_rest.py | 28 | ||||
-rw-r--r-- | ryu/lib/ofctl_v1_3.py | 36 |
2 files changed, 62 insertions, 2 deletions
diff --git a/ryu/app/ofctl_rest.py b/ryu/app/ofctl_rest.py index 788714d3..61e99ed5 100644 --- a/ryu/app/ofctl_rest.py +++ b/ryu/app/ofctl_rest.py @@ -51,6 +51,9 @@ LOG = logging.getLogger('ryu.app.ofctl_rest') # get meter features stats of the switch # GET /stats/meterfeatures/<dpid> # +# get meter config stats of the switch +# GET /stats/meterconfig/<dpid> +# # get meters stats of the switch # GET /stats/meter/<dpid> # @@ -77,8 +80,6 @@ LOG = logging.getLogger('ryu.app.ofctl_rest') # delete a meter entry # POST /stats/meterentry/delete -# TODO: support OFPMeterConfigStats - class StatsController(ControllerBase): def __init__(self, req, link, data, **config): @@ -153,6 +154,20 @@ class StatsController(ControllerBase): body = json.dumps(meters) return (Response(content_type='application/json', body=body)) + def get_meter_config(self, req, dpid, **_kwargs): + dp = self.dpset.get(int(dpid)) + if dp is None: + return Response(status=404) + + if dp.ofproto.OFP_VERSION == ofproto_v1_3.OFP_VERSION: + meters = ofctl_v1_3.get_meter_config(dp, self.waiters) + else: + LOG.debug('Unsupported OF protocol') + return Response(status=501) + + body = json.dumps(meters) + return (Response(content_type='application/json', body=body)) + def get_meter_stats(self, req, dpid, **_kwargs): dp = self.dpset.get(int(dpid)) if dp is None: @@ -288,6 +303,11 @@ class RestStatsApi(app_manager.RyuApp): 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 + '/meter/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_meter_stats', @@ -349,3 +369,7 @@ class RestStatsApi(app_manager.RyuApp): @set_ev_cls(ofp_event.EventOFPMeterFeaturesStatsReply, MAIN_DISPATCHER) def meter_features_stats_reply_handler(self, ev): self.stats_reply_handler(ev) + + @set_ev_cls(ofp_event.EventOFPMeterConfigStatsReply, MAIN_DISPATCHER) + def meter_config_stats_reply_handler(self, ev): + self.stats_reply_handler(ev) diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py index 7f67a710..107220c1 100644 --- a/ryu/lib/ofctl_v1_3.py +++ b/ryu/lib/ofctl_v1_3.py @@ -479,6 +479,42 @@ def get_meter_features(dp, waiters): return features +def get_meter_config(dp, waiters): + flags = {dp.ofproto.OFPMF_KBPS: 'KBPS', + dp.ofproto.OFPMF_PKTPS: 'PKTPS', + dp.ofproto.OFPMF_BURST: 'BURST', + dp.ofproto.OFPMF_STATS: 'STATS'} + + band_type = {dp.ofproto.OFPMBT_DROP: 'DROP', + dp.ofproto.OFPMBT_DSCP_REMARK: 'REMARK', + dp.ofproto.OFPMBT_EXPERIMENTER: 'EXPERIMENTER'} + + stats = dp.ofproto_parser.OFPMeterConfigStatsRequest( + dp, 0, dp.ofproto.OFPM_ALL) + msgs = [] + send_stats_request(dp, stats, waiters, msgs) + + configs = [] + for msg in msgs: + for config in msg.body: + bands = [] + for band in config.bands: + b = {'type': band_type.get(band.type, ''), + 'rate': band.rate, + 'burst_size': band.burst_size} + if band.type == dp.ofproto.OFPMBT_DSCP_REMARK: + b['prec_level'] = band.prec_level + elif band.type == dp.ofproto.OFPMBT_EXPERIMENTER: + b['experimenter'] = band.experimenter + bands.append(b) + c = {'flags': flags.get(config.flags, 0), + 'meter_id': config.meter_id, + 'bands': bands} + configs.append(c) + configs = {str(dp.id): configs} + return configs + + def mod_flow_entry(dp, flow, cmd): cookie = int(flow.get('cookie', 0)) cookie_mask = int(flow.get('cookie_mask', 0)) |