On Sat,  1 Mar 2014 17:17:16 +0800
Wei-Li Tang <[email protected]> wrote:

> 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.

Thanks a lot!

Sounds supporting arbitrary bitmask here fully makes sense. But I'm
bit concerned with the API incompatibility. Is there any way to keep
it? If not, can you describe the new REST API somewhere?


> 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

------------------------------------------------------------------------------
Subversion Kills Productivity. Get off Subversion & Make the Move to Perforce.
With Perforce, you get hassle-free workflows. Merge that actually works. 
Faster operations. Version large binaries.  Built-in WAN optimization and the
freedom to use Git, Perforce or both. Make the move to Perforce.
http://pubads.g.doubleclick.net/gampad/clk?id=122218951&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to