DESC, FLOW, AGGREGATE, and TABLE stats are supported now.

Signed-off-by: FUJITA Tomonori <[email protected]>
---
 ryu/ofproto/ofproto_v1_2.py        |   24 +++--
 ryu/ofproto/ofproto_v1_2_parser.py |  207 +++++++++++++++++++++++++++++++++++-
 2 files changed, 218 insertions(+), 13 deletions(-)

diff --git a/ryu/ofproto/ofproto_v1_2.py b/ryu/ofproto/ofproto_v1_2.py
index 394f392..b9d9062 100644
--- a/ryu/ofproto/ofproto_v1_2.py
+++ b/ryu/ofproto/ofproto_v1_2.py
@@ -432,23 +432,25 @@ DESC_STR_LEN_STR = str(DESC_STR_LEN)
 SERIAL_NUM_LEN = 32
 SERIAL_NUM_LEN_STR = str(SERIAL_NUM_LEN)
 OFP_DESC_STATS_PACK_STR = '!' + \
-                          DESC_STR_LEN_STR + 'c' + \
-                          DESC_STR_LEN_STR + 'c' + \
-                          DESC_STR_LEN_STR + 'c' + \
-                          SERIAL_NUM_LEN_STR + 'c' + \
-                          DESC_STR_LEN_STR + 'c'
+                          DESC_STR_LEN_STR + 's' + \
+                          DESC_STR_LEN_STR + 's' + \
+                          DESC_STR_LEN_STR + 's' + \
+                          SERIAL_NUM_LEN_STR + 's' + \
+                          DESC_STR_LEN_STR + 's'
 OFP_DESC_STATS_SIZE = 1056
 assert calcsize(OFP_DESC_STATS_PACK_STR) == OFP_DESC_STATS_SIZE
 
 # struct ofp_flow_stats_request
-OFP_FLOW_STATS_REQUEST_PACK_STR = '!B3xII4xQQ' + _OFP_MATCH_PACK_STR
+OFP_FLOW_STATS_REQUEST_PACK_STR = '!B3xII4xQQ'
 OFP_FLOW_STATS_REQUEST_SIZE = 40
-assert calcsize(OFP_FLOW_STATS_REQUEST_PACK_STR) == OFP_FLOW_STATS_REQUEST_SIZE
+assert (calcsize(OFP_FLOW_STATS_REQUEST_PACK_STR) + OFP_MATCH_SIZE ==
+        OFP_FLOW_STATS_REQUEST_SIZE)
 
 # struct ofp_flow_stats
-OFP_FLOW_STATS_PACK_STR = '!HBxIIHHH6xQQQ' + _OFP_MATCH_PACK_STR
+OFP_FLOW_STATS_PACK_STR = '!HBxIIHHH6xQQQ'
 OFP_FLOW_STATS_SIZE = 56
-assert calcsize(OFP_FLOW_STATS_PACK_STR) == OFP_FLOW_STATS_SIZE
+assert (calcsize(OFP_FLOW_STATS_PACK_STR) + OFP_MATCH_SIZE ==
+        OFP_FLOW_STATS_SIZE)
 
 # struct ofp_aggregate_stats_request
 OFP_AGGREGATE_STATS_REQUEST_PACK_STR = '!B3xII4xQQ'
@@ -467,10 +469,10 @@ OFP_TABLE_STATS_SIZE = 128
 OFP_MAX_TABLE_NAME_LEN = 32
 OFP_MAX_TABLE_NAME_LEN_STR = str(OFP_MAX_TABLE_NAME_LEN)
 OFP_TABLE_STATS_PACK_STR = '!B7x' + OFP_MAX_TABLE_NAME_LEN_STR + \
-                           'cQQIIQQQQIIIIQQ'
+                           'sQQIIQQQQIIIIQQ'
 assert calcsize(OFP_TABLE_STATS_PACK_STR) == OFP_TABLE_STATS_SIZE
 
-# struct ofp_por_stats_request
+# struct ofp_port_stats_request
 OFP_PORT_STATS_REQUEST_PACK_STR = '!I4x'
 OFP_PORT_STATS_REQUEST_SIZE = 8
 assert calcsize(OFP_PORT_STATS_REQUEST_PACK_STR) == OFP_PORT_STATS_REQUEST_SIZE
