Merge "Remove fdb entries for ha router interfaces when going DOWN" into stable/queens

This commit is contained in:
Zuul 2018-08-29 11:42:26 +00:00 committed by Gerrit Code Review
commit 96a957a5dc
2 changed files with 60 additions and 6 deletions

View File

@ -52,6 +52,14 @@ class L2populationMechanismDriver(api.MechanismDriver):
ip_address=ip['ip_address'])
for ip in port['fixed_ips']]
def _remove_flooding(self, fdb_entries):
for network_fdb in fdb_entries.values():
for agent_fdb in network_fdb.get('ports', {}).values():
try:
agent_fdb.remove(const.FLOODING_ENTRY)
except ValueError:
pass
def check_vlan_transparency(self, context):
"""L2population driver vlan transparency support."""
return True
@ -255,11 +263,15 @@ class L2populationMechanismDriver(api.MechanismDriver):
l3plugin, "list_router_ids_on_host", None):
admin_context = n_context.get_admin_context()
port_context = context._plugin_context
if l3plugin.list_router_ids_on_host(
admin_context, agent_host, [port['device_id']]):
return
fdb_entries = self._get_agent_fdb(
port_context, context.bottom_bound_segment, port, agent_host)
port_context, context.bottom_bound_segment, port, agent_host,
include_ha_router_ports=True)
if (fdb_entries and
l3plugin.list_router_ids_on_host(
admin_context, agent_host, [port['device_id']])):
# NOTE(slaweq): in case this is HA router, remove unicast
# entries to this port but don't remove flood entry
self._remove_flooding(fdb_entries)
self.L2populationAgentNotify.remove_fdb_entries(
self.rpc_ctx, fdb_entries)
@ -310,7 +322,8 @@ class L2populationMechanismDriver(api.MechanismDriver):
self.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx,
other_fdb_entries)
def _get_agent_fdb(self, context, segment, port, agent_host):
def _get_agent_fdb(self, context, segment, port, agent_host,
include_ha_router_ports=False):
if not agent_host:
return
@ -338,9 +351,10 @@ class L2populationMechanismDriver(api.MechanismDriver):
const.FLOODING_ENTRY)
# Notify other agents to remove fdb rules for current port
if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE and
(include_ha_router_ports or
not l3_hamode_db.is_ha_router_port(context,
port['device_owner'],
port['device_id'])):
port['device_id']))):
fdb_entries = self._get_port_fdb_entries(port)
other_fdb_entries[network_id]['ports'][agent_ip] += fdb_entries

View File

@ -57,6 +57,7 @@ TEST_ROUTER_ID = 'router_id'
NOTIFIER = 'neutron.plugins.ml2.rpc.AgentNotifierApi'
DEVICE_OWNER_COMPUTE = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'fake'
DEVICE_OWNER_ROUTER_HA_INTF = constants.DEVICE_OWNER_ROUTER_HA_INTF + 'fake'
class FakeL3PluginWithAgents(common_db_mixin.CommonDbMixin,
@ -858,6 +859,45 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
self.mock_fanout.assert_called_with(
mock.ANY, 'remove_fdb_entries', expected)
def test_update_port_down_ha_router_port(self):
router = self._create_ha_router()
directory.add_plugin(plugin_constants.L3, self.plugin)
with self.subnet(network=self._network, enable_dhcp=False) as snet:
subnet = snet['subnet']
router_port = self._add_router_interface(subnet, router, HOST)
router_port_device = 'tap' + router_port['id']
host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True}
with self.port(subnet=snet,
device_owner=DEVICE_OWNER_COMPUTE,
arg_list=(portbindings.HOST_ID,),
**host_arg) as port1:
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=router_port_device,
host=HOST)
router_port_ips = [
p['ip_address'] for p in router_port['fixed_ips']]
expected = {
router_port['network_id']: {
'ports': {
'20.0.0.1': [
l2pop_rpc.PortInfo(router_port['mac_address'],
router_port_ips[0])]},
'network_type': 'vxlan',
'segment_id': 1}}
self.mock_fanout.assert_called_with(
mock.ANY, 'remove_fdb_entries', expected)
def test_delete_port(self):
self._register_ml2_agents()