diff options
author | YAMAMOTO Takashi <yamamoto@valinux.co.jp> | 2013-11-20 15:48:29 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-11-20 05:42:58 -0800 |
commit | ad9c7df2eadc99eda44463f54368479945c983c8 (patch) | |
tree | 5c91035973715777d50c72444e5c4481f8b79bee | |
parent | 085717b41fda6d275eb55ff74470534a685d2690 (diff) |
of13: implement EXT-256 (PBB UCA match field)
note: while we usually try to represent on-wire structure as it is,
this code hides on-wire details (the use of experimenter oxm for this
extension), preferring OF1.4 compatibility.
Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/ofproto/ofproto_v1_3.py | 1 | ||||
-rw-r--r-- | ryu/ofproto/oxm_fields.py | 97 |
2 files changed, 80 insertions, 18 deletions
diff --git a/ryu/ofproto/ofproto_v1_3.py b/ryu/ofproto/ofproto_v1_3.py index dcdf48e5..0a2ac97b 100644 --- a/ryu/ofproto/ofproto_v1_3.py +++ b/ryu/ofproto/ofproto_v1_3.py @@ -1057,6 +1057,7 @@ oxm_types = [ oxm_fields.OpenFlowBasic('pbb_isid', 37, oxm_fields.Int3), oxm_fields.OpenFlowBasic('tunnel_id', 38, oxm_fields.Int8), oxm_fields.OpenFlowBasic('ipv6_exthdr', 39, oxm_fields.Int2), + oxm_fields.ONFExperimenter('pbb_uca', 2560, oxm_fields.Int1), ] oxm_fields.generate(__name__) diff --git a/ryu/ofproto/oxm_fields.py b/ryu/ofproto/oxm_fields.py index e1860d03..1f83a70e 100644 --- a/ryu/ofproto/oxm_fields.py +++ b/ryu/ofproto/oxm_fields.py @@ -26,6 +26,7 @@ import itertools import struct +import ofproto_common from ofproto_parser import msg_pack_into from ryu.lib import addrconv @@ -87,17 +88,37 @@ class UnknownType(TypeDescr): OFPXMC_OPENFLOW_BASIC = 0x8000 +OFPXMC_EXPERIMENTER = 0xffff -class OpenFlowBasic(object): - _class = OFPXMC_OPENFLOW_BASIC - +class _OxmClass(object): def __init__(self, name, num, type_): self.name = name - self.num = num | (self._class << 7) + self.oxm_type = num | (self._class << 7) self.type = type_ +class OpenFlowBasic(_OxmClass): + _class = OFPXMC_OPENFLOW_BASIC + + def __init__(self, name, num, type_): + super(OpenFlowBasic, self).__init__(name, num, type_) + self.num = self.oxm_type + + +class _Experimenter(_OxmClass): + _class = OFPXMC_EXPERIMENTER + + +class ONFExperimenter(_Experimenter): + experimenter_id = ofproto_common.ONF_EXPERIMENTER_ID + + def __init__(self, name, num, type_): + super(ONFExperimenter, self).__init__(name, 0, type_) + self.num = (ONFExperimenter, num) + self.exp_type = num + + def generate(modname): import sys import string @@ -110,6 +131,8 @@ def generate(modname): for i in mod.oxm_types: uk = string.upper(i.name) + if isinstance(i.num, tuple): + continue oxm_class = i.num >> 7 if oxm_class != OFPXMC_OPENFLOW_BASIC: continue @@ -123,9 +146,10 @@ def generate(modname): num_to_field = dict((f.num, f) for f in mod.oxm_types) add_attr('oxm_from_user', functools.partial(from_user, name_to_field)) add_attr('oxm_to_user', functools.partial(to_user, num_to_field)) + add_attr('_oxm_field_desc', functools.partial(_field_desc, num_to_field)) add_attr('oxm_normalize_user', functools.partial(normalize_user, mod)) add_attr('oxm_parse', functools.partial(parse, mod)) - add_attr('oxm_serialize', serialize) + add_attr('oxm_serialize', functools.partial(serialize, mod)) add_attr('oxm_to_jsondict', to_jsondict) add_attr('oxm_from_jsondict', from_jsondict) @@ -174,6 +198,10 @@ def to_user(num_to_field, n, v, m): return name, user_value +def _field_desc(num_to_field, n): + return num_to_field[n] + + def normalize_user(mod, k, uv): (n, v, m) = mod.oxm_from_user(k, uv) # apply mask @@ -191,30 +219,63 @@ def parse(mod, buf, offset): hdr_len = struct.calcsize(hdr_pack_str) oxm_type = header >> 9 # class|field oxm_hasmask = mod.oxm_tlv_header_extract_hasmask(header) - value_len = mod.oxm_tlv_header_extract_length(header) + len = mod.oxm_tlv_header_extract_length(header) + oxm_class = oxm_type >> 7 + if oxm_class == OFPXMC_EXPERIMENTER: + exp_hdr_pack_str = '!I' # experimenter_id + (exp_id, ) = struct.unpack_from(exp_hdr_pack_str, buf, + offset + hdr_len) + exp_hdr_len = struct.calcsize(exp_hdr_pack_str) + if exp_id == ofproto_common.ONF_EXPERIMENTER_ID: + onf_exp_type_pack_str = '!H' + (exp_type, ) = struct.unpack_from(onf_exp_type_pack_str, buf, + offset + hdr_len + exp_hdr_len) + exp_hdr_len += struct.calcsize(onf_exp_type_pack_str) + num = (ONFExperimenter, exp_type) + else: + num = oxm_type + exp_hdr_len = 0 + value_offset = offset + hdr_len + exp_hdr_len + value_len = len - exp_hdr_len value_pack_str = '!%ds' % value_len assert struct.calcsize(value_pack_str) == value_len - (value, ) = struct.unpack_from(value_pack_str, buf, - offset + hdr_len) + (value, ) = struct.unpack_from(value_pack_str, buf, value_offset) if oxm_hasmask: (mask, ) = struct.unpack_from(value_pack_str, buf, - offset + hdr_len + value_len) + value_offset + value_len) else: mask = None field_len = hdr_len + (header & 0xff) - return oxm_type, value, mask, field_len - - -def serialize(n, value, mask, buf, offset): + return num, value, mask, field_len + + +def serialize(mod, n, value, mask, buf, offset): + exp_hdr = bytearray() + if isinstance(n, tuple): + (cls, exp_type) = n + desc = mod._oxm_field_desc(n) + assert issubclass(cls, _Experimenter) + assert isinstance(desc, cls) + assert cls is ONFExperimenter + onf_exp_hdr_pack_str = '!IH' # experimenter_id, exp_type + msg_pack_into(onf_exp_hdr_pack_str, exp_hdr, 0, + cls.experimenter_id, exp_type) + assert len(exp_hdr) == struct.calcsize(onf_exp_hdr_pack_str) + n = desc.oxm_type + assert (n >> 7) == OFPXMC_EXPERIMENTER + exp_hdr_len = len(exp_hdr) + value_len = len(value) if mask: - assert len(value) == len(mask) - pack_str = "!I%ds%ds" % (len(value), len(mask)) + assert value_len == len(mask) + pack_str = "!I%ds%ds%ds" % (exp_hdr_len, value_len, len(mask)) msg_pack_into(pack_str, buf, offset, - (n << 9) | (1 << 8) | (len(value) * 2), value, mask) + (n << 9) | (1 << 8) | (exp_hdr_len + value_len * 2), + bytes(exp_hdr), value, mask) else: - pack_str = "!I%ds" % (len(value),) + pack_str = "!I%ds%ds" % (exp_hdr_len, value_len,) msg_pack_into(pack_str, buf, offset, - (n << 9) | (0 << 8) | len(value), value) + (n << 9) | (0 << 8) | (exp_hdr_len + value_len), + bytes(exp_hdr), value) return struct.calcsize(pack_str) |