diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index fb8c859..06f2636 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -1046,6 +1046,15 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2, if attributes.is_attr_set(s.get('cidr')): self._validate_ip_version(ip_ver, s['cidr'], 'cidr') + # Note(watanabe.isao): We are only restricting IPv4 here. + # This is because, for now, neutron is only using EUI64 interface, + # and prefix length of IPv6 has already been restricted to 64. + # Note(watanabe.isao): After we found a way to avoid the re-sync + # from the agent side, this restrict could be removed. + if ip_ver == 4 and netaddr.IPNetwork(s['cidr']).prefixlen > 30: + error_message = _("Netmask is not valid on subnet") + raise n_exc.InvalidInput(error_message=error_message) + if attributes.is_attr_set(s.get('gateway_ip')): self._validate_ip_version(ip_ver, s['gateway_ip'], 'gateway_ip') if (cfg.CONF.force_gateway_on_subnet and diff --git a/neutron/tests/unit/db/test_db_base_plugin_v2.py b/neutron/tests/unit/db/test_db_base_plugin_v2.py index 0dc1800..5e529e3 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -1337,9 +1337,13 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s data['port']['fixed_ips']) def test_no_more_port_exception(self): - with self.subnet(cidr='10.0.0.0/32', gateway_ip=None) as subnet: + with self.subnet(cidr='10.0.0.0/30') as subnet: id = subnet['subnet']['network_id'] res = self._create_port(self.fmt, id) + # Note(watanabe.isao): 4 Ports are, Gateway port, Broadcast port, + # DHCP port and the ONE created above. + # The following port_create call will cause an exception. + res = self._create_port(self.fmt, id) data = self.deserialize(self.fmt, res) msg = str(n_exc.IpAddressGenerationFailure(net_id=id)) self.assertEqual(data['NeutronError']['message'], msg) @@ -3220,8 +3224,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): self.subnet(cidr='13.129.122.5/18'), self.subnet(cidr='14.129.122.5/22'), self.subnet(cidr='15.129.122.5/24'), - self.subnet(cidr='16.129.122.5/28'), - self.subnet(cidr='17.129.122.5/32', gateway_ip=None) + self.subnet(cidr='16.129.122.5/28', gateway_ip=None) ) as subs: # the API should accept and correct these for users self.assertEqual(subs[0]['subnet']['cidr'], '10.0.0.0/8') @@ -3231,7 +3234,17 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): self.assertEqual(subs[4]['subnet']['cidr'], '14.129.120.0/22') self.assertEqual(subs[5]['subnet']['cidr'], '15.129.122.0/24') self.assertEqual(subs[6]['subnet']['cidr'], '16.129.122.0/28') - self.assertEqual(subs[7]['subnet']['cidr'], '17.129.122.5/32') + + def test_create_subnet_with_invalid_netmask_returns_400(self): + with self.network() as network: + self._create_subnet(self.fmt, + network['network']['id'], + '10.0.0.0/31', + webob.exc.HTTPClientError.code) + self._create_subnet(self.fmt, + network['network']['id'], + '10.0.0.0/32', + webob.exc.HTTPClientError.code) def test_create_subnet_bad_ip_version(self): with self.network() as network: