ofctl_rest: support OFPQueueGetConfig Message

this patch makes ofctl_rest enable use of OFPQueueGetConfig message.

Get queues config:

  usage)

    URI:    /stats/queueconfig/<dpid>/<port>
    method: GET

  e.g.)

    $ curl -X GET http://localhost:8080/stats/queueconfig/1/1
    {
      "1": [
        {
          "port": 1,
          "queues": [
            {
              "properties": [
                {
                  "property": "MIN_RATE",
                  "rate": 80
                }
              ],
              "port": 0,
              "queue_id": 1
            },
            {
              "properties": [
                {
                  "property": "MAX_RATE",
                  "rate": 120
                }
              ],
              "port": 2,
              "queue_id": 2
            },
            {
              "properties": [
                {
                  "property": "EXPERIMENTER",
                  "data": [],
                  "experimenter": 999
                }
              ],
              "port": 3,
              "queue_id": 3
            }
          ]
        }
      ]
    }

Signed-off-by: Minoru TAKAHASHI <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Minoru TAKAHASHI 2015-10-22 17:31:35 +09:00 committed by FUJITA Tomonori
parent 26e8efb246
commit 6518654a1b
3 changed files with 113 additions and 1 deletions

View File

@ -77,6 +77,9 @@ supported_ofctl = {
# get queues stats of the switch
# GET /stats/queue/<dpid>
#
# get queues config stats of the switch
# GET /stats/queueconfig/<dpid>/<port>
#
# get meter features stats of the switch
# GET /stats/meterfeatures/<dpid>
#
@ -345,6 +348,35 @@ class StatsController(ControllerBase):
body = json.dumps(queues)
return Response(content_type='application/json', body=body)
def get_queue_config(self, req, dpid, port, **_kwargs):
if type(dpid) == str and not dpid.isdigit():
LOG.debug('invalid dpid %s', dpid)
return Response(status=400)
if type(port) == str and not port.isdigit():
LOG.debug('invalid port %s', port)
return Response(status=400)
dp = self.dpset.get(int(dpid))
port = int(port)
if dp is None:
return Response(status=404)
_ofp_version = dp.ofproto.OFP_VERSION
_ofctl = supported_ofctl.get(_ofp_version, None)
if _ofctl is not None:
queues = _ofctl.get_queue_config(dp, port, self.waiters)
else:
LOG.debug('Unsupported OF protocol')
return Response(status=501)
body = json.dumps(queues)
return Response(content_type='application/json', body=body)
def get_meter_features(self, req, dpid, **_kwargs):
if type(dpid) == str and not dpid.isdigit():
@ -815,6 +847,11 @@ class RestStatsApi(app_manager.RyuApp):
controller=StatsController, action='get_queue_stats',
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 + '/meterfeatures/{dpid}'
mapper.connect('stats', uri,
controller=StatsController, action='get_meter_features',
@ -920,7 +957,8 @@ class RestStatsApi(app_manager.RyuApp):
del self.waiters[dp.id][msg.xid]
lock.set()
@set_ev_cls([ofp_event.EventOFPSwitchFeatures], MAIN_DISPATCHER)
@set_ev_cls([ofp_event.EventOFPSwitchFeatures,
ofp_event.EventOFPQueueGetConfigReply], MAIN_DISPATCHER)
def features_reply_handler(self, ev):
msg = ev.msg
dp = msg.datapath

View File

@ -453,6 +453,43 @@ def get_queue_stats(dp, waiters):
return desc
def get_queue_config(dp, port, waiters):
ofp = dp.ofproto
stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
msgs = []
send_stats_request(dp, stats, waiters, msgs)
prop_type = {dp.ofproto.OFPQT_MIN_RATE: 'MIN_RATE',
dp.ofproto.OFPQT_MAX_RATE: 'MAX_RATE',
dp.ofproto.OFPQT_EXPERIMENTER: 'EXPERIMENTER',
}
configs = []
for config in msgs:
queue_list = []
for queue in config.queues:
prop_list = []
for prop in queue.properties:
p = {'property': prop_type.get(prop.property, 'UNKNOWN')}
if prop.property == dp.ofproto.OFPQT_MIN_RATE or \
prop.property == dp.ofproto.OFPQT_MAX_RATE:
p['rate'] = prop.rate
elif prop.property == dp.ofproto.OFPQT_EXPERIMENTER:
p['experimenter'] = prop.experimenter
p['data'] = prop.data
prop_list.append(p)
q = {'port': queue.port,
'properties': prop_list,
'queue_id': queue.queue_id}
queue_list.append(q)
c = {'port': config.port,
'queues': queue_list}
configs.append(c)
configs = {str(dp.id): configs}
return configs
def get_flow_stats(dp, waiters, flow={}):
table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL))
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))

View File

@ -478,6 +478,43 @@ def get_queue_stats(dp, waiters):
return desc
def get_queue_config(dp, port, waiters):
ofp = dp.ofproto
stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
msgs = []
send_stats_request(dp, stats, waiters, msgs)
prop_type = {dp.ofproto.OFPQT_MIN_RATE: 'MIN_RATE',
dp.ofproto.OFPQT_MAX_RATE: 'MAX_RATE',
dp.ofproto.OFPQT_EXPERIMENTER: 'EXPERIMENTER',
}
configs = []
for config in msgs:
queue_list = []
for queue in config.queues:
prop_list = []
for prop in queue.properties:
p = {'property': prop_type.get(prop.property, 'UNKNOWN')}
if prop.property == dp.ofproto.OFPQT_MIN_RATE or \
prop.property == dp.ofproto.OFPQT_MAX_RATE:
p['rate'] = prop.rate
elif prop.property == dp.ofproto.OFPQT_EXPERIMENTER:
p['experimenter'] = prop.experimenter
p['data'] = prop.data
prop_list.append(p)
q = {'port': queue.port,
'properties': prop_list,
'queue_id': queue.queue_id}
queue_list.append(q)
c = {'port': config.port,
'queues': queue_list}
configs.append(c)
configs = {str(dp.id): configs}
return configs
def get_flow_stats(dp, waiters, flow={}):
table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL))
flags = int(flow.get('flags', 0))