From 98c4c0876d4df31cf1eb34a2bcc40660e938a2ef Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Sun, 25 Sep 2016 15:49:19 -0700 Subject: [PATCH] Correct fix for IPv6 auto address interfaces This is a partial revert of d1fb4238306f854ab610204a50c5cdc20ea5c770. That patch attempted to allow the DHCP agent to manage IPv6 interfaces to avoid a KeyError in the subnet_interface_map. However, this led to races with router advertisements and static configuration (see bug 1627902). The correct fix was actually a very simple conditional that was broken because this map shouldn't have been referenced for IPv6 subnets in the first place. The force metadata option was shortcutting the whole evaluation so the agent was trying to add a metadata route to a v6 subnet. This patch undoes the v6 changes from d1fb4238306f854ab610204a50c5cdc20ea5c770, corrects the conditional, and adds a simple unit test that ensures the branch doesn't throw and error. Closes-Bug: #1624079 Change-Id: Ide494b6333a4f1e279ab58aa27c0aa719e79545d (cherry picked from commit c0d0986e8b7412f7c37db799177dc529ce9045d2) --- neutron/agent/linux/dhcp.py | 10 +++++----- neutron/common/ipv6_utils.py | 6 ------ neutron/tests/unit/agent/linux/test_dhcp.py | 9 +++++++++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 70f26683097..42de7a2c27f 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -894,10 +894,10 @@ class Dnsmasq(DhcpLocalProcess): # Add host routes for isolated network segments - if (self.conf.force_metadata or - (isolated_subnets[subnet.id] and - self.conf.enable_isolated_metadata and - subnet.ip_version == 4)): + if ((self.conf.force_metadata or + (isolated_subnets[subnet.id] and + self.conf.enable_isolated_metadata)) and + subnet.ip_version == 4): subnet_dhcp_ip = subnet_to_interface_ip[subnet.id] host_routes.append( '%s/32,%s' % (METADATA_DEFAULT_IP, subnet_dhcp_ip) @@ -1373,7 +1373,7 @@ class DeviceManager(object): ip_cidrs = [] for fixed_ip in port.fixed_ips: subnet = fixed_ip.subnet - if not ipv6_utils.is_slaac_subnet(subnet): + if not ipv6_utils.is_auto_address_subnet(subnet): net = netaddr.IPNetwork(subnet.cidr) ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen) ip_cidrs.append(ip_cidr) diff --git a/neutron/common/ipv6_utils.py b/neutron/common/ipv6_utils.py index aee35db13ad..f54ef4c759b 100644 --- a/neutron/common/ipv6_utils.py +++ b/neutron/common/ipv6_utils.py @@ -76,12 +76,6 @@ def is_auto_address_subnet(subnet): or subnet['ipv6_ra_mode'] in modes) -def is_slaac_subnet(subnet): - """Check if subnet is a slaac subnet.""" - return (subnet['ipv6_address_mode'] == const.IPV6_SLAAC - or subnet['ipv6_ra_mode'] == const.IPV6_SLAAC) - - def is_eui64_address(ip_address): """Check if ip address is EUI64.""" ip = netaddr.IPAddress(ip_address) diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index be2b8c290b6..2dd645644e8 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -1572,6 +1572,15 @@ class TestDnsmasq(TestBase): self._test_output_opts_file(expected, FakeV6Network()) + def test_output_opts_file_ipv6_address_force_metadata(self): + fake_v6 = '2001:0200:feed:7ac0::1' + expected = ( + 'tag:tag0,option6:dns-server,%s\n' + 'tag:tag0,option6:domain-search,openstacklocal').lstrip() % ( + '[' + fake_v6 + ']') + self.conf.force_metadata = True + self._test_output_opts_file(expected, FakeV6Network()) + @property def _test_no_dhcp_domain_alloc_data(self): exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host'