diff --git a/ryu/ofproto/ofproto_v1_2_parser.py 
b/ryu/ofproto/ofproto_v1_2_parser.py
index 6acf7d2..5bc81f1 100644
--- a/ryu/ofproto/ofproto_v1_2_parser.py
+++ b/ryu/ofproto/ofproto_v1_2_parser.py
@@ -770,8 +770,211 @@ class OFPTableMod(MsgBase):
                       self.table_id, self.config)
 
 
-# class OFPStatsRequest
-# class OFPStatsReply
+class OFPStatsRequest(MsgBase):
+    def __init__(self, datapath, type_):
+        super(OFPStatsRequest, self).__init__(datapath)
+        self.type = type_
+        self.flags = 0
+
+    def _serialize_stats_body(self):
+        pass
+
+    def _serialize_body(self):
+        msg_pack_into(ofproto_v1_2.OFP_STATS_REQUEST_PACK_STR,
+                      self.buf, ofproto_v1_2.OFP_HEADER_SIZE,
+                      self.type, self.flags)
+
+        self._serialize_stats_body()
+
+
+@_register_parser
+@_set_msg_type(ofproto_v1_2.OFPT_STATS_REPLY)
+class OFPStatsReply(MsgBase):
+    _STATS_TYPES = {}
+
+    @staticmethod
+    def register_stats_reply_type(type_, body_single_struct=False):
+        def _register_stats_reply_type(cls):
+            OFPStatsReply._STATS_TYPES[type_] = cls
+            cls.cls_body_single_struct = body_single_struct
+            return cls
+        return _register_stats_reply_type
+
+    def __init__(self, datapath):
+        super(OFPStatsReply, self).__init__(datapath)
+
+    @classmethod
+    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
+        msg = super(OFPStatsReply, cls).parser(datapath, version, msg_type,
+                                               msg_len, xid, buf)
+        msg.type, msg.flags = struct.unpack_from(
+            ofproto_v1_2.OFP_STATS_REPLY_PACK_STR, msg.buf,
+            ofproto_v1_2.OFP_HEADER_SIZE)
+        stats_type_cls = cls._STATS_TYPES.get(msg.type)
+
+        offset = ofproto_v1_2.OFP_STATS_REPLY_SIZE
+        body = []
+        while offset < msg_len:
+            r = stats_type_cls.parser(msg.buf, offset)
+            body.append(r)
+            offset += r.length
+
+        if stats_type_cls.cls_body_single_struct:
+            msg.body = body[0]
+        else:
+            msg.bdoy = body
+
+        return msg
+
+
+@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
+class OFPDescStatsRequest(OFPStatsRequest):
+    def __init__(self, datapath):
+        super(OFPDescStatsRequest, self).__init__(datapath,
+                                                  ofproto_v1_2.OFPST_DESC)
+
+
[email protected]_stats_reply_type(ofproto_v1_2.OFPST_DESC,
+                                         body_single_struct=True)
+class OFPDescStats(collections.namedtuple('OFPDescStats',
+        ('mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
+    @classmethod
+    def parser(cls, buf, offset):
+        desc = struct.unpack_from(ofproto_v1_2.OFP_DESC_STATS_PACK_STR,
+                                  buf, offset)
+        stats = cls(*desc)
+        stats.length = ofproto_v1_2.OFP_DESC_STATS_SIZE
+        return stats
+
+
+@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
+class OFPFlowStatsRequest(OFPStatsRequest):
+    def __init__(self, datapath, table_id, out_port, out_group,
+                 cookie, cookie_mask, match):
+        super(OFPFlowStatsRequest, self).__init__(datapath,
+                                                  ofproto_v1_2.OFPST_FLOW)
+        self.table_id = table_id
+        self.out_port = out_port
+        self.out_group = out_group
+        self.cookie = cookie
+        self.cookie_mask = cookie_mask
+        self.match = match
+
+    def _serialize_stats_body(self):
+        msg_pack_into(ofproto_v1_2.OFP_FLOW_STATS_REQUEST_PACK_STR,
+                      self.buf, ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
+                      self.table_id, self.out_port, self.out_group,
+                      self.cookie, self.cookie_mask)
+
+        offset = (ofproto_v1_2.OFP_STATS_REQUEST_SIZE +
+                  ofproto_v1_2.OFP_FLOW_STATS_REQUEST_SIZE -
+                  ofproto_v1_2.OFP_MATCH_SIZE)
+
+        self.match.serialize(self.buf, offset)
+
+
[email protected]_stats_reply_type(ofproto_v1_2.OFPST_FLOW)
+class OFPFlowStats(object):
+    def __init__(self, length, table_id, duration_sec, duration_nsec,
+                 priority, idle_timeout, hard_timeout, cookie, packet_count,
+                 byte_count, match):
+        super(OFPFlowStats, self).__init__()
+        self.length = length
+        self.table_id = table_id
+        self.duration_sec = duration_sec
+        self.duration_nsec = duration_nsec
+        self.priority = priority
+        self.idle_timeout = idle_timeout
+        self.hard_timeout = hard_timeout
+        self.cookie = cookie
+        self.packet_count = packet_count
+        self.byte_count = byte_count
+        self.match = match
+
+    @classmethod
+    def parser(cls, buf, offset):
+        (length, table_id, duration_sec,
+         duration_nsec, priority,
+         idle_timeout, hard_timeout,
+         cookie, packet_count, byte_count) = struct.unpack_from(
+            ofproto_v1_2.OFP_FLOW_STATS_PACK_STR,
+            buf, offset)
+        offset += (ofproto_v1_2.OFP_FLOW_STATS_SIZE -
+                   ofproto_v1_2.OFP_MATCH_SIZE)
+        match = OFPMatch.parser(buf, offset)
+
+        return cls(length, table_id, duration_sec, duration_nsec, priority,
+                   idle_timeout, hard_timeout, cookie, packet_count,
+                   byte_count, match)
+
+
+@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
+class OFPAggregateStatsRequest(OFPStatsRequest):
+    def __init__(self, datapath, table_id, out_port, out_group,
+                 cookie, cookie_mask, match):
+        super(OFPAggregateStatsRequest, self).__init__(
+            datapath,
+            ofproto_v1_2.OFPST_AGGREGATE)
+        self.table_id = table_id
+        self.out_port = out_port
+        self.out_group = out_group
+        self.cookie = cookie
+        self.cookie_mask = cookie_mask
+        self.match = match
+
+    def _serialize_stats_body(self):
+        msg_pack_into(ofproto_v1_2.OFP_AGGREGATE_STATS_REQUEST_PACK_STR,
+                      self.buf,
+                      ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
+                      self.table_id, self.out_port, self.out_group,
+                      self.cookie, self.cookie_mask)
+
+        offset = (ofproto_v1_2.OFP_STATS_REQUEST_SIZE +
+                  ofproto_v1_2.OFP_AGGREGATE_STATS_REQUEST_SIZE -
+                  ofproto_v1_2.OFP_MATCH_SIZE)
+
+        self.match.serialize(self.buf, offset)
+
+
[email protected]_stats_reply_type(ofproto_v1_2.OFPST_AGGREGATE,
+                                         body_single_struct=True)
+class OFPAggregateStatsReply(collections.namedtuple('OFPAggregateStats',
+        ('packet_count', 'byte_count', 'flow_count'))):
+    @classmethod
+    def parser(cls, buf, offset):
+        desc = struct.unpack_from(
+            ofproto_v1_2.OFP_AGGREGATE_STATS_REPLY_PACK_STR,
+            buf, offset)
+        stats = cls(*desc)
+        stats.length = ofproto_v1_2.OFP_AGGREGATE_STATS_REPLY_SIZE
+        return stats
+
+
+@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
+class OFPTableStatsRequest(OFPStatsRequest):
+    def __init__(self, datapath):
+        super(OFPTableStatsRequest, self).__init__(datapath,
+                                                   ofproto_v1_2.OFPST_TABLE)
+
+
[email protected]_stats_reply_type(ofproto_v1_2.OFPST_TABLE)
+class OFPTableStats(
+    collections.namedtuple('OFPTableStats',
+                           ('table_id', 'name', 'match', 'wildcards',
+                            'write_actions', 'apply_actions',
+                            'write_setfields', 'apply_setfields',
+                            'metadata_match', 'metadata_write',
+                            'instructions', 'config',
+                            'max_entries', 'active_count',
+                            'lookup_count', 'matched_count'))):
+    @classmethod
+    def parser(cls, buf, offset):
+        table = struct.unpack_from(
+            ofproto_v1_2.OFP_TABLE_STATS_PACK_STR,
+            buf, offset)
+        stats = cls(*table)
+        stats.length = ofproto_v1_2.OFP_TABLE_STATS_SIZE
+        return stats
 
 
 @_set_msg_type(ofproto_v1_2.OFPT_QUEUE_GET_CONFIG_REQUEST)
-- 
1.7.4.4


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to