l2-population : send flooding entries when the last port goes down
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
This commit is contained in:
parent
ee0788b9b3
commit
e2c1bcfc94
@ -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(
|
||||
|
@ -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,12 +385,46 @@ 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 port2:
|
||||
p2 = port2['port']
|
||||
device2 = 'tap' + p2['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()
|
||||
@ -392,14 +432,24 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
|
||||
agent_id=HOST,
|
||||
device=device)
|
||||
|
||||
p1_ips = [p['ip_address'] for p in p1['fixed_ips']]
|
||||
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=device1)
|
||||
|
||||
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,12 +458,14 @@ 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):
|
||||
with self.port(subnet=subnet,
|
||||
arg_list=(portbindings.HOST_ID,),
|
||||
**host_arg) as port:
|
||||
|
Loading…
Reference in New Issue
Block a user