Openflow 1.1 and later versions allow the use of IP address with
arbitrary bitmask in match fields. This adds arbitrary bitmask
support to related functions.

After applying this patch, it's no longer compatible with ACL
hybrid CIDR format (Cisco-like ACL bitmasks) because such format
exists only in some router's ACL configuration.

Reported-by: Yi-Ching Lee <[email protected]>
Reported-by: Li-Der Chou <[email protected]>
Signed-off-by: Wei-Li Tang <[email protected]>
---
 ryu/lib/ofctl_v1_2.py |   32 ++++++++++++++++++++++++++++----
 ryu/lib/ofctl_v1_3.py |   32 ++++++++++++++++++++++++++++----
 2 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py
index e6023ed..4f87768 100644
--- a/ryu/lib/ofctl_v1_2.py
+++ b/ryu/lib/ofctl_v1_2.py
@@ -326,13 +326,37 @@ def to_match_tpdst(value, match, rest):
 
 
 def to_match_ip(value):
-    ip = netaddr.IPNetwork(value)
-    return ip.ip.value, ip.netmask.value
+    ip_mask = value.split('/')
+
+    # IP address
+    ipv4 = struct.unpack('!I', socket.inet_aton(ip_mask[0]))[0]
+    # netmask
+    netmask = ofproto_v1_2_parser.UINT32_MAX
+
+    if len(ip_mask) == 2:
+        # Check the mask is CIDR or not.
+        if ip_mask[1].isdigit():
+            netmask &= ofproto_v1_2_parser.UINT32_MAX << 32 - int(ip_mask[1])
+        else:
+            netmask = struct.unpack('!I', socket.inet_aton(ip_mask[1]))[0]
+
+    return ipv4, netmask
 
 
 def to_match_ipv6(value):
-    ip = netaddr.IPNetwork(value)
-    return ip.ip.words, ip.netmask.words
+    ip_mask = value.split('/')
+
+    if len(ip_mask) == 2 and ip_mask[1].isdigit() is False:
+        # Both address and netmask are colon-hexadecimal.
+        ipv6 = netaddr.IPAddress(ip_mask[0]).words
+        netmask = netaddr.IPAddress(ip_mask[1]).words
+    else:
+        # For other formats.
+        network = netaddr.IPNetwork(value)
+        ipv6 = network.ip.words
+        netmask = network.netmask.words
+
+    return ipv6, netmask
 
 
 def match_to_str(ofmatch):
diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py
index 748f389..af6ac81 100644
--- a/ryu/lib/ofctl_v1_3.py
+++ b/ryu/lib/ofctl_v1_3.py
@@ -368,13 +368,37 @@ def to_match_tpdst(value, match, rest):
 
 
 def to_match_ip(value):
-    ip = netaddr.IPNetwork(value)
-    return ip.ip.value, ip.netmask.value
+    ip_mask = value.split('/')
+
+    # IP address
+    ipv4 = struct.unpack('!I', socket.inet_aton(ip_mask[0]))[0]
+    # netmask
+    netmask = ofproto_v1_3_parser.UINT32_MAX
+
+    if len(ip_mask) == 2:
+        # Check the mask is CIDR or not.
+        if ip_mask[1].isdigit():
+            netmask &= ofproto_v1_3_parser.UINT32_MAX << 32 - int(ip_mask[1])
+        else:
+            netmask = struct.unpack('!I', socket.inet_aton(ip_mask[1]))[0]
+
+    return ipv4, netmask
 
 
 def to_match_ipv6(value):
-    ip = netaddr.IPNetwork(value)
-    return ip.ip.words, ip.netmask.words
+    ip_mask = value.split('/')
+
+    if len(ip_mask) == 2 and ip_mask[1].isdigit() is False:
+        # Both address and netmask are colon-hexadecimal.
+        ipv6 = netaddr.IPAddress(ip_mask[0]).words
+        netmask = netaddr.IPAddress(ip_mask[1]).words
+    else:
+        # For other formats.
+        network = netaddr.IPNetwork(value)
+        ipv6 = network.ip.words
+        netmask = network.netmask.words
+
+    return ipv6, netmask
 
 
 def to_match_metadata(value):
-- 
1.7.9.5


------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/13534_NeoTech
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to