Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
 ryu/ofproto/ofproto_v1_2.py        |  12 ++
 ryu/ofproto/ofproto_v1_2_parser.py | 246 +++++++++++++++++++++++++------------
 2 files changed, 180 insertions(+), 78 deletions(-)

diff --git a/ryu/ofproto/ofproto_v1_2.py b/ryu/ofproto/ofproto_v1_2.py
index 27fc6b3..e2bda20 100644
--- a/ryu/ofproto/ofproto_v1_2.py
+++ b/ryu/ofproto/ofproto_v1_2.py
@@ -805,6 +805,18 @@ def oxm_tlv_header_w(field, length):
     return _oxm_tlv_header(OFPXMC_OPENFLOW_BASIC, field, 1, length * 2)
 
 
+def oxm_tlv_header_extract_hasmask(header):
+    return (header >> 8) & 1
+
+
+def oxm_tlv_header_extract_length(header):
+    if oxm_tlv_header_extract_hasmask(header):
+        length = (header & 0xff) / 2
+    else:
+        length = header & 0xff
+    return length
+
+
 OXM_OF_IN_PORT = oxm_tlv_header(OFPXMT_OFB_IN_PORT, 4)
 OXM_OF_IN_PHY_PORT = oxm_tlv_header(OFPXMT_OFB_IN_PHY_PORT, 4)
 OXM_OF_METADATA = oxm_tlv_header(OFPXMT_OFB_METADATA, 8)
diff --git a/ryu/ofproto/ofproto_v1_2_parser.py 
b/ryu/ofproto/ofproto_v1_2_parser.py
index 112cd45..d13d044 100644
--- a/ryu/ofproto/ofproto_v1_2_parser.py
+++ b/ryu/ofproto/ofproto_v1_2_parser.py
@@ -14,13 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import collections
 import struct
 import itertools
 
 from ryu.lib import mac
 from ryu import utils
-from ofproto_parser import MsgBase, msg_pack_into, msg_str_attr
+from ofproto_parser import StringifyMixin, MsgBase, msg_pack_into, msg_str_attr
 from . import ofproto_parser
 from . import ofproto_v1_2
 
@@ -165,7 +164,7 @@ class OFPExperimenter(MsgBase):
         return msg
 
 
