File 0001-l2-pop-check-for-more-than-1-first-active-port-on-a-.patch of Package openstack-neutron
From 1ba5e6964b5eadd660f2f333e774ce174c4e6f06 Mon Sep 17 00:00:00 2001
From: Oleg Bondarev <obondarev@mirantis.com>
Date: Thu, 30 Aug 2018 12:25:07 +0400
Subject: [PATCH] l2 pop: check for more than 1 first active port on a node
With high concurrency more than 1 port may be activated on an
OVS agent at the same time (like VM port + a DVR port),
so the patch mitigates the condition by checking for 1 or 2
first active ports.
Given that the condition also contains "or self.agent_restarted(context)"
which makes it True first 180 sec (by default) after agent restart,
I believe the downside of changing 1 to 2 should be negligible.
Please see bug for more details on the issue.
Closes-Bug: #1789846
Change-Id: Ieab0186cbe05185d47bbf5a31141563cf923f66f
(cherry picked from commit b32db30874a7729c4e9209cfc18e106a7e9fc697)
---
.../plugins/ml2/drivers/l2pop/mech_driver.py | 9 ++--
.../ml2/drivers/l2pop/test_mech_driver.py | 54 +++++++++++++++++++
2 files changed, 60 insertions(+), 3 deletions(-)
Index: neutron-9.4.2.dev21/neutron/plugins/ml2/drivers/l2pop/mech_driver.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/plugins/ml2/drivers/l2pop/mech_driver.py
+++ neutron-9.4.2.dev21/neutron/plugins/ml2/drivers/l2pop/mech_driver.py
@@ -273,9 +273,12 @@ class L2populationMechanismDriver(api.Me
segment, agent_ip, network_id)
other_fdb_ports = other_fdb_entries[network_id]['ports']
- if agent_active_ports == 1 or (l2pop_db.get_agent_uptime(agent) <
- cfg.CONF.l2pop.agent_boot_time):
- # First port activated on current agent in this network,
+ # with high concurrency more than 1 port may be activated on an agent
+ # at the same time (like VM port + a DVR port) so checking for 1 or 2
+ is_first_port = agent_active_ports in (1, 2)
+ if is_first_port or (l2pop_db.get_agent_uptime(agent) <
+ cfg.CONF.l2pop.agent_boot_time):
+ # First port(s) activated on current agent in this network,
# we have to provide it with the whole list of fdb entries
agent_fdb_entries = self._create_agent_fdb(session,
agent,
Index: neutron-9.4.2.dev21/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py
+++ neutron-9.4.2.dev21/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py
@@ -707,6 +707,60 @@ class TestL2PopulationRpcTestCase(test_p
self.mock_fanout.assert_called_with(
mock.ANY, 'add_fdb_entries', expected)
+ def test_update_port_up_two_active_ports(self):
+ '''The test will check that even with 2 active ports on the host,
+ agent will be provided with the whole list of fdb entries. Bug 1789846
+ '''
+ self._register_ml2_agents()
+
+ with self.subnet(network=self._network) as subnet:
+ host_arg = {portbindings.HOST_ID: HOST}
+ # 2 ports on host 1
+ with self.port(subnet=subnet,
+ device_owner=DEVICE_OWNER_COMPUTE,
+ arg_list=(portbindings.HOST_ID,),
+ **host_arg) as port1:
+ with self.port(subnet=subnet,
+ device_owner=DEVICE_OWNER_COMPUTE,
+ arg_list=(portbindings.HOST_ID,),
+ **host_arg) as port2:
+ # 1 port on another host to have fdb entree to update
+ # agent on host 1
+ host_arg = {portbindings.HOST_ID: HOST + '_2'}
+ with self.port(subnet=subnet,
+ device_owner=DEVICE_OWNER_COMPUTE,
+ arg_list=(portbindings.HOST_ID,),
+ **host_arg) as port3:
+ p1 = port1['port']
+ p2 = port2['port']
+ p3 = port3['port']
+
+ # only ACTIVE ports count
+ plugin = directory.get_plugin()
+ p2['status'] = 'ACTIVE'
+ plugin.update_port(self.adminContext, p2['id'], port2)
+ p3['status'] = 'ACTIVE'
+ plugin.update_port(self.adminContext, p3['id'], port3)
+
+ self.mock_cast.reset_mock()
+ p1['status'] = 'ACTIVE'
+ plugin.update_port(self.adminContext, p1['id'], port1)
+
+ # agent on host 1 should be updated with entry from
+ # another host
+ expected = {p3['network_id']:
+ {'ports':
+ {'20.0.0.2': [
+ constants.FLOODING_ENTRY,
+ l2pop_rpc.PortInfo(
+ p3['mac_address'],
+ p3['fixed_ips'][0]['ip_address'])]},
+ 'network_type': 'vxlan',
+ 'segment_id': 1}}
+
+ self.mock_cast.assert_called_once_with(
+ mock.ANY, 'add_fdb_entries', expected, HOST)
+
def test_update_port_down(self):
self._register_ml2_agents()