From 828daf9f133c51fb18b0147760c5a2d4f3b9f663 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 (cherry picked from commit 4747de23d80ab32eea073846221adf94987f755b) --- 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 cc65410377a..b921d6a2099 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -643,21 +643,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 b87ca983f81..dacff2a0aaf 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -1418,9 +1418,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: