From 597288b1d1dfd148d1d782230bd258f3c851cbe0 Mon Sep 17 00:00:00 2001 From: Xuhan Peng Date: Wed, 12 Feb 2014 03:41:23 -0500 Subject: [PATCH] Fix unshortened IPv6 address caused DHCP crash When unshortened IPv6 address provided to allocation pool, DHCP agent crashed because OpenStack is trying to add same IPv6 addresses to dhcp tap device. The root cause is that current code compares provided unshortened IPv6 address with the returned result of "ip addr list", which is shortened. So the same IPv6 address is treated as different ones. The fix is trying to shorten the provided address before comparison. Change-Id: If1e183e65c5ab785b73771d9a3d4b525d38284a9 Closes-Bug: 1266780 --- neutron/agent/linux/interface.py | 4 +++ neutron/tests/unit/test_linux_interface.py | 40 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/neutron/agent/linux/interface.py b/neutron/agent/linux/interface.py index c763b03a30..24d7c2c448 100644 --- a/neutron/agent/linux/interface.py +++ b/neutron/agent/linux/interface.py @@ -90,6 +90,10 @@ class LinuxInterfaceDriver(object): for ip_cidr in ip_cidrs: net = netaddr.IPNetwork(ip_cidr) + # Convert to compact IPv6 address because the return values of + # "ip addr list" are compact. + if net.version == 6: + ip_cidr = str(net) if ip_cidr in previous: del previous[ip_cidr] continue diff --git a/neutron/tests/unit/test_linux_interface.py b/neutron/tests/unit/test_linux_interface.py index 43ebd093a3..0ea878a94f 100644 --- a/neutron/tests/unit/test_linux_interface.py +++ b/neutron/tests/unit/test_linux_interface.py @@ -109,6 +109,46 @@ class TestABCDriver(TestBase): mock.call().addr.add(4, '192.168.1.2/24', '192.168.1.255')]) self.assertFalse(self.ip_dev().addr.delete.called) + def test_l3_init_with_ipv6(self): + addresses = [dict(ip_version=6, + scope='global', + dynamic=False, + cidr='2001:db8:a::123/64')] + self.ip_dev().addr.list = mock.Mock(return_value=addresses) + bc = BaseChild(self.conf) + ns = '12345678-1234-5678-90ab-ba0987654321' + bc.init_l3('tap0', ['2001:db8:a::124/64'], namespace=ns) + self.ip_dev.assert_has_calls( + [mock.call('tap0', 'sudo', namespace=ns), + mock.call().addr.list(scope='global', filters=['permanent']), + mock.call().addr.add(6, '2001:db8:a::124/64', + '2001:db8:a:0:ffff:ffff:ffff:ffff'), + mock.call().addr.delete(6, '2001:db8:a::123/64')]) + + def test_l3_init_with_duplicated_ipv6(self): + addresses = [dict(ip_version=6, + scope='global', + dynamic=False, + cidr='2001:db8:a::123/64')] + self.ip_dev().addr.list = mock.Mock(return_value=addresses) + bc = BaseChild(self.conf) + ns = '12345678-1234-5678-90ab-ba0987654321' + bc.init_l3('tap0', ['2001:db8:a::123/64'], namespace=ns) + self.assertFalse(self.ip_dev().addr.add.called) + + def test_l3_init_with_duplicated_ipv6_uncompact(self): + addresses = [dict(ip_version=6, + scope='global', + dynamic=False, + cidr='2001:db8:a::123/64')] + self.ip_dev().addr.list = mock.Mock(return_value=addresses) + bc = BaseChild(self.conf) + ns = '12345678-1234-5678-90ab-ba0987654321' + bc.init_l3('tap0', + ['2001:db8:a:0000:0000:0000:0000:0123/64'], + namespace=ns) + self.assertFalse(self.ip_dev().addr.add.called) + class TestOVSInterfaceDriver(TestBase):