In OF1.0, OFPMatch is required to specify MAC address as a binary
type value and to specify IPv4 Address as an int type value.
This behavior is differ from that in OF1.2+.
This patch makes OFPMatch in OF1.0 enable to support human readable
representation of MAC/IPv4 address like OF1.2+ API.

The current API in OF1.0:
  >>> match = parser.OFPMatch(dl_src=b'\x01\x02\x03\x04\x05\x06',
  ...                         nw_src=167772163)
  >>> match.dl_src
  '\x01\x02\x03\x04\x05\x06'
  >>> match.nw_src
  167772163

The introduced API (the same as OF1.2+ API):
  >>> match = parser.OFPMatch(dl_dst='aa:bb:cc:dd:ee:ff',
  ...                         nw_dst='192.168.0.1')
  >>> match['dl_dst']
  'aa:bb:cc:dd:ee:ff'
  >>> match['nw_dst']
  '192.168.0.1'

Signed-off-by: IWASE Yusuke <[email protected]>
---
 ryu/lib/ip.py                             | 72 +++++++++++++++++++++++--------
 ryu/ofproto/ofproto_v1_0_parser.py        | 23 ++++++++--
 ryu/tests/unit/ofproto/test_parser_v10.py | 44 ++++++++++---------
 3 files changed, 97 insertions(+), 42 deletions(-)

diff --git a/ryu/lib/ip.py b/ryu/lib/ip.py
index 10a9abd..6630418 100644
--- a/ryu/lib/ip.py
+++ b/ryu/lib/ip.py
@@ -1,30 +1,66 @@
+# Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
+#
+# 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.lib import addrconv
 
 
 def ipv4_to_bin(ip):
-    '''
-        Parse an IP address and return an unsigned int.
-        The IP address is in dotted decimal notation.
-    '''
+    """
+    Converts human readable IPv4 string to binary representation.
+    :param str ip: IPv4 address string
+    :return: binary representation of IPv4 address
+    """
     return addrconv.ipv4.text_to_bin(ip)
 
 
+def ipv4_to_int(ip):
+    """
+    Converts human readable IPv4 string to int type representation.
+    :param str ip: IPv4 address string w.x.y.z
+    :returns: unsigned int of form w << 24 | x << 16 | y << 8 | z
+    """
+    return struct.unpack("!I", addrconv.ipv4.text_to_bin(ip))[0]
+
+
 def ipv4_to_str(ip):
-    """Generate IP address string from an unsigned int.
-       ip: unsigned int of form w << 24 | x << 16 | y << 8 | z
-       returns: ip address string w.x.y.z"""
-    return addrconv.ipv4.bin_to_text(ip)
+    """
+    Converts binary or int type representation to human readable IPv4 string.
+    :param str ip: binary or int type representation of IPv4 address
+    :return: IPv4 address string
+    """
+    if isinstance(ip, int):
+        return addrconv.ipv4.bin_to_text(struct.pack("!I", ip))
+    else:
+        return addrconv.ipv4.bin_to_text(ip)
 
 
-def ipv6_to_bin(ipv6):
-    '''
-        convert ipv6 string to binary representation
-    '''
-    return addrconv.ipv6.text_to_bin(ipv6)
+def ipv6_to_bin(ip):
+    """
+    Converts human readable IPv6 string to binary representation.
+    :param str ip: IPv6 address string
+    :return: binary representation of IPv6 address
+    """
+    return addrconv.ipv6.text_to_bin(ip)
 
 
-def ipv6_to_str(bin_addr):
-    '''
-        convert binary representation to human readable string
-    '''
-    return addrconv.ipv6.bin_to_text(bin_addr)
+def ipv6_to_str(ip):
+    """
+    Converts binary representation to human readable IPv6 string.
+    :param str ip: binary representation of IPv6 address
+    :return: IPv6 address string
+    """
+    return addrconv.ipv6.bin_to_text(ip)
diff --git a/ryu/ofproto/ofproto_v1_0_parser.py 
b/ryu/ofproto/ofproto_v1_0_parser.py
index 4b00db1..73d3409 100644
--- a/ryu/ofproto/ofproto_v1_0_parser.py
+++ b/ryu/ofproto/ofproto_v1_0_parser.py
@@ -24,6 +24,7 @@ import six
 
 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase
 from ryu.lib import addrconv
+from ryu.lib import ip
 from ryu.lib import mac
 from ryu.lib.pack_utils import msg_pack_into
 from ryu.ofproto import ofproto_common
@@ -130,6 +131,8 @@ class OFPMatch(StringifyMixin):
             self.dl_src = mac.DONTCARE
         else:
             wc &= ~ofproto.OFPFW_DL_SRC
