From 4747de23d80ab32eea073846221adf94987f755b Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Mon, 14 Jan 2019 18:47:21 +0000 Subject: [PATCH] Remove IPv6 addresses in dnsmasq leases file IPv6 address format in dnsmasq leases file is incorrect (correct format is described in bug description). This bad formatting generates the following error when initializing dnsmasq: dnsmasq[20603]: failed to parse lease database, invalid line: \ 1547121093 fa:16:3e:a0:3a:9a [fd5b:1fd5:8295:5339::43] * ... This patch removes the IPv6 addresses from the leases file, as proposed in the bug, because the DHCP agent does not have the IAID (identity association identifier) of each IPv6 address assigned. In case of agent restart, dnsmasq won't have any IPv6 address in the leases file, but the hosts file and the additional hosts file will contain all MAC/IPv6 previous assignations. When the IPv6 client sends a DHCPDISCOVER, dnsmasq will offer the same IPv6 address to this client. At the same time, the client will request to the server the same address: DHCPDISCOVER(tap2c14823a-e6) fa:16:3e:54:c6:8e DHCPOFFER(tap2c14823a-e6) fd5b:1fd5:8295:5339::43 fa:16:3e:54:c6:8e DHCPREQUEST(tap2c14823a-e6) fd5b:1fd5:8295:5339::43 fa:16:3e:54:c6:8e DHCPACK(tap2c14823a-e6) fd5b:1fd5:8295:5339::43 fa:16:3e:54:c6:8e \ host-fd5b-1fd5-8295-5339--43 Once dnsmasq updates the leases database, rewrites the leases file with the new IPv6 address (including the IAID) and the server DUID (if not present). Change-Id: Ib1b2f284ab81f1c4af7b08b5257b45a3f6e79c3e Closes-Bug: #1722126 --- neutron/agent/linux/dhcp.py | 13 ++++++------- neutron/tests/unit/agent/linux/test_dhcp.py | 2 -- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 04a2d3564ea..0c078e22837 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -638,21 +638,20 @@ class Dnsmasq(DhcpLocalProcess): timestamp = 0 else: timestamp = int(time.time()) + self.conf.dhcp_lease_duration - dhcp_enabled_subnet_ids = [s.id for s in - self._get_all_subnets(self.network) - if s.enable_dhcp] + dhcpv4_enabled_subnet_ids = [ + s.id for s in self._get_all_subnets(self.network) + if s.enable_dhcp and s.ip_version == constants.IP_VERSION_4] for host_tuple in self._iter_hosts(): port, alloc, hostname, name, no_dhcp, no_opts = host_tuple # don't write ip address which belongs to a dhcp disabled subnet - # or an IPv6 SLAAC/stateless subnet - if no_dhcp or alloc.subnet_id not in dhcp_enabled_subnet_ids: + # or an IPv6 subnet. + if no_dhcp or alloc.subnet_id not in dhcpv4_enabled_subnet_ids: continue - ip_address = self._format_address_for_dnsmasq(alloc.ip_address) # all that matters is the mac address and IP. the hostname and # client ID will be overwritten on the next renewal. buf.write('%s %s %s * *\n' % - (timestamp, port.mac_address, ip_address)) + (timestamp, port.mac_address, alloc.ip_address)) contents = buf.getvalue() file_utils.replace_file(filename, contents) LOG.debug('Done building initial lease file %s with contents:\n%s', diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index ef25769e1cc..b2869c6ed00 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -1465,9 +1465,7 @@ class TestDnsmasq(TestBase): def _test_output_init_lease_file(self, timestamp): expected = [ '00:00:80:aa:bb:cc 192.168.0.2 * *', - '00:00:f3:aa:bb:cc [fdca:3ba5:a17a:4ba3::2] * *', '00:00:0f:aa:bb:cc 192.168.0.3 * *', - '00:00:0f:aa:bb:cc [fdca:3ba5:a17a:4ba3::3] * *', '00:00:0f:rr:rr:rr 192.168.0.1 * *\n'] expected = "\n".join(['%s %s' % (timestamp, l) for l in expected]) with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn: