On Thu, Sep 25, 2025 at 8:16 AM Lucas Vargas Dias via dev
<[email protected]> wrote:
>
> Change the logic to save sbflow uuid and just update if
> the lflow is reused. Otherwise, it's removed.
> Also, reduce sbflow searching with uuidset instead of
> searching through all lflow table.
> Add lflow states:
> LFLOW_STALE - Lflow is not relevant
> LFLOW_TO_SYNC - Lflow needs to be synced with SB DB
> LFLOW_SYNCED - Lflow is synced with SB SB
>
> It generates the following results in a scenario with:
> - LSPs: 56548
> - LRPs: 27304
> - LRs: 7922
> - LSs: 28602
>
> Without the commit:
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb lr-add lr9-1
> Time spent on processing nb_cfg 275438:
>         ovn-northd delay before processing:     16069ms
>         ovn-northd completion:                  32828ms
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb ls-add bar9-1
> Time spent on processing nb_cfg 275439:
>         ovn-northd delay before processing:     15019ms
>         ovn-northd completion:                  33207ms
>
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb lrp-add lr9-1 
> rp9-1-bar 00:01:ff:22:00:01 192.168.10.1/24 2801:80:3eaf:4401::1/64
> Time spent on processing nb_cfg 275440:
>         ovn-northd delay before processing:     14784ms
>         ovn-northd completion:                  33577ms
>
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb lsp-add bar9-1 
> bar-rp9-1 -- set Logical_Switch_Port bar-rp9-1 type=router 
> options:router-port=rp9-1-bar -- lsp-set-addresses bar-rp9-1 router
> Time spent on processing nb_cfg 275441:
>         ovn-northd delay before processing:     14598ms
>         ovn-northd completion:                  31942ms
>
> With the commit:
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb lr-add lr9-1
> Time spent on processing nb_cfg 275401:
>         ovn-northd delay before processing:     12602ms
>         ovn-northd completion:                  26103ms
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb ls-add bar9-1
> Time spent on processing nb_cfg 275402:
>         ovn-northd delay before processing:     12639ms
>         ovn-northd completion:                  26759ms
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb lrp-add lr9-1 
> rp9-1-bar 00:01:ff:22:00:01 192.168.10.1/24 2801:80:3eaf:4401::1/64
> Time spent on processing nb_cfg 275403:
>         ovn-northd delay before processing:     11874ms
>         ovn-northd completion:                  29733ms
> ovn-nbctl --no-leader-only --print-wait-time --wait=sb lsp-add bar9-1 
> bar-rp9-1 -- set Logical_Switch_Port bar-rp9-1 type=router 
> options:router-port=rp9-1-bar -- lsp-set-addresses bar-rp9-1 router
> Time spent on processing nb_cfg 275404:
>         ovn-northd delay before processing:     4058ms
>         ovn-northd completion:                  17323ms
>
> Signed-off-by: Lucas Vargas Dias <[email protected]>

Thanks for addressing the comments and for the great improvements.

Acked-by: Numan Siddique <[email protected]>

Numan

