Signed-off-by: Shinpei Muraoka <[email protected]>
---
 ryu/ofproto/nicira_ext.py                 |   2 +
 ryu/ofproto/nx_actions.py                 | 419 ++++++++++++++++++++++++++++--
 ryu/tests/unit/ofproto/test_parser_v10.py |   1 +
 3 files changed, 398 insertions(+), 24 deletions(-)

diff --git a/ryu/ofproto/nicira_ext.py b/ryu/ofproto/nicira_ext.py
index 74616b5..86ebe1f 100644
--- a/ryu/ofproto/nicira_ext.py
+++ b/ryu/ofproto/nicira_ext.py
@@ -84,6 +84,7 @@ assert calcsize(NX_ACTION_NOTE_PACK_STR) == 
NX_ACTION_NOTE_SIZE
 
 NX_ACTION_BUNDLE_PACK_STR = '!HHIHHHHIHHI4x'
 NX_ACTION_BUNDLE_SIZE = 32
+NX_ACTION_BUNDLE_0_SIZE = 24
 assert calcsize(NX_ACTION_BUNDLE_PACK_STR) == NX_ACTION_BUNDLE_SIZE
 
 NX_ACTION_AUTOPATH_PACK_STR = '!HHIHHII4x'
@@ -108,6 +109,7 @@ assert calcsize(NX_ACTION_FIN_TIMEOUT_PACK_STR) == 
NX_ACTION_FIN_TIMEOUT_SIZE
 
 NX_ACTION_HEADER_PACK_STR = '!HHIH6x'
 NX_ACTION_HEADER_SIZE = 16
+NX_ACTION_HEADER_0_SIZE = 2
 assert calcsize(NX_ACTION_HEADER_PACK_STR) == NX_ACTION_HEADER_SIZE
 
 # Messages
diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py
index 18d0409..b91ce95 100644
--- a/ryu/ofproto/nx_actions.py
+++ b/ryu/ofproto/nx_actions.py
@@ -165,7 +165,7 @@ def generate(ofp_name, ofpp_name):
             rest = buf[struct.calcsize(fmt_str):]
             if subtype_cls is None:
                 return NXActionUnknown(subtype, rest)
-            return subtype_cls.parse(rest)
+            return subtype_cls.parser(rest)
 
         def serialize(self, buf, offset):
             data = self.serialize_body()
@@ -194,13 +194,31 @@ def generate(ofp_name, ofpp_name):
             self.data = data
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             return cls(data=buf)
 
         def serialize_body(self):
             # fixup
             return bytearray() if self.data is None else self.data
 
+    class NXActionPopQueue(NXAction):
+        _subtype = nicira_ext.NXAST_POP_QUEUE
+
+        _fmt_str = '!6x'
+
+        def __init__(self,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionPopQueue, self).__init__()
+
+        @classmethod
+        def parser(cls, buf):
+            return cls()
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0)
+            return data
+
     class NXActionRegLoad(NXAction):
         _subtype = nicira_ext.NXAST_REG_LOAD
         _fmt_str = '!HIQ'  # ofs_nbits, dst, value
@@ -219,7 +237,7 @@ def generate(ofp_name, ofpp_name):
             self.value = value
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             (ofs_nbits, dst, value,) = struct.unpack_from(
                 cls._fmt_str, buf, 0)
             ofs = ofs_nbits >> 6
@@ -240,6 +258,72 @@ def generate(ofp_name, ofpp_name):
                           ofs_nbits, dst_num, self.value)
             return data
 
+    class NXActionNote(NXAction):
+        _subtype = nicira_ext.NXAST_NOTE
+
+        # note
+        _fmt_str = '!%dB'
+
+        # set the integer array in a note
+        def __init__(self,
+                     note,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionNote, self).__init__()
+            self.note = note
+
+        @classmethod
+        def parser(cls, buf):
+            note = struct.unpack_from(
+                cls._fmt_str % len(buf), buf, 0)
+            return cls(list(note))
+
+        def serialize_body(self):
+            assert isinstance(self.note, (tuple, list))
+            for n in self.note:
+                assert isinstance(n, six.integer_types)
+
+            pad = (len(self.note) + nicira_ext.NX_ACTION_HEADER_0_SIZE) % 8
+            if pad:
+                self.note += [0x0 for i in range(8 - pad)]
+            note_len = len(self.note)
+            data = bytearray()
+            msg_pack_into(self._fmt_str % note_len, data, 0,
+                          *self.note)
+            return data
+
+    class _NXActionSetTunnelBase(NXAction):
+        # _subtype, _fmt_str must be attributes of subclass.
+
+        def __init__(self,
+                     tun_id,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(_NXActionSetTunnelBase, self).__init__()
+            self.tun_id = tun_id
+
+        @classmethod
+        def parser(cls, buf):
+            (tun_id,) = struct.unpack_from(
+                cls._fmt_str, buf, 0)
+            return cls(tun_id)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          self.tun_id)
+            return data
+
+    class NXActionSetTunnel(_NXActionSetTunnelBase):
+        _subtype = nicira_ext.NXAST_SET_TUNNEL
+
+        # tun_id
+        _fmt_str = '!2xI'
+
+    class NXActionSetTunnel64(_NXActionSetTunnelBase):
+        _subtype = nicira_ext.NXAST_SET_TUNNEL64
+
+        # tun_id
+        _fmt_str = '!6xQ'
+
     class NXActionRegMove(NXAction):
         _subtype = nicira_ext.NXAST_REG_MOVE
         _fmt_str = '!HHH'  # n_bits, src_ofs, dst_ofs
