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