+            if isinstance(dl_src, str) and ':' in dl_src:
+                dl_src = addrconv.mac.text_to_bin(dl_src)
             if dl_src == 0:
                 self.dl_src = mac.DONTCARE
             else:
@@ -139,6 +142,8 @@ class OFPMatch(StringifyMixin):
             self.dl_dst = mac.DONTCARE
         else:
             wc &= ~ofproto.OFPFW_DL_DST
+            if isinstance(dl_dst, str) and ':' in dl_dst:
+                dl_dst = addrconv.mac.text_to_bin(dl_dst)
             if dl_dst == 0:
                 self.dl_dst = mac.DONTCARE
             else:
@@ -179,6 +184,8 @@ class OFPMatch(StringifyMixin):
         else:
             wc &= (32 - nw_src_mask) << ofproto.OFPFW_NW_SRC_SHIFT \
                 | ~ofproto.OFPFW_NW_SRC_MASK
+            if isinstance(nw_src, str) and '.' in nw_src:
+                nw_src = ip.ipv4_to_int(nw_src)
             self.nw_src = nw_src
 
         if nw_dst is None:
@@ -186,6 +193,8 @@ class OFPMatch(StringifyMixin):
         else:
             wc &= (32 - nw_dst_mask) << ofproto.OFPFW_NW_DST_SHIFT \
                 | ~ofproto.OFPFW_NW_DST_MASK
+            if isinstance(nw_dst, str) and '.' in nw_dst:
+                nw_dst = ip.ipv4_to_int(nw_dst)
             self.nw_dst = nw_dst
 
         if tp_src is None:
@@ -219,10 +228,16 @@ class OFPMatch(StringifyMixin):
         elif name == 'wildcards':
             return self.wildcards
 
-        wc_name = 'OFPFW_' + name.upper()
-        wc = getattr(ofproto, wc_name, ofproto.OFPFW_ALL)
-        if self.wildcards & ~wc:
-            return getattr(self, name)
+        wc = getattr(ofproto, 'OFPFW_' + name.upper(), 0)
+        if ~self.wildcards & wc:
+            value = getattr(self, name)
+            if isinstance(value, six.binary_type) \
+                    and name in ['dl_src', 'dl_dst']:
+                value = addrconv.mac.bin_to_text(value)
+            elif isinstance(value, int) \
+                    and name in ['nw_src', 'nw_dst']:
+                value = ip.ipv4_to_str(value)
+            return value
         else:
             raise KeyError(name)
 
diff --git a/ryu/tests/unit/ofproto/test_parser_v10.py 
b/ryu/tests/unit/ofproto/test_parser_v10.py
index dca2b47..a9c3d63 100644
--- a/ryu/tests/unit/ofproto/test_parser_v10.py
+++ b/ryu/tests/unit/ofproto/test_parser_v10.py
@@ -105,8 +105,10 @@ class TestOFPMatch(unittest.TestCase):
     #                         nw_src, nw_dst, tp_src, tp_dst
     wildcards = {'buf': b'\xd2\x71\x25\x23', 'val': 3530630435}
     in_port = {'buf': b'\x37\x8b', 'val': 14219}
-    dl_src = b'\x52\x54\x54\x10\x20\x99'
-    dl_dst = b'\x61\x31\x50\x6d\xc9\xe5'
+    dl_src = {'buf': b'\x52\x54\x54\x10\x20\x99',
+              'human': '52:54:54:10:20:99'}
+    dl_dst = {'buf': b'\x61\x31\x50\x6d\xc9\xe5',
+              'human': '61:31:50:6d:c9:e5'}
     dl_vlan = {'buf': b'\xc1\xf9', 'val': 49657}
     dl_vlan_pcp = {'buf': b'\x79', 'val': 121}
     zfill0 = b'\x00'
@@ -114,15 +116,17 @@ class TestOFPMatch(unittest.TestCase):
     nw_tos = {'buf': b'\xde', 'val': 222}
     nw_proto = {'buf': b'\xe5', 'val': 229}
     zfil11 = b'\x00' * 2
-    nw_src = {'buf': b'\x1b\x6d\x8d\x4b', 'val': 460164427}
-    nw_dst = {'buf': b'\xab\x25\xe1\x20', 'val': 2871386400}
+    nw_src = {'buf': b'\x1b\x6d\x8d\x4b', 'val': 460164427,
+              'human': '27.109.141.75'}
+    nw_dst = {'buf': b'\xab\x25\xe1\x20', 'val': 2871386400,
+              'human': '171.37.225.32'}
     tp_src = {'buf': b'\xd5\xc3', 'val': 54723}
     tp_dst = {'buf': b'\x78\xb9', 'val': 30905}
 
     buf = wildcards['buf'] \
         + in_port['buf'] \