@@ -261,7 +345,7 @@ def generate(ofp_name, ofpp_name):
             self.dst_field = dst_field
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             (n_bits, src_ofs, dst_ofs,) = struct.unpack_from(
                 cls._fmt_str, buf, 0)
             rest = buf[struct.calcsize(NXActionRegMove._fmt_str):]
@@ -290,6 +374,91 @@ def generate(ofp_name, ofpp_name):
             ofp.oxm_serialize_header(n, data, len(data))
             return data
 
+    class NXActionResubmit(NXAction):
+        _subtype = nicira_ext.NXAST_RESUBMIT
+
+        # in_port
+        _fmt_str = '!H4x'
+
+        def __init__(self,
+                     in_port=0xfff8,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionResubmit, self).__init__()
+            self.in_port = in_port
+
+        @classmethod
+        def parser(cls, buf):
+            (in_port,) = struct.unpack_from(
+                cls._fmt_str, buf, 0)
+            return cls(in_port)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          self.in_port)
+            return data
+
+    class NXActionResubmitTable(NXAction):
+        _subtype = nicira_ext.NXAST_RESUBMIT_TABLE
+
+        # in_port, table_id
+        _fmt_str = '!HB3x'
+
+        def __init__(self,
+                     in_port=0xfff8,
+                     table_id=0xff,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionResubmitTable, self).__init__()
+            self.in_port = in_port
+            self.table_id = table_id
+
+        @classmethod
+        def parser(cls, buf):
+            (in_port,
+             table_id) = struct.unpack_from(
+                cls._fmt_str, buf, 0)
+            return cls(in_port, table_id)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          self.in_port, self.table_id)
+            return data
+
+    class NXActionOutputReg(NXAction):
+        _subtype = nicira_ext.NXAST_OUTPUT_REG
+
+        # ofs_nbits, src, max_len
+        _fmt_str = '!HIH6x'
+
+        def __init__(self,
+                     ofs_nbits,
+                     src,
+                     max_len,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionOutputReg, self).__init__()
+            self.ofs_nbits = ofs_nbits
+            self.src = src
+            self.max_len = max_len
+
+        @classmethod
+        def parser(cls, buf):
+            (ofs_nbits,
+             src,
+             max_len) = struct.unpack_from(
+                cls._fmt_str, buf, 0)
+            return cls(ofs_nbits,
+                       src,
+                       max_len)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          ofs_nbits,
+                          self.src,
+                          self.max_len)
+            return data
+
     class NXActionLearn(NXAction):
         _subtype = nicira_ext.NXAST_LEARN
 