-class OFPPort(collections.namedtuple('OFPPort', (
+class OFPPort(ofproto_parser.namedtuple('OFPPort', (
         'port_no', 'hw_addr', 'name', 'config', 'state', 'curr',
         'advertised', 'supported', 'peer', 'curr_speed', 'max_speed'))):
 
@@ -184,8 +183,14 @@ class OFPFeaturesRequest(MsgBase):
 @_register_parser
 @_set_msg_type(ofproto_v1_2.OFPT_FEATURES_REPLY)
 class OFPSwitchFeatures(MsgBase):
-    def __init__(self, datapath):
+    def __init__(self, datapath, datapath_id=None, n_buffers=None,
+                 n_tables=None, capabilities=None, ports=None):
         super(OFPSwitchFeatures, self).__init__(datapath)
+        self.datapath_id = datapath_id
+        self.n_buffers = n_buffers
+        self.n_tables = n_tables
+        self.capabilities = capabilities
+        self.ports = ports
 
     @classmethod
     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
@@ -195,7 +200,7 @@ class OFPSwitchFeatures(MsgBase):
          msg.n_buffers,
          msg.n_tables,
          msg.capabilities,
-         msg.reserved) = struct.unpack_from(
+         msg._reserved) = struct.unpack_from(
              ofproto_v1_2.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
              ofproto_v1_2.OFP_HEADER_SIZE)
 
@@ -251,8 +256,15 @@ class OFPSetConfig(MsgBase):
 @_register_parser
 @_set_msg_type(ofproto_v1_2.OFPT_PACKET_IN)
 class OFPPacketIn(MsgBase):
-    def __init__(self, datapath):
+    def __init__(self, datapath, buffer_id=None, total_len=None, reason=None,
+                 table_id=None, match=None, data=None):
         super(OFPPacketIn, self).__init__(datapath)
+        self.buffer_id = buffer_id
+        self.total_len = total_len
+        self.reason = reason
+        self.table_id = table_id
+        self.match = match
+        self.data = data
 
     @classmethod
     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
@@ -334,17 +346,17 @@ class OFPPacketOut(MsgBase):
         super(OFPPacketOut, self).__init__(datapath)
         self.buffer_id = buffer_id
         self.in_port = in_port
-        self.actions_len = 0
+        self._actions_len = 0
         self.actions = actions
         self.data = data
 
     def _serialize_body(self):
-        self.actions_len = 0
+        self._actions_len = 0
         offset = ofproto_v1_2.OFP_PACKET_OUT_SIZE
         for a in self.actions:
             a.serialize(self.buf, offset)
             offset += a.len
-            self.actions_len += a.len
+            self._actions_len += a.len
 
         if self.data is not None:
             assert self.buffer_id == 0xffffffff
@@ -352,7 +364,7 @@ class OFPPacketOut(MsgBase):
 
         msg_pack_into(ofproto_v1_2.OFP_PACKET_OUT_PACK_STR,
                       self.buf, ofproto_v1_2.OFP_HEADER_SIZE,
-                      self.buffer_id, self.in_port, self.actions_len)
+                      self.buffer_id, self.in_port, self._actions_len)
 
 
 @_set_msg_type(ofproto_v1_2.OFPT_FLOW_MOD)
@@ -394,7 +406,7 @@ class OFPFlowMod(MsgBase):
             offset += inst.len
 
 
-class OFPInstruction(object):
+class OFPInstruction(StringifyMixin):
     _INSTRUCTION_TYPES = {}
 
     @staticmethod
@@ -413,7 +425,9 @@ class OFPInstruction(object):
 
 
 @OFPInstruction.register_instruction_type([ofproto_v1_2.OFPIT_GOTO_TABLE])
-class OFPInstructionGotoTable(object):
+class OFPInstructionGotoTable(StringifyMixin):
+    _base_attributes = ['type', 'len']
+
     def __init__(self, table_id):
         super(OFPInstructionGotoTable, self).__init__()
         self.type = ofproto_v1_2.OFPIT_GOTO_TABLE
@@ -433,7 +447,9 @@ class OFPInstructionGotoTable(object):
 
 
 @OFPInstruction.register_instruction_type([ofproto_v1_2.OFPIT_WRITE_METADATA])
-class OFPInstructionWriteMetadata(object):
+class OFPInstructionWriteMetadata(StringifyMixin):
+    _base_attributes = ['type', 'len']
+
     def __init__(self, metadata, metadata_mask):
         super(OFPInstructionWriteMetadata, self).__init__()
         self.type = ofproto_v1_2.OFPIT_WRITE_METADATA
@@ -457,7 +473,9 @@ class OFPInstructionWriteMetadata(object):
 @OFPInstruction.register_instruction_type([ofproto_v1_2.OFPIT_WRITE_ACTIONS,
                                            ofproto_v1_2.OFPIT_APPLY_ACTIONS,
                                            ofproto_v1_2.OFPIT_CLEAR_ACTIONS])
-class OFPInstructionActions(object):
+class OFPInstructionActions(StringifyMixin):
+    _base_attributes = ['len']
+
     def __init__(self, type_, actions=None):
         super(OFPInstructionActions, self).__init__()
         self.type = type_
@@ -486,6 +504,7 @@ class OFPInstructionActions(object):
         action_offset = offset + ofproto_v1_2.OFP_INSTRUCTION_ACTIONS_SIZE
         if self.actions:
             for a in self.actions:
+                assert isinstance(a, OFPAction)
                 a.serialize(buf, action_offset)
                 action_offset += a.len
 
@@ -498,7 +517,9 @@ class OFPInstructionActions(object):
                       buf, offset, self.type, self.len)
 
 
