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.

For match_ip*_to_str functions, it outputs full mask address only
if the mask cannot be represented in CIDR format.

Please notice that to_match_ipv6() is no longer compatible with
ACL hybrid CIDR format (Cisco-like ACL bitmasks) after applying
this patch.

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 |   40 ++++++++++++++++++++++++++++++----------
 ryu/lib/ofctl_v1_3.py |   40 ++++++++++++++++++++++++++++++----------
 2 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py
index 273b387..9662d3a 100644
--- a/ryu/lib/ofctl_v1_2.py
+++ b/ryu/lib/ofctl_v1_2.py
@@ -330,18 +330,28 @@ def to_match_ip(value):
     # ip
     ipv4 = struct.unpack('!I', socket.inet_aton(ip_mask[0]))[0]
     # netmask
-    mask = 32
+    netmask = ofproto_v1_2_parser.UINT32_MAX
     if len(ip_mask) == 2:
-        mask = int(ip_mask[1])
-    netmask = ofproto_v1_2_parser.UINT32_MAX << 32 - mask\
-        & ofproto_v1_2_parser.UINT32_MAX
+        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:
+        ipv6 = netaddr.IPAddress(ip_mask[0]).words
+        netmask = netaddr.IPAddress(ip_mask[1]).words
+    else:
+        network = netaddr.IPNetwork(value)
+        ipv6 = network.ip.words
+        netmask = network.netmask.words
+
+    return ipv6, netmask
 
 
 def match_to_str(ofmatch):
@@ -389,8 +399,11 @@ def match_ip_to_str(value, mask):
     ip = socket.inet_ntoa(struct.pack('!I', value))
 
     if mask is not None and mask != 0:
-        binary_str = bin(mask)[2:].zfill(8)
-        netmask = '/%d' % len(binary_str.rstrip('0'))
+        binary_str = bin(mask)[2:].zfill(32).rstrip('0')
+        if binary_str.find('0') >= 0:
+            netmask = '/%s' % socket.inet_ntoa(struct.pack('!I', mask))
+        else:
+            netmask = '/%d' % len(binary_str)
     else:
         netmask = ''
 
@@ -404,14 +417,21 @@ def match_ipv6_to_str(value, mask):
     ip = netaddr.IPNetwork(':'.join(ip_list))
 
     netmask = 128
+    netmask_str = None
     if mask is not None:
         mask_list = []
         for word in mask:
             mask_list.append('%04x' % word)
         mask_v = netaddr.IPNetwork(':'.join(mask_list))
-        netmask = len(mask_v.ip.bits().replace(':', '').rstrip('0'))
+        binary_str = mask_v.ip.bits().replace(':', '').zfill(128).rstrip('0')
+        if binary_str.find('0') >= 0:
+            netmask_str = str(mask_v.ip)
+        else:
+            netmask = len(binary_str)
 
-    if netmask == 128:
+    if netmask_str is not None:
+        ip_str = str(ip.ip) + '/' + netmask_str
+    elif netmask == 128:
         ip_str = str(ip.ip)
     else:
         ip.prefixlen = netmask
diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py
index 3e2713e..9c470bd 100644
--- a/ryu/lib/ofctl_v1_3.py
+++ b/ryu/lib/ofctl_v1_3.py
@@ -372,18 +372,28 @@ def to_match_ip(value):
     # ip
     ipv4 = struct.unpack('!I', socket.inet_aton(ip_mask[0]))[0]
     # netmask
-    mask = 32
+    netmask = ofproto_v1_3_parser.UINT32_MAX
     if len(ip_mask) == 2:
-        mask = int(ip_mask[1])
-    netmask = ofproto_v1_3_parser.UINT32_MAX << 32 - mask\
-        & ofproto_v1_3_parser.UINT32_MAX
+        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:
+        ipv6 = netaddr.IPAddress(ip_mask[0]).words
+        netmask = netaddr.IPAddress(ip_mask[1]).words
+    else:
+        network = netaddr.IPNetwork(value)
+        ipv6 = network.ip.words
+        netmask = network.netmask.words
+
+    return ipv6, netmask
 
 
 def to_match_metadata(value):
@@ -469,8 +479,11 @@ def match_ip_to_str(value, mask):
     ip = socket.inet_ntoa(struct.pack('!I', value))
 
     if mask is not None and mask != 0:
-        binary_str = bin(mask)[2:].zfill(8)
-        netmask = '/%d' % len(binary_str.rstrip('0'))
+        binary_str = bin(mask)[2:].zfill(32).rstrip('0')
+        if binary_str.find('0') >= 0:
+            netmask = '/%s' % socket.inet_ntoa(struct.pack('!I', mask))
+        else:
+            netmask = '/%d' % len(binary_str)
     else:
         netmask = ''
 
@@ -484,14 +497,21 @@ def match_ipv6_to_str(value, mask):
     ip = netaddr.IPNetwork(':'.join(ip_list))
 
     netmask = 128
+    netmask_str = None
     if mask is not None:
         mask_list = []
         for word in mask:
             mask_list.append('%04x' % word)
         mask_v = netaddr.IPNetwork(':'.join(mask_list))
-        netmask = len(mask_v.ip.bits().replace(':', '').rstrip('0'))
+        binary_str = mask_v.ip.bits().replace(':', '').zfill(128).rstrip('0')
+        if binary_str.find('0') >= 0:
+            netmask_str = str(mask_v.ip)
+        else:
+            netmask = len(binary_str)
 
-    if netmask == 128:
+    if netmask_str is not None:
+        ip_str = str(ip.ip) + '/' + netmask_str
+    elif netmask == 128:
         ip_str = str(ip.ip)
     else:
         ip.prefixlen = netmask
-- 
1.7.9.5


------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool.
Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer
Customize your own dashboards, set traffic alerts and generate reports.
Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to