This covers fields that are also present in OF1.3.
In particular it does not cover PBB_UCA.
I plan to address this in a subsequent patch.

Signed-off-by: Simon Horman <[email protected]>
---
 ryu/ofproto/ofproto_v1_4.py        |   2 +
 ryu/ofproto/ofproto_v1_4_parser.py | 560 +++++++++++++++++++++++++++++++++++++
 2 files changed, 562 insertions(+)

diff --git a/ryu/ofproto/ofproto_v1_4.py b/ryu/ofproto/ofproto_v1_4.py
index d987835..49d8341 100644
--- a/ryu/ofproto/ofproto_v1_4.py
+++ b/ryu/ofproto/ofproto_v1_4.py
@@ -314,6 +314,8 @@ OFPXMC_NXM_1 = 0x0001  # Backward compatibility with NXM
 OFPXMC_OPENFLOW_BASIC = 0x8000  # Basic class for OpenFlow
 OFPXMC_EXPERIMENTER = 0xFFFF  # Experimenter class
 
+# enum ofp_vlan_id
+OFPVID_PRESENT = 0x1000  # bit that indicate that a VLAN id is set.
 
 def _oxm_tlv_header(class_, field, hasmask, length):
     return (class_ << 16) | (field << 9) | (hasmask << 8) | length
diff --git a/ryu/ofproto/ofproto_v1_4_parser.py 
b/ryu/ofproto/ofproto_v1_4_parser.py
index 0b1cd47..facfab3 100644
--- a/ryu/ofproto/ofproto_v1_4_parser.py
+++ b/ryu/ofproto/ofproto_v1_4_parser.py
@@ -567,6 +567,566 @@ class OFPPortDescPropEthernet(StringifyMixin):
         return ether
 
 