@@ -321,7 +490,7 @@ def generate(ofp_name, ofpp_name):
             self.specs = specs
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             (idle_timeout,
              hard_timeout,
              priority,
@@ -365,6 +534,87 @@ def generate(ofp_name, ofpp_name):
                 data += spec.serialize()
             return data
 
+    class NXActionExit(NXAction):
+        _subtype = nicira_ext.NXAST_EXIT
+
+        _fmt_str = '!6x'
+
+        def __init__(self,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionExit, self).__init__()
+
+        @classmethod
+        def parser(cls, buf):
+            return cls()
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0)
+            return data
+
+    class NXActionController(NXAction):
+        _subtype = nicira_ext.NXAST_CONTROLLER
+
+        # max_len, controller_id, reason
+        _fmt_str = '!HHBx'
+
+        def __init__(self,
+                     max_len,
+                     controller_id,
+                     reason,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionController, self).__init__()
+            self.max_len = max_len
+            self.controller_id = controller_id
+            self.reason = reason
+
+        @classmethod
+        def parser(cls, buf):
+            (max_len,
+             controller_id,
+             reason) = struct.unpack_from(
+                cls._fmt_str, buf)
+            return cls(max_len,
+                       controller_id,
+                       reason)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          self.max_len,
+                          self.controller_id,
+                          self.reason)
+            return data
+
+    class NXActionFinTimeout(NXAction):
+        _subtype = nicira_ext.NXAST_FIN_TIMEOUT
+
+        # fin_idle_timeout, fin_hard_timeout
+        _fmt_str = '!HH2x'
+
+        def __init__(self,
+                     fin_idle_timeout,
+                     fin_hard_timeout,
+                     type_=None, len_=None, experimenter=None, subtype=None):
+            super(NXActionFinTimeout, self).__init__()
+            self.fin_idle_timeout = fin_idle_timeout
+            self.fin_hard_timeout = fin_hard_timeout
+
+        @classmethod
+        def parser(cls, buf):
+            (fin_idle_timeout,
+             fin_hard_timeout) = struct.unpack_from(
+                cls._fmt_str, buf, 0)
+            return cls(fin_idle_timeout,
+                       fin_hard_timeout)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          self.fin_idle_timeout,
+                          self.fin_hard_timeout)
+            return data
+
     class NXActionConjunction(NXAction):
         _subtype = nicira_ext.NXAST_CONJUNCTION
 
@@ -382,7 +632,7 @@ def generate(ofp_name, ofpp_name):
             self.id = id_
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             (clause,
              n_clauses,
              id_,) = struct.unpack_from(
@@ -397,34 +647,143 @@ def generate(ofp_name, ofpp_name):
                           self.id)
             return data
 
-    class NXActionResubmitTable(NXAction):
-        _subtype = nicira_ext.NXAST_RESUBMIT_TABLE
+    class NXActionMultipath(NXAction):
+        _subtype = nicira_ext.NXAST_MULTIPATH
 
-        # in_port, table_id
-        _fmt_str = '!HB3x'
+        # fields, basis, algorithm, max_link,
+        # arg, ofs_nbits, dst
+        _fmt_str = '!HH2xHHI2xHI'
 
         def __init__(self,
-                     in_port,
-                     table_id,
+                     fields,
+                     basis,
+                     algorithm,
+                     max_link,
+                     arg,
+                     ofs_nbits,
+                     dst,
                      type_=None, len_=None, experimenter=None, subtype=None):
-            super(NXActionResubmitTable, self).__init__()
-            self.in_port = in_port
-            self.table_id = table_id
+            super(NXActionMultipath, self).__init__()
+            self.fields = fields
+            self.basis = basis
+            self.algorithm = algorithm
+            self.max_link = max_link
+            self.arg = arg
+            self.ofs_nbits = ofs_nbits
+            self.dst = dst
 
         @classmethod
-        def parse(cls, buf):
-            (in_port,
-             table_id) = struct.unpack_from(
+        def parser(cls, buf):
+            (fields,
+             basis,
+             algorithm,
+             max_link,
+             arg,
+             ofs_nbits,
+             dst) = struct.unpack_from(
                 cls._fmt_str, buf, 0)
-            return cls(in_port, table_id)
+            return cls(fields,
+                       basis,
+                       algorithm,
+                       max_link,
+                       arg,
+                       ofs_nbits,
+                       dst)
+
+        def serialize_body(self):
+            data = bytearray()
+            msg_pack_into(self._fmt_str, data, 0,
+                          self.fields,
+                          self.basis,
+                          self.algorithm,
+                          self.max_link,
+                          self.arg,
+                          self.ofs_nbits,
+                          self.dst)
+            return data
+
+    class _NXActionBundleBase(NXAction):
+        # algorithm, fields, basis, slave_type, n_slaves
+        # ofs_nbits, dst, slaves
+        _fmt_str = '!HHHIHHI4x'
+
+        def __init__(self, algorithm, fields, basis, slave_type, n_slaves,
+                     ofs_nbits, dst, slaves):
+            super(_NXActionBundleBase, self).__init__()
+            self.len = utils.round_up(
+                nicira_ext.NX_ACTION_BUNDLE_0_SIZE + len(slaves) * 2, 8)
+
+            self.algorithm = algorithm
+            self.fields = fields
+            self.basis = basis
+            self.slave_type = slave_type
+            self.n_slaves = n_slaves
+            self.ofs_nbits = ofs_nbits
+            self.dst = dst
+
+            assert isinstance(slaves, (list, tuple))
+            for s in slaves:
+                assert isinstance(s, six.integer_types)
+
+            self.slaves = slaves
+
+        @classmethod
+        def parser(cls, buf):
+            (algorithm, fields, basis,
+                slave_type, n_slaves, ofs_nbits, dst) = struct.unpack_from(
+                cls._fmt_str, buf, 0)
+            slave_offset = (nicira_ext.NX_ACTION_BUNDLE_0_SIZE -
+                            nicira_ext.NX_ACTION_HEADER_0_SIZE)
+
+            slaves = []
+            for i in range(0, n_slaves):
+                s = struct.unpack_from('!H', buf, slave_offset)
+                slaves.append(s[0])
+                slave_offset += 2
+
+            return cls(algorithm, fields, basis, slave_type,
+                       n_slaves, ofs_nbits, dst, slaves)
 
         def serialize_body(self):
             data = bytearray()
+            slave_offset = (nicira_ext.NX_ACTION_BUNDLE_0_SIZE -
+                            nicira_ext.NX_ACTION_HEADER_0_SIZE)
+            self.n_slaves = len(self.slaves)
+            for s in self.slaves:
+                msg_pack_into('!H', data, slave_offset, s)
+                slave_offset += 2
+            pad_len = (utils.round_up(self.n_slaves, 4) -
+                       self.n_slaves)
+
+            if pad_len != 0:
+                msg_pack_into('%dx' % pad_len * 2, data, slave_offset)
+
             msg_pack_into(self._fmt_str, data, 0,
-                          self.in_port,
-                          self.table_id)
+                          self.algorithm, self.fields, self.basis,
+                          self.slave_type, self.n_slaves,
+                          self.ofs_nbits, self.dst)
+
             return data
 
