Skip to content

Commit 15d5db0

Browse files
luis5tbbbezak
authored andcommitted
Ensure ovn loadbalancer FIPs are centralized upon neutron restarts
When neutron server restarts the mac address for NAT entries related to ovn-lb FIPs gets re-added, distributing the traffic that should be centralized and therefore breaking the connectivity. This happens due to the port being down. This patch is ensuring the MAC entry is only being readded in case the port is UP Closes-Bug: #2042938 Change-Id: I6203009750a4e589eeb808f842cb522d61476179 (cherry picked from commit f2a3020)
1 parent 0e38f2a commit 15d5db0

File tree

2 files changed

+30
-21
lines changed

2 files changed

+30
-21
lines changed

neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ def get_workers(self):
10561056
# See doc/source/design/ovn_worker.rst for more details.
10571057
return [worker.MaintenanceWorker()]
10581058

1059-
def _update_dnat_entry_if_needed(self, port_id):
1059+
def _update_dnat_entry_if_needed(self, port_id, up=True):
10601060
"""Update DNAT entry if using distributed floating ips."""
10611061
if not self.nb_ovn:
10621062
self.nb_ovn = self._ovn_client._nb_idl
@@ -1078,13 +1078,14 @@ def _update_dnat_entry_if_needed(self, port_id):
10781078
nat['external_mac']})).execute()
10791079

10801080
if ovn_conf.is_ovn_distributed_floating_ip():
1081-
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1082-
if mac and nat['external_mac'] != mac:
1083-
LOG.debug("Setting external_mac of port %s to %s",
1084-
port_id, mac)
1085-
self.nb_ovn.db_set(
1086-
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
1087-
check_error=True)
1081+
if up:
1082+
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1083+
if mac and nat['external_mac'] != mac:
1084+
LOG.debug("Setting external_mac of port %s to %s",
1085+
port_id, mac)
1086+
self.nb_ovn.db_set(
1087+
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
1088+
check_error=True)
10881089
else:
10891090
if nat['external_mac']:
10901091
LOG.debug("Clearing up external_mac of port %s", port_id)
@@ -1147,7 +1148,7 @@ def set_port_status_down(self, port_id):
11471148
# to prevent another entity from bypassing the block with its own
11481149
# port status update.
11491150
LOG.info("OVN reports status down for port: %s", port_id)
1150-
self._update_dnat_entry_if_needed(port_id)
1151+
self._update_dnat_entry_if_needed(port_id, False)
11511152
admin_context = n_context.get_admin_context()
11521153
try:
11531154
db_port = ml2_db.get_port(admin_context, port_id)

neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ def _test_set_port_status_down(self, is_compute_port=False):
11301130
resources.PORT,
11311131
provisioning_blocks.L2_AGENT_ENTITY
11321132
)
1133-
ude.assert_called_once_with(port1['port']['id'])
1133+
ude.assert_called_once_with(port1['port']['id'], False)
11341134

11351135
# If the port does NOT bellong to compute, do not notify Nova
11361136
# about it's status changes
@@ -1182,7 +1182,7 @@ def test_set_port_status_concurrent_delete(self):
11821182
resources.PORT,
11831183
provisioning_blocks.L2_AGENT_ENTITY
11841184
)
1185-
ude.assert_called_once_with(port1['port']['id'])
1185+
ude.assert_called_once_with(port1['port']['id'], False)
11861186

11871187
def test_bind_port_unsupported_vnic_type(self):
11881188
fake_port = fakes.FakePort.create_one_port(
@@ -2376,7 +2376,7 @@ def test_agent_with_nb_cfg_timestamp_not_timeout(self):
23762376
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
23772377
agent.agent_type, agent.alive))
23782378

2379-
def _test__update_dnat_entry_if_needed(self, dvr=True):
2379+
def _test__update_dnat_entry_if_needed(self, up=True, dvr=True):
23802380
if dvr:
23812381
ovn_conf.cfg.CONF.set_override(
23822382
'enable_distributed_floating_ip', True, group='ovn')
@@ -2392,25 +2392,33 @@ def _test__update_dnat_entry_if_needed(self, dvr=True):
23922392
fake_db_find.execute.return_value = [nat_row]
23932393
self.nb_ovn.db_find.return_value = fake_db_find
23942394

2395-
self.mech_driver._update_dnat_entry_if_needed(port_id)
2395+
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
23962396

2397-
if dvr:
2397+
if up and dvr:
23982398
# Assert that we are setting the external_mac in the NAT table
23992399
self.nb_ovn.db_set.assert_called_once_with(
24002400
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
2401-
self.nb_ovn.db_clear.assert_not_called()
24022401
else:
2403-
self.nb_ovn.db_set.assert_not_called()
2404-
# Assert that we are cleaning the external_mac from the NAT table
2405-
self.nb_ovn.db_clear.assert_called_once_with(
2406-
'NAT', fake_nat_uuid, 'external_mac')
2402+
if dvr:
2403+
self.nb_ovn.db_set.assert_not_called()
2404+
else:
2405+
# Assert that we are cleaning the external_mac from the NAT
2406+
# table
2407+
self.nb_ovn.db_clear.assert_called_once_with(
2408+
'NAT', fake_nat_uuid, 'external_mac')
24072409

2408-
def test__update_dnat_entry_if_needed_dvr(self):
2410+
def test__update_dnat_entry_if_needed_up_dvr(self):
24092411
self._test__update_dnat_entry_if_needed()
24102412

2411-
def test__update_dnat_entry_if_needed_no_dvr(self):
2413+
def test__update_dnat_entry_if_needed_up_no_dvr(self):
24122414
self._test__update_dnat_entry_if_needed(dvr=False)
24132415

2416+
def test__update_dnat_entry_if_needed_down_dvr(self):
2417+
self._test__update_dnat_entry_if_needed(up=False)
2418+
2419+
def test__update_dnat_entry_if_needed_down_no_dvr(self):
2420+
self._test__update_dnat_entry_if_needed(up=False, dvr=False)
2421+
24142422
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
24152423
'ovn_client.OVNClient._get_router_ports')
24162424
def _test_update_network_fragmentation(self, new_mtu, expected_opts, grps):

0 commit comments

Comments
 (0)