diff --git a/ryu/app/ofctl_rest.py b/ryu/app/ofctl_rest.py index 8efc0a45..c398d941 100644 --- a/ryu/app/ofctl_rest.py +++ b/ryu/app/ofctl_rest.py @@ -52,6 +52,12 @@ LOG = logging.getLogger('ryu.app.ofctl_rest') # 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 ports stats of the switch # GET /stats/port/ # @@ -181,6 +187,33 @@ class StatsController(ControllerBase): body = json.dumps(flows) return (Response(content_type='application/json', body=body)) + def get_aggregate_flow_stats(self, req, dpid, **_kwargs): + if req.body == '': + flow = {} + else: + try: + flow = ast.literal_eval(req.body) + except SyntaxError: + LOG.debug('invalid syntax %s', req.body) + return Response(status=400) + + dp = self.dpset.get(int(dpid)) + if dp is None: + return Response(status=404) + + if dp.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION: + flows = ofctl_v1_0.get_aggregate_flow_stats(dp, self.waiters, flow) + elif dp.ofproto.OFP_VERSION == ofproto_v1_2.OFP_VERSION: + flows = ofctl_v1_2.get_aggregate_flow_stats(dp, self.waiters, flow) + elif dp.ofproto.OFP_VERSION == ofproto_v1_3.OFP_VERSION: + flows = ofctl_v1_3.get_aggregate_flow_stats(dp, self.waiters, flow) + else: + LOG.debug('Unsupported OF protocol') + return Response(status=501) + + body = json.dumps(flows) + return Response(content_type='application/json', body=body) + def get_port_stats(self, req, dpid, **_kwargs): dp = self.dpset.get(int(dpid)) if dp is None: @@ -572,6 +605,12 @@ class RestStatsApi(app_manager.RyuApp): 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 + '/port/{dpid}' mapper.connect('stats', uri, controller=StatsController, action='get_port_stats', @@ -650,6 +689,7 @@ class RestStatsApi(app_manager.RyuApp): @set_ev_cls([ofp_event.EventOFPStatsReply, ofp_event.EventOFPDescStatsReply, ofp_event.EventOFPFlowStatsReply, + ofp_event.EventOFPAggregateStatsReply, ofp_event.EventOFPPortStatsReply, ofp_event.EventOFPQueueStatsReply, ofp_event.EventOFPMeterStatsReply, diff --git a/ryu/lib/ofctl_v1_0.py b/ryu/lib/ofctl_v1_0.py index ee4bffa6..a72d9b79 100644 --- a/ryu/lib/ofctl_v1_0.py +++ b/ryu/lib/ofctl_v1_0.py @@ -322,6 +322,30 @@ def get_flow_stats(dp, waiters, flow={}): return flows +def get_aggregate_flow_stats(dp, waiters, flow={}): + match = to_match(dp, flow.get('match', {})) + table_id = int(flow.get('table_id', 0xff)) + out_port = int(flow.get('out_port', dp.ofproto.OFPP_NONE)) + + stats = dp.ofproto_parser.OFPAggregateStatsRequest( + dp, 0, match, table_id, out_port) + + msgs = [] + send_stats_request(dp, stats, waiters, msgs) + + flows = [] + for msg in msgs: + stats = msg.body + for st in stats: + s = {'packet_count': st.packet_count, + 'byte_count': st.byte_count, + 'flow_count': st.flow_count} + flows.append(s) + flows = {str(dp.id): flows} + + return flows + + def get_port_stats(dp, waiters): stats = dp.ofproto_parser.OFPPortStatsRequest( dp, 0, dp.ofproto.OFPP_NONE) diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py index 8c8e7682..07299ee5 100644 --- a/ryu/lib/ofctl_v1_2.py +++ b/ryu/lib/ofctl_v1_2.py @@ -465,6 +465,32 @@ def get_flow_stats(dp, waiters, flow={}): return flows +def get_aggregate_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)) + out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY)) + cookie = int(flow.get('cookie', 0)) + cookie_mask = int(flow.get('cookie_mask', 0)) + match = to_match(dp, flow.get('match', {})) + + stats = dp.ofproto_parser.OFPAggregateStatsRequest( + dp, table_id, out_port, out_group, cookie, cookie_mask, match) + + msgs = [] + send_stats_request(dp, stats, waiters, msgs) + + flows = [] + for msg in msgs: + stats = msg.body + s = {'packet_count': stats.packet_count, + 'byte_count': stats.byte_count, + 'flow_count': stats.flow_count} + flows.append(s) + flows = {str(dp.id): flows} + + return flows + + def get_port_stats(dp, waiters): stats = dp.ofproto_parser.OFPPortStatsRequest( dp, dp.ofproto.OFPP_ANY, 0) diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py index b15f2b52..34383068 100644 --- a/ryu/lib/ofctl_v1_3.py +++ b/ryu/lib/ofctl_v1_3.py @@ -493,6 +493,34 @@ def get_flow_stats(dp, waiters, flow={}): return flows +def get_aggregate_flow_stats(dp, waiters, flow={}): + table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL)) + flags = int(flow.get('flags', 0)) + out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY)) + out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY)) + cookie = int(flow.get('cookie', 0)) + cookie_mask = int(flow.get('cookie_mask', 0)) + match = to_match(dp, flow.get('match', {})) + + stats = dp.ofproto_parser.OFPAggregateStatsRequest( + dp, flags, table_id, out_port, out_group, cookie, cookie_mask, + match) + + msgs = [] + send_stats_request(dp, stats, waiters, msgs) + + flows = [] + for msg in msgs: + stats = msg.body + s = {'packet_count': stats.packet_count, + 'byte_count': stats.byte_count, + 'flow_count': stats.flow_count} + flows.append(s) + flows = {str(dp.id): flows} + + return flows + + def get_port_stats(dp, waiters): stats = dp.ofproto_parser.OFPPortStatsRequest( dp, 0, dp.ofproto.OFPP_ANY)