summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYusuke Iwase <iwase.yusuke0@gmail.com>2015-10-06 16:48:08 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-10-11 21:51:37 +0900
commit9663fbe5631492d28a0fcf643b6381c15ddbeb45 (patch)
tree495d6e2327e91797e5437e9531d1328db7bb7e6a
parentc0723eb0a632870a3077c2513aee7ed51cb31779 (diff)
of10: Support human readable MAC/IPv4 address in OFPMatch
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 <iwase.yusuke0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/ip.py72
-rw-r--r--ryu/ofproto/ofproto_v1_0_parser.py23
-rw-r--r--ryu/tests/unit/ofproto/test_parser_v10.py44
3 files changed, 97 insertions, 42 deletions
diff --git a/ryu/lib/ip.py b/ryu/lib/ip.py
index 10a9abdb..6630418d 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 4b00db1e..73d3409b 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 dca2b470..a9c3d639 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"])