summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYuichi Ito <ito.yuichi0@gmail.com>2014-01-14 17:26:46 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2014-01-15 19:54:39 +0900
commita3e6dc6706d0449b64a565e1f82a05b95506a3ef (patch)
treef4967e947432b7a57dfb9b1f94f778554788042f
parentfaebcd2b3f273338ea01e0ff54229a5052eb41c3 (diff)
rest_firewall: support IPv6 match conditions
this patch gets rest_firewall to support IPv6 match conditions. 'ipv6_src' and 'ipv6_dst' are allowed as key. 'ICMPv6' is allowed as the value of 'nw_proto'. e.g.) curl -X POST -d '{"ipv6_src": "10::/64"}' http://localhost:8080/firewall/rules/0000000000000001 curl http://localhost:8080/firewall/rules/0000000000000001 [ { "access_control_list": [ { "rules": [ { "priority": 1, "dl_type": "IPv6", "ipv6_src": "10::/64", "rule_id": 1, "actions": "ALLOW" } ] } ], "switch_id": "0000000000000001" } ] Signed-off-by: Yuichi Ito <ito.yuichi0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/app/rest_firewall.py141
1 files changed, 119 insertions, 22 deletions
diff --git a/ryu/app/rest_firewall.py b/ryu/app/rest_firewall.py
index 4710b0b0..3b4e3af5 100644
--- a/ryu/app/rest_firewall.py
+++ b/ryu/app/rest_firewall.py
@@ -100,10 +100,12 @@ from ryu.ofproto import ofproto_v1_3_parser
# "in_port" : "<int>"
# "dl_src" : "<xx:xx:xx:xx:xx:xx>"
# "dl_dst" : "<xx:xx:xx:xx:xx:xx>"
-# "dl_type" : "<ARP or IPv4>"
+# "dl_type" : "<ARP or IPv4 or IPv6>"
# "nw_src" : "<A.B.C.D/M>"
# "nw_dst" : "<A.B.C.D/M>"
-# "nw_proto": "<TCP or UDP or ICMP>"
+# "ipv6_src": "<xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/M>"
+# "ipv6_dst": "<xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/M>"
+# "nw_proto": "<TCP or UDP or ICMP or ICMPv6>"
# "tp_src" : "<int>"
# "tp_dst" : "<int>"
# "actions" : "<ALLOW or DENY>"
@@ -112,6 +114,10 @@ from ryu.ofproto import ofproto_v1_3_parser
# without specifying dl-type as "ARP" or "IPv4"
# will automatically set dl-type as "IPv4".
#
+# Note: specifying ipv6_src/ipv6_dst
+# without specifying dl-type as "IPv6"
+# will automatically set dl-type as "IPv6".
+#
# Note: When "priority" has not been set up,
# "0" is set to "priority".
#
@@ -157,13 +163,17 @@ REST_DST_MAC = 'dl_dst'
REST_DL_TYPE = 'dl_type'
REST_DL_TYPE_ARP = 'ARP'
REST_DL_TYPE_IPV4 = 'IPv4'
+REST_DL_TYPE_IPV6 = 'IPv6'
REST_DL_VLAN = 'dl_vlan'
REST_SRC_IP = 'nw_src'
REST_DST_IP = 'nw_dst'
+REST_SRC_IPV6 = 'ipv6_src'
+REST_DST_IPV6 = 'ipv6_dst'
REST_NW_PROTO = 'nw_proto'
REST_NW_PROTO_TCP = 'TCP'
REST_NW_PROTO_UDP = 'UDP'
REST_NW_PROTO_ICMP = 'ICMP'
+REST_NW_PROTO_ICMPV6 = 'ICMPv6'
REST_TP_SRC = 'tp_src'
REST_TP_DST = 'tp_dst'
REST_ACTION = 'actions'
@@ -878,32 +888,114 @@ class Match(object):
_CONVERT = {REST_DL_TYPE:
{REST_DL_TYPE_ARP: ether.ETH_TYPE_ARP,
- REST_DL_TYPE_IPV4: ether.ETH_TYPE_IP},
+ REST_DL_TYPE_IPV4: ether.ETH_TYPE_IP,
+ REST_DL_TYPE_IPV6: ether.ETH_TYPE_IPV6},
REST_NW_PROTO:
{REST_NW_PROTO_TCP: inet.IPPROTO_TCP,
REST_NW_PROTO_UDP: inet.IPPROTO_UDP,
- REST_NW_PROTO_ICMP: inet.IPPROTO_ICMP}}
+ REST_NW_PROTO_ICMP: inet.IPPROTO_ICMP,
+ REST_NW_PROTO_ICMPV6: inet.IPPROTO_ICMPV6}}
@staticmethod
def to_openflow(rest):
- match = {}
- set_dltype_flg = False
- for key, value in rest.items():
- if (key == REST_SRC_IP or key == REST_DST_IP
- or key == REST_NW_PROTO):
- if (REST_DL_TYPE in rest) is False:
- set_dltype_flg = True
- elif (rest[REST_DL_TYPE] != REST_DL_TYPE_IPV4
- and rest[REST_DL_TYPE] != REST_DL_TYPE_ARP):
- continue
+ def __inv_combi(msg):
+ raise ValueError('Invalid combination: [%s]' % msg)
- elif key == REST_TP_SRC or key == REST_TP_DST:
- if ((REST_NW_PROTO in rest) is False
- or (rest[REST_NW_PROTO] != REST_NW_PROTO_TCP
- and rest[REST_NW_PROTO] != REST_NW_PROTO_UDP)):
- continue
+ def __inv_2and1(*args):
+ __inv_combi('%s=%s and %s' % (args[0], args[1], args[2]))
+
+ def __inv_2and2(*args):
+ __inv_combi('%s=%s and %s=%s' % (
+ args[0], args[1], args[2], args[3]))
+
+ def __inv_1and1(*args):
+ __inv_combi('%s and %s' % (args[0], args[1]))
+
+ def __inv_1and2(*args):
+ __inv_combi('%s and %s=%s' % (args[0], args[1], args[2]))
+
+ match = {}
+ # error check
+ dl_type = rest.get(REST_DL_TYPE)
+ nw_proto = rest.get(REST_NW_PROTO)
+ if dl_type is not None:
+ if dl_type == REST_DL_TYPE_ARP:
+ if REST_SRC_IPV6 in rest:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_ARP, REST_SRC_IPV6)
+ if REST_DST_IPV6 in rest:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_ARP, REST_DST_IPV6)
+ if nw_proto:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_ARP, REST_NW_PROTO)
+ elif dl_type == REST_DL_TYPE_IPV4:
+ if REST_SRC_IPV6 in rest:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_IPV4, REST_SRC_IPV6)
+ if REST_DST_IPV6 in rest:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_IPV4, REST_DST_IPV6)
+ if nw_proto == REST_NW_PROTO_ICMPV6:
+ __inv_2and2(
+ REST_DL_TYPE, REST_DL_TYPE_IPV4,
+ REST_NW_PROTO, REST_NW_PROTO_ICMPV6)
+ elif dl_type == REST_DL_TYPE_IPV6:
+ if REST_SRC_IP in rest:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_IPV6, REST_SRC_IP)
+ if REST_DST_IP in rest:
+ __inv_2and1(
+ REST_DL_TYPE, REST_DL_TYPE_IPV6, REST_DST_IP)
+ if nw_proto == REST_NW_PROTO_ICMP:
+ __inv_2and2(
+ REST_DL_TYPE, REST_DL_TYPE_IPV6,
+ REST_NW_PROTO, REST_NW_PROTO_ICMP)
+ else:
+ raise ValueError('Unknown dl_type : %s' % dl_type)
+ else:
+ if REST_SRC_IP in rest:
+ if REST_SRC_IPV6 in rest:
+ __inv_1and1(REST_SRC_IP, REST_SRC_IPV6)
+ if REST_DST_IPV6 in rest:
+ __inv_1and1(REST_SRC_IP, REST_DST_IPV6)
+ if nw_proto == REST_NW_PROTO_ICMPV6:
+ __inv_1and2(
+ REST_SRC_IP, REST_NW_PROTO, REST_NW_PROTO_ICMPV6)
+ rest[REST_DL_TYPE] = REST_DL_TYPE_IPV4
+ elif REST_DST_IP in rest:
+ if REST_SRC_IPV6 in rest:
+ __inv_1and1(REST_DST_IP, REST_SRC_IPV6)
+ if REST_DST_IPV6 in rest:
+ __inv_1and1(REST_DST_IP, REST_DST_IPV6)
+ if nw_proto == REST_NW_PROTO_ICMPV6:
+ __inv_1and2(
+ REST_DST_IP, REST_NW_PROTO, REST_NW_PROTO_ICMPV6)
+ rest[REST_DL_TYPE] = REST_DL_TYPE_IPV4
+ elif REST_SRC_IPV6 in rest:
+ if nw_proto == REST_NW_PROTO_ICMP:
+ __inv_1and2(
+ REST_SRC_IPV6, REST_NW_PROTO, REST_NW_PROTO_ICMP)
+ rest[REST_DL_TYPE] = REST_DL_TYPE_IPV6
+ elif REST_DST_IPV6 in rest:
+ if nw_proto == REST_NW_PROTO_ICMP:
+ __inv_1and2(
+ REST_DST_IPV6, REST_NW_PROTO, REST_NW_PROTO_ICMP)
+ rest[REST_DL_TYPE] = REST_DL_TYPE_IPV6
+ else:
+ if nw_proto == REST_NW_PROTO_ICMP:
+ rest[REST_DL_TYPE] = REST_DL_TYPE_IPV4
+ elif nw_proto == REST_NW_PROTO_ICMPV6:
+ rest[REST_DL_TYPE] = REST_DL_TYPE_IPV6
+ elif nw_proto == REST_NW_PROTO_TCP or \
+ nw_proto == REST_NW_PROTO_UDP:
+ raise ValueError('no dl_type was specified')
+ else:
+ raise ValueError('Unknown nw_proto: %s' % nw_proto)
+
+ for key, value in rest.items():
if key in Match._CONVERT:
if value in Match._CONVERT[key]:
match.setdefault(key, Match._CONVERT[key][value])
@@ -912,9 +1004,6 @@ class Match(object):
else:
match.setdefault(key, value)
- if set_dltype_flg:
- match.setdefault(REST_DL_TYPE, ether.ETH_TYPE_IP)
-
return match
@staticmethod
@@ -923,6 +1012,7 @@ class Match(object):
mac_dontcare = mac.haddr_to_str(mac.DONTCARE)
ip_dontcare = '0.0.0.0'
+ ipv6_dontcare = '::'
match = {}
for key, value in of_match.items():
@@ -932,6 +1022,9 @@ class Match(object):
elif key == REST_SRC_IP or key == REST_DST_IP:
if value == ip_dontcare:
continue
+ elif key == REST_SRC_IPV6 or key == REST_DST_IPV6:
+ if value == ipv6_dontcare:
+ continue
elif value == 0:
continue
@@ -948,6 +1041,7 @@ class Match(object):
def to_mod_openflow(of_match):
mac_dontcare = mac.haddr_to_str(mac.DONTCARE)
ip_dontcare = '0.0.0.0'
+ ipv6_dontcare = '::'
match = {}
for key, value in of_match.items():
@@ -957,6 +1051,9 @@ class Match(object):
elif key == REST_SRC_IP or key == REST_DST_IP:
if value == ip_dontcare:
continue
+ elif key == REST_SRC_IPV6 or key == REST_DST_IPV6:
+ if value == ipv6_dontcare:
+ continue
elif value == 0:
continue