Hi Paulo, I have a few findings below.
On Wed, Aug 12, 2026 at 10:56 PM Paulo Guilherme Silva
<[email protected]> wrote:
>
> Add the incremental change handlers for the en_gateway node so SB/IC-SB
> gateway and chassis changes are reconciled in place instead of forcing a
> full recompute.
>
> Add a tests/ovn-ic.at test exercising the en_dp_enum and en_gateway
> incremental handlers (the change handler of the node that reads a changed
> table fires, and a forced recompute produces no diff).
>
> Assisted-by: Claude Opus 4.8, Claude Code
> Signed-off-by: Paulo Guilherme Silva <[email protected]>
> ---
> ic/en-gateway.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++-
> ic/en-gateway.h | 5 +
> ic/inc-proc-ic.c | 16 ++-
> ic/ovn-ic.c | 156 +--------------------
> ic/ovn-ic.h | 5 +-
> tests/ovn-ic.at | 64 +++++++++
> 6 files changed, 439 insertions(+), 162 deletions(-)
>
> diff --git a/ic/en-gateway.c b/ic/en-gateway.c
> index 8a8755673..26fcd65cc 100644
> --- a/ic/en-gateway.c
> +++ b/ic/en-gateway.c
> @@ -14,14 +14,320 @@
>
> #include <config.h>
>
> -#include "en-gateway.h"
> #include "en-az.h"
> +#include "en-gateway.h"
> #include "lib/inc-proc-eng.h"
> +#include "lib/ovn-ic-sb-idl.h"
> +#include "lib/ovn-sb-idl.h"
> #include "openvswitch/vlog.h"
> #include "ovn-ic.h"
>
> VLOG_DEFINE_THIS_MODULE(en_ic_gateway);
>
> +/* Returns true if any information in gw and chassis is different. */
> +static bool
> +is_gateway_data_changed(const struct icsbrec_gateway *gw,
> + const struct sbrec_chassis *chassis)
> +{
> + if (strcmp(gw->hostname, chassis->hostname)) {
> + return true;
> + }
> +
> + if (gw->n_encaps != chassis->n_encaps) {
> + return true;
> + }
> +
> + for (size_t g = 0; g < gw->n_encaps; g++) {
> + bool found = false;
> + const struct icsbrec_encap *gw_encap = gw->encaps[g];
> + for (size_t s = 0; s < chassis->n_encaps; s++) {
> + const struct sbrec_encap *chassis_encap = chassis->encaps[s];
> + if (!strcmp(gw_encap->type, chassis_encap->type) &&
> + !strcmp(gw_encap->ip, chassis_encap->ip)) {
> + found = true;
> + if (!smap_equal(&gw_encap->options,
> &chassis_encap->options)) {
> + return true;
> + }
> + break;
> + }
> + }
> + if (!found) {
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> +static void
> +sync_isb_gw_to_sb(struct ic_context *ctx,
> + const struct icsbrec_gateway *gw,
> + const struct sbrec_chassis *chassis)
> +{
> + struct smap temp_map;
> + sbrec_chassis_set_hostname(chassis, gw->hostname);
> + smap_clone(&temp_map, &chassis->other_config);
> + smap_replace(&temp_map, "is-remote", "true");
> + /* Use sbrec_chassis_set_other_config instead of
> + * sbrec_chassis_update_other_config_setkey so the in-memory datum is
> + * updated for reads in the same loop iteration. */
> + sbrec_chassis_set_other_config(chassis, &temp_map);
> + smap_destroy(&temp_map);
> +
> + /* Sync encaps used by this gateway. */
> + ovs_assert(gw->n_encaps);
> + struct sbrec_encap *sb_encap;
> + struct sbrec_encap **sb_encaps =
> + xmalloc(gw->n_encaps * sizeof *sb_encaps);
> + for (size_t i = 0; i < gw->n_encaps; i++) {
> + sb_encap = sbrec_encap_insert(ctx->ovnsb_txn);
> + sbrec_encap_set_chassis_name(sb_encap, gw->name);
> + sbrec_encap_set_ip(sb_encap, gw->encaps[i]->ip);
> + sbrec_encap_set_type(sb_encap, gw->encaps[i]->type);
> + sbrec_encap_set_options(sb_encap, &gw->encaps[i]->options);
> + sb_encaps[i] = sb_encap;
> + }
> + sbrec_chassis_set_encaps(chassis, sb_encaps, gw->n_encaps);
> + free(sb_encaps);
> +}
> +
> +static void
> +sync_sb_gw_to_isb(struct ic_context *ctx,
> + const struct sbrec_chassis *chassis,
> + const struct icsbrec_gateway *gw)
> +{
> + icsbrec_gateway_set_hostname(gw, chassis->hostname);
> +
> + /* Sync encaps used by this chassis. */
> + ovs_assert(chassis->n_encaps);
> + struct icsbrec_encap *isb_encap;
> + struct icsbrec_encap **isb_encaps =
> + xmalloc(chassis->n_encaps * sizeof *isb_encaps);
> + for (size_t i = 0; i < chassis->n_encaps; i++) {
> + isb_encap = icsbrec_encap_insert(ctx->ovnisb_unlocked_txn);
> + icsbrec_encap_set_gateway_name(isb_encap,
> + chassis->name);
> + icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);
> + icsbrec_encap_set_type(isb_encap,
> + chassis->encaps[i]->type);
> + icsbrec_encap_set_options(isb_encap,
> + &chassis->encaps[i]->options);
> + isb_encaps[i] = isb_encap;
> + }
> + icsbrec_gateway_set_encaps(gw, isb_encaps,
> + chassis->n_encaps);
> + free(isb_encaps);
> +}
> +
> +/* Returns true if it ran to completion, false if the IC-SB/SB transactions
> + * needed to sync were not available (in which case the caller should report
> + * that the node is still stale). */
> +static bool
> +gateway_run(struct ic_context *ctx,
> + const struct icsbrec_availability_zone *runned_az)
> +{
> + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {
> + return false;
> + }
> +
> + struct shash local_gws = SHASH_INITIALIZER(&local_gws);
> + struct shash remote_gws = SHASH_INITIALIZER(&remote_gws);
> + const struct icsbrec_gateway *gw;
> + ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_unlocked_idl) {
> + if (gw->availability_zone == runned_az) {
> + shash_add(&local_gws, gw->name, gw);
> + } else {
> + shash_add(&remote_gws, gw->name, gw);
> + }
> + }
> +
> + const struct sbrec_chassis *chassis;
> + SBREC_CHASSIS_FOR_EACH (chassis, ctx->ovnsb_idl) {
> + if (smap_get_bool(&chassis->other_config, "is-interconn", false)) {
> + gw = shash_find_and_delete(&local_gws, chassis->name);
> + if (!gw) {
> + gw = icsbrec_gateway_insert(ctx->ovnisb_unlocked_txn);
> + icsbrec_gateway_set_availability_zone(gw, runned_az);
> + icsbrec_gateway_set_name(gw, chassis->name);
> + sync_sb_gw_to_isb(ctx, chassis, gw);
> + } else if (is_gateway_data_changed(gw, chassis)) {
> + sync_sb_gw_to_isb(ctx, chassis, gw);
> + }
> + } else if (smap_get_bool(&chassis->other_config, "is-remote",
> false)) {
> + gw = shash_find_and_delete(&remote_gws, chassis->name);
> + if (!gw) {
> + sbrec_chassis_delete(chassis);
> + } else if (is_gateway_data_changed(gw, chassis)) {
> + sync_isb_gw_to_sb(ctx, gw, chassis);
> + }
> + }
> + }
> +
> + /* Delete extra gateways from ISB for the local AZ */
> + struct shash_node *node;
> + SHASH_FOR_EACH (node, &local_gws) {
> + icsbrec_gateway_delete(node->data);
> + }
> + shash_destroy(&local_gws);
> +
> + /* Create SB chassis for remote gateways in ISB */
> + SHASH_FOR_EACH (node, &remote_gws) {
> + gw = node->data;
> + chassis = sbrec_chassis_insert(ctx->ovnsb_txn);
> + sbrec_chassis_set_name(chassis, gw->name);
> + sync_isb_gw_to_sb(ctx, gw, chassis);
> + }
> + shash_destroy(&remote_gws);
> +
> + return true;
> +}
> +
> +/* Returns the IC-SB gateway named 'name' whose availability zone is (when
> + * 'local') or is not (otherwise) this instance's AZ, or NULL. There is no
> + * index on Gateway by name, but the number of gateways is small. */
> +static const struct icsbrec_gateway *
> +find_gw_by_name(struct ic_context *ctx,
> + const struct icsbrec_availability_zone *runned_az,
> + const char *name, bool local)
> +{
> + const struct icsbrec_gateway *gw;
> + ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_unlocked_idl) {
> + if ((gw->availability_zone == runned_az) == local
> + && !strcmp(gw->name, name)) {
> + return gw;
> + }
> + }
> + return NULL;
> +}
> +
> +/* Incremental handler for en_gateway's SB Chassis input. Mirrors the
> + * SB-Chassis-driven half of gateway_run() for the tracked chassis only:
> + * an is-interconn chassis maintains its local IC-SB gateway, while an
> + * is-remote chassis (one we created from a remote gateway) is re-synced or
> + * deleted. Returns false to fall back to a full recompute for cases that
> + * cannot be handled incrementally. */
> +static bool
> +sync_gateway_handle_sb_chassis(struct ic_context *ctx,
> + const struct icsbrec_availability_zone
> *runned_az,
> + const struct sbrec_chassis_table *tbl)
> +{
> + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {
> + return false;
> + }
> +
> + const struct sbrec_chassis *chassis;
> + SBREC_CHASSIS_TABLE_FOR_EACH_TRACKED (chassis, tbl) {
> + const struct icsbrec_gateway *local_gw =
> + find_gw_by_name(ctx, runned_az, chassis->name, true);
> +
> + if (sbrec_chassis_is_deleted(chassis)) {
> + /* The local gateway derived from this chassis (if any) is now
> + * orphaned. IC-SB Gateway is indexed uniquely by name, so a
> local
> + * gateway with this name rules out a remote one: nothing more to
> + * do for this chassis. */
> + if (local_gw) {
> + icsbrec_gateway_delete(local_gw);
> + continue;
> + }
> + /* If this was a remote chassis we created and the remote gateway
> + * still exists, it must be recreated: leave that to a full
> + * recompute. */
> + if (find_gw_by_name(ctx, runned_az, chassis->name, false)) {
> + return false;
> + }
> + continue;
> + }
> +
> + if (smap_get_bool(&chassis->other_config, "is-interconn", false)) {
> + if (!local_gw) {
> + local_gw = icsbrec_gateway_insert(ctx->ovnisb_unlocked_txn);
> + icsbrec_gateway_set_availability_zone(local_gw,
> + runned_az);
> + icsbrec_gateway_set_name(local_gw, chassis->name);
> + sync_sb_gw_to_isb(ctx, chassis, local_gw);
> + } else if (is_gateway_data_changed(local_gw, chassis)) {
> + sync_sb_gw_to_isb(ctx, chassis, local_gw);
> + }
> + } else {
> + /* No longer an interconn chassis: drop any local gateway derived
> + * from it. */
> + if (local_gw) {
> + icsbrec_gateway_delete(local_gw);
> + }
> + if (smap_get_bool(&chassis->other_config, "is-remote", false)) {
> + const struct icsbrec_gateway *remote_gw =
> + find_gw_by_name(ctx, runned_az, chassis->name, false);
> + if (!remote_gw) {
> + sbrec_chassis_delete(chassis);
> + } else if (is_gateway_data_changed(remote_gw, chassis)) {
> + sync_isb_gw_to_sb(ctx, remote_gw, chassis);
> + }
> + }
> + }
> + }
> +
> + return true;
> +}
> +
> +/* Incremental handler for en_gateway's IC-SB Gateway input. Mirrors the
> + * remote-gateway-driven half of gateway_run() for the tracked gateways only:
> + * a remote gateway maintains its SB chassis mirror. Returns false to fall
> + * back to a full recompute for cases that cannot be handled incrementally.
> */
> +static bool
> +sync_gateway_handle_icsb_gateway(struct ic_context *ctx,
> + const struct icsbrec_availability_zone
> *runned_az,
> + const struct icsbrec_gateway_table *tbl)
> +{
> + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {
> + return false;
> + }
> +
> + const struct icsbrec_gateway *gw;
> + ICSBREC_GATEWAY_TABLE_FOR_EACH_TRACKED (gw, tbl) {
> + bool local = gw->availability_zone == runned_az;
> + const struct sbrec_chassis *chassis = find_sb_chassis(ctx, gw->name);
> +
> + if (icsbrec_gateway_is_deleted(gw)) {
> + if (!local && chassis &&
> + smap_get_bool(&chassis->other_config, "is-remote", false)) {
> + sbrec_chassis_delete(chassis);
> + }
> + /* A local gateway disappearing while its interconn chassis still
> + * exists needs the chassis-driven recreate path:
> + * full recompute. */
> + if (local && chassis &&
> + smap_get_bool(&chassis->other_config, "is-interconn",
> false)) {
> + return false;
> + }
> + continue;
> + }
> +
> + if (local) {
> + /* Local gateways are produced from SB chassis (handled by the
> + * SB Chassis handler); a create/update here is our own write. */
> + continue;
> + }
> +
> + /* Remote gateway: ensure a matching SB chassis exists and is synced.
> + * If the only chassis with this name is a local interconn chassis,
> + * this is an unexpected name collision; fall back. */
> + if (chassis &&
> + smap_get_bool(&chassis->other_config, "is-interconn", false)) {
> + return false;
> + }
> + if (!chassis) {
> + chassis = sbrec_chassis_insert(ctx->ovnsb_txn);
> + sbrec_chassis_set_name(chassis, gw->name);
> + sync_isb_gw_to_sb(ctx, gw, chassis);
> + } else if (is_gateway_data_changed(gw, chassis)) {
> + sync_isb_gw_to_sb(ctx, gw, chassis);
> + }
> + }
> +
> + return true;
> +}
> +
> +
> enum engine_node_state
> en_gateway_run(struct engine_node *node, void *data OVS_UNUSED)
> {
> @@ -35,11 +341,56 @@ en_gateway_run(struct engine_node *node, void *data
> OVS_UNUSED)
> return EN_UNCHANGED;
> }
>
> - gateway_run(ctx);
> + /* If the transactions needed to sync were not available, the node could
> + * not be brought up to date; report it as stale so the engine retries.
> */
> + if (!gateway_run(ctx, az->runned_az)) {
> + return EN_STALE;
> + }
>
> return EN_UPDATED;
> }
>
> +enum engine_input_handler_result
> +en_gateway_sb_chassis_handler(struct engine_node *node, void *data
> OVS_UNUSED)
> +{
> + const struct engine_context *eng_ctx = engine_get_context();
> + struct ic_context *ctx = eng_ctx->client_ctx;
> + const struct ed_type_az *az = engine_get_input_data("az", node);
> +
> + if (!az->runned_az) {
> + return EN_HANDLED_UNCHANGED;
> + }
> +
> + const struct sbrec_chassis_table *tbl =
> + EN_OVSDB_GET(engine_get_input("SB_chassis", node));
> + if (!sync_gateway_handle_sb_chassis(ctx, az->runned_az, tbl)) {
> + return EN_UNHANDLED;
> + }
> +
> + return EN_HANDLED_UPDATED;
I may be misreading the code, but it appears there are code paths in
sync_gateway_handle_sb_chassis() where nothing actually ends up
happening, but sync_gateway_handle_sb_chassis() ends up returning
true. This results in returning EN_HANDLED_UPDATED here. In those
situations, we should return EN_HANDLED_UNCHANGED here instead, since
no data in en_gateway actually changed.
The same thing happens in en_gateway_icsb_gateway_handler() below.
> +}
> +
> +enum engine_input_handler_result
> +en_gateway_icsb_gateway_handler(struct engine_node *node,
> + void *data OVS_UNUSED)
> +{
> + const struct engine_context *eng_ctx = engine_get_context();
> + struct ic_context *ctx = eng_ctx->client_ctx;
> + const struct ed_type_az *az = engine_get_input_data("az", node);
> +
> + if (!az->runned_az) {
> + return EN_HANDLED_UNCHANGED;
> + }
> +
> + const struct icsbrec_gateway_table *tbl =
> + EN_OVSDB_GET(engine_get_input("ICSB_gateway", node));
> + if (!sync_gateway_handle_icsb_gateway(ctx, az->runned_az, tbl)) {
> + return EN_UNHANDLED;
> + }
> +
> + return EN_HANDLED_UPDATED;
> +}
> +
> void *
> en_gateway_init(struct engine_node *node OVS_UNUSED,
> struct engine_arg *arg OVS_UNUSED)
> diff --git a/ic/en-gateway.h b/ic/en-gateway.h
> index 76d0b08a9..365c29b83 100644
> --- a/ic/en-gateway.h
> +++ b/ic/en-gateway.h
> @@ -9,4 +9,9 @@ enum engine_node_state en_gateway_run(struct engine_node
> *node, void *data);
> void *en_gateway_init(struct engine_node *node, struct engine_arg *arg);
> void en_gateway_cleanup(void *data);
>
> +enum engine_input_handler_result
> +en_gateway_sb_chassis_handler(struct engine_node *node, void *data);
> +enum engine_input_handler_result
> +en_gateway_icsb_gateway_handler(struct engine_node *node, void *data);
> +
> #endif /* EN_IC_GATEWAY_H */
> diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c
> index 4a281251a..d36e4ff93 100644
> --- a/ic/inc-proc-ic.c
> +++ b/ic/inc-proc-ic.c
> @@ -201,12 +201,20 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
> * splitting the monolithic ovn_db_run() into independently-gated nodes.
> * Change handlers are added incrementally in a later step. */
>
> - /* en_gateway: sync gateways/chassis between SB and IC-SB. */
> + /* en_gateway: sync gateways/chassis between SB and IC-SB.
> + *
> + * The availability zone is provided by en_az (which reports EN_UPDATED
> + * only when the AZ identity changes). en_gateway does not read the
> + * Availability_Zone table itself - only gateway rows' availability_zone
> + * reference and en_az's resolved AZ - so it deliberately does not depend
> + * on en_icsb_availability_zone, whose rows also carry the
> + * frequently-bumped nb_ic_cfg sequence number. */
> engine_add_input(&en_gateway, &en_az, NULL);
> - engine_add_input(&en_gateway, &en_icsb_availability_zone, NULL);
> - engine_add_input(&en_gateway, &en_icsb_gateway, NULL);
> + engine_add_input(&en_gateway, &en_icsb_gateway,
> + en_gateway_icsb_gateway_handler);
> engine_add_input(&en_gateway, &en_icsb_encap, NULL);
> - engine_add_input(&en_gateway, &en_sb_chassis, NULL);
> + engine_add_input(&en_gateway, &en_sb_chassis,
> + en_gateway_sb_chassis_handler);
> engine_add_input(&en_gateway, &en_sb_encap, NULL);
>
> /* en_ts: sync transit switches to their AZ NB Logical_Switch mirrors.
> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
> index 2f3286bd8..f335617ed 100644
> --- a/ic/ovn-ic.c
> +++ b/ic/ovn-ic.c
> @@ -302,102 +302,6 @@ ts_sync_scope(struct ic_context *ctx, struct shash
> *isb_ts_dps,
> shash_destroy(&nb_ts_mirrors);
> }
>
> -/* Returns true if any information in gw and chassis is different. */
> -static bool
> -is_gateway_data_changed(const struct icsbrec_gateway *gw,
> - const struct sbrec_chassis *chassis)
> -{
> - if (strcmp(gw->hostname, chassis->hostname)) {
> - return true;
> - }
> -
> - if (gw->n_encaps != chassis->n_encaps) {
> - return true;
> - }
> -
> - for (int g = 0; g < gw->n_encaps; g++) {
> -
> - bool found = false;
> - const struct icsbrec_encap *gw_encap = gw->encaps[g];
> - for (int s = 0; s < chassis->n_encaps; s++) {
> - const struct sbrec_encap *chassis_encap = chassis->encaps[s];
> - if (!strcmp(gw_encap->type, chassis_encap->type) &&
> - !strcmp(gw_encap->ip, chassis_encap->ip)) {
> - found = true;
> - if (!smap_equal(&gw_encap->options,
> &chassis_encap->options)) {
> - return true;
> - }
> - break;
> - }
> - }
> - if (!found) {
> - return true;
> - }
> - }
> -
> - return false;
> -}
> -
> -static void
> -sync_isb_gw_to_sb(struct ic_context *ctx,
> - const struct icsbrec_gateway *gw,
> - const struct sbrec_chassis *chassis)
> -{
> - struct smap temp_map;
> - sbrec_chassis_set_hostname(chassis, gw->hostname);
> - smap_clone(&temp_map, &chassis->other_config);
> - smap_replace(&temp_map, "is-remote", "true");
> - /* Use sbrec_chassis_set_other_config instead of
> - * sbrec_chassis_update_other_config_setkey so the in-memory datum is
> - * updated for reads in the same loop iteration. */
> - sbrec_chassis_set_other_config(chassis, &temp_map);
> - smap_destroy(&temp_map);
> -
> - /* Sync encaps used by this gateway. */
> - ovs_assert(gw->n_encaps);
> - struct sbrec_encap *sb_encap;
> - struct sbrec_encap **sb_encaps =
> - xmalloc(gw->n_encaps * sizeof *sb_encaps);
> - for (int i = 0; i < gw->n_encaps; i++) {
> - sb_encap = sbrec_encap_insert(ctx->ovnsb_txn);
> - sbrec_encap_set_chassis_name(sb_encap, gw->name);
> - sbrec_encap_set_ip(sb_encap, gw->encaps[i]->ip);
> - sbrec_encap_set_type(sb_encap, gw->encaps[i]->type);
> - sbrec_encap_set_options(sb_encap, &gw->encaps[i]->options);
> - sb_encaps[i] = sb_encap;
> - }
> - sbrec_chassis_set_encaps(chassis, sb_encaps, gw->n_encaps);
> - free(sb_encaps);
> -}
> -
> -static void
> -sync_sb_gw_to_isb(struct ic_context *ctx,
> - const struct sbrec_chassis *chassis,
> - const struct icsbrec_gateway *gw)
> -{
> - icsbrec_gateway_set_hostname(gw, chassis->hostname);
> -
> - /* Sync encaps used by this chassis. */
> - ovs_assert(chassis->n_encaps);
> - struct icsbrec_encap *isb_encap;
> - struct icsbrec_encap **isb_encaps =
> - xmalloc(chassis->n_encaps * sizeof *isb_encaps);
> - for (int i = 0; i < chassis->n_encaps; i++) {
> - isb_encap = icsbrec_encap_insert(ctx->ovnisb_unlocked_txn);
> - icsbrec_encap_set_gateway_name(isb_encap,
> - chassis->name);
> - icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);
> - icsbrec_encap_set_type(isb_encap,
> - chassis->encaps[i]->type);
> - icsbrec_encap_set_options(isb_encap,
> - &chassis->encaps[i]->options);
> - isb_encaps[i] = isb_encap;
> - }
> - icsbrec_gateway_set_encaps(gw, isb_encaps,
> - chassis->n_encaps);
> - free(isb_encaps);
> -}
> -
> static void
> nb_addr_set_apply_diff(const void *arg, const char *item, bool add)
> {
> @@ -576,64 +480,6 @@ address_set_run(struct ic_context *ctx,
> shash_destroy(&ic_remote_as);
> }
>
> -void
> -gateway_run(struct ic_context *ctx)
> -{
> - if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {
> - return;
> - }
> -
> - struct shash local_gws = SHASH_INITIALIZER(&local_gws);
> - struct shash remote_gws = SHASH_INITIALIZER(&remote_gws);
> - const struct icsbrec_gateway *gw;
> - ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_unlocked_idl) {
> - if (gw->availability_zone == inc_proc_ic_get_runned_az()) {
> - shash_add(&local_gws, gw->name, gw);
> - } else {
> - shash_add(&remote_gws, gw->name, gw);
> - }
> - }
> -
> - const struct sbrec_chassis *chassis;
> - SBREC_CHASSIS_FOR_EACH (chassis, ctx->ovnsb_idl) {
> - if (smap_get_bool(&chassis->other_config, "is-interconn", false)) {
> - gw = shash_find_and_delete(&local_gws, chassis->name);
> - if (!gw) {
> - gw = icsbrec_gateway_insert(ctx->ovnisb_unlocked_txn);
> - icsbrec_gateway_set_availability_zone(gw,
> - inc_proc_ic_get_runned_az());
> - icsbrec_gateway_set_name(gw, chassis->name);
> - sync_sb_gw_to_isb(ctx, chassis, gw);
> - } else if (is_gateway_data_changed(gw, chassis)) {
> - sync_sb_gw_to_isb(ctx, chassis, gw);
> - }
> - } else if (smap_get_bool(&chassis->other_config, "is-remote",
> false)) {
> - gw = shash_find_and_delete(&remote_gws, chassis->name);
> - if (!gw) {
> - sbrec_chassis_delete(chassis);
> - } else if (is_gateway_data_changed(gw, chassis)) {
> - sync_isb_gw_to_sb(ctx, gw, chassis);
> - }
> - }
> - }
> -
> - /* Delete extra gateways from ISB for the local AZ */
> - struct shash_node *node;
> - SHASH_FOR_EACH (node, &local_gws) {
> - icsbrec_gateway_delete(node->data);
> - }
> - shash_destroy(&local_gws);
> -
> - /* Create SB chassis for remote gateways in ISB */
> - SHASH_FOR_EACH (node, &remote_gws) {
> - gw = node->data;
> - chassis = sbrec_chassis_insert(ctx->ovnsb_txn);
> - sbrec_chassis_set_name(chassis, gw->name);
> - sync_isb_gw_to_sb(ctx, gw, chassis);
> - }
> - shash_destroy(&remote_gws);
> -}
> -
> const struct nbrec_logical_switch *
> find_ts_in_nb(struct ic_context *ctx, char *ts_name)
> {
> @@ -784,7 +630,7 @@ get_lp_address_for_sb_pb(struct ic_context *ctx,
> return peer->n_mac ? *peer->mac : NULL;
> }
>
> -static const struct sbrec_chassis *
> +const struct sbrec_chassis *
> find_sb_chassis(struct ic_context *ctx, const char *name)
> {
> const struct sbrec_chassis *key =
> diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h
> index 359749b86..faf11bf61 100644
> --- a/ic/ovn-ic.h
> +++ b/ic/ovn-ic.h
> @@ -65,11 +65,12 @@ struct shash;
> struct sset;
> struct icsbrec_availability_zone;
> struct icsbrec_datapath_binding;
> +struct sbrec_chassis_table;
> +struct icsbrec_gateway_table;
>
> enum ic_datapath_type ic_dp_get_type(
> const struct icsbrec_datapath_binding *isb_dp);
>
> -void gateway_run(struct ic_context *ctx);
> void address_set_run(struct ic_context *ctx,
> const struct icsbrec_availability_zone *runned_az);
>
> @@ -93,6 +94,8 @@ void sync_service_monitor(struct ic_context *ctx);
> /* Shared IC helpers used by more than one engine node. */
> uint32_t
> allocate_dp_key(struct hmap *dp_tnlids, bool vxlan_mode, const char *name);
> +const struct sbrec_chassis *
> +find_sb_chassis(struct ic_context *ctx, const char *name);
> const struct nbrec_logical_switch *
> find_ts_in_nb(struct ic_context *ctx, char *ts_name);
> bool
> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
> index 1435a19a3..49172951c 100644
> --- a/tests/ovn-ic.at
> +++ b/tests/ovn-ic.at
> @@ -817,6 +817,70 @@ OVN_CLEANUP_IC([az1], [az2])
> AT_CLEANUP
> ])
>
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([ovn-ic -- incremental processing - dp_enum and gateway])
> +
> +# Validates the incremental-processing change handlers of the en_dp_enum and
> +# en_gateway engine nodes in two ways:
> +# - the change handler of the node that reads the affected table fires
> +# (its compute stat is non-zero), and
> +# - forcing a full recompute afterwards leaves the databases unchanged,
> +# i.e. the incremental result matches a full recompute.
> +
> +ovn_init_ic_db
> +net_add n1
> +ovn_start az1
> +sim_add gw1
> +as gw1
> +check ovs-vsctl add-br br-phys
> +ovn_az_attach az1 n1 br-phys 192.168.0.1
> +check ovs-vsctl set open . external-ids:ovn-is-interconn=true \
> + external-ids:hostname=gw1
> +as az1
> +
> +# Wait until the local gateway is registered in IC-SB.
> +OVS_WAIT_UNTIL([test "$(ovn-ic-sbctl --bare --columns=hostname \
> + find gateway name=gw1)" = gw1])
> +check ovn-ic-nbctl --wait=sb sync
> +
> +# A targeted SB Chassis change is handled by the gateway node's change
> +# handler: its compute stat becomes non-zero.
> +check ovn-appctl -t ic/ovn-ic inc-engine/clear-stats
> +as gw1
> +check ovs-vsctl set open . external-ids:hostname=gw1-new
> +as az1
> +OVS_WAIT_UNTIL([test "$(ovn-ic-sbctl --bare --columns=hostname \
> + find gateway name=gw1)" = gw1-new])
> +AT_CHECK([test "$(ovn-appctl -t ic/ovn-ic \
> + inc-engine/show-stats gateway compute)" -gt 0])
> +
> +# Exercise the dp_enum handler too: a transit switch creates an IC-SB
> +# datapath binding, and adding a port binding drives further IC-SB updates.
> +check ovn-ic-nbctl --wait=sb ts-add ts1
> +OVS_WAIT_UNTIL([test "$(ovn-nbctl --bare --columns=name \
> + find logical_switch name=ts1)" = ts1])
> +check ovn-ic-nbctl --wait=sb sync
> +
> +# After all the incremental updates above, a forced full recompute must not
> +# change any IC-managed table: incremental processing produced the same
> result.
> +m4_define([_IC_DUMP], [
> + ovn-ic-sbctl --columns=name,hostname,availability_zone list gateway \
> + | sort > $1
> + ovn-ic-sbctl --columns=transit_switch,type,tunnel_key \
> + list datapath_binding | sort >> $1
> + ovn-nbctl --columns=name,other_config list logical_switch | sort >> $1
> + ovn-sbctl --columns=name,hostname,other_config list chassis | sort >> $1
> +])
> +_IC_DUMP([ic_before])
> +check ovn-appctl -t ic/ovn-ic inc-engine/recompute
> +check ovn-ic-nbctl --wait=sb sync
> +_IC_DUMP([ic_after])
> +AT_CHECK([diff ic_before ic_after])
> +
> +OVN_CLEANUP_IC([az1])
> +AT_CLEANUP
> +])
> +
> OVN_FOR_EACH_NORTHD([
> AT_SETUP([ovn-ic -- port sync])
>
> --
> 2.34.1
>
>
> --
>
>
>
>
> _'Esta mensagem é direcionada apenas para os endereços constantes no
> cabeçalho inicial. Se você não está listado nos endereços constantes no
> cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa
> mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão
> imediatamente anuladas e proibidas'._
>
>
> * **'Apesar do Magazine Luiza tomar
> todas as precauções razoáveis para assegurar que nenhum vírus esteja
> presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por
> quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.*
>
>
>
> _______________________________________________
> 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