Merge "Add popular IP protocols for security group"

This commit is contained in:
Jenkins 2016-02-05 14:53:35 +00:00 committed by Gerrit Code Review
commit eee37a86a5
11 changed files with 117 additions and 33 deletions

View File

@ -138,7 +138,7 @@ def icmpv6_header_match_supported():
table=ovs_const.ARP_SPOOF_TABLE,
priority=1,
dl_type=n_consts.ETHERTYPE_IPV6,
nw_proto=n_consts.PROTO_NUM_ICMP_V6,
nw_proto=n_consts.PROTO_NUM_IPV6_ICMP,
icmp_type=n_consts.ICMPV6_TYPE_NA,
nd_target='fdf8:f53b:82e4::10',
actions="NORMAL")

View File

@ -125,14 +125,71 @@ SUBNET_ALLOCATION_EXT_ALIAS = 'subnet_allocation'
ETHERTYPE_IPV6 = 0x86DD
# Protocol names and numbers for Security Groups/Firewalls
PROTO_NAME_TCP = 'tcp'
PROTO_NAME_AH = 'ah'
PROTO_NAME_DCCP = 'dccp'
PROTO_NAME_EGP = 'egp'
PROTO_NAME_ESP = 'esp'
PROTO_NAME_GRE = 'gre'
PROTO_NAME_ICMP = 'icmp'
PROTO_NAME_ICMP_V6 = 'icmpv6'
PROTO_NAME_IGMP = 'igmp'
PROTO_NAME_IPV6_ENCAP = 'ipv6-encap'
PROTO_NAME_IPV6_FRAG = 'ipv6-frag'
PROTO_NAME_IPV6_ICMP = 'ipv6-icmp'
PROTO_NAME_IPV6_NONXT = 'ipv6-nonxt'
PROTO_NAME_IPV6_OPTS = 'ipv6-opts'
PROTO_NAME_IPV6_ROUTE = 'ipv6-route'
PROTO_NAME_OSPF = 'ospf'
PROTO_NAME_PGM = 'pgm'
PROTO_NAME_RSVP = 'rsvp'
PROTO_NAME_SCTP = 'sctp'
PROTO_NAME_TCP = 'tcp'
PROTO_NAME_UDP = 'udp'
PROTO_NUM_TCP = 6
PROTO_NAME_UDPLITE = 'udplite'
PROTO_NAME_VRRP = 'vrrp'
PROTO_NUM_AH = 51
PROTO_NUM_DCCP = 33
PROTO_NUM_EGP = 8
PROTO_NUM_ESP = 50
PROTO_NUM_GRE = 47
PROTO_NUM_ICMP = 1
PROTO_NUM_ICMP_V6 = 58
PROTO_NUM_IGMP = 2
PROTO_NUM_IPV6_ENCAP = 41
PROTO_NUM_IPV6_FRAG = 44
PROTO_NUM_IPV6_ICMP = 58
PROTO_NUM_IPV6_NONXT = 59
PROTO_NUM_IPV6_OPTS = 60
PROTO_NUM_IPV6_ROUTE = 43
PROTO_NUM_OSPF = 89
PROTO_NUM_PGM = 113
PROTO_NUM_RSVP = 46
PROTO_NUM_SCTP = 132
PROTO_NUM_TCP = 6
PROTO_NUM_UDP = 17
PROTO_NUM_UDPLITE = 136
PROTO_NUM_VRRP = 112
IP_PROTOCOL_MAP = {PROTO_NAME_AH: PROTO_NUM_AH,
PROTO_NAME_DCCP: PROTO_NUM_DCCP,
PROTO_NAME_EGP: PROTO_NUM_EGP,
PROTO_NAME_ESP: PROTO_NUM_ESP,
PROTO_NAME_GRE: PROTO_NUM_GRE,
PROTO_NAME_ICMP: PROTO_NUM_ICMP,
PROTO_NAME_IGMP: PROTO_NUM_IGMP,
PROTO_NAME_IPV6_ENCAP: PROTO_NUM_IPV6_ENCAP,
PROTO_NAME_IPV6_FRAG: PROTO_NUM_IPV6_FRAG,
PROTO_NAME_IPV6_ICMP: PROTO_NUM_IPV6_ICMP,
PROTO_NAME_IPV6_NONXT: PROTO_NUM_IPV6_NONXT,
PROTO_NAME_IPV6_OPTS: PROTO_NUM_IPV6_OPTS,
PROTO_NAME_IPV6_ROUTE: PROTO_NUM_IPV6_ROUTE,
PROTO_NAME_OSPF: PROTO_NUM_OSPF,
PROTO_NAME_PGM: PROTO_NUM_PGM,
PROTO_NAME_RSVP: PROTO_NUM_RSVP,
PROTO_NAME_SCTP: PROTO_NUM_SCTP,
PROTO_NAME_TCP: PROTO_NUM_TCP,
PROTO_NAME_UDP: PROTO_NUM_UDP,
PROTO_NAME_UDPLITE: PROTO_NUM_UDPLITE,
PROTO_NAME_VRRP: PROTO_NUM_VRRP}
# List of ICMPv6 types that should be allowed by default:
# Multicast Listener Query (130),

