if ra_mode_set and address_mode_set:
self._validate_ipv6_combination(subnet['ipv6_ra_mode'],
subnet['ipv6_address_mode'])
+ if address_mode_set:
+ self._validate_eui64_applicable(subnet)
+
+ def _validate_eui64_applicable(self, subnet):
+ # Per RFC 4862, section 5.5.3, prefix length and interface
+ # id together should be equal to 128. Currently neutron supports
+ # EUI64 interface id only, thus limiting the prefix
+ # length to be 64 only.
+ if self._check_if_subnet_uses_eui64(subnet):
+ if netaddr.IPNetwork(subnet['cidr']).prefixlen != 64:
+ msg = _('Invalid CIDR %s for IPv6 address mode. '
+ 'OpenStack uses the EUI-64 address format, '
+ 'which requires the prefix to be /64.')
+ raise n_exc.InvalidInput(
+ error_message=(msg % subnet['cidr']))
def _validate_ipv6_combination(self, ra_mode, address_mode):
if ra_mode != address_mode:
self._delete('ports', port3['port']['id'])
self._delete('ports', port4['port']['id'])
- def test_ip_allocation_for_ipv6_subnet_slaac_adddress_mode(self):
+ def test_ip_allocation_for_ipv6_subnet_slaac_address_mode(self):
res = self._create_network(fmt=self.fmt, name='net',
admin_state_up=True)
network = self.deserialize(self.fmt, res)
v6_subnet = self._make_subnet(self.fmt, network,
gateway='fe80::1',
- cidr='fe80::/80',
+ cidr='fe80::/64',
ip_version=6,
ipv6_ra_mode=None,
ipv6_address_mode=constants.IPV6_SLAAC)
res = subnet_req.get_response(self.api)
self.assertEqual(res.status_int, webob.exc.HTTPClientError.code)
+ def test_create_subnet_V6_slaac_big_prefix(self):
+ with self.network() as network:
+ data = {'subnet': {'network_id': network['network']['id'],
+ 'cidr': '2014::/65',
+ 'ip_version': '6',
+ 'tenant_id': network['network']['tenant_id'],
+ 'gateway_ip': 'fe80::1',
+ 'ipv6_address_mode': 'slaac'}}
+ subnet_req = self.new_create_request('subnets', data)
+ res = subnet_req.get_response(self.api)
+ self.assertEqual(webob.exc.HTTPClientError.code, res.status_int)
+
def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self):
cidr_1 = '10.0.0.0/23'
cidr_2 = '10.0.0.0/24'
def test_create_subnet_ipv6_attributes(self):
gateway_ip = 'fe80::1'
- cidr = 'fe80::/80'
+ cidr = 'fe80::/64'
for mode in constants.IPV6_MODES:
self._test_create_subnet(gateway_ip=gateway_ip,
def test_create_subnet_ipv6_attributes_no_dhcp_enabled(self):
gateway_ip = 'fe80::1'
- cidr = 'fe80::/80'
+ cidr = 'fe80::/64'
with testlib_api.ExpectedException(
webob.exc.HTTPClientError) as ctx_manager:
for mode in constants.IPV6_MODES:
def test_create_subnet_ipv6_single_attribute_set(self):
gateway_ip = 'fe80::1'
- cidr = 'fe80::/80'
+ cidr = 'fe80::/64'
for mode in constants.IPV6_MODES:
self._test_create_subnet(gateway_ip=gateway_ip,
cidr=cidr, ip_version=6,
webob.exc.HTTPConflict.code)
def test_update_subnet_ipv6_attributes(self):
- with self.subnet(ip_version=6, cidr='fe80::/80',
+ with self.subnet(ip_version=6, cidr='fe80::/64',
ipv6_ra_mode=constants.IPV6_SLAAC,
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
data = {'subnet': {'ipv6_ra_mode': constants.DHCPV6_STATEFUL,
data['subnet']['ipv6_address_mode'])
def test_update_subnet_ipv6_inconsistent_ra_attribute(self):
- with self.subnet(ip_version=6, cidr='fe80::/80',
+ with self.subnet(ip_version=6, cidr='fe80::/64',
ipv6_ra_mode=constants.IPV6_SLAAC,
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
data = {'subnet': {'ipv6_ra_mode': constants.DHCPV6_STATEFUL}}
webob.exc.HTTPClientError.code)
def test_update_subnet_ipv6_inconsistent_address_attribute(self):
- with self.subnet(ip_version=6, cidr='fe80::/80',
+ with self.subnet(ip_version=6, cidr='fe80::/64',
ipv6_ra_mode=constants.IPV6_SLAAC,
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
data = {'subnet': {'ipv6_address_mode': constants.DHCPV6_STATEFUL}}
webob.exc.HTTPClientError.code)
def test_update_subnet_ipv6_inconsistent_enable_dhcp(self):
- with self.subnet(ip_version=6, cidr='fe80::/80',
+ with self.subnet(ip_version=6, cidr='fe80::/64',
ipv6_ra_mode=constants.IPV6_SLAAC,
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
data = {'subnet': {'enable_dhcp': False}}