Hi Paulo, Tiago Same rename problem as in 07/14. Leak on transit switch's rename.
Regards, Lucas Em qua., 2 de set. de 2026 às 18:19, Paulo Guilherme Silva <[email protected]> escreveu: > 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 d983e6bb0..93a53fe92 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 cf33d9ab6..32bdfedb0 100644 > --- a/ic/en-ts.h > +++ b/ic/en-ts.h > @@ -21,4 +21,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 a30ddf367..89135fc5d 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 > -- _‘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
