On Thu, Feb 1, 2024 at 10:13 AM Numan Siddique <[email protected]> wrote:
>
> On Tue, Jan 30, 2024 at 4:25 PM <[email protected]> wrote:
> >
> > From: Numan Siddique <[email protected]>
> >
> > A new engine node "global_config" is added which handles the changes
> > to NB_Global an SB_Global tables. It also creates these rows if
> > not present.
> >
> > Without the I-P, any changes to the options column of these tables
> > result in recompute of 'northd' and 'lflow' engine nodes.
> >
> > Acked-by: Dumitru Ceara <[email protected]>
> > Acked-by: Han Zhou <[email protected]>
> > Signed-off-by: Numan Siddique <[email protected]>
>
> Recheck-request: github-robot-_Build_and_Test
Recheck-request: github-robot-_Build_and_Test
>
> > ---
> > northd/aging.c | 21 +-
> > northd/automake.mk | 2 +
> > northd/en-global-config.c | 576 ++++++++++++++++++++++++++++++++++++++
> > northd/en-global-config.h | 65 +++++
> > northd/en-lflow.c | 11 +-
> > northd/en-northd.c | 52 ++--
> > northd/en-northd.h | 2 +-
> > northd/en-sync-sb.c | 21 +-
> > northd/inc-proc-northd.c | 38 ++-
> > northd/northd.c | 230 +++------------
> > northd/northd.h | 24 +-
> > tests/ovn-northd.at | 256 +++++++++++++++--
> > 12 files changed, 1001 insertions(+), 297 deletions(-)
> > create mode 100644 northd/en-global-config.c
> > create mode 100644 northd/en-global-config.h
> >
> > diff --git a/northd/aging.c b/northd/aging.c
> > index cdf5f4464e..b76963a2dd 100644
> > --- a/northd/aging.c
> > +++ b/northd/aging.c
> > @@ -15,6 +15,7 @@
> >
> > #include <config.h>
> >
> > +#include "en-global-config.h"
> > #include "lib/inc-proc-eng.h"
> > #include "lib/ovn-nb-idl.h"
> > #include "lib/ovn-sb-idl.h"
> > @@ -347,15 +348,10 @@ aging_context_handle_timestamp(struct aging_context
> > *ctx, int64_t timestamp,
> > static uint32_t
> > get_removal_limit(struct engine_node *node, const char *name)
> > {
> > - const struct nbrec_nb_global_table *nb_global_table =
> > - EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
> > - const struct nbrec_nb_global *nb =
> > - nbrec_nb_global_table_first(nb_global_table);
> > - if (!nb) {
> > - return 0;
> > - }
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> >
> > - return smap_get_uint(&nb->options, name, 0);
> > + return smap_get_uint(&global_config->nb_options, name, 0);
> > }
> >
> > /* MAC binding aging */
> > @@ -394,11 +390,14 @@ en_mac_binding_aging_run(struct engine_node *node,
> > void *data OVS_UNUSED)
> > {
> > const struct engine_context *eng_ctx = engine_get_context();
> > struct northd_data *northd_data = engine_get_input_data("northd",
> > node);
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > +
> > struct aging_waker *waker =
> > engine_get_input_data("mac_binding_aging_waker", node);
> >
> > if (!eng_ctx->ovnsb_idl_txn ||
> > - !northd_data->features.mac_binding_timestamp ||
> > + !global_config->features.mac_binding_timestamp ||
> > time_msec() < waker->next_wake_msec) {
> > return;
> > }
> > @@ -530,9 +529,11 @@ en_fdb_aging_run(struct engine_node *node, void *data
> > OVS_UNUSED)
> > const struct engine_context *eng_ctx = engine_get_context();
> > struct northd_data *northd_data = engine_get_input_data("northd",
> > node);
> > struct aging_waker *waker = engine_get_input_data("fdb_aging_waker",
> > node);
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> >
> > if (!eng_ctx->ovnsb_idl_txn ||
> > - !northd_data->features.fdb_timestamp ||
> > + !global_config->features.fdb_timestamp ||
> > time_msec() < waker->next_wake_msec) {
> > return;
> > }
> > diff --git a/northd/automake.mk b/northd/automake.mk
> > index 19abb0dece..d491973a8b 100644
> > --- a/northd/automake.mk
> > +++ b/northd/automake.mk
> > @@ -8,6 +8,8 @@ northd_ovn_northd_SOURCES = \
> > northd/northd.c \
> > northd/northd.h \
> > northd/ovn-northd.c \
> > + northd/en-global-config.c \
> > + northd/en-global-config.h \
> > northd/en-northd.c \
> > northd/en-northd.h \
> > northd/en-lflow.c \
> > diff --git a/northd/en-global-config.c b/northd/en-global-config.c
> > new file mode 100644
> > index 0000000000..9ac5faf995
> > --- /dev/null
> > +++ b/northd/en-global-config.c
> > @@ -0,0 +1,576 @@
> > +/*
> > + * Licensed under the Apache License, Version 2.0 (the "License");
> > + * you may not use this file except in compliance with the License.
> > + * You may obtain a copy of the License at:
> > + *
> > + * http://www.apache.org/licenses/LICENSE-2.0
> > + *
> > + * Unless required by applicable law or agreed to in writing, software
> > + * distributed under the License is distributed on an "AS IS" BASIS,
> > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> > + * See the License for the specific language governing permissions and
> > + * limitations under the License.
> > + */
> > +
> > +#include <config.h>
> > +
> > +#include <getopt.h>
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +
> > +/* OVS includes */
> > +#include "openvswitch/vlog.h"
> > +
> > +/* OVN includes */
> > +#include "debug.h"
> > +#include "en-global-config.h"
> > +#include "include/ovn/features.h"
> > +#include "ipam.h"
> > +#include "lib/ovn-nb-idl.h"
> > +#include "lib/ovn-sb-idl.h"
> > +#include "northd.h"
> > +
> > +
> > +VLOG_DEFINE_THIS_MODULE(en_global_config);
> > +
> > +/* static function declarations. */
> > +static void northd_enable_all_features(struct ed_type_global_config *);
> > +static void build_chassis_features(const struct sbrec_chassis_table *,
> > + struct chassis_features *);
> > +static bool chassis_features_changed(const struct chassis_features *,
> > + const struct chassis_features *);
> > +static bool config_out_of_sync(const struct smap *config,
> > + const struct smap *saved_config,
> > + const char *key, bool must_be_present);
> > +static bool check_nb_options_out_of_sync(const struct nbrec_nb_global *,
> > + struct ed_type_global_config *);
> > +static void update_sb_config_options_to_sbrec(struct ed_type_global_config
> > *,
> > + const struct sbrec_sb_global
> > *);
> > +
> > +void *
> > +en_global_config_init(struct engine_node *node OVS_UNUSED,
> > + struct engine_arg *args OVS_UNUSED)
> > +{
> > + struct ed_type_global_config *data = xzalloc(sizeof *data);
> > + smap_init(&data->nb_options);
> > + smap_init(&data->sb_options);
> > + northd_enable_all_features(data);
> > + return data;
> > +}
> > +
> > +void
> > +en_global_config_run(struct engine_node *node , void *data)
> > +{
> > + const struct engine_context *eng_ctx = engine_get_context();
> > + if (!eng_ctx->ovnnb_idl_txn || !eng_ctx->ovnsb_idl_txn) {
> > + return;
> > + }
> > +
> > + const struct nbrec_nb_global_table *nb_global_table =
> > + EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
> > + const struct sbrec_sb_global_table *sb_global_table =
> > + EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
> > + const struct sbrec_chassis_table *sbrec_chassis_table =
> > + EN_OVSDB_GET(engine_get_input("SB_chassis", node));
> > +
> > + struct ed_type_global_config *config_data = data;
> > +
> > + /* Sync ipsec configuration.
> > + * Copy nb_cfg from northbound to southbound database.
> > + * Also set up to update sb_cfg once our southbound transaction
> > commits. */
> > + const struct nbrec_nb_global *nb =
> > + nbrec_nb_global_table_first(nb_global_table);
> > + if (!nb) {
> > + nb = nbrec_nb_global_insert(eng_ctx->ovnnb_idl_txn);
> > + }
> > +
> > + const char *mac_addr_prefix = set_mac_prefix(smap_get(&nb->options,
> > + "mac_prefix"));
> > +
> > + const char *monitor_mac = smap_get(&nb->options, "svc_monitor_mac");
> > + if (monitor_mac) {
> > + if (eth_addr_from_string(monitor_mac,
> > + &config_data->svc_monitor_mac_ea)) {
> > + snprintf(config_data->svc_monitor_mac,
> > + sizeof config_data->svc_monitor_mac,
> > + ETH_ADDR_FMT,
> > + ETH_ADDR_ARGS(config_data->svc_monitor_mac_ea));
> > + } else {
> > + monitor_mac = NULL;
> > + }
> > + }
> > +
> > + struct smap *options = &config_data->nb_options;
> > + smap_destroy(options);
> > + smap_clone(options, &nb->options);
> > +
> > + smap_replace(options, "mac_prefix", mac_addr_prefix);
> > +
> > + if (!monitor_mac) {
> > + eth_addr_random(&config_data->svc_monitor_mac_ea);
> > + snprintf(config_data->svc_monitor_mac,
> > + sizeof config_data->svc_monitor_mac, ETH_ADDR_FMT,
> > + ETH_ADDR_ARGS(config_data->svc_monitor_mac_ea));
> > + smap_replace(options, "svc_monitor_mac",
> > + config_data->svc_monitor_mac);
> > + }
> > +
> > + char *max_tunid = xasprintf("%d",
> > + get_ovn_max_dp_key_local(sbrec_chassis_table));
> > + smap_replace(options, "max_tunid", max_tunid);
> > + free(max_tunid);
> > +
> > + char *ovn_internal_version = ovn_get_internal_version();
> > + if (strcmp(ovn_internal_version,
> > + smap_get_def(options, "northd_internal_version", ""))) {
> > + smap_replace(options, "northd_internal_version",
> > + ovn_internal_version);
> > + config_data->ovn_internal_version_changed = true;
> > + } else {
> > + config_data->ovn_internal_version_changed = false;
> > + }
> > +
> > + free(ovn_internal_version);
> > +
> > + if (!smap_equal(&nb->options, options)) {
> > + nbrec_nb_global_verify_options(nb);
> > + nbrec_nb_global_set_options(nb, options);
> > + }
> > +
> > + if (smap_get_bool(&nb->options, "ignore_chassis_features", false)) {
> > + northd_enable_all_features(config_data);
> > + } else {
> > + build_chassis_features(sbrec_chassis_table,
> > &config_data->features);
> > + }
> > +
> > + init_debug_config(nb);
> > +
> > + const struct sbrec_sb_global *sb =
> > + sbrec_sb_global_table_first(sb_global_table);
> > + if (!sb) {
> > + sb = sbrec_sb_global_insert(eng_ctx->ovnsb_idl_txn);
> > + }
> > + if (nb->ipsec != sb->ipsec) {
> > + sbrec_sb_global_set_ipsec(sb, nb->ipsec);
> > + }
> > +
> > + /* Set up SB_Global (depends on chassis features). */
> > + update_sb_config_options_to_sbrec(config_data, sb);
> > +
> > + engine_set_node_state(node, EN_UPDATED);
> > +}
> > +
> > +void en_global_config_cleanup(void *data OVS_UNUSED)
> > +{
> > + struct ed_type_global_config *config_data = data;
> > + smap_destroy(&config_data->nb_options);
> > + smap_destroy(&config_data->sb_options);
> > + destroy_debug_config();
> > +}
> > +
> > +void
> > +en_global_config_clear_tracked_data(void *data)
> > +{
> > + struct ed_type_global_config *config_data = data;
> > + config_data->tracked = false;
> > + config_data->tracked_data.nb_options_changed = false;
> > + config_data->tracked_data.chassis_features_changed = false;
> > +}
> > +
> > +bool
> > +global_config_nb_global_handler(struct engine_node *node, void *data)
> > +{
> > + const struct nbrec_nb_global_table *nb_global_table =
> > + EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
> > + const struct sbrec_sb_global_table *sb_global_table =
> > + EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
> > +
> > + const struct nbrec_nb_global *nb =
> > + nbrec_nb_global_table_first(nb_global_table);
> > + if (!nb) {
> > + return false;
> > + }
> > +
> > + const struct sbrec_sb_global *sb =
> > + sbrec_sb_global_table_first(sb_global_table);
> > + if (!sb) {
> > + return false;
> > + }
> > +
> > + /* We are only interested in ipsec and options column. */
> > + if (!nbrec_nb_global_is_updated(nb, NBREC_NB_GLOBAL_COL_IPSEC)
> > + && !nbrec_nb_global_is_updated(nb, NBREC_NB_GLOBAL_COL_OPTIONS)) {
> > + return true;
> > + }
> > +
> > + if (nb->ipsec != sb->ipsec) {
> > + sbrec_sb_global_set_ipsec(sb, nb->ipsec);
> > + }
> > +
> > + struct ed_type_global_config *config_data = data;
> > + config_data->tracked = true;
> > +
> > + if (smap_equal(&nb->options, &config_data->nb_options)) {
> > + return true;
> > + }
> > +
> > + /* Return false if an option is out of sync and requires updating the
> > + * NB config. (Like svc_monitor_mac, max_tunid and mac_prefix). */
> > + /* Check if svc_monitor_mac has changed or not. */
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "svc_monitor_mac", true)) {
> > + return false;
> > + }
> > +
> > + /* Check if max_tunid has changed or not. */
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "max_tunid", true)) {
> > + return false;
> > + }
> > +
> > + /* Check if mac_prefix has changed or not. */
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "mac_prefix", true)) {
> > + return false;
> > + }
> > +
> > + /* Check if ignore_chassis_features has changed or not. */
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "ignore_chassis_features", false)) {
> > + return false;
> > + }
> > +
> > + /* Check if northd_internal_version has changed or not. */
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "northd_internal_version", false)) {
> > + return false;
> > + }
> > +
> > + if (check_nb_options_out_of_sync(nb, config_data)) {
> > + config_data->tracked_data.nb_options_changed = true;
> > + }
> > +
> > + smap_destroy(&config_data->nb_options);
> > + smap_clone(&config_data->nb_options, &nb->options);
> > +
> > + update_sb_config_options_to_sbrec(config_data, sb);
> > +
> > + engine_set_node_state(node, EN_UPDATED);
> > + return true;
> > +}
> > +
> > +bool
> > +global_config_sb_global_handler(struct engine_node *node, void *data)
> > +{
> > + const struct sbrec_sb_global_table *sb_global_table =
> > + EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
> > +
> > + const struct sbrec_sb_global *sb =
> > + sbrec_sb_global_table_first(sb_global_table);
> > + if (!sb) {
> > + return false;
> > + }
> > +
> > + struct ed_type_global_config *config_data = data;
> > +
> > + if (!smap_equal(&sb->options, &config_data->sb_options)) {
> > + return false;
> > + }
> > +
> > + /* No need to update the engine node. */
> > + return true;
> > +}
> > +
> > +bool
> > +global_config_sb_chassis_handler(struct engine_node *node, void *data)
> > +{
> > + struct ed_type_global_config *config_data = data;
> > +
> > + const struct sbrec_chassis_table *sbrec_chassis_table =
> > + EN_OVSDB_GET(engine_get_input("SB_chassis", node));
> > + const struct sbrec_chassis *chassis;
> > +
> > + SBREC_CHASSIS_TABLE_FOR_EACH_TRACKED (chassis, sbrec_chassis_table) {
> > + if (sbrec_chassis_is_new(chassis)
> > + || sbrec_chassis_is_deleted(chassis)
> > + || sbrec_chassis_is_updated(chassis,
> > + SBREC_CHASSIS_COL_ENCAPS)) {
> > + return false;
> > + }
> > +
> > + for (size_t i = 0; i < chassis->n_encaps; i++) {
> > + if (sbrec_encap_row_get_seqno(chassis->encaps[i],
> > + OVSDB_IDL_CHANGE_MODIFY) > 0) {
> > + return false;
> > + }
> > + }
> > + }
> > +
> > + if (smap_get_bool(&config_data->nb_options, "ignore_chassis_features",
> > + false)) {
> > + return true;
> > + }
> > +
> > + bool reevaluate_chassis_features = false;
> > +
> > + /* Check and evaluate chassis features. */
> > + SBREC_CHASSIS_TABLE_FOR_EACH_TRACKED (chassis, sbrec_chassis_table) {
> > + if (sbrec_chassis_is_updated(chassis,
> > + SBREC_CHASSIS_COL_OTHER_CONFIG)) {
> > + reevaluate_chassis_features = true;
> > + break;
> > + }
> > + }
> > +
> > + if (!reevaluate_chassis_features) {
> > + return true;
> > + }
> > +
> > + struct chassis_features present_features = config_data->features;
> > +
> > + /* Enable all features before calling build_chassis_features() as
> > + * build_chassis_features() only sets the feature flags to false. */
> > + northd_enable_all_features(config_data);
> > + build_chassis_features(sbrec_chassis_table, &config_data->features);
> > +
> > + if (chassis_features_changed(&present_features,
> > &config_data->features)) {
> > + config_data->tracked_data.chassis_features_changed = true;
> > + config_data->tracked = true;
> > + engine_set_node_state(node, EN_UPDATED);
> > + }
> > +
> > + return true;
> > +}
> > +
> > +/* generic global config handler for any engine node which has
> > global_config
> > + * has an input node . */
> > +bool
> > +node_global_config_handler(struct engine_node *node, void *data OVS_UNUSED)
> > +{
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > +
> > + if (!global_config->tracked
> > + || global_config->tracked_data.chassis_features_changed
> > + || global_config->tracked_data.nb_options_changed) {
> > + return false;
> > + }
> > +
> > + return true;
> > +}
> > +
> > +/* static functions. */
> > +static void
> > +northd_enable_all_features(struct ed_type_global_config *data)
> > +{
> > + data->features = (struct chassis_features) {
> > + .ct_no_masked_label = true,
> > + .mac_binding_timestamp = true,
> > + .ct_lb_related = true,
> > + .fdb_timestamp = true,
> > + .ls_dpg_column = true,
> > + };
> > +}
> > +
> > +static void
> > +build_chassis_features(const struct sbrec_chassis_table
> > *sbrec_chassis_table,
> > + struct chassis_features *chassis_features)
> > +{
> > + const struct sbrec_chassis *chassis;
> > +
> > + SBREC_CHASSIS_TABLE_FOR_EACH (chassis, sbrec_chassis_table) {
> > + /* Only consider local AZ chassis. Remote ones don't install
> > + * flows generated by the local northd.
> > + */
> > + if (smap_get_bool(&chassis->other_config, "is-remote", false)) {
> > + continue;
> > + }
> > +
> > + bool ct_no_masked_label =
> > + smap_get_bool(&chassis->other_config,
> > + OVN_FEATURE_CT_NO_MASKED_LABEL,
> > + false);
> > + if (!ct_no_masked_label && chassis_features->ct_no_masked_label) {
> > + chassis_features->ct_no_masked_label = false;
> > + }
> > +
> > + bool mac_binding_timestamp =
> > + smap_get_bool(&chassis->other_config,
> > + OVN_FEATURE_MAC_BINDING_TIMESTAMP,
> > + false);
> > + if (!mac_binding_timestamp &&
> > + chassis_features->mac_binding_timestamp) {
> > + chassis_features->mac_binding_timestamp = false;
> > + }
> > +
> > + bool ct_lb_related =
> > + smap_get_bool(&chassis->other_config,
> > + OVN_FEATURE_CT_LB_RELATED,
> > + false);
> > + if (!ct_lb_related &&
> > + chassis_features->ct_lb_related) {
> > + chassis_features->ct_lb_related = false;
> > + }
> > +
> > + bool fdb_timestamp =
> > + smap_get_bool(&chassis->other_config,
> > + OVN_FEATURE_FDB_TIMESTAMP,
> > + false);
> > + if (!fdb_timestamp &&
> > + chassis_features->fdb_timestamp) {
> > + chassis_features->fdb_timestamp = false;
> > + }
> > +
> > + bool ls_dpg_column =
> > + smap_get_bool(&chassis->other_config,
> > + OVN_FEATURE_LS_DPG_COLUMN,
> > + false);
> > + if (!ls_dpg_column &&
> > + chassis_features->ls_dpg_column) {
> > + chassis_features->ls_dpg_column = false;
> > + }
> > + }
> > +}
> > +
> > +static bool
> > +config_out_of_sync(const struct smap *config, const struct smap
> > *saved_config,
> > + const char *key, bool must_be_present)
> > +{
> > + const char *value = smap_get(config, key);
> > + if (!value && must_be_present) {
> > + return true;
> > + }
> > +
> > + const char *saved_value = smap_get(saved_config, key);
> > + if (!saved_value && must_be_present) {
> > + return true;
> > + }
> > +
> > + if (!value && !saved_value) {
> > + return false;
> > + }
> > +
> > + if (!value || !saved_value) {
> > + return true;
> > + }
> > +
> > + return strcmp(value, saved_value);
> > +}
> > +
> > +static bool
> > +check_nb_options_out_of_sync(const struct nbrec_nb_global *nb,
> > + struct ed_type_global_config *config_data)
> > +{
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "mac_binding_removal_limit", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "fdb_removal_limit", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "controller_event", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "ignore_lsp_down", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "use_ct_inv_match", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "default_acl_drop", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "debug_drop_domain_id", false)) {
> > + init_debug_config(nb);
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "debug_drop_collector_set", false)) {
> > + init_debug_config(nb);
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "use_common_zone", false)) {
> > + return true;
> > + }
> > +
> > + if (config_out_of_sync(&nb->options, &config_data->nb_options,
> > + "install_ls_lb_from_router", false)) {
> > + return true;
> > + }
> > +
> > + return false;
> > +}
> > +
> > +static void
> > +update_sb_config_options_to_sbrec(struct ed_type_global_config
> > *config_data,
> > + const struct sbrec_sb_global *sb)
> > +{
> > + struct smap *options = &config_data->sb_options;
> > +
> > + smap_destroy(options);
> > + smap_clone(options, &config_data->nb_options);
> > +
> > + /* Inform ovn-controllers whether LB flows will use ct_mark (i.e., only
> > + * if all chassis support it). If not explicitly present in the
> > database
> > + * the default value to be used for this option is 'true'.
> > + */
> > + if (!config_data->features.ct_no_masked_label) {
> > + smap_replace(options, "lb_hairpin_use_ct_mark", "false");
> > + } else {
> > + smap_remove(options, "lb_hairpin_use_ct_mark");
> > + }
> > +
> > + /* Hackaround SB_global.options overwrite by NB_Global.options for
> > + * 'sbctl_probe_interval' option.
> > + */
> > + const char *sip = smap_get(&sb->options, "sbctl_probe_interval");
> > + if (sip) {
> > + smap_replace(options, "sbctl_probe_interval", sip);
> > + }
> > +
> > + if (!smap_equal(&sb->options, options)) {
> > + sbrec_sb_global_set_options(sb, options);
> > + }
> > +}
> > +
> > +static bool
> > +chassis_features_changed(const struct chassis_features *present,
> > + const struct chassis_features *updated)
> > +{
> > + if (present->ct_no_masked_label != updated->ct_no_masked_label) {
> > + return true;
> > + }
> > +
> > + if (present->mac_binding_timestamp != updated->mac_binding_timestamp) {
> > + return true;
> > + }
> > +
> > + if (present->ct_lb_related != updated->ct_lb_related) {
> > + return true;
> > + }
> > +
> > + if (present->fdb_timestamp != updated->fdb_timestamp) {
> > + return true;
> > + }
> > +
> > + if (present->ls_dpg_column != updated->ls_dpg_column) {
> > + return true;
> > + }
> > +
> > + return false;
> > +}
> > diff --git a/northd/en-global-config.h b/northd/en-global-config.h
> > new file mode 100644
> > index 0000000000..436bc7fa35
> > --- /dev/null
> > +++ b/northd/en-global-config.h
> > @@ -0,0 +1,65 @@
> > +#ifndef EN_GLOBAL_CONFIG_H
> > +#define EN_GLOBAL_CONFIG_H 1
> > +
> > +#include <config.h>
> > +
> > +/* OVS includes. */
> > +#include "lib/packets.h"
> > +#include "lib/smap.h"
> > +
> > +/* OVN includes. */
> > +#include "lib/inc-proc-eng.h"
> > +
> > +struct nbrec_nb_global;
> > +struct sbrec_sb_global;
> > +
> > +struct chassis_features {
> > + bool ct_no_masked_label;
> > + bool mac_binding_timestamp;
> > + bool ct_lb_related;
> > + bool fdb_timestamp;
> > + bool ls_dpg_column;
> > +};
> > +
> > +struct global_config_tracked_data {
> > + bool nb_options_changed;
> > + bool chassis_features_changed;
> > +};
> > +
> > +/* struct which maintains the data of the engine node global_config. */
> > +struct ed_type_global_config {
> > + struct smap nb_options;
> > + struct smap sb_options;
> > + const struct nbrec_nb_global *nb_global;
> > + const struct sbrec_sb_global *sb_global;
> > +
> > + /* MAC allocated for service monitor usage. Just one mac is allocated
> > + * for this purpose and ovn-controller's on each chassis will make use
> > + * of this mac when sending out the packets to monitor the services
> > + * defined in Service_Monitor Southbound table. Since these packets
> > + * are locally handled, having just one mac is good enough. */
> > + char svc_monitor_mac[ETH_ADDR_STRLEN + 1];
> > + struct eth_addr svc_monitor_mac_ea;
> > +
> > + struct chassis_features features;
> > +
> > + bool ovn_internal_version_changed;
> > +
> > + bool tracked;
> > + struct global_config_tracked_data tracked_data;
> > +};
> > +
> > +void *en_global_config_init(struct engine_node *, struct engine_arg *);
> > +void en_global_config_run(struct engine_node *, void *data);
> > +void en_global_config_cleanup(void *data);
> > +void en_global_config_clear_tracked_data(void *data);
> > +
> > +bool global_config_nb_global_handler(struct engine_node *, void *data);
> > +bool global_config_sb_global_handler(struct engine_node *, void *data);
> > +bool global_config_sb_chassis_handler(struct engine_node *, void *data);
> > +
> > +/* generic global config handler for any engine node which has
> > global_config
> > + * has an input node . */
> > +bool node_global_config_handler(struct engine_node *, void *data);
> > +
> > +#endif /* EN_GLOBAL_CONFIG_H */
> > diff --git a/northd/en-lflow.c b/northd/en-lflow.c
> > index 525453054b..f1a83839df 100644
> > --- a/northd/en-lflow.c
> > +++ b/northd/en-lflow.c
> > @@ -18,6 +18,7 @@
> > #include <stdlib.h>
> > #include <stdio.h>
> >
> > +#include "en-global-config.h"
> > #include "en-lflow.h"
> > #include "en-lr-nat.h"
> > #include "en-lr-stateful.h"
> > @@ -77,10 +78,14 @@ lflow_get_input_data(struct engine_node *node,
> > lflow_input->meter_groups = &sync_meters_data->meter_groups;
> > lflow_input->lb_datapaths_map = &northd_data->lb_datapaths_map;
> > lflow_input->svc_monitor_map = &northd_data->svc_monitor_map;
> > - lflow_input->features = &northd_data->features;
> > - lflow_input->ovn_internal_version_changed =
> > - northd_data->ovn_internal_version_changed;
> > lflow_input->bfd_connections = NULL;
> > +
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > + lflow_input->features = &global_config->features;
> > + lflow_input->ovn_internal_version_changed =
> > + global_config->ovn_internal_version_changed;
> > + lflow_input->svc_monitor_mac = global_config->svc_monitor_mac;
> > }
> >
> > void en_lflow_run(struct engine_node *node, void *data)
> > diff --git a/northd/en-northd.c b/northd/en-northd.c
> > index 5143603f39..4479b4aff2 100644
> > --- a/northd/en-northd.c
> > +++ b/northd/en-northd.c
> > @@ -19,6 +19,7 @@
> > #include <stdio.h>
> >
> > #include "coverage.h"
> > +#include "en-global-config.h"
> > #include "en-northd.h"
> > #include "en-lb-data.h"
> > #include "lib/inc-proc-eng.h"
> > @@ -65,8 +66,6 @@ northd_get_input_data(struct engine_node *node,
> > engine_get_input("SB_fdb", node),
> > "sbrec_fdb_by_dp_and_port");
> >
> > - input_data->nbrec_nb_global_table =
> > - EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
> > input_data->nbrec_logical_switch_table =
> > EN_OVSDB_GET(engine_get_input("NB_logical_switch", node));
> > input_data->nbrec_logical_router_table =
> > @@ -78,8 +77,6 @@ northd_get_input_data(struct engine_node *node,
> > input_data->nbrec_mirror_table =
> > EN_OVSDB_GET(engine_get_input("NB_mirror", node));
> >
> > - input_data->sbrec_sb_global_table =
> > - EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
> > input_data->sbrec_datapath_binding_table =
> > EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node));
> > input_data->sbrec_port_binding_table =
> > @@ -109,6 +106,14 @@ northd_get_input_data(struct engine_node *node,
> > engine_get_input_data("lb_data", node);
> > input_data->lbs = &lb_data->lbs;
> > input_data->lbgrps = &lb_data->lbgrps;
> > +
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > + input_data->nb_options = &global_config->nb_options;
> > + input_data->sb_options = &global_config->sb_options;
> > + input_data->svc_monitor_mac = global_config->svc_monitor_mac;
> > + input_data->svc_monitor_mac_ea = global_config->svc_monitor_mac_ea;
> > + input_data->features = &global_config->features;
> > }
> >
> > void
> > @@ -129,31 +134,6 @@ en_northd_run(struct engine_node *node, void *data)
> > eng_ctx->ovnsb_idl_txn);
> > stopwatch_stop(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());
> > engine_set_node_state(node, EN_UPDATED);
> > -
> > -}
> > -
> > -bool
> > -northd_nb_nb_global_handler(struct engine_node *node,
> > - void *data OVS_UNUSED)
> > -{
> > - const struct nbrec_nb_global_table *nb_global_table
> > - = EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
> > -
> > - const struct nbrec_nb_global *nb =
> > - nbrec_nb_global_table_first(nb_global_table);
> > -
> > - if (!nb) {
> > - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> > - VLOG_WARN_RL(&rl, "NB_Global is updated but has no record.");
> > - return false;
> > - }
> > -
> > - /* We care about the 'options' and 'ipsec' columns only. */
> > - if (nbrec_nb_global_is_updated(nb, NBREC_NB_GLOBAL_COL_OPTIONS) ||
> > - nbrec_nb_global_is_updated(nb, NBREC_NB_GLOBAL_COL_IPSEC)) {
> > - return false;
> > - }
> > - return true;
> > }
> >
> > bool
> > @@ -242,6 +222,20 @@ northd_lb_data_handler(struct engine_node *node, void
> > *data)
> > return true;
> > }
> >
> > +bool
> > +northd_global_config_handler(struct engine_node *node, void *data
> > OVS_UNUSED)
> > +{
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > +
> > + if (!global_config->tracked
> > + || global_config->tracked_data.nb_options_changed) {
> > + return false;
> > + }
> > +
> > + return true;
> > +}
> > +
> > void
> > *en_northd_init(struct engine_node *node OVS_UNUSED,
> > struct engine_arg *arg OVS_UNUSED)
> > diff --git a/northd/en-northd.h b/northd/en-northd.h
> > index 5a88871760..9b7bda32aa 100644
> > --- a/northd/en-northd.h
> > +++ b/northd/en-northd.h
> > @@ -14,7 +14,7 @@ void *en_northd_init(struct engine_node *node OVS_UNUSED,
> > struct engine_arg *arg);
> > void en_northd_cleanup(void *data);
> > void en_northd_clear_tracked_data(void *data);
> > -bool northd_nb_nb_global_handler(struct engine_node *, void *data
> > OVS_UNUSED);
> > +bool northd_global_config_handler(struct engine_node *, void *data
> > OVS_UNUSED);
> > bool northd_nb_logical_switch_handler(struct engine_node *, void *data);
> > bool northd_nb_logical_router_handler(struct engine_node *, void *data);
> > bool northd_sb_port_binding_handler(struct engine_node *, void *data);
> > diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
> > index 9002729b39..9bd8a1fc61 100644
> > --- a/northd/en-sync-sb.c
> > +++ b/northd/en-sync-sb.c
> > @@ -24,6 +24,7 @@
> >
> > /* OVN includes. */
> > #include "en-lr-nat.h"
> > +#include "en-global-config.h"
> > #include "en-lr-stateful.h"
> > #include "en-sync-sb.h"
> > #include "lb.h"
> > @@ -47,7 +48,8 @@ static void sync_addr_sets(struct ovsdb_idl_txn
> > *ovnsb_txn,
> > const struct nbrec_port_group_table *,
> > const struct sbrec_address_set_table *,
> > const struct lr_stateful_table *,
> > - const struct ovn_datapaths *);
> > + const struct ovn_datapaths *,
> > + const char *svc_monitor_macp);
> > static const struct sbrec_address_set *sb_address_set_lookup_by_name(
> > struct ovsdb_idl_index *, const char *name);
> > static void update_sb_addr_set(struct sorted_array *,
> > @@ -96,10 +98,13 @@ en_sync_to_sb_addr_set_run(struct engine_node *node,
> > void *data OVS_UNUSED)
> > const struct ed_type_lr_stateful *lr_stateful_data =
> > engine_get_input_data("lr_stateful", node);
> > struct northd_data *northd_data = engine_get_input_data("northd",
> > node);
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > sync_addr_sets(eng_ctx->ovnsb_idl_txn, nb_address_set_table,
> > nb_port_group_table, sb_address_set_table,
> > &lr_stateful_data->table,
> > - &northd_data->lr_datapaths);
> > + &northd_data->lr_datapaths,
> > + global_config->svc_monitor_mac);
> >
> > engine_set_node_state(node, EN_UPDATED);
> > }
> > @@ -283,6 +288,8 @@ en_sync_to_sb_lb_run(struct engine_node *node, void
> > *data_)
> > EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
> > const struct sbrec_logical_dp_group_table *sb_dpgrp_table =
> > EN_OVSDB_GET(engine_get_input("SB_logical_dp_group", node));
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > const struct engine_context *eng_ctx = engine_get_context();
> > struct ed_type_sync_to_sb_lb_data *data = data_;
> >
> > @@ -293,7 +300,7 @@ en_sync_to_sb_lb_run(struct engine_node *node, void
> > *data_)
> > &northd_data->lb_datapaths_map,
> > &northd_data->ls_datapaths,
> > &northd_data->lr_datapaths,
> > - &northd_data->features);
> > + &global_config->features);
> >
> > engine_set_node_state(node, EN_UPDATED);
> > }
> > @@ -324,12 +331,14 @@ sync_to_sb_lb_northd_handler(struct engine_node
> > *node, void *data_)
> > EN_OVSDB_GET(engine_get_input("SB_logical_dp_group", node));
> > const struct sbrec_load_balancer_table *sb_lb_table =
> > EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
> > + struct ed_type_global_config *global_config =
> > + engine_get_input_data("global_config", node);
> > struct ed_type_sync_to_sb_lb_data *data = data_;
> >
> > if (!sync_changed_lbs(&data->sb_lbs, eng_ctx->ovnsb_idl_txn,
> > sb_lb_table,
> > sb_dpgrp_table, &nd->trk_data.trk_lbs,
> > &nd->ls_datapaths, &nd->lr_datapaths,
> > - &nd->features)) {
> > + &global_config->features)) {
> > return false;
> > }
> >
> > @@ -455,7 +464,8 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
> > const struct nbrec_port_group_table *nb_port_group_table,
> > const struct sbrec_address_set_table *sb_address_set_table,
> > const struct lr_stateful_table *lr_statefuls,
> > - const struct ovn_datapaths *lr_datapaths)
> > + const struct ovn_datapaths *lr_datapaths,
> > + const char *svc_monitor_macp)
> > {
> > struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets);
> >
> > @@ -466,7 +476,6 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
> > }
> >
> > /* Service monitor MAC. */
> > - const char *svc_monitor_macp = northd_get_svc_monitor_mac();
> > struct sorted_array svc = sorted_array_create(&svc_monitor_macp, 1,
> > false);
> > sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets);
> > sorted_array_destroy(&svc);
> > diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
> > index d215c7792b..e1073812c8 100644
> > --- a/northd/inc-proc-northd.c
> > +++ b/northd/inc-proc-northd.c
> > @@ -30,6 +30,7 @@
> > #include "openvswitch/poll-loop.h"
> > #include "openvswitch/vlog.h"
> > #include "inc-proc-northd.h"
> > +#include "en-global-config.h"
> > #include "en-lb-data.h"
> > #include "en-lr-stateful.h"
> > #include "en-lr-nat.h"
> > @@ -149,6 +150,7 @@ static ENGINE_NODE(fdb_aging, "fdb_aging");
> > static ENGINE_NODE(fdb_aging_waker, "fdb_aging_waker");
> > static ENGINE_NODE(sync_to_sb_lb, "sync_to_sb_lb");
> > static ENGINE_NODE(sync_to_sb_pb, "sync_to_sb_pb");
> > +static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(global_config, "global_config");
> > static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lb_data, "lb_data");
> > static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lr_nat, "lr_nat");
> > static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lr_stateful, "lr_stateful");
> > @@ -168,11 +170,17 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > engine_add_input(&en_lb_data, &en_nb_logical_router,
> > lb_data_logical_router_handler);
> >
> > + engine_add_input(&en_global_config, &en_nb_nb_global,
> > + global_config_nb_global_handler);
> > + engine_add_input(&en_global_config, &en_sb_sb_global,
> > + global_config_sb_global_handler);
> > + engine_add_input(&en_global_config, &en_sb_chassis,
> > + global_config_sb_chassis_handler);
> > +
> > engine_add_input(&en_northd, &en_nb_mirror, NULL);
> > engine_add_input(&en_northd, &en_nb_static_mac_binding, NULL);
> > engine_add_input(&en_northd, &en_nb_chassis_template_var, NULL);
> >
> > - engine_add_input(&en_northd, &en_sb_sb_global, NULL);
> > engine_add_input(&en_northd, &en_sb_chassis, NULL);
> > engine_add_input(&en_northd, &en_sb_mirror, NULL);
> > engine_add_input(&en_northd, &en_sb_meter, NULL);
> > @@ -184,6 +192,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > engine_add_input(&en_northd, &en_sb_fdb, NULL);
> > engine_add_input(&en_northd, &en_sb_static_mac_binding, NULL);
> > engine_add_input(&en_northd, &en_sb_chassis_template_var, NULL);
> > + engine_add_input(&en_northd, &en_global_config,
> > + northd_global_config_handler);
> >
> > /* northd engine node uses the sb mac binding table to
> > * cleanup mac binding entries for deleted logical ports
> > @@ -198,8 +208,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> >
> > engine_add_input(&en_northd, &en_sb_port_binding,
> > northd_sb_port_binding_handler);
> > - engine_add_input(&en_northd, &en_nb_nb_global,
> > - northd_nb_nb_global_handler);
> > engine_add_input(&en_northd, &en_nb_logical_switch,
> > northd_nb_logical_switch_handler);
> > engine_add_input(&en_northd, &en_nb_logical_router,
> > @@ -217,15 +225,17 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > engine_add_input(&en_ls_stateful, &en_port_group,
> > ls_stateful_port_group_handler);
> >
> > - engine_add_input(&en_mac_binding_aging, &en_nb_nb_global, NULL);
> > engine_add_input(&en_mac_binding_aging, &en_sb_mac_binding, NULL);
> > engine_add_input(&en_mac_binding_aging, &en_northd, NULL);
> > engine_add_input(&en_mac_binding_aging, &en_mac_binding_aging_waker,
> > NULL);
> > + engine_add_input(&en_mac_binding_aging, &en_global_config,
> > + node_global_config_handler);
> >
> > - engine_add_input(&en_fdb_aging, &en_nb_nb_global, NULL);
> > engine_add_input(&en_fdb_aging, &en_sb_fdb, NULL);
> > engine_add_input(&en_fdb_aging, &en_northd, NULL);
> > engine_add_input(&en_fdb_aging, &en_fdb_aging_waker, NULL);
> > + engine_add_input(&en_fdb_aging, &en_global_config,
> > + node_global_config_handler);
> >
> > engine_add_input(&en_sync_meters, &en_nb_acl, NULL);
> > engine_add_input(&en_sync_meters, &en_nb_meter, NULL);
> > @@ -239,18 +249,22 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > engine_add_input(&en_lflow, &en_sb_multicast_group, NULL);
> > engine_add_input(&en_lflow, &en_sb_igmp_group, NULL);
> > engine_add_input(&en_lflow, &en_sb_logical_dp_group, NULL);
> > + engine_add_input(&en_lflow, &en_global_config,
> > + node_global_config_handler);
> > engine_add_input(&en_lflow, &en_northd, lflow_northd_handler);
> > engine_add_input(&en_lflow, &en_port_group, lflow_port_group_handler);
> > engine_add_input(&en_lflow, &en_lr_stateful,
> > lflow_lr_stateful_handler);
> > engine_add_input(&en_lflow, &en_ls_stateful,
> > lflow_ls_stateful_handler);
> >
> > + engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL);
> > + engine_add_input(&en_sync_to_sb_addr_set, &en_lr_stateful, NULL);
> > + engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL);
> > engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set,
> > sync_to_sb_addr_set_nb_address_set_handler);
> > engine_add_input(&en_sync_to_sb_addr_set, &en_nb_port_group,
> > sync_to_sb_addr_set_nb_port_group_handler);
> > - engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL);
> > - engine_add_input(&en_sync_to_sb_addr_set, &en_lr_stateful, NULL);
> > - engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL);
> > + engine_add_input(&en_sync_to_sb_addr_set, &en_global_config,
> > + node_global_config_handler);
> >
> > engine_add_input(&en_port_group, &en_nb_port_group,
> > port_group_nb_port_group_handler);
> > @@ -260,6 +274,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > * table too (because of the explicit dependency in the schema). */
> > engine_add_input(&en_port_group, &en_northd, engine_noop_handler);
> >
> > + engine_add_input(&en_sync_to_sb_lb, &en_global_config,
> > + node_global_config_handler);
> > engine_add_input(&en_sync_to_sb_lb, &en_northd,
> > sync_to_sb_lb_northd_handler);
> > engine_add_input(&en_sync_to_sb_lb, &en_sb_load_balancer,
> > @@ -365,11 +381,11 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > "sbrec_fdb_by_dp_and_port",
> > sbrec_fdb_by_dp_and_port);
> >
> > - struct northd_data *northd_data =
> > - engine_get_internal_data(&en_northd);
> > + struct ed_type_global_config *global_config =
> > + engine_get_internal_data(&en_global_config);
> > unixctl_command_register("debug/chassis-features-list", "", 0, 0,
> > chassis_features_list,
> > - &northd_data->features);
> > + &global_config->features);
> > }
> >
> > /* Returns true if the incremental processing ended up updating nodes. */
> > diff --git a/northd/northd.c b/northd/northd.c
> > index 574cd1d116..7a887f2722 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -45,6 +45,7 @@
> > #include "lflow-mgr.h"
> > #include "memory.h"
> > #include "northd.h"
> > +#include "en-global-config.h"
> > #include "en-lb-data.h"
> > #include "en-lr-nat.h"
> > #include "en-lr-stateful.h"
> > @@ -79,14 +80,6 @@ static bool install_ls_lb_from_router;
> > /* Use common zone for SNAT and DNAT if this option is set to "true". */
> > static bool use_common_zone = false;
> >
> > -/* MAC allocated for service monitor usage. Just one mac is allocatedg5534
> > - * for this purpose and ovn-controller's on each chassis will make use
> > - * of this mac when sending out the packets to monitor the services
> > - * defined in Service_Monitor Southbound table. Since these packets
> > - * all locally handled, having just one mac is good enough. */
> > -static char svc_monitor_mac[ETH_ADDR_STRLEN + 1];
> > -static struct eth_addr svc_monitor_mac_ea;
> > -
> > /* If this option is 'true' northd will make use of ct.inv match fields.
> > * Otherwise, it will avoid using it. The default is true. */
> > static bool use_ct_inv_match = true;
> > @@ -297,66 +290,6 @@ ovn_stage_to_datapath_type(enum ovn_stage stage)
> > }
> > }
> >
> > -static void
> > -build_chassis_features(const struct sbrec_chassis_table
> > *sbrec_chassis_table,
> > - struct chassis_features *chassis_features)
> > -{
> > - const struct sbrec_chassis *chassis;
> > -
> > - SBREC_CHASSIS_TABLE_FOR_EACH (chassis, sbrec_chassis_table) {
> > - /* Only consider local AZ chassis. Remote ones don't install
> > - * flows generated by the local northd.
> > - */
> > - if (smap_get_bool(&chassis->other_config, "is-remote", false)) {
> > - continue;
> > - }
> > -
> > - bool ct_no_masked_label =
> > - smap_get_bool(&chassis->other_config,
> > - OVN_FEATURE_CT_NO_MASKED_LABEL,
> > - false);
> > - if (!ct_no_masked_label && chassis_features->ct_no_masked_label) {
> > - chassis_features->ct_no_masked_label = false;
> > - }
> > -
> > - bool mac_binding_timestamp =
> > - smap_get_bool(&chassis->other_config,
> > - OVN_FEATURE_MAC_BINDING_TIMESTAMP,
> > - false);
> > - if (!mac_binding_timestamp &&
> > - chassis_features->mac_binding_timestamp) {
> > - chassis_features->mac_binding_timestamp = false;
> > - }
> > -
> > - bool ct_lb_related =
> > - smap_get_bool(&chassis->other_config,
> > - OVN_FEATURE_CT_LB_RELATED,
> > - false);
> > - if (!ct_lb_related &&
> > - chassis_features->ct_lb_related) {
> > - chassis_features->ct_lb_related = false;
> > - }
> > -
> > - bool fdb_timestamp =
> > - smap_get_bool(&chassis->other_config,
> > - OVN_FEATURE_FDB_TIMESTAMP,
> > - false);
> > - if (!fdb_timestamp &&
> > - chassis_features->fdb_timestamp) {
> > - chassis_features->fdb_timestamp = false;
> > - }
> > -
> > - bool ls_dpg_column =
> > - smap_get_bool(&chassis->other_config,
> > - OVN_FEATURE_LS_DPG_COLUMN,
> > - false);
> > - if (!ls_dpg_column &&
> > - chassis_features->ls_dpg_column) {
> > - chassis_features->ls_dpg_column = false;
> > - }
> > - }
> > -}
> > -
> > static uint32_t
> > allocate_queueid(unsigned long *queue_id_bitmap)
> > {
> > @@ -954,7 +887,7 @@ is_vxlan_mode(const struct sbrec_chassis_table
> > *sbrec_chassis_table)
> > return false;
> > }
> >
> > -static uint32_t
> > +uint32_t
> > get_ovn_max_dp_key_local(const struct sbrec_chassis_table
> > *sbrec_chassis_table)
> > {
> > if (is_vxlan_mode(sbrec_chassis_table)) {
> > @@ -3367,6 +3300,8 @@ create_or_get_service_mon(struct ovsdb_idl_txn
> > *ovnsb_txn,
> > static void
> > ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn,
> > const struct ovn_northd_lb *lb,
> > + const char *svc_monitor_mac,
> > + const struct eth_addr *svc_monitor_mac_ea,
> > struct hmap *monitor_map, struct hmap *ls_ports,
> > struct sset *svc_monitor_lsps)
> > {
> > @@ -3412,7 +3347,7 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn,
> > struct eth_addr ea;
> > if (!mon_info->sbrec_mon->src_mac ||
> > !eth_addr_from_string(mon_info->sbrec_mon->src_mac, &ea) ||
> > - !eth_addr_equals(ea, svc_monitor_mac_ea)) {
> > + !eth_addr_equals(ea, *svc_monitor_mac_ea)) {
> > sbrec_service_monitor_set_src_mac(mon_info->sbrec_mon,
> > svc_monitor_mac);
> > }
> > @@ -3624,6 +3559,8 @@ static void
> > build_lb_svcs(
> > struct ovsdb_idl_txn *ovnsb_txn,
> > const struct sbrec_service_monitor_table *sbrec_service_monitor_table,
> > + const char *svc_monitor_mac,
> > + const struct eth_addr *svc_monitor_mac_ea,
> > struct hmap *ls_ports, struct hmap *lb_dps_map,
> > struct sset *svc_monitor_lsps,
> > struct hmap *svc_monitor_map)
> > @@ -3642,7 +3579,8 @@ build_lb_svcs(
> >
> > struct ovn_lb_datapaths *lb_dps;
> > HMAP_FOR_EACH (lb_dps, hmap_node, lb_dps_map) {
> > - ovn_lb_svc_create(ovnsb_txn, lb_dps->lb, svc_monitor_map, ls_ports,
> > + ovn_lb_svc_create(ovnsb_txn, lb_dps->lb, svc_monitor_mac,
> > + svc_monitor_mac_ea, svc_monitor_map, ls_ports,
> > svc_monitor_lsps);
> > }
> >
> > @@ -3713,12 +3651,15 @@ static void
> > build_lb_port_related_data(
> > struct ovsdb_idl_txn *ovnsb_txn,
> > const struct sbrec_service_monitor_table *sbrec_service_monitor_table,
> > + const char *svc_monitor_mac,
> > + const struct eth_addr *svc_monitor_mac_ea,
> > struct ovn_datapaths *lr_datapaths, struct hmap *ls_ports,
> > struct hmap *lb_dps_map, struct hmap *lb_group_dps_map,
> > struct sset *svc_monitor_lsps,
> > struct hmap *svc_monitor_map)
> > {
> > - build_lb_svcs(ovnsb_txn, sbrec_service_monitor_table, ls_ports,
> > lb_dps_map,
> > + build_lb_svcs(ovnsb_txn, sbrec_service_monitor_table, svc_monitor_mac,
> > + svc_monitor_mac_ea, ls_ports, lb_dps_map,
> > svc_monitor_lsps, svc_monitor_map);
> > build_lswitch_lbs_from_lrouter(lr_datapaths, lb_dps_map,
> > lb_group_dps_map);
> > }
> > @@ -9047,6 +8988,7 @@ build_lswitch_arp_nd_responder_default(struct
> > ovn_datapath *od,
> > static void
> > build_lswitch_arp_nd_service_monitor(const struct ovn_lb_datapaths *lb_dps,
> > const struct hmap *ls_ports,
> > + const char *svc_monitor_mac,
> > struct lflow_table *lflows,
> > struct ds *actions,
> > struct ds *match)
> > @@ -15532,6 +15474,7 @@ struct lswitch_flow_build_info {
> > struct ds match;
> > struct ds actions;
> > size_t thread_lflow_counter;
> > + const char *svc_monitor_mac;
> > };
> >
> > /* Helper function to combine all lflow generation which is iterated by
> > @@ -15762,6 +15705,7 @@ build_lflows_thread(void *arg)
> > }
> > build_lswitch_arp_nd_service_monitor(lb_dps,
> > lsi->ls_ports,
> > +
> > lsi->svc_monitor_mac,
> > lsi->lflows,
> > &lsi->match,
> > &lsi->actions);
> > @@ -15888,7 +15832,8 @@ build_lswitch_and_lrouter_flows(
> > const struct hmap *lb_dps_map,
> > const struct hmap *svc_monitor_map,
> > const struct hmap *bfd_connections,
> > - const struct chassis_features *features)
> > + const struct chassis_features *features,
> > + const char *svc_monitor_mac)
> > {
> >
> > char *svc_check_match = xasprintf("eth.dst == %s", svc_monitor_mac);
> > @@ -15921,6 +15866,7 @@ build_lswitch_and_lrouter_flows(
> > lsiv[index].features = features;
> > lsiv[index].svc_check_match = svc_check_match;
> > lsiv[index].thread_lflow_counter = 0;
> > + lsiv[index].svc_monitor_mac = svc_monitor_mac;
> > ds_init(&lsiv[index].match);
> > ds_init(&lsiv[index].actions);
> >
> > @@ -15960,6 +15906,7 @@ build_lswitch_and_lrouter_flows(
> > .bfd_connections = bfd_connections,
> > .features = features,
> > .svc_check_match = svc_check_match,
> > + .svc_monitor_mac = svc_monitor_mac,
> > .match = DS_EMPTY_INITIALIZER,
> > .actions = DS_EMPTY_INITIALIZER,
> > };
> > @@ -15999,6 +15946,7 @@ build_lswitch_and_lrouter_flows(
> > stopwatch_start(LFLOWS_LBS_STOPWATCH_NAME, time_msec());
> > HMAP_FOR_EACH (lb_dps, hmap_node, lb_dps_map) {
> > build_lswitch_arp_nd_service_monitor(lb_dps, lsi.ls_ports,
> > + lsi.svc_monitor_mac,
> > lsi.lflows, &lsi.actions,
> > &lsi.match);
> > build_lrouter_defrag_flows_for_lb(lb_dps, lsi.lflows,
> > @@ -16119,7 +16067,8 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn,
> > input_data->lb_datapaths_map,
> > input_data->svc_monitor_map,
> > input_data->bfd_connections,
> > - input_data->features);
> > + input_data->features,
> > + input_data->svc_monitor_mac);
> >
> > if (parallelization_state == STATE_INIT_HASH_SIZES) {
> > parallelization_state = STATE_USE_PARALLELIZATION;
> > @@ -16401,6 +16350,7 @@ lflow_handle_northd_lb_changes(struct ovsdb_idl_txn
> > *ovnsb_txn,
> > struct ds actions = DS_EMPTY_INITIALIZER;
> >
> > build_lswitch_arp_nd_service_monitor(lb_dps, lflow_input->ls_ports,
> > + lflow_input->svc_monitor_mac,
> > lflows, &actions,
> > &match);
> > build_lrouter_defrag_flows_for_lb(lb_dps, lflows,
> > @@ -17179,18 +17129,6 @@ destroy_datapaths_and_ports(struct ovn_datapaths
> > *ls_datapaths,
> > ovn_datapaths_destroy(lr_datapaths);
> > }
> >
> > -static void
> > -northd_enable_all_features(struct northd_data *data)
> > -{
> > - data->features = (struct chassis_features) {
> > - .ct_no_masked_label = true,
> > - .mac_binding_timestamp = true,
> > - .ct_lb_related = true,
> > - .fdb_timestamp = true,
> > - .ls_dpg_column = true,
> > - };
> > -}
> > -
> > void
> > northd_init(struct northd_data *data)
> > {
> > @@ -17201,8 +17139,6 @@ northd_init(struct northd_data *data)
> > hmap_init(&data->lb_datapaths_map);
> > hmap_init(&data->lb_group_datapaths_map);
> > ovs_list_init(&data->lr_list);
> > - northd_enable_all_features(data);
> > - data->ovn_internal_version_changed = false;
> > sset_init(&data->svc_monitor_lsps);
> > hmap_init(&data->svc_monitor_map);
> > init_northd_tracked_data(data);
> > @@ -17242,7 +17178,6 @@ northd_destroy(struct northd_data *data)
> > destroy_datapaths_and_ports(&data->ls_datapaths, &data->lr_datapaths,
> > &data->ls_ports, &data->lr_ports,
> > &data->lr_list);
> > - destroy_debug_config();
> >
> > sset_destroy(&data->svc_monitor_lsps);
> > destroy_northd_tracked_data(data);
> > @@ -17259,83 +17194,22 @@ ovnnb_db_run(struct northd_input *input_data,
> > }
> > stopwatch_start(BUILD_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
> >
> > - /* Sync ipsec configuration.
> > - * Copy nb_cfg from northbound to southbound database.
> > - * Also set up to update sb_cfg once our southbound transaction
> > commits. */
> > - const struct nbrec_nb_global *nb = nbrec_nb_global_table_first(
> > - input_data->nbrec_nb_global_table);
> > - if (!nb) {
> > - nb = nbrec_nb_global_insert(ovnnb_txn);
> > - }
> > -
> > - const char *mac_addr_prefix = set_mac_prefix(smap_get(&nb->options,
> > - "mac_prefix"));
> > -
> > - const char *monitor_mac = smap_get(&nb->options, "svc_monitor_mac");
> > - if (monitor_mac) {
> > - if (eth_addr_from_string(monitor_mac, &svc_monitor_mac_ea)) {
> > - snprintf(svc_monitor_mac, sizeof svc_monitor_mac,
> > - ETH_ADDR_FMT, ETH_ADDR_ARGS(svc_monitor_mac_ea));
> > - } else {
> > - monitor_mac = NULL;
> > - }
> > - }
> > -
> > - struct smap options;
> > - smap_clone(&options, &nb->options);
> > -
> > - smap_replace(&options, "mac_prefix", mac_addr_prefix);
> > -
> > - if (!monitor_mac) {
> > - eth_addr_random(&svc_monitor_mac_ea);
> > - snprintf(svc_monitor_mac, sizeof svc_monitor_mac,
> > - ETH_ADDR_FMT, ETH_ADDR_ARGS(svc_monitor_mac_ea));
> > - smap_replace(&options, "svc_monitor_mac", svc_monitor_mac);
> > - }
> > -
> > - char *max_tunid = xasprintf("%d",
> > - get_ovn_max_dp_key_local(input_data->sbrec_chassis_table));
> > - smap_replace(&options, "max_tunid", max_tunid);
> > - free(max_tunid);
> > -
> > - char *ovn_internal_version = ovn_get_internal_version();
> > - if (!strcmp(ovn_internal_version,
> > - smap_get_def(&options, "northd_internal_version", ""))) {
> > - data->ovn_internal_version_changed = false;
> > - } else {
> > - smap_replace(&options, "northd_internal_version",
> > - ovn_internal_version);
> > - }
> > - free(ovn_internal_version);
> > -
> > - if (!smap_equal(&nb->options, &options)) {
> > - nbrec_nb_global_verify_options(nb);
> > - nbrec_nb_global_set_options(nb, &options);
> > - }
> > -
> > - use_ct_inv_match = smap_get_bool(&nb->options,
> > + use_ct_inv_match = smap_get_bool(input_data->nb_options,
> > "use_ct_inv_match", true);
> >
> > /* deprecated, use --event instead */
> > - controller_event_en = smap_get_bool(&nb->options,
> > + controller_event_en = smap_get_bool(input_data->nb_options,
> > "controller_event", false);
> > - check_lsp_is_up = !smap_get_bool(&nb->options,
> > + check_lsp_is_up = !smap_get_bool(input_data->nb_options,
> > "ignore_lsp_down", true);
> > - default_acl_drop = smap_get_bool(&nb->options, "default_acl_drop",
> > false);
> > + default_acl_drop = smap_get_bool(input_data->nb_options,
> > + "default_acl_drop", false);
> >
> > - install_ls_lb_from_router = smap_get_bool(&nb->options,
> > + install_ls_lb_from_router = smap_get_bool(input_data->nb_options,
> > "install_ls_lb_from_router",
> > false);
> > - use_common_zone = smap_get_bool(&nb->options, "use_common_zone",
> > false);
> > -
> > - if (smap_get_bool(&nb->options, "ignore_chassis_features", false)) {
> > - northd_enable_all_features(data);
> > - } else {
> > - build_chassis_features(input_data->sbrec_chassis_table,
> > - &data->features);
> > - }
> > -
> > - init_debug_config(nb);
> > + use_common_zone = smap_get_bool(input_data->nb_options,
> > "use_common_zone",
> > + false);
> >
> > build_datapaths(ovnsb_txn,
> > input_data->nbrec_logical_switch_table,
> > @@ -17360,6 +17234,8 @@ ovnnb_db_run(struct northd_input *input_data,
> > &data->ls_ports, &data->lr_ports);
> > build_lb_port_related_data(ovnsb_txn,
> > input_data->sbrec_service_monitor_table,
> > + input_data->svc_monitor_mac,
> > + &input_data->svc_monitor_mac_ea,
> > &data->lr_datapaths, &data->ls_ports,
> > &data->lb_datapaths_map,
> > &data->lb_group_datapaths_map,
> > @@ -17392,38 +17268,6 @@ ovnnb_db_run(struct northd_input *input_data,
> > &data->ls_datapaths.datapaths);
> > stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
> >
> > - /* Set up SB_Global (depends on chassis features). */
> > - const struct sbrec_sb_global *sb = sbrec_sb_global_table_first(
> > - input_data->sbrec_sb_global_table);
> > - if (!sb) {
> > - sb = sbrec_sb_global_insert(ovnsb_txn);
> > - }
> > - if (nb->ipsec != sb->ipsec) {
> > - sbrec_sb_global_set_ipsec(sb, nb->ipsec);
> > - }
> > -
> > - /* Inform ovn-controllers whether LB flows will use ct_mark (i.e., only
> > - * if all chassis support it). If not explicitly present in the
> > database
> > - * the default value to be used for this option is 'true'.
> > - */
> > - if (!data->features.ct_no_masked_label) {
> > - smap_replace(&options, "lb_hairpin_use_ct_mark", "false");
> > - } else {
> > - smap_remove(&options, "lb_hairpin_use_ct_mark");
> > - }
> > -
> > - /* Hackaround SB_global.options overwrite by NB_Global.options for
> > - * 'sbctl_probe_interval' option.
> > - */
> > - const char *sip = smap_get(&sb->options, "sbctl_probe_interval");
> > - if (sip) {
> > - smap_replace(&options, "sbctl_probe_interval", sip);
> > - }
> > -
> > - if (!smap_equal(&sb->options, &options)) {
> > - sbrec_sb_global_set_options(sb, &options);
> > - }
> > - smap_destroy(&options);
> > }
> >
> > /* Stores the set of chassis which references an ha_chassis_group.
> > @@ -17714,12 +17558,6 @@ ovnsb_db_run(struct ovsdb_idl_txn *ovnnb_txn,
> > ovn_update_ipv6_prefix(lr_ports);
> > }
> >
> > -const char *
> > -northd_get_svc_monitor_mac(void)
> > -{
> > - return svc_monitor_mac;
> > -}
> > -
> > const struct ovn_datapath *
> > northd_get_datapath_for_port(const struct hmap *ls_ports,
> > const char *port_name)
> > diff --git a/northd/northd.h b/northd/northd.h
> > index 9d001206c1..b5c175929e 100644
> > --- a/northd/northd.h
> > +++ b/northd/northd.h
> > @@ -27,7 +27,6 @@
> >
> > struct northd_input {
> > /* Northbound table references */
> > - const struct nbrec_nb_global_table *nbrec_nb_global_table;
> > const struct nbrec_logical_switch_table *nbrec_logical_switch_table;
> > const struct nbrec_logical_router_table *nbrec_logical_router_table;
> > const struct nbrec_static_mac_binding_table
> > @@ -37,7 +36,6 @@ struct northd_input {
> > const struct nbrec_mirror_table *nbrec_mirror_table;
> >
> > /* Southbound table references */
> > - const struct sbrec_sb_global_table *sbrec_sb_global_table;
> > const struct sbrec_datapath_binding_table
> > *sbrec_datapath_binding_table;
> > const struct sbrec_port_binding_table *sbrec_port_binding_table;
> > const struct sbrec_mac_binding_table *sbrec_mac_binding_table;
> > @@ -57,6 +55,13 @@ struct northd_input {
> > const struct hmap *lbs;
> > const struct hmap *lbgrps;
> >
> > + /* Global config data node inputs. */
> > + const struct smap *nb_options;
> > + const struct smap *sb_options;
> > + const char *svc_monitor_mac;
> > + struct eth_addr svc_monitor_mac_ea;
> > + const struct chassis_features *features;
> > +
> > /* Indexes */
> > struct ovsdb_idl_index *sbrec_chassis_by_name;
> > struct ovsdb_idl_index *sbrec_chassis_by_hostname;
> > @@ -66,14 +71,6 @@ struct northd_input {
> > struct ovsdb_idl_index *sbrec_fdb_by_dp_and_port;
> > };
> >
> > -struct chassis_features {
> > - bool ct_no_masked_label;
> > - bool mac_binding_timestamp;
> > - bool ct_lb_related;
> > - bool fdb_timestamp;
> > - bool ls_dpg_column;
> > -};
> > -
> > /* A collection of datapaths. E.g. all logical switch datapaths, or all
> > * logical router datapaths. */
> > struct ovn_datapaths {
> > @@ -156,8 +153,6 @@ struct northd_data {
> > struct hmap lb_datapaths_map;
> > struct hmap lb_group_datapaths_map;
> > struct ovs_list lr_list;
> > - bool ovn_internal_version_changed;
> > - struct chassis_features features;
> > struct sset svc_monitor_lsps;
> > struct hmap svc_monitor_map;
> >
> > @@ -194,6 +189,7 @@ struct lflow_input {
> > const struct chassis_features *features;
> > const struct hmap *svc_monitor_map;
> > bool ovn_internal_version_changed;
> > + const char *svc_monitor_mac;
> > };
> >
> > extern int parallelization_state;
> > @@ -722,8 +718,6 @@ void bfd_cleanup_connections(const struct
> > nbrec_bfd_table *,
> > struct hmap *bfd_map);
> > void run_update_worker_pool(int n_threads);
> >
> > -const char *northd_get_svc_monitor_mac(void);
> > -
> > const struct ovn_datapath *northd_get_datapath_for_port(
> > const struct hmap *ls_ports, const char *port_name);
> >
> > @@ -787,4 +781,6 @@ lr_has_multiple_gw_ports(const struct ovn_datapath *od)
> > return od->n_l3dgw_ports > 1 && !od->is_gw_router;
> > }
> >
> > +uint32_t get_ovn_max_dp_key_local(const struct sbrec_chassis_table *);
> > +
> > #endif /* NORTHD_H */
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index 929bb45aed..d8ec3eead5 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -8838,7 +8838,7 @@ AT_CHECK([grep "ls_in_lb " S1flows | sed
> > 's/table=../table=??/' | sort], [0], [d
> > table=??(ls_in_lb ), priority=0 , match=(1), action=(next;)
> > ])
> >
> > -ovn-nbctl --wait=sb set NB_Global . options:install_ls_lb_from_router=true
> > +check ovn-nbctl --wait=sb set NB_Global .
> > options:install_ls_lb_from_router=true
> >
> > ovn-sbctl dump-flows S0 > S0flows
> > ovn-sbctl dump-flows S1 > S1flows
> > @@ -8857,6 +8857,7 @@ AT_CHECK([grep "ls_in_lb " S1flows | sed
> > 's/table=../table=??/' | sort], [0], [d
> > table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst
> > == 172.16.0.11 && tcp.dst == 8080), action=(reg0[[1]] = 0;
> > ct_lb_mark(backends=10.0.0.2:8080);)
> > ])
> >
> > +
> > ovn-sbctl get datapath S0 _uuid > dp_uuids
> > ovn-sbctl get datapath S1 _uuid >> dp_uuids
> > lb_dp_group=$(ovn-sbctl --bare --columns ls_datapath_group find
> > Load_Balancer name=lb0)
> > @@ -8865,7 +8866,7 @@ AT_CHECK_UNQUOTED([ovn-sbctl --bare --columns
> > _uuid,datapaths find Logical_DP_Gr
> > $(cat dp_uuids | sort)
> > ])
> >
> > -ovn-nbctl --wait=sb set NB_Global . options:install_ls_lb_from_router=false
> > +check ovn-nbctl --wait=sb set NB_Global .
> > options:install_ls_lb_from_router=false
> >
> > ovn-sbctl dump-flows S0 > S0flows
> > ovn-sbctl dump-flows S1 > S1flows
> > @@ -9250,12 +9251,11 @@ $4
> > AS_BOX([Create new PG1 and PG2])
> > check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > check ovn-nbctl --wait=sb -- pg-add pg1 -- pg-add pg2
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl The port_group node recomputes every time a NB port group is
> > added/deleted.
> > @@ -9288,12 +9288,11 @@ check ovn-nbctl --wait=sb \
> > check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1"
> > check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1"
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl The port_group node recomputes also every time a port from a new switch
> > @@ -9325,12 +9324,11 @@ check_column "sw2.1" sb:Port_Group ports
> > name="${sw2_key}_pg1"
> > check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2"
> > check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2"
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl The port_group node recomputes also every time a port from a new switch
> > @@ -9363,12 +9361,11 @@ check_column "sw2.1 sw2.3" sb:Port_Group ports
> > name="${sw2_key}_pg1"
> > check_column "sw1.2 sw1.3" sb:Port_Group ports name="${sw1_key}_pg2"
> > check_column "sw2.2 sw2.3" sb:Port_Group ports name="${sw2_key}_pg2"
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl We did not change the set of switches a pg is applied to, there should
> > be
> > @@ -9406,7 +9403,7 @@ dnl though, therefore "compute: 1".
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl We did not change the set of switches a pg is applied to, there should
> > be
> > @@ -9438,12 +9435,11 @@ check_column "sw1.2" sb:Port_Group ports
> > name="${sw1_key}_pg2"
> > AT_CHECK([fetch_column sb:Port_Group ports name="${sw2_key}_pg2"], [0], [
> > ])
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl We changed the set of switches a pg is applied to, there should be
> > @@ -9476,12 +9472,11 @@ check_column "sw1.2" sb:Port_Group ports
> > name="${sw1_key}_pg2"
> > AT_CHECK([fetch_column sb:Port_Group ports name="${sw2_key}_pg2"], [0], [
> > ])
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl We changed the set of switches a pg is applied to, there should be
> > @@ -9514,12 +9509,11 @@ check_column "sw2.1" sb:Port_Group ports
> > name="${sw2_key}_pg1"
> > check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2"
> > check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2"
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl We changed the set of switches a pg is applied to, there should be a
> > @@ -9554,12 +9548,11 @@ check_column "sw1.2" sb:Port_Group ports
> > name="${sw1_key}_pg2"
> > AT_CHECK([fetch_column sb:Port_Group ports name="${sw2_key}_pg2"], [0], [
> > ])
> >
> > -dnl The northd node should not recompute, it should handle nb_global update
> > -dnl though, therefore "compute: 1".
> > +dnl The northd node should not recompute,.
> > AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > northd], [0], [dnl
> > Node: northd
> > - recompute: 0
> > -- compute: 1
> > +- compute: 0
> > - abort: 0
> > ])
> > dnl We changed the set of switches a pg is applied to, there should be a
> > @@ -11922,3 +11915,212 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
> > OVN_CLEANUP([hv1])
> > AT_CLEANUP
> > ])
> > +
> > +OVN_FOR_EACH_NORTHD_NO_HV([
> > +AT_SETUP([NB_Global and SB_Global incremental processing])
> > +
> > +ovn_start
> > +
> > +check_engine_stats() {
> > + node=$1
> > + recompute=$2
> > + compute=$3
> > +
> > + echo "__file__:__line__: Checking engine stats for node $node :
> > recompute - \
> > +$recompute : compute - $compute"
> > +
> > + node_stat=$(as northd ovn-appctl -t ovn-northd inc-engine/show-stats
> > $node)
> > + # node_stat will be of this format :
> > + # - Node: lflow - recompute: 3 - compute: 0 - abort: 0
> > + node_recompute_ct=$(echo $node_stat | cut -d '-' -f2 | cut -d ':' -f2)
> > + node_compute_ct=$(echo $node_stat | cut -d '-' -f3 | cut -d ':' -f2)
> > +
> > + if [[ "$recompute" == "norecompute" ]]; then
> > + # node should not be recomputed
> > + echo "Expecting $node recompute count - $node_recompute_ct to be 0"
> > + check test "$node_recompute_ct" -eq "0"
> > + else
> > + echo "Expecting $node recompute count - $node_recompute_ct not to be 0"
> > + check test "$node_recompute_ct" -ne "0"
> > + fi
> > +
> > + if [[ "$compute" == "nocompute" ]]; then
> > + # node should not be computed
> > + echo "Expecting $node compute count - $node_compute_ct to be 0"
> > + check test "$node_compute_ct" -eq "0"
> > + else
> > + echo "Expecting $node compute count - $node_compute_ct not to be 0"
> > + check test "$node_compute_ct" -ne "0"
> > + fi
> > +}
> > +
> > +check ovn-nbctl ls-add sw0
> > +check ovn-nbctl lr-add lr0
> > +check ovn-nbctl lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1
> > "00:00:20:20:00:03 10.0.0.3"
> > +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
> > +check ovn-nbctl lsp-add sw0 sw0-lr0
> > +check ovn-nbctl lsp-set-type sw0-lr0 router
> > +check ovn-nbctl lsp-set-addresses sw0-lr0 router
> > +check ovn-nbctl --wait=sb lsp-set-options sw0-lr0 router-port=lr0-sw0
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +
> > +# This should not result in recomputes.
> > +check ovn-nbctl --wait=sb set NB_Global . options:foo=bar
> > +check_engine_stats global_config norecompute compute
> > +check_engine_stats northd norecompute compute
> > +check_engine_stats lflow norecompute compute
> > +CHECK_NO_CHANGE_AFTER_RECOMPUTE
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +# This should result in recomputes.
> > +check ovn-sbctl set SB_Global . options:bar=foo
> > +check_engine_stats global_config recompute compute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +CHECK_NO_CHANGE_AFTER_RECOMPUTE
> > +
> > +# Clears an nb option and checks that recomputes were triggered
> > +# and the option was added back by ovn-northd or not depending
> > +# on the 'added_back' argument.
> > +clear_nb_option() {
> > + option=$1
> > + add_back=$2
> > + echo "clearing the nb option - $option"
> > + check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > + check ovn-nbctl --wait=sb remove NB_Global . options $option
> > + check_engine_stats global_config recompute compute
> > + check_engine_stats northd recompute nocompute
> > + check_engine_stats lflow recompute nocompute
> > +
> > + local retval=1
> > + if [ "$add_back" == "true" ]; then
> > + retval=0
> > + fi
> > + AT_CHECK([ovn-nbctl get NB_Global . options:$option], [$retval],
> > [ignore], [ignore])
> > +}
> > +
> > +# Clear svc_monitor_mac and few other options which result in recompute.
> > +# and ovn-northd should update the nb options back.
> > +clear_nb_option svc_monitor_mac true
> > +clear_nb_option max_tunid true
> > +clear_nb_option mac_prefix true
> > +clear_nb_option northd_internal_version true
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-nbctl --wait=sb set NB_Global .
> > options:ignore_chassis_features=true
> > +check_engine_stats global_config recompute compute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +clear_nb_option ignore_chassis_features false
> > +
> > +set_nb_option_lflow_recompute() {
> > + local option=$1
> > + local value=$2
> > + check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > + check ovn-nbctl --wait=sb set NB_Global . options:$option=$value
> > + check_engine_stats global_config norecompute compute
> > + check_engine_stats northd recompute nocompute
> > + check_engine_stats lflow recompute nocompute
> > + check_engine_stats mac_binding_aging recompute nocompute
> > + CHECK_NO_CHANGE_AFTER_RECOMPUTE
> > +}
> > +
> > +clear_nb_option_lflow_recompute() {
> > + local option=$1
> > + check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > + check ovn-nbctl --wait=sb remove NB_Global . options $option
> > + check_engine_stats global_config norecompute compute
> > + check_engine_stats northd recompute nocompute
> > + check_engine_stats lflow recompute nocompute
> > + check_engine_stats mac_binding_aging recompute nocompute
> > + CHECK_NO_CHANGE_AFTER_RECOMPUTE
> > +}
> > +
> > +set_nb_option_lflow_recompute debug_drop_domain_id 1
> > +clear_nb_option_lflow_recompute debug_drop_domain_id
> > +
> > +set_nb_option_lflow_recompute debug_drop_collector_set 1
> > +clear_nb_option_lflow_recompute debug_drop_collector_set
> > +
> > +set_nb_option_lflow_recompute mac_binding_removal_limit 100
> > +clear_nb_option_lflow_recompute mac_binding_removal_limit
> > +
> > +set_nb_option_lflow_recompute fdb_removal_limit 100
> > +clear_nb_option_lflow_recompute fdb_removal_limit
> > +
> > +set_nb_option_lflow_recompute controller_event true
> > +clear_nb_option_lflow_recompute controller_event
> > +
> > +set_nb_option_lflow_recompute ignore_lsp_down true
> > +clear_nb_option_lflow_recompute ignore_lsp_down
> > +
> > +set_nb_option_lflow_recompute use_ct_inv_match true
> > +clear_nb_option_lflow_recompute use_ct_inv_match
> > +
> > +set_nb_option_lflow_recompute default_acl_drop true
> > +clear_nb_option_lflow_recompute default_acl_drop
> > +
> > +set_nb_option_lflow_recompute use_common_zone true
> > +clear_nb_option_lflow_recompute use_common_zone
> > +
> > +set_nb_option_lflow_recompute install_ls_lb_from_router true
> > +clear_nb_option_lflow_recompute install_ls_lb_from_router
> > +
> > +# Now test changes to chassis for feature changes.
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-sbctl chassis-add ch1 geneve 127.0.0.1
> > +check ovn-nbctl --wait=sb sync
> > +check_engine_stats global_config recompute compute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-sbctl chassis-add ch2 geneve 127.0.0.2
> > +check ovn-nbctl --wait=sb sync
> > +check_engine_stats global_config recompute compute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +AT_CHECK([ovn-nbctl get NB_Global . options:max_tunid | \
> > +sed s/":"//g | sed s/\"//g], [0], [16711680
> > +], [])
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-sbctl chassis-del ch2
> > +check ovn-nbctl --wait=sb sync
> > +check_engine_stats global_config recompute compute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-sbctl set encap . type=vxlan
> > +check ovn-nbctl --wait=sb sync
> > +check_engine_stats global_config recompute compute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +AT_CHECK([ovn-nbctl get NB_Global . options:max_tunid | \
> > +sed s/":"//g | sed s/\"//g], [0], [4095
> > +], [])
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-sbctl set chassis . other_config:foo=bar
> > +check ovn-nbctl --wait=sb sync
> > +check_engine_stats global_config norecompute compute
> > +check_engine_stats mac_binding_aging recompute nocompute
> > +check_engine_stats fdb_aging recompute nocompute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
> > +check ovn-sbctl set chassis . other_config:ct-no-masked-label=true
> > +check ovn-nbctl --wait=sb sync
> > +check_engine_stats global_config norecompute compute
> > +check_engine_stats mac_binding_aging recompute nocompute
> > +check_engine_stats fdb_aging recompute nocompute
> > +check_engine_stats northd recompute nocompute
> > +check_engine_stats lflow recompute nocompute
> > +
> > +AT_CLEANUP
> > +])
> > --
> > 2.43.0
> >
> > _______________________________________________
> > dev mailing list
> > [email protected]
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev