diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index e84d7761f9e..3fc3d0cd8bd 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1128,12 +1128,19 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, if int_type == 'veth': self.int_br.delete_port(int_if_name) br.delete_port(phys_if_name) - # Create patch ports without associating them in order to block - # untranslated traffic before association - int_ofport = self.int_br.add_patch_port( - int_if_name, constants.NONEXISTENT_PEER) - phys_ofport = br.add_patch_port( - phys_if_name, constants.NONEXISTENT_PEER) + + # Setup int_br to physical bridge patches. If they already + # exist we leave them alone, otherwise we create them but don't + # connect them until after the drop rules are in place. + int_ofport = self.int_br.get_port_ofport(int_if_name) + if int_ofport == ovs_lib.INVALID_OFPORT: + int_ofport = self.int_br.add_patch_port( + int_if_name, constants.NONEXISTENT_PEER) + + phys_ofport = br.get_port_ofport(phys_if_name) + if phys_ofport == ovs_lib.INVALID_OFPORT: + phys_ofport = br.add_patch_port( + phys_if_name, constants.NONEXISTENT_PEER) self.int_ofports[physical_network] = int_ofport self.phys_ofports[physical_network] = phys_ofport diff --git a/neutron/tests/functional/agent/test_l2_ovs_agent.py b/neutron/tests/functional/agent/test_l2_ovs_agent.py index d81395fe323..1a3130d2413 100644 --- a/neutron/tests/functional/agent/test_l2_ovs_agent.py +++ b/neutron/tests/functional/agent/test_l2_ovs_agent.py @@ -226,7 +226,7 @@ class TestOVSAgent(base.OVSAgentTestFramework): self.agent.setup_physical_bridges(self.agent.bridge_mappings) time.sleep(0.25) - def test_assert_patch_port_ofports_dont_change(self): + def test_assert_br_int_patch_port_ofports_dont_change(self): # When the integration bridge is setup, it should reuse the existing # patch ports between br-int and br-tun. self.setup_agent_and_ports(port_dicts=[], create_tunnels=True) @@ -237,6 +237,19 @@ class TestOVSAgent(base.OVSAgentTestFramework): self.assertEqual(patch_int_ofport_before, self.agent.patch_int_ofport) self.assertEqual(patch_tun_ofport_before, self.agent.patch_tun_ofport) + def test_assert_br_phys_patch_port_ofports_dont_change(self): + # When the integration bridge is setup, it should reuse the existing + # patch ports between br-int and br-phys. + self.setup_agent_and_ports(port_dicts=[]) + patch_int_ofport_before = self.agent.int_ofports['physnet'] + patch_phys_ofport_before = self.agent.phys_ofports['physnet'] + + self.setup_agent_and_ports(port_dicts=[]) + self.assertEqual(patch_int_ofport_before, + self.agent.int_ofports['physnet']) + self.assertEqual(patch_phys_ofport_before, + self.agent.phys_ofports['physnet']) + def test_noresync_after_port_gone(self): '''This will test the scenario where a port is removed after listing it but before getting vif info about it. diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index 1cd19edbec3..cf828e71f6b 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -1073,6 +1073,8 @@ class TestOvsNeutronAgent(object): parent.attach_mock(int_br, 'int_br') phys_br.add_patch_port.return_value = "phy_ofport" int_br.add_patch_port.return_value = "int_ofport" + phys_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT + int_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT self.agent.setup_physical_bridges({"physnet1": "br-eth"}) expected_calls = [ mock.call.phys_br_cls('br-eth'), @@ -1084,8 +1086,10 @@ class TestOvsNeutronAgent(object): # Have to use __getattr__ here to avoid mock._Call.__eq__ # method being called mock.call.int_br.db_get_val().__getattr__('__eq__')('veth'), + mock.call.int_br.get_port_ofport('int-br-eth'), mock.call.int_br.add_patch_port('int-br-eth', constants.NONEXISTENT_PEER), + mock.call.phys_br.get_port_ofport('phy-br-eth'), mock.call.phys_br.add_patch_port('phy-br-eth', constants.NONEXISTENT_PEER), mock.call.int_br.drop_port(in_port='int_ofport'), @@ -1154,6 +1158,8 @@ class TestOvsNeutronAgent(object): parent.attach_mock(int_br, 'int_br') phys_br.add_patch_port.return_value = "phy_ofport" int_br.add_patch_port.return_value = "int_ofport" + phys_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT + int_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT self.agent.setup_physical_bridges({"physnet1": "br-eth"}) expected_calls = [ mock.call.phys_br_cls('br-eth'), @@ -1162,8 +1168,10 @@ class TestOvsNeutronAgent(object): mock.call.phys_br.setup_default_table(), mock.call.int_br.delete_port('int-br-eth'), mock.call.phys_br.delete_port('phy-br-eth'), + mock.call.int_br.get_port_ofport('int-br-eth'), mock.call.int_br.add_patch_port('int-br-eth', constants.NONEXISTENT_PEER), + mock.call.phys_br.get_port_ofport('phy-br-eth'), mock.call.phys_br.add_patch_port('phy-br-eth', constants.NONEXISTENT_PEER), mock.call.int_br.drop_port(in_port='int_ofport'), diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index 4111551b3aa..bae6e001400 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -139,6 +139,8 @@ class TunnelTest(object): self.mock_int_bridge.add_port.return_value = self.MAP_TUN_INT_OFPORT self.mock_int_bridge.add_patch_port.side_effect = ( lambda tap, peer: self.ovs_int_ofports[tap]) + self.mock_int_bridge.get_port_ofport.return_value = ( + ovs_lib.INVALID_OFPORT) self.mock_int_bridge.get_vif_ports.return_value = [] self.mock_int_bridge.get_ports_attributes.return_value = [] self.mock_int_bridge.db_get_val.return_value = {} @@ -149,6 +151,8 @@ class TunnelTest(object): self.MAP_TUN_PHY_OFPORT) self.mock_map_tun_bridge.add_patch_port.return_value = ( self.MAP_TUN_PHY_OFPORT) + self.mock_map_tun_bridge.get_port_ofport.return_value = ( + ovs_lib.INVALID_OFPORT) self.mock_tun_bridge = self.ovs_bridges[self.TUN_BRIDGE] self.mock_tun_bridge.add_port.return_value = self.INT_OFPORT @@ -202,11 +206,14 @@ class TunnelTest(object): mock.call.create(), mock.call.setup_controllers(mock.ANY), mock.call.setup_default_table(), + mock.call.get_port_ofport('phy-%s' % self.MAP_TUN_BRIDGE), mock.call.add_patch_port('phy-%s' % self.MAP_TUN_BRIDGE, - constants.NONEXISTENT_PEER), ] + constants.NONEXISTENT_PEER), + ] self.mock_int_bridge_expected += [ mock.call.db_get_val('Interface', 'int-%s' % self.MAP_TUN_BRIDGE, 'type'), + mock.call.get_port_ofport('int-%s' % self.MAP_TUN_BRIDGE), mock.call.add_patch_port('int-%s' % self.MAP_TUN_BRIDGE, constants.NONEXISTENT_PEER), ]