Skip to content

Commit ad4c50d

Browse files
committed
[OVN][L3] Optimize FIP update operation
If the floating IP updates only the QoS policy, the method now skips the OVN NAT rules update and updates only the QoS policy. That avoids the OVN NAT rules deletion and creation and the ``FIPAddDeleteEvent`` event that deletes the MAC binding entries for an active floating IP, causing a disruption. Closes-Bug: #2025144 Change-Id: Ib9ec45d643c6162c526cd5a02db270094b575e34 (cherry picked from commit 7b85f9c)
1 parent 06694e3 commit ad4c50d

File tree

3 files changed

+47
-17
lines changed

3 files changed

+47
-17
lines changed

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from neutron_lib.plugins import directory
3333
from neutron_lib.plugins import utils as p_utils
3434
from neutron_lib.services.logapi import constants as log_const
35+
from neutron_lib.services.qos import constants as qos_consts
3536
from neutron_lib.utils import helpers
3637
from neutron_lib.utils import net as n_net
3738
from oslo_config import cfg
@@ -1130,25 +1131,30 @@ def create_floatingip(self, context, floatingip):
11301131
n_context.get_admin_context(), floatingip['id'],
11311132
const.FLOATINGIP_STATUS_ACTIVE)
11321133

1133-
def update_floatingip(self, context, floatingip):
1134+
def update_floatingip(self, context, floatingip, fip_request=None):
11341135
fip_status = None
11351136
router_id = None
11361137
ovn_fip = self._nb_idl.get_floatingip(floatingip['id'])
1138+
fip_request = fip_request[l3.FLOATINGIP] if fip_request else {}
1139+
qos_update_only = (len(fip_request.keys()) == 1 and
1140+
qos_consts.QOS_POLICY_ID in fip_request)
11371141

11381142
check_rev_cmd = self._nb_idl.check_revision_number(
11391143
floatingip['id'], floatingip, ovn_const.TYPE_FLOATINGIPS)
11401144
with self._nb_idl.transaction(check_error=True) as txn:
11411145
txn.add(check_rev_cmd)
1142-
if ovn_fip:
1143-
lrouter = ovn_fip['external_ids'].get(
1144-
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY,
1145-
utils.ovn_name(router_id))
1146-
self._delete_floatingip(ovn_fip, lrouter, txn=txn)
1147-
fip_status = const.FLOATINGIP_STATUS_DOWN
1148-
1149-
if floatingip.get('port_id'):
1150-
self._create_or_update_floatingip(floatingip, txn=txn)
1151-
fip_status = const.FLOATINGIP_STATUS_ACTIVE
1146+
# If FIP updates the QoS policy only, skip the OVN NAT rules update
1147+
if not qos_update_only:
1148+
if ovn_fip:
1149+
lrouter = ovn_fip['external_ids'].get(
1150+
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY,
1151+
utils.ovn_name(router_id))
1152+
self._delete_floatingip(ovn_fip, lrouter, txn=txn)
1153+
fip_status = const.FLOATINGIP_STATUS_DOWN
1154+
1155+
if floatingip.get('port_id'):
1156+
self._create_or_update_floatingip(floatingip, txn=txn)
1157+
fip_status = const.FLOATINGIP_STATUS_ACTIVE
11521158

11531159
self._qos_driver.update_floatingip(txn, floatingip)
11541160

neutron/services/ovn_l3/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def delete_floatingip(self, context, id):
290290
def update_floatingip(self, context, id, floatingip):
291291
fip = super(OVNL3RouterPlugin, self).update_floatingip(context, id,
292292
floatingip)
293-
self._ovn_client.update_floatingip(context, fip)
293+
self._ovn_client.update_floatingip(context, fip, floatingip)
294294
return fip
295295

296296
def update_floatingip_status(self, context, floatingip_id, status):

neutron/tests/unit/services/ovn_l3/test_plugin.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from unittest import mock
1717

1818
from neutron_lib.api.definitions import external_net
19+
from neutron_lib.api.definitions import l3 as l3_def
1920
from neutron_lib.api.definitions import portbindings
2021
from neutron_lib.api.definitions import provider_net as pnet
2122
from neutron_lib.callbacks import events
@@ -26,13 +27,15 @@
2627
from neutron_lib.exceptions import l3 as l3_exc
2728
from neutron_lib.plugins import constants as plugin_constants
2829
from neutron_lib.plugins import directory
30+
from neutron_lib.services.qos import constants as qos_consts
2931
from oslo_config import cfg
3032
from oslo_utils import uuidutils
3133

