summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYuichi Ito <ito.yuichi0@gmail.com>2013-12-20 16:10:40 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2013-12-24 20:38:33 +0900
commit119990d1eba339e1088cf87b32d39eb3169ddcde (patch)
treea64b7e874c0cd71cec9083cbc43e5270d798ed95
parentd30e9da4da4e03161d77df0d049dfa9bebe0457b (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.py28
-rw-r--r--ryu/lib/ofctl_v1_3.py36
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))