[OVN] Tune OVN routers to reduce the mem footprint for ML2/OVN
In order to avoid having a MAC_Binding table explosion and helping
lowering the memory footprint when using ML2/OVN this patch is setting
two options to the OVN routers:
* always_learn_from_arp_request: By setting this to False we
avoid learning from ARP replies observed in the network. Only the
ARP requests sent by OVN will generate a MAC_Binding entry in the
OVSDB database. For larger broadcasts domains this avoids having a
MAC_Binding table explosion, reduce the DB size and memory footprint
of ML2/OVN.
* dynamic_neigh_routers: By setting this to True we avoid
pre-populating flows for router to router communication, reduding
the number of flows, DB size and memory footprint of ML2/OVN.
For more information on these option for core OVN please refer to:
https://www.ovn.org/support/dist-docs/ovn-nb.5.html
This patch also includes a new maintenance task to include these options
to existing routers in the system.
Related-Bug: #1946318
Change-Id: I056acdec9b6ee2341d2bc4f7bd9a678f3bf91972
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
(cherry picked from commit a278c5ba78
)
This commit is contained in:
parent
72b16aeac0
commit
e814e93e8e
|
@ -14,6 +14,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
import copy
|
||||||
import inspect
|
import inspect
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
@ -675,6 +676,31 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase):
|
||||||
|
|
||||||
raise periodics.NeverAgain()
|
raise periodics.NeverAgain()
|
||||||
|
|
||||||
|
# TODO(lucasagomes): Remove this in the Z cycle
|
||||||
|
# A static spacing value is used here, but this method will only run
|
||||||
|
# once per lock due to the use of periodics.NeverAgain().
|
||||||
|
@periodics.periodic(spacing=600, run_immediately=True)
|
||||||
|
def check_router_mac_binding_options(self):
|
||||||
|
if not self.has_lock:
|
||||||
|
return
|
||||||
|
|
||||||
|
cmds = []
|
||||||
|
for router in self._nb_idl.lr_list().execute(check_error=True):
|
||||||
|
if (router.options.get('always_learn_from_arp_request') and
|
||||||
|
router.options.get('dynamic_neigh_routers')):
|
||||||
|
continue
|
||||||
|
|
||||||
|
opts = copy.deepcopy(router.options)
|
||||||
|
opts.update({'always_learn_from_arp_request': 'false',
|
||||||
|
'dynamic_neigh_routers': 'true'})
|
||||||
|
cmds.append(self._nb_idl.update_lrouter(router.name, options=opts))
|
||||||
|
|
||||||
|
if cmds:
|
||||||
|
with self._nb_idl.transaction(check_error=True) as txn:
|
||||||
|
for cmd in cmds:
|
||||||
|
txn.add(cmd)
|
||||||
|
raise periodics.NeverAgain()
|
||||||
|
|
||||||
|
|
||||||
class HashRingHealthCheckPeriodics(object):
|
class HashRingHealthCheckPeriodics(object):
|
||||||
|
|
||||||
|
|
|
@ -1170,11 +1170,13 @@ class OVNClient(object):
|
||||||
enabled = router.get('admin_state_up')
|
enabled = router.get('admin_state_up')
|
||||||
lrouter_name = utils.ovn_name(router['id'])
|
lrouter_name = utils.ovn_name(router['id'])
|
||||||
added_gw_port = None
|
added_gw_port = None
|
||||||
|
options = {'always_learn_from_arp_request': 'false',
|
||||||
|
'dynamic_neigh_routers': 'true'}
|
||||||
with self._nb_idl.transaction(check_error=True) as txn:
|
with self._nb_idl.transaction(check_error=True) as txn:
|
||||||
txn.add(self._nb_idl.create_lrouter(lrouter_name,
|
txn.add(self._nb_idl.create_lrouter(lrouter_name,
|
||||||
external_ids=external_ids,
|
external_ids=external_ids,
|
||||||
enabled=enabled,
|
enabled=enabled,
|
||||||
options={}))
|
options=options))
|
||||||
# TODO(lucasagomes): add_external_gateway is being only used
|
# TODO(lucasagomes): add_external_gateway is being only used
|
||||||
# by the ovn_db_sync.py script, remove it after the database
|
# by the ovn_db_sync.py script, remove it after the database
|
||||||
# synchronization work
|
# synchronization work
|
||||||
|
|
|
@ -432,3 +432,31 @@ class TestDBInconsistenciesPeriodics(testlib_api.SqlTestCaseLight,
|
||||||
mock.call('lsp5', mcast_flood_reports='true', mcast_flood='false')]
|
mock.call('lsp5', mcast_flood_reports='true', mcast_flood='false')]
|
||||||
|
|
||||||
nb_idl.lsp_set_options.assert_has_calls(expected_calls)
|
nb_idl.lsp_set_options.assert_has_calls(expected_calls)
|
||||||
|
|
||||||
|
def test_check_router_mac_binding_options(self):
|
||||||
|
nb_idl = self.fake_ovn_client._nb_idl
|
||||||
|
lr0 = fakes.FakeOvsdbRow.create_one_ovsdb_row(
|
||||||
|
attrs={'name': 'lr0',
|
||||||
|
'options': {'always_learn_from_arp_request': 'false',
|
||||||
|
'dynamic_neigh_routers': 'true'}})
|
||||||
|
lr1 = fakes.FakeOvsdbRow.create_one_ovsdb_row(
|
||||||
|
attrs={'name': 'lr1', 'options': {}})
|
||||||
|
lr2 = fakes.FakeOvsdbRow.create_one_ovsdb_row(
|
||||||
|
attrs={'name': 'lr2', 'options': {}})
|
||||||
|
nb_idl.lr_list.return_value.execute.return_value = [lr0, lr1, lr2]
|
||||||
|
|
||||||
|
# Invoke the periodic method, it meant to run only once at startup
|
||||||
|
# so NeverAgain will be raised at the end
|
||||||
|
self.assertRaises(periodics.NeverAgain,
|
||||||
|
self.periodic.check_router_mac_binding_options)
|
||||||
|
|
||||||
|
# Assert lr1 and lr2 had their options updated since the values
|
||||||
|
# were not set
|
||||||
|
expected_calls = [
|
||||||
|
mock.call('lr1',
|
||||||
|
options={'always_learn_from_arp_request': 'false',
|
||||||
|
'dynamic_neigh_routers': 'true'}),
|
||||||
|
mock.call('lr2',
|
||||||
|
options={'always_learn_from_arp_request': 'false',
|
||||||
|
'dynamic_neigh_routers': 'true'})]
|
||||||
|
nb_idl.update_lrouter.assert_has_calls(expected_calls)
|
||||||
|
|
|
@ -538,7 +538,8 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
|
||||||
ovn_const.OVN_ROUTER_AZ_HINTS_EXT_ID_KEY: ''}
|
ovn_const.OVN_ROUTER_AZ_HINTS_EXT_ID_KEY: ''}
|
||||||
self.l3_inst._ovn.create_lrouter.assert_called_once_with(
|
self.l3_inst._ovn.create_lrouter.assert_called_once_with(
|
||||||
'neutron-router-id', external_ids=external_ids,
|
'neutron-router-id', external_ids=external_ids,
|
||||||
enabled=True, options={})
|
enabled=True, options={'always_learn_from_arp_request': 'false',
|
||||||
|
'dynamic_neigh_routers': 'true'})
|
||||||
self.l3_inst._ovn.add_lrouter_port.assert_called_once_with(
|
self.l3_inst._ovn.add_lrouter_port.assert_called_once_with(
|
||||||
**self.fake_ext_gw_port_assert)
|
**self.fake_ext_gw_port_assert)
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
|
|
Loading…
Reference in New Issue