-class OFPActionHeader(object):
+class OFPActionHeader(StringifyMixin):
+    _base_attributes = ['type', 'len']
+
     def __init__(self, type_, len_):
         self.type = type_
         self.len = len_
@@ -795,7 +816,7 @@ class OFPActionExperimenter(OFPAction):
                       buf, offset, self.type, self.len, self.experimenter)
 
 
-class OFPBucket(object):
+class OFPBucket(StringifyMixin):
     def __init__(self, len_, weight, watch_port, watch_group, actions):
         super(OFPBucket, self).__init__()
         self.len = len_
@@ -885,10 +906,17 @@ class OFPTableMod(MsgBase):
 
 
 class OFPStatsRequest(MsgBase):
-    def __init__(self, datapath, type_):
+    def __init__(self, datapath, type_, flags):
         super(OFPStatsRequest, self).__init__(datapath)
         self.type = type_
-        self.flags = 0
+        self.flags = flags
+
+    def to_jsondict(self):
+        # remove some redundant attributes
+        d = super(OFPStatsRequest, self).to_jsondict()
+        v = d[self.__class__.__name__]
+        del v['type']  # implied by subclass
+        return d
 
     def _serialize_stats_body(self):
         pass
@@ -914,8 +942,18 @@ class OFPStatsReply(MsgBase):
             return cls
         return _register_stats_reply_type
 
-    def __init__(self, datapath):
+    def __init__(self, datapath, type_=None, flags=None, body=None):
         super(OFPStatsReply, self).__init__(datapath)
+        self.type = type_
+        self.flags = flags
+        self.body = body
+
+    def to_jsondict(self):
+        # remove some redundant attributes
+        d = super(OFPStatsReply, self).to_jsondict()
+        v = d[self.__class__.__name__]
+        del v['type']  # implied by subclass
+        return d
 
     @classmethod
     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
@@ -943,14 +981,15 @@ class OFPStatsReply(MsgBase):
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPDescStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath):
+    def __init__(self, datapath, flags=0):
         super(OFPDescStatsRequest, self).__init__(datapath,
-                                                  ofproto_v1_2.OFPST_DESC)
+                                                  ofproto_v1_2.OFPST_DESC,
+                                                  flags)
 
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_DESC,
                                          body_single_struct=True)
-class OFPDescStats(collections.namedtuple('OFPDescStats', (
+class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
         'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
     @classmethod
     def parser(cls, buf, offset):
@@ -964,9 +1003,10 @@ class OFPDescStats(collections.namedtuple('OFPDescStats', 
(
 @_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):
+                 cookie, cookie_mask, match, flags=0):
         super(OFPFlowStatsRequest, self).__init__(datapath,
-                                                  ofproto_v1_2.OFPST_FLOW)
+                                                  ofproto_v1_2.OFPST_FLOW,
+                                                  flags)
         self.table_id = table_id
         self.out_port = out_port
         self.out_group = out_group
@@ -988,7 +1028,7 @@ class OFPFlowStatsRequest(OFPStatsRequest):
 
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_FLOW)
-class OFPFlowStats(object):
+class OFPFlowStats(StringifyMixin):
     def __init__(self, length, table_id, duration_sec, duration_nsec,
                  priority, idle_timeout, hard_timeout, cookie, packet_count,
                  byte_count, match, instructions=None):
@@ -1037,10 +1077,11 @@ class OFPFlowStats(object):
 @_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):
+                 cookie, cookie_mask, match, flags=0):
         super(OFPAggregateStatsRequest, self).__init__(
             datapath,
-            ofproto_v1_2.OFPST_AGGREGATE)
+            ofproto_v1_2.OFPST_AGGREGATE,
+            flags)
         self.table_id = table_id
         self.out_port = out_port
         self.out_group = out_group
