Skip to content

Commit fb99b7b

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 2b611b7 commit fb99b7b

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

1064-
def _update_dnat_entry_if_needed(self, port_id):
1064+
def _update_dnat_entry_if_needed(self, port_id, up=True):
10651065
"""Update DNAT entry if using distributed floating ips."""
10661066
if not self.nb_ovn:
10671067
self.nb_ovn = self._ovn_client._nb_idl
@@ -1083,13 +1083,14 @@ def _update_dnat_entry_if_needed(self, port_id):
10831083
nat['external_mac']})).execute()
10841084

10851085
if ovn_conf.is_ovn_distributed_floating_ip():
1086-
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1087-
if mac and nat['external_mac'] != mac:
1088-
LOG.debug("Setting external_mac of port %s to %s",
1089-
port_id, mac)
1090-
self.nb_ovn.db_set(
1091-
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
1092-
check_error=True)
1086+
if up:
1087+
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1088+
if mac and nat['external_mac'] != mac:
1089+
LOG.debug("Setting external_mac of port %s to %s",
1090+
port_id, mac)
1091+
self.nb_ovn.db_set(
1092+
'NAT', nat['_uuid'], ('external_mac', mac)).execute(
1093+
check_error=True)
10931094
else:
10941095
if nat['external_mac']:
10951096
LOG.debug("Clearing up external_mac of port %s", port_id)
@@ -1152,7 +1153,7 @@ def set_port_status_down(self, port_id):
11521153
# to prevent another entity from bypassing the block with its own
11531154
# port status update.
11541155
LOG.info("OVN reports status down for port: %s", port_id)
1155-
self._update_dnat_entry_if_needed(port_id)
1156+
self._update_dnat_entry_if_needed(port_id, False)
11561157
admin_context = n_context.get_admin_context()
11571158
try:
11581159
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(
@@ -2382,7 +2382,7 @@ def test_agent_with_nb_cfg_timestamp_not_timeout(self):
23822382
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
23832383
agent.agent_type, agent.alive))
23842384

2385-
def _test__update_dnat_entry_if_needed(self, dvr=True):
2385+
def _test__update_dnat_entry_if_needed(self, up=True, dvr=True):
23862386
if dvr:
23872387
ovn_conf.cfg.CONF.set_override(
23882388
'enable_distributed_floating_ip', True, group='ovn')
@@ -2398,25 +2398,33 @@ def _test__update_dnat_entry_if_needed(self, dvr=True):
23982398
fake_db_find.execute.return_value = [nat_row]
23992399
self.nb_ovn.db_find.return_value = fake_db_find
24002400

2401-
self.mech_driver._update_dnat_entry_if_needed(port_id)
2401+
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
24022402

2403-
if dvr:
2403+
if up and dvr:
24042404
# Assert that we are setting the external_mac in the NAT table
24052405
self.nb_ovn.db_set.assert_called_once_with(
24062406
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
2407-
self.nb_ovn.db_clear.assert_not_called()
24082407
else:
2409-
self.nb_ovn.db_set.assert_not_called()
2410-
# Assert that we are cleaning the external_mac from the NAT table
2411-
self.nb_ovn.db_clear.assert_called_once_with(
2412-
'NAT', fake_nat_uuid, 'external_mac')
2408+
if dvr:
2409+
self.nb_ovn.db_set.assert_not_called()
2410+
else:
2411+
# Assert that we are cleaning the external_mac from the NAT
2412+
# table
2413+
self.nb_ovn.db_clear.assert_called_once_with(
2414+
'NAT', fake_nat_uuid, 'external_mac')
24132415

2414-
def test__update_dnat_entry_if_needed_dvr(self):
2416+
def test__update_dnat_entry_if_needed_up_dvr(self):
24152417
self._test__update_dnat_entry_if_needed()
24162418

2417-
def test__update_dnat_entry_if_needed_no_dvr(self):
2419+
def test__update_dnat_entry_if_needed_up_no_dvr(self):
24182420
self._test__update_dnat_entry_if_needed(dvr=False)
24192421

2422+
def test__update_dnat_entry_if_needed_down_dvr(self):
2423+
self._test__update_dnat_entry_if_needed(up=False)
2424+
2425+
def test__update_dnat_entry_if_needed_down_no_dvr(self):
2426+
self._test__update_dnat_entry_if_needed(up=False, dvr=False)
2427+
24202428
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
24212429
'ovn_client.OVNClient._get_router_ports')
24222430
def _test_update_network_fragmentation(self, new_mtu, expected_opts, grps):

0 commit comments

Comments
 (0)