From 64abee5aa27c22ba386592ada2d52e6983727a89 Mon Sep 17 00:00:00 2001 From: LIU Yulong Date: Tue, 2 Mar 2021 11:26:34 +0800 Subject: [PATCH] Clean port forwarding cache when router is DOWN Port forwarding L3 agent extension needs to clean cache when router is DOWN, otherwise the port forwarding extension will skip all objects processing when router is UP again, because the cache is hitting. This patch addresses this issue. Change-Id: Idd65f1eda020ada9a76c39904efa8d55680d9e6b Closes-bug: #1917393 (cherry picked from commit 058214670820be6f40e8ab05c0e1dbe8dc389abc) --- .../agent/l3/extensions/port_forwarding.py | 10 +++++- .../l3/extensions/test_port_forwarding.py | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/neutron/agent/l3/extensions/port_forwarding.py b/neutron/agent/l3/extensions/port_forwarding.py index 118ab951536..a9ad4a68924 100644 --- a/neutron/agent/l3/extensions/port_forwarding.py +++ b/neutron/agent/l3/extensions/port_forwarding.py @@ -100,6 +100,14 @@ class RouterFipPortForwardingMapping(object): old_pf = self.managed_port_forwardings.get(new_pf.id) return old_pf != new_pf + @lockutils.synchronized('port-forwarding-cache') + def clean_port_forwardings_by_router_id(self, router_id): + router_fips = self.router_fip_mapping.pop(router_id, []) + for fip_id in router_fips: + pf_ids = self.fip_port_forwarding.pop(fip_id, []) + for pf_id in pf_ids: + self.managed_port_forwardings.pop(pf_id, None) + class PortForwardingAgentExtension(l3_extension.L3AgentExtension): SUPPORTED_RESOURCE_TYPES = [resources.PORTFORWARDING] @@ -458,7 +466,7 @@ class PortForwardingAgentExtension(l3_extension.L3AgentExtension): :param context: RPC context. :param data: Router data. """ - pass + self.mapping.clean_port_forwardings_by_router_id(data['id']) def ha_state_change(self, context, data): pass diff --git a/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py b/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py index 24ef57a03cd..5a262622d0e 100644 --- a/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py +++ b/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py @@ -282,6 +282,38 @@ class FipPortForwardingExtensionTestCase(PortForwardingExtensionBaseTestCase): lib_const.FLOATINGIP_STATUS_DOWN} mock_send_fip_status.assert_called_once_with(mock.ANY, fip_status) + @mock.patch.object(pf.PortForwardingAgentExtension, + '_sending_port_forwarding_fip_status') + @mock.patch.object(iptables_manager.IptablesTable, 'add_rule') + @mock.patch.object(iptables_manager.IptablesTable, 'add_chain') + @mock.patch.object(l3router.RouterInfo, 'add_floating_ip') + def test_add_delete_router(self, mock_add_fip, + mock_add_chain, mock_add_rule, + mock_send_fip_status): + # simulate the router add and already there is a port forwarding + # resource association. + mock_add_fip.return_value = lib_const.FLOATINGIP_STATUS_ACTIVE + self.fip_pf_ext.add_router(self.context, self.router) + self._assert_called_iptables_process( + mock_add_chain, mock_add_rule, mock_add_fip, mock_send_fip_status, + target_obj=self.portforwarding1) + + router_fip_ids = self.fip_pf_ext.mapping.router_fip_mapping.get( + self.router['id']) + self.assertIsNotNone(router_fip_ids) + for fip_id in router_fip_ids: + pf_ids = self.fip_pf_ext.mapping.fip_port_forwarding.get(fip_id) + self.assertIsNotNone(pf_ids) + for pf_id in pf_ids: + pf = self.fip_pf_ext.mapping.managed_port_forwardings.get( + pf_id) + self.assertIsNotNone(pf) + + self.fip_pf_ext.delete_router(self.context, self.router) + + self.assertIsNone( + self.fip_pf_ext.mapping.router_fip_mapping.get(self.router['id'])) + def test_check_if_need_process_no_snat_ns(self): ex_gw_port = {'id': _uuid()} router_id = _uuid()