summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYAMAMOTO Takashi <yamamoto@valinux.co.jp>2015-01-19 16:48:26 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-01-20 13:12:48 +0900
commitcbb387f8eb97c751d4af34a7246e5e34073fba87 (patch)
tree3fb705c63923ce38e2549eb4de49a335c58549f5
parent1a03f4c65022340240313b1c6bac3684d43f5180 (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.py154
-rw-r--r--ryu/ofproto/ofproto_v1_3_parser.py46
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'
+)