]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix unshortened IPv6 address caused DHCP crash
authorXuhan Peng <xuhanp@cn.ibm.com>
Wed, 12 Feb 2014 08:41:23 +0000 (03:41 -0500)
committerXuhan Peng <xuhanp@cn.ibm.com>
Thu, 20 Feb 2014 05:29:53 +0000 (00:29 -0500)
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
neutron/tests/unit/test_linux_interface.py

index c763b03a30d62771f73cb6be5ef979d64b3e12ac..24d7c2c44817118951f1504fe44d423d41e918b8 100644 (file)
@@ -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
index 43ebd093a3c8ff55caedb9cdfebe41b3c1ec613a..0ea878a94fa430b13b2b6fad4da10cfafc842e87 100644 (file)
@@ -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):