-        + dl_src \
-        + dl_dst \
+        + dl_src['buf'] \
+        + dl_dst['buf'] \
         + dl_vlan['buf'] \
         + dl_vlan_pcp['buf'] \
         + zfill0 \
@@ -158,12 +162,12 @@ class TestOFPMatch(unittest.TestCase):
         pass
 
     def test_init(self):
-        c = self._get_obj(self.dl_src, self.dl_dst)
+        c = self._get_obj(self.dl_src['buf'], self.dl_dst['buf'])
 
         eq_(self.wildcards['val'], c.wildcards)
         eq_(self.in_port['val'], c.in_port)
-        eq_(self.dl_src, c.dl_src)
-        eq_(self.dl_dst, c.dl_dst)
+        eq_(self.dl_src['buf'], c.dl_src)
+        eq_(self.dl_dst['buf'], c.dl_dst)
         eq_(self.dl_vlan['val'], c.dl_vlan)
         eq_(self.dl_vlan_pcp['val'], c.dl_vlan_pcp)
         eq_(self.dl_type['val'], c.dl_type)
@@ -180,13 +184,13 @@ class TestOFPMatch(unittest.TestCase):
         eq_(mac.DONTCARE, c.dl_dst)
 
     def test_parse(self):
-        c = self._get_obj(self.dl_src, self.dl_dst)
+        c = self._get_obj(self.dl_src['buf'], self.dl_dst['buf'])
         res = c.parse(self.buf, 0)
 
         eq_(self.wildcards['val'], res.wildcards)
         eq_(self.in_port['val'], res.in_port)
-        eq_(self.dl_src, res.dl_src)
-        eq_(self.dl_dst, res.dl_dst)
+        eq_(self.dl_src['buf'], res.dl_src)
+        eq_(self.dl_dst['buf'], res.dl_dst)
         eq_(self.dl_vlan['val'], res.dl_vlan)
         eq_(self.dl_vlan_pcp['val'], res.dl_vlan_pcp)
         eq_(self.dl_type['val'], res.dl_type)
@@ -199,7 +203,7 @@ class TestOFPMatch(unittest.TestCase):
 
     def test_serialize(self):
         buf = bytearray()
-        c = self._get_obj(self.dl_src, self.dl_dst)
+        c = self._get_obj(self.dl_src['buf'], self.dl_dst['buf'])
 
         c.serialize(buf, 0)
 
@@ -208,8 +212,8 @@ class TestOFPMatch(unittest.TestCase):
 
         eq_(self.wildcards['val'], res[0])
         eq_(self.in_port['val'], res[1])
-        eq_(self.dl_src, res[2])
-        eq_(self.dl_dst, res[3])
+        eq_(self.dl_src['buf'], res[2])
+        eq_(self.dl_dst['buf'], res[3])
         eq_(self.dl_vlan['val'], res[4])
         eq_(self.dl_vlan_pcp['val'], res[5])
         eq_(self.dl_type['val'], res[6])
@@ -221,19 +225,19 @@ class TestOFPMatch(unittest.TestCase):
         eq_(self.tp_dst['val'], res[12])
 
     def test_getitem(self):
-        c = self._get_obj(self.dl_src, self.dl_dst)
+        c = self._get_obj(self.dl_src['buf'], self.dl_dst['buf'])
 
         eq_(self.wildcards['val'], c["wildcards"])
         eq_(self.in_port['val'], c["in_port"])
-        eq_(self.dl_src, c["dl_src"])
-        eq_(self.dl_dst, c["dl_dst"])
+        eq_(self.dl_src['human'], c["dl_src"])
+        eq_(self.dl_dst['human'], c["dl_dst"])
         eq_(self.dl_vlan['val'], c["dl_vlan"])
         eq_(self.dl_vlan_pcp['val'], c["dl_vlan_pcp"])
         eq_(self.dl_type['val'], c["dl_type"])
         eq_(self.nw_tos['val'], c["nw_tos"])
         eq_(self.nw_proto['val'], c["nw_proto"])
-        eq_(self.nw_src['val'], c["nw_src"])
-        eq_(self.nw_dst['val'], c["nw_dst"])
+        eq_(self.nw_src['human'], c["nw_src"])
+        eq_(self.nw_dst['human'], c["nw_dst"])
         eq_(self.tp_src['val'], c["tp_src"])
         eq_(self.tp_dst['val'], c["tp_dst"])
 
-- 
1.9.1


------------------------------------------------------------------------------
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to