View File

@ -38,11 +38,6 @@ from neutron.extensions import securitygroup as ext_sg
LOG = logging.getLogger(__name__)
IP_PROTOCOL_MAP = {constants.PROTO_NAME_TCP: constants.PROTO_NUM_TCP,
constants.PROTO_NAME_UDP: constants.PROTO_NUM_UDP,
constants.PROTO_NAME_ICMP: constants.PROTO_NUM_ICMP,
constants.PROTO_NAME_ICMP_V6: constants.PROTO_NUM_ICMP_V6}
class SecurityGroup(model_base.HasStandardAttributes, model_base.BASEV2,
model_base.HasId, model_base.HasTenant):
@ -420,7 +415,7 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
# problems with comparing int and string in PostgreSQL. Here this
# string is converted to int to give an opportunity to use it as
# before.
return int(IP_PROTOCOL_MAP.get(protocol, protocol))
return int(constants.IP_PROTOCOL_MAP.get(protocol, protocol))
def _validate_port_range(self, rule):
"""Check that port_range is valid."""
@ -452,7 +447,12 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase):
def _validate_ethertype_and_protocol(self, rule):
"""Check if given ethertype and protocol are valid or not"""
if rule['protocol'] == constants.PROTO_NAME_ICMP_V6:
if rule['protocol'] in [constants.PROTO_NAME_IPV6_ENCAP,
constants.PROTO_NAME_IPV6_FRAG,
constants.PROTO_NAME_IPV6_ICMP,
constants.PROTO_NAME_IPV6_NONXT,
constants.PROTO_NAME_IPV6_OPTS,
constants.PROTO_NAME_IPV6_ROUTE]:
if rule['ethertype'] == constants.IPv4:
raise ext_sg.SecurityGroupEthertypeConflictWithProtocol(
ethertype=rule['ethertype'], protocol=rule['protocol'])

View File

@ -432,7 +432,7 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
for ra_ip in ra_ips:
ra_rule = {'direction': 'ingress',
'ethertype': n_const.IPv6,
'protocol': n_const.PROTO_NAME_ICMP_V6,
'protocol': n_const.PROTO_NAME_IPV6_ICMP,
'source_ip_prefix': ra_ip,
'source_port_range_min': n_const.ICMPV6_TYPE_RA}
port['security_group_rules'].append(ra_rule)

View File

@ -211,8 +211,7 @@ def _validate_name_not_default(data, valid_values=None):
attr.validators['type:name_not_default'] = _validate_name_not_default
sg_supported_protocols = [None, const.PROTO_NAME_TCP, const.PROTO_NAME_UDP,
const.PROTO_NAME_ICMP, const.PROTO_NAME_ICMP_V6]
sg_supported_protocols = [None] + list(const.IP_PROTOCOL_MAP.keys())
sg_supported_ethertypes = ['IPv4', 'IPv6']
# Attribute Map

