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 614e41b4a8c..1b52efd187d 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1117,6 +1117,16 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, self.available_local_vlans.add(lvm.vlan) + def _set_port_vlan(self, port, vlan): + ovsdb = self.int_br.ovsdb + with self.int_br.ovsdb.transaction() as txn: + # When adding the port's tag, + # also clear port's vlan_mode and trunks, + # which were set to make sure all packets are dropped. + txn.add(ovsdb.db_set('Port', port.port_name, ('tag', vlan))) + txn.add(ovsdb.db_clear('Port', port.port_name, 'vlan_mode')) + txn.add(ovsdb.db_clear('Port', port.port_name, 'trunks')) + def port_bound(self, port, net_uuid, network_type, physical_network, segmentation_id, fixed_ips, device_owner, @@ -1157,10 +1167,12 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, vlan_mapping = {'net_uuid': net_uuid, 'network_type': network_type, - 'physical_network': str(physical_network)} + 'physical_network': str(physical_network), + 'tag': str(lvm.vlan)} if segmentation_id is not None: vlan_mapping['segmentation_id'] = str(segmentation_id) port_other_config.update(vlan_mapping) + self._set_port_vlan(port, lvm.vlan) self.int_br.set_db_attribute("Port", port.port_name, "other_config", port_other_config) return True 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 e087a57806a..e11f08abda4 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 @@ -179,18 +179,21 @@ class TestOvsNeutronAgent(object): self.agent.vlan_manager.add( net_uuid, old_local_vlan, None, None, None) with mock.patch.object(self.agent, 'int_br', autospec=True) as int_br: - int_br.db_get_val.return_value = db_get_val - int_br.set_db_attribute.return_value = True - needs_binding = self.agent.port_bound( - port, net_uuid, 'local', None, None, - fixed_ips, DEVICE_OWNER_COMPUTE, False) + with mock.patch.object(self.agent, '_set_port_vlan') as set_vlan: + int_br.db_get_val.return_value = db_get_val + int_br.set_db_attribute.return_value = True + needs_binding = self.agent.port_bound( + port, net_uuid, 'local', None, None, + fixed_ips, DEVICE_OWNER_COMPUTE, False) if db_get_val is None: int_br.assert_not_called() self.assertFalse(needs_binding) else: vlan_mapping = {'net_uuid': net_uuid, 'network_type': 'local', - 'physical_network': 'None'} + 'physical_network': 'None', + 'tag': str(new_local_vlan)} + set_vlan.assert_called_once_with(port, new_local_vlan) int_br.set_db_attribute.assert_called_once_with( "Port", mock.ANY, "other_config", vlan_mapping) self.assertTrue(needs_binding) @@ -3102,6 +3105,7 @@ class TestOvsDvrNeutronAgent(object): self.agent = self.mod_agent.OVSNeutronAgent(self._bridge_classes(), ext_manager, cfg.CONF) self.agent.tun_br = self.br_tun_cls(br_name='br-tun') + self.agent._set_port_vlan = mock.Mock() self.agent.sg_agent = mock.Mock() def _setup_for_dvr_test(self): 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 0e3b0c0d89b..0bce429767b 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 @@ -503,7 +503,8 @@ class TunnelTest(object): vlan_mapping = {'segmentation_id': str(LS_ID), 'physical_network': 'None', 'net_uuid': NET_UUID, - 'network_type': 'gre'} + 'network_type': 'gre', + 'tag': str(LV_ID)} self.mock_int_bridge_expected += [ mock.call.db_get_val('Port', 'port', 'other_config'), mock.call.set_db_attribute('Port', VIF_PORT.port_name, @@ -514,9 +515,11 @@ class TunnelTest(object): a.vlan_manager.add(NET_UUID, *self.LVM_DATA) a.local_dvr_map = {} self.ovs_bridges[self.INT_BRIDGE].db_get_val.return_value = {} - a.port_bound(VIF_PORT, NET_UUID, 'gre', None, LS_ID, - FIXED_IPS, VM_DEVICE_OWNER, False) - self._verify_mock_calls() + with mock.patch.object(a, "_set_port_vlan") as set_vlan: + a.port_bound(VIF_PORT, NET_UUID, 'gre', None, LS_ID, + FIXED_IPS, VM_DEVICE_OWNER, False) + self._verify_mock_calls() + set_vlan.assert_called_once_with(VIF_PORT, LV_ID) def test_port_unbound(self): with mock.patch.object(self.mod_agent.OVSNeutronAgent,