Skip to content

Commit 61d9e59

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 73ba302 commit 61d9e59

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

1043-
def _update_dnat_entry_if_needed(self, port_id, up=True):
1043+
def _update_dnat_entry_if_needed(self, port_id):
10441044
"""Update DNAT entry if using distributed floating ips."""
10451045
if not self.nb_ovn:
10461046
self.nb_ovn = self._ovn_client._nb_idl
@@ -1061,9 +1061,9 @@ def _update_dnat_entry_if_needed(self, port_id, up=True):
10611061
{ovn_const.OVN_FIP_EXT_MAC_KEY:
10621062
nat['external_mac']})).execute()
10631063

1064-
if up and ovn_conf.is_ovn_distributed_floating_ip():
1065-
mac = nat['external_ids'][ovn_const.OVN_FIP_EXT_MAC_KEY]
1066-
if nat['external_mac'] != mac:
1064+
if ovn_conf.is_ovn_distributed_floating_ip():
1065+
mac = nat['external_ids'].get(ovn_const.OVN_FIP_EXT_MAC_KEY)
1066+
if mac and nat['external_mac'] != mac:
10671067
LOG.debug("Setting external_mac of port %s to %s",
10681068
port_id, mac)
10691069
self.nb_ovn.db_set(
@@ -1129,7 +1129,7 @@ def set_port_status_down(self, port_id):
11291129
# to prevent another entity from bypassing the block with its own
11301130
# port status update.
11311131
LOG.info("OVN reports status down for port: %s", port_id)
1132-
self._update_dnat_entry_if_needed(port_id, False)
1132+
self._update_dnat_entry_if_needed(port_id)
11331133
admin_context = n_context.get_admin_context()
11341134
try:
11351135
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
@@ -1106,7 +1106,7 @@ def _test_set_port_status_down(self, is_compute_port=False):
11061106
resources.PORT,
11071107
provisioning_blocks.L2_AGENT_ENTITY
11081108
)
1109-
ude.assert_called_once_with(port1['port']['id'], False)
1109+
ude.assert_called_once_with(port1['port']['id'])
11101110

11111111
# If the port does NOT bellong to compute, do not notify Nova
11121112
# about it's status changes
@@ -1156,7 +1156,7 @@ def test_set_port_status_concurrent_delete(self):
11561156
resources.PORT,
11571157
provisioning_blocks.L2_AGENT_ENTITY
11581158
)
1159-
ude.assert_called_once_with(port1['port']['id'], False)
1159+
ude.assert_called_once_with(port1['port']['id'])
11601160

11611161
def test_bind_port_unsupported_vnic_type(self):
11621162
fake_port = fakes.FakePort.create_one_port(
@@ -2350,9 +2350,10 @@ def test_agent_with_nb_cfg_timestamp_not_timeout(self):
23502350
self.assertTrue(agent.alive, "Agent of type %s alive=%s" % (
23512351
agent.agent_type, agent.alive))
23522352

2353-
def _test__update_dnat_entry_if_needed(self, up=True):
2354-
ovn_conf.cfg.CONF.set_override(
2355-
'enable_distributed_floating_ip', True, group='ovn')
2353+
def _test__update_dnat_entry_if_needed(self, dvr=True):
2354+
if dvr:
2355+
ovn_conf.cfg.CONF.set_override(
2356+
'enable_distributed_floating_ip', True, group='ovn')
23562357
port_id = 'fake-port-id'
23572358
fake_ext_mac_key = 'fake-ext-mac-key'
23582359
fake_nat_uuid = uuidutils.generate_uuid()
@@ -2365,22 +2366,24 @@ def _test__update_dnat_entry_if_needed(self, up=True):
23652366
fake_db_find.execute.return_value = [nat_row]
23662367
self.nb_ovn.db_find.return_value = fake_db_find
23672368

2368-
self.mech_driver._update_dnat_entry_if_needed(port_id, up=up)
2369+
self.mech_driver._update_dnat_entry_if_needed(port_id)
23692370

2370-
if up:
2371+
if dvr:
23712372
# Assert that we are setting the external_mac in the NAT table
23722373
self.nb_ovn.db_set.assert_called_once_with(
23732374
'NAT', fake_nat_uuid, ('external_mac', fake_ext_mac_key))
2375+
self.nb_ovn.db_clear.assert_not_called()
23742376
else:
2377+
self.nb_ovn.db_set.assert_not_called()
23752378
# Assert that we are cleaning the external_mac from the NAT table
23762379
self.nb_ovn.db_clear.assert_called_once_with(
23772380
'NAT', fake_nat_uuid, 'external_mac')
23782381

2379-
def test__update_dnat_entry_if_needed_up(self):
2382+
def test__update_dnat_entry_if_needed_dvr(self):
23802383
self._test__update_dnat_entry_if_needed()
23812384

2382-
def test__update_dnat_entry_if_needed_down(self):
2383-
self._test__update_dnat_entry_if_needed(up=False)
2385+
def test__update_dnat_entry_if_needed_no_dvr(self):
2386+
self._test__update_dnat_entry_if_needed(dvr=False)
23842387

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