IPv6 accepts first address only for routers

Neutron considers the network address a valid IPv6 address if the
owner is a router or is not defined yet [1][2]. If not, the IPv6
address is discharded.

[1] https://tools.ietf.org/html/rfc4291#section-2.6.1
[2] https://review.opendev.org/#/c/647484/

Change-Id: I1ddee94bd34182960de8e5261fbc99edc10b6654
Closes-Bug: #1859163
This commit is contained in:
Rodolfo Alonso Hernandez 2020-01-10 13:57:08 +00:00
parent ae67ae824c
commit b20669fa6e
2 changed files with 33 additions and 7 deletions

View File

@ -27,7 +27,8 @@ def check_subnet_ip(cidr, ip_address, port_owner=''):
# NOTE(njohnston): In some cases the code cannot know the owner of the
# port. In these cases port_owner should an empty string, and we pass
# it through here.
return (port_owner in (constants.ROUTER_PORT_OWNERS + ('', )) and
return ((port_owner in (constants.ROUTER_PORT_OWNERS + ('', )) or
ip != net.network) and
ip in net)
else:
return ip != net.network and ip != net.broadcast and ip in net

View File

@ -14,6 +14,7 @@
# under the License.
import netaddr
from neutron_lib import constants
from neutron.ipam import utils
from neutron.tests import base
@ -31,13 +32,37 @@ class TestIpamUtils(base.BaseTestCase):
self.assertTrue(utils.check_subnet_ip('1.1.1.0/24', '1.1.1.1'))
self.assertTrue(utils.check_subnet_ip('1.1.1.0/24', '1.1.1.254'))
def test_check_subnet_ip_v6_network(self):
self.assertTrue(utils.check_subnet_ip('F111::0/64', 'F111::0'))
def test_check_subnet_ip_v6_owner_router_or_not_defined(self):
for port_owner in (constants.ROUTER_PORT_OWNERS + ('', )):
# IP address == network
self.assertTrue(utils.check_subnet_ip('F111::0/64', 'F111::0',
port_owner=port_owner))
# IP address == broadcast
self.assertTrue(utils.check_subnet_ip(
'F111::0/64', 'F111::FFFF:FFFF:FFFF:FFFF',
port_owner=port_owner))
# IP address in network
self.assertTrue(utils.check_subnet_ip('F111::0/64', 'F111::50',
port_owner=port_owner))
# IP address not in network
self.assertFalse(utils.check_subnet_ip('F111::0/64', 'F112::50',
port_owner=port_owner))
def test_check_subnet_ip_v6_valid(self):
self.assertTrue(utils.check_subnet_ip('F111::0/64', 'F111::1'))
self.assertTrue(utils.check_subnet_ip('F111::0/64',
'F111::FFFF:FFFF:FFFF:FFFF'))
def test_check_subnet_ip_v6_owner_not_router(self):
port_owner = 'nova:compute'
# IP address == network
self.assertFalse(utils.check_subnet_ip('F111::0/64', 'F111::0',
port_owner=port_owner))
# IP address == broadcast
self.assertTrue(utils.check_subnet_ip(
'F111::0/64', 'F111::FFFF:FFFF:FFFF:FFFF',
port_owner=port_owner))
# IP address in network
self.assertTrue(utils.check_subnet_ip('F111::0/64', 'F111::50',
port_owner=port_owner))
# IP address not in network
self.assertFalse(utils.check_subnet_ip('F111::0/64', 'F112::50',
port_owner=port_owner))
def test_generate_pools_v4_nogateway(self):
cidr = '192.168.0.0/24'