@@ -1064,7 +1105,7 @@ class OFPAggregateStatsRequest(OFPStatsRequest):
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_AGGREGATE,
                                          body_single_struct=True)
-class OFPAggregateStatsReply(collections.namedtuple('OFPAggregateStats', (
+class OFPAggregateStatsReply(ofproto_parser.namedtuple('OFPAggregateStats', (
         'packet_count', 'byte_count', 'flow_count'))):
     @classmethod
     def parser(cls, buf, offset):
@@ -1078,21 +1119,22 @@ class 
OFPAggregateStatsReply(collections.namedtuple('OFPAggregateStats', (
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPTableStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath):
+    def __init__(self, datapath, flags=0):
         super(OFPTableStatsRequest, self).__init__(datapath,
-                                                   ofproto_v1_2.OFPST_TABLE)
+                                                   ofproto_v1_2.OFPST_TABLE,
+                                                   flags)
 
 
 @OFPStatsReply.register_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'))):
+    ofproto_parser.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(
@@ -1105,9 +1147,10 @@ class OFPTableStats(
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPPortStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath, port_no):
+    def __init__(self, datapath, port_no, flags=0):
         super(OFPPortStatsRequest, self).__init__(datapath,
-                                                  ofproto_v1_2.OFPST_PORT)
+                                                  ofproto_v1_2.OFPST_PORT,
+                                                  flags)
         self.port_no = port_no
 
     def _serialize_stats_body(self):
@@ -1118,13 +1161,13 @@ class OFPPortStatsRequest(OFPStatsRequest):
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_PORT)
 class OFPPortStats(
-    collections.namedtuple('OFPPortStats',
-                           ('port_no', 'rx_packets', 'tx_packets',
-                            'rx_bytes', 'tx_bytes',
-                            'rx_dropped', 'tx_dropped',
-                            'rx_errors', 'tx_errors',
-                            'rx_frame_err', 'rx_over_err',
-                            'rx_crc_err', 'collisions'))):
+    ofproto_parser.namedtuple('OFPPortStats',
+                              ('port_no', 'rx_packets', 'tx_packets',
+                               'rx_bytes', 'tx_bytes',
+                               'rx_dropped', 'tx_dropped',
+                               'rx_errors', 'tx_errors',
+                               'rx_frame_err', 'rx_over_err',
+                               'rx_crc_err', 'collisions'))):
     @classmethod
     def parser(cls, buf, offset):
         port = struct.unpack_from(ofproto_v1_2.OFP_PORT_STATS_PACK_STR,
@@ -1136,9 +1179,10 @@ class OFPPortStats(
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPQueueStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath, port_no, queue_id):
+    def __init__(self, datapath, port_no, queue_id, flags=0):
         super(OFPQueueStatsRequest, self).__init__(datapath,
-                                                   ofproto_v1_2.OFPST_QUEUE)
+                                                   ofproto_v1_2.OFPST_QUEUE,
+                                                   flags)
         self.port_no = port_no
         self.queue_id = queue_id
 
@@ -1150,9 +1194,9 @@ class OFPQueueStatsRequest(OFPStatsRequest):
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_QUEUE)
 class OFPQueueStats(
-    collections.namedtuple('OFPQueueStats',
-                           ('port_no', 'queue_id', 'tx_bytes',
-                            'tx_packets', 'tx_errors'))):
+    ofproto_parser.namedtuple('OFPQueueStats',
+                              ('port_no', 'queue_id', 'tx_bytes',
+                               'tx_packets', 'tx_errors'))):
     @classmethod
     def parser(cls, buf, offset):
         queue = struct.unpack_from(ofproto_v1_2.OFP_QUEUE_STATS_PACK_STR,
@@ -1162,7 +1206,7 @@ class OFPQueueStats(
         return stats
 
 
-class OFPBucketCounter(object):
+class OFPBucketCounter(StringifyMixin):
     def __init__(self, packet_count, byte_count):
         super(OFPBucketCounter, self).__init__()
         self.packet_count = packet_count
@@ -1178,9 +1222,10 @@ class OFPBucketCounter(object):
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPGroupStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath, group_id):
+    def __init__(self, datapath, group_id, flags=0):
         super(OFPGroupStatsRequest, self).__init__(datapath,
-                                                   ofproto_v1_2.OFPST_GROUP)
+                                                   ofproto_v1_2.OFPST_GROUP,
+                                                   flags)
         self.group_id = group_id
 
     def _serialize_stats_body(self):
