Merge "Add support for FDB aging"
This commit is contained in:
commit
f185379980
@ -402,6 +402,9 @@ LRP_OPTIONS_RESIDE_REDIR_CH = 'reside-on-redirect-chassis'
|
||||
LRP_OPTIONS_REDIRECT_TYPE = 'redirect-type'
|
||||
BRIDGE_REDIRECT_TYPE = "bridged"
|
||||
|
||||
# FDB AGE Settings
|
||||
LS_OPTIONS_FDB_AGE_THRESHOLD = 'fdb_age_threshold'
|
||||
|
||||
# Port Binding types
|
||||
PB_TYPE_VIRTUAL = 'virtual'
|
||||
|
||||
|
@ -226,6 +226,12 @@ ovn_opts = [
|
||||
'flooding for traffic towards unknown IPs when port '
|
||||
'security is disabled. It requires OVN 22.09 or '
|
||||
'newer.')),
|
||||
cfg.IntOpt('fdb_age_threshold',
|
||||
min=0,
|
||||
default=0,
|
||||
help=_('The number of seconds to keep FDB entries in the OVN '
|
||||
'DB. The value defaults to 0, which means disabled. '
|
||||
'This is supported by OVN >= 23.09.')),
|
||||
]
|
||||
|
||||
nb_global_opts = [
|
||||
@ -241,6 +247,14 @@ nb_global_opts = [
|
||||
'is not an issue, setting it to True can reduce '
|
||||
'the load and latency of the control plane. '
|
||||
'The default value is False.')),
|
||||
cfg.IntOpt('fdb_removal_limit',
|
||||
min=0,
|
||||
default=0,
|
||||
help=_('FDB aging bulk removal limit. This limits how many '
|
||||
'rows can expire in a single transaction. Default '
|
||||
'is 0, which is unlimited. When the limit is reached, '
|
||||
'the next batch removal is delayed by 5 seconds. '
|
||||
'This is supported by OVN >= 23.09.')),
|
||||
]
|
||||
|
||||
|
||||
@ -360,3 +374,11 @@ def is_ovn_dhcp_disabled_for_baremetal():
|
||||
|
||||
def is_learn_fdb_enabled():
|
||||
return cfg.CONF.ovn.localnet_learn_fdb
|
||||
|
||||
|
||||
def get_fdb_age_threshold():
|
||||
return str(cfg.CONF.ovn.fdb_age_threshold)
|
||||
|
||||
|
||||
def get_fdb_removal_limit():
|
||||
return str(cfg.CONF.ovn_nb_global.fdb_removal_limit)
|
||||
|
@ -798,6 +798,39 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase):
|
||||
txn.add(cmd)
|
||||
raise periodics.NeverAgain()
|
||||
|
||||
# A static spacing value is used here, but this method will only run
|
||||
# once per lock due to the use of periodics.NeverAgain().
|
||||
@has_lock_periodic(spacing=600, run_immediately=True)
|
||||
def check_fdb_aging_settings(self):
|
||||
"""Check FDB aging settings
|
||||
Ensure FDB aging settings are enforced.
|
||||
"""
|
||||
context = n_context.get_admin_context()
|
||||
cmds = []
|
||||
|
||||
config_fdb_age_threshold = ovn_conf.get_fdb_age_threshold()
|
||||
# Get provider networks
|
||||
nets = self._ovn_client._plugin.get_networks(context)
|
||||
for net in nets:
|
||||
if not utils.is_provider_network(net):
|
||||
continue
|
||||
ls_name = utils.ovn_name(net['id'])
|
||||
ls = self._nb_idl.get_lswitch(ls_name)
|
||||
ls_fdb_age_threshold = ls.other_config.get(
|
||||
ovn_const.LS_OPTIONS_FDB_AGE_THRESHOLD)
|
||||
|
||||
if config_fdb_age_threshold != ls_fdb_age_threshold:
|
||||
other_config = {ovn_const.LS_OPTIONS_FDB_AGE_THRESHOLD:
|
||||
config_fdb_age_threshold}
|
||||
cmds.append(self._nb_idl.db_set(
|
||||
'Logical_Switch', ls_name,
|
||||
('other_config', other_config)))
|
||||
if cmds:
|
||||
with self._nb_idl.transaction(check_error=True) as txn:
|
||||
for cmd in cmds:
|
||||
txn.add(cmd)
|
||||
raise periodics.NeverAgain()
|
||||
|
||||
# TODO(fnordahl): Remove this in the B+3 cycle. This method removes the
|
||||
# now redundant "external_ids:OVN_GW_NETWORK_EXT_ID_KEY" and
|
||||
# "external_ids:OVN_GW_PORT_EXT_ID_KEY" from to each router.
|
||||
|
@ -1914,6 +1914,9 @@ class OVNClient(object):
|
||||
params['other_config'] = {ovn_const.MCAST_SNOOP: value,
|
||||
ovn_const.MCAST_FLOOD_UNREGISTERED: 'false',
|
||||
ovn_const.VLAN_PASSTHRU: vlan_transparent}
|
||||
if utils.is_provider_network(network):
|
||||
params['other_config'][ovn_const.LS_OPTIONS_FDB_AGE_THRESHOLD] = (
|
||||
ovn_conf.get_fdb_age_threshold())
|
||||
return params
|
||||
|
||||
def create_network(self, context, network):
|
||||
|
@ -20,6 +20,7 @@ from oslo_config import cfg
|
||||
from futurist import periodics
|
||||
from neutron_lib.api.definitions import external_net as extnet_apidef
|
||||
from neutron_lib.api.definitions import floating_ip_port_forwarding as pf_def
|
||||
from neutron_lib.api.definitions import provider_net as provnet_apidef
|
||||
from neutron_lib import constants as n_const
|
||||
from neutron_lib import context as n_context
|
||||
from neutron_lib.exceptions import l3 as lib_l3_exc
|
||||
@ -60,8 +61,12 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase):
|
||||
ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY) == name):
|
||||
return row
|
||||
|
||||
def _create_network(self, name, external=False):
|
||||
data = {'network': {'name': name, extnet_apidef.EXTERNAL: external}}
|
||||
def _create_network(self, name, external=False, provider=None):
|
||||
data = {'network': {'name': name,
|
||||
extnet_apidef.EXTERNAL: external}}
|
||||
if provider:
|
||||
data['network'][provnet_apidef.NETWORK_TYPE] = 'flat'
|
||||
data['network'][provnet_apidef.PHYSICAL_NETWORK] = provider
|
||||
req = self.new_create_request('networks', data, self.fmt,
|
||||
as_admin=True)
|
||||
res = req.get_response(self.api)
|
||||
@ -756,6 +761,26 @@ class TestMaintenance(_TestMaintenanceHelper):
|
||||
self.assertEqual(
|
||||
'false', ls['other_config'][ovn_const.MCAST_FLOOD_UNREGISTERED])
|
||||
|
||||
def test_check_for_aging_settings(self):
|
||||
net = self._create_network('net', provider='datacentre')
|
||||
ls = self.nb_api.get_lswitch(utils.ovn_name(net['id']))
|
||||
|
||||
self.assertEqual(
|
||||
'0', ls.other_config.get(ovn_const.LS_OPTIONS_FDB_AGE_THRESHOLD))
|
||||
|
||||
# Change the value of the configuration
|
||||
cfg.CONF.set_override('fdb_age_threshold', 5, group='ovn')
|
||||
|
||||
# Call the maintenance task and check that the value has been
|
||||
# updated in the Logical Switch
|
||||
self.assertRaises(periodics.NeverAgain,
|
||||
self.maint.check_fdb_aging_settings)
|
||||
|
||||
ls = self.nb_api.get_lswitch(utils.ovn_name(net['id']))
|
||||
|
||||
self.assertEqual(
|
||||
'5', ls.other_config.get(ovn_const.LS_OPTIONS_FDB_AGE_THRESHOLD))
|
||||
|
||||
def test_floating_ip(self):
|
||||
ext_net = self._create_network('ext_networktest', external=True)
|
||||
ext_subnet = self._create_subnet(
|
||||
|
@ -891,6 +891,37 @@ class TestDBInconsistenciesPeriodics(testlib_api.SqlTestCaseLight,
|
||||
self.fake_ovn_client._nb_idl.db_set.assert_has_calls(
|
||||
expected_calls)
|
||||
|
||||
def test_check_fdb_aging_settings(self):
|
||||
cfg.CONF.set_override('fdb_age_threshold', 5, group='ovn')
|
||||
networks = [{'id': 'foo',
|
||||
'provider:physical_network': 'datacentre'}]
|
||||
self.fake_ovn_client._plugin.get_networks.return_value = networks
|
||||
fake_ls = mock.Mock(other_config={})
|
||||
self.fake_ovn_client._nb_idl.get_lswitch.return_value = fake_ls
|
||||
|
||||
self.assertRaises(
|
||||
periodics.NeverAgain,
|
||||
self.periodic.check_fdb_aging_settings)
|
||||
|
||||
self.fake_ovn_client._nb_idl.db_set.assert_called_once_with(
|
||||
'Logical_Switch', 'neutron-foo',
|
||||
('other_config', {constants.LS_OPTIONS_FDB_AGE_THRESHOLD: '5'}))
|
||||
|
||||
def test_check_fdb_aging_settings_with_threshold_set(self):
|
||||
cfg.CONF.set_override('fdb_age_threshold', 5, group='ovn')
|
||||
networks = [{'id': 'foo',
|
||||
'provider:network_type': n_const.TYPE_VLAN}]
|
||||
self.fake_ovn_client._plugin.get_networks.return_value = networks
|
||||
fake_ls = mock.Mock(other_config={
|
||||
constants.LS_OPTIONS_FDB_AGE_THRESHOLD: '5'})
|
||||
self.fake_ovn_client._nb_idl.get_lswitch.return_value = fake_ls
|
||||
|
||||
self.assertRaises(
|
||||
periodics.NeverAgain,
|
||||
self.periodic.check_fdb_aging_settings)
|
||||
|
||||
self.fake_ovn_client._nb_idl.db_set.assert_not_called()
|
||||
|
||||
def test_remove_gw_ext_ids_from_logical_router(self):
|
||||
nb_idl = self.fake_ovn_client._nb_idl
|
||||
# lr0: GW port ID, not GW network ID --> we need to remove port ID.
|
||||
|
14
releasenotes/notes/support-fdb-aging-b9ab82d75db81bbc.yaml
Normal file
14
releasenotes/notes/support-fdb-aging-b9ab82d75db81bbc.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
In OVN 22.09 the option ``localnet_learn_fdb`` was added, enabling localnet
|
||||
ports to learn MAC addresses and store them at the FDB table. There was no
|
||||
aging mechanism for those MACs until OVN 23.06, where the configuration
|
||||
option ``fdb_age_threshold`` was added. This enables to set the maximum
|
||||
time the learned MACs will stay in the FDB table (in seconds). When the
|
||||
``localnet_learn_fdb`` configuration option is enabled, the proper value
|
||||
for ``fdb_age_threshold`` should also be set, to avoid
|
||||
performance/scalability issues due to the table growing too much --
|
||||
especially when provider networks are large. In addition the configuration
|
||||
option ``fdb_removal_limit`` was also added to avoid removing a large
|
||||
number of entries at once.
|
Loading…
x
Reference in New Issue
Block a user