]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix dynamic arp populate error for dvr routers
authorSwaminathan Vasudevan <swaminathan.vasudevan@hp.com>
Fri, 3 Apr 2015 00:25:39 +0000 (17:25 -0700)
committerarmando-migliaccio <armamig@gmail.com>
Tue, 7 Apr 2015 02:58:51 +0000 (19:58 -0700)
Recent refactor to the L3 Agent have introduced
this problem. When we create a VM after we
attach an interface to a router or when we add
an interface with an existing VM to a router, in
both cases the arp entries for the dvr serviced
ports are not getting populated in the Router
Namespace.

Closes-Bug: #1438969

Change-Id: I4a82e2435d176f3d9336d7f0dab9726c063840b9
Co-authored-by: Armando Migliaccio <armamig@gmail.com>
neutron/agent/l3/dvr_router.py
neutron/agent/linux/ip_lib.py
neutron/tests/functional/agent/test_l3_agent.py

index b18cb9aee46905d2e108de36327e13d89b14f0e0..4d2539ff44f7415399458a1f37f243e1b1ad2404 100644 (file)
@@ -307,6 +307,14 @@ class DvrRouter(router.RouterInfo):
     def internal_network_added(self, port):
         super(DvrRouter, self).internal_network_added(port)
 
+        # NOTE: The following function _set_subnet_arp_info
+        # should be called to dynamically populate the arp
+        # entries for the dvr services ports into the router
+        # namespace. This does not have dependency on the
+        # external_gateway port or the agent_mode.
+        for subnet in port['subnets']:
+            self._set_subnet_arp_info(subnet['id'])
+
         ex_gw_port = self.get_ex_gw_port()
         if not ex_gw_port:
             return
@@ -333,9 +341,6 @@ class DvrRouter(router.RouterInfo):
             interface_name,
             dvr_snat_ns.SNAT_INT_DEV_PREFIX)
 
-        for subnet in port['subnets']:
-            self._set_subnet_arp_info(subnet['id'])
-
     def _dvr_internal_network_removed(self, port):
         if not self.ex_gw_port:
             return
index 330ea3dd6501a724ef8698ad24bdd4f6fcf93ae0..119dc9341d00269ced14fe1ea20be0617a711a5f 100644 (file)
@@ -544,6 +544,11 @@ class IpNeighCommand(IpDeviceCommandBase):
                        'lladdr', mac_address,
                        'dev', self.name))
 
+    def show(self):
+        return self._as_root([],
+                      ('show',
+                       'dev', self.name))
+
 
 class IpNetnsCommand(IpCommandBase):
     COMMAND = 'netns'
index 719ab605af62cbe543777f32b06ccc8184a5548a..ec5deb025a1da27b1a6b558cf198fbb6461b4bfe 100755 (executable)
@@ -1051,6 +1051,26 @@ class TestDvrRouter(L3AgentTestFramework):
         self._assert_dvr_snat_gateway(router1)
         self.assertFalse(self._namespace_exists(fip_ns))
 
+    def test_dvr_router_add_internal_network_set_arp_cache(self):
+        # Check that, when the router is set up and there are
+        # existing ports on the the uplinked subnet, the ARP
+        # cache is properly populated.
+        self.agent.conf.agent_mode = 'dvr_snat'
+        router_info = test_l3_agent.prepare_router_data()
+        router_info['distributed'] = True
+        expected_neighbor = '35.4.1.10'
+        port_data = {
+            'fixed_ips': [{'ip_address': expected_neighbor}],
+            'mac_address': 'fa:3e:aa:bb:cc:dd',
+            'device_owner': 'compute:None'
+        }
+        self.agent.plugin_rpc.get_ports_by_subnet.return_value = [port_data]
+        router1 = self._create_router(self.agent, router_info)
+        internal_device = router1.get_internal_device_name(
+            router_info['_interfaces'][0]['id'])
+        neighbors = ip_lib.IPDevice(internal_device, router1.ns_name).neigh
+        self.assertEqual(expected_neighbor, neighbors.show().split()[0])
+
     def _assert_rfp_fpr_mtu(self, router, expected_mtu=1500):
         dev_mtu = self.get_device_mtu(
             router.router_id, router.fip_ns.get_rtr_ext_device_name,