On Fri, Jul 24, 2026 at 12:42 PM Lucas Vargas Dias <[email protected]>
wrote:

> When a logical switch is created or updated,
> lflow_handle_northd_ls_changes()
> already builds and syncs that switch's ls_stateful flows together with its
> by_ls flows (so the shared datapath groups stay stable).  The ls_stateful
> record for the same switch also shows up in the ls_stateful node's tracked
> "crupdated" set, so lflow_ls_stateful_handler() would rebuild and resync
> those exact flows a second time.
>
> Pass northd's tracked switches down to lflow_handle_ls_stateful_changes()
> and skip any crupdated ls_stateful record whose switch datapath was already
> handled by lflow_handle_northd_ls_changes().  Records for pre-existing
> switches (e.g. an ACL or port-group change) are untouched and still
> processed here.
>
> Assisted-bt: Claude Opus 4.8, Claude Code
>

nit: Assisted-by:


> Signed-off-by: Lucas Vargas Dias <[email protected]>
> ---
>  northd/en-lflow.c |  9 +++++++++
>  northd/northd.c   | 24 ++++++++++++++++++++++++
>  northd/northd.h   |  1 +
>  3 files changed, 34 insertions(+)
>
> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
> index 9a517ae48..052e22c9d 100644
> --- a/northd/en-lflow.c
> +++ b/northd/en-lflow.c
> @@ -236,6 +236,14 @@ lflow_ls_stateful_handler(struct engine_node *node,
> void *data)
>          return EN_UNHANDLED;
>      }
>
> +    /* Switch datapaths created/updated in this run had their ls_stateful
> +     * flows already handled by lflow_handle_northd_ls_changes(); pass
> northd's
> +     * tracked switches so we don't reprocess them here. */
> +    struct northd_data *northd_data = engine_get_input_data("northd",
> node);
> +    const struct tracked_dps *trk_switches =
> +        northd_has_lswitches_in_tracked_data(&northd_data->trk_data)
> +        ? &northd_data->trk_data.trk_switches : NULL;
> +
>      const struct engine_context *eng_ctx = engine_get_context();
>      struct lflow_data *lflow_data = data;
>      struct lflow_input lflow_input;
> @@ -243,6 +251,7 @@ lflow_ls_stateful_handler(struct engine_node *node,
> void *data)
>      lflow_get_input_data(node, &lflow_input);
>      if (!lflow_handle_ls_stateful_changes(eng_ctx->ovnsb_idl_txn,
>                                            &ls_sful_data->trk_data,
> +                                          trk_switches,
>                                            &lflow_input,
>                                            lflow_data->lflow_table)) {
>          return EN_UNHANDLED;
> diff --git a/northd/northd.c b/northd/northd.c
> index 9ecc072f3..d15ad8395 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -22126,6 +22126,7 @@ exit:
>  bool
>  lflow_handle_ls_stateful_changes(struct ovsdb_idl_txn *ovnsb_txn,
>                                  struct ls_stateful_tracked_data *trk_data,
> +                                const struct tracked_dps *trk_switches,
>                                  struct lflow_input *lflow_input,
>                                  struct lflow_table *lflows)
>  {
> @@ -22139,6 +22140,17 @@ lflow_handle_ls_stateful_changes(struct
> ovsdb_idl_txn *ovnsb_txn,
>          ovs_assert(od->nbs && uuid_equals(&od->nbs->header_.uuid,
>                                            &ls_stateful_rec->nbs_uuid));
>
> +        /* Newly created/updated switch datapaths already had their
> +         * ls_stateful flows built and synced by
> +         * lflow_handle_northd_ls_changes() (which processes both the
> by_ls
> +         * and ls_stateful refs together to keep shared datapath groups
> +         * stable).  Skip them here to avoid rebuilding the same flows. */
> +        if (trk_switches && hmapx_contains(&trk_switches->crupdated,
> +                                           CONST_CAST(struct ovn_datapath
> *,
> +                                                      od))) {
>

Why are you using CONST_CAST here and other places you call hmapx_contains?


> +            continue;
> +        }
> +
>          lflow_ref_unlink_lflows(ls_stateful_rec->lflow_ref);
>
>          /* Generate new lflows. */
> @@ -22156,6 +22168,18 @@ lflow_handle_ls_stateful_changes(struct
> ovsdb_idl_txn *ovnsb_txn,
>       * those datapath groups within those flows over and over again. */
>      HMAPX_FOR_EACH (hmapx_node, &trk_data->crupdated) {
>          struct ls_stateful_record *ls_stateful_rec = hmapx_node->data;
> +
> +        /* Already synced by lflow_handle_northd_ls_changes() (see
> above). */
> +        if (trk_switches) {
> +            const struct ovn_datapath *od =
> +                ovn_datapaths_find_by_index(lflow_input->ls_datapaths,
> +                                            ls_stateful_rec->ls_index);
> +            if (hmapx_contains(&trk_switches->crupdated,
> +                               CONST_CAST(struct ovn_datapath *, od))) {
> +                continue;
> +            }
> +        }
> +
>

Why only for created/updated switches should previously processed
ls_stateful be skipped why not also on delete?


>          /* Sync the new flows to SB. */
>          bool handled = lflow_ref_sync_lflows(
>              ls_stateful_rec->lflow_ref, lflows, ovnsb_txn,
> diff --git a/northd/northd.h b/northd/northd.h
> index 217f3c6fb..20e03e1a5 100644
> --- a/northd/northd.h
> +++ b/northd/northd.h
> @@ -1024,6 +1024,7 @@ bool lflow_handle_lr_stateful_changes(struct
> ovsdb_idl_txn *,
>                                        struct lflow_table *lflows);
>  bool lflow_handle_ls_stateful_changes(struct ovsdb_idl_txn *,
>                                        struct ls_stateful_tracked_data *,
> +                                      const struct tracked_dps
> *trk_switches,
>                                        struct lflow_input *,
>                                        struct lflow_table *lflows);
>  bool northd_handle_sb_port_binding_changes(
> --
> 2.43.0
>
>
> --
>
>
>
>
> _'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

Reply via email to