Skip to content

Commit c5ff5ba

Browse files
luis5tbMoteHue
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
1 parent b9067eb commit c5ff5ba

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
@@ -1048,7 +1048,7 @@ def get_workers(self):
10481048
# See doc/source/design/ovn_worker.rst for more details.
10491049
return [worker.MaintenanceWorker()]
10501050

1051-
def _update_dnat_entry_if_needed(self, port_id):
1051+
def _update_dnat_entry_if_needed(self, port_id, up=True):
10521052
"""Update DNAT entry if using distributed floating ips."""
10531053
if not self.nb_ovn:
10541054
self.nb_ovn = self._ovn_client._nb_idl
@@ -1070,13 +1070,14 @@ def _update_dnat_entry_if_needed(self, port_id):
10701070
nat['external_mac']})).execute()
10711071

10721072
if ovn_conf.is_ovn_distributed_floating_ip():
1073-
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1074-
if mac and nat['external_mac'] != mac:
1075-
LOG.debug("Setting external_mac of port %s to %s",
1076-
port_id, mac)
1077-
self.nb_ovn.db_set(
1078-
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
1079-
check_error=True)
1073+
if up:
1074+
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1075+
if mac and nat['external_mac'] != mac:
1076+
LOG.debug("Setting external_mac of port %s to %s",
1077+
port_id, mac)
1078+
self.nb_ovn.db_set(
1079+
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
1080+
check_error=True)
10801081
else:
10811082
if nat['external_mac']:
10821083
LOG.debug("Clearing up external_mac of port %s", port_id)
@@ -1139,7 +1140,7 @@ def set_port_status_down(self, port_id):
11391140
# to prevent another entity from bypassing the block with its own
11401141
# port status update.
11411142
LOG.info("OVN reports status down for port: %s", port_id)
1142-
self._update_dnat_entry_if_needed(port_id)
1143+
self._update_dnat_entry_if_needed(port_id, False)
11431144
admin_context = n_context.get_admin_context()
11441145
try:
11451146
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
@@ -1112,7 +1112,7 @@ def _test_set_port_status_down(self, is_compute_port=False):
11121112
resources.PORT,
11131113
provisioning_blocks.L2_AGENT_ENTITY
11141114
)
1115-
ude.assert_called_once_with(port1['port']['id'])
1115+
ude.assert_called_once_with(port1['port']['id'], False)
11161116

11171117
# If the port does NOT bellong to compute, do not notify Nova
11181118
# about it's status changes
@@ -1164,7 +1164,7 @@ def test_set_port_status_concurrent_delete(self):
11641164
resources.PORT,
11651165
provisioning_blocks.L2_AGENT_ENTITY
11661166
)
1167-
ude.assert_called_once_with(port1['port']['id'])
1167+
ude.assert_called_once_with(port1['port']['id'], False)
11681168

11691169
def test_bind_port_unsupported_vnic_type(self):
11701170
fake_port = fakes.FakePort.create_one_port(
@@ -2358,7 +2358,7 @@ def test_agent_with_nb_cfg_timestamp_not_timeout(self):
23582358
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
23592359
agent.agent_type, agent.alive))
23602360

2361-
def _test__update_dnat_entry_if_needed(self, dvr=True):
2361+
def _test__update_dnat_entry_if_needed(self, up=True, dvr=True):
23622362
if dvr:
23632363
ovn_conf.cfg.CONF.set_override(
23642364
'enable_distributed_floating_ip', True, group='ovn')
@@ -2374,25 +2374,33 @@ def _test__update_dnat_entry_if_needed(self, dvr=True):
23742374
fake_db_find.execute.return_value = [nat_row]
23752375
self.nb_ovn.db_find.return_value = fake_db_find
23762376

2377-
self.mech_driver._update_dnat_entry_if_needed(port_id)
2377+
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
23782378

2379-
if dvr:
2379+
if up and dvr:
23802380
# Assert that we are setting the external_mac in the NAT table
23812381
self.nb_ovn.db_set.assert_called_once_with(
23822382
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
2383-
self.nb_ovn.db_clear.assert_not_called()
23842383
else:
2385-
self.nb_ovn.db_set.assert_not_called()
2386-
# Assert that we are cleaning the external_mac from the NAT table
2387-
self.nb_ovn.db_clear.assert_called_once_with(
2388-
'NAT', fake_nat_uuid, 'external_mac')
2384+
if dvr:
2385+
self.nb_ovn.db_set.assert_not_called()
2386+
else:
2387+
# Assert that we are cleaning the external_mac from the NAT
2388+
# table
2389+
self.nb_ovn.db_clear.assert_called_once_with(
2390+
'NAT', fake_nat_uuid, 'external_mac')
23892391

2390-
def test__update_dnat_entry_if_needed_dvr(self):
2392+
def test__update_dnat_entry_if_needed_up_dvr(self):
23912393
self._test__update_dnat_entry_if_needed()
23922394

2393-
def test__update_dnat_entry_if_needed_no_dvr(self):
2395+
def test__update_dnat_entry_if_needed_up_no_dvr(self):
23942396
self._test__update_dnat_entry_if_needed(dvr=False)
23952397

2398+
def test__update_dnat_entry_if_needed_down_dvr(self):
2399+
self._test__update_dnat_entry_if_needed(up=False)
2400+
2401+
def test__update_dnat_entry_if_needed_down_no_dvr(self):
2402+
self._test__update_dnat_entry_if_needed(up=False, dvr=False)
2403+
23962404
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
23972405
'ovn_client.OVNClient._get_router_ports')
23982406
def _test_update_network_fragmentation(self, new_mtu, expected_opts, grps):

0 commit comments

Comments
 (0)