Introduce ovn_nb_global config section

The patch introduces a new config section ovn_nb_global. All options
from this section are passed to OVN Northbound NB_Global table to
configure Northbound OVN.

First option is ignore_lsp_down to override OVN default configuration.
This option was changed in OVN to `true` [1] but for Neutron it's better
to not answer ARP packets when ports are in DOWN status.

[1] https://www.mail-archive.com/ovs-dev@openvswitch.org/msg60064.html

Change-Id: I478249cae483fd2540a7ff3ab714e3d9c3e13f17
Signed-off-by: Jakub Libosvar <libosvar@redhat.com>
This commit is contained in:
Jakub Libosvar 2023-09-25 23:35:02 +00:00
parent c3ba36bc83
commit 4e566b11d0
6 changed files with 88 additions and 1 deletions

View File

@ -28,6 +28,8 @@ VLOG_LEVELS = {'CRITICAL': vlog.CRITICAL, 'ERROR': vlog.ERROR, 'WARNING':
MIGRATE_MODE = "migrate"
OVN_NB_GLOBAL = "ovn_nb_global"
ovn_opts = [
cfg.StrOpt('ovn_nb_connection',
default='tcp:127.0.0.1:6641',
@ -226,16 +228,33 @@ ovn_opts = [
'newer.')),
]
nb_global_opts = [
cfg.BoolOpt('ignore_lsp_down',
default=False,
help=_('If set to False, ARP/ND reply flows for logical '
'switch ports will be installed only if the port is '
'UP, i.e. claimed by a Chassis. If set to True, these '
'flows are installed regardless of the status of the '
'port, which can result in a situation that an ARP '
'request to an IP is resolved even before the relevant '
'VM/container is running. For environments where this '
'is not an issue, setting it to True can reduce '
'the load and latency of the control plane. '
'The default value is False.')),
]
def register_opts():
cfg.CONF.register_opts(ovn_opts, group='ovn')
ovs_conf.register_ovs_agent_opts()
cfg.CONF.register_opts(nb_global_opts, group=OVN_NB_GLOBAL)
def list_opts():
return [
('ovn', ovn_opts),
('ovs', ovs_conf.OPTS)
('ovs', ovs_conf.OPTS),
(OVN_NB_GLOBAL, nb_global_opts),
]

View File

@ -623,6 +623,10 @@ class API(api.API, metaclass=abc.ABCMeta):
:returns: The NAT rule row or Load_Balancer row or None
"""
@abc.abstractmethod
def set_nb_global_options(self, key, value):
"""Set NB_Global options configuration"""
class SbAPI(api.API, metaclass=abc.ABCMeta):

View File

@ -848,6 +848,10 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
def update_lb_external_ids(self, lb_name, values, if_exists=True):
return cmd.UpdateLbExternalIds(self, lb_name, values, if_exists)
def set_nb_global_options(self, **options):
LOG.debug("Setting NB_Global options: %s", options)
return self.db_set("NB_Global", ".", options=options)
class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
def __init__(self, connection):

View File

@ -1079,6 +1079,22 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase):
context = n_context.get_admin_context()
hash_ring_db.cleanup_old_nodes(context, days=5)
@has_lock_periodic(spacing=86400, run_immediately=True)
def configure_nb_global(self):
"""Configure Northbound OVN NB_Global options
The method goes over all config options from ovn_nb_global config
sections and configures same key/value pairs to the NB_Global:options
column.
"""
options = {opt.name: str(cfg.CONF.ovn_nb_global.get(opt.name)).lower()
for opt in ovn_conf.nb_global_opts}
self._nb_idl.set_nb_global_options(**options).execute(
check_error=True)
raise periodics.NeverAgain()
class HashRingHealthCheckPeriodics(object):

View File

@ -1032,6 +1032,39 @@ class TestMaintenance(_TestMaintenanceHelper):
# "Chassis_Private" register was missing.
self.assertEqual(2, len(chassis_result))
def test_configure_nb_global(self):
def options_intersect(options1, options2):
return bool(set(
new_nb_global_options.keys()).intersection(nb_options.keys()))
new_nb_global_options = {
'foo': 'bar',
'baz': 'qux',
}
cfg_nb_global_options = [
ovn_config.cfg.StrOpt(key) for key in new_nb_global_options
]
def get_opt(key):
return new_nb_global_options[key]
nb_options = self.nb_api.db_get('NB_Global', '.', 'options').execute(
check_error=True, log_errors=True)
self.assertFalse(options_intersect(new_nb_global_options, nb_options))
with mock.patch.object(
ovn_config, 'nb_global_opts', cfg_nb_global_options), \
mock.patch.object(
ovn_config.cfg.CONF.ovn_nb_global, 'get',
side_effect=get_opt):
self.assertRaises(periodics.NeverAgain,
self.maint.configure_nb_global)
nb_options = self.nb_api.db_get('NB_Global', '.', 'options').execute(
check_error=True, log_errors=True)
self.assertTrue(options_intersect(new_nb_global_options, nb_options))
class TestLogMaintenance(_TestMaintenanceHelper,
test_log_driver.LogApiTestCaseBase):

View File

@ -0,0 +1,11 @@
---
upgrade:
- |
Starting with OVN version v21.12.0, OVN replies to ARP requests for ports
that are in a DOWN status. It does not reply in versions older than
v21.12.0. In order to keep the same behavior in Neutron, the default OVN
behavior is overridden by Neutron and Neutron ports will no longer reply to
ARP packets if the ports are in a DOWN state. If it is required to reply to
ARP for such ports, the config option ``ignore_lsp_down`` from
``[ovn_nb_global]`` section can be set to True in the Neutron config. It is
set to False by default.