From 3593620faa37322a1aaf1ce0c0ae3065ec623c2f Mon Sep 17 00:00:00 2001 From: Yaohua Yan Date: Mon, 27 Feb 2017 22:26:08 +0800 Subject: [PATCH] Change the way to distinguish the port type In delete_port_postcommit, a DVR port (port['device_owner'] = DEVICE_OWNER_ROUTER_SNAT) can match on l2pop_db.HA_ROUTER_PORTS[1], but can not get any fdb entries by _get_ha_port_agents_fdb. Then, the fdb_entries[network_id]['ports'] is been overwritten by {}. So the associated flow entries will not be deleted. Closes-Bug: #1668277 Change-Id: I7b621157fe85945acd99e4f08b6370d2f9c3d44d --- .../plugins/ml2/drivers/l2pop/mech_driver.py | 3 +- .../ml2/drivers/l2pop/test_mech_driver.py | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py index e1f5a1371b3..2232054d4ee 100644 --- a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py +++ b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py @@ -73,7 +73,8 @@ class L2populationMechanismDriver(api.MechanismDriver): agent_host = context.host fdb_entries = self._get_agent_fdb( context, context.bottom_bound_segment, port, agent_host) - if port['device_owner'] in l2pop_db.HA_ROUTER_PORTS and fdb_entries: + if fdb_entries and l3_hamode_db.is_ha_router_port( + context, port['device_owner'], port['device_id']): session = db_api.get_reader_session() network_id = port['network_id'] other_fdb_ports = self._get_ha_port_agents_fdb( diff --git a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py index ab5292ffede..d01b8eea9e3 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py +++ b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py @@ -30,6 +30,7 @@ from neutron.db import l3_agentschedulers_db from neutron.db import l3_hamode_db from neutron.extensions import portbindings from neutron.extensions import providernet as pnet +from neutron.plugins.ml2 import db as ml2_db from neutron.plugins.ml2 import driver_context from neutron.plugins.ml2.drivers.l2pop import db as l2pop_db from neutron.plugins.ml2.drivers.l2pop import mech_driver as l2pop_mech_driver @@ -1111,6 +1112,44 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): # are raised. l2pop_mech.delete_port_postcommit(port_context) + def test_delete_dvr_snat_port_fdb_entries(self): + l2pop_mech = l2pop_mech_driver.L2populationMechanismDriver() + l2pop_mech.initialize() + + self._setup_l3() + + with self.subnet(network=self._network, enable_dhcp=False) as snet: + host_arg = {portbindings.HOST_ID: HOST, 'admin_state_up': True} + with self.port(subnet=snet, + device_owner=constants.DEVICE_OWNER_ROUTER_SNAT, + arg_list=(portbindings.HOST_ID,), + **host_arg) as p: + device = 'tap' + p['port']['id'] + self.callbacks.update_device_up(self.adminContext, + agent_id=HOST, device=device) + dvr_snat_port = ml2_db.get_port(self.adminContext, + p['port']['id']) + self.mock_fanout.reset_mock() + + context = mock.Mock() + context.current = dvr_snat_port + context.host = HOST + segment = {'network_type': 'vxlan', 'segmentation_id': 1} + context.bottom_bound_segment = segment + + expected = {self._network['network']['id']: + {'segment_id': segment['segmentation_id'], + 'network_type': segment['network_type'], + 'ports': {'20.0.0.1': + [l2pop_rpc.PortInfo( + mac_address=p['port']['mac_address'], + ip_address=p['port']['fixed_ips'][0] + ['ip_address'])]}}} + + l2pop_mech.delete_port_postcommit(context) + self.mock_fanout.assert_called_with( + mock.ANY, 'remove_fdb_entries', expected) + def test_fixed_ips_change_unbound_port_no_rpc(self): l2pop_mech = l2pop_mech_driver.L2populationMechanismDriver() l2pop_mech.initialize()