Will be used for NX learn implementation.
Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
ryu/ofproto/nx_actions.py | 129 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 124 insertions(+), 5 deletions(-)
diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py
index dbe7c8a..a9b1e52 100644
--- a/ryu/ofproto/nx_actions.py
+++ b/ryu/ofproto/nx_actions.py
@@ -17,9 +17,11 @@
import struct
from ryu import utils
+from ryu.lib import type_desc
from ryu.ofproto import nicira_ext
from ryu.ofproto import ofproto_common
from ryu.ofproto.ofproto_parser import msg_pack_into
+from ryu.ofproto.ofproto_parser import StringifyMixin
def generate(ofp_name, ofpp_name):
@@ -30,6 +32,116 @@ def generate(ofp_name, ofpp_name):
ofp = sys.modules[ofp_name]
ofpp = sys.modules[ofpp_name]
+ class _NXFlowSpec(StringifyMixin):
+ _hdr_fmt_str = '!H' # 2 bit 0s, 1 bit src, 2 bit dst, 11 bit n_bits
+ _dst_type = None
+ _subclasses = {}
+
+ def __init__(self, src, dst, n_bits):
+ self.src = src
+ self.dst = dst
+ self.n_bits = n_bits
+
+ @classmethod
+ def register(cls, subcls):
+ assert issubclass(subcls, cls)
+ assert subcls._dst_type not in cls._subclasses
+ cls._subclasses[subcls._dst_type] = subcls
+
+ @classmethod
+ def parse(cls, buf):
+ (hdr,) = struct.unpack_from(cls._hdr_fmt_str, buf, 0)
+ rest = buf[struct.calcsize(cls._hdr_fmt_str):]
+ if hdr == 0:
+ return None, rest # all-0 header is no-op for padding
+ src_type = (hdr >> 13) & 0x1
+ dst_type = (hdr >> 11) & 0x3
+ n_bits = hdr & 0x3ff
+ subcls = cls._subclasses[dst_type]
+ if src_type == 0: # subfield
+ src = cls._parse_subfield(rest)
+ rest = rest[6:]
+ elif src_type == 1: # immediate
+ src_len = (n_bits + 15) / 16 * 2
+ src_bin = rest[:src_len]
+ src = type_desc.IntDescr(size=src_len).to_user(src_bin)
+ rest = rest[src_len:]
+ if dst_type == 0: # match
+ dst = cls._parse_subfield(rest)
+ rest = rest[6:]
+ elif dst_type == 1: # load
+ dst = cls._parse_subfield(rest)
+ rest = rest[6:]
+ elif dst_type == 2: # output
+ dst = '' # empty
+ return subcls(src=src, dst=dst, n_bits=n_bits), rest
+
+ def serialize(self):
+ buf = bytearray()
+ if isinstance(self.src, tuple):
+ src_type = 0 # subfield
+ else:
+ src_type = 1 # immediate
+ # header
+ val = (src_type << 13) | (self._dst_type << 11) | self.n_bits
+ msg_pack_into(self._hdr_fmt_str, buf, 0, val)
+ # src
+ if src_type == 0: # subfield
+ buf += self._serialize_subfield(self.src)
+ elif src_type == 1: # immediate
+ src_len = (self.n_bits + 15) / 16 * 2
+ buf += type_desc.IntDescr(size=src_len).from_user(self.src)
+ # dst
+ if self._dst_type == 0: # match
+ buf += self._serialize_subfield(self.dst)
+ elif self._dst_type == 1: # load
+ buf += self._serialize_subfield(self.dst)
+ elif self._dst_type == 2: # output
+ pass # empty
+ return buf
+
+ @staticmethod
+ def _parse_subfield(buf):
+ (n, len) = ofp.oxm_parse_header(buf, 0)
+ assert len == 4 # only 4-bytes NXM/OXM are defined
+ field = ofp.oxm_to_user_header(n)
+ rest = buf[len:]
+ (ofs,) = struct.unpack_from('!H', rest, 0)
+ return (field, ofs)
+
+ @staticmethod
+ def _serialize_subfield(subfield):
+ (field, ofs) = subfield
+ buf = bytearray()
+ n = ofp.oxm_from_user_header(field)
+ ofp.oxm_serialize_header(n, buf, 0)
+ assert len(buf) == 4 # only 4-bytes NXM/OXM are defined
+ msg_pack_into('!H', buf, 4, ofs)
+ return buf
+
+ class NXFlowSpecMatch(_NXFlowSpec):
+ # Add a match criteria
+ # an example of the corresponding ovs-ofctl syntax:
+ # NXM_OF_VLAN_TCI[0..11]
+ _dst_type = 0
+
+ class NXFlowSpecLoad(_NXFlowSpec):
+ # Add NXAST_REG_LOAD actions
+ # an example of the corresponding ovs-ofctl syntax:
+ # NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
+ _dst_type = 1
+
+ class NXFlowSpecOutput(_NXFlowSpec):
+ # Add an OFPAT_OUTPUT action
+ # an example of the corresponding ovs-ofctl syntax:
+ # output:NXM_OF_IN_PORT[]
+ _dst_type = 2
+
+ def __init__(self, src, n_bits, dst=''):
+ assert dst == ''
+ super(NXFlowSpecOutput, self).__init__(src=src, dst=dst,
+ n_bits=n_bits)
+
class NXAction(ofpp.OFPActionExperimenter):
_fmt_str = '!H' # subtype
_subtypes = {}
@@ -141,11 +253,18 @@ def generate(ofp_name, ofpp_name):
add_attr('NXAction', NXAction)
add_attr('NXActionUnknown', NXActionUnknown)
- actions = [
+ classes = [
'NXActionRegMove',
+ '_NXFlowSpec', # exported for testing
+ 'NXFlowSpecMatch',
+ 'NXFlowSpecLoad',
+ 'NXFlowSpecOutput',
]
vars = locals()
- for a in actions:
- cls = vars[a]
- add_attr(a, cls)
- NXAction.register(cls)
+ for name in classes:
+ cls = vars[name]
+ add_attr(name, cls)
+ if issubclass(cls, NXAction):
+ NXAction.register(cls)
+ if issubclass(cls, _NXFlowSpec):
+ _NXFlowSpec.register(cls)
--
2.1.0
------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel