diff --git a/neutron/agent/l3/dvr_local_router.py b/neutron/agent/l3/dvr_local_router.py index af5ce59f792..4f753685cdb 100644 --- a/neutron/agent/l3/dvr_local_router.py +++ b/neutron/agent/l3/dvr_local_router.py @@ -336,6 +336,19 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase): 'add', device=device, device_exists=device_exists) + + # subnet_ports does not have snat port if the port is still unbound + # by the time this function is called. So ensure to add arp entry + # for snat port if port details are updated in router info. + for p in self.get_snat_interfaces(): + for fixed_ip in p['fixed_ips']: + if fixed_ip['subnet_id'] == subnet_id: + self._update_arp_entry(fixed_ip['ip_address'], + p['mac_address'], + subnet_id, + 'add', + device=device, + device_exists=device_exists) self._process_arp_cache_for_internal_port(subnet_id) @staticmethod diff --git a/neutron/tests/unit/agent/l3/test_agent.py b/neutron/tests/unit/agent/l3/test_agent.py index 30e3caa8a35..8154dd3dbe0 100644 --- a/neutron/tests/unit/agent/l3/test_agent.py +++ b/neutron/tests/unit/agent/l3/test_agent.py @@ -1271,6 +1271,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): router[lib_constants.INTERFACE_KEY][0]) ri.router['distributed'] = True ri.router['_snat_router_interfaces'] = [{ + 'mac_address': 'fa:16:3e:80:8d:80', 'fixed_ips': [{'subnet_id': subnet_id, 'ip_address': '1.2.3.4'}]}] ri.router['gw_port_host'] = None diff --git a/neutron/tests/unit/agent/l3/test_dvr_local_router.py b/neutron/tests/unit/agent/l3/test_dvr_local_router.py index 4c913815bbe..d30e5ced38f 100644 --- a/neutron/tests/unit/agent/l3/test_dvr_local_router.py +++ b/neutron/tests/unit/agent/l3/test_dvr_local_router.py @@ -545,6 +545,11 @@ class TestDvrRouterOperations(base.BaseTestCase): ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) ports = ri.router.get(lib_constants.INTERFACE_KEY, []) subnet_id = l3_test_common.get_subnet_id(ports[0]) + ri.router['_snat_router_interfaces'] = [{ + 'mac_address': 'fa:16:3e:80:8d:80', + 'fixed_ips': [{'subnet_id': subnet_id, + 'ip_address': '1.2.3.10'}]}] + test_ports = [{'mac_address': '00:11:22:33:44:55', 'device_owner': lib_constants.DEVICE_OWNER_DHCP, 'fixed_ips': [{'ip_address': '1.2.3.4', @@ -576,7 +581,8 @@ class TestDvrRouterOperations(base.BaseTestCase): self.assertEqual(1, parp.call_count) self.mock_ip_dev.neigh.add.assert_has_calls([ mock.call('1.2.3.4', '00:11:22:33:44:55'), - mock.call('10.20.30.40', '00:11:22:33:44:55')]) + mock.call('10.20.30.40', '00:11:22:33:44:55'), + mock.call('1.2.3.10', 'fa:16:3e:80:8d:80')]) # Test negative case router['distributed'] = False