@@ -1190,7 +1235,7 @@ class OFPGroupStatsRequest(OFPStatsRequest):
 
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_GROUP)
-class OFPGroupStats(object):
+class OFPGroupStats(StringifyMixin):
     def __init__(self, length, group_id, ref_count, packet_count,
                  byte_count, bucket_counters):
         super(OFPGroupStats, self).__init__()
@@ -1222,14 +1267,15 @@ class OFPGroupStats(object):
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPGroupDescStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath):
+    def __init__(self, datapath, flags=0):
         super(OFPGroupDescStatsRequest, self).__init__(
             datapath,
-            ofproto_v1_2.OFPST_GROUP_DESC)
+            ofproto_v1_2.OFPST_GROUP_DESC,
+            flags)
 
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_GROUP_DESC)
-class OFPGroupDescStats(object):
+class OFPGroupDescStats(StringifyMixin):
     def __init__(self, length, type_, group_id, buckets):
         self.length = length
         self.type = type_
@@ -1256,15 +1302,16 @@ class OFPGroupDescStats(object):
 
 @_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
 class OFPGroupFeaturesStatsRequest(OFPStatsRequest):
-    def __init__(self, datapath):
+    def __init__(self, datapath, flags=0):
         super(OFPGroupFeaturesStatsRequest, self).__init__(
             datapath,
-            ofproto_v1_2.OFPST_GROUP_FEATURES)
+            ofproto_v1_2.OFPST_GROUP_FEATURES,
+            flags)
 
 
 @OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_GROUP_FEATURES,
                                          body_single_struct=True)
-class OFPGroupFeaturesStats(object):
+class OFPGroupFeaturesStats(StringifyMixin):
     def __init__(self, types, capabilities, max_groups, actions):
         self.types = types
         self.capabilities = capabilities
@@ -1294,7 +1341,7 @@ class OFPQueueGetConfigRequest(MsgBase):
                       self.buf, ofproto_v1_2.OFP_HEADER_SIZE, self.port)
 
 
-class OFPQueuePropHeader(object):
+class OFPQueuePropHeader(StringifyMixin):
     def __init__(self, property_, len_):
         self.property = property_
         self.len = len_
@@ -1331,7 +1378,7 @@ class OFPQueueProp(OFPQueuePropHeader):
         return cls_.parser(buf, offset)
 
 
-class OFPPacketQueue(object):
+class OFPPacketQueue(StringifyMixin):
     def __init__(self, queue_id, port, len_, properties):
         super(OFPPacketQueue, self).__init__()
         self.queue_id = queue_id
@@ -1518,12 +1565,38 @@ class FlowWildcards(object):
         return not self.wildcards & (1 << shift)
 
 
-class OFPMatch(object):
-    def __init__(self):
+class OFPMatch(StringifyMixin):
+    def __init__(self, fields=[], type_=None, length=None):
         super(OFPMatch, self).__init__()
         self._wc = FlowWildcards()
         self._flow = Flow()
         self.fields = []
