summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorWei-Li Tang <alextwl@xinguard.com>2014-03-18 11:08:49 +0800
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2014-03-18 13:46:01 +0900
commit97f81e58a2f370b7f7d192cd640c9eef2ac33412 (patch)
treee7d9de5252dbb30777be3237205866254befe789
parent8728c11e1280b9c6bd4b7a68c5d2fbe4ec5f2ad3 (diff)
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>
-rw-r--r--ryu/lib/ofctl_v1_2.py32
-rw-r--r--ryu/lib/ofctl_v1_3.py32
2 files changed, 56 insertions, 8 deletions
diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py
index e6023ed2..4f87768d 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 748f3898..af6ac81c 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):