a new api to compose matches.  it looks like:

    match = OFPMatch(in_port=1,
                     eth_type=0x86dd,
                     ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee',
                               'ffff:ffff:ffff:ffff::'),
                     ipv6_dst = '2001:db8:bd05:1d2:288a:1fc0:1:10ee')

the old match.set_foo and match.append_field methods are kept for now
but will be removed later.

Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
 ryu/ofproto/ofproto_v1_3_parser.py | 56 +++++++++++++++++++++++++++++++++-
 ryu/ofproto/oxm_fields.py          | 62 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/ryu/ofproto/ofproto_v1_3_parser.py 
b/ryu/ofproto/ofproto_v1_3_parser.py
index 77af01f..2a4e472 100644
--- a/ryu/ofproto/ofproto_v1_3_parser.py
+++ b/ryu/ofproto/ofproto_v1_3_parser.py
@@ -22,6 +22,7 @@ from ryu import utils
 from ofproto_parser import StringifyMixin, MsgBase, msg_pack_into, msg_str_attr
 from . import ofproto_parser
 from . import ofproto_v1_3
+from . import oxm_fields
 
 import logging
 LOG = logging.getLogger('ryu.ofproto.ofproto_v1_3_parser')
@@ -349,7 +350,7 @@ class FlowWildcards(object):
 
 
 class OFPMatch(StringifyMixin):
-    def __init__(self, fields=[], type_=None):
+    def __init__(self, fields=[], type_=None, **kwargs):
         super(OFPMatch, self).__init__()
         self._wc = FlowWildcards()
         self._flow = Flow()
@@ -379,10 +380,63 @@ class OFPMatch(StringifyMixin):
                     f = cls(header, value, mask)
                     self.fields.append(f)
 
+        # eg.
+        #   OFPMatch(eth_src=('ff:ff:ff:00:00:00'), eth_type=0x800,
+        #            ipv4_src='10.0.0.1')
+        fields2 = {}
+        for k, uv in kwargs.iteritems():
+            (n, v, m) = oxm_fields.from_user(k, uv)
+            # apply mask
+            if not m is None:
+                v = ''.join(chr(ord(x) & ord(y)) for (x, y)
+                    in itertools.izip(v, m))
+            k2, uv2 = oxm_fields.to_user(n, v, m)
+            assert k2 == k
+            fields2[k2] = uv2
+        self._fields2 = fields2
+
     def append_field(self, header, value, mask=None):
         self.fields.append(OFPMatchField.make(header, value, mask))
 
     def serialize(self, buf, offset):
+        # XXX compat
+        if self.fields or self._wc.__dict__ != FlowWildcards().__dict__:
+            return self.serialize_old(buf, offset)
+
+        fields = []
+        for k, v in self._fields2.iteritems():
+            fields.append(oxm_fields.from_user(k, v))
+
+        # assumption: sorting by OXM type values makes fields
+        # meet ordering requirements (eg. eth_type before ipv4_src)
+        fields.sort()
+
+        hdr_pack_str = '!HH'
+        field_offset = offset + struct.calcsize(hdr_pack_str)
+        for (n, value, mask) in fields:
+            if mask:
+                assert len(value) == len(mask)
+                pack_str = "!I%ds%ds" % (len(value), len(mask))
+                msg_pack_into(pack_str, buf, field_offset,
+                              ofproto_v1_3.oxm_tlv_header_w(n, len(value)),
+                              value, mask)
+            else:
+                pack_str = "!I%ds" % (len(value),)
+                msg_pack_into(pack_str, buf, field_offset,
+                              ofproto_v1_3.oxm_tlv_header(n, len(value)),
+                              value)
+            field_offset += struct.calcsize(pack_str)
+
+        length = field_offset - offset
+        msg_pack_into(hdr_pack_str, buf, offset,
+                      ofproto_v1_3.OFPMT_OXM, length)
+
+        pad_len = utils.round_up(length, 8) - length
+        ofproto_parser.msg_pack_into("%dx" % pad_len, buf, field_offset)
+
+        return length + pad_len
+
+    def serialize_old(self, buf, offset):
         if self._wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IN_PORT):
             self.append_field(ofproto_v1_3.OXM_OF_IN_PORT,
                               self._flow.in_port)
diff --git a/ryu/ofproto/oxm_fields.py b/ryu/ofproto/oxm_fields.py
index a7c319d..e44962c 100644
--- a/ryu/ofproto/oxm_fields.py
+++ b/ryu/ofproto/oxm_fields.py
@@ -16,6 +16,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from ryu.lib import addrconv
+
 
 class TypeDescr(object):
     pass
@@ -25,6 +27,21 @@ class IntDescr(TypeDescr):
     def __init__(self, size):
         self.size = size
 
+    def to_user(self, bin):
+        i = 0
+        for x in xrange(self.size):
+            c = bin[:1]
+            i = i * 256 + ord(c)
+            bin = bin[1:]
+        return i
+
+    def from_user(self, i):
+        bin = ''
+        for x in xrange(self.size):
+            bin = chr(i & 255) + bin
+            i /= 256
+        return bin
+
 Int1 = IntDescr(1)
 Int2 = IntDescr(2)
 Int3 = IntDescr(3)
@@ -34,14 +51,20 @@ Int8 = IntDescr(8)
 
 class MacAddr(TypeDescr):
     size = 6
+    to_user = addrconv.mac.bin_to_text
+    from_user = addrconv.mac.text_to_bin
 
 
 class IPv4Addr(TypeDescr):
     size = 4
+    to_user = addrconv.ipv4.bin_to_text
+    from_user = addrconv.ipv4.text_to_bin
 
 
 class IPv6Addr(TypeDescr):
     size = 16
+    to_user = addrconv.ipv6.bin_to_text
+    from_user = addrconv.ipv6.text_to_bin
 
 
 class D(object):
@@ -111,3 +134,42 @@ def generate_constants(modname):
         add_attr('OFPXMT_OFB_' + uk, ofpxmt)
         add_attr('OXM_OF_' + uk, mod.oxm_tlv_header(ofpxmt, td.size))
         add_attr('OXM_OF_' + uk + '_W', mod.oxm_tlv_header_w(ofpxmt, td.size))
+
+
+def find_field_by_name(name):
+    for t in oxm_types:
+        if t.name == name:
+            return t
+    raise KeyError
+
+
+def from_user(name, user_value):
+    f = find_field_by_name(name)
+    t = f.type
+    if isinstance(user_value, tuple):
+        (value, mask) = user_value
+    else:
+        value = user_value
+        mask = None
+    value = t.from_user(value)
+    if not mask is None:
+        mask = t.from_user(mask)
+    return f.num, value, mask
+
+
+def find_field_by_num(n):
+    for t in oxm_types:
+        if t.num == n:
+            return t
+    raise KeyError
+
+
+def to_user(n, v, m):
+    f = find_field_by_num(n)
+    t = f.type
+    value = t.to_user(v)
+    if m is None:
+        user_value = value
+    else:
+        user_value = (value, t.to_user(m))
+    return f.name, user_value
-- 
1.8.1.5


------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to