+        # accept type_ and length to be compatible with parser
+        if not type_ is None:
+            self.type = type_
+        if not length is None:
+            self.length = length
+        if fields:
+            # we are doing de-stringify.
+            # we have two goals:
+            #   - the resulted object should be serialize()-able.
+            #   - the resulted object should be inspectable by applications.
+            #     ie. fields[] should be filled.
+            # mimic appropriate set_foo calls and the first half of serialize.
+            import sys
+            this_module = sys.modules[__name__]
+            for o in fields:
+                assert len(o) == 1
+                for k, v in o.iteritems():
+                    cls = getattr(this_module, k)
+                    mask = v.get("mask", None)
+                    header = OFPMatchField.cls_to_header(cls, not mask is None)
+                    value = v["value"]
+                    value = self._decode_value(value)
+                    if not mask is None:
+                        mask = self._decode_value(mask)
+                    f = cls(header, value, mask)
+                    self.fields.append(f)
 
     def append_field(self, header, value, mask=None):
         self.fields.append(OFPMatchField.make(header, value, mask))
@@ -1950,7 +2023,7 @@ class OFPMatch(object):
         self._flow.mpls_tc = mpls_tc
 
 
-class OFPMatchField(object):
+class OFPMatchField(StringifyMixin):
     _FIELDS_HEADERS = {}
 
     @staticmethod
@@ -1963,13 +2036,16 @@ class OFPMatchField(object):
 
     def __init__(self, header):
         self.header = header
-        hasmask = (header >> 8) & 1
-        if hasmask:
-            self.n_bytes = (header & 0xff) / 2
-        else:
-            self.n_bytes = header & 0xff
+        self.n_bytes = ofproto_v1_2.oxm_tlv_header_extract_length(header)
         self.length = 0
 
+    @classmethod
+    def cls_to_header(cls, cls_, hasmask):
+        # XXX efficiency
+        inv = dict((v, k) for k, v in cls._FIELDS_HEADERS.iteritems()
+                   if (((k >> 8) & 1) != 0) == hasmask)
+        return inv[cls_]
+
     @staticmethod
     def make(header, value, mask=None):
         cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
@@ -1988,9 +2064,8 @@ class OFPMatchField(object):
 
     @classmethod
     def field_parser(cls, header, buf, offset):
-        hasmask = (header >> 8) & 1
         mask = None
-        if hasmask:
+        if ofproto_v1_2.oxm_tlv_header_extract_hasmask(header):
             pack_str = '!' + cls.pack_str[1:] * 2
             (value, mask) = struct.unpack_from(pack_str, buf, offset + 4)
         else:
@@ -1998,8 +2073,7 @@ class OFPMatchField(object):
         return cls(header, value, mask)
 
     def serialize(self, buf, offset):
-        hasmask = (self.header >> 8) & 1
-        if hasmask:
+        if ofproto_v1_2.oxm_tlv_header_extract_hasmask(self.header):
             self.put_w(buf, offset, self.value, self.mask)
         else:
             self.put(buf, offset, self.value)
@@ -2035,6 +2109,23 @@ class OFPMatchField(object):
     def oxm_len(self):
         return self.header & 0xff
 
+    def to_jsondict(self):
+        # remove some redundant attributes
+        d = super(OFPMatchField, self).to_jsondict()
+        v = d[self.__class__.__name__]
+        del v['header']
+        del v['length']
+        del v['n_bytes']
+        if 'mask' in v and v['mask'] is None:
+            del v['mask']
+        return d
+
+    @classmethod
+    def from_jsondict(cls, dict_):
+        # just pass the dict around.
+        # it will be converted by OFPMatch.__init__().
+        return {cls.__name__: dict_}
+
 
 @OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IN_PORT])
 class MTInPort(OFPMatchField):
@@ -2303,8 +2394,7 @@ class MTArpTha(OFPMatchField):
 class MTIPv6(object):
     @classmethod
     def field_parser(cls, header, buf, offset):
-        hasmask = (header >> 8) & 1
-        if hasmask:
+        if ofproto_v1_2.oxm_tlv_header_extract_hasmask(header):
             pack_str = '!' + cls.pack_str[1:] * 2
             value = struct.unpack_from(pack_str, buf, offset + 4)
             return cls(header, list(value[:8]), list(value[8:]))
-- 
1.8.1.5


------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to