This reverts commit 354d766ca8924b9ba6ab8f471440bb9ae1b6e341.
As reported by Ilya this change significantly increased load on
ovsdb-servers running the Southbound database in large scale scenarios
(lots of OVN nodes). That's because ovsdb-server currently cannot use
its JSON cache if not all monitor conditions for a given client are set
to 'true'.
Until ovsdb-server behavior is changed/fixed we need to also revert the
ovn-controller change. While at it also partially revert the follow up
documentation change done by 1098d316be57 ("controller: Update
ovn-monitor-all documentation.") - we keep the part that fixes the
reference to the OVN Southbound database. Also add a comment in the code
and a test to explicitly validate the current behavior.
Reported-at:
https://mail.openvswitch.org/pipermail/ovs-dev/2025-February/421142.html
Reported-by: Ilya Maximets <[email protected]>
Fixes: 354d766ca892 ("ovn-controller: Remove monitor all of chassis private.")
Fixes: 1098d316be57 ("controller: Update ovn-monitor-all documentation.")
Signed-off-by: Dumitru Ceara <[email protected]>
---
V2:
- Address Ilya's comment:
- keep the fix for the OVN_Southbound database reference in the
documentation.
- Fix one more instance of <var>OVN Southbound</var> in the same
section.
---
controller/ovn-controller.8.xml | 19 +++++++---------
controller/ovn-controller.c | 39 ++++++++++++++-------------------
tests/ovn-controller.at | 37 +++++++++++++++++--------------
3 files changed, 45 insertions(+), 50 deletions(-)
diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
index 27ea77fa52..eace2c5cf2 100644
--- a/controller/ovn-controller.8.xml
+++ b/controller/ovn-controller.8.xml
@@ -117,21 +117,18 @@
<dd>
<p>
A boolean value that tells if <code>ovn-controller</code> should
- monitor all records of most tables in the
- <code>OVN Southbound</code> database. The only exception is the
- <code>Chassis_Private</code> table for which ovn-controller
- always monitors only the record that is relevant to the local
- chassis. If this option is set to <code>false</code>,
- ovn-controller will conditionally monitor only the records that
- are needed for the local chassis.
+ monitor all records of tables in the <code>OVN_Southbound</code>.
+ If this option is set to <code>false</code>, ovn-controller will
+ conditionally monitor only the records that are needed for the local
+ chassis.
</p>
<p>
It is more efficient to set it to <code>true</code> in use cases
where the chassis would anyway need to monitor most of the records in
- <var>OVN Southbound</var> database, which would save the overhead of
- conditions processing, especially for server side. Typically, set it
- to <code>true</code> for environments where all workloads need to be
- reachable from each other.
+ the <code>OVN_Southbound</code> database, which would save the
+ overhead of conditions processing, especially for server side.
+ Typically, set it to <code>true</code> for environments where all
+ workloads need to be reachable from each other.
</p>
<p>
NOTE: for efficiency and scalability in common scenarios
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index d8d1f363e5..081411cba8 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -273,17 +273,12 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
* routes until db conditions are updated. */
ovsdb_idl_condition_add_clause_true(&lr);
- if (chassis) {
- /* Monitors Chassis_Private record for current chassis only. */
- sbrec_chassis_private_add_clause_name(&chprv, OVSDB_F_EQ,
- chassis->name);
- } else {
- /* During initialization, we monitor all records in Chassis_Private so
- * that we don't try to recreate existing ones. */
- ovsdb_idl_condition_add_clause_true(&chprv);
- }
-
if (monitor_all) {
+ /* Monitor all Southbound tables unconditionally. Do that even for
+ * tables that could be easily filtered by chassis name (like
+ * Chassis_Private). That's because the current ovsdb-server
+ * implementation uses a cache whose efficiency significantly
+ * decreases when monitor conditions are present. */
ovsdb_idl_condition_add_clause_true(&pb);
ovsdb_idl_condition_add_clause_true(&lf);
ovsdb_idl_condition_add_clause_true(&mb);
@@ -293,6 +288,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
ovsdb_idl_condition_add_clause_true(&ce);
ovsdb_idl_condition_add_clause_true(&ip_mcast);
ovsdb_idl_condition_add_clause_true(&igmp);
+ ovsdb_idl_condition_add_clause_true(&chprv);
ovsdb_idl_condition_add_clause_true(&tv);
ovsdb_idl_condition_add_clause_true(&nh);
ovsdb_idl_condition_add_clause_true(&ar);
@@ -331,9 +327,16 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
sbrec_igmp_group_add_clause_chassis(&igmp, OVSDB_F_EQ,
&chassis->header_.uuid);
+ /* Monitors Chassis_Private record for current chassis only. */
+ sbrec_chassis_private_add_clause_name(&chprv, OVSDB_F_EQ,
+ chassis->name);
+
sbrec_chassis_template_var_add_clause_chassis(&tv, OVSDB_F_EQ,
chassis->name);
} else {
+ /* During initialization, we monitor all records in Chassis_Private so
+ * that we don't try to recreate existing ones. */
+ ovsdb_idl_condition_add_clause_true(&chprv);
/* Also, to avoid traffic disruption (e.g., conntrack flushing for
* zones that are used by OVN but not yet known due to the SB initial
* contents not being available), monitor all port bindings
@@ -712,8 +715,7 @@ static void
update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl,
bool *monitor_all_p, bool *reset_ovnsb_idl_min_index,
struct controller_engine_ctx *ctx,
- unsigned int *sb_cond_seqno,
- struct ovsdb_idl_index *sbrec_chassis_by_name)
+ unsigned int *sb_cond_seqno)
{
const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
if (!cfg) {
@@ -739,18 +741,12 @@ update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl
*ovnsb_idl,
get_chassis_external_id_value_bool(
&cfg->external_ids, chassis_id, "ovn-monitor-all", false);
if (monitor_all) {
- const struct sbrec_chassis *chassis = NULL;
- if (chassis_id && sbrec_chassis_by_name) {
- chassis =
- chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
- }
-
/* Always call update_sb_monitors when monitor_all is true.
* Otherwise, don't call it here, because there would be unnecessary
* extra cost. Instead, it is called after the engine execution only
* when it is necessary. */
unsigned int next_cond_seqno =
- update_sb_monitors(ovnsb_idl, chassis, NULL, NULL, NULL, true);
+ update_sb_monitors(ovnsb_idl, NULL, NULL, NULL, NULL, true);
if (sb_cond_seqno) {
*sb_cond_seqno = next_cond_seqno;
}
@@ -6044,8 +6040,7 @@ main(int argc, char *argv[])
update_sb_db(ovs_idl_loop.idl, ovnsb_idl_loop.idl, &sb_monitor_all,
&reset_ovnsb_idl_min_index,
- &ctrl_engine_ctx, &ovnsb_expected_cond_seqno,
- sbrec_chassis_by_name);
+ &ctrl_engine_ctx, &ovnsb_expected_cond_seqno);
update_ssl_config(ovsrec_ssl_table_get(ovs_idl_loop.idl));
struct ovsdb_idl_txn *ovnsb_idl_txn
@@ -6532,7 +6527,7 @@ loop_done:
bool done = !ovsdb_idl_has_ever_connected(ovnsb_idl_loop.idl);
while (!done) {
update_sb_db(ovs_idl_loop.idl, ovnsb_idl_loop.idl,
- NULL, NULL, NULL, NULL, sbrec_chassis_by_name);
+ NULL, NULL, NULL, NULL);
update_ssl_config(ovsrec_ssl_table_get(ovs_idl_loop.idl));
struct ovsdb_idl_txn *ovs_idl_txn
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index 47f48d8b4c..6561e177f6 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -484,10 +484,11 @@ OVN_CLEANUP([hv])
AT_CLEANUP
])
-# Checks that ovn-controller increments the nb_cfg value in the
Chassis_Private table
-# and each hv doesn't exchange messages of update of Chassis_Private table
-OVN_FOR_EACH_NORTHD([
-AT_SETUP([ovn-controller - Bump Chassis_Private nb_cfg value with Monitor All])
+# Checks that when ovn-controller increments the nb_cfg value in the
+# Chassis_Private table each hv receives Chassis_Private update messages.
+# NOTE: Only run this test once, it's relevant only for the case when
+# monitor_all is set to 'true'.
+AT_SETUP([ovn-controller - Chassis_Private processing with conditional
monitoring disabled])
AT_KEYWORDS([ovn])
ovn_start
@@ -502,34 +503,36 @@ as hv2
check ovs-vsctl add-br br-phys
ovn_attach n1 br-phys 192.168.0.12
-as hv1 ovs-vsctl set open . external_ids:ovn-monitor-all=true
-as hv2 ovs-vsctl set open . external_ids:ovn-monitor-all=true
+as hv1
+check ovs-vsctl set open . external_ids:ovn-monitor-all=true
+as hv2
+check ovs-vsctl set open . external_ids:ovn-monitor-all=true
# Wait until ovn-monitor-all is processed by ovn-controller.
wait_row_count Chassis 1 name=hv1 other_config:ovn-monitor-all=true
wait_row_count Chassis 1 name=hv2 other_config:ovn-monitor-all=true
# Enable debug for check the received messages.
-as hv1 ovn-appctl -t ovn-controller vlog/set dbg
-as hv2 ovn-appctl -t ovn-controller vlog/set dbg
+as hv1
+check ovn-appctl -t ovn-controller vlog/set dbg
+as hv2
+check ovn-appctl -t ovn-controller vlog/set dbg
# Bump the NB_Global nb_cfg value.
-check ovn-nbctl set NB_Global . nb_cfg=999
+check ovn-nbctl --wait=hv sync
-# ovn-controller should bump the nb_cfg in the chassis_private table.
-wait_row_count Chassis_Private 1 name=hv1 nb_cfg=999
-wait_row_count Chassis_Private 1 name=hv2 nb_cfg=999
+nb_cfg=$(fetch_column nb:NB_Global options:nb_cfg)
-AT_CHECK([grep -c 'Chassis_Private.*nb_cfg":999' hv1/ovn-controller.log], [0],
[dnl
-1
+# Both chassis should receive all Chassis_Private notifications.
+AT_CHECK([grep -c "Chassis_Private.*nb_cfg\":${nb_cfg}"
hv1/ovn-controller.log], [0], [dnl
+2
])
-AT_CHECK([grep -c 'Chassis_Private.*nb_cfg":999' hv2/ovn-controller.log], [0],
[dnl
-1
+AT_CHECK([grep -c "Chassis_Private.*nb_cfg\":${nb_cfg}"
hv2/ovn-controller.log], [0], [dnl
+2
])
OVN_CLEANUP([hv1],[hv2])
AT_CLEANUP
-])
# check that nb_cfg overflow cases handled properly
AT_SETUP([ovn-controller - overflow the nb_cfg value across the tables])
--
2.48.1
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev