Skip to content

Commit fc29d62

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 9060971 commit fc29d62

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

1055-
def _update_dnat_entry_if_needed(self, port_id, up=True):
1055+
def _update_dnat_entry_if_needed(self, port_id):
10561056
"""Update DNAT entry if using distributed floating ips."""
10571057
if not self.nb_ovn:
10581058
self.nb_ovn = self._ovn_client._nb_idl
@@ -1073,9 +1073,9 @@ def _update_dnat_entry_if_needed(self, port_id, up=True):
10731073
{ovn_const.OVN_FIP_EXT_MAC_KEY:
10741074
nat['external_mac']})).execute()
10751075

1076-
if up and ovn_conf.is_ovn_distributed_floating_ip():
1077-
mac = nat['external_ids'][ovn_const.OVN_FIP_EXT_MAC_KEY]
1078-
if nat['external_mac'] != mac:
1076+
if ovn_conf.is_ovn_distributed_floating_ip():
1077+
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1078+
if mac and nat['external_mac'] != mac:
10791079
LOG.debug("Setting external_mac of port %s to %s",
10801080
port_id, mac)
10811081
self.nb_ovn.db_set(
@@ -1141,7 +1141,7 @@ def set_port_status_down(self, port_id):
11411141
# to prevent another entity from bypassing the block with its own
11421142
# port status update.
11431143
LOG.info("OVN reports status down for port: %s", port_id)
1144-
self._update_dnat_entry_if_needed(port_id, False)
1144+
self._update_dnat_entry_if_needed(port_id)
11451145
admin_context = n_context.get_admin_context()
11461146
try:
11471147
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(
@@ -2374,9 +2374,10 @@ def test_agent_with_nb_cfg_timestamp_not_timeout(self):
23742374
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
23752375
agent.agent_type, agent.alive))
23762376

2377-
def _test__update_dnat_entry_if_needed(self, up=True):
2378-
ovn_conf.cfg.CONF.set_override(
2379-
'enable_distributed_floating_ip', True, group='ovn')
2377+
def _test__update_dnat_entry_if_needed(self, dvr=True):
2378+
if dvr:
2379+
ovn_conf.cfg.CONF.set_override(
2380+
'enable_distributed_floating_ip', True, group='ovn')
23802381
port_id = 'fake-port-id'
23812382
fake_ext_mac_key = 'fake-ext-mac-key'
23822383
fake_nat_uuid = uuidutils.generate_uuid()
@@ -2389,22 +2390,24 @@ def _test__update_dnat_entry_if_needed(self, up=True):
23892390
fake_db_find.execute.return_value = [nat_row]
23902391
self.nb_ovn.db_find.return_value = fake_db_find
23912392

2392-
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
2393+
self.mech_driver._update_dnat_entry_if_needed(port_id)
23932394

2394-
if up:
2395+
if dvr:
23952396
# Assert that we are setting the external_mac in the NAT table
23962397
self.nb_ovn.db_set.assert_called_once_with(
23972398
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
2399+
self.nb_ovn.db_clear.assert_not_called()
23982400
else:
2401+
self.nb_ovn.db_set.assert_not_called()
23992402
# Assert that we are cleaning the external_mac from the NAT table
24002403
self.nb_ovn.db_clear.assert_called_once_with(
24012404
'NAT', fake_nat_uuid, 'external_mac')
24022405

2403-
def test__update_dnat_entry_if_needed_up(self):
2406+
def test__update_dnat_entry_if_needed_dvr(self):
24042407
self._test__update_dnat_entry_if_needed()
24052408

2406-
def test__update_dnat_entry_if_needed_down(self):
2407-
self._test__update_dnat_entry_if_needed(up=False)
2409+
def test__update_dnat_entry_if_needed_no_dvr(self):
2410+
self._test__update_dnat_entry_if_needed(dvr=False)
24082411

24092412
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
24102413
'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)