diff --git a/vmware_nsx/common/nsxv_constants.py b/vmware_nsx/common/nsxv_constants.py index 59f329adfa..03e2c25076 100644 --- a/vmware_nsx/common/nsxv_constants.py +++ b/vmware_nsx/common/nsxv_constants.py @@ -55,3 +55,9 @@ CSR_REQUEST = ("" "CUS" "RSA2048" "") + +# Reserved IPs that cannot overlap defined subnets +RESERVED_IPS = ["169.254.128.0/17", + "169.254.1.0/24", + "169.254.2.0/28", + "169.254.64.192/26"] diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 8f6ec5c9af..de12f0cb2c 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -1105,6 +1105,31 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, self._update_dhcp_edge_service(context, network_id, address_groups) + def _is_overlapping_reserved_subnets(self, subnet): + """Return True if the subnet overlaps with reserved subnets. + + For the V plugin we have a limitation that we should not use + some reserved ranges like: 169.254.128.0/17 and 169.254.1.0/24 + """ + reserved_subnets = nsxv_constants.RESERVED_IPS + + # translate the given subnet to a range object + data = subnet['subnet'] + + if data['cidr'] not in (attr.ATTR_NOT_SPECIFIED, None): + range = netaddr.IPNetwork(data['cidr']) + + # Check each reserved subnet for intersection + for reserved_subnet in reserved_subnets: + # translate the reserved subnet to a range object + reserved_range = netaddr.IPNetwork(reserved_subnet) + # check if new subnet overlaps this reserved subnet + if (range.first <= reserved_range.last + and reserved_range.first <= range.last): + return True + + return False + def create_subnet(self, context, subnet): """Create subnet on nsx_v provider network. @@ -1128,6 +1153,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, and netaddr.IPNetwork(data['cidr']).version == 6)): err_msg = _("No support for DHCP for IPv6") raise n_exc.InvalidInput(error_message=err_msg) + if self._is_overlapping_reserved_subnets(subnet): + err_msg = _("The requested subnet contains reserved IP's") + raise n_exc.InvalidInput(error_message=err_msg) with locking.LockManager.get_lock( 'nsx-edge-pool', lock_file_prefix='edge-bind-'): diff --git a/vmware_nsx/tests/unit/nsx_v/test_plugin.py b/vmware_nsx/tests/unit/nsx_v/test_plugin.py index 9f04c9554b..733ba41c0c 100644 --- a/vmware_nsx/tests/unit/nsx_v/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v/test_plugin.py @@ -1212,6 +1212,22 @@ class TestSubnetsV2(NsxVPluginV2TestCase, def test_create_subnet_only_ip_version_v6_old(self): self.skipTest('Currently not supported') + def test_create_subnet_reserved_network(self): + self.mock_create_dhcp_service.stop() + name = 'overlap-reserved-net' + providernet_args = {pnet.NETWORK_TYPE: 'flat', + pnet.PHYSICAL_NETWORK: 'dvs-uuid'} + with testlib_api.ExpectedException( + webob.exc.HTTPClientError) as ctx_manager: + with self.network(name=name, do_delete=False, + providernet_args=providernet_args, + arg_list=(pnet.NETWORK_TYPE, + pnet.SEGMENTATION_ID, + pnet.PHYSICAL_NETWORK)) as net: + self._test_create_subnet(network=net, + cidr='169.254.128.128/25') + self.assertEqual(ctx_manager.exception.code, 400) + class TestSubnetPoolsV2(NsxVPluginV2TestCase, test_plugin.TestSubnetsV2): def setUp(self,