> ---
>  northd/en-lflow.c   |   2 +-
>  northd/lflow-mgr.c  | 108 ++++++++++++++++++++++++--------------------
>  northd/lflow-mgr.h  |  10 +++-
>  northd/northd.c     |   8 ++--
>  tests/ovn-northd.at |  32 +++++++++++++
>  5 files changed, 106 insertions(+), 54 deletions(-)
>
> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
> index 50570b611..13c5e3119 100644
> --- a/northd/en-lflow.c
> +++ b/northd/en-lflow.c
> @@ -122,7 +122,7 @@ en_lflow_run(struct engine_node *node, void *data)
>      stopwatch_start(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
>
>      struct lflow_data *lflow_data = data;
> -    lflow_table_clear(lflow_data->lflow_table);
> +    lflow_table_clear(lflow_data->lflow_table, false);
>      lflow_reset_northd_refs(&lflow_input);
>      lflow_ref_clear(lflow_input.igmp_lflow_ref);
>
> diff --git a/northd/lflow-mgr.c b/northd/lflow-mgr.c
> index 6a66a9718..5a989fe19 100644
> --- a/northd/lflow-mgr.c
> +++ b/northd/lflow-mgr.c
> @@ -26,6 +26,7 @@
>  #include "lflow-mgr.h"
>  #include "lib/ovn-parallel-hmap.h"
>  #include "lib/ovn-util.h"
> +#include "lib/uuidset.h"
>
>  VLOG_DEFINE_THIS_MODULE(lflow_mgr);
>
> @@ -37,7 +38,8 @@ static void ovn_lflow_init(struct ovn_lflow *, struct 
> ovn_datapath *od,
>                             uint16_t priority, char *match,
>                             char *actions, char *io_port,
>                             char *ctrl_meter, char *stage_hint,
> -                           const char *where, const char *flow_desc);
> +                           const char *where, const char *flow_desc,
> +                           struct uuid sbuuid);
>  static struct ovn_lflow *ovn_lflow_find(const struct hmap *lflows,
>                                          enum ovn_stage stage,
>                                          uint16_t priority, const char *match,
> @@ -147,6 +149,13 @@ static struct ovs_mutex 
> lflow_hash_locks[LFLOW_HASH_LOCK_MASK + 1];
>   */
>  extern struct ovs_mutex fake_hash_mutex;
>
> +
> +enum ovn_lflow_state {
> +    LFLOW_STALE,
> +    LFLOW_TO_SYNC,
> +    LFLOW_SYNCED,
> +};
> +
>  /* Represents a logical ovn flow (lflow).
>   *
>   * A logical flow with match 'M' and actions 'A' - L(M, A) is created
> @@ -181,14 +190,7 @@ struct ovn_lflow {
>      struct hmap dp_refcnts_map; /* Maintains the number of times this 
> ovn_lflow
>                                   * is referenced by a given datapath.
>                                   * Contains 'struct dp_refcnt' in the map. */
> -};
> -
> -/* Logical flow table. */
> -struct lflow_table {
> -    struct hmap entries; /* hmap of lflows. */
> -    struct hmap ls_dp_groups; /* hmap of logical switch dp groups. */
> -    struct hmap lr_dp_groups; /* hmap of logical router dp groups. */
> -    ssize_t max_seen_lflow_size;
> +    enum ovn_lflow_state sync_state;
>  };
>
>  struct lflow_table *
> @@ -210,10 +212,14 @@ lflow_table_init(struct lflow_table *lflow_table)
>  }
>
>  void
> -lflow_table_clear(struct lflow_table *lflow_table)
> +lflow_table_clear(struct lflow_table *lflow_table, bool destroy_all)
>  {
>      struct ovn_lflow *lflow;
>      HMAP_FOR_EACH_SAFE (lflow, hmap_node, &lflow_table->entries) {
> +        if (!destroy_all) {
> +            lflow->sync_state = LFLOW_STALE;
> +            continue;
> +        }
>          ovn_lflow_destroy(lflow_table, lflow);
>      }
>
> @@ -224,7 +230,7 @@ lflow_table_clear(struct lflow_table *lflow_table)
>  void
>  lflow_table_destroy(struct lflow_table *lflow_table)
>  {
> -    lflow_table_clear(lflow_table);
> +    lflow_table_clear(lflow_table, true);
>      hmap_destroy(&lflow_table->entries);
>      ovn_dp_groups_destroy(&lflow_table->ls_dp_groups);
>      ovn_dp_groups_destroy(&lflow_table->lr_dp_groups);
> @@ -257,16 +263,42 @@ lflow_table_sync_to_sb(struct lflow_table *lflow_table,
>                         const struct sbrec_logical_flow_table *sb_flow_table,
>                         const struct sbrec_logical_dp_group_table 
> *dpgrp_table)
>  {
> +    struct uuidset sb_uuid_set = UUIDSET_INITIALIZER(&sb_uuid_set);
>      struct hmap lflows_temp = HMAP_INITIALIZER(&lflows_temp);
>      struct hmap *lflows = &lflow_table->entries;
>      struct ovn_lflow *lflow;
> +    const struct sbrec_logical_flow *sbflow;
>
>      fast_hmap_size_for(&lflows_temp,
>                         lflow_table->max_seen_lflow_size);
>
> +    HMAP_FOR_EACH_SAFE (lflow, hmap_node, lflows) {
> +        if (lflow->sync_state == LFLOW_STALE) {
> +            ovn_lflow_destroy(lflow_table, lflow);
> +            continue;
> +        }
> +        sbflow = NULL;
> +        if (!uuid_is_zero(&lflow->sb_uuid)) {
> +            sbflow = sbrec_logical_flow_table_get_for_uuid(sb_flow_table,
> +                                                           &lflow->sb_uuid);
> +        }
> +        sync_lflow_to_sb(lflow, ovnsb_txn, lflow_table, ls_datapaths,
> +                         lr_datapaths, ovn_internal_version_changed,
> +                         sbflow, dpgrp_table);
> +        uuidset_insert(&sb_uuid_set, &lflow->sb_uuid);
> +        hmap_remove(lflows, &lflow->hmap_node);
> +        hmap_insert(&lflows_temp, &lflow->hmap_node,
> +                    hmap_node_hash(&lflow->hmap_node));
> +    }
>      /* Push changes to the Logical_Flow table to database. */
> -    const struct sbrec_logical_flow *sbflow;
>      SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_SAFE (sbflow, sb_flow_table) {
> +        struct uuidset_node *node = uuidset_find(&sb_uuid_set,
> +                                                 &sbflow->header_.uuid);
> +        if (!node) {
> +            sbrec_logical_flow_delete(sbflow);
> +            continue;
> +        }
> +        uuidset_delete(&sb_uuid_set, node);
>          struct sbrec_logical_dp_group *dp_group = sbflow->logical_dp_group;
>          struct ovn_datapath *logical_datapath_od = NULL;
>          size_t i;
> @@ -297,38 +329,8 @@ lflow_table_sync_to_sb(struct lflow_table *lflow_table,
>              sbrec_logical_flow_delete(sbflow);
>              continue;
>          }
> -
> -        enum ovn_pipeline pipeline
> -            = !strcmp(sbflow->pipeline, "ingress") ? P_IN : P_OUT;
> -
> -        lflow = ovn_lflow_find(
> -            lflows,
> -            ovn_stage_build(ovn_datapath_get_type(logical_datapath_od),
> -                            pipeline, sbflow->table_id),
> -            sbflow->priority, sbflow->match, sbflow->actions,
> -            sbflow->controller_meter, sbflow->hash);
> -        if (lflow) {
> -            sync_lflow_to_sb(lflow, ovnsb_txn, lflow_table, ls_datapaths,
> -                             lr_datapaths, ovn_internal_version_changed,
> -                             sbflow, dpgrp_table);
> -
> -            hmap_remove(lflows, &lflow->hmap_node);
> -            hmap_insert(&lflows_temp, &lflow->hmap_node,
> -                        hmap_node_hash(&lflow->hmap_node));
> -        } else {
> -            sbrec_logical_flow_delete(sbflow);
> -        }
> -    }
> -
> -    HMAP_FOR_EACH_SAFE (lflow, hmap_node, lflows) {
> -        sync_lflow_to_sb(lflow, ovnsb_txn, lflow_table, ls_datapaths,
> -                         lr_datapaths, ovn_internal_version_changed,
> -                         NULL, dpgrp_table);
> -
> -        hmap_remove(lflows, &lflow->hmap_node);
> -        hmap_insert(&lflows_temp, &lflow->hmap_node,
> -                    hmap_node_hash(&lflow->hmap_node));
>      }
> +    uuidset_destroy(&sb_uuid_set);
>      hmap_swap(lflows, &lflows_temp);
>      hmap_destroy(&lflows_temp);
>  }
> @@ -847,7 +849,7 @@ ovn_lflow_init(struct ovn_lflow *lflow, struct 
> ovn_datapath *od,
>                 size_t dp_bitmap_len, enum ovn_stage stage, uint16_t priority,
>                 char *match, char *actions, char *io_port, char *ctrl_meter,
>                 char *stage_hint, const char *where,
> -               const char *flow_desc)
> +               const char *flow_desc, struct uuid sbuuid)
>  {
>      lflow->dpg_bitmap = bitmap_allocate(dp_bitmap_len);
>      lflow->od = od;
> @@ -861,7 +863,8 @@ ovn_lflow_init(struct ovn_lflow *lflow, struct 
> ovn_datapath *od,
>      lflow->flow_desc = flow_desc;
>      lflow->dpg = NULL;
>      lflow->where = where;
> -    lflow->sb_uuid = UUID_ZERO;
> +    lflow->sb_uuid = sbuuid;
> +    lflow->sync_state = LFLOW_TO_SYNC;
>      hmap_init(&lflow->dp_refcnts_map);
>      ovs_list_init(&lflow->referenced_by);
>  }
> @@ -957,13 +960,18 @@ do_ovn_lflow_add(struct lflow_table *lflow_table, 
> size_t dp_bitmap_len,
>  {
>      struct ovn_lflow *old_lflow;
>      struct ovn_lflow *lflow;
> +    struct uuid sbuuid = UUID_ZERO;
>
>      ovs_assert(dp_bitmap_len);
>
>      old_lflow = ovn_lflow_find(&lflow_table->entries, stage,
>                                 priority, match, actions, ctrl_meter, hash);
>      if (old_lflow) {
> -        return old_lflow;
> +        if (old_lflow->sync_state != LFLOW_STALE) {
> +            return old_lflow;
> +        }
> +        sbuuid = old_lflow->sb_uuid;
> +        ovn_lflow_destroy(lflow_table, old_lflow);
>      }
>
>      lflow = xzalloc(sizeof *lflow);
> @@ -975,14 +983,16 @@ do_ovn_lflow_add(struct lflow_table *lflow_table, 
> size_t dp_bitmap_len,
>                     io_port ? xstrdup(io_port) : NULL,
>                     nullable_xstrdup(ctrl_meter),
>                     ovn_lflow_hint(stage_hint), where,
> -                   flow_desc);
> +                   flow_desc, sbuuid);
>
>      if (parallelization_state != STATE_USE_PARALLELIZATION) {
>          hmap_insert(&lflow_table->entries, &lflow->hmap_node, hash);
>      } else {
>          hmap_insert_fast(&lflow_table->entries, &lflow->hmap_node,
>                           hash);
> -        thread_lflow_counter++;
> +        if (uuid_is_zero(&lflow->sb_uuid)) {
> +            thread_lflow_counter++;
> +        }
>      }
>
>      return lflow;
> @@ -1150,6 +1160,7 @@ sync_lflow_to_sb(struct ovn_lflow *lflow,
>                              "referencing the dp group ["UUID_FMT"]",
>                              UUID_ARGS(&sbflow->header_.uuid),
>                              UUID_ARGS(&lflow->dpg->dpg_uuid));
> +                lflow->sync_state = LFLOW_STALE;
>                  return false;
>              }
>          } else {
> @@ -1169,6 +1180,7 @@ sync_lflow_to_sb(struct ovn_lflow *lflow,
>          ovn_dp_group_release(dp_groups, pre_sync_dpg);
>      }
>
> +    lflow->sync_state = LFLOW_SYNCED;
>      return true;
>  }
>
> diff --git a/northd/lflow-mgr.h b/northd/lflow-mgr.h
> index 1521270d6..91708c8a9 100644
> --- a/northd/lflow-mgr.h
> +++ b/northd/lflow-mgr.h
> @@ -26,10 +26,16 @@ struct ovn_datapath;
>  struct ovsdb_idl_row;
>
>  /* lflow map which stores the logical flows. */
> -struct lflow_table;
> +struct lflow_table {
> +    struct hmap entries; /* hmap of lflows. */
> +    struct hmap ls_dp_groups; /* hmap of logical switch dp groups. */
> +    struct hmap lr_dp_groups; /* hmap of logical router dp groups. */
> +    ssize_t max_seen_lflow_size;
> +};
> +
>  struct lflow_table *lflow_table_alloc(void);
>  void lflow_table_init(struct lflow_table *);
> -void lflow_table_clear(struct lflow_table *);
> +void lflow_table_clear(struct lflow_table *, bool);
>  void lflow_table_destroy(struct lflow_table *);
>  void lflow_table_expand(struct lflow_table *);
>  void lflow_table_set_size(struct lflow_table *, size_t);
> diff --git a/northd/northd.c b/northd/northd.c
> index fe5199a86..214a3bf6f 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -18068,9 +18068,9 @@ noop_callback(struct worker_pool *pool OVS_UNUSED,
>  static void
>  fix_flow_table_size(struct lflow_table *lflow_table,
>                    struct lswitch_flow_build_info *lsiv,
> -                  size_t n_lsiv)
> +                  size_t n_lsiv, size_t start)
>  {
> -    size_t total = 0;
> +    size_t total = start;
>      for (size_t i = 0; i < n_lsiv; i++) {
>          total += lsiv[i].thread_lflow_counter;
>      }
> @@ -18145,8 +18145,10 @@ build_lswitch_and_lrouter_flows(
>          }
>
>          /* Run thread pool. */
> +        size_t current_lflow_table_size = hmap_count(&lflows->entries);
>          run_pool_callback(build_lflows_pool, NULL, NULL, noop_callback);
> -        fix_flow_table_size(lflows, lsiv, build_lflows_pool->size);
> +        fix_flow_table_size(lflows, lsiv, build_lflows_pool->size,
> +                            current_lflow_table_size);
>
>          for (index = 0; index < build_lflows_pool->size; index++) {
>              ds_destroy(&lsiv[index].match);
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 83a142d20..b2df05256 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -12535,6 +12535,38 @@ AT_CHECK([echo $dpgrp_dps | grep $sw3_uuid], [0], 
> [ignore])
>  AT_CHECK([echo $dpgrp_dps | grep $sw4_uuid], [0], [ignore])
>  AT_CHECK([echo $dpgrp_dps | grep $sw5_uuid], [0], [ignore])
>
> +# Clear the SB:Logical_Flow.logical_dp_groups column of all the
> +# logical flows and then modify the NB:Load_balancer.  ovn-northd
> +# should resync the logical flows.
> +for l in $(ovn-sbctl --bare --columns _uuid list logical_flow)
> +do
> +    check ovn-sbctl clear logical_flow $l logical_dp_group
> +done
> +
> +check ovn-nbctl --wait=sb set load_balancer lb2 
> vips='{"10.0.0.10:80"="10.0.0.3:80,10.0.0.4:80"}'
> +check_engine_stats lflow recompute compute
> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
> +
> +lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
> 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80"')
> +AT_CHECK([test "$lb_lflow_uuid" != ""])
> +
> +lb_lflow_dp=$(ovn-sbctl --bare --columns logical_datapath list logical_flow 
> $lb_lflow_uuid)
> +AT_CHECK([test "$lb_lflow_dp" = ""])
> +
> +lb_lflow_dpgrp=$(ovn-sbctl --bare --columns logical_dp_group list 
> logical_flow $lb_lflow_uuid)
> +AT_CHECK([test "$lb_lflow_dpgrp" != ""])
> +
> +dpgrp_dps=$(ovn-sbctl --bare --columns datapaths list logical_dp_group 
> $lb_lflow_dpgrp)
> +
> +echo "dpgrp dps - $dpgrp_dps"
> +
> +AT_CHECK([echo $dpgrp_dps | grep $sw0_uuid], [1], [ignore])
> +AT_CHECK([echo $dpgrp_dps | grep $sw1_uuid], [1], [ignore])
> +AT_CHECK([echo $dpgrp_dps | grep $sw2_uuid], [1], [ignore])
> +AT_CHECK([echo $dpgrp_dps | grep $sw3_uuid], [0], [ignore])
> +AT_CHECK([echo $dpgrp_dps | grep $sw4_uuid], [0], [ignore])
> +AT_CHECK([echo $dpgrp_dps | grep $sw5_uuid], [0], [ignore])
> +
>  AT_CLEANUP
>  ])
>
> --
> 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

Reply via email to