3234
from neutron.api.v2 import router as api_router
3335
from neutron.common.ovn import constants as ovn_const
3436
from neutron.common.ovn import utils
3537
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf as config
38+
from neutron.db import extraroute_db
3639
from neutron import manager as neutron_manager
3740
from neutron.plugins.ml2 import managers
3841
from neutron.services.ovn_l3 import exceptions as ovn_l3_exc
@@ -1220,7 +1223,8 @@ def test_update_floatingip(self, uf):
12201223
uf.return_value = self.fake_floating_ip_new
12211224
nb_ovn.get_floatingip.return_value = (
12221225
self.fake_ovn_nat_rule)
1223-
self.l3_inst.update_floatingip(self.context, 'id', 'floatingip')
1226+
fip = {l3_def.FLOATINGIP: {'port_id': 'port1'}}
1227+
self.l3_inst.update_floatingip(self.context, 'id', fip)
12241228
nb_ovn.delete_nat_rule_in_lrouter.assert_called_once_with(
12251229
'neutron-router-id',
12261230
type='dnat_and_snat',
@@ -1244,13 +1248,30 @@ def test_update_floatingip(self, uf):
12441248
logical_port='new-port_id',
12451249
external_ids=expected_ext_ids)
12461250

1251+
@mock.patch.object(extraroute_db.ExtraRoute_dbonly_mixin,
1252+
'update_floatingip')
1253+
def test_update_floatingip_qos(self, uf):
1254+
nb_ovn = self.l3_inst._nb_ovn
1255+
nb_ovn.is_col_present.return_value = True
1256+
uf.return_value = self.fake_floating_ip_new
1257+
nb_ovn.get_floatingip.return_value = (
1258+
self.fake_ovn_nat_rule)
1259+
fip = {l3_def.FLOATINGIP: {qos_consts.QOS_POLICY_ID: 'qos_id_1'}}
1260+
with mock.patch.object(self.l3_inst._ovn_client._qos_driver,
1261+
'update_floatingip') as ufip:
1262+
self.l3_inst.update_floatingip(self.context, 'id', fip)
1263+
nb_ovn.delete_nat_rule_in_lrouter.assert_not_called()
1264+
nb_ovn.add_nat_rule_in_lrouter.assert_not_called()
1265+
ufip.assert_called_once_with(mock.ANY, self.fake_floating_ip_new)
1266+
12471267
@mock.patch('neutron.db.extraroute_db.ExtraRoute_dbonly_mixin.'
12481268
'update_floatingip')
12491269
def test_update_floatingip_associate(self, uf):
12501270
self.l3_inst._nb_ovn.is_col_present.return_value = True
12511271
self.fake_floating_ip.update({'fixed_port_id': None})
12521272
uf.return_value = self.fake_floating_ip_new
1253-
self.l3_inst.update_floatingip(self.context, 'id', 'floatingip')
1273+
fip = {l3_def.FLOATINGIP: {'port_id': 'port1'}}
1274+
self.l3_inst.update_floatingip(self.context, 'id', fip)
12541275
self.l3_inst._nb_ovn.delete_nat_rule_in_lrouter.assert_not_called()
12551276
expected_ext_ids = {
12561277
ovn_const.OVN_FIP_EXT_ID_KEY: self.fake_floating_ip_new['id'],
@@ -1286,7 +1307,8 @@ def test_update_floatingip_associate_distributed(self, uf, gn):
12861307

12871308
config.cfg.CONF.set_override(
12881309
'enable_distributed_floating_ip', True, group='ovn')
1289-
self.l3_inst.update_floatingip(self.context, 'id', 'floatingip')
1310+
fip = {l3_def.FLOATINGIP: {'port_id': 'port1'}}
1311+
self.l3_inst.update_floatingip(self.context, 'id', fip)
12901312
self.l3_inst._nb_ovn.delete_nat_rule_in_lrouter.assert_not_called()
12911313
expected_ext_ids = {
12921314
ovn_const.OVN_FIP_EXT_ID_KEY: self.fake_floating_ip_new['id'],
@@ -1314,7 +1336,8 @@ def test_update_floatingip_association_empty_update(self, uf):
13141336
self.fake_floating_ip.update({'fixed_port_id': 'foo'})
13151337
self.fake_floating_ip_new.update({'port_id': 'foo'})
13161338
uf.return_value = self.fake_floating_ip_new
1317-
self.l3_inst.update_floatingip(self.context, 'id', 'floatingip')
1339+
fip = {l3_def.FLOATINGIP: {'port_id': 'port1'}}
1340+
self.l3_inst.update_floatingip(self.context, 'id', fip)
13181341
nb_ovn.delete_nat_rule_in_lrouter.assert_called_once_with(
13191342
'neutron-router-id',
13201343
type='dnat_and_snat',
@@ -1349,7 +1372,8 @@ def test_update_floatingip_reassociate_to_same_port_diff_fixed_ip(
13491372
self.fake_floating_ip_new.update({'port_id': 'port_id',
13501373
'fixed_port_id': 'port_id'})
13511374
uf.return_value = self.fake_floating_ip_new
1352-
self.l3_inst.update_floatingip(self.context, 'id', 'floatingip')
1375+
fip = {l3_def.FLOATINGIP: {'port_id': 'port1'}}
1376+
self.l3_inst.update_floatingip(self.context, 'id', fip)
13531377

13541378
nb_ovn.delete_nat_rule_in_lrouter.assert_called_once_with(
13551379
'neutron-router-id',

0 commit comments

Comments
 (0)