From c1827a074654d2e8d07e93945fa605ad3b6c18fb Mon Sep 17 00:00:00 2001 From: fumihiko kakuma Date: Mon, 14 Apr 2014 14:17:31 +0900 Subject: [PATCH] OFAgent: Fixing lost vlan ids on interfaces Port the following patch to OFAgent. commit: 60cb0911712ad11688b4d09e5c01ac39c49f5aea https://review.openstack.org/#/c/66375/ Closes-Bug: #1309286 Change-Id: I04f99ef7928cd07959b29eb64b5744df397979b8 --- .../ofagent/agent/ofa_neutron_agent.py | 27 ++++++++++++++++ .../unit/ofagent/test_ofa_neutron_agent.py | 31 +++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/neutron/plugins/ofagent/agent/ofa_neutron_agent.py b/neutron/plugins/ofagent/agent/ofa_neutron_agent.py index 8eeb7577b6..29d4676b96 100644 --- a/neutron/plugins/ofagent/agent/ofa_neutron_agent.py +++ b/neutron/plugins/ofagent/agent/ofa_neutron_agent.py @@ -956,6 +956,9 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin): cur_ports = self.int_br.get_vif_port_set() self.int_br_device_count = len(cur_ports) port_info = {'current': cur_ports} + if updated_ports is None: + updated_ports = set() + updated_ports.update(self._find_lost_vlan_port(registered_ports)) if updated_ports: # Some updated ports might have been removed in the # meanwhile, and therefore should not be processed. @@ -974,6 +977,30 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin): port_info['removed'] = registered_ports - cur_ports return port_info + def _find_lost_vlan_port(self, registered_ports): + """Return ports which have lost their vlan tag. + + The returned value is a set of port ids of the ports concerned by a + vlan tag loss. + """ + port_tags = self.int_br.get_port_tag_dict() + changed_ports = set() + for lvm in self.local_vlan_map.values(): + for port in registered_ports: + if ( + port in lvm.vif_ports + and lvm.vif_ports[port].port_name in port_tags + and port_tags[lvm.vif_ports[port].port_name] != lvm.vlan + ): + LOG.info( + _("Port '%(port_name)s' has lost " + "its vlan tag '%(vlan_tag)d'!"), + {'port_name': lvm.vif_ports[port].port_name, + 'vlan_tag': lvm.vlan} + ) + changed_ports.add(port) + return changed_ports + def update_ancillary_ports(self, registered_ports): ports = set() for bridge in self.ancillary_brs: diff --git a/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py b/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py index 4b2f5556ac..6ef8be7f58 100644 --- a/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py +++ b/neutron/tests/unit/ofagent/test_ofa_neutron_agent.py @@ -24,6 +24,7 @@ from oslo.config import cfg import testtools from neutron.agent.linux import ip_lib +from neutron.agent.linux import ovs_lib from neutron.agent.linux import utils from neutron.openstack.common import importutils from neutron.plugins.common import constants as p_const @@ -310,9 +311,14 @@ class TestOFANeutronAgent(OFAAgentTestCase): self._test_port_dead(self.mod_agent.DEAD_VLAN_TAG) def mock_scan_ports(self, vif_port_set=None, registered_ports=None, - updated_ports=None): - with mock.patch.object(self.agent.int_br, 'get_vif_port_set', - return_value=vif_port_set): + updated_ports=None, port_tags_dict=None): + port_tags_dict = port_tags_dict or {} + with contextlib.nested( + mock.patch.object(self.agent.int_br, 'get_vif_port_set', + return_value=vif_port_set), + mock.patch.object(self.agent.int_br, 'get_port_tag_dict', + return_value=port_tags_dict) + ): return self.agent.scan_ports(registered_ports, updated_ports) def test_scan_ports_returns_current_only_for_unchanged_ports(self): @@ -365,6 +371,25 @@ class TestOFANeutronAgent(OFAAgentTestCase): updated_ports) self.assertEqual(expected, actual) + def test_update_ports_returns_lost_vlan_port(self): + br = self.mod_agent.OVSBridge('br-int', 'fake_helper', self.ryuapp) + mac = "ca:fe:de:ad:be:ef" + port = ovs_lib.VifPort(1, 1, 1, mac, br) + lvm = self.mod_agent.LocalVLANMapping( + 1, '1', None, 1, {port.vif_id: port}) + local_vlan_map = {'1': lvm} + vif_port_set = set([1, 3]) + registered_ports = set([1, 2]) + port_tags_dict = {1: []} + expected = dict( + added=set([3]), current=vif_port_set, + removed=set([2]), updated=set([1]) + ) + with mock.patch.dict(self.agent.local_vlan_map, local_vlan_map): + actual = self.mock_scan_ports( + vif_port_set, registered_ports, port_tags_dict=port_tags_dict) + self.assertEqual(expected, actual) + def test_treat_devices_added_returns_true_for_missing_device(self): with mock.patch.object(self.agent.plugin_rpc, 'get_device_details', side_effect=Exception()):