this patch makes ofctl_rest enable use of OFPAggregateStats message.

Get aggregate flow stats:

  usage)

    URI:    /stats/aggregateflow/<dpid>
    method: GET

  e.g.)

    $ curl -X GET http://localhost:8080/stats/aggregateflow/1
    {
      "1": [
        {
          "packet_count": 18,
          "byte_count": 756,
          "flow_count": 3
        }
      ]
    }

Get aggregate flow stats filtered by fields:

  usage)

    URI:    /stats/aggregateflow/<dpid>
    method: POST

    the message body is as follows.

        table_id     Table ID (int)
        out_port     Require matching entries to include this as an output port 
(int)
        out_group    Require matching entries to include this as an output 
group (int)
        cookie       Require matching entries to contain this cookie value (int)
        cookie_mask  Mask used to restrict the cookie bits that must match (int)
        match        Fields to match (dict)

  e.g.)

    $ curl -X POST -d '{
             "table_id": 0,
             "out_port": 2,
             "cookie": 1,
             "cookie_mask": 1,
             "match":{
                 "in_port":1
             }
         }' http://localhost:8080/stats/aggregateflow/1

Signed-off-by: IWASE Yusuke <[email protected]>
---
 ryu/app/ofctl_rest.py | 40 ++++++++++++++++++++++++++++++++++++++++
 ryu/lib/ofctl_v1_0.py | 24 ++++++++++++++++++++++++
 ryu/lib/ofctl_v1_2.py | 26 ++++++++++++++++++++++++++
 ryu/lib/ofctl_v1_3.py | 28 ++++++++++++++++++++++++++++
 4 files changed, 118 insertions(+)

diff --git a/ryu/app/ofctl_rest.py b/ryu/app/ofctl_rest.py
index 8efc0a4..c398d94 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/<dpid>
 #
+# get aggregate flows stats of the switch
+# GET /stats/aggregateflow/<dpid>
+#
+# get aggregate flows stats of the switch filtered by the fields
+# POST /stats/aggregateflow/<dpid>
+#
 # get ports stats of the switch
 # GET /stats/port/<dpid>
 #
@@ -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 9fc0f93..a44b4bb 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 a62fbd9..52b0ad4 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 4372e53..532d3b0 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)
-- 
1.9.1



------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to