diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index e56f75ca73e..35991a43d3c 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -1023,16 +1023,15 @@ class _DVRAgentInterfaceMixin(object): """Generates the arp table entry and notifies the l3 agent.""" ip_address = fixed_ip['ip_address'] subnet = fixed_ip['subnet_id'] - filters = {'fixed_ips': {'subnet_id': [subnet]}, - 'device_owner': [const.DEVICE_OWNER_DVR_INTERFACE]} - ports = self._core_plugin.get_ports(context, filters=filters) - router_id = next((port['device_id'] for port in ports), None) - if not router_id: - return arp_table = {'ip_address': ip_address, 'mac_address': mac_address, 'subnet_id': subnet} - notifier(context, router_id, arp_table) + filters = {'fixed_ips': {'subnet_id': [subnet]}, + 'device_owner': [const.DEVICE_OWNER_DVR_INTERFACE]} + ports = self._core_plugin.get_ports(context, filters=filters) + routers = [port['device_id'] for port in ports] + for router_id in routers: + notifier(context, router_id, arp_table) def _get_subnet_id_for_given_fixed_ip( self, context, fixed_ip, port_dict): diff --git a/neutron/tests/unit/db/test_l3_dvr_db.py b/neutron/tests/unit/db/test_l3_dvr_db.py index 492207a58a9..94fd05e182b 100644 --- a/neutron/tests/unit/db/test_l3_dvr_db.py +++ b/neutron/tests/unit/db/test_l3_dvr_db.py @@ -826,6 +826,26 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): port=mock.ANY, interface_info=interface_info) + def test__generate_arp_table_and_notify_agent(self): + fixed_ip = { + 'ip_address': '1.2.3.4', + 'subnet_id': _uuid()} + mac_address = "00:11:22:33:44:55" + expected_arp_table = { + 'ip_address': fixed_ip['ip_address'], + 'subnet_id': fixed_ip['subnet_id'], + 'mac_address': mac_address} + notifier = mock.Mock() + ports = [{'id': _uuid(), 'device_id': 'router_1'}, + {'id': _uuid(), 'device_id': 'router_2'}] + with mock.patch.object(self.core_plugin, "get_ports", + return_value=ports): + self.mixin._generate_arp_table_and_notify_agent( + self.ctx, fixed_ip, mac_address, notifier) + notifier.assert_has_calls([ + mock.call(self.ctx, "router_1", expected_arp_table), + mock.call(self.ctx, "router_2", expected_arp_table)]) + def _test_update_arp_entry_for_dvr_service_port( self, device_owner, action): router_dict = {'name': 'test_router', 'admin_state_up': True,