Skip to content

Commit b9b819d

Browse files
committed
Ensure traffic is not centralized if DVR is enabled
There is no need to clear the external_mac if DVR is enabled, not even when the port is down. This patch ensures the external_mac is only deleted when DVR is not enabled. Without this patch, if a VM with a floating IP gets deleted, and DVR is enabled, during some time the traffic gets (wrongly) centralized while it should not. And it is also generating more load on the OVN side unnecesarily. Closes-Bug: #2025264 Change-Id: I89db15dd1b629bc963f3b63926391a4a02cbedf7 (cherry picked from commit 0090572)
1 parent b4f7c9d commit b9b819d

File tree

3 files changed

+28
-15
lines changed

3 files changed

+28
-15
lines changed

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

Lines changed: 5 additions & 5 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, up=True):
1051+
def _update_dnat_entry_if_needed(self, port_id):
10521052
"""Update DNAT entry if using distributed floating ips."""
10531053
if not self.nb_ovn:
10541054
self.nb_ovn = self._ovn_client._nb_idl
@@ -1069,9 +1069,9 @@ def _update_dnat_entry_if_needed(self, port_id, up=True):
10691069
{ovn_const.OVN_FIP_EXT_MAC_KEY:
10701070
nat['external_mac']})).execute()
10711071

1072-
if up and ovn_conf.is_ovn_distributed_floating_ip():
1073-
mac = nat['external_ids'][ovn_const.OVN_FIP_EXT_MAC_KEY]
1074-
if nat['external_mac'] != mac:
1072+
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:
10751075
LOG.debug("Setting external_mac of port %s to %s",
10761076
port_id, mac)
10771077
self.nb_ovn.db_set(
@@ -1137,7 +1137,7 @@ def set_port_status_down(self, port_id):
11371137
# to prevent another entity from bypassing the block with its own
11381138
# port status update.
11391139
LOG.info("OVN reports status down for port: %s", port_id)
1140-
self._update_dnat_entry_if_needed(port_id, False)
1140+
self._update_dnat_entry_if_needed(port_id)
11411141
admin_context = n_context.get_admin_context()
11421142
try:
11431143
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: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ def _test_set_port_status_down(self, is_compute_port=False):
11241124
resources.PORT,
11251125
provisioning_blocks.L2_AGENT_ENTITY
11261126
)
1127-
ude.assert_called_once_with(port1['port']['id'], False)
1127+
ude.assert_called_once_with(port1['port']['id'])
11281128

11291129
# If the port does NOT bellong to compute, do not notify Nova
11301130
# about it's status changes
@@ -1174,7 +1174,7 @@ def test_set_port_status_concurrent_delete(self):
11741174
resources.PORT,
11751175
provisioning_blocks.L2_AGENT_ENTITY
11761176
)
1177-
ude.assert_called_once_with(port1['port']['id'], False)
1177+
ude.assert_called_once_with(port1['port']['id'])
11781178

11791179
def test_bind_port_unsupported_vnic_type(self):
11801180
fake_port = fakes.FakePort.create_one_port(
@@ -2368,9 +2368,10 @@ def test_agent_with_nb_cfg_timestamp_not_timeout(self):
23682368
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
23692369
agent.agent_type, agent.alive))
23702370

2371-
def _test__update_dnat_entry_if_needed(self, up=True):
2372-
ovn_conf.cfg.CONF.set_override(
2373-
'enable_distributed_floating_ip', True, group='ovn')
2371+
def _test__update_dnat_entry_if_needed(self, dvr=True):
2372+
if dvr:
2373+
ovn_conf.cfg.CONF.set_override(
2374+
'enable_distributed_floating_ip', True, group='ovn')
23742375
port_id = 'fake-port-id'
23752376
fake_ext_mac_key = 'fake-ext-mac-key'
23762377
fake_nat_uuid = uuidutils.generate_uuid()
@@ -2383,22 +2384,24 @@ def _test__update_dnat_entry_if_needed(self, up=True):
23832384
fake_db_find.execute.return_value = [nat_row]
23842385
self.nb_ovn.db_find.return_value = fake_db_find
23852386

2386-
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
2387+
self.mech_driver._update_dnat_entry_if_needed(port_id)
23872388

2388-
if up:
2389+
if dvr:
23892390
# Assert that we are setting the external_mac in the NAT table
23902391
self.nb_ovn.db_set.assert_called_once_with(
23912392
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
2393+
self.nb_ovn.db_clear.assert_not_called()
23922394
else:
2395+
self.nb_ovn.db_set.assert_not_called()
23932396
# Assert that we are cleaning the external_mac from the NAT table
23942397
self.nb_ovn.db_clear.assert_called_once_with(
23952398
'NAT', fake_nat_uuid, 'external_mac')
23962399

2397-
def test__update_dnat_entry_if_needed_up(self):
2400+
def test__update_dnat_entry_if_needed_dvr(self):
23982401
self._test__update_dnat_entry_if_needed()
23992402

2400-
def test__update_dnat_entry_if_needed_down(self):
2401-
self._test__update_dnat_entry_if_needed(up=False)
2403+
def test__update_dnat_entry_if_needed_no_dvr(self):
2404+
self._test__update_dnat_entry_if_needed(dvr=False)
24022405

24032406
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
24042407
'ovn_client.OVNClient._get_router_ports')
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
other:
3+
- |
4+
The external_mac entry in the NAT table is used to distribute/centralize
5+
the traffic to the FIPs. When there is an external_mac set the traffic
6+
is distributed (DVR). When it is empty it is centralized through the
7+
gateway port (no DVR). Upon port status transition to down, the
8+
external_mac was removed regardless of DVR being enabled or not, leading
9+
to centralize the FIP traffic for DVR -- though it was for down ports that
10+
won't accept traffic anyway.

0 commit comments

Comments
 (0)