]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
l2-population : send flooding entries when the last port goes down
authormathieu-rohon <mathieu.rohon@gmail.com>
Thu, 20 Feb 2014 09:39:43 +0000 (10:39 +0100)
committermathieu-rohon <mathieu.rohon@gmail.com>
Tue, 25 Feb 2014 10:11:23 +0000 (11:11 +0100)
Delete port used to call update_port_down to calculate
its fdb entries during delete_port_precommit. But during
the pre-commit, the port is still up, so update_port_down
acts as if there was still one port on the agent, and
doesn't add flooding entry in its fdb_entries.

Closes bug #1282141

Change-Id: Icedd02f33d999200505950beb9169ae3634e551b

neutron/plugins/ml2/drivers/l2pop/mech_driver.py
neutron/tests/unit/ml2/drivers/test_l2population.py

index a22df7b40d9626ce097d161b9427856d053d3eb7..df9bcbb57a13bad367f507ed8e7c977d5f59b88e 100644 (file)
@@ -43,7 +43,11 @@ class L2populationMechanismDriver(api.MechanismDriver,
                  ip['ip_address']] for ip in port['fixed_ips']]
 
     def delete_port_precommit(self, context):
-        self.remove_fdb_entries = self._update_port_down(context)
+        # TODO(matrohon): revisit once the original bound segment will be
+        # available in delete_port_postcommit. in delete_port_postcommit
+        # agent_active_ports will be equal to 0, and the _update_port_down
+        # won't need agent_active_ports_count_for_flooding anymore
+        self.remove_fdb_entries = self._update_port_down(context, 1)
 
     def delete_port_postcommit(self, context):
         l2pop_rpc.L2populationAgentNotify.remove_fdb_entries(
@@ -192,7 +196,8 @@ class L2populationMechanismDriver(api.MechanismDriver,
         l2pop_rpc.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx,
                                                           other_fdb_entries)
 
-    def _update_port_down(self, context):
+    def _update_port_down(self, context,
+                          agent_active_ports_count_for_flooding=0):
         port_context = context.current
         port_infos = self._get_port_infos(context, port_context)
         if not port_infos:
@@ -211,7 +216,7 @@ class L2populationMechanismDriver(api.MechanismDriver,
                               'network_type': segment['network_type'],
                               'ports': {agent_ip: []}}}
 
-        if agent_active_ports == 1:
+        if agent_active_ports == agent_active_ports_count_for_flooding:
             # Agent is removing its last activated port in this network,
             # other agents needs to be notified to delete their flooding entry.
             other_fdb_entries[network_id]['ports'][agent_ip].append(
index c02cd6b2770cd5bcd3a17233ad5f3a046935f6af..352405ad0c90fea99def7b9b36667c7c31d28d2f 100644 (file)
@@ -332,37 +332,43 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                 mock.ANY, expected2,
                                 topic=self.fanout_topic)
 
-    def test_fdb_remove_called_from_rpc(self):
+    def test_update_port_down(self):
         self._register_ml2_agents()
 
         with self.subnet(network=self._network) as subnet:
             host_arg = {portbindings.HOST_ID: HOST}
             with self.port(subnet=subnet,
                            arg_list=(portbindings.HOST_ID,),
-                           **host_arg):
+                           **host_arg) as port1:
                 with self.port(subnet=subnet,
                                arg_list=(portbindings.HOST_ID,),
-                               **host_arg) as port:
-                    p1 = port['port']
-
-                    device = 'tap' + p1['id']
+                               **host_arg) as port2:
+                    p2 = port2['port']
+                    device2 = 'tap' + p2['id']
 
                     self.mock_fanout.reset_mock()
                     self.callbacks.update_device_up(self.adminContext,
                                                     agent_id=HOST,
-                                                    device=device)
+                                                    device=device2)
+
+                    p1 = port1['port']
+                    device1 = 'tap' + p1['id']
 
+                    self.callbacks.update_device_up(self.adminContext,
+                                                    agent_id=HOST,
+                                                    device=device1)
+                    self.mock_fanout.reset_mock()
                     self.callbacks.update_device_down(self.adminContext,
                                                       agent_id=HOST,
-                                                      device=device)
+                                                      device=device2)
 