+class OFPMatchField(StringifyMixin):
+    _FIELDS_HEADERS = {}
+
+    @staticmethod
+    def register_field_header(headers):
+        def _register_field_header(cls):
+            for header in headers:
+                OFPMatchField._FIELDS_HEADERS[header] = cls
+            return cls
+        return _register_field_header
+
+    def __init__(self, header):
+        self.header = header
+        self.n_bytes = ofproto.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)
+        return cls_(header, value, mask)
+
+    @classmethod
+    def parser(cls, buf, offset):
+        (header,) = struct.unpack_from('!I', buf, offset)
+        cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
+        if cls_:
+            field = cls_.field_parser(header, buf, offset)
+        else:
+            field = OFPMatchField(header)
+        field.length = (header & 0xff) + 4
+        return field
+
+    @classmethod
+    def field_parser(cls, header, buf, offset):
+        hasmask = (header >> 8) & 1
+        mask = None
+        if ofproto.oxm_tlv_header_extract_hasmask(header):
+            pack_str = '!' + cls.pack_str[1:] * 2
+            (value, mask) = struct.unpack_from(pack_str, buf, offset + 4)
+        else:
+            (value,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
+        return cls(header, value, mask)
+
+    def serialize(self, buf, offset):
+        if ofproto.oxm_tlv_header_extract_hasmask(self.header):
+            self.put_w(buf, offset, self.value, self.mask)
+        else:
+            self.put(buf, offset, self.value)
+
+    def _put_header(self, buf, offset):
+        ofproto_parser.msg_pack_into('!I', buf, offset, self.header)
+        self.length = 4
+
+    def _put(self, buf, offset, value):
+        ofproto_parser.msg_pack_into(self.pack_str, buf, offset, value)
+        self.length += self.n_bytes
+
+    def put_w(self, buf, offset, value, mask):
+        self._put_header(buf, offset)
+        self._put(buf, offset + self.length, value)
+        self._put(buf, offset + self.length, mask)
+
+    def put(self, buf, offset, value):
+        self._put_header(buf, offset)
+        self._put(buf, offset + self.length, value)
+
+    def _putv6(self, buf, offset, value):
+        ofproto_parser.msg_pack_into(self.pack_str, buf, offset,
+                                     *value)
+        self.length += self.n_bytes
+
+    def putv6(self, buf, offset, value, mask=None):
+        self._put_header(buf, offset)
+        self._putv6(buf, offset + self.length, value)
+        if mask and len(mask):
+            self._putv6(buf, offset + self.length, mask)
+
+    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']
+        return d
+
+    @classmethod
+    def from_jsondict(cls, dict_):
+        # just pass the dict around.
+        # it will be converted by OFPMatch.__init__().
+        return {cls.__name__: dict_}
+
+    def stringify_attrs(self):
+        f = super(OFPMatchField, self).stringify_attrs
+        if not ofproto.oxm_tlv_header_extract_hasmask(self.header):
+            # something like the following, but yield two values (k,v)
+            # return itertools.ifilter(lambda k, v: k != 'mask', iter())
+            def g():
+                for k, v in f():
+                    if k != 'mask':
+                        yield (k, v)
+            return g()
+        else:
+            return f()
+
+
[email protected]_field_header([ofproto.OXM_OF_IN_PORT])
+class MTInPort(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTInPort, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_METADATA,
+                                      ofproto.OXM_OF_METADATA_W])
+class MTMetadata(OFPMatchField):
+    pack_str = '!Q'
+
+    def __init__(self, header, value, mask=None):
+        super(MTMetadata, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_IN_PHY_PORT])
+class MTInPhyPort(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTInPhyPort, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ETH_DST,
+                                      ofproto.OXM_OF_ETH_DST_W])
+class MTEthDst(OFPMatchField):
+    pack_str = '!6s'
+
+    def __init__(self, header, value, mask=None):
+        super(MTEthDst, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_ETH_SRC,
+                                      ofproto.OXM_OF_ETH_SRC_W])
+class MTEthSrc(OFPMatchField):
+    pack_str = '!6s'
+
+    def __init__(self, header, value, mask=None):
+        super(MTEthSrc, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_ETH_TYPE])
+class MTEthType(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTEthType, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_VLAN_VID,
+                                      ofproto.OXM_OF_VLAN_VID_W])
+class MTVlanVid(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTVlanVid, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+    @classmethod
+    def field_parser(cls, header, buf, offset):
+        m = super(MTVlanVid, cls).field_parser(header, buf, offset)
+        m.value &= ~ofproto.OFPVID_PRESENT
+        return m
+
+    def serialize(self, buf, offset):
+        self.value |= ofproto.OFPVID_PRESENT
+        super(MTVlanVid, self).serialize(buf, offset)
+
+
[email protected]_field_header([ofproto.OXM_OF_VLAN_PCP])
+class MTVlanPcp(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTVlanPcp, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_IP_DSCP])
+class MTIPDscp(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPDscp, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_IP_ECN])
+class MTIPECN(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPECN, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_IP_PROTO])
+class MTIPProto(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPProto, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV4_SRC,
+                                      ofproto.OXM_OF_IPV4_SRC_W])
+class MTIPV4Src(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPV4Src, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV4_DST,
+                                      ofproto.OXM_OF_IPV4_DST_W])
+class MTIPV4Dst(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPV4Dst, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_TCP_SRC])
+class MTTCPSrc(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTTCPSrc, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_TCP_DST])
+class MTTCPDst(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTTCPDst, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_UDP_SRC])
+class MTUDPSrc(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTUDPSrc, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_UDP_DST])
+class MTUDPDst(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTUDPDst, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_SCTP_SRC])
+class MTSCTPSrc(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTSCTPSrc, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_SCTP_DST])
+class MTSCTPDst(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTSCTPDst, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ICMPV4_TYPE])
+class MTICMPV4Type(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTICMPV4Type, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ICMPV4_CODE])
+class MTICMPV4Code(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTICMPV4Code, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ARP_OP])
+class MTArpOp(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTArpOp, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ARP_SPA,
+                                      ofproto.OXM_OF_ARP_SPA_W])
+class MTArpSpa(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTArpSpa, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_ARP_TPA,
+                                      ofproto.OXM_OF_ARP_TPA_W])
+class MTArpTpa(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTArpTpa, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_ARP_SHA,
+                                      ofproto.OXM_OF_ARP_SHA_W])
+class MTArpSha(OFPMatchField):
+    pack_str = '!6s'
+
+    def __init__(self, header, value, mask=None):
+        super(MTArpSha, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_ARP_THA,
+                                      ofproto.OXM_OF_ARP_THA_W])
+class MTArpTha(OFPMatchField):
+    pack_str = '!6s'
+
+    def __init__(self, header, value, mask=None):
+        super(MTArpTha, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
+class MTIPv6(StringifyMixin):
+    @classmethod
+    def field_parser(cls, header, buf, offset):
+        if ofproto.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:]))
+        else:
+            value = struct.unpack_from(cls.pack_str, buf, offset + 4)
+            return cls(header, list(value))
+
+    def serialize(self, buf, offset):
+        self.putv6(buf, offset, self.value, self.mask)
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_SRC,
+                                      ofproto.OXM_OF_IPV6_SRC_W])
+class MTIPv6Src(MTIPv6, OFPMatchField):
+    pack_str = '!8H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6Src, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_DST,
+                                      ofproto.OXM_OF_IPV6_DST_W])
+class MTIPv6Dst(MTIPv6, OFPMatchField):
+    pack_str = '!8H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6Dst, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_FLABEL,
+                                      ofproto.OXM_OF_IPV6_FLABEL_W])
+class MTIPv6Flabel(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6Flabel, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_MPLS_LABEL])
+class MTMplsLabel(OFPMatchField):
+    pack_str = '!I'
+
+    def __init__(self, header, value, mask=None):
+        super(MTMplsLabel, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ICMPV6_TYPE])
+class MTICMPV6Type(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTICMPV6Type, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_ICMPV6_CODE])
+class MTICMPV6Code(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTICMPV6Code, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_ND_TARGET])
+class MTIPv6NdTarget(MTIPv6, OFPMatchField):
+    pack_str = '!8H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6NdTarget, self).__init__(header)
+        self.value = value
+
+    def serialize(self, buf, offset):
+        self.putv6(buf, offset, self.value)
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_ND_SLL])
+class MTIPv6NdSll(OFPMatchField):
+    pack_str = '!6s'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6NdSll, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_ND_TLL])
+class MTIPv6NdTll(OFPMatchField):
+    pack_str = '!6s'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6NdTll, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_MPLS_TC])
+class MTMplsTc(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTMplsTc, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_MPLS_BOS])
+class MTMplsBos(OFPMatchField):
+    pack_str = '!B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTMplsBos, self).__init__(header)
+        self.value = value
+
+
[email protected]_field_header([ofproto.OXM_OF_PBB_ISID,
+                                      ofproto.OXM_OF_PBB_ISID_W])
+class MTPbbIsid(OFPMatchField):
+    pack_str = '!3B'
+
+    def __init__(self, header, value, mask=None):
+        super(MTPbbIsid, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+    @classmethod
+    def field_parser(cls, header, buf, offset):
+        hasmask = (header >> 8) & 1
+        mask = None
+        if ofproto.oxm_tlv_header_extract_hasmask(header):
+            pack_str = '!' + cls.pack_str[1:] * 2
+            (v1, v2, v3, m1, m2, m3) = struct.unpack_from(pack_str, buf,
+                                                          offset + 4)
+            value = v1 << 16 | v2 << 8 | v3
+            mask = m1 << 16 | m2 << 8 | m3
+        else:
+            (v1, v2, v3,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
+            value = v1 << 16 | v2 << 8 | v3
+        return cls(header, value, mask)
+
+    def _put(self, buf, offset, value):
+        ofproto_parser.msg_pack_into(self.pack_str, buf, offset,
+                                     (value >> 16) & 0xff,
+                                     (value >> 8) & 0xff,
+                                     (value >> 0) & 0xff)
+        self.length += self.n_bytes
+
+
[email protected]_field_header([ofproto.OXM_OF_TUNNEL_ID,
+                                      ofproto.OXM_OF_TUNNEL_ID_W])
+class MTTunnelId(OFPMatchField):
+    pack_str = '!Q'
+
+    def __init__(self, header, value, mask=None):
+        super(MTTunnelId, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
[email protected]_field_header([ofproto.OXM_OF_IPV6_EXTHDR,
+                                      ofproto.OXM_OF_IPV6_EXTHDR_W])
+class MTIPv6ExtHdr(OFPMatchField):
+    pack_str = '!H'
+
+    def __init__(self, header, value, mask=None):
+        super(MTIPv6ExtHdr, self).__init__(header)
+        self.value = value
+        self.mask = mask
+
+
+
+
 @_register_parser
 @_set_msg_type(ofproto.OFPT_PACKET_IN)
 class OFPPacketIn(MsgBase):
-- 
1.8.4


------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to