View File

@ -116,14 +116,15 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
for ip in ip_addresses:
self.install_normal(
table_id=constants.ARP_SPOOF_TABLE, priority=2,
dl_type=const.ETHERTYPE_IPV6, nw_proto=const.PROTO_NUM_ICMP_V6,
dl_type=const.ETHERTYPE_IPV6,
nw_proto=const.PROTO_NUM_IPV6_ICMP,
icmp_type=const.ICMPV6_TYPE_NA, nd_target=ip, in_port=port)
# Now that the rules are ready, direct icmpv6 neighbor advertisement
# traffic from the port into the anti-spoof table.
self.add_flow(table=constants.LOCAL_SWITCHING,
priority=10, dl_type=const.ETHERTYPE_IPV6,
nw_proto=const.PROTO_NUM_ICMP_V6,
nw_proto=const.PROTO_NUM_IPV6_ICMP,
icmp_type=const.ICMPV6_TYPE_NA, in_port=port,
actions=("resubmit(,%s)" % constants.ARP_SPOOF_TABLE))
@ -147,7 +148,7 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
self.delete_flows(table_id=constants.LOCAL_SWITCHING,
in_port=port, proto='arp')
self.delete_flows(table_id=constants.LOCAL_SWITCHING,
in_port=port, nw_proto=const.PROTO_NUM_ICMP_V6,
in_port=port, nw_proto=const.PROTO_NUM_IPV6_ICMP,
icmp_type=const.ICMPV6_TYPE_NA)
self.delete_arp_spoofing_allow_rules(port)

View File

@ -612,7 +612,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'port_range_min': 23,
'source_ip_prefix': fake_prefix},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': fake_gateway,
'source_port_range_min': const.ICMPV6_TYPE_RA},
@ -727,7 +727,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'security_group_id': sg1_id,
'port_range_min': 22},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': gateway_lla_ip,
'source_port_range_min': const.ICMPV6_TYPE_RA},
@ -801,7 +801,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'security_group_id': sg1_id,
'port_range_min': 22},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': gateway_lla_ip,
'source_port_range_min': const.ICMPV6_TYPE_RA},
@ -870,7 +870,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'security_group_id': sg1_id,
'port_range_min': 22},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': gateway_lla_ip,
'source_port_range_min': const.ICMPV6_TYPE_RA},
@ -926,7 +926,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'security_group_id': sg1_id,
'port_range_min': 22},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': fake_gateway,
'source_port_range_min': const.ICMPV6_TYPE_RA},
@ -1032,7 +1032,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'port_range_min': 23,
'dest_ip_prefix': fake_prefix},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': fake_gateway,
'source_port_range_min': const.ICMPV6_TYPE_RA},
@ -1097,7 +1097,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
'remote_group_id': sg2_id,
'security_group_id': sg1_id},
{'direction': 'ingress',
'protocol': const.PROTO_NAME_ICMP_V6,
'protocol': const.PROTO_NAME_IPV6_ICMP,
'ethertype': const.IPv6,
'source_ip_prefix': fake_gateway,
'source_port_range_min': const.ICMPV6_TYPE_RA},

View File