-                    p1_ips = [p['ip_address'] for p in p1['fixed_ips']]
+                    p2_ips = [p['ip_address'] for p in p2['fixed_ips']]
                     expected = {'args':
                                 {'fdb_entries':
-                                 {p1['network_id']:
+                                 {p2['network_id']:
                                   {'ports':
-                                   {'20.0.0.1': [[p1['mac_address'],
-                                                  p1_ips[0]]]},
+                                   {'20.0.0.1': [[p2['mac_address'],
+                                                  p2_ips[0]]]},
                                    'network_type': 'vxlan',
                                    'segment_id': 1}}},
                                 'namespace': None,
@@ -371,7 +377,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                     self.mock_fanout.assert_called_with(
                         mock.ANY, expected, topic=self.fanout_topic)
 
-    def test_fdb_remove_called(self):
+    def test_update_port_down_last_port_up(self):
         self._register_ml2_agents()
 
         with self.subnet(network=self._network) as subnet:
@@ -379,27 +385,71 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
             with self.port(subnet=subnet,
                            arg_list=(portbindings.HOST_ID,),
                            **host_arg):
-
                 with self.port(subnet=subnet,
                                arg_list=(portbindings.HOST_ID,),
-                               **host_arg) as port:
-                    p1 = port['port']
+                               **host_arg) as port2:
+                    p2 = port2['port']
+                    device2 = 'tap' + p2['id']
 
-                    device = 'tap' + p1['id']
+                    self.mock_fanout.reset_mock()
+                    self.callbacks.update_device_up(self.adminContext,
+                                                    agent_id=HOST,
+                                                    device=device2)
+
+                    self.callbacks.update_device_down(self.adminContext,
+                                                      agent_id=HOST,
+                                                      device=device2)
+
+                    p2_ips = [p['ip_address'] for p in p2['fixed_ips']]
+                    expected = {'args':
+                                {'fdb_entries':
+                                 {p2['network_id']:
+                                  {'ports':
+                                   {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                                 [p2['mac_address'],
+                                                  p2_ips[0]]]},
+                                   'network_type': 'vxlan',
+                                   'segment_id': 1}}},
+                                'namespace': None,
+                                'method': 'remove_fdb_entries'}
+
+                    self.mock_fanout.assert_called_with(
+                        mock.ANY, expected, topic=self.fanout_topic)
+
+    def test_delete_port(self):
+        self._register_ml2_agents()
+
+        with self.subnet(network=self._network) as subnet:
+            host_arg = {portbindings.HOST_ID: HOST}
+            with self.port(subnet=subnet,
+                           arg_list=(portbindings.HOST_ID,),
+                           **host_arg) as port:
+                p1 = port['port']
+                device = 'tap' + p1['id']
+
+                self.mock_fanout.reset_mock()
+                self.callbacks.update_device_up(self.adminContext,
+                                                agent_id=HOST,
+                                                device=device)
+
+                with self.port(subnet=subnet,
+                               arg_list=(portbindings.HOST_ID,),
+                               **host_arg) as port2:
+                    p2 = port2['port']
+                    device1 = 'tap' + p2['id']
 
                     self.mock_fanout.reset_mock()
                     self.callbacks.update_device_up(self.adminContext,
                                                     agent_id=HOST,
-                                                    device=device)
+                                                    device=device1)
 
-                p1_ips = [p['ip_address'] for p in p1['fixed_ips']]
+                p2_ips = [p['ip_address'] for p in p2['fixed_ips']]
                 expected = {'args':
                             {'fdb_entries':
-                             {p1['network_id']:
+                             {p2['network_id']:
                               {'ports':
-                               {'20.0.0.1': [constants.FLOODING_ENTRY,
-                                             [p1['mac_address'],
-                                              p1_ips[0]]]},
+                               {'20.0.0.1': [[p2['mac_address'],
+                                              p2_ips[0]]]},
                                'network_type': 'vxlan',
                                'segment_id': 1}}},
                             'namespace': None,
@@ -408,38 +458,40 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                 self.mock_fanout.assert_any_call(
                     mock.ANY, expected, topic=self.fanout_topic)
 
-    def test_fdb_remove_called_last_port(self):
+    def test_delete_port_last_port_up(self):
         self._register_ml2_agents()
 
         with self.subnet(network=self._network) as subnet:
             host_arg = {portbindings.HOST_ID: HOST}
-
             with self.port(subnet=subnet,
                            arg_list=(portbindings.HOST_ID,),
-                           **host_arg) as port:
-                p1 = port['port']
+                           **host_arg):
+                with self.port(subnet=subnet,
+                               arg_list=(portbindings.HOST_ID,),
+                               **host_arg) as port:
+                    p1 = port['port']
 
-                device = 'tap' + p1['id']
+                    device = 'tap' + p1['id']
 
-                self.callbacks.update_device_up(self.adminContext,
-                                                agent_id=HOST,
-                                                device=device)
+                    self.callbacks.update_device_up(self.adminContext,
+                                                    agent_id=HOST,
+                                                    device=device)
 
-            p1_ips = [p['ip_address'] for p in p1['fixed_ips']]
-            expected = {'args':
-                        {'fdb_entries':
-                         {p1['network_id']:
-                          {'ports':
-                           {'20.0.0.1': [constants.FLOODING_ENTRY,
-                                         [p1['mac_address'],
-                                          p1_ips[0]]]},
-                           'network_type': 'vxlan',
-                           'segment_id': 1}}},
-                        'namespace': None,
-                        'method': 'remove_fdb_entries'}
-
-            self.mock_fanout.assert_any_call(
-                mock.ANY, expected, topic=self.fanout_topic)
+                p1_ips = [p['ip_address'] for p in p1['fixed_ips']]
+                expected = {'args':
+                            {'fdb_entries':
+                             {p1['network_id']:
+                              {'ports':
+                               {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                             [p1['mac_address'],
+                                              p1_ips[0]]]},
+                               'network_type': 'vxlan',
+                               'segment_id': 1}}},
+                            'namespace': None,
+                            'method': 'remove_fdb_entries'}
+
+                self.mock_fanout.assert_any_call(
+                    mock.ANY, expected, topic=self.fanout_topic)
 
     def test_fixed_ips_changed(self):
         self._register_ml2_agents()