Add the incremental change handlers for the en_ts node: an NB Logical_Switch change that is not a transit-switch mirror is a no-op, and transit-switch changes are reconciled per transit switch (scoped) instead of forcing a full recompute of every transit switch.
Assisted-by: Claude Opus 4.8, Claude Code Co-authored-by: Tiago Matos <[email protected]> Signed-off-by: Tiago Matos <[email protected]> Signed-off-by: Paulo Guilherme Silva <[email protected]> --- ic/en-ts.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++ ic/en-ts.h | 9 ++++ ic/inc-proc-ic.c | 21 +++++--- 3 files changed, 159 insertions(+), 6 deletions(-) diff --git a/ic/en-ts.c b/ic/en-ts.c index 1f1bb5253..f830fa18e 100644 --- a/ic/en-ts.c +++ b/ic/en-ts.c @@ -68,6 +68,141 @@ en_ts_run(struct engine_node *node, void *data OVS_UNUSED) return EN_UPDATED; } +/* Returns the ic_context, or NULL when there is no availability zone yet (in + * which case the caller should report EN_HANDLED_UNCHANGED). */ +static struct ic_context * +ts_handler_ctx(struct engine_node *node) +{ + struct ic_context *ctx = engine_get_context()->client_ctx; + const struct ed_type_az *az = engine_get_input_data("az", node); + return az->runned_az ? ctx : NULL; +} + +/* Runs the scoped NB-mirror sync for the collected transit-switch scope and + * maps it to an engine result. ts_sync_scope() gates the NB mirror on the + * ovnnb_txn it needs, exactly as the full recompute does. */ +static enum engine_input_handler_result +ts_scope_finish(struct ic_context *ctx, struct sset *ts_scope) +{ + if (sset_is_empty(ts_scope)) { + return EN_HANDLED_UNCHANGED; + } + + struct shash isb_ts_dps; + collect_ts_datapaths(ctx, &isb_ts_dps); + ts_sync_scope(ctx, &isb_ts_dps, ts_scope); + shash_destroy(&isb_ts_dps); + + return EN_HANDLED_UPDATED; +} + +/* IC-NB Transit_Switch: a new/deleted/renamed transit switch must have its NB + * mirror reconciled. A deletion is honoured via the scoped GC in + * ts_sync_scope() (the deleted row's name stays in scope but is absent from + * IC-NB, so its mirror leftover is removed). */ +enum engine_input_handler_result +en_ts_icnb_transit_switch_handler(struct engine_node *node, + void *data OVS_UNUSED) +{ + struct ic_context *ctx = ts_handler_ctx(node); + if (!ctx) { + return EN_HANDLED_UNCHANGED; + } + + const struct icnbrec_transit_switch_table *tbl = + EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node)); + struct sset ts_scope = SSET_INITIALIZER(&ts_scope); + const struct icnbrec_transit_switch *ts; + ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH_TRACKED (ts, tbl) { + sset_add(&ts_scope, ts->name); + } + + enum engine_input_handler_result ret = ts_scope_finish(ctx, &ts_scope); + sset_destroy(&ts_scope); + return ret; +} + +/* Only transit-switch mirror logical switches (other_config:interconn-ts) + * affect en_ts. A change to such a logical switch reconciles that transit + * switch (re-creating the mirror if it was deleted externally); any other + * logical switch is irrelevant to en_ts, so its change is a no-op, avoiding a + * recompute on unrelated NB Logical_Switch updates. */ +enum engine_input_handler_result +en_ts_nb_logical_switch_handler(struct engine_node *node, + void *data OVS_UNUSED) +{ + struct ic_context *ctx = ts_handler_ctx(node); + if (!ctx) { + return EN_HANDLED_UNCHANGED; + } + + const struct nbrec_logical_switch_table *tbl = + EN_OVSDB_GET(engine_get_input("NB_logical_switch", node)); + struct sset ts_scope = SSET_INITIALIZER(&ts_scope); + const struct nbrec_logical_switch *ls; + NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH_TRACKED (ls, tbl) { + const char *ts_name = smap_get(&ls->other_config, "interconn-ts"); + if (ts_name) { + sset_add(&ts_scope, ts_name); + } + } + + enum engine_input_handler_result ret = ts_scope_finish(ctx, &ts_scope); + sset_destroy(&ts_scope); + return ret; +} + +/* IC-SB Datapath_Binding: when a transit switch's datapath tunnel key is + * (re)assigned by en_tunnel_key, the NB Logical_Switch mirror's + * other_config:requested-tnl-key must be updated to the committed value. This + * is what synchronizes the key after a global tunnel-key refresh (an IC-NB + * vxlan_mode change reallocates the datapath key into the VXLAN range in + * IC-SB, but the NB value only catches up on a follow-up iteration). + * + * Only transit-switch bindings have an NB mirror; transit routers (IC_ROUTER) + * are irrelevant. Deletions are ignored: a transit switch removal is + * reconciled through en_ts_icnb_transit_switch_handler and the scoped GC in + * ts_sync_scope(). + * + * Newly *inserted* bindings are also ignored, on purpose. en_tunnel_key + * inserts the binding and already publishes its freshly-allocated key to the + * mirror in the same iteration; reacting to that insert here would re-sync the + * transit switch while its mirror (if just created by + * en_ts_icnb_transit_switch_handler) is still uncommitted - find_ts_in_nb()'s + * index does not see the txn-local insert, so a duplicate NB Logical_Switch + * would be created. Here we only react to a tunnel-key *modify* on an + * already-existing binding (the vxlan refresh), whose mirror already + * exists. */ +enum engine_input_handler_result +en_ts_icsb_datapath_binding_handler(struct engine_node *node, + void *data OVS_UNUSED) +{ + struct ic_context *ctx = ts_handler_ctx(node); + if (!ctx) { + return EN_HANDLED_UNCHANGED; + } + + const struct icsbrec_datapath_binding_table *tbl = + EN_OVSDB_GET(engine_get_input("ICSB_datapath_binding", node)); + struct sset ts_scope = SSET_INITIALIZER(&ts_scope); + const struct icsbrec_datapath_binding *isb_dp; + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (isb_dp, tbl) { + if (icsbrec_datapath_binding_is_deleted(isb_dp) || + icsbrec_datapath_binding_is_new(isb_dp) || + ic_dp_get_type(isb_dp) != IC_SWITCH) { + continue; + } + if (ovsdb_idl_track_is_updated(&isb_dp->header_, + &icsbrec_datapath_binding_col_tunnel_key)) { + sset_add(&ts_scope, isb_dp->transit_switch); + } + } + + enum engine_input_handler_result ret = ts_scope_finish(ctx, &ts_scope); + sset_destroy(&ts_scope); + return ret; +} + void * en_ts_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED) diff --git a/ic/en-ts.h b/ic/en-ts.h index 039b3196f..d1890205b 100644 --- a/ic/en-ts.h +++ b/ic/en-ts.h @@ -9,4 +9,13 @@ enum engine_node_state en_ts_run(struct engine_node *node, void *data); void *en_ts_init(struct engine_node *node, struct engine_arg *arg); void en_ts_cleanup(void *data); +enum engine_input_handler_result +en_ts_icnb_transit_switch_handler(struct engine_node *node, void *data); + +enum engine_input_handler_result +en_ts_nb_logical_switch_handler(struct engine_node *node, void *data); + +enum engine_input_handler_result +en_ts_icsb_datapath_binding_handler(struct engine_node *node, void *data); + #endif /* EN_IC_TS_H */ diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index d36e4ff93..b2e4823e4 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -218,14 +218,23 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_gateway, &en_sb_encap, NULL); /* en_ts: sync transit switches to their AZ NB Logical_Switch mirrors. + * * en_ts builds its own transit-switch IC-SB Datapath_Binding map each run - * and only maintains the NB mirror; IC-SB Datapath_Binding creation/keying - * is owned by en_tunnel_key (downstream). */ + * (local data, never shared) and only maintains the NB mirror. IC-SB + * Datapath_Binding creation/keying is owned by en_tunnel_key (downstream), + * so en_ts no longer allocates tunnel keys. en_icsb_datapath_binding + * drives the follow-up NB requested-tnl-key sync after en_tunnel_key + * (re)assigns a key - notably the global refresh from an IC-NB vxlan_mode + * change (see en_ts_icsb_datapath_binding_handler). */ engine_add_input(&en_ts, &en_az, NULL); - engine_add_input(&en_ts, &en_icsb_datapath_binding, NULL); - engine_add_input(&en_ts, &en_icnb_ic_nb_global, NULL); - engine_add_input(&en_ts, &en_icnb_transit_switch, NULL); - engine_add_input(&en_ts, &en_nb_logical_switch, NULL); + engine_add_input(&en_ts, &en_icsb_datapath_binding, + en_ts_icsb_datapath_binding_handler); + engine_add_input(&en_ts, &en_icnb_ic_nb_global, + ic_nb_global_options_handler); + engine_add_input(&en_ts, &en_icnb_transit_switch, + en_ts_icnb_transit_switch_handler); + engine_add_input(&en_ts, &en_nb_logical_switch, + en_ts_nb_logical_switch_handler); engine_add_input(&en_ts, &en_icsb_encap, NULL); /* en_tr: sync transit routers to their AZ NB Logical_Router mirrors. -- 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