@ -16,6 +16,7 @@ import testtools
from neutron.callbacks import exceptions
from neutron.callbacks import registry
from neutron.common import constants
from neutron import context
from neutron.db import common_db_mixin
from neutron.db import securitygroups_db
@ -83,3 +84,22 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase):
with testtools.ExpectedException(
securitygroup.SecurityGroupRuleNotFound):
self.mixin.delete_security_group_rule(self.ctx, 'foo_rule')
def test_validate_ethertype_and_protocol(self):
fake_ipv4_rules = [{'protocol': constants.PROTO_NAME_IPV6_ICMP,
'ethertype': constants.IPv4},
{'protocol': constants.PROTO_NAME_IPV6_ENCAP,
'ethertype': constants.IPv4},
{'protocol': constants.PROTO_NAME_IPV6_ROUTE,
'ethertype': constants.IPv4},
{'protocol': constants.PROTO_NAME_IPV6_FRAG,
'ethertype': constants.IPv4},
{'protocol': constants.PROTO_NAME_IPV6_NONXT,
'ethertype': constants.IPv4},
{'protocol': constants.PROTO_NAME_IPV6_OPTS,
'ethertype': constants.IPv4}]
# test wrong protocols
for rule in fake_ipv4_rules:
with testtools.ExpectedException(
securitygroup.SecurityGroupEthertypeConflictWithProtocol):
self.mixin._validate_ethertype_and_protocol(rule)

View File

@ -427,7 +427,7 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
with self.security_group(name, description) as sg:
security_group_id = sg['security_group']['id']
rule = self._build_security_group_rule(
security_group_id, 'ingress', const.PROTO_NAME_ICMP_V6)
security_group_id, 'ingress', const.PROTO_NAME_IPV6_ICMP)
res = self._create_security_group_rule(self.fmt, rule)
self.deserialize(self.fmt, res)
self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int)
@ -813,7 +813,7 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
direction = "ingress"
ethertype = const.IPv6
remote_ip_prefix = "2001::f401:56ff:fefe:d3dc/128"
protocol = const.PROTO_NAME_ICMP_V6
protocol = const.PROTO_NAME_IPV6_ICMP
# ICMPV6 type
port_range_min = const.ICMPV6_TYPE_RA
# ICMPV6 code
@ -1348,7 +1348,7 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
with self.security_group() as sg:
rule = {'security_group_id': sg['security_group']['id'],
'direction': 'ingress',
'ethertype': 'IPv4',
'ethertype': const.IPv4,
'tenant_id': 'test-tenant'}
res = self._create_security_group_rule(
@ -1363,11 +1363,11 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
with self.security_group() as sg:
rule_v4 = {'security_group_id': sg['security_group']['id'],
'direction': 'ingress',
'ethertype': 'IPv4',
'ethertype': const.IPv4,
'tenant_id': 'test-tenant'}
rule_v6 = {'security_group_id': sg['security_group']['id'],
'direction': 'ingress',
'ethertype': 'IPv6',
'ethertype': const.IPv6,
'tenant_id': 'test-tenant'}
rules = {'security_group_rules': [rule_v4, rule_v6]}

View File

@ -194,17 +194,17 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
expected = [
call.add_flow(dl_type=const.ETHERTYPE_IPV6, actions='normal',
icmp_type=const.ICMPV6_TYPE_NA,
nw_proto=const.PROTO_NUM_ICMP_V6,
nw_proto=const.PROTO_NUM_IPV6_ICMP,
nd_target='2001:db8::1',
priority=2, table=24, in_port=8888),
call.add_flow(dl_type=const.ETHERTYPE_IPV6, actions='normal',
icmp_type=const.ICMPV6_TYPE_NA,
nw_proto=const.PROTO_NUM_ICMP_V6,
nw_proto=const.PROTO_NUM_IPV6_ICMP,
nd_target='fdf8:f53b:82e4::1/128',
priority=2, table=24, in_port=8888),
call.add_flow(dl_type=const.ETHERTYPE_IPV6,
icmp_type=const.ICMPV6_TYPE_NA,
nw_proto=const.PROTO_NUM_ICMP_V6,
nw_proto=const.PROTO_NUM_IPV6_ICMP,
priority=10, table=0, in_port=8888,
actions='resubmit(,24)')
]

View File

@ -0,0 +1,7 @@
---
prelude: >
Add popular IP protocols to the security group code. End-users can
specify protocol names instead of protocol numbers in both RESTful
API and python-neutronclient CLI.
upgrade:
- Add popular IP protocols to security group code.