Signed-off-by: Simon Horman <[email protected]>
---
 ryu/ofproto/ofproto_v1_4_parser.py | 346 +++++++++++++++++++++++++++++++++++++
 1 file changed, 346 insertions(+)

diff --git a/ryu/ofproto/ofproto_v1_4_parser.py 
b/ryu/ofproto/ofproto_v1_4_parser.py
index 567051c..52ff6d8 100644
--- a/ryu/ofproto/ofproto_v1_4_parser.py
+++ b/ryu/ofproto/ofproto_v1_4_parser.py
@@ -1800,6 +1800,352 @@ class OFPDescStatsReply(OFPMultipartReply):
         super(OFPDescStatsReply, self).__init__(datapath, **kwargs)
 
 
+class OFPTableFeaturesStats(StringifyMixin):
+
+    _TYPE = {
+        'utf-8': [
+            # OF spec is unclear about the encoding of name.
+            # we assumes UTF-8.
+            'name',
+        ]
+    }
+
+    def __init__(self, table_id=None, name=None, metadata_match=None,
+                 metadata_write=None, config=None, max_entries=None,
+                 properties=None, length=None):
+        super(OFPTableFeaturesStats, self).__init__()
+        self.length = None
+        self.table_id = table_id
+        self.name = name
+        self.metadata_match = metadata_match
+        self.metadata_write = metadata_write
+        self.config = config
+        self.max_entries = max_entries
+        self.properties = properties
+
+    @classmethod
+    def parser(cls, buf, offset):
+        table_features = cls()
+        (table_features.length, table_features.table_id,
+         name, table_features.metadata_match,
+         table_features.metadata_write, table_features.config,
+         table_features.max_entries
+         ) = struct.unpack_from(ofproto.OFP_TABLE_FEATURES_PACK_STR,
+                                buf, offset)
+        table_features.name = name.rstrip('\0')
+
+        props = []
+        rest = buf[offset + ofproto.OFP_TABLE_FEATURES_SIZE:
+                   offset + table_features.length]
+        while rest:
+            p, rest = OFPTableFeatureProp.parse(rest)
+            props.append(p)
+        table_features.properties = props
+
+        return table_features
+
+    def serialize(self):
+        # fixup
+        bin_props = bytearray()
+        for p in self.properties:
+            bin_props += p.serialize()
+        self.length = ofproto.OFP_TABLE_FEATURES_SIZE + len(bin_props)
+
+        buf = bytearray()
+        msg_pack_into(ofproto.OFP_TABLE_FEATURES_PACK_STR, buf, 0,
+                      self.length, self.table_id, self.name,
+                      self.metadata_match, self.metadata_write,
+                      self.config, self.max_entries)
+        return buf + bin_props
+
+
+class OFPTableFeatureProp(OFPPropBase):
+    _TYPES = {}
+
+    @classmethod
+    def get_rest(cls, buf):
+        (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
+        offset = struct.calcsize(cls._PACK_STR)
+        return buf[offset:length]
+
+    def serialize(self):
+        # Body
+        # serialize_body should be implemented by subclass
+        body = bytearray()
+        body += self.serialize_body()
+
+        # fixup
+        self.length = len(body) + struct.calcsize(self._PACK_STR)
+
+        # Header
+        buf = bytearray()
+        msg_pack_into(self._PACK_STR, buf, 0, self.type, self.length)
+        buf += body
+
+        # Pad
+        pad_len = utils.round_up(self.length, 8) - self.length
+        ofproto_parser.msg_pack_into("%dx" % pad_len, buf, len(buf))
+
+        return buf
+
+
+class OFPInstructionId(StringifyMixin):
+    _PACK_STR = '!HH'  # type, len
+
+    def __init__(self, type_, len_=None):
+        self.type = type_
+        self.len = len_
+        # XXX experimenter
+
+    @classmethod
+    def parse(cls, buf):
+        (type_, len_,) = struct.unpack_from(cls._PACK_STR, buffer(buf), 0)
+        rest = buf[len_:]
+        return cls(type_=type_, len_=len_), rest
+
+    def serialize(self):
+        # fixup
+        self.len = struct.calcsize(self._PACK_STR)
+
+        buf = bytearray()
+        msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
+        return buf
+
+
[email protected]_type(ofproto.OFPTFPT_INSTRUCTIONS)
[email protected]_type(ofproto.OFPTFPT_INSTRUCTIONS_MISS)
+class OFPTableFeaturePropInstructions(OFPTableFeatureProp):
+    def __init__(self, type_=None, length=None, instruction_ids=[]):
+        super(OFPTableFeaturePropInstructions, self).__init__(type_, length)
+        self.instruction_ids = instruction_ids
+
+    @classmethod
+    def parser(cls, buf):
+        rest = cls.get_rest(buf)
+        ids = []
+        while rest:
+            i, rest = OFPInstructionId.parse(rest)
+            ids.append(i)
+        return cls(instruction_ids=ids)
+
+    def serialize_body(self):
+        bin_ids = bytearray()
+        for i in self.instruction_ids:
+            bin_ids += i.serialize()
+
+        return bin_ids
+
+
+# Implementation note: While OpenFlow 1.3.2 shares the same ofp_action_header
+# for flow_mod and table_features, we have separate classes.  We named this
+# class to match with OpenFlow 1.4's name.  (ofp_action_id)
+class OFPActionId(StringifyMixin):
+    _PACK_STR = '!HH'  # type, len
+
+    def __init__(self, type_, len_=None):
+        self.type = type_
+        self.len = len_
+        # XXX experimenter
+
+    @classmethod
+    def parse(cls, buf):
+        (type_, len_,) = struct.unpack_from(cls._PACK_STR, buffer(buf), 0)
+        rest = buf[len_:]
+        return cls(type_=type_, len_=len_), rest
+
+    def serialize(self):
+        # fixup
+        self.len = struct.calcsize(self._PACK_STR)
+
+        buf = bytearray()
+        msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
+        return buf
+
+
[email protected]_type(ofproto.OFPTFPT_WRITE_ACTIONS)
[email protected]_type(ofproto.OFPTFPT_WRITE_ACTIONS_MISS)
[email protected]_type(ofproto.OFPTFPT_APPLY_ACTIONS)
[email protected]_type(ofproto.OFPTFPT_APPLY_ACTIONS_MISS)
+class OFPTableFeaturePropActions(OFPTableFeatureProp):
+    def __init__(self, type_=None, length=None, action_ids=[]):
+        super(OFPTableFeaturePropActions, self).__init__(type_, length)
+        self.action_ids = action_ids
+
+    @classmethod
+    def parser(cls, buf):
+        rest = cls.get_rest(buf)
+        ids = []
+        while rest:
+            i, rest = OFPActionId.parse(rest)
+            ids.append(i)
+        return cls(action_ids=ids)
+
+    def serialize_body(self):
+        bin_ids = bytearray()
+        for i in self.action_ids:
+            bin_ids += i.serialize()
+        return bin_ids
+
+
[email protected]_type(ofproto.OFPTFPT_NEXT_TABLES)
[email protected]_type(ofproto.OFPTFPT_NEXT_TABLES_MISS)
+class OFPTableFeaturePropNextTables(OFPTableFeatureProp):
+    _TABLE_ID_PACK_STR = '!B'
+
+    def __init__(self, type_=None, length=None, table_ids=[]):
+        super(OFPTableFeaturePropNextTables, self).__init__(type_, length)
+        self.table_ids = table_ids
+
+    @classmethod
+    def parser(cls, buf):
+        rest = cls.get_rest(buf)
+        ids = []
+        while rest:
+            (i,) = struct.unpack_from(cls._TABLE_ID_PACK_STR, buffer(rest), 0)
+            rest = rest[struct.calcsize(cls._TABLE_ID_PACK_STR):]
+            ids.append(i)
+        return cls(table_ids=ids)
+
+    def serialize_body(self):
+        bin_ids = bytearray()
+        for i in self.table_ids:
+            bin_id = bytearray()
+            msg_pack_into(self._TABLE_ID_PACK_STR, bin_id, 0, i)
+            bin_ids += bin_id
+        return bin_ids
+
+
+# Implementation note: OFPOxmId is specific to this implementation.
+# It does not have a corresponding structure in the specification.
+# (the specification uses plain uint32_t for them.)
+#
+# i have taken a look at some of software switch implementations
+# but they all look broken or incomplete.  according to the spec,
+# oxm_hasmask should be 1 if a switch supports masking for the type.
+# the right value for oxm_length is not clear from the spec.
+# update: OpenFlow 1.3.3 "clarified" that oxm_length here is the payload
+# length.  it's still unclear if it should be doubled for hasmask or not,
+# though.
+#   ofsoftswitch13
+#     oxm_hasmask  always 0
+#     oxm_length   same as ofp_match etc (as without mask)
+#   linc/of_protocol
+#     oxm_hasmask  always 0
+#     oxm_length   always 0
+#   ovs:
+#     table-feature is not implemented
+class OFPOxmId(StringifyMixin):
+    _PACK_STR = '!I'  # oxm header
+
+    _TYPE = {
+        'ascii': [
+            'type',
+        ],
+    }
+
+    def __init__(self, type_, hasmask=False, length=None):
+        self.type = type_
+        self.hasmask = hasmask
+        self.length = length
+        # XXX experimenter
+
+    @classmethod
+    def parse(cls, buf):
+        (oxm,) = struct.unpack_from(cls._PACK_STR, buffer(buf), 0)
+        (type_, _v) = ofproto.oxm_to_user(oxm >> 9, None, None)
+        hasmask = ofproto.oxm_tlv_header_extract_hasmask(oxm)
+        length = oxm & 0xff  # XXX see the comment on OFPOxmId
+        rest = buf[4:]  # XXX see the comment on OFPOxmId
+        return cls(type_=type_, hasmask=hasmask, length=length), rest
+
+    def serialize(self):
+        # fixup
+        self.length = 0  # XXX see the comment on OFPOxmId
+
+        (n, _v, _m) = ofproto.oxm_from_user(self.type, None)
+        oxm = (n << 9) | (self.hasmask << 8) | self.length
+        buf = bytearray()
+        msg_pack_into(self._PACK_STR, buf, 0, oxm)
+        return buf
+
+
[email protected]_type(ofproto.OFPTFPT_MATCH)
[email protected]_type(ofproto.OFPTFPT_WILDCARDS)
[email protected]_type(ofproto.OFPTFPT_WRITE_SETFIELD)
[email protected]_type(ofproto.OFPTFPT_WRITE_SETFIELD_MISS)
[email protected]_type(ofproto.OFPTFPT_APPLY_SETFIELD)
[email protected]_type(ofproto.OFPTFPT_APPLY_SETFIELD_MISS)
+class OFPTableFeaturePropOxm(OFPTableFeatureProp):
+    def __init__(self, type_=None, length=None, oxm_ids=[]):
+        super(OFPTableFeaturePropOxm, self).__init__(type_, length)
+        self.oxm_ids = oxm_ids
+
+    @classmethod
+    def parser(cls, buf):
+        rest = cls.get_rest(buf)
+        ids = []
+        while rest:
+            i, rest = OFPOxmId.parse(rest)
+            ids.append(i)
+        return cls(oxm_ids=ids)
+
+    def serialize_body(self):
+        bin_ids = bytearray()
+        for i in self.oxm_ids:
+            bin_ids += i.serialize()
+        return bin_ids
+
+
+@_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
+@_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
+class OFPTableFeaturesStatsRequest(OFPMultipartRequest):
+    """
+    Table features statistics request message
+
+    The controller uses this message to query table features.
+
+    ================ ======================================================
+    Attribute        Description
+    ================ ======================================================
+    body             List of ``OFPTableFeaturesStats`` instances.
+                     The default is [].
+    ================ ======================================================
+    """
+    def __init__(self, datapath, flags=0, body=[], type_=None):
+        super(OFPTableFeaturesStatsRequest, self).__init__(datapath, flags)
+        self.body = body
+
+    def _serialize_stats_body(self):
+        bin_body = bytearray()
+        for p in self.body:
+            bin_body += p.serialize()
+        self.buf += bin_body
+
+
[email protected]_stats_type()
+@_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
+@_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
+class OFPTableFeaturesStatsReply(OFPMultipartReply):
+    """
+    Table features statistics reply message
+
+    The switch responds with this message to a table features statistics
+    request.
+
+    This implmentation is still incomplete.
+    Namely, this implementation does not parse ``properties`` list and
+    always reports it empty.
+
+    ================ ======================================================
+    Attribute        Description
+    ================ ======================================================
+    body             List of ``OFPTableFeaturesStats`` instance
+    ================ ======================================================
+    """
+    def __init__(self, datapath, type_=None, **kwargs):
+        super(OFPTableFeaturesStatsReply, self).__init__(datapath, **kwargs)
+
+
 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
 class OFPPortDescStatsRequest(OFPMultipartRequest):
-- 
1.8.5.2


------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to