diff options
author | YAMAMOTO Takashi <yamamoto@valinux.co.jp> | 2015-01-19 16:48:26 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-01-20 13:12:48 +0900 |
commit | cbb387f8eb97c751d4af34a7246e5e34073fba87 (patch) | |
tree | 3fb705c63923ce38e2549eb4de49a335c58549f5 | |
parent | 1a03f4c65022340240313b1c6bac3684d43f5180 (diff) |
Implement nx_action_reg_move for OpenFlow 1.3
Also, improve experimenter action related code so that
it can handle unknown actions as unknown.
Only OpenFlow 1.3 for now because this is planned to be used
for Neutron OVS agent and 1.3 is the version to be used there.
(https://blueprints.launchpad.net/neutron/+spec/ovs-ofctl-to-python)
Following the style of oxm_fields, make an OpenFlow version independent
module generate OpenFlow version specific code so that it's easier to
add the functionality to other OpenFlow versions later.
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/nx_actions.py | 154 | ||||
-rw-r--r-- | ryu/ofproto/ofproto_v1_3_parser.py | 46 |
2 files changed, 193 insertions, 7 deletions
diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py new file mode 100644 index 00000000..b8879e6c --- /dev/null +++ b/ryu/ofproto/nx_actions.py @@ -0,0 +1,154 @@ +# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +# Copyright (C) 2015 YAMAMOTO Takashi <yamamoto at valinux co jp> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import struct + +from ryu import utils +from ryu.ofproto import nicira_ext +from ryu.ofproto import ofproto_common +from ryu.ofproto.ofproto_parser import msg_pack_into + + +def generate(ofp_name, ofpp_name): + import sys + import string + import functools + + ofp = sys.modules[ofp_name] + ofpp = sys.modules[ofpp_name] + + class NXAction(ofpp.OFPActionExperimenter): + _fmt_str = '!H' # subtype + _subtypes = {} + experimenter = ofproto_common.NX_EXPERIMENTER_ID + + def __init__(self): + super(NXAction, self).__init__(experimenter=self.experimenter) + self.subtype = self.subtype + + @classmethod + def parse(cls, buf): + fmt_str = NXAction._fmt_str + (subtype,) = struct.unpack_from(fmt_str, buf, 0) + subtype_cls = cls._subtypes.get(subtype) + rest = buf[struct.calcsize(fmt_str):] + if subtype_cls is None: + return NXActionUnknown(subtype, rest) + return subtype_cls.parse(rest) + + def serialize(self, buf, offset): + super(NXAction, self).serialize(buf, offset) + msg_pack_into(NXAction._fmt_str, + buf, + offset + ofp.OFP_ACTION_EXPERIMENTER_HEADER_SIZE, + self.subtype) + + @classmethod + def register(cls, subtype_cls): + assert subtype_cls.subtype is not cls._subtypes + cls._subtypes[subtype_cls.subtype] = subtype_cls + + class NXActionUnknown(NXAction): + def __init__(self, subtype, data=None, + type_=None, len_=None, experimenter=None): + self.subtype = subtype + super(NXActionUnknown, self).__init__() + self.data = data + + @classmethod + def parse(cls, subtype, buf): + return cls(data=buf) + + def serialize(self, buf, offset): + # fixup + data = self.data + if data is None: + data = bytearray() + payload_offset = ( + ofp.OFP_ACTION_EXPERIMENTER_HEADER_SIZE + + struct.calcsize(NXAction._fmt_str) + ) + self.len = utils.round_up(payload_offset + len(data), 8) + super(NXActionUnknown, self).serialize(buf, offset) + buf += data + + class NXActionRegMove(NXAction): + subtype = nicira_ext.NXAST_REG_MOVE + _fmt_str = '!HHH' # n_bits, src_ofs, dst_ofs + # Followed by OXM fields (src, dst) and padding to 8 bytes boundary + + def __init__(self, src_field, dst_field, n_bits, src_ofs=0, dst_ofs=0, + type_=None, len_=None, experimenter=None, subtype=None): + super(NXActionRegMove, self).__init__() + self.experimenter = ofproto_common.NX_EXPERIMENTER_ID + self.subtype = self.subtype + self.n_bits = n_bits + self.src_ofs = src_ofs + self.dst_ofs = dst_ofs + self.src_field = src_field + self.dst_field = dst_field + + @classmethod + def parse(cls, buf): + (n_bits, src_ofs, dst_ofs,) = struct.unpack_from( + NXActionRegMove._fmt_str, buf, 0) + rest = buf[struct.calcsize(NXActionRegMove._fmt_str):] + # src field + (n, len) = ofp.oxm_parse_header(rest, 0) + src_field = ofp.oxm_to_user_header(n) + rest = rest[len:] + # dst field + (n, len) = ofp.oxm_parse_header(rest, 0) + dst_field = ofp.oxm_to_user_header(n) + rest = rest[len:] + # ignore padding + return cls(src_field, dst_field=dst_field, n_bits=n_bits, + src_ofs=src_ofs, dst_ofs=dst_ofs) + + def serialize(self, buf, offset): + # fixup + data = bytearray() + msg_pack_into(NXActionRegMove._fmt_str, data, 0, + self.n_bits, self.src_ofs, self.dst_ofs) + # src field + n = ofp.oxm_from_user_header(self.src_field) + ofp.oxm_serialize_header(n, data, len(data)) + # dst field + n = ofp.oxm_from_user_header(self.dst_field) + ofp.oxm_serialize_header(n, data, len(data)) + payload_offset = ( + ofp.OFP_ACTION_EXPERIMENTER_HEADER_SIZE + + struct.calcsize(NXAction._fmt_str) + ) + self.len = utils.round_up(payload_offset + len(data), 8) + super(NXActionRegMove, self).serialize(buf, offset) + msg_pack_into('!%ds' % len(data), buf, offset + payload_offset, + bytes(data)) + + def add_attr(k, v): + setattr(ofpp, k, v) + + add_attr('NXAction', NXAction) + add_attr('NXActionUnknown', NXActionUnknown) + + actions = [ + 'NXActionRegMove', + ] + vars = locals() + for a in actions: + cls = vars[a] + add_attr(a, cls) + NXAction.register(cls) diff --git a/ryu/ofproto/ofproto_v1_3_parser.py b/ryu/ofproto/ofproto_v1_3_parser.py index 1d2d671b..e9b4b293 100644 --- a/ryu/ofproto/ofproto_v1_3_parser.py +++ b/ryu/ofproto/ofproto_v1_3_parser.py @@ -48,6 +48,7 @@ from ryu.lib import mac from ryu import utils from ofproto_parser import StringifyMixin, MsgBase, msg_pack_into, msg_str_attr from . import ether +from . import nicira_ext from . import ofproto_parser from . import ofproto_common from . import ofproto_v1_3 as ofproto @@ -3225,12 +3226,12 @@ class OFPActionExperimenter(OFPAction): experimenter Experimenter ID ================ ====================================================== """ - def __init__(self, experimenter, data=None, type_=None, len_=None): + + def __init__(self, experimenter): super(OFPActionExperimenter, self).__init__() + self.type = ofproto.OFPAT_EXPERIMENTER self.experimenter = experimenter - self.data = data - self.len = (utils.round_up(len(data), 8) + - ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE) + self.len = None @classmethod def parser(cls, buf, offset): @@ -3238,13 +3239,36 @@ class OFPActionExperimenter(OFPAction): ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset) data = buf[(offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE ): offset + len_] - return cls(experimenter, data) + if experimenter == ofproto_common.NX_EXPERIMENTER_ID: + obj = NXAction.parse(data) + else: + obj = OFPActionExperimenterUnknown(experimenter, data) + obj.len = len_ + return obj def serialize(self, buf, offset): msg_pack_into(ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset, self.type, self.len, self.experimenter) - if self.data: - buf += self.data + + +class OFPActionExperimenterUnknown(OFPActionExperimenter): + def __init__(self, experimenter, data=None, type_=None, len_=None): + super(OFPActionExperimenterUnknown, + self).__init__(experimenter=experimenter) + self.data = data + + def serialize(self, buf, offset): + # fixup + data = self.data + if data is None: + data = bytearray() + self.len = (utils.round_up(len(data), 8) + + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE) + super(OFPActionExperimenterUnknown, self).serialize(buf, offset) + msg_pack_into('!%ds' % len(self.data), + buf, + offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE, + self.data) class OFPBucket(StringifyMixin): @@ -6014,3 +6038,11 @@ class OFPSetAsync(MsgBase): self.packet_in_mask[0], self.packet_in_mask[1], self.port_status_mask[0], self.port_status_mask[1], self.flow_removed_mask[0], self.flow_removed_mask[1]) + + +import nx_actions + +nx_actions.generate( + 'ryu.ofproto.ofproto_v1_3', + 'ryu.ofproto.ofproto_v1_3_parser' +) |