Add OF1.4 OFPMatchField support

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 <horms@verge.net.au>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Simon Horman 2014-01-29 12:05:54 +09:00 committed by FUJITA Tomonori
parent 4a52daee65
commit ec18b3f0f1
2 changed files with 561 additions and 0 deletions

View File

@ -314,6 +314,9 @@ 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

View File

@ -568,6 +568,564 @@ 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()
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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)
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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)
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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)
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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
@OFPMatchField.register_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):