ofctl_v1_2/3: IP arbitrary bitmask support

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 <potatoching11@gmail.com>
Reported-by: Li-Der Chou <cld@csie.ncu.edu.tw>
Signed-off-by: Wei-Li Tang <alextwl@xinguard.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Wei-Li Tang 2014-03-18 11:08:49 +08:00 committed by FUJITA Tomonori
parent 8728c11e12
commit 97f81e58a2
2 changed files with 56 additions and 8 deletions

View File

@ -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):

View File

@ -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):