+    class NXActionBundle(_NXActionBundleBase):
+        _subtype = nicira_ext.NXAST_BUNDLE
+
+        def __init__(self, algorithm, fields, basis, slave_type, n_slaves,
+                     ofs_nbits, dst, slaves):
+            # NXAST_BUNDLE actions should have 'ofs_nbits' and 'dst' zeroed.
+            super(NXActionBundle, self).__init__(
+                algorithm, fields, basis, slave_type, n_slaves,
+                ofs_nbits=0, dst=0, slaves=slaves)
+
+    class NXActionBundleLoad(_NXActionBundleBase):
+        _subtype = nicira_ext.NXAST_BUNDLE_LOAD
+
+        def __init__(self, algorithm, fields, basis, slave_type, n_slaves,
+                     ofs_nbits, dst, slaves):
+            super(NXActionBundleLoad, self).__init__(
+                algorithm, fields, basis, slave_type, n_slaves,
+                ofs_nbits, dst, slaves)
+
     class NXActionCT(NXAction):
         _subtype = nicira_ext.NXAST_CT
 
@@ -450,7 +809,7 @@ def generate(ofp_name, ofpp_name):
             self.actions = actions
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             (flags,
              zone_src,
              zone_ofs_nbits,
@@ -515,7 +874,7 @@ def generate(ofp_name, ofpp_name):
             self.range_proto_max = range_proto_max
 
         @classmethod
-        def parse(cls, buf):
+        def parser(cls, buf):
             (flags,
              range_present) = struct.unpack_from(
                 cls._fmt_str, buf, 0)
@@ -591,11 +950,23 @@ def generate(ofp_name, ofpp_name):
     add_attr('NXActionUnknown', NXActionUnknown)
 
     classes = [
+        'NXActionPopQueue',
         'NXActionRegLoad',
+        'NXActionNote',
+        'NXActionSetTunnel',
+        'NXActionSetTunnel64',
         'NXActionRegMove',
+        'NXActionResubmit',
+        'NXActionResubmitTable',
+        'NXActionOutputReg',
         'NXActionLearn',
+        'NXActionExit',
+        'NXActionController',
+        'NXActionFinTimeout',
         'NXActionConjunction',
-        'NXActionResubmitTable',
+        'NXActionMultipath',
+        'NXActionBundle',
+        'NXActionBundleLoad',
         'NXActionCT',
         'NXActionNAT',
         '_NXFlowSpec',  # exported for testing
diff --git a/ryu/tests/unit/ofproto/test_parser_v10.py 
b/ryu/tests/unit/ofproto/test_parser_v10.py
index 02ce69b..6e025e4 100644
--- a/ryu/tests/unit/ofproto/test_parser_v10.py
+++ b/ryu/tests/unit/ofproto/test_parser_v10.py
@@ -20,6 +20,7 @@ import logging
 import six
 from nose.tools import *
 from ryu.ofproto.ofproto_v1_0_parser import *
+from ryu.ofproto.nx_actions import *
 from ryu.ofproto import ofproto_v1_0_parser
 from ryu.lib import addrconv
 
-- 
1.9.1


------